diff --git a/Makefile b/Makefile index 0facae16..623c8fcc 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ PANDORA=1 SDL_CFLAGS = `sdl-config --cflags` DEFS += `xml2-config --cflags` -DEFS += -DCPU_arm -DARM_ASSEMBLY -DARMV6_ASSEMBLY -DGP2X -DPANDORA -DSIX_AXIS_WORKAROUND +DEFS += -DCPU_arm -DARM_ASSEMBLY -DARMV6_ASSEMBLY -DARMV6T2 -DGP2X -DPANDORA -DSIX_AXIS_WORKAROUND DEFS += -DWITH_INGAME_WARNING DEFS += -DROM_PATH_PREFIX=\"./\" -DDATA_PREFIX=\"./data/\" -DSAVE_PREFIX=\"./saves/\" DEFS += -DUSE_SDL @@ -70,14 +70,21 @@ ASFLAGS += $(CPU_FLAGS) CXXFLAGS += $(SDL_CFLAGS) $(CPU_FLAGS) $(DEFS) $(MORE_CFLAGS) + +# src/kb-sdl/keyboard.o \ + OBJS = \ + src/akiko.o \ src/aros.rom.o \ src/audio.o \ src/autoconf.o \ src/blitfunc.o \ src/blittable.o \ src/blitter.o \ + src/blkdev.o \ + src/blkdev_cdimage.o \ src/bsdsocket.o \ + src/cdrom.o \ src/cfgfile.o \ src/cia.o \ src/crc32.o \ @@ -115,7 +122,7 @@ OBJS = \ src/archivers/7z/7zBuf.o \ src/archivers/7z/7zCrc.o \ src/archivers/7z/7zStream.o \ - src/archivers/7z/Bcj2.o \ + src/archivers/7z/Bcj2.o \ src/archivers/7z/Bra.o \ src/archivers/7z/Bra86.o \ src/archivers/7z/LzmaDec.o \ @@ -146,14 +153,14 @@ OBJS = \ src/archivers/zip/unzip.o \ src/md-pandora/support.o \ src/od-pandora/bsdsocket_host.o \ + src/od-pandora/cda_play.o \ src/od-pandora/fsdb_host.o \ src/od-pandora/hardfile_pandora.o \ - src/od-pandora/joystick.o \ - src/kb-sdl/keyboard.o \ - src/od-pandora/inputmode.o \ + src/od-pandora/keyboard.o \ src/od-pandora/writelog.o \ src/od-pandora/pandora.o \ src/od-pandora/pandora_filesys.o \ + src/od-pandora/pandora_input.o \ src/od-pandora/pandora_gui.o \ src/od-pandora/pandora_rp9.o \ src/od-pandora/pandora_mem.o \ diff --git a/Readme_Pandora.txt b/Readme_Pandora.txt index ce736e65..d6cf1304 100644 --- a/Readme_Pandora.txt +++ b/Readme_Pandora.txt @@ -1,6 +1,6 @@ UAE4ARM - Pandora edition -Version 1.0.0.0 +Version 1.0.0.12 Thanks to all for working on the different versions of UAE this emulator based on: - Toni Wilen @@ -39,12 +39,12 @@ The main differences to UAE4ALL: - bsdsockets - RDB hardfiles - Support for rp9 + - CD32 support What's missing compared to WinUAE: - Cycle exact emulation of cpu and blitter - SCSI support - AHI - - CD - Builtin debugger and some more... @@ -55,9 +55,9 @@ Index 2. Controls 2.1 General and quick keys (outside of GUI) - 2.2 Joystick mode - 2.3 Mouse mode - 2.4 Stylus mode + 2.2 Nubs as mouse + 2.3 dPad as mouse + 2.4 Mousehack enabled 2.5 Specific controls inside GUI 3. GUI @@ -68,7 +68,7 @@ Index 3.5 ROM 3.6 RAM 3.7 Floppy drives - 3.8 Hard drives + 3.8 Hard drives / CD 3.9 Display 3.10 Sound 3.11 Input @@ -80,10 +80,10 @@ Index 1. Setup -Place the UAE4ALL PND in the required directory (menu, desktop or apps). Running it for the first time will create the +Place the UAE4ARM PND in the required directory (menu, desktop or apps). Running it for the first time will create the necessary folders in pandora/appdata on you SD card. -In order to use UAE4ALL you need an Amiga Bios image (kickstart rom). Place all your roms and the keyfiles (if required) +In order to use UAE4ARM you need an Amiga Bios image (kickstart rom). Place all your roms and the keyfiles (if required) in the appdata folder of UAE4ARM and select this folder with the GUI (goto page Paths, choose folder in option "System ROMS" and click on "Rescan ROMs"). @@ -98,12 +98,15 @@ the AmigaForever data folder to appdata/uae4arm/rp9. 2.1 General & Quick Keys (outside of GUI) SELECT: Open GUI -START: Toggle joystick/mouse/stylus mode -Pandora Key: pressing this at any time (inside or outside the GUI) and it will minimise UAE4AALL +START: Play button of CD32 +Pandora Key: pressing this at any time (inside or outside the GUI) and it will minimise UAE4ARM Hold L+R + D-pad up/down: Move displayed gfx vertically Hold L+R + 1/2/3/4/5/6/7/8: select preset screenmode Hold L+R + 9/0: set number of displayed lines Hold L+R + w: change Amiga displayed width +Hold L+R + r: toggle lores/hires +L+START: RWD button of CD32 +R+START: FFW button of CD32 L+c: Toggle custom controls L+d: Toggle status line L+f: Toggle frameskip @@ -112,43 +115,36 @@ L+s: Quick save R+D-pad: Arrow keys in all control modes -2.2 Joystick Mode +2.2 Nubs as mouse D-pad: Joystick movement -A/X: Joystick fire button (depends which button mode you are in) -X/A: Up on joystick (used as jump in platform games, etc. depends which button mode you are in) -B: mapped to the space bar -Y: Space bar -L: Alt -L+D-pad: Move mouse pointer -L+A: Left mouse click -L+B: Right mouse click +X: 1st Joystick button / RED button on CD32 controller +B: 2nd Joystick button / BLUE button on CD32 controller +A: GREEN button on CD32 controller +Y: Space bar / YELLOW button on CD32 controller R+D-pad: Arrow keys -R+Y: Toggle auto fire on/off R+A: Ctrl +R+B: left Alt R+X: Help -R+B: Num Enter -2.3 Mouse Mode +2.3 dPad as mouse D-pad: Move mouse pointer -Left Nub: Move mouse pointer (not workng) -Right Nub: Flick left for "left mouse button", flick right for "right mouse button" (not working) -Y: Space bar A: left mouse click B: right mouse click +Y: Space bar D-pad left or right: Left flipper (Pinball Dreams/Fantasies) A/B: Right flipper (Pinball Dreams/Fantasies) X: Pull spring (Pinball Dreams/Fantasies) -2.4 Stylus Mode +2.4 Mousehack enabled Tap screen: left click L/R: Hold and tap with stylus performs right click -D-pad: Left operates left mouse button, right operates right mouse button. Hold down on D-pad to prevent mouse from clicking and up on D-pad -equals a right and left click together. + +Other buttons same as in 2.1. 2.5 Specific controls inside GUI @@ -221,7 +217,7 @@ For "Collision Level", select "Sprites and Sprites vs. Playfield" which is fine Select the required kickstart ROM for the Amiga you want to emulate. -"Extended ROM File" isn't really useful in the current version of UAE4ARM. +"Extended ROM File" is required for CD32. 3.6 RAM @@ -247,7 +243,7 @@ with higher drive speed and you have to select 100%. loaded each time you select the disk and have the option "Load config with same name as disk" enabled. -3.8 Hard drives +3.8 Hard drives / CD Use "Add Directory" to add a folder or "Add Hardfile" to add a HDF file as a hard disk. @@ -256,6 +252,10 @@ To edit the settings of a HDD, click on "..." left to the entry in the list. With "Create Hardfile", you can create a new formatted HDF file up to 2 GB. For large files, it will take some time to create the new hard disk. You have to format the new HDD in Amiga via the Workbench. +Select "CD drive" to emulate CD for CD32. Use "Eject"" to remove currentCD and click on "..." to open a dialog to select +the iso/cue file for CD emulation. +Note: in current version, only WAV is supported for audio tracks. MP3 and FLAC may be supported in a later version. + 3.9 Display @@ -284,12 +284,11 @@ the left and right channels of the Pandora. A value of 70% for separation and no 3.11 Input -With "Control config", you can choose one of four preset button configurations. -Select the port for which the joystick should be emulated with "Joystick". -"Tap Delay" specifies the time between taping the screen and an emulated mouse button click. +You can select the control type for both ports. Set the emulated mouse speed to .25x, .5x, 1x 2x and 4x to slow down or speed up the mouse. When "Enable mousehack" is activated, you can use the stylus to set the mouse pointer to the exact position. This works very well on Workbench, but many games using there own mouse handling and will not profit from this code. +"Tap Delay" specifies the time between taping the screen and an emulated mouse button click. When enabling "Custom Control", you can define which Amiga key should be emulated by pressing one of the ABXY- or D-pad buttons. Useful to setup controls for pinball games. During emulation, you can switch between regular behaviour of the diff --git a/src/akiko.cpp b/src/akiko.cpp new file mode 100644 index 00000000..9806270e --- /dev/null +++ b/src/akiko.cpp @@ -0,0 +1,1965 @@ +/* +* UAE - The Un*x Amiga Emulator +* +* CD32 Akiko emulation +* +* - C2P +* - NVRAM +* - CDROM +* +* Copyright 2001-2010 Toni Wilen +* +*/ + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "options.h" +#include "memory.h" +#include "newcpu.h" +#include "events.h" +#include "savestate.h" +#include "blkdev.h" +#include "zfile.h" +#include "td-sdl/thread.h" +#include "akiko.h" +#include "gui.h" +#include "crc32.h" +#include "uae.h" +#include "custom.h" +#include "uae.h" + +#define AKIKO_DEBUG_NVRAM 0 +#define AKIKO_DEBUG_IO 0 +#define AKIKO_DEBUG_IO_CMD 0 + +// 43 48 49 4E 4F 4E 20 20 4F 2D 36 35 38 2D 32 20 32 34 +#define FIRMWAREVERSION "CHINON O-658-2 24" + +static void irq (void) +{ +#if AKIKO_DEBUG_IO > 1 + write_log (_T("Akiko Interrupt\n")); +#endif + if (!(intreq & 8)) { + INTREQ_0 (0x8000 | 0x0008); + } +} + +/* +* CD32 1Kb NVRAM (EEPROM) emulation +* +* NVRAM chip is 24C08 CMOS EEPROM (1024x8 bits = 1Kb) +* Chip interface is I2C (2 wire serial) +* Akiko addresses used: +* 0xb80030: bit 7 = SCL (clock), 6 = SDA (data) +* 0xb80032: 0xb80030 data direction register (0 = input, 1 = output) +* +* Because I don't have any experience on I2C, following code may be +* unnecessarily complex and not 100% correct.. +*/ + +enum i2c { I2C_WAIT, I2C_START, I2C_DEVICEADDR, I2C_WORDADDR, I2C_DATA }; + +/* size of EEPROM, don't try to change, +* (hardcoded in Kickstart) +*/ +#define NVRAM_SIZE 1024 +/* max size of one write request */ +#define NVRAM_PAGE_SIZE 16 + +static uae_u8 cd32_nvram[NVRAM_SIZE], nvram_writetmp[NVRAM_PAGE_SIZE]; +static int nvram_address, nvram_writeaddr; +static int nvram_rw; +static int bitcounter = -1, direction = -1; +static uae_u8 nvram_byte; +static int scl_out, scl_in, scl_dir, oscl, sda_out, sda_in, sda_dir, osda; +static int sda_dir_nvram; +static int state = I2C_WAIT; + +static void nvram_write (int offset, int len) +{ + struct zfile *f; + + if (!currprefs.cs_cd32nvram) + return; + f = zfile_fopen (currprefs.flashfile, _T("rb+"), ZFD_NORMAL); + if (!f) { + f = zfile_fopen (currprefs.flashfile, _T("wb"), 0); + if (!f) return; + zfile_fwrite (cd32_nvram, NVRAM_SIZE, 1, f); + } + zfile_fseek (f, offset, SEEK_SET); + zfile_fwrite (cd32_nvram + offset, len, 1, f); + zfile_fclose (f); +} + +static void nvram_read (void) +{ + struct zfile *f; + + if (!currprefs.cs_cd32nvram) + return; + f = zfile_fopen (currprefs.flashfile, _T("rb"), ZFD_NORMAL); + memset (cd32_nvram, 0, NVRAM_SIZE); + if (!f) return; + zfile_fread (cd32_nvram, NVRAM_SIZE, 1, f); + zfile_fclose (f); +} + +static void i2c_do (void) +{ +#if AKIKO_DEBUG_NVRAM + int i; +#endif + sda_in = 1; + if (!sda_dir_nvram && scl_out && oscl) { + if (!sda_out && osda) { /* START-condition? */ + state = I2C_DEVICEADDR; + bitcounter = 0; + direction = -1; +#if AKIKO_DEBUG_NVRAM + write_log (_T("START\n")); +#endif + return; + } else if(sda_out && !osda) { /* STOP-condition? */ + state = I2C_WAIT; + bitcounter = -1; +#if AKIKO_DEBUG_NVRAM + write_log (_T("STOP\n")); +#endif + if (direction > 0) { + memcpy (cd32_nvram + (nvram_address & ~(NVRAM_PAGE_SIZE - 1)), nvram_writetmp, NVRAM_PAGE_SIZE); + nvram_write (nvram_address & ~(NVRAM_PAGE_SIZE - 1), NVRAM_PAGE_SIZE); + direction = -1; + gui_flicker_led (LED_MD, 0, 2); +#if AKIKO_DEBUG_NVRAM + write_log (_T("NVRAM write address %04X:"), nvram_address & ~(NVRAM_PAGE_SIZE - 1)); + for (i = 0; i < NVRAM_PAGE_SIZE; i++) + write_log (_T("%02X"), nvram_writetmp[i]); + write_log (_T("\n")); + +#endif + } + return; + } + } + if (bitcounter >= 0) { + if (direction) { + /* Amiga -> NVRAM */ + if (scl_out && !oscl) { + if (bitcounter == 8) { +#if AKIKO_DEBUG_NVRAM + write_log (_T("RB %02X "), nvram_byte, M68K_GETPC); +#endif + sda_in = 0; /* ACK */ + if (direction > 0) { + nvram_writetmp[nvram_writeaddr++] = nvram_byte; + nvram_writeaddr &= 15; + bitcounter = 0; + } else { + bitcounter = -1; + } + } else { + //write_log (_T("NVRAM received bit %d, offset %d\n"), sda_out, bitcounter); + nvram_byte <<= 1; + nvram_byte |= sda_out; + bitcounter++; + } + } + } else { + /* NVRAM -> Amiga */ + if (scl_out && !oscl && bitcounter < 8) { + if (bitcounter == 0) + nvram_byte = cd32_nvram[nvram_address]; + sda_dir_nvram = 1; + sda_in = (nvram_byte & 0x80) ? 1 : 0; + //write_log (_T("NVRAM sent bit %d, offset %d\n"), sda_in, bitcounter); + nvram_byte <<= 1; + bitcounter++; + if (bitcounter == 8) { +#if AKIKO_DEBUG_NVRAM + write_log (_T("NVRAM sent byte %02X address %04X PC=%08X\n"), cd32_nvram[nvram_address], nvram_address, M68K_GETPC); +#endif + nvram_address++; + nvram_address &= NVRAM_SIZE - 1; + sda_dir_nvram = 0; + } + } + if(!sda_out && sda_dir && !scl_out) /* ACK from Amiga */ + bitcounter = 0; + } + if (bitcounter >= 0) return; + } + switch (state) + { + case I2C_DEVICEADDR: + if ((nvram_byte & 0xf0) != 0xa0) { + write_log (_T("WARNING: I2C_DEVICEADDR: device address != 0xA0\n")); + state = I2C_WAIT; + return; + } + nvram_rw = (nvram_byte & 1) ? 0 : 1; + if (nvram_rw) { + /* 2 high address bits, only fetched if WRITE = 1 */ + nvram_address &= 0xff; + nvram_address |= ((nvram_byte >> 1) & 3) << 8; + state = I2C_WORDADDR; + direction = -1; + } else { + state = I2C_DATA; + direction = 0; + sda_dir_nvram = 1; + } + bitcounter = 0; +#if AKIKO_DEBUG_NVRAM + write_log (_T("I2C_DEVICEADDR: rw %d, address %02Xxx PC=%08X\n"), nvram_rw, nvram_address >> 8, M68K_GETPC); +#endif + break; + case I2C_WORDADDR: + nvram_address &= 0x300; + nvram_address |= nvram_byte; +#if AKIKO_DEBUG_NVRAM + write_log (_T("I2C_WORDADDR: address %04X PC=%08X\n"), nvram_address, M68K_GETPC); +#endif + if (direction < 0) { + memcpy (nvram_writetmp, cd32_nvram + (nvram_address & ~(NVRAM_PAGE_SIZE - 1)), NVRAM_PAGE_SIZE); + nvram_writeaddr = nvram_address & (NVRAM_PAGE_SIZE - 1); + gui_flicker_led (LED_MD, 0, 1); + } + state = I2C_DATA; + bitcounter = 0; + direction = 1; + break; + } +} + +static void akiko_nvram_write (int offset, uae_u32 v) +{ + int sda; + switch (offset) + { + case 0: + oscl = scl_out; + scl_out = (v & 0x80) ? 1 : 0; + osda = sda_out; + sda_out = (v & 0x40) ? 1 : 0; + break; + case 2: + scl_dir = (v & 0x80) ? 1 : 0; + sda_dir = (v & 0x40) ? 1 : 0; + break; + default: + return; + } + sda = sda_out; + if (oscl != scl_out || osda != sda) { + i2c_do (); + oscl = scl_out; + osda = sda; + } +} + +static uae_u32 akiko_nvram_read (int offset) +{ + uae_u32 v = 0; + switch (offset) + { + case 0: + if (!scl_dir) + v |= scl_in ? 0x80 : 0x00; + else + v |= scl_out ? 0x80 : 0x00; + if (!sda_dir) + v |= sda_in ? 0x40 : 0x00; + else + v |= sda_out ? 0x40 : 0x00; + break; + case 2: + v |= scl_dir ? 0x80 : 0x00; + v |= sda_dir ? 0x40 : 0x00; + break; + } + return v; +} + +/* CD32 Chunky to Planar hardware emulation +* Akiko addresses used: +* 0xb80038-0xb8003b +*/ + +static uae_u32 akiko_buffer[8]; +static int akiko_read_offset, akiko_write_offset; +static uae_u32 akiko_result[8]; + +#if 0 +static void akiko_c2p_do (void) +{ + int i; + + for (i = 0; i < 8; i++) + akiko_result[i] = 0; + /* FIXME: better c2p algoritm than this piece of crap.... */ + for (i = 0; i < 8 * 32; i++) { + if (akiko_buffer[7 - (i >> 5)] & (1 << (i & 31))) + akiko_result[i & 7] |= 1 << (i >> 3); + } +} +#else +/* Optimised Chunky-to-Planar algorithm by Mequa */ +static uae_u32 akiko_precalc_shift[32]; +static uae_u32 akiko_precalc_bytenum[32][8]; +static void akiko_precalculate (void) +{ + uae_u32 i, j; + for (i = 0; i < 32; i++) { + akiko_precalc_shift [(int)i] = 1 << i; + for (j = 0; j < 8; j++) { + akiko_precalc_bytenum[(int)i][(int)j] = (i >> 3) + ((7 - j) << 2); + } + } +} + +static void akiko_c2p_do (void) +{ + int i; + + for (i = 0; i < 8; i++) { + akiko_result[i] = (((akiko_buffer[0] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][0]) ) + | (((akiko_buffer[1] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][1]) ) + | (((akiko_buffer[2] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][2]) ) + | (((akiko_buffer[3] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][3]) ) + | (((akiko_buffer[4] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][4]) ) + | (((akiko_buffer[5] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][5]) ) + | (((akiko_buffer[6] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][6]) ) + | (((akiko_buffer[7] & akiko_precalc_shift[i]) != 0) << (akiko_precalc_bytenum[i][7]) ) + | (((akiko_buffer[0] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][0]) ) + | (((akiko_buffer[1] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][1]) ) + | (((akiko_buffer[2] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][2]) ) + | (((akiko_buffer[3] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][3]) ) + | (((akiko_buffer[4] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][4]) ) + | (((akiko_buffer[5] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][5]) ) + | (((akiko_buffer[6] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][6]) ) + | (((akiko_buffer[7] & akiko_precalc_shift[i+8]) != 0) << (akiko_precalc_bytenum[i+8][7]) ) + | (((akiko_buffer[0] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][0])) + | (((akiko_buffer[1] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][1])) + | (((akiko_buffer[2] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][2])) + | (((akiko_buffer[3] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][3])) + | (((akiko_buffer[4] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][4])) + | (((akiko_buffer[5] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][5])) + | (((akiko_buffer[6] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][6])) + | (((akiko_buffer[7] & akiko_precalc_shift[i+16]) != 0) << (akiko_precalc_bytenum[i+16][7])) + | (((akiko_buffer[0] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][0])) + | (((akiko_buffer[1] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][1])) + | (((akiko_buffer[2] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][2])) + | (((akiko_buffer[3] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][3])) + | (((akiko_buffer[4] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][4])) + | (((akiko_buffer[5] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][5])) + | (((akiko_buffer[6] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][6])) + | (((akiko_buffer[7] & akiko_precalc_shift[i+24]) != 0) << (akiko_precalc_bytenum[i+24][7])); + } +} +#endif + +static void akiko_c2p_write (int offset, uae_u32 v) +{ + if (offset == 3) + akiko_buffer[akiko_write_offset] = 0; + akiko_buffer[akiko_write_offset] |= v << ( 8 * (3 - offset)); + if (offset == 0) { + akiko_write_offset++; + akiko_write_offset &= 7; + } + akiko_read_offset = 0; +} + +static uae_u32 akiko_c2p_read (int offset) +{ + uae_u32 v; + + if (akiko_read_offset == 0 && offset == 3) + akiko_c2p_do (); + akiko_write_offset = 0; + v = akiko_result[akiko_read_offset]; + if (offset == 0) { + akiko_read_offset++; + akiko_read_offset &= 7; + } + return v >> (8 * (3 - offset)); +} + +/* CD32 CDROM hardware emulation +* Akiko addresses used: +* 0xb80004-0xb80028 +*/ + +#define CDINTERRUPT_SUBCODE 0x80000000 +#define CDINTERRUPT_DRIVEXMIT 0x40000000 /* not used by ROM */ +#define CDINTERRUPT_DRIVERECV 0x20000000 /* not used by ROM */ +#define CDINTERRUPT_RXDMADONE 0x10000000 +#define CDINTERRUPT_TXDMADONE 0x08000000 +#define CDINTERRUPT_PBX 0x04000000 +#define CDINTERRUPT_OVERFLOW 0x02000000 + +#define CDFLAG_SUBCODE 0x80000000 +#define CDFLAG_TXD 0x40000000 +#define CDFLAG_RXD 0x20000000 +#define CDFLAG_CAS 0x10000000 +#define CDFLAG_PBX 0x08000000 +#define CDFLAG_ENABLE 0x04000000 +#define CDFLAG_RAW 0x02000000 +#define CDFLAG_MSB 0x01000000 + +#define CDS_ERROR 0x80 +#define CDS_PLAYING 0x08 +#define CDS_PLAYEND 0x00 + +#define CH_ERR_BADCOMMAND 0x80 // %10000000 +#define CH_ERR_CHECKSUM 0x88 // %10001000 +#define CH_ERR_DRAWERSTUCK 0x90 // %10010000 +#define CH_ERR_DISKUNREADABLE 0x98 // %10011000 +#define CH_ERR_INVALIDADDRESS 0xa0 // %10100000 +#define CH_ERR_WRONGDATA 0xa8 // %10101000 +#define CH_ERR_FOCUSERROR 0xc8 // %11001000 +#define CH_ERR_SPINDLEERROR 0xd0 // %11010000 +#define CH_ERR_TRACKINGERROR 0xd8 // %11011000 +#define CH_ERR_SLEDERROR 0xe0 // %11100000 +#define CH_ERR_TRACKJUMP 0xe8 // %11101000 +#define CH_ERR_ABNORMALSEEK 0xf0 // %11110000 +#define CH_ERR_NODISK 0xf8 // %11111000 + +static int subcodecounter; + +#define MAX_SUBCODEBUFFER 36 +static volatile int subcodebufferoffset, subcodebufferoffsetw; +static uae_u8 subcodebufferinuse[MAX_SUBCODEBUFFER]; +static uae_u8 subcodebuffer[MAX_SUBCODEBUFFER * SUB_CHANNEL_SIZE]; + +static uae_u32 cdrom_intreq, cdrom_intena; +static uae_u8 cdrom_subcodeoffset; +static uae_u32 cdrom_addressdata, cdrom_addressmisc; +static uae_u32 subcode_address, cdrx_address, cdtx_address; +static uae_u32 cdrom_flags; +static uae_u32 cdrom_pbx; + +static uae_u8 cdcomtxinx; /* 0x19 */ +static uae_u8 cdcomrxinx; /* 0x1a */ +static uae_u8 cdcomtxcmp; /* 0x1d */ +static uae_u8 cdrom_result_buffer[32]; +static uae_u8 cdrom_command_buffer[32]; +static uae_u8 cdrom_command; + +static int cdrom_toc_counter; +static uae_u32 cdrom_toc_crc; +static uae_u8 cdrom_toc_buffer[MAX_TOC_ENTRIES * 13]; +static struct cd_toc_head cdrom_toc_cd_buffer; +static uae_u8 qcode_buf[SUBQ_SIZE]; +static int qcode_valid; + +static int cdrom_disk, cdrom_paused, cdrom_playing, cdrom_audiostatus; +static int cdrom_command_active, cdrom_command_startdelay, cdrom_command_idle; +static int cdrom_command_length; +static int cdrom_checksum_error, cdrom_unknown_command; +static int cdrom_data_offset, cdrom_speed, cdrom_sector_counter; +static int cdrom_current_sector, cdrom_seek_delay; +static int cdrom_data_end; +static int cdrom_audiotimeout; +static int cdrom_led; +static int cdrom_dosomething; +static int cdrom_receive_started; +static int cdrom_muted; +static int cd_initialized; + +static uae_u8 *sector_buffer_1, *sector_buffer_2; +static int sector_buffer_sector_1, sector_buffer_sector_2; +#define SECTOR_BUFFER_SIZE 64 +static uae_u8 *sector_buffer_info_1, *sector_buffer_info_2; + +static int unitnum = -1; +static bool akiko_inited; +static volatile int mediachanged, mediacheckcounter; +static volatile int frame2counter; + +static smp_comm_pipe requests; +static volatile int akiko_thread_running; +static uae_sem_t akiko_sem, sub_sem; + +static void checkint (void) +{ + if (cdrom_intreq & cdrom_intena) + irq (); +} + +static void set_status (uae_u32 status) +{ +#if AKIKO_DEBUG_IO + if (!(cdrom_intreq & status)) + write_log (_T("Akiko INTREQ %08x (%08x)\n"), status, cdrom_intreq | status); +#endif + cdrom_intreq |= status; + checkint (); + cdrom_led ^= LED_CD_ACTIVE2; +} + +void rethink_akiko (void) +{ + checkint (); +} + +static void cdaudiostop_do (void) +{ + qcode_valid = 0; + if (unitnum < 0) + return; + sys_command_cd_pause (unitnum, 0); + sys_command_cd_stop (unitnum); +} + +static void cdaudiostop (void) +{ + cdrom_audiostatus = 0; + cdrom_audiotimeout = 0; + cdrom_paused = 0; + cdrom_playing = 0; + write_comm_pipe_u32 (&requests, 0x0104, 1); +} + +static void subfunc (uae_u8 *data, int cnt) +{ + if (!(cdrom_flags & CDFLAG_SUBCODE)) + return; + uae_sem_wait (&sub_sem); +#if 0 + int total = 0; + for (int i = 0; i < MAX_SUBCODEBUFFER; i++) { + if (subcodebufferinuse[i]) + total++; + } + write_log (_T("%d "), total); +#endif + if (subcodebufferinuse[subcodebufferoffsetw]) { + memset (subcodebufferinuse, 0,sizeof (subcodebufferinuse)); + subcodebufferoffsetw = subcodebufferoffset = 0; + uae_sem_post (&sub_sem); + write_log (_T("CD32: subcode buffer overflow 1\n")); + return; + } + int offset = subcodebufferoffsetw; + while (cnt > 0) { + if (subcodebufferinuse[offset]) { + write_log (_T("CD32: subcode buffer overflow 2\n")); + break; + } + subcodebufferinuse[offset] = 1; + memcpy (&subcodebuffer[offset * SUB_CHANNEL_SIZE], data, SUB_CHANNEL_SIZE); + data += SUB_CHANNEL_SIZE; + offset++; + if (offset >= MAX_SUBCODEBUFFER) + offset = 0; + cnt--; + } + subcodebufferoffsetw = offset; + uae_sem_post (&sub_sem); +} + +static int statusfunc (int status) +{ + if (status == -1) + return 0; + if (status == -2) + return 150; + if (cdrom_audiostatus != status) { + if (status == AUDIO_STATUS_IN_PROGRESS) { + cdrom_playing = 1; + cdrom_audiotimeout = 1; + } + if (cdrom_playing && status != AUDIO_STATUS_IN_PROGRESS && status != AUDIO_STATUS_PAUSED) { + cdrom_audiotimeout = -1; + } + } + cdrom_audiostatus = status; + return 0; +} + +static void cdaudioplay_do (void) +{ + uae_u32 startlsn = read_comm_pipe_u32_blocking (&requests); + uae_u32 endlsn = read_comm_pipe_u32_blocking (&requests); + uae_u32 scan = read_comm_pipe_u32_blocking (&requests); + qcode_valid = 0; + if (unitnum < 0) + return; + sys_command_cd_pause (unitnum, 0); + sys_command_cd_play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc); +} + +static bool isaudiotrack (int startlsn) +{ + struct cd_toc *s = NULL; + uae_u32 addr; + int i; + + if (!cdrom_toc_cd_buffer.points) + return false; + for (i = 0; i < cdrom_toc_cd_buffer.points; i++) { + s = &cdrom_toc_cd_buffer.toc[i]; + addr = s->paddress; + if (s->track > 0 && s->track < 100 && addr >= startlsn) + break; + s++; + } + if (s && (s->control & 0x0c) == 0x04) { + write_log (_T("tried to play data track %d!\n"), s->track); + return false; + } + return true; +} + +static struct cd_toc *get_track (int startlsn) +{ + for (int i = cdrom_toc_cd_buffer.first_track_offset + 1; i <= cdrom_toc_cd_buffer.last_track_offset; i++) { + struct cd_toc *s = &cdrom_toc_cd_buffer.toc[i]; + uae_u32 addr = s->paddress; + if (startlsn < addr) + return s - 1; + } + return NULL; +} + +static int last_play_end; +static int cd_play_audio (int startlsn, int endlsn, int scan) +{ + struct cd_toc *s = NULL; + + if (!cdrom_toc_cd_buffer.points) + return 0; + s = get_track (startlsn); + if (s && (s->control & 0x0c) == 0x04) { + s = get_track (startlsn + 150); + if (s && (s->control & 0x0c) == 0x04) { + write_log (_T("tried to play data track %d!\n"), s->track); + s++; + startlsn = s->paddress; + s++; + endlsn = s->paddress; + } + startlsn = s->paddress; + } + qcode_valid = 0; + last_play_end = endlsn; + cdrom_audiotimeout = 10; + cdrom_paused = 0; + write_comm_pipe_u32 (&requests, 0x0110, 0); + write_comm_pipe_u32 (&requests, startlsn, 0); + write_comm_pipe_u32 (&requests, endlsn, 0); + write_comm_pipe_u32 (&requests, scan, 1); + return 1; +} + + +/* read qcode */ +static int last_play_pos; +static int cd_qcode (uae_u8 *d) +{ + uae_u8 *buf, *s, as; + + if (d) + memset (d, 0, 11); + last_play_pos = 0; + buf = qcode_buf; + as = buf[1]; + buf[2] = 0x80; + if (!qcode_valid) + return 0; + if (cdrom_audiostatus != AUDIO_STATUS_IN_PROGRESS && cdrom_audiostatus != AUDIO_STATUS_PAUSED) + return 0; + s = buf + 4; + last_play_pos = msf2lsn (fromlongbcd (s + 7)); + if (!d) + return 0; + buf[2] = 0; + /* ??? */ + d[0] = 0; + /* CtlAdr */ + d[1] = s[0]; + /* Track */ + d[2] = s[1]; + /* Index */ + d[3] = s[2]; + /* TrackPos */ + d[4] = s[3]; + d[5] = s[4]; + d[6] = s[5]; + /* DiskPos */ + d[7] = 0; + d[8] = s[7]; + d[9] = s[8]; + d[10] = s[9]; + if (as == AUDIO_STATUS_IN_PROGRESS) { + /* Make sure end of disc position is not missed. + */ + if (last_play_pos >= cdrom_toc_cd_buffer.lastaddress || cdrom_toc_cd_buffer.lastaddress - last_play_pos < 10) { + int msf = lsn2msf (cdrom_toc_cd_buffer.lastaddress); + d[8] = tobcd ((uae_u8)(msf >> 16)); + d[9] = tobcd ((uae_u8)(msf >> 8)); + d[10] = tobcd ((uae_u8)(msf >> 0)); + } + } +// write_log (_T("%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X\n"), +// d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11]); + return 0; +} + +/* read toc */ +static int get_cdrom_toc (void) +{ + int j; + int datatrack = 0, secondtrack = 0; + + cdrom_toc_counter = -1; + if (!sys_command_cd_toc (unitnum, &cdrom_toc_cd_buffer)) + return 1; + memset (cdrom_toc_buffer, 0, MAX_TOC_ENTRIES * 13); + cdrom_data_end = -1; + for (j = 0; j < cdrom_toc_cd_buffer.points; j++) { + struct cd_toc *s = &cdrom_toc_cd_buffer.toc[j]; + uae_u8 *d = &cdrom_toc_buffer[j * 13]; + int addr = s->paddress; + int msf = lsn2msf (addr); + if (s->point == 0xa0 || s->point == 0xa1) + msf = s->track << 16; + d[1] = (s->adr << 0) | (s->control << 4); + d[3] = s->point < 100 ? tobcd (s->point) : s->point; + d[8] = tobcd ((msf >> 16) & 0xff); + d[9] = tobcd ((msf >> 8) & 0xff); + d[10] = tobcd ((msf >> 0) & 0xff); + if (s->point == 1 && (s->control & 0x0c) == 0x04) + datatrack = 1; + if (s->point == 2) + secondtrack = addr; + } + cdrom_toc_crc = get_crc32 (cdrom_toc_buffer, cdrom_toc_cd_buffer.points * 13); + if (datatrack) { + if (secondtrack) + cdrom_data_end = secondtrack; + else + cdrom_data_end = cdrom_toc_cd_buffer.lastaddress; + } + return 0; +} + +/* open device */ +static int sys_cddev_open (void) +{ + struct device_info di; + unitnum = get_standard_cd_unit (CD_STANDARD_UNIT_CD32); + sys_command_info (unitnum, &di, 0); + write_log (_T("using drive %s (unit %d, media %d)\n"), di.label, unitnum, di.media_inserted); + /* make sure CD audio is not playing */ + cdaudiostop_do (); + return 0; +} + +/* close device */ +static void sys_cddev_close (void) +{ + if (unitnum >= 0) { + cdaudiostop_do (); + sys_command_close (unitnum); + } + unitnum = -1; + +} + +static int command_lengths[] = { 1,2,1,1,12,2,1,1,4,1,-1,-1,-1,-1,-1,-1 }; + +static int cdrom_start_return_data (int len) +{ + if (cdrom_receive_started > 0) + return 0; + if (len <= 0) + return -1; + cdrom_receive_started = len; + return 1; +} + +static void cdrom_return_data (void) +{ + uae_u32 cmd_buf = cdrx_address; + int i; + uae_u8 checksum; + int len = cdrom_receive_started; + + if (!len) + return; + if (!(cdrom_flags & CDFLAG_RXD)) + return; +#if AKIKO_DEBUG_IO_CMD + write_log (_T("OUT:")); +#endif + checksum = 0xff; + for (i = 0; i < len; i++) { + checksum -= cdrom_result_buffer[i]; + put_byte (cmd_buf + ((cdcomrxinx + i) & 0xff), cdrom_result_buffer[i]); +#if AKIKO_DEBUG_IO_CMD + write_log (_T("%02X "), cdrom_result_buffer[i]); +#endif + } + put_byte (cmd_buf + ((cdcomrxinx + len) & 0xff), checksum); +#if AKIKO_DEBUG_IO_CMD + write_log (_T("(%02X)\n"), checksum); +#endif + cdcomrxinx += len + 1; + cdcomrxinx &= 0xff; + set_status (CDINTERRUPT_RXDMADONE); + cdrom_receive_started = 0; +} + +static int cdrom_command_led (void) +{ + int v = cdrom_command_buffer[1]; + int old = cdrom_led; + cdrom_led &= ~LED_CD_ACTIVE; + cdrom_led |= (v & 1) ? LED_CD_ACTIVE : 0; + if (cdrom_led != old) + gui_flicker_led (LED_CD, 0, cdrom_led); + if (v & 0x80) { // result wanted? + cdrom_result_buffer[0] = cdrom_command; + cdrom_result_buffer[1] = (cdrom_led & LED_CD_ACTIVE) ? 1 : 0; + return 2; + } + return 0; +} + +static int cdrom_command_idle_status (void) +{ + cdrom_result_buffer[0] = 0x0a; + cdrom_result_buffer[1] = 0x70; + return 2; +} + +static int cdrom_command_media_status (void) +{ + cdrom_result_buffer[0] = 0x0a; + cdrom_result_buffer[1] = sys_command_ismedia (unitnum, 0) > 0 ? 0x83: 0x80; + return 2; +} + +/* check if cd drive door is open or closed, return firmware info */ +static int cdrom_command_status (void) +{ + cdrom_result_buffer[1] = 0x01; + //cdrom_result_buffer[1] = 0x80; door open + if (unitnum >= 0) + get_cdrom_toc (); + /* firmware info */ + memcpy (cdrom_result_buffer + 2, FIRMWAREVERSION, sizeof FIRMWAREVERSION); + cdrom_result_buffer[0] = cdrom_command; + cd_initialized = 1; + return 20; +} + +/* return one TOC entry */ +static int cdrom_return_toc_entry (void) +{ + cdrom_result_buffer[0] = 6; + if (cdrom_toc_cd_buffer.points == 0) { + cdrom_result_buffer[1] = CDS_ERROR; + return 15; + } + cdrom_result_buffer[1] = 0; + memcpy (cdrom_result_buffer + 2, cdrom_toc_buffer + cdrom_toc_counter * 13, 13); + cdrom_toc_counter++; + if (cdrom_toc_counter >= cdrom_toc_cd_buffer.points) + cdrom_toc_counter = -1; + return 15; +} + +static int checkerr (void) +{ + if (!cdrom_disk) { + cdrom_result_buffer[1] = CH_ERR_NODISK; + return 1; + } + return 0; +} + +static int cdrom_command_stop (void) +{ + cdrom_audiotimeout = 0; + cdrom_result_buffer[0] = cdrom_command; + if (checkerr ()) + return 2; + cdrom_result_buffer[1] = 0; + cdaudiostop (); + return 2; +} + +/* pause CD audio */ +static int cdrom_command_pause (void) +{ +#if AKIKO_DEBUG_IO_CMD + write_log (_T("CD32: pause: %d, %d\n"), cdrom_paused, cdrom_playing); +#endif + cdrom_audiotimeout = 0; + cdrom_toc_counter = -1; + cdrom_result_buffer[0] = cdrom_command; + if (checkerr ()) + return 2; + cdrom_result_buffer[1] = cdrom_playing ? CDS_PLAYING : 0; + if (cdrom_paused) + return 2; + cdrom_paused = 1; + if (!cdrom_playing) + return 2; + write_comm_pipe_u32 (&requests, 0x0102, 1); + return 2; +} + +/* unpause CD audio */ +static int cdrom_command_unpause (void) +{ +#if AKIKO_DEBUG_IO_CMD + write_log (_T("CD32: unpause: %d, %d\n"), cdrom_paused, cdrom_playing); +#endif + cdrom_result_buffer[0] = cdrom_command; + if (checkerr ()) + return 2; + cdrom_result_buffer[1] = cdrom_playing ? CDS_PLAYING : 0; + if (!cdrom_paused) + return 2; + cdrom_paused = 0; + if (!cdrom_playing) + return 2; + write_comm_pipe_u32 (&requests, 0x0103, 1); + return 2; +} + +/* seek head/play CD audio/read data sectors */ +static int cdrom_command_multi (void) +{ + int seekpos = msf2lsn (fromlongbcd (cdrom_command_buffer + 1)); + int endpos = msf2lsn (fromlongbcd (cdrom_command_buffer + 4)); + + if (cdrom_playing) + cdaudiostop (); + cdrom_speed = (cdrom_command_buffer[8] & 0x40) ? 2 : 1; + cdrom_result_buffer[0] = cdrom_command; + cdrom_result_buffer[1] = 0; + if (!cdrom_disk) { + cdrom_result_buffer[1] = 1; // no disk + return 2; + } + + if (cdrom_command_buffer[7] == 0x80) { /* data read */ + int cdrom_data_offset_end = endpos; + cdrom_data_offset = seekpos; + cdrom_seek_delay = abs (cdrom_current_sector - cdrom_data_offset); + if (cdrom_seek_delay < 100) { + cdrom_seek_delay = 1; + } else { + cdrom_seek_delay /= 1000; + cdrom_seek_delay += 10; + if (cdrom_seek_delay > 100) + cdrom_seek_delay = 100; + } +#if AKIKO_DEBUG_IO_CMD + write_log (_T("READ DATA %06X (%d) - %06X (%d) SPD=%dx PC=%08X\n"), + seekpos, cdrom_data_offset, endpos, cdrom_data_offset_end, cdrom_speed, M68K_GETPC); +#endif + cdrom_result_buffer[1] |= 0x02; + } else if (cdrom_command_buffer[10] & 4) { /* play audio */ + int scan = 0; + if (cdrom_command_buffer[7] & 0x04) + scan = 1; + else if (cdrom_command_buffer[7] & 0x08) + scan = -1; +#if AKIKO_DEBUG_IO_CMD + write_log (_T("PLAY FROM %06X (%d) to %06X (%d) SCAN=%d\n"), + seekpos, msf2lsn (seekpos), endpos, msf2lsn (endpos), scan); +#endif + cdrom_playing = 1; + if (!cd_play_audio (seekpos, endpos, 0)) { + // play didn't start, report it in next status packet + cdrom_audiotimeout = -3; + } + cdrom_result_buffer[1] |= CDS_PLAYING; + } else { +#if AKIKO_DEBUG_IO_CMD + write_log (_T("SEEKTO %06X\n"),seekpos); +#endif + if (seekpos < 150) + cdrom_toc_counter = 0; + else + cdrom_toc_counter = -1; + } + return 2; +} + +static int cdrom_playend_notify (int status) +{ + cdrom_result_buffer[0] = 4; + if (status < 0) + cdrom_result_buffer[1] = 0x80; // error + else if (status == 0) + cdrom_result_buffer[1] = 0x08; // play started + else + cdrom_result_buffer[1] = 0x00; // play ended + return 2; +} + +/* return subq entry */ +static int cdrom_command_subq (void) +{ + cdrom_result_buffer[0] = cdrom_command; + cdrom_result_buffer[1] = 0; + cd_qcode (cdrom_result_buffer + 2); + return 15; +} + +static void cdrom_run_command (void) +{ + int i, cmd_len; + uae_u8 checksum; + uae_u8 *pp = get_real_address (cdtx_address); + + if (!(cdrom_flags & CDFLAG_TXD)) + return; + if (cdrom_command_startdelay) + return; + for (;;) { + if (cdrom_command_active) + return; + if (cdcomtxinx == cdcomtxcmp) + return; + cdrom_command = get_byte (cdtx_address + cdcomtxinx); +#if 1 + if ((cdrom_command & 0xf0) == 0) { + cdcomtxinx = (cdcomtxinx + 1) & 0xff; + return; + } +#endif + cdrom_checksum_error = 0; + cdrom_unknown_command = 0; + + cmd_len = command_lengths[cdrom_command & 0x0f]; + if (cmd_len < 0) { +#if AKIKO_DEBUG_IO_CMD + write_log (_T("unknown command %x\n"), cdrom_command & 0x0f); +#endif + cdrom_unknown_command = 1; + cdrom_command_active = 1; + cdrom_command_length = 1; + set_status (CDINTERRUPT_TXDMADONE); + return; + } + +#if AKIKO_DEBUG_IO_CMD + write_log (_T("IN:")); +#endif + checksum = 0; + for (i = 0; i < cmd_len + 1; i++) { + cdrom_command_buffer[i] = get_byte (cdtx_address + ((cdcomtxinx + i) & 0xff)); + checksum += cdrom_command_buffer[i]; +#if AKIKO_DEBUG_IO_CMD + if (i == cmd_len) + write_log (_T("(%02X) "), cdrom_command_buffer[i]); // checksum + else + write_log (_T("%02X "), cdrom_command_buffer[i]); +#endif + } + if (checksum != 0xff) { +#if AKIKO_DEBUG_IO_CMD + write_log (_T(" checksum error")); +#endif + cdrom_checksum_error = 1; + } +#if AKIKO_DEBUG_IO_CMD + write_log (_T("\n")); +#endif + cdrom_command_active = 1; + cdrom_command_length = cmd_len; + set_status (CDINTERRUPT_TXDMADONE); + return; + } +} + +static void cdrom_run_command_run (void) +{ + int len; + + cdcomtxinx = (cdcomtxinx + cdrom_command_length + 1) & 0xff; + memset (cdrom_result_buffer, 0, sizeof (cdrom_result_buffer)); + switch (cdrom_command & 0x0f) + { + case 1: + len = cdrom_command_stop (); + break; + case 2: + len = cdrom_command_pause (); + break; + case 3: + len = cdrom_command_unpause (); + break; + case 4: + len = cdrom_command_multi (); + break; + case 5: + cdrom_dosomething = 1; // this is a hack + len = cdrom_command_led (); + break; + case 6: + len = cdrom_command_subq (); + break; + case 7: + len = cdrom_command_status (); + break; + default: + len = 0; + break; + } + if (len == 0) + return; + if (cdrom_checksum_error || cdrom_unknown_command) + cdrom_result_buffer[1] |= 0x80; + cdrom_start_return_data (len); +} + +/* DMA transfer one CD sector */ +static void cdrom_run_read (void) +{ + int i, sector, inc; + int read = 0; + int sec; + int seccnt; + + if (!(cdrom_flags & CDFLAG_ENABLE)) + return; + if (!cdrom_pbx) { + set_status (CDINTERRUPT_OVERFLOW); + return; + } + if (!(cdrom_flags & CDFLAG_PBX)) + return; + if (cdrom_data_offset < 0) + return; + if (unitnum < 0) + return; + + inc = 1; + // always use highest available slot or Lotus 3 (Lotus Trilogy) fails to load + for (seccnt = 15; seccnt >= 0; seccnt--) { + if (cdrom_pbx & (1 << seccnt)) + break; + } + sector = cdrom_current_sector = cdrom_data_offset + cdrom_sector_counter; + sec = sector - sector_buffer_sector_1; + if (sector_buffer_sector_1 >= 0 && sec >= 0 && sec < SECTOR_BUFFER_SIZE) { + if (sector_buffer_info_1[sec] != 0xff && sector_buffer_info_1[sec] != 0) { + uae_u8 buf[2352]; + + memcpy (buf, sector_buffer_1 + sec * 2352, 2352); + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = cdrom_sector_counter & 31; + for (i = 0; i < 2352; i++) + put_byte (cdrom_addressdata + seccnt * 4096 + i, buf[i]); + for (i = 0; i < 73 * 2; i++) + put_byte (cdrom_addressdata + seccnt * 4096 + 0xc00 + i, 0); + cdrom_pbx &= ~(1 << seccnt); + set_status (CDINTERRUPT_PBX); + } else { + inc = 0; + } + if (sector_buffer_info_1[sec] != 0xff) + sector_buffer_info_1[sec]--; +#if AKIKO_DEBUG_IO_CMD + write_log (_T("read sector=%d, scnt=%d -> %d. %d %08X\n"), + cdrom_data_offset, cdrom_sector_counter, sector, seccnt, cdrom_addressdata + seccnt * 4096); +#endif + } else { + inc = 0; + } + if (inc) + cdrom_sector_counter++; +} + +static int lastmediastate = 0; + +static void akiko_handler (void) +{ + if (unitnum < 0) + return; + if (!cd_initialized || cdrom_receive_started) + return; + + if (mediachanged) { + if (cdrom_start_return_data (0) < 0) { + cdrom_start_return_data (cdrom_command_media_status ()); + mediachanged = 0; + get_cdrom_toc (); + /* do not remove! first try may fail */ + get_cdrom_toc (); + } + return; + } + if (cdrom_audiotimeout > 1) + cdrom_audiotimeout--; + if (cdrom_audiotimeout == 1) { // play start + cdrom_playing = 1; + cdrom_start_return_data (cdrom_playend_notify (0)); + cdrom_audiotimeout = 0; + } + if (cdrom_audiotimeout == -1) { // play finished (or disk end) + if (cdrom_playing) { + cdaudiostop (); + cdrom_audiotimeout = -2; + } else { + cdrom_audiotimeout = 0; + } + } + if (cdrom_audiotimeout == -2) { // play end notification + cdrom_start_return_data (cdrom_playend_notify (1)); + cdrom_audiotimeout = 0; + } + // play didn't start notification (illegal address) + if (cdrom_audiotimeout == -3) { // return error status + cdrom_start_return_data (cdrom_playend_notify (-1)); + cdrom_audiotimeout = 0; + } + + if (cdrom_toc_counter >= 0 && !cdrom_command_active && cdrom_dosomething) { + cdrom_start_return_data (cdrom_return_toc_entry ()); + cdrom_dosomething--; + return; + } +} + +static void akiko_internal (void) +{ + if (!currprefs.cs_cd32cd) + return; + cdrom_return_data (); + cdrom_run_command (); + if (cdrom_command_active > 0) { + cdrom_command_active--; + if (!cdrom_command_active) + cdrom_run_command_run (); + } +#if 0 + if (!cdrom_playing && !cdrom_command_active) { + cdrom_command_idle++; + if (cdrom_command_idle > 1000) { + cdrom_command_idle = 0; + cdrom_start_return_data (cdrom_command_idle_status ()); + } + } +#endif +} + +void AKIKO_hsync_handler (void) +{ + if (!currprefs.cs_cd32cd || !akiko_inited) + return; + + if (cdrom_command_startdelay > 0) { + cdrom_command_startdelay--; + } + + static float framecounter; + framecounter--; + if (framecounter <= 0) { + if (cdrom_seek_delay <= 0) { + cdrom_run_read (); + } else { + cdrom_seek_delay--; + } + framecounter += (float)maxvpos * vblank_hz / (75.0 * cdrom_speed); + } + + subcodecounter--; + if (subcodecounter <= 0) { + if ((cdrom_flags & CDFLAG_SUBCODE) && cdrom_playing && subcodebufferoffset != subcodebufferoffsetw) { + uae_sem_wait (&sub_sem); + if (subcodebufferinuse[subcodebufferoffset]) { + if (cdrom_subcodeoffset >= 128) + cdrom_subcodeoffset = 0; + else + cdrom_subcodeoffset = 128; + // 96 byte subchannel data + for (int i = 0; i < SUB_CHANNEL_SIZE; i++) + put_byte (subcode_address + cdrom_subcodeoffset + i, subcodebuffer[subcodebufferoffset * SUB_CHANNEL_SIZE + i]); + put_long (subcode_address + cdrom_subcodeoffset + SUB_CHANNEL_SIZE, 0xffffffff); + subcodebufferinuse[subcodebufferoffset] = 0; + cdrom_subcodeoffset += 100; + subcodebufferoffset++; + if (subcodebufferoffset >= MAX_SUBCODEBUFFER) + subcodebufferoffset -= MAX_SUBCODEBUFFER; + set_status (CDINTERRUPT_SUBCODE); + write_log (_T("*")); + } + uae_sem_post (&sub_sem); + } + subcodecounter = maxvpos * vblank_hz / (75 * cdrom_speed) - 5; + } + + if (frame2counter > 0) + frame2counter--; + if (mediacheckcounter > 0) + mediacheckcounter--; + + akiko_internal (); + akiko_handler (); +} + +/* cdrom data buffering thread */ +static void *akiko_thread (void *null) +{ + int i; + uae_u8 *tmp1; + uae_u8 *tmp2; + int tmp3; + int offset; + int sector; + + while (akiko_thread_running || comm_pipe_has_data (&requests)) { + + if (comm_pipe_has_data (&requests)) { + uae_u32 b = read_comm_pipe_u32_blocking (&requests); + switch (b) + { + case 0x0102: // pause + sys_command_cd_pause (unitnum, 1); + break; + case 0x0103: // unpause + sys_command_cd_pause (unitnum, 0); + break; + case 0x0104: // stop + cdaudiostop_do (); + break; + case 0x0105: // mute change + sys_command_cd_volume (unitnum, cdrom_muted ? 0 : 0x7fff, cdrom_muted ? 0 : 0x7fff); + break; + case 0x0110: // do_play! + sys_command_cd_volume (unitnum, cdrom_muted ? 0 : 0x7fff, cdrom_muted ? 0 : 0x7fff); + cdaudioplay_do (); + break; + } + } + + if (frame2counter <= 0) { + frame2counter = 312 * 50 / 2; + if (unitnum >= 0 && sys_command_cd_qcode (unitnum, qcode_buf)) { + uae_u8 as = qcode_buf[1]; + qcode_valid = 1; + } + } + + if (mediacheckcounter <= 0) { + mediacheckcounter = 312 * 50 * 2; + int media = sys_command_ismedia (unitnum, 1); + if (media < 0) { + write_log (_T("CD32: device unit %d lost\n"), unitnum); + media = lastmediastate = cdrom_disk = 0; + mediachanged = 1; + cdaudiostop_do (); + } else if (media != lastmediastate) { + write_log (_T("CD32: media changed = %d\n"), media); + lastmediastate = cdrom_disk = media; + mediachanged = 1; + cdaudiostop_do (); + } + } + + uae_sem_wait (&akiko_sem); + sector = cdrom_current_sector; + for (i = 0; i < SECTOR_BUFFER_SIZE; i++) { + if (sector_buffer_info_1[i] == 0xff) + break; + } + if (cdrom_data_end > 0 && sector >= 0 && + (sector_buffer_sector_1 < 0 || sector < sector_buffer_sector_1 || sector >= sector_buffer_sector_1 + SECTOR_BUFFER_SIZE * 2 / 3 || i != SECTOR_BUFFER_SIZE)) { + memset (sector_buffer_info_2, 0, SECTOR_BUFFER_SIZE); +#if AKIKO_DEBUG_IO_CMD + write_log (_T("filling buffer sector=%d (max=%d)\n"), sector, cdrom_data_end); +#endif + sector_buffer_sector_2 = sector; + offset = 0; + while (offset < SECTOR_BUFFER_SIZE) { + int ok = 0; + if (sector < cdrom_data_end) + ok = sys_command_cd_rawread (unitnum, sector_buffer_2 + offset * 2352, sector, 1, 2352); + sector_buffer_info_2[offset] = ok ? 3 : 0; + offset++; + sector++; + } + tmp1 = sector_buffer_info_1; + sector_buffer_info_1 = sector_buffer_info_2; + sector_buffer_info_2 = tmp1; + tmp2 = sector_buffer_1; + sector_buffer_1 = sector_buffer_2; + sector_buffer_2 = tmp2; + tmp3 = sector_buffer_sector_1; + sector_buffer_sector_1 = sector_buffer_sector_2; + sector_buffer_sector_2 = tmp3; + } + uae_sem_post (&akiko_sem); + sleep_millis (10); + } + akiko_thread_running = -1; + return 0; +} + +STATIC_INLINE uae_u8 akiko_get_long (uae_u32 v, int offset) +{ + return v >> ((3 - offset) * 8); +} + +STATIC_INLINE void akiko_put_long (uae_u32 *p, int offset, int v) +{ + *p &= ~(0xff << ((3 - offset) * 8)); + *p |= v << ((3 - offset) * 8); +} + +static uae_u32 REGPARAM3 akiko_lget (uaecptr) REGPARAM; +static uae_u32 REGPARAM3 akiko_wget (uaecptr) REGPARAM; +static uae_u32 REGPARAM3 akiko_bget (uaecptr) REGPARAM; +static uae_u32 REGPARAM3 akiko_lgeti (uaecptr) REGPARAM; +static uae_u32 REGPARAM3 akiko_wgeti (uaecptr) REGPARAM; +static void REGPARAM3 akiko_lput (uaecptr, uae_u32) REGPARAM; +static void REGPARAM3 akiko_wput (uaecptr, uae_u32) REGPARAM; +static void REGPARAM3 akiko_bput (uaecptr, uae_u32) REGPARAM; + +static uae_u32 akiko_bget2 (uaecptr addr, int msg) +{ + uae_u8 v = 0; + + addr &= 0xffff; + + switch (addr) + { + /* "CAFE" = Akiko identification. + * Kickstart ignores Akiko C2P if this ID isn't correct */ + case 0x02: + return 0xCA; + case 0x03: + return 0xFE; + /* NVRAM */ + case 0x30: + case 0x31: + case 0x32: + case 0x33: + if (currprefs.cs_cd32nvram) + v = akiko_nvram_read (addr - 0x30); + return v; + + /* C2P */ + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + if (currprefs.cs_cd32c2p) + v = akiko_c2p_read (addr - 0x38); + return v; + } + + + uae_sem_wait (&akiko_sem); + switch (addr) + { + if (currprefs.cs_cd32cd) { + /* CDROM control */ + case 0x04: + case 0x05: + case 0x06: + case 0x07: + v = akiko_get_long (cdrom_intreq, addr - 0x04); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + v = akiko_get_long (cdrom_intena, addr - 0x08); + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + v = akiko_get_long (cdrom_addressdata, addr - 0x10); + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + v = akiko_get_long (cdrom_addressmisc, addr - 0x14); + break; + case 0x18: + v = cdrom_subcodeoffset; + break; + case 0x19: + v = cdcomtxinx; + break; + case 0x1a: + v = cdcomrxinx; + break; + case 0x20: + case 0x21: + v = akiko_get_long (cdrom_pbx, addr - 0x20 + 2); + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + v = akiko_get_long (cdrom_flags, addr - 0x24); + break; + } else if (addr < 0x30) { + break; + } + + default: + write_log (_T("akiko_bget: unknown address %08X PC=%08X\n"), addr, M68K_GETPC); + v = 0; + break; + } + akiko_internal (); + uae_sem_post (&akiko_sem); + if (msg && addr < 0x30 && AKIKO_DEBUG_IO) + write_log (_T("akiko_bget %08X: %08X %02X\n"), M68K_GETPC, addr, v & 0xff); + return v; +} + +static uae_u32 REGPARAM2 akiko_bget (uaecptr addr) +{ +#ifdef JIT + special_mem |= S_READ; +#endif + return akiko_bget2 (addr, 1); +} + +static uae_u32 REGPARAM2 akiko_wget (uaecptr addr) +{ + uae_u16 v; +#ifdef JIT + special_mem |= S_READ; +#endif + addr &= 0xffff; + v = akiko_bget2 (addr + 1, 0); + v |= akiko_bget2 (addr + 0, 0) << 8; + if (addr < 0x30 && AKIKO_DEBUG_IO) + write_log (_T("akiko_wget %08X: %08X %04X\n"), M68K_GETPC, addr, v & 0xffff); + return v; +} + +static uae_u32 REGPARAM2 akiko_lget (uaecptr addr) +{ + uae_u32 v; + +#ifdef JIT + special_mem |= S_READ; +#endif + addr &= 0xffff; + v = akiko_bget2 (addr + 3, 0); + v |= akiko_bget2 (addr + 2, 0) << 8; + v |= akiko_bget2 (addr + 1, 0) << 16; + v |= akiko_bget2 (addr + 0, 0) << 24; + if (addr < 0x30 && (addr != 4 && addr != 8) && AKIKO_DEBUG_IO) + write_log (_T("akiko_lget %08X: %08X %08X\n"), M68K_GETPC, addr, v); + return v; +} + +static void akiko_bput2 (uaecptr addr, uae_u32 v, int msg) +{ + uae_u32 tmp; + + addr &= 0xffff; + v &= 0xff; + + if(msg && addr < 0x30 && AKIKO_DEBUG_IO) + write_log (_T("akiko_bput %08X: %08X=%02X\n"), M68K_GETPC, addr, v & 0xff); + + switch (addr) + { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + if (currprefs.cs_cd32nvram) + akiko_nvram_write (addr - 0x30, v); + return; + + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + if (currprefs.cs_cd32c2p) + akiko_c2p_write (addr - 0x38, v); + return; + } + + uae_sem_wait (&akiko_sem); + switch (addr) + { + if (currprefs.cs_cd32cd) { + case 0x04: + case 0x05: + case 0x06: + case 0x07: + akiko_put_long (&cdrom_intreq, addr - 0x04, v); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + akiko_put_long (&cdrom_intena, addr - 0x08, v); + if (addr == 8) + cdrom_intreq &= cdrom_intena; + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + akiko_put_long (&cdrom_addressdata, addr - 0x10, v); + cdrom_addressdata &= 0x00fff000; + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + akiko_put_long (&cdrom_addressmisc, addr - 0x14, v); + cdrom_addressmisc &= 0x00fffc00; + subcode_address = cdrom_addressmisc | 0x100; + cdrx_address = cdrom_addressmisc; + cdtx_address = cdrom_addressmisc | 0x200; + break; + case 0x18: + cdrom_intreq &= ~CDINTERRUPT_SUBCODE; + break; + case 0x1d: + cdrom_intreq &= ~CDINTERRUPT_TXDMADONE; + cdcomtxcmp = v; + if (cdrom_command_active == 0) + cdrom_command_startdelay = 2; + break; + case 0x1f: + cdrom_intreq &= ~CDINTERRUPT_RXDMADONE; + break; + case 0x20: + case 0x21: + tmp = cdrom_pbx; + akiko_put_long (&cdrom_pbx, addr - 0x20 + 2, v); + cdrom_pbx |= tmp; + cdrom_pbx &= 0xffff; + cdrom_intreq &= ~CDINTERRUPT_PBX; + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + tmp = cdrom_flags; + akiko_put_long (&cdrom_flags, addr - 0x24, v); + if ((cdrom_flags & CDFLAG_ENABLE) && !(tmp & CDFLAG_ENABLE)) + cdrom_sector_counter = 0; + if (!(cdrom_flags & CDFLAG_PBX) && (tmp & CDFLAG_PBX)) + cdrom_pbx = 0; + if ((cdrom_flags & CDFLAG_SUBCODE) && !(tmp & CDFLAG_SUBCODE)) { + uae_sem_wait (&sub_sem); + memset (subcodebufferinuse, 0, sizeof subcodebufferinuse); + subcodebufferoffset = subcodebufferoffsetw = 0; + uae_sem_post (&sub_sem); + } + break; + } else if (addr < 0x30) { + break; + } + + default: + write_log (_T("akiko_bput: unknown address %08X=%02X PC=%08X\n"), addr, v & 0xff, M68K_GETPC); + break; + } + akiko_internal (); + uae_sem_post (&akiko_sem); +} + +static void REGPARAM2 akiko_bput (uaecptr addr, uae_u32 v) +{ +#ifdef JIT + special_mem |= S_WRITE; +#endif + akiko_bput2 (addr, v, 1); +} + +static void REGPARAM2 akiko_wput (uaecptr addr, uae_u32 v) +{ +#ifdef JIT + special_mem |= S_WRITE; +#endif + addr &= 0xfff; + if((addr < 0x30 && AKIKO_DEBUG_IO)) + write_log (_T("akiko_wput %08X: %08X=%04X\n"), M68K_GETPC, addr, v & 0xffff); + akiko_bput2 (addr + 1, v & 0xff, 0); + akiko_bput2 (addr + 0, v >> 8, 0); +} + +static void REGPARAM2 akiko_lput (uaecptr addr, uae_u32 v) +{ +#ifdef JIT + special_mem |= S_WRITE; +#endif + addr &= 0xffff; + if(addr < 0x30 && AKIKO_DEBUG_IO) + write_log (_T("akiko_lput %08X: %08X=%08X\n"), M68K_GETPC, addr, v); + akiko_bput2 (addr + 3, (v >> 0) & 0xff, 0); + akiko_bput2 (addr + 2, (v >> 8) & 0xff, 0); + akiko_bput2 (addr + 1, (v >> 16) & 0xff, 0); + akiko_bput2 (addr + 0, (v >> 24) & 0xff, 0); +} + +addrbank akiko_bank = { + akiko_lget, akiko_wget, akiko_bget, + akiko_lput, akiko_wput, akiko_bput, + default_xlate, default_check, NULL, _T("Akiko"), + dummy_lgeti, dummy_wgeti, ABFLAG_IO +}; + +static void akiko_cdrom_free (void) +{ + sys_cddev_close (); + xfree (sector_buffer_1); + xfree (sector_buffer_2); + xfree (sector_buffer_info_1); + xfree (sector_buffer_info_2); + sector_buffer_1 = 0; + sector_buffer_2 = 0; + sector_buffer_info_1 = 0; + sector_buffer_info_2 = 0; +} + +void akiko_reset (void) +{ + cdaudiostop_do (); + nvram_read (); + state = I2C_WAIT; + bitcounter = -1; + direction = -1; + + cdrom_speed = 1; + cdrom_current_sector = -1; + if (!savestate_state) { + cdcomtxinx = 0; + cdcomrxinx = 0; + cdcomtxcmp = 0; + lastmediastate = -1; + } + cdrom_led = 0; + cdrom_receive_started = 0; + cd_initialized = 0; + + if (akiko_thread_running > 0) { + cdaudiostop (); + akiko_thread_running = 0; + while(akiko_thread_running == 0) + Sleep (10); + akiko_thread_running = 0; + } + akiko_cdrom_free (); + mediacheckcounter = 0; + akiko_inited = false; +} + + +void akiko_free (void) +{ + akiko_reset (); + akiko_cdrom_free (); +} + +int akiko_init (void) +{ + if (!currprefs.cs_cd32cd) + return 0; + akiko_free (); + akiko_precalculate (); + unitnum = -1; + sys_cddev_open (); + sector_buffer_1 = xmalloc (uae_u8, SECTOR_BUFFER_SIZE * 2352); + sector_buffer_2 = xmalloc (uae_u8, SECTOR_BUFFER_SIZE * 2352); + sector_buffer_info_1 = xmalloc (uae_u8, SECTOR_BUFFER_SIZE); + sector_buffer_info_2 = xmalloc (uae_u8, SECTOR_BUFFER_SIZE); + sector_buffer_sector_1 = -1; + sector_buffer_sector_2 = -1; + uae_sem_init (&akiko_sem, 0, 1); + uae_sem_init (&sub_sem, 0, 1); + if (!savestate_state) { + cdrom_playing = cdrom_paused = 0; + cdrom_data_offset = -1; + } + if (!akiko_thread_running) { + akiko_thread_running = 1; + init_comm_pipe (&requests, 100, 1); + uae_start_thread (_T("akiko"), akiko_thread, 0, NULL); + } + akiko_inited = true; + return 1; +} + +#ifdef SAVESTATE + +uae_u8 *save_akiko (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + int i; + + if (!currprefs.cs_cd32cd) + return NULL; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + save_u16 (0); + save_u16 (0xCAFE); + save_u32 (cdrom_intreq); + save_u32 (cdrom_intena); + save_u32 (0); + save_u32 (cdrom_addressdata); + save_u32 (cdrom_addressmisc); + save_u8 (cdrom_subcodeoffset); + save_u8 (cdcomtxinx); + save_u8 (cdcomrxinx); + save_u8 (0); + save_u8 (0); + save_u8 (cdcomtxcmp); + save_u8 (0); + save_u8 (0); + save_u16 ((uae_u16)cdrom_pbx); + save_u16 (0); + save_u32 (cdrom_flags); + save_u32 (0); + save_u32 (0); + save_u32 ((scl_dir ? 0x8000 : 0) | (sda_dir ? 0x4000 : 0)); + save_u32 (0); + save_u32 (0); + + for (i = 0; i < 8; i++) + save_u32 (akiko_buffer[i]); + save_u8 ((uae_u8)akiko_read_offset); + save_u8 ((uae_u8)akiko_write_offset); + + save_u32 ((cdrom_playing ? 1 : 0) | (cdrom_paused ? 2 : 0) | (cdrom_disk ? 4 : 0)); + if (cdrom_playing) + cd_qcode (0); + save_u32 (lsn2msf (last_play_pos)); + save_u32 (lsn2msf (last_play_end)); + save_u8 ((uae_u8)cdrom_toc_counter); + + save_u8 (cdrom_speed); + save_u8 (cdrom_current_sector); + + save_u32 (cdrom_toc_crc); + save_u8 (cdrom_toc_cd_buffer.points); + save_u32 (cdrom_toc_cd_buffer.lastaddress); + + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_akiko (uae_u8 *src) +{ + uae_u32 v; + int i; + + akiko_free (); + if (!currprefs.cs_cd32cd) { + changed_prefs.cs_cd32c2p = changed_prefs.cs_cd32cd = changed_prefs.cs_cd32nvram = true; + currprefs.cs_cd32c2p = currprefs.cs_cd32cd = currprefs.cs_cd32nvram = true; + akiko_init (); + } + + restore_u16 (); + restore_u16 (); + cdrom_intreq = restore_u32 (); + cdrom_intena = restore_u32 (); + restore_u32 (); + cdrom_addressdata = restore_u32 (); + cdrom_addressmisc = restore_u32 (); + subcode_address = cdrom_addressmisc | 0x100; + cdrx_address = cdrom_addressmisc; + cdtx_address = cdrom_addressmisc | 0x200; + cdrom_subcodeoffset = restore_u8 (); + cdcomtxinx = restore_u8 (); + cdcomrxinx = restore_u8 (); + restore_u8 (); + restore_u8 (); + cdcomtxcmp = restore_u8 (); + restore_u8 (); + restore_u8 (); + cdrom_pbx = restore_u16 (); + restore_u16 (); + cdrom_flags = restore_u32 (); + restore_u32 (); + restore_u32 (); + v = restore_u32 (); + scl_dir = (v & 0x8000) ? 1 : 0; + sda_dir = (v & 0x4000) ? 1 : 0; + restore_u32 (); + restore_u32 (); + + for (i = 0; i < 8; i++) + akiko_buffer[i] = restore_u32 (); + akiko_read_offset = restore_u8 (); + akiko_write_offset = restore_u8 (); + + cdrom_playing = cdrom_paused = cdrom_disk = 0; + v = restore_u32 (); + if (v & 1) + cdrom_playing = 1; + if (v & 2) + cdrom_paused = 1; + if (v & 4) + cdrom_disk = 1; + lastmediastate = cdrom_disk; + + last_play_pos = msf2lsn (restore_u32 ()); + last_play_end = msf2lsn (restore_u32 ()); + cdrom_toc_counter = (uae_s8)restore_u8 (); + cdrom_speed = restore_u8 (); + cdrom_current_sector = (uae_s8)restore_u8 (); + + restore_u32 (); + restore_u8 (); + restore_u32 (); + + return src; +} + +void restore_akiko_finish (void) +{ + if (!currprefs.cs_cd32cd) + return; + sys_cddev_close (); + akiko_init (); + akiko_c2p_do (); + get_cdrom_toc (); + write_comm_pipe_u32 (&requests, 0x0102, 1); // pause + write_comm_pipe_u32 (&requests, 0x0104, 1); // stop + write_comm_pipe_u32 (&requests, 0x0103, 1); // unpause + if (cdrom_playing && isaudiotrack (last_play_pos)) { + write_comm_pipe_u32 (&requests, 0x0103, 1); // unpause + write_comm_pipe_u32 (&requests, 0x0110, 0); // play + write_comm_pipe_u32 (&requests, last_play_pos, 0); + write_comm_pipe_u32 (&requests, last_play_end, 0); + write_comm_pipe_u32 (&requests, 0, 1); + } + cd_initialized = 1; +} + +#endif + +void akiko_mute (int muted) +{ + cdrom_muted = muted; + if (unitnum >= 0) + write_comm_pipe_u32 (&requests, 0x0105, 1); +} + diff --git a/src/blkdev.cpp b/src/blkdev.cpp new file mode 100644 index 00000000..74d6ff81 --- /dev/null +++ b/src/blkdev.cpp @@ -0,0 +1,1671 @@ +/* +* UAE - The Un*x Amiga Emulator +* +* lowlevel cd device glue, scsi emulator +* +* Copyright 2009-2010 Toni Wilen +* +*/ + +#include "sysconfig.h" +#include "sysdeps.h" +#include "options.h" +#include "memory.h" + +#include "blkdev.h" +#include "scsidev.h" +#include "savestate.h" +#include "crc32.h" +#include "td-sdl/thread.h" +#include "execio.h" + +int log_scsiemu = 0; + +#define PRE_INSERT_DELAY (3 * (currprefs.ntscmode ? 60 : 50)) + +static int scsiemu[MAX_TOTAL_SCSI_DEVICES]; + +static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES]; +static int openlist[MAX_TOTAL_SCSI_DEVICES]; +static int waspaused[MAX_TOTAL_SCSI_DEVICES]; +static int delayed[MAX_TOTAL_SCSI_DEVICES]; +static uae_sem_t unitsem[MAX_TOTAL_SCSI_DEVICES]; +static int unitsem_cnt[MAX_TOTAL_SCSI_DEVICES]; + +static int play_end_pos[MAX_TOTAL_SCSI_DEVICES]; +static uae_u8 play_qcode[MAX_TOTAL_SCSI_DEVICES][SUBQ_SIZE]; + +static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256]; +static int imagechangetime[MAX_TOTAL_SCSI_DEVICES]; +static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES]; +static bool wasopen[MAX_TOTAL_SCSI_DEVICES]; + +/* convert minutes, seconds and frames -> logical sector number */ +int msf2lsn (int msf) +{ + int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)); + sector -= 150; + return sector; +} + +/* convert logical sector number -> minutes, seconds and frames */ +int lsn2msf (int sectors) +{ + int msf; + sectors += 150; + msf = (sectors / (75 * 60)) << 16; + msf |= ((sectors / 75) % 60) << 8; + msf |= (sectors % 75) << 0; + return msf; +} + +uae_u8 frombcd (uae_u8 v) +{ + return (v >> 4) * 10 + (v & 15); +} +uae_u8 tobcd (uae_u8 v) +{ + return ((v / 10) << 4) | (v % 10); +} +int fromlongbcd (uae_u8 *p) +{ + return (frombcd (p[0]) << 16) | (frombcd (p[1]) << 8) | (frombcd (p[2]) << 0); +} +void tolongbcd (uae_u8 *p, int v) +{ + p[0] = tobcd ((v >> 16) & 0xff); + p[1] = tobcd ((v >> 8) & 0xff); + p[2] = tobcd ((v >> 0) & 0xff); +} + +static struct cd_toc *gettoc (struct cd_toc_head *th, int block) +{ + for (int i = th->first_track_offset; i < th->last_track_offset; i++) { + struct cd_toc *t = &th->toc[i]; + if (block < t->paddress) { + if (i == th->first_track_offset) + return t; + else + return t - 1; + } + } + return &th->toc[th->last_track_offset]; +} + +int isaudiotrack (struct cd_toc_head *th, int block) +{ + struct cd_toc *t = gettoc (th, block); + if (!t) + return 0; + return (t->control & 0x0c) != 4; +} +int isdatatrack (struct cd_toc_head *th, int block) +{ + return !isaudiotrack (th, block); +} + +static int cdscsidevicetype[MAX_TOTAL_SCSI_DEVICES]; + +extern struct device_functions devicefunc_cdimage; + +static struct device_functions *devicetable[] = { + NULL, + &devicefunc_cdimage, + NULL +}; +static int driver_installed[6]; + +static void install_driver (int flags) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + scsiemu[i] = false; + device_func[i] = NULL; + } + if (flags > 0) { + device_func[0] = devicetable[flags]; + scsiemu[0] = true; + } else { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + scsiemu[i] = false; + device_func[i] = NULL; + switch (cdscsidevicetype[i]) + { + case SCSI_UNIT_IMAGE: + device_func[i] = devicetable[SCSI_UNIT_IMAGE]; + scsiemu[i] = true; + break; + } + } + } + + for (int j = 1; devicetable[j]; j++) { + if (!driver_installed[j]) { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (device_func[i] == devicetable[j]) { + int ok = device_func[i]->openbus (0); + driver_installed[j] = 1; + write_log (_T("%s driver installed, ok=%d\n"), device_func[i]->name, ok); + break; + } + } + } + } + +} + +void blkdev_default_prefs (struct uae_prefs *p) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + p->cdslots[i].name[0] = 0; + p->cdslots[i].inuse = false; + p->cdslots[i].type = SCSI_UNIT_DEFAULT; + cdscsidevicetype[i] = SCSI_UNIT_DEFAULT; + } +} + +void blkdev_fix_prefs (struct uae_prefs *p) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + cdscsidevicetype[i] = p->cdslots[i].type; + if (p->cdslots[i].inuse == false && p->cdslots[i].name[0] && p->cdslots[i].type != SCSI_UNIT_DISABLED) + p->cdslots[i].inuse = true; + } + + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (cdscsidevicetype[i] != SCSI_UNIT_DEFAULT) + continue; + if (p->cdslots[i].inuse || p->cdslots[i].name[0]) { + cdscsidevicetype[i] = SCSI_UNIT_IMAGE; + } + } + +} + +static bool getsem (int unitnum, bool dowait) +{ + if (unitsem[unitnum] == NULL) + uae_sem_init (&unitsem[unitnum], 0, 1); + bool gotit = false; + if (dowait) { + uae_sem_wait (&unitsem[unitnum]); + gotit = true; + } else { + gotit = uae_sem_trywait (&unitsem[unitnum]) == 0; + } + if (gotit) + unitsem_cnt[unitnum]++; + if (unitsem_cnt[unitnum] > 1) + write_log (_T("CD: unitsem%d acquire mismatch! cnt=%d\n"), unitnum, unitsem_cnt[unitnum]); + return gotit; +} +static bool getsem (int unitnum) +{ + return getsem (unitnum, false); +} +static void freesem (int unitnum) +{ + unitsem_cnt[unitnum]--; + if (unitsem_cnt[unitnum] < 0) + write_log (_T("CD: unitsem%d release mismatch! cnt=%d\n"), unitnum, unitsem_cnt[unitnum]); + uae_sem_post (&unitsem[unitnum]); +} +static void sys_command_close_internal (int unitnum) +{ + getsem (unitnum, true); + waspaused[unitnum] = 0; + if (openlist[unitnum] <= 0) + write_log (_T("BUG unit %d close: opencnt=%d!\n"), unitnum, openlist[unitnum]); + if (device_func[unitnum]) { + device_func[unitnum]->closedev (unitnum); + if (openlist[unitnum] > 0) + openlist[unitnum]--; + } + freesem (unitnum); + if (openlist[unitnum] == 0) { + uae_sem_destroy (&unitsem[unitnum]); + unitsem[unitnum] = NULL; + } +} + +static int sys_command_open_internal (int unitnum, const TCHAR *ident, cd_standard_unit csu) +{ + int ret = 0; + if (unitsem[unitnum] == NULL) + uae_sem_init (&unitsem[unitnum], 0, 1); + getsem (unitnum, true); + if (openlist[unitnum]) + write_log (_T("BUG unit %d open: opencnt=%d!\n"), unitnum, openlist[unitnum]); + if (device_func[unitnum]) { + ret = device_func[unitnum]->opendev (unitnum, ident, csu != CD_STANDARD_UNIT_DEFAULT); + if (ret) + openlist[unitnum]++; + } + freesem (unitnum); + return ret; +} + +static int getunitinfo (int unitnum, int drive, cd_standard_unit csu, int *isaudio) +{ + struct device_info di; + if (sys_command_info (unitnum, &di, 0)) { + write_log (_T("Scanning drive %s: "), di.label); + if (di.media_inserted) { + if (isaudiotrack (&di.toc, 0)) { + if (*isaudio == 0) + *isaudio = drive; + write_log (_T("CDA")); + } + uae_u8 buffer[2048]; + if (sys_command_cd_read (unitnum, buffer, 16, 1)) { + if (!memcmp (buffer + 8, "CDTV", 4) || !memcmp (buffer + 8, "CD32", 4) || !memcmp (buffer + 8, "COMM", 4)) { + uae_u32 crc; + write_log (_T("CD32 or CDTV")); + if (sys_command_cd_read (unitnum, buffer, 21, 1)) { + crc = get_crc32 (buffer, sizeof buffer); + if (crc == 0xe56c340f) { + write_log (_T(" [CD32.TM]")); + if (csu == CD_STANDARD_UNIT_CD32) { + write_log (_T("\n")); + return 1; + } + } + } + if (csu == CD_STANDARD_UNIT_CDTV || csu == CD_STANDARD_UNIT_CD32) { + write_log (_T("\n")); + return 1; + } + } + } + } else { + write_log (_T("no media")); + } + } + write_log (_T("\n")); + return 0; +} + +static int get_standard_cd_unit2 (cd_standard_unit csu) +{ + int unitnum = 0; + int isaudio = 0; + if (currprefs.cdslots[unitnum].name[0] || currprefs.cdslots[unitnum].inuse) { + if (currprefs.cdslots[unitnum].name[0]) { + device_func_init (SCSI_UNIT_IMAGE); + if (!sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name, csu)) + goto fallback; + } else { + goto fallback; + } + return unitnum; + } + +fallback: + device_func_init (SCSI_UNIT_IMAGE); + if (!sys_command_open_internal (unitnum, _T(""), csu)) { + write_log (_T("image mounter failed to open as empty!?\n")); + return -1; + } + return unitnum; +} + +int get_standard_cd_unit (cd_standard_unit csu) +{ + int unitnum = get_standard_cd_unit2 (csu); + if (unitnum < 0) + return -1; + delayed[unitnum] = 0; + if (currprefs.cdslots[unitnum].delayed) { + delayed[unitnum] = PRE_INSERT_DELAY; + } + return unitnum; +} + +void close_standard_cd_unit (int unitnum) +{ + sys_command_close (unitnum); +} + +int sys_command_isopen (int unitnum) +{ + return openlist[unitnum]; +} + +int sys_command_open (int unitnum) +{ + if (openlist[unitnum]) { + openlist[unitnum]++; + return -1; + } + waspaused[unitnum] = 0; + int v = sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT); + if (!v) + return 0; + return v; +} + +void sys_command_close (int unitnum) +{ + if (openlist[unitnum] > 1) { + openlist[unitnum]--; + return; + } + sys_command_close_internal (unitnum); +} + +void blkdev_cd_change (int unitnum, const TCHAR *name) +{ + struct device_info di; + sys_command_info (unitnum, &di, 1); +} + +void device_func_reset (void) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + wasopen[i] = false; + waspaused[i] = false; + imagechangetime[i] = 0; + cdimagefileinuse[i] = false; + newimagefiles[i][0] = 0; + } +} + +int device_func_init (int flags) +{ + blkdev_fix_prefs (&currprefs); + install_driver (flags); + return 1; +} + +void blkdev_entergui (void) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + waspaused[i] = 0; + struct device_info di; + if (sys_command_info (i, &di, 1)) { + if (sys_command_cd_pause (i, 1) == 0) + waspaused[i] = 1; + } + } +} +void blkdev_exitgui (void) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (waspaused[i]) { + struct device_info di; + if (sys_command_info (i, &di, 1)) { + sys_command_cd_pause (i, 0); + } + } + waspaused[i] = 0; + } +} + +static void check_changes (int unitnum) +{ + bool changed = false; + bool gotsem = false; + + if (device_func[unitnum] == NULL) + return; + + if (delayed[unitnum]) { + delayed[unitnum]--; + if (delayed[unitnum] == 0) + write_log (_T("CD: startup delayed insert '%s'\n"), currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : _T("")); + return; + } + + if(currprefs.sound_volume_cd != changed_prefs.sound_volume_cd) + currprefs.sound_volume_cd = changed_prefs.sound_volume_cd; + if (_tcscmp (changed_prefs.cdslots[unitnum].name, currprefs.cdslots[unitnum].name) != 0) + changed = true; + if (!changed && changed_prefs.cdslots[unitnum].name[0] == 0 && changed_prefs.cdslots[unitnum].inuse != currprefs.cdslots[unitnum].inuse) + changed = true; + + if (changed) { + if (unitsem[unitnum]) + gotsem = getsem (unitnum, true); + cdimagefileinuse[unitnum] = changed_prefs.cdslots[unitnum].inuse; + _tcscpy (newimagefiles[unitnum], changed_prefs.cdslots[unitnum].name); + changed_prefs.cdslots[unitnum].name[0] = currprefs.cdslots[unitnum].name[0] = 0; + currprefs.cdslots[unitnum].inuse = changed_prefs.cdslots[unitnum].inuse; + int pollmode = 0; + imagechangetime[unitnum] = 3 * 50; + struct device_info di; + device_func[unitnum]->info (unitnum, &di, 0); + wasopen[unitnum] = di.open; + if (wasopen[unitnum]) { + device_func[unitnum]->closedev (unitnum); + } + write_log (_T("CD: eject (%s) open=%d\n"), pollmode ? _T("slow") : _T("fast"), wasopen[unitnum] ? 1 : 0); + if (gotsem) { + freesem (unitnum); + gotsem = false; + } + } + if (imagechangetime[unitnum] == 0) + return; + imagechangetime[unitnum]--; + if (imagechangetime[unitnum] > 0) + return; + if (unitsem[unitnum]) + gotsem = getsem (unitnum, true); + _tcscpy (currprefs.cdslots[unitnum].name, newimagefiles[unitnum]); + _tcscpy (changed_prefs.cdslots[unitnum].name, newimagefiles[unitnum]); + currprefs.cdslots[unitnum].inuse = changed_prefs.cdslots[unitnum].inuse = cdimagefileinuse[unitnum]; + newimagefiles[unitnum][0] = 0; + write_log (_T("CD: delayed insert '%s' (open=%d,unit=%d)\n"), currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : _T(""), wasopen[unitnum] ? 1 : 0, unitnum); + device_func_init (0); + if (wasopen[unitnum]) { + if (!device_func[unitnum]->opendev (unitnum, currprefs.cdslots[unitnum].name, 0)) { + write_log (_T("-> device open failed\n")); + wasopen[unitnum] = 0; + } else { + write_log (_T("-> device reopened\n")); + } + } + if (gotsem) { + freesem (unitnum); + gotsem = false; + } +} + +void blkdev_vsync (void) +{ + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) + check_changes (i); +} + +static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen) +{ + uae_u8 *p = device_func[unitnum]->exec_out (unitnum, cmd, cmdlen); + return p != NULL; +} +static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen, uae_u8 *out, int outsize) +{ + uae_u8 *p = device_func[unitnum]->exec_in (unitnum, cmd, cmdlen, &outsize); + if (p) + memcpy (out, p, outsize); + return p != NULL; +} + +static int failunit (int unitnum) +{ + if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES) + return 1; + if (device_func[unitnum] == NULL) + return 1; + return 0; +} + +static int audiostatus (int unitnum) +{ + if (!getsem (unitnum)) + return 0; + uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0}; + uae_u8 *p = device_func[unitnum]->exec_in (unitnum, cmd, sizeof (cmd), 0); + freesem (unitnum); + if (!p) + return 0; + return p[1]; +} + +/* pause/unpause CD audio */ +int sys_command_cd_pause (int unitnum, int paused) +{ + if (failunit (unitnum)) + return -1; + if (!getsem (unitnum)) + return 0; + int v; + if (device_func[unitnum]->pause == NULL) { + int as = audiostatus (unitnum); + uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,paused?0:1,0}; + do_scsi (unitnum, cmd, sizeof cmd); + v = as == AUDIO_STATUS_PAUSED; + } else { + v = device_func[unitnum]->pause (unitnum, paused); + } + freesem (unitnum); + return v; +} + +/* stop CD audio */ +void sys_command_cd_stop (int unitnum) +{ + if (failunit (unitnum)) + return; + if (!getsem (unitnum)) + return; + if (device_func[unitnum]->stop == NULL) { + int as = audiostatus (unitnum); + uae_u8 cmd[6] = {0x4e,0,0,0,0,0}; + do_scsi (unitnum, cmd, sizeof cmd); + } else { + device_func[unitnum]->stop (unitnum); + } + freesem (unitnum); +} + +/* play CD audio */ +int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + play_end_pos[unitnum] = endlsn; + if (device_func[unitnum]->play == NULL) { + uae_u8 cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + int startmsf = lsn2msf (startlsn); + int endmsf = lsn2msf (endlsn); + cmd[0] = 0x47; + cmd[3] = (uae_u8)(startmsf >> 16); + cmd[4] = (uae_u8)(startmsf >> 8); + cmd[5] = (uae_u8)(startmsf >> 0); + cmd[6] = (uae_u8)(endmsf >> 16); + cmd[7] = (uae_u8)(endmsf >> 8); + cmd[8] = (uae_u8)(endmsf >> 0); + v = do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1; + } else { + v = device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL, NULL); + } + freesem (unitnum); + return v; +} + +/* play CD audio with subchannels */ +int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->play == NULL) + v = sys_command_cd_play (unitnum, startlsn, endlsn, scan); + else + v = device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc); + freesem (unitnum); + return v; +} + +/* set CD audio volume */ +uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->volume == NULL) + v = -1; + else + v = device_func[unitnum]->volume (unitnum, volume_left, volume_right); + freesem (unitnum); + return v; +} + +/* read qcode */ +int sys_command_cd_qcode (int unitnum, uae_u8 *buf) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->qcode == NULL) { + uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(SUBQ_SIZE>>8),(uae_u8)(SUBQ_SIZE&0xff),0}; + v = do_scsi (unitnum, cmd, sizeof cmd, buf, SUBQ_SIZE); + } else { + v = device_func[unitnum]->qcode (unitnum, buf, -1); + } + freesem (unitnum); + return v; +}; + +/* read table of contents */ +int sys_command_cd_toc (int unitnum, struct cd_toc_head *toc) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->toc == NULL) { + uae_u8 buf[4 + 8 * 103]; + int size = sizeof buf; + uae_u8 cmd [10] = { 0x43,0,2,0,0,0,0,(uae_u8)(size>>8),(uae_u8)(size&0xff),0}; + if (do_scsi (unitnum, cmd, sizeof cmd, buf, size)) { + // toc parse to do + v = 0; + } + v = 0; + } else { + v = device_func[unitnum]->toc (unitnum, toc); + } + freesem (unitnum); + return v; +} + +/* read one cd sector */ +int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->read == NULL) { + uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); + } else { + v = device_func[unitnum]->read (unitnum, data, block, size); + } + freesem (unitnum); + return v; +} +int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize) +{ + int v; + if (failunit (unitnum)) + return -1; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->rawread == NULL) { + uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + } else { + v = device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, 0xffffffff); + } + freesem (unitnum); + return v; +} +int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize, uae_u8 sectortype, uae_u8 scsicmd9, uae_u8 subs) +{ + int v; + if (failunit (unitnum)) + return -1; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->rawread == NULL) { + uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + } else { + v = device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, (sectortype << 16) | (scsicmd9 << 8) | subs); + } + freesem (unitnum); + return v; +} + +/* read block */ +int sys_command_read (int unitnum, uae_u8 *data, int block, int size) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->read == NULL) { + uae_u8 cmd[12] = { 0xa8, 0, 0, 0, 0, 0, size >> 24, size >> 16, size >> 8, size >> 0, 0, 0 }; + cmd[2] = (uae_u8)(block >> 24); + cmd[3] = (uae_u8)(block >> 16); + cmd[4] = (uae_u8)(block >> 8); + cmd[5] = (uae_u8)(block >> 0); + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); + } else { + v = device_func[unitnum]->read (unitnum, data, block, size); + } + freesem (unitnum); + return v; +} + +/* write block */ +int sys_command_write (int unitnum, uae_u8 *data, int offset, int size) +{ + int v; + if (failunit (unitnum)) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum]->write == NULL) { + v = 0; + } else { + v = device_func[unitnum]->write (unitnum, data, offset, size); + } + freesem (unitnum); + return v; +} + +int sys_command_ismedia (int unitnum, int quick) +{ + int v; + if (failunit (unitnum)) + return -1; + if (delayed[unitnum]) + return 0; + if (!getsem (unitnum)) + return 0; + if (device_func[unitnum] == NULL) { + uae_u8 cmd[6] = { 0, 0, 0, 0, 0, 0 }; + v = do_scsi (unitnum, cmd, sizeof cmd); + } else { + v = device_func[unitnum]->ismedia (unitnum, quick); + } + freesem (unitnum); + return v; +} + +struct device_info *sys_command_info (int unitnum, struct device_info *di, int quick) +{ + if (failunit (unitnum)) + return NULL; + if (!getsem (unitnum)) + return 0; + struct device_info *di2 = device_func[unitnum]->info (unitnum, di, quick); + if (di2 && delayed[unitnum]) + di2->media_inserted = 0; + freesem (unitnum); + return di2; +} + +#define MODE_SELECT_6 0x15 +#define MODE_SENSE_6 0x1a +#define MODE_SELECT_10 0x55 +#define MODE_SENSE_10 0x5a + +static void scsi_atapi_fixup_inquiry (struct amigascsi *as) +{ + uae_u8 *scsi_data = as->data; + uae_u32 scsi_len = as->len; + uae_u8 *scsi_cmd = as->cmd; + uae_u8 cmd; + + cmd = scsi_cmd[0]; + /* CDROM INQUIRY: most Amiga programs expect ANSI version == 2 + * (ATAPI normally responds with zero) + */ + if (cmd == 0x12 && scsi_len > 2 && scsi_data) { + uae_u8 per = scsi_data[0]; + uae_u8 b = scsi_data[2]; + /* CDROM and ANSI version == 0 ? */ + if ((per & 31) == 5 && (b & 7) == 0) { + b |= 2; + scsi_data[2] = b; + } + } +} + +void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen) +{ + int i; + for (i = 0; i < cdblen; i++) { + write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), cdb[i]); + } + write_log (_T("\n")); + if (data) { + write_log (_T("DATAOUT: %d\n"), datalen); + for (i = 0; i < datalen && i < 100; i++) + write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), data[i]); + if (datalen > 0) + write_log (_T("\n")); + } +} + +void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen) +{ + int i; + write_log (_T("DATAIN: %d\n"), datalen); + for (i = 0; i < datalen && i < 100 && data; i++) + write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), data[i]); + if (data && datalen > 0) + write_log (_T("\n")); + if (senselen > 0) { + write_log (_T("SENSE: %d,"), senselen); + for (i = 0; i < senselen && i < 32; i++) { + write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), sense[i]); + } + write_log (_T("\n")); + } +} + +static bool nodisk (struct device_info *di) +{ + return di->media_inserted == 0; +} +static uae_u64 cmd_readx (int unitnum, uae_u8 *dataptr, int offset, int len) +{ + if (!getsem (unitnum)) + return 0; + int v = device_func[unitnum]->read (unitnum, dataptr, offset, len); + freesem (unitnum); + if (v) + return len; + return 0; +} + +static void wl (uae_u8 *p, int v) +{ + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v; +} +static void ww (uae_u8 *p, int v) +{ + p[0] = v >> 8; + p[1] = v; +} +static int rl (uae_u8 *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); +} +static int rw (uae_u8 *p) +{ + return (p[0] << 8) | (p[1]); +} + +static void stopplay (int unitnum) +{ + sys_command_cd_stop (unitnum); +} + +static int addtocentry (uae_u8 **dstp, int *len, int point, int newpoint, int msf, uae_u8 *head, struct cd_toc_head *th) +{ + uae_u8 *dst = *dstp; + + for (int i = 0; i < th->points; i++) { + struct cd_toc *t = &th->toc[i]; + if (t->point == point) { + if (*len < 8) + return 0; + int addr = t->paddress; + if (msf) + addr = lsn2msf (addr); + dst[0] = 0; + dst[1] = (t->adr << 4) | t->control; + dst[2] = newpoint >= 0 ? newpoint : point; + dst[3] = 0; + dst[4] = addr >> 24; + dst[5] = addr >> 16; + dst[6] = addr >> 8; + dst[7] = addr >> 0; + + if (point >= 1 && point <= 99) { + if (head[2] == 0) + head[2] = point; + head[3] = point; + } + + *len -= 8; + *dstp = dst + 8; + return 1; + } + } + return -1; +} + +static int scsiemudrv (int unitnum, uae_u8 *cmd) +{ + if (failunit (unitnum)) + return -1; + if (!getsem (unitnum)) + return 0; + int v = 0; + if (device_func[unitnum]->scsiemu) + v = device_func[unitnum]->scsiemu (unitnum, cmd); + freesem (unitnum); + return v; +} + +static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_info *di) +{ + int msf = cmd[0] == 0xb9; + int start = msf ? msf2lsn (rl (cmd + 2) & 0x00ffffff) : rl (cmd + 2); + int len = rl (cmd + 5) & 0x00ffffff; + if (msf) { + int end = msf2lsn (len); + len = end - start; + if (len < 0) + return -1; + } + int subs = cmd[10] & 7; + if (len == 0) + return 0; + return sys_command_cd_rawread (unitnum, data, start, len, 0, (cmd[1] >> 2) & 7, cmd[9], subs); +} + +static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, + uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len) +{ + uae_u64 len, offset; + int lr = 0, ls = 0; + int scsi_len = -1; + int status = 0; + struct device_info di; + uae_u8 cmd = cmdbuf[0]; + + *reply_len = *sense_len = 0; + memset (r, 0, 256); + memset (s, 0, 256); + + sys_command_info (unitnum, &di, 1); + + if (cmdbuf[0] == 0) { /* TEST UNIT READY */ + if (nodisk (&di)) + goto nodisk; + scsi_len = 0; + goto end; + } + if (log_scsiemu) + write_log (_T("SCSIEMU %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%08X LEN=%d\n"), unitnum, + cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], + cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], + scsi_cmd_len, scsi_data, *data_len); + switch (cmdbuf[0]) + { + case 0x12: /* INQUIRY */ + { + if ((cmdbuf[1] & 1) || cmdbuf[2] != 0) + goto err; + len = cmdbuf[4]; + if (cmdbuf[1] >> 5) + goto err; + r[0] = 5; // CDROM + r[1] |= 0x80; // removable + r[2] = 2; /* supports SCSI-2 */ + r[3] = 2; /* response data format */ + r[4] = 32; /* additional length */ + r[7] = 0x20; /* 16 bit bus */ + scsi_len = lr = len < 36 ? (uae_u32)len : 36; + r[2] = 2; + r[3] = 2; + memcpy (r + 8, di.vendorid, strlen (di.vendorid)); + memcpy (r + 16, di.productid, strlen (di.productid)); + memcpy (r + 32, di.revision, strlen (di.revision)); + for (int i = 8; i < 36; i++) { + if (r[i] == 0) + r[i] = 32; + } + } + break; + case 0xbe: // READ CD + case 0xb9: // READ CD MSF + if (nodisk (&di)) + goto nodisk; + scsi_len = scsi_read_cd (unitnum, cmdbuf, scsi_data, &di); + if (scsi_len == -2) + goto notdatatrack; + if (scsi_len == -1) + goto errreq; + break; + case 0x55: // MODE SELECT(10) + case 0x15: // MODE SELECT(6) + { + uae_u8 *p; + p = scsi_data + 4; + if (cmdbuf[0] == 0x55) + p += 4; + int pcode = p[0] & 0x3f; + if (pcode == 14) { // CD audio control + uae_u16 vol_left = (p[9] << 7) | (p[9] >> 1); + uae_u16 vol_right = (p[11] << 7) | (p[11] >> 1); + sys_command_cd_volume (unitnum, vol_left, vol_right); + scsi_len = 0; + } else { + goto errreq; + } + } + break; + case 0x5a: // MODE SENSE(10) + case 0x1a: /* MODE SENSE(6) */ + { + uae_u8 *p; + int pc = cmdbuf[2] >> 6; + int pcode = cmdbuf[2] & 0x3f; + int dbd = cmdbuf[1] & 8; + if (cmdbuf[0] == 0x5a) + dbd = 1; + if (log_scsiemu) + write_log (_T("MODE SENSE PC=%d CODE=%d DBD=%d\n"), pc, pcode, dbd); + p = r; + if (cmdbuf[0] == 0x5a) { + p[0] = 8 - 1; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + p += 8; + } else { + p[0] = 4 - 1; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p += 4; + } + if (!dbd) { + if (nodisk (&di)) + goto nodisk; + uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder; + p[-1] = 8; + wl(p + 0, blocks); + wl(p + 4, di.bytespersector); + p += 8; + } + if (pcode == 0) { + p[0] = 0; + p[1] = 0; + p[2] = 0x20; + p[3] = 0; + r[0] += 4; + } else if (pcode == 3) { + if (nodisk (&di)) + goto nodisk; + p[0] = 3; + p[1] = 24; + p[3] = 1; + p[10] = di.trackspercylinder >> 8; + p[11] = di.trackspercylinder; + p[12] = di.bytespersector >> 8; + p[13] = di.bytespersector; + p[15] = 1; // interleave + p[20] = 0x80; + r[0] += p[1]; + } else if (pcode == 4) { + if (nodisk (&di)) + goto nodisk; + p[0] = 4; + wl(p + 1, di.cylinders); + p[1] = 24; + p[5] = 1; + wl(p + 13, di.cylinders); + ww(p + 20, 0); + r[0] += p[1]; + } else if (pcode == 14) { // CD audio control + uae_u32 vol = sys_command_cd_volume (unitnum, 0xffff, 0xffff); + p[0] = 0x0e; + p[1] = 0x0e; + p[2] = 1; + p[3] = 4; + p[6] = 0; + p[7] = 75; + p[8] = 1; + p[9] = pc == 0 ? (vol >> 7) & 0xff : 0xff; + p[10] = 2; + p[11] = pc == 0 ? (vol >> (16 + 7)) & 0xff : 0xff; + r[0] += p[1]; + } else { + goto err; + } + r[0] += r[3]; + scsi_len = lr = r[0] + 1; + } + break; + case 0x1d: /* SEND DIAGNOSTICS */ + scsi_len = 0; + break; + case 0x25: /* READ_CAPACITY */ + { + int pmi = cmdbuf[8] & 1; + uae_u32 lba = (cmdbuf[2] << 24) | (cmdbuf[3] << 16) | (cmdbuf[4] << 8) | cmdbuf[5]; + int cyl, cylsec, head, tracksec; + if (nodisk (&di)) + goto nodisk; + uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder; + cyl = di.cylinders; + head = 1; + cylsec = tracksec = di.trackspercylinder; + if (pmi == 0 && lba != 0) + goto errreq; + if (pmi) { + lba += tracksec * head; + lba /= tracksec * head; + lba *= tracksec * head; + if (lba > blocks) + lba = blocks; + blocks = lba; + } + wl (r, blocks); + wl (r + 4, di.bytespersector); + scsi_len = lr = 8; + } + break; + case 0x08: /* READ (6) */ + { + if (nodisk (&di)) + goto nodisk; + stopplay (unitnum); + offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + struct cd_toc *t = gettoc (&di.toc, offset); + if ((t->control & 0x0c) == 0x04) { + len = cmdbuf[4]; + if (!len) + len = 256; + scsi_len = (uae_u32)cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;; + } else { + goto notdatatrack; + } + } + break; + case 0x0a: /* WRITE (6) */ + goto readprot; + case 0x28: /* READ (10) */ + { + if (nodisk (&di)) + goto nodisk; + stopplay (unitnum); + offset = rl (cmdbuf + 2); + struct cd_toc *t = gettoc (&di.toc, offset); + if ((t->control & 0x0c) == 0x04) { + len = rl (cmdbuf + 7 - 2) & 0xffff; + scsi_len = cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector; + } else { + goto notdatatrack; + } + } + break; + case 0x2a: /* WRITE (10) */ + goto readprot; + case 0xa8: /* READ (12) */ + { + if (nodisk (&di)) + goto nodisk; + stopplay (unitnum); + offset = rl (cmdbuf + 2); + struct cd_toc *t = gettoc (&di.toc, offset); + if ((t->control & 0x0c) == 0x04) { + len = rl (cmdbuf + 6); + scsi_len = (uae_u32)cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;; + } else { + goto notdatatrack; + } + } + break; + case 0xaa: /* WRITE (12) */ + goto readprot; + case 0x43: // READ TOC + { + if (nodisk (&di)) + goto nodisk; + uae_u8 *p = scsi_data; + int strack = cmdbuf[6]; + int msf = cmdbuf[1] & 2; + int format = cmdbuf[2] & 7; + if (format >= 3) + goto errreq; + int maxlen = (cmdbuf[7] << 8) | cmdbuf[8]; + struct cd_toc_head ttoc; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + if (maxlen < 4) + goto errreq; + if (format == 1) { + p[0] = 0; + p[1] = 8; + p[2] = 1; + p[3] = 1; + p[4] = 0; + p[5] = (toc->toc[0].adr << 4) | toc->toc[0].control; + p[6] = toc->first_track; + p[7] = 0; + if (msf) + wl (p + 8, lsn2msf (toc->toc[0].address)); + else + wl (p + 8 , toc->toc[0].address); + scsi_len = 12; + } else if (format == 2 || format == 0) { + if (format == 2 && !msf) + goto errreq; + if (strack == 0) + strack = toc->first_track; + if (format == 0 && strack >= 100 && strack != 0xaa) + goto errreq; + uae_u8 *p2 = p + 4; + p[2] = 0; + p[3] = 0; + maxlen -= 4; + if (format == 2) { + if (!addtocentry (&p2, &maxlen, 0xa0, -1, msf, p, toc)) + goto errreq; + if (!addtocentry (&p2, &maxlen, 0xa1, -1, msf, p, toc)) + goto errreq; + if (!addtocentry (&p2, &maxlen, 0xa2, -1, msf, p, toc)) + goto errreq; + } + while (strack < 100) { + if (!addtocentry (&p2, &maxlen, strack, -1, msf, p, toc)) + goto errreq; + strack++; + } + if (!addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc)) + goto errreq; + int tlen = p2 - (p + 4); + p[0] = tlen >> 8; + p[1] = tlen >> 0; + scsi_len = tlen + 4; + } + } + break; + case 0x42: // READ SUB-CHANNEL + { + int msf = cmdbuf[1] & 2; + int subq = cmdbuf[2] & 0x40; + int format = cmdbuf[3]; + int track = cmdbuf[6]; + int len = rw (cmdbuf + 7); + uae_u8 buf[SUBQ_SIZE] = { 0 }; + + if (nodisk (&di)) + goto nodisk; + sys_command_cd_qcode (unitnum, buf); + if (len < 4) + goto errreq; + scsi_len = 4; + scsi_data[0] = 0; + scsi_data[1] = buf[1]; + if (subq && format == 1) { + if (len < 4 + 12) + goto errreq; + scsi_data[2] = 0; + scsi_data[3] = 12; + scsi_len += 12; + scsi_data[4] = 1; + scsi_data[5] = (buf[4 + 0] << 4) | (buf[4 + 0] >> 4); + scsi_data[6] = frombcd (buf[4 + 1]); // track + scsi_data[7] = frombcd (buf[4 + 2]); // index + int reladdr = fromlongbcd (&buf[4 + 3]); + int absaddr = fromlongbcd (&buf[4 + 7]); + if (!msf) { + reladdr = msf2lsn (reladdr); + absaddr = msf2lsn (absaddr); + } + wl (scsi_data + 8, absaddr); + wl (scsi_data + 12, reladdr); + } else { + scsi_data[2] = 0; + scsi_data[3] = 0; + } + } + break; + case 0x1b: // START/STOP + sys_command_cd_stop (unitnum); + scsiemudrv (unitnum, cmdbuf); + scsi_len = 0; + break; + case 0x1e: // PREVENT/ALLOW MEDIA REMOVAL + // do nothing + scsi_len = 0; + break; + case 0x4e: // STOP PLAY/SCAN + if (nodisk (&di)) + goto nodisk; + sys_command_cd_stop (unitnum); + scsi_len = 0; + break; + case 0xba: // SCAN + { + if (nodisk (&di)) + goto nodisk; + struct cd_toc_head ttoc; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + int scan = (cmdbuf[1] & 0x10) ? -1 : 1; + int start = rl (cmdbuf + 1) & 0x00ffffff; + int end = scan > 0 ? toc->lastaddress : toc->toc[toc->first_track_offset].paddress; + int type = cmdbuf[9] >> 6; + if (type == 1) + start = lsn2msf (start); + if (type == 3) + goto errreq; + if (type == 2) { + if (toc->first_track_offset + start >= toc->last_track_offset) + goto errreq; + start = toc->toc[toc->first_track_offset + start].paddress; + } + sys_command_cd_pause (unitnum, 0); + sys_command_cd_play (unitnum, start, end, scan); + scsi_len = 0; + } + break; + case 0x48: // PLAY AUDIO TRACK/INDEX + { + if (nodisk (&di)) + goto nodisk; + int strack = cmdbuf[4]; + int etrack = cmdbuf[7]; + struct cd_toc_head ttoc; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + if (strack < toc->first_track || strack > toc->last_track || + etrack < toc->first_track || etrack > toc->last_track || + strack > etrack) + goto errreq; + int start = toc->toc[toc->first_track_offset + strack - 1].paddress; + int end = etrack == toc->last_track ? toc->lastaddress : toc->toc[toc->first_track_offset + etrack - 1 + 1].paddress; + sys_command_cd_pause (unitnum, 0); + if (!sys_command_cd_play (unitnum, start, end, 0)) + goto notdatatrack; + scsi_len = 0; + } + break; + case 0x49: // PLAY AUDIO TRACK RELATIVE (10) + case 0xa9: // PLAY AUDIO TRACK RELATIVE (12) + { + if (nodisk (&di)) + goto nodisk; + int len = cmd == 0xa9 ? rl (cmdbuf + 6) : rw (cmdbuf + 7); + int track = cmd == 0xa9 ? cmdbuf[10] : cmdbuf[6]; + if (track < di.toc.first_track || track > di.toc.last_track) + goto errreq; + int start = di.toc.toc[di.toc.first_track_offset + track - 1].paddress; + int rel = rl (cmdbuf + 2); + start += rel; + int end = start + len; + if (end > di.toc.lastaddress) + end = di.toc.lastaddress; + if (len > 0) { + sys_command_cd_pause (unitnum, 0); + if (!sys_command_cd_play (unitnum, start, start + len, 0)) + goto notdatatrack; + } + scsi_len = 0; + } + break; + case 0x47: // PLAY AUDIO MSF + { + if (nodisk (&di)) + goto nodisk; + int start = rl (cmdbuf + 2) & 0x00ffffff; + if (start == 0x00ffffff) { + uae_u8 buf[SUBQ_SIZE] = { 0 }; + sys_command_cd_qcode (unitnum, buf); + start = fromlongbcd (buf + 4 + 7); + } + int end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff); + if (end > di.toc.lastaddress) + end = di.toc.lastaddress; + start = msf2lsn (start); + if (start > end) + goto errreq; + if (start < end) + sys_command_cd_pause (unitnum, 0); + if (!sys_command_cd_play (unitnum, start, end, 0)) + goto notdatatrack; + scsi_len = 0; + } + break; + case 0x45: // PLAY AUDIO (10) + case 0xa5: // PLAY AUDIO (12) + { + if (nodisk (&di)) + goto nodisk; + int start = rl (cmdbuf + 2); + int len; + if (cmd = 0xa5) + len = rl (cmdbuf + 6); + else + len = rw (cmdbuf + 7); + if (len > 0) { + if (start == -1) { + uae_u8 buf[SUBQ_SIZE] = { 0 }; + sys_command_cd_qcode (unitnum, buf); + start = msf2lsn (fromlongbcd (buf + 4 + 7)); + } + int end = start + len; + if (end > di.toc.lastaddress) + end = di.toc.lastaddress; + sys_command_cd_pause (unitnum, 0); + if (!sys_command_cd_play (unitnum, start, end, 0)) + goto notdatatrack; + } + scsi_len = 0; + } + break; + case 0xbc: // PLAY CD + { + if (nodisk (&di)) + goto nodisk; + int start = -1; + int end = -1; + if (cmdbuf[1] & 2) { + start = msf2lsn (rl (cmdbuf + 2) & 0x00ffffff); + end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff); + } else { + start = rl (cmdbuf + 2); + end = start + rl (cmdbuf + 6); + } + if (end > di.toc.lastaddress) + end = di.toc.lastaddress; + if (start > end) + goto errreq; + if (start < end) { + sys_command_cd_pause (unitnum, 0); + if (!sys_command_cd_play (unitnum, start, end, 0)) + goto notdatatrack; + } + } + break; + case 0x4b: // PAUSE/RESUME + { + if (nodisk (&di)) + goto nodisk; + uae_u8 buf[SUBQ_SIZE] = { 0 }; + int resume = cmdbuf[8] & 1; + sys_command_cd_qcode (unitnum, buf); + if (buf[1] != AUDIO_STATUS_IN_PROGRESS && buf[1] != AUDIO_STATUS_PAUSED) + goto errreq; + sys_command_cd_pause (unitnum, resume ? 0 : 1); + scsi_len = 0; + } + break; +readprot: + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 7; /* DATA PROTECT */ + s[12] = 0x27; /* WRITE PROTECTED */ + ls = 12; + break; +nodisk: + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 2; /* NOT READY */ + s[12] = 0x3A; /* MEDIUM NOT PRESENT */ + ls = 12; + break; +readerr: + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 2; /* NOT READY */ + s[12] = 0x11; /* UNRECOVERED READ ERROR */ + ls = 12; + break; +notdatatrack: + status = 2; + s[0] = 0x70; + s[2] = 5; + s[12] = 0x64; /* ILLEGAL MODE FOR THIS TRACK */ + ls = 12; + break; + + default: +err: + write_log (_T("CDEMU: unsupported scsi command 0x%02X\n"), cmdbuf[0]); +errreq: + lr = -1; + status = 2; /* CHECK CONDITION */ + s[0] = 0x70; + s[2] = 5; /* ILLEGAL REQUEST */ + s[12] = 0x24; /* ILLEGAL FIELD IN CDB */ + ls = 12; + break; + } +end: + *data_len = scsi_len; + *reply_len = lr; + *sense_len = ls; + if (cmdbuf[0] && log_scsiemu) + write_log (_T("-> DATAOUT=%d ST=%d SENSELEN=%d\n"), scsi_len, status, ls); + return status; +} + +static int execscsicmd_direct (int unitnum, struct amigascsi *as) +{ + int sactual = 0; + int io_error = 0; + uae_u8 *scsi_datap, *scsi_datap_org; + uae_u32 scsi_cmd_len_orig = as->cmd_len; + uae_u8 cmd[16] = { 0 }; + uae_u8 replydata[256]; + int datalen = as->len; + int senselen = as->sense_len; + int replylen = 0; + + memcpy (cmd, as->cmd, as->cmd_len); + scsi_datap = scsi_datap_org = as->len ? as->data : 0; + if (as->sense_len > 32) + as->sense_len = 32; + + as->status = scsi_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen); + + as->cmdactual = as->status != 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */ + if (as->status) { + io_error = IOERR_BadStatus; + as->sense_len = senselen; + as->actual = 0; /* scsi_Actual */ + } else { + int i; + if (replylen > 0) { + for (i = 0; i < replylen; i++) + scsi_datap[i] = replydata[i]; + datalen = replylen; + } + for (i = 0; i < as->sense_len; i++) + as->sensedata[i] = 0; + sactual = 0; + if (datalen < 0) { + io_error = IOERR_NotSpecified; + as->actual = 0; /* scsi_Actual */ + } else { + as->len = datalen; + io_error = 0; + as->actual = as->len; /* scsi_Actual */ + } + } + as->sactual = sactual; + + return io_error; +} + +int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as) +{ + if (scsiemu[unitnum]) { + return execscsicmd_direct (unitnum, as); + } else { + if (!device_func[unitnum]->exec_direct) + return -1; + } + int ret = device_func[unitnum]->exec_direct (unitnum, as); + if (!ret && device_func[unitnum]->isatapi(unitnum)) + scsi_atapi_fixup_inquiry (as); + return ret; +} + +int sys_command_scsi_direct (int unitnum, uaecptr acmd) +{ + int ret, i; + struct amigascsi as; + uaecptr ap; + addrbank *bank; + + ap = get_long (acmd + 0); + as.len = get_long (acmd + 4); + + bank = &get_mem_bank (ap); + if (!bank || !bank->check(ap, as.len)) + return IOERR_BADADDRESS; + as.data = bank->xlateaddr (ap); + + ap = get_long (acmd + 12); + as.cmd_len = get_word (acmd + 16); + if (as.cmd_len > sizeof as.cmd) + return IOERR_BADLENGTH; + for (i = 0; i < as.cmd_len; i++) + as.cmd[i] = get_byte (ap++); + while (i < sizeof as.cmd) + as.cmd[i++] = 0; + as.flags = get_byte (acmd + 20); + as.sense_len = get_word (acmd + 26); + + ret = sys_command_scsi_direct_native (unitnum, &as); + + put_long (acmd + 8, as.actual); + put_word (acmd + 18, as.cmdactual); + put_byte (acmd + 21, as.status); + put_word (acmd + 28, as.sactual); + + ap = get_long (acmd + 22); + for (i = 0; i < as.sactual; i++) + put_byte (ap, as.sensedata[i]); + + return ret; +} + +#ifdef SAVESTATE + +uae_u8 *save_cd (int num, int *len) +{ + uae_u8 *dstbak, *dst; + + memset(play_qcode[num], 0, SUBQ_SIZE); + if (!currprefs.cdslots[num].inuse || num >= MAX_TOTAL_SCSI_DEVICES) + return NULL; + if (!currprefs.cs_cd32cd) + return NULL; + dstbak = dst = xmalloc (uae_u8, 4 + 256 + 4 + 4); + save_u32 (4 | 8); + save_path (currprefs.cdslots[num].name, SAVESTATE_PATH_CD); + save_u32 (currprefs.cdslots[num].type); + save_u32 (0); + save_u32 (0); + sys_command_cd_qcode (num, play_qcode[num]); + for (int i = 0; i < SUBQ_SIZE; i++) + save_u8 (play_qcode[num][i]); + save_u32 (play_end_pos[num]); + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_cd (int num, uae_u8 *src) +{ + uae_u32 flags; + TCHAR *s; + + if (num >= MAX_TOTAL_SCSI_DEVICES) + return NULL; + flags = restore_u32 (); + s = restore_path (SAVESTATE_PATH_CD); + int type = restore_u32 (); + restore_u32 (); + if (flags & 4) { + _tcscpy (changed_prefs.cdslots[num].name, s); + _tcscpy (currprefs.cdslots[num].name, s); + changed_prefs.cdslots[num].type = currprefs.cdslots[num].type = type; + } + if (flags & 8) { + restore_u32 (); + for (int i = 0; i < SUBQ_SIZE; i++) + play_qcode[num][i] = restore_u8 (); + play_end_pos[num] = restore_u32 (); + } + return src; +} + +#endif + diff --git a/src/blkdev_cdimage.cpp b/src/blkdev_cdimage.cpp new file mode 100644 index 00000000..cf507029 --- /dev/null +++ b/src/blkdev_cdimage.cpp @@ -0,0 +1,1590 @@ +/* +* UAE +* +* CD image file support +* +* - iso (2048/2352 block size) +* - cue/bin, cue/bin/wav, cue/bin/mp3 +* - ccd/img and ccd/img/sub +* +* Copyright 2010 Toni Wilen +* +*/ +#include "sysconfig.h" +#include "sysdeps.h" + +#include + +#include "options.h" +#include "blkdev.h" +#include "zfile.h" +#include "gui.h" +#include "fsdb.h" +#include "td-sdl/thread.h" +#include "scsidev.h" +//#include "mp3decoder.h" +#include "od-pandora/cda_play.h" +#include "memory.h" +#include "uae.h" + +#define scsi_log write_log + +#define CDDA_BUFFERS 12 + +enum audenc { AUDENC_NONE, AUDENC_PCM, AUDENC_MP3, AUDENC_FLAC }; + +struct cdtoc +{ + struct zfile *handle; + int offset; + uae_u8 *data; + struct zfile *subhandle; + int suboffset; + uae_u8 *subdata; + + int filesize; + TCHAR *fname; + int address; + uae_u8 adr, ctrl; + int track; + int size; + int skipsize; // bytes to skip after each block + audenc enctype; + int writeoffset; + int subcode; +}; + +struct cdunit { + bool enabled; + bool open; + uae_u8 buffer[2352]; + struct cdtoc toc[102]; + int tracks; + uae_u64 cdsize; + int blocksize; + + int cdda_play_state; + int cdda_play; + int cdda_paused; + int cdda_volume[2]; + int cdda_scan; + int cd_last_pos; + int cdda_start, cdda_end; + play_subchannel_callback cdda_subfunc; + play_status_callback cdda_statusfunc; + int cdda_delay, cdda_delay_frames; + + int imagechange; + TCHAR newfile[MAX_DPATH]; + uae_sem_t sub_sem; + struct device_info di; +}; + +static struct cdunit cdunits[MAX_TOTAL_SCSI_DEVICES]; +static int bus_open; + +static volatile int cdimage_unpack_thread, cdimage_unpack_active; +static smp_comm_pipe unpack_pipe; + +static struct cdunit *unitisopen (int unitnum) +{ + struct cdunit *cdu = &cdunits[unitnum]; + if (cdu->open) + return cdu; + return NULL; +} + + +static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp) +{ + int i; + int sector; + + if (*sectorp < 0) + return NULL; + sector = *sectorp; + for (i = 0; i <= cdu->tracks; i++) { + struct cdtoc *t = &cdu->toc[i]; + if (t->address > sector) { + if (i == 0) { + *sectorp = 0; + return t; + } + t--; + sector -= t->address; + *sectorp = sector; + return t; + } + } + return NULL; +} + +static void sub_to_interleaved (const uae_u8 *s, uae_u8 *d) +{ + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i & 7)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i / 8) + j * 12] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} +static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d) +{ + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i / 12)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} + +static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) +{ + int ret = 0; + uae_sem_wait (&cdu->sub_sem); + if (t->subcode) { + if (t->subhandle) { + int offset = 0; + int totalsize = SUB_CHANNEL_SIZE; + if (t->skipsize) { + totalsize += t->size; + offset = t->size; + } + zfile_fseek (t->subhandle, sector * totalsize + t->suboffset + offset, SEEK_SET); + if (zfile_fread (dst, SUB_CHANNEL_SIZE, 1, t->subhandle) > 0) + ret = t->subcode; + } else { + memcpy (dst, t->subdata + sector * SUB_CHANNEL_SIZE + t->suboffset, SUB_CHANNEL_SIZE); + ret = t->subcode; + } + } + if (!ret) { + memset (dst, 0, SUB_CHANNEL_SIZE); + // regenerate Q-subchannel + uae_u8 *s = dst + 12; + s[0] = (t->ctrl << 4) | (t->adr << 0); + s[1] = tobcd (t - &cdu->toc[0] + 1); + s[2] = tobcd (1); + int msf = lsn2msf (sector); + tolongbcd (s + 7, msf); + msf = lsn2msf (sector - t->address - 150); + tolongbcd (s + 3, msf); + ret = 2; + } + if (ret == 1) { + uae_u8 tmp[SUB_CHANNEL_SIZE]; + memcpy (tmp, dst, SUB_CHANNEL_SIZE); + sub_to_deinterleaved (tmp, dst); + ret = 2; + } + uae_sem_post (&cdu->sub_sem); + return ret; +} + +static void dosub (struct cdunit *cdu, uae_u8 *subbuf) +{ + uae_u8 subbuf2[SUB_CHANNEL_SIZE]; + + if (!cdu->cdda_subfunc) + return; + + if (!subbuf) { + memset (subbuf2, 0, sizeof subbuf2); + cdu->cdda_subfunc (subbuf2, 1); + return; + } + sub_to_interleaved (subbuf, subbuf2); + cdu->cdda_subfunc (subbuf2, 1); +} + +static int setstate (struct cdunit *cdu, int state) +{ + cdu->cdda_play_state = state; + if (cdu->cdda_statusfunc) + return cdu->cdda_statusfunc (cdu->cdda_play_state); + return 0; +} + +static void *cdda_unpack_func (void *v) +{ + cdimage_unpack_thread = 1; +// mp3decoder *mp3dec = NULL; + + for (;;) { + uae_u32 cduidx = read_comm_pipe_u32_blocking (&unpack_pipe); + if (cdimage_unpack_thread == 0) + break; + uae_u32 tocidx = read_comm_pipe_u32_blocking (&unpack_pipe); + struct cdunit *cdu = &cdunits[cduidx]; + struct cdtoc *t = &cdu->toc[tocidx]; + if (t->handle) { + // force unpack if handle points to delayed zipped file + uae_s64 pos = zfile_ftell (t->handle); + zfile_fseek (t->handle, -1, SEEK_END); + uae_u8 b; + zfile_fread (&b, 1, 1, t->handle); + zfile_fseek (t->handle, pos, SEEK_SET); + if (!t->data && (t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC)) { + t->data = xcalloc (uae_u8, t->filesize + 2352); + cdimage_unpack_active = 1; + if (t->data) { + if (t->enctype == AUDENC_MP3) { +// if (!mp3dec) { +// try { +// mp3dec = new mp3decoder(); +// } catch (exception) { }; +// } +// if (mp3dec) +// t->data = mp3dec->get (t->handle, t->data, t->filesize); + } else if (t->enctype == AUDENC_FLAC) { +// flac_get_data (t); + } + } + } + } + cdimage_unpack_active = 2; + } +// delete mp3dec; + cdimage_unpack_thread = -1; + return 0; +} + +static void *cdda_play_func (void *v) +{ + int cdda_pos; + int num_sectors = CDDA_BUFFERS; + int quit = 0; + int bufnum; + int bufon[2]; + int oldplay; + int idleframes; + bool foundsub; + struct cdunit *cdu = (struct cdunit*)v; + + while (cdu->cdda_play == 0) + Sleep (10); + oldplay = -1; + + bufon[0] = bufon[1] = 0; + bufnum = 0; + + cda_audio *cda = new cda_audio (num_sectors); + + while (cdu->cdda_play > 0) { + + if (oldplay != cdu->cdda_play) { + struct cdtoc *t; + int sector, diff; + struct timeb tb1, tb2; + + idleframes = 0; + foundsub = false; + ftime (&tb1); + cdda_pos = cdu->cdda_start; + oldplay = cdu->cdda_play; + sector = cdu->cd_last_pos = cdda_pos; + t = findtoc (cdu, §or); + if (!t) { + write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start); + setstate (cdu, AUDIO_STATUS_PLAY_ERROR); + } else { + write_log (_T("IMAGE CDDA: playing from %d to %d, track %d ('%s', offset %d, secoffset %d)\n"), + cdu->cdda_start, cdu->cdda_end, t->track, t->fname, t->offset, sector); + // do this even if audio is not compressed, t->handle also could be + // compressed and we want to unpack it in background too + while (cdimage_unpack_active == 1) + Sleep (10); + cdimage_unpack_active = 0; + write_comm_pipe_u32 (&unpack_pipe, cdu - &cdunits[0], 0); + write_comm_pipe_u32 (&unpack_pipe, t - &cdu->toc[0], 1); + while (cdimage_unpack_active == 0) + Sleep (10); + } + idleframes = cdu->cdda_delay_frames; + while (cdu->cdda_paused && cdu->cdda_play > 0) { + Sleep (10); + idleframes = -1; + } + + if (cdu->cdda_scan == 0) { + // find possible P-subchannel=1 and fudge starting point so that + // buggy CD32/CDTV software CD+G handling does not miss any frames + bool seenindex = false; + for (sector = cdda_pos - 200; sector < cdda_pos; sector++) { + int sec = sector; + t = findtoc (cdu, &sec); + if (t) { + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + getsub_deinterleaved (subbuf, cdu, t, sector); + if (seenindex) { + for (int i = 2 * SUB_ENTRY_SIZE; i < SUB_CHANNEL_SIZE; i++) { + if (subbuf[i]) { // non-zero R-W subchannels + int diff = cdda_pos - sector + 2; + write_log (_T("-> CD+G start pos fudge -> %d (%d)\n"), sector, -diff); + idleframes -= diff; + cdda_pos = sector; + break; + } + } + } else if (subbuf[0] == 0xff) { // P == 1? + seenindex = true; + } + } + } + } + cdda_pos -= idleframes; + + ftime (&tb2); + diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); + diff -= cdu->cdda_delay; + if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0) + Sleep (-diff); + setstate (cdu, AUDIO_STATUS_IN_PROGRESS); + } + + cda->wait(bufnum); + bufon[bufnum] = 0; + if (!cdu->cdda_play) + goto end; + + if (idleframes <= 0 && cdda_pos >= cdu->cdda_start && !isaudiotrack (&cdu->di.toc, cdda_pos)) { + setstate (cdu, AUDIO_STATUS_PLAY_ERROR); + write_log (_T("IMAGE CDDA: attempted to play data track %d\n"), cdda_pos); + goto end; // data track? + } + + if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) { + struct cdtoc *t; + int sector, cnt; + int dofinish = 0; + +// gui_flicker_led (LED_CD, cdu->di.unitnum - 1, LED_CD_AUDIO); + + memset (cda->buffers[bufnum], 0, num_sectors * 2352); + + for (cnt = 0; cnt < num_sectors; cnt++) { + uae_u8 *dst = cda->buffers[bufnum] + cnt * 2352; + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + sector = cdda_pos; + + memset (subbuf, 0, SUB_CHANNEL_SIZE); + + t = findtoc (cdu, §or); + if (t) { + if (t->handle && !(t->ctrl & 4)) { + int totalsize = t->size + t->skipsize; + if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) { + if (t->filesize >= sector * totalsize + t->offset + t->size) + memcpy (dst, t->data + sector * totalsize + t->offset, t->size); + } else if (t->enctype == AUDENC_PCM) { + if (sector * totalsize + t->offset + totalsize < t->filesize) { + zfile_fseek (t->handle, sector * totalsize + t->offset, SEEK_SET); + zfile_fread (dst, t->size, 1, t->handle); + } + } + } + getsub_deinterleaved (subbuf, cdu, t, cdda_pos); + } + + if (idleframes > 0) { + idleframes--; + memset (dst, 0, 2352); + memset (subbuf, 0, SUB_CHANNEL_SIZE); + } + + if (cdda_pos < cdu->cdda_start && cdu->cdda_scan == 0) + memset (dst, 0, 2352); + + dosub (cdu, subbuf); + + if (cdu->cdda_scan) { + cdda_pos += cdu->cdda_scan; + if (cdda_pos < 0) + cdda_pos = 0; + } else { + cdda_pos++; + } + + if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end) + dofinish = 1; + + } + + if (idleframes <= 0) + cdu->cd_last_pos = cdda_pos; + + bufon[bufnum] = 1; + cda->setvolume (currprefs.sound_volume_cd, cdu->cdda_volume[0], cdu->cdda_volume[1]); + if (!cda->play (bufnum)) { + setstate (cdu, AUDIO_STATUS_PLAY_ERROR); + goto end; + } + + if (dofinish) { + setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE); + cdu->cdda_play = -1; + cdda_pos = cdu->cdda_end + 1; + } + + } + + if (bufon[0] == 0 && bufon[1] == 0) { + while (cdu->cdda_paused && cdu->cdda_play == oldplay) + Sleep (10); + } + + bufnum = 1 - bufnum; + } + +end: + cda->wait (0); + cda->wait (1); + + while (cdimage_unpack_active == 1) + Sleep (10); + + delete cda; + + cdu->cdda_play = 0; + write_log (_T("IMAGE CDDA: thread killed\n")); + return NULL; +} + + +static void cdda_stop (struct cdunit *cdu) +{ + if (cdu->cdda_play != 0) { + cdu->cdda_play = -1; + while (cdu->cdda_play) { + Sleep (10); + } + } + cdu->cdda_paused = 0; + cdu->cdda_play_state = 0; +} + + +static int command_pause (int unitnum, int paused) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return -1; + int old = cdu->cdda_paused; + cdu->cdda_paused = paused; + return old; +} + +static int command_stop (int unitnum) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + cdda_stop (cdu); + return 1; +} + +static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + cdu->cd_last_pos = startlsn; + cdu->cdda_start = startlsn; + cdu->cdda_end = endlsn; + cdu->cdda_subfunc = subfunc; + cdu->cdda_statusfunc = statusfunc; + cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); + cdu->cdda_delay = setstate (cdu, -1); + cdu->cdda_delay_frames = setstate (cdu, -2); + setstate (cdu, AUDIO_STATUS_NOT_SUPPORTED); + if (!isaudiotrack (&cdu->di.toc, startlsn)) { + setstate (cdu, AUDIO_STATUS_PLAY_ERROR); + return 0; + } + if (!cdu->cdda_play) + uae_start_thread (_T("cdimage_cdda_play"), cdda_play_func, cdu, NULL); + cdu->cdda_play++; + return 1; +} + +static int command_qcode (int unitnum, uae_u8 *buf, int sector) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + uae_u8 *p; + int trk; + int pos; + int status; + + memset (buf, 0, SUBQ_SIZE); + p = buf; + + status = cdu->cdda_play_state; + if (cdu->cdda_play > 0 && cdu->cdda_paused) + status = AUDIO_STATUS_PAUSED; + + if (sector < 0) + pos = cdu->cd_last_pos; + else + pos = sector; + + p[1] = status; + p[3] = 12; + + p = buf + 4; + + struct cdtoc *td = NULL; + for (trk = 0; trk <= cdu->tracks; trk++) { + td = &cdu->toc[trk]; + if (pos < td->address) { + if (trk > 0) + td--; + break; + } + if (pos >= td->address && pos < td[1].address) + break; + } + if (!td) + return 0; + getsub_deinterleaved (subbuf, cdu, td, pos); + memcpy (p, subbuf + 12, 12); +// write_log (_T("%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"), +// pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); + return 1; +} + +static uae_u32 command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return -1; + uae_u32 old = (cdu->cdda_volume[1] << 16) | (cdu->cdda_volume[0] << 0); + cdu->cdda_volume[0] = volume_left; + cdu->cdda_volume[1] = volume_right; + return old; +} + +extern void encode_l2 (uae_u8 *p, int address); + +static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u32 extra) +{ + int ret = 0; + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + struct cdtoc *t = findtoc (cdu, §or); + + if (!t || t->handle == NULL) + goto end; + + cdda_stop (cdu); + if (sectorsize > 0) { + if (sectorsize == 2352 && t->size == 2048) { + // 2048 -> 2352 + while (size-- > 0) { + memset (data, 0, 16); + zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); + zfile_fread (data + 16, t->size, 1, t->handle); + encode_l2 (data, sector + 150); + sector++; + data += sectorsize; + } + } else if (sectorsize == 2048 && t->size == 2352) { + // 2352 -> 2048 + while (size-- > 0) { + uae_u8 b = 0; + zfile_fseek (t->handle, t->offset + sector * t->size + 15, SEEK_SET); + zfile_fread (&b, 1, 1, t->handle); + if (b == 2) // MODE2? + zfile_fseek (t->handle, t->offset + sector * t->size + 24, SEEK_SET); + zfile_fread (data, sectorsize, 1, t->handle); + sector++; + data += sectorsize; + } + } else if (sectorsize == 2336 && t->size == 2352) { + // 2352 -> 2336 + while (size-- > 0) { + uae_u8 b = 0; + zfile_fseek (t->handle, t->offset + sector * t->size + 15, SEEK_SET); + zfile_fread (&b, 1, 1, t->handle); + if (b != 2 && b != 0) // MODE0 or MODE2 only allowed + return 0; + zfile_fread (data, sectorsize, 1, t->handle); + sector++; + data += sectorsize; + } + } else if (sectorsize == t->size) { + // no change + zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); + zfile_fread (data, sectorsize, size, t->handle); + sector += size; + } + cdu->cd_last_pos = sector; + ret = sectorsize * size; + + } else { + + uae_u8 sectortype = extra >> 16; + uae_u8 cmd9 = extra >> 8; + int sync = (cmd9 >> 7) & 1; + int headercodes = (cmd9 >> 5) & 3; + int userdata = (cmd9 >> 4) & 1; + int edcecc = (cmd9 >> 3) & 1; + int errorfield = (cmd9 >> 1) & 3; + uae_u8 subs = extra & 7; + if (subs != 0 && subs != 1 && subs != 2 && subs != 4) { + ret = -1; + goto end; + } + + if (isaudiotrack (&cdu->di.toc, sector)) { + if (sectortype != 0 && sectortype != 1) { + ret = -2; + goto end; + } + if (t->size != 2352) { + ret = -1; + goto end; + } + for (int i = 0; i < size; i++) { + zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); + zfile_fread (data, t->size, 1, t->handle); + uae_u8 *p = data + t->size; + if (subs) { + uae_u8 subdata[SUB_CHANNEL_SIZE]; + getsub_deinterleaved (subdata, cdu, t, sector); + if (subs == 4) { // all, de-interleaved + memcpy (p, subdata, SUB_CHANNEL_SIZE); + p += SUB_CHANNEL_SIZE; + } else if (subs == 2) { // q-only + memcpy (p, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE); + p += SUB_ENTRY_SIZE; + } else if (subs == 1) { // all, interleaved + sub_to_interleaved (subdata, p); + p += SUB_CHANNEL_SIZE; + } + } + ret += p - data; + data = p; + sector++; + } + } + } +end: + return ret; +} + +// this only supports 2048 byte sectors +static int command_read (int unitnum, uae_u8 *data, int sector, int size) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + + struct cdtoc *t = findtoc (cdu, §or); + + if (!t || t->handle == NULL) + return 0; + cdda_stop (cdu); + if (t->size == 2048) { + zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); + zfile_fread (data, size, 2048, t->handle); + sector += size; + } else { + while (size-- > 0) { + if (t->size == 2352) { + uae_u8 b = 0; + zfile_fseek (t->handle, t->offset + sector * t->size + 15, SEEK_SET); + zfile_fread (&b, 1, 1, t->handle); + if (b == 2) // MODE2? + zfile_fseek (t->handle, t->offset + sector * t->size + 24, SEEK_SET); + } else { + zfile_fseek (t->handle, t->offset + sector * t->size + 16, SEEK_SET); + } + zfile_fread (data, 1, 2048, t->handle); + data += 2048; + sector++; + } + } + cdu->cd_last_pos = sector; + return 1; +} + +static int command_toc (int unitnum, struct cd_toc_head *th) +{ + struct cdunit *cdu = unitisopen (unitnum); + if (!cdu) + return 0; + + int i; + + memset (&cdu->di.toc, 0, sizeof (struct cd_toc_head)); + if (!cdu->tracks) + return 0; + + memset (th, 0, sizeof (struct cd_toc_head)); + struct cd_toc *toc = &th->toc[0]; + th->first_track = 1; + th->last_track = cdu->tracks; + th->points = cdu->tracks + 3; + th->tracks = cdu->tracks; + th->lastaddress = cdu->toc[cdu->tracks].address; + + toc->adr = 1; + toc->point = 0xa0; + toc->track = th->first_track; + toc++; + + th->first_track_offset = 1; + for (i = 0; i < cdu->tracks; i++) { + toc->adr = cdu->toc[i].adr; + toc->control = cdu->toc[i].ctrl; + toc->track = i + 1; + toc->point = i + 1; + toc->paddress = cdu->toc[i].address; + toc++; + } + + th->last_track_offset = cdu->tracks; + toc->adr = 1; + toc->point = 0xa1; + toc->track = th->last_track; + toc++; + + toc->adr = 1; + toc->point = 0xa2; + toc->paddress = th->lastaddress; + toc++; + + memcpy (&cdu->di.toc, th, sizeof (struct cd_toc_head)); + return 1; +} + +static void skipspace (TCHAR **s) +{ + while (_istspace (**s)) + (*s)++; +} +static void skipnspace (TCHAR **s) +{ + while (!_istspace (**s)) + (*s)++; +} + +static TCHAR *nextstring (TCHAR **sp) +{ + TCHAR *s; + TCHAR *out = NULL; + + skipspace (sp); + s = *sp; + if (*s == '\"') { + s++; + out = s; + while (*s && *s != '\"') + s++; + *s++ = 0; + } else if (*s) { + out = s; + skipnspace (&s); + *s++ = 0; + } + *sp = s; + return out; +} + +static int readval (const TCHAR *s) +{ + int base = 10; + TCHAR *endptr; + if (s[0] == '0' && _totupper (s[1]) == 'X') + s += 2, base = 16; + return _tcstol (s, &endptr, base); +} + +#define MEDIA_DESCRIPTOR "MEDIA DESCRIPTOR" + +/* MDS spec structures from cdemu */ + +#define MDS_MEDIUM_CD 0x00 /* CD-ROM */ +#define MDS_MEDIUM_CD_R 0x01 /* CD-R */ +#define MDS_MEDIUM_CD_RW 0x02 /* CD-RW */ +#define MDS_MEDIUM_DVD 0x10 /* DVD-ROM */ +#define MDS_MEDIUM_DVD_MINUS_R 0x12 /* DVD-R */ + +#define MDS_TRACKMODE_UNKNOWN 0x00 +#define MDS_TRACKMODE_AUDIO 0xA9 /* sector size = 2352 */ +#define MDS_TRACKMODE_MODE1 0xAA /* sector size = 2048 */ +#define MDS_TRACKMODE_MODE2 0xAB /* sector size = 2336 */ +#define MDS_TRACKMODE_MODE2_FORM1 0xAC /* sector size = 2048 */ +#define MDS_TRACKMODE_MODE2_FORM2 0xAD /* sector size = 2324 (+4) */ + +#define MDS_SUBCHAN_NONE 0x00 /* no subchannel */ +#define MDS_SUBCHAN_PW_INTERLEAVED 0x08 /* 96-byte PW subchannel, interleaved */ + +#define MDS_POINT_TRACK_FIRST 0xA0 /* info about first track */ +#define MDS_POINT_TRACK_LAST 0xA1 /* info about last track */ +#define MDS_POINT_TRACK_LEADOUT 0xA2 /* info about lead-out */ + +#pragma pack(1) + +typedef struct { + uae_u8 signature[16]; /* "MEDIA DESCRIPTOR" */ + uae_u8 version[2]; /* Version ? */ + uae_u16 medium_type; /* Medium type */ + uae_u16 num_sessions; /* Number of sessions */ + uae_u16 __dummy1__[2]; /* Wish I knew... */ + uae_u16 bca_len; /* Length of BCA data (DVD-ROM) */ + uae_u32 __dummy2__[2]; + uae_u32 bca_data_offset; /* Offset to BCA data (DVD-ROM) */ + uae_u32 __dummy3__[6]; /* Probably more offsets */ + uae_u32 disc_structures_offset; /* Offset to disc structures */ + uae_u32 __dummy4__[3]; /* Probably more offsets */ + uae_u32 sessions_blocks_offset; /* Offset to session blocks */ + uae_u32 dpm_blocks_offset; /* offset to DPM data blocks */ +} MDS_Header; /* length: 88 bytes */ + +typedef struct { + uae_s32 session_start; /* Session's start address */ + uae_s32 session_end; /* Session's end address */ + uae_u16 session_number; /* (Unknown) */ + uae_u8 num_all_blocks; /* Number of all data blocks. */ + uae_u8 num_nontrack_blocks; /* Number of lead-in data blocks */ + uae_u16 first_track; /* Total number of sessions in image? */ + uae_u16 last_track; /* Number of regular track data blocks. */ + uae_u32 __dummy2__; /* (unknown) */ + uae_u32 tracks_blocks_offset; /* Offset of lead-in+regular track data blocks. */ +} MDS_SessionBlock; /* length: 24 bytes */ + +typedef struct { + uae_u8 mode; /* Track mode */ + uae_u8 subchannel; /* Subchannel mode */ + uae_u8 adr_ctl; /* Adr/Ctl */ + uae_u8 __dummy2__; /* Track flags? */ + uae_u8 point; /* Track number. (>0x99 is lead-in track) */ + + uae_u32 __dummy3__; + uae_u8 min; /* Min */ + uae_u8 sec; /* Sec */ + uae_u8 frame; /* Frame */ + uae_u32 extra_offset; /* Start offset of this track's extra block. */ + uae_u16 sector_size; /* Sector size. */ + + uae_u8 __dummy4__[18]; + uae_u32 start_sector; /* Track start sector (PLBA). */ + uae_u64 start_offset; /* Track start offset. */ + uae_u8 session; /* Session or index? */ + uae_u8 __dummy5__[3]; + uae_u32 footer_offset; /* Start offset of footer. */ + uae_u8 __dummy6__[24]; +} MDS_TrackBlock; /* length: 80 bytes */ + +typedef struct { + uae_u32 pregap; /* Number of sectors in pregap. */ + uae_u32 length; /* Number of sectors in track. */ +} MDS_TrackExtraBlock; /* length: 8 bytes */ + +typedef struct { + uae_u32 filename_offset; /* Start offset of image filename. */ + uae_u32 widechar_filename; /* Seems to be set to 1 if widechar filename is used */ + uae_u32 __dummy1__; + uae_u32 __dummy2__; +} MDS_Footer; /* length: 16 bytes */ + +#pragma pack() + +static int parsemds (struct cdunit *cdu, struct zfile *zmds, const TCHAR *img) +{ + MDS_Header *head; + struct cdtoc *t; + uae_u8 *mds = NULL; + MDS_TrackBlock *tb = NULL; + MDS_SessionBlock *sb = NULL; + + write_log (_T("MDS TOC: '%s'\n"), img); + int size = zfile_size (zmds); + mds = xmalloc (uae_u8, size); + if (!mds) + goto end; + if (zfile_fread (mds, size, 1, zmds) != 1) + goto end; + + head = (MDS_Header*)mds; + if (!memcmp (&head, MEDIA_DESCRIPTOR, strlen (MEDIA_DESCRIPTOR))) + goto end; + if (head->version[0] != 1) { + write_log (_T("unsupported MDS version %d, only v.1 supported\n"), head->version[0]); + goto end; + } + + sb = (MDS_SessionBlock*)(mds + head->sessions_blocks_offset); + cdu->tracks = sb->last_track - sb->first_track + 1; + for (int i = 0; i < sb->num_all_blocks; i++) { + tb = (MDS_TrackBlock*)(mds + sb->tracks_blocks_offset + i * sizeof (MDS_TrackBlock)); + int point = tb->point; + int tracknum = -1; + if (point == 0xa2) + tracknum = cdu->tracks; + else if (point >= 1 && point <= 99) + tracknum = point - 1; + if (tracknum >= 0) { + MDS_Footer *footer = tb->footer_offset == 0 ? NULL : (MDS_Footer*)(mds + tb->footer_offset); + MDS_TrackExtraBlock *teb = tb->extra_offset == 0 ? NULL : (MDS_TrackExtraBlock*)(mds + tb->extra_offset); + t = &cdu->toc[tracknum]; + t->adr = tb->adr_ctl >> 4; + t->ctrl = tb->adr_ctl & 15; + if (point == 0xa2) + t->address = sb->session_end; + else + t->address = tb->start_sector; + t->track = point; + t->offset = tb->start_offset; + t->size = tb->sector_size; + + if (footer) { + TCHAR *fname = NULL; + fname = my_strdup ((char *)(mds + footer->filename_offset)); + if (fname[0] == '*' && fname[1] == '.') { + TCHAR newname[MAX_DPATH]; + _tcscpy (newname, img); + TCHAR *ext = _tcsrchr (newname, '.'); + if (ext) + _tcscpy (ext, fname + 1); + xfree (fname); + fname = my_strdup (newname); + } + + t->handle = zfile_fopen (fname, _T("rb"), ZFD_NORMAL); + t->fname = my_strdup (fname); + if (t->handle) + t->filesize = zfile_size (t->handle); + } + + if (tb->subchannel && t->handle) { + t->suboffset = t->size; + t->subcode = 1; // interleaved + t->subhandle = zfile_dup (t->handle); + t->skipsize = SUB_CHANNEL_SIZE; + t->size -= SUB_CHANNEL_SIZE; + if ((t->ctrl & 0x0c) != 4) + t->enctype = AUDENC_PCM; + } + + } + } + +end: + xfree (mds); + + return cdu->tracks; +} + +static int parseccd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img) +{ + int mode; + int num, tracknum, trackmode; + int adr, control, lba; + bool gotlba; + struct cdtoc *t; + struct zfile *zimg, *zsub; + TCHAR fname[MAX_DPATH]; + + write_log (_T("CCD TOC: '%s'\n"), img); + _tcscpy (fname, img); + TCHAR *ext = _tcsrchr (fname, '.'); + if (ext) + *ext = 0; + _tcscat (fname, _T(".img")); + zimg = zfile_fopen (fname, _T("rb"), ZFD_NORMAL); + if (!zimg) { + write_log (_T("CCD: can't open '%s'\n"), fname); + return 0; + } + ext = _tcsrchr (fname, '.'); + if (ext) + *ext = 0; + _tcscat (fname, _T(".sub")); + zsub = zfile_fopen (fname, _T("rb"), ZFD_NORMAL); + if (zsub) + write_log (_T("CCD: '%s' detected\n"), fname); + + num = -1; + mode = -1; + for (;;) { + TCHAR buf[MAX_DPATH], *p; + if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue)) + break; + p = buf; + skipspace (&p); + if (!_tcsnicmp (p, _T("[DISC]"), 6)) { + mode = 1; + } else if (!_tcsnicmp (p, _T("[ENTRY "), 7)) { + t = NULL; + mode = 2; + num = readval (p + 7); + if (num < 0) + break; + adr = control = -1; + gotlba = false; + } else if (!_tcsnicmp (p, _T("[TRACK "), 7)) { + mode = 3; + tracknum = readval (p + 7); + trackmode = -1; + if (tracknum <= 0 || tracknum > 99) + break; + t = &cdu->toc[tracknum - 1]; + } + if (mode < 0) + continue; + if (mode == 1) { + if (!_tcsnicmp (p, _T("TocEntries="), 11)) { + cdu->tracks = readval (p + 11) - 3; + if (cdu->tracks <= 0 || cdu->tracks > 99) + break; + } + continue; + } + if (cdu->tracks <= 0) + break; + + if (mode == 2) { + + if (!_tcsnicmp (p, _T("SESSION="), 8)) { + if (readval (p + 8) != 1) + mode = -1; + continue; + } else if (!_tcsnicmp (p, _T("POINT="), 6)) { + tracknum = readval (p + 6); + if (tracknum <= 0) + break; + if (tracknum >= 0xa0 && tracknum != 0xa2) { + mode = -1; + continue; + } + if (tracknum == 0xa2) + tracknum = cdu->tracks + 1; + t = &cdu->toc[tracknum - 1]; + continue; + } + if (!_tcsnicmp (p, _T("ADR="), 4)) + adr = readval (p + 4); + if (!_tcsnicmp (p, _T("CONTROL="), 8)) + control = readval (p + 8); + if (!_tcsnicmp (p, _T("PLBA="), 5)) { + lba = readval (p + 5); + gotlba = true; + } + if (gotlba && adr >= 0 && control >= 0) { + t->adr = adr; + t->ctrl = control; + t->address = lba; + t->offset = 0; + t->size = 2352; + t->offset = lba * t->size; + t->track = tracknum; + if ((control & 0x0c) != 4) + t->enctype = AUDENC_PCM; + if (zsub) { + t->subcode = 2; + t->subhandle = zfile_dup (zsub); + t->suboffset = 0; + } + if (zimg) { + t->handle = zfile_dup (zimg); + t->fname = my_strdup (zfile_getname (zimg)); + } + mode = -1; + } + + } else if (mode == 3) { + + if (!_tcsnicmp (p, _T("MODE="), 5)) + trackmode = _tstol (p + 5); + if (trackmode < 0 || trackmode > 2) + continue; + + } + + } + zfile_fclose (zimg); + zfile_fclose (zsub); + return cdu->tracks; +} + +static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img) +{ + int tracknum, index0, pregap; + int offset, secoffset, newfile; + TCHAR *fname, *fnametype; + audenc fnametypeid; + int ctrl; +// mp3decoder *mp3dec = NULL; + + fname = NULL; + fnametype = NULL; + tracknum = 0; + offset = 0; + secoffset = 0; + newfile = 0; + ctrl = 0; + index0 = -1; + pregap = 0; + fnametypeid = AUDENC_NONE; + + write_log (_T("CUE TOC: '%s'\n"), img); + for (;;) { + TCHAR buf[MAX_DPATH], *p; + if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue)) + break; + + p = buf; + skipspace (&p); + + if (!_tcsnicmp (p, _T("FILE"), 4)) { + p += 4; + xfree (fname); + fname = my_strdup (nextstring (&p)); + fnametype = nextstring (&p); + fnametypeid = AUDENC_NONE; + if (!fnametype) + break; + if (_tcsicmp (fnametype, _T("BINARY")) && _tcsicmp (fnametype, _T("WAVE")) && _tcsicmp (fnametype, _T("MP3")) && _tcsicmp (fnametype, _T("FLAC"))) { + write_log (_T("CUE: unknown file type '%s' ('%s')\n"), fnametype, fname); + } + fnametypeid = AUDENC_PCM; + if (!_tcsicmp (fnametype, _T("MP3"))) + fnametypeid = AUDENC_MP3; + else if (!_tcsicmp (fnametype, _T("FLAC"))) + fnametypeid = AUDENC_FLAC; + offset = 0; + newfile = 1; + ctrl = 0; + } else if (!_tcsnicmp (p, _T("FLAGS"), 5)) { + ctrl &= ~(1 | 2 | 8); + for (;;) { + TCHAR *f = nextstring (&p); + if (!f) + break; + if (!_tcsicmp (f, _T("PRE"))) + ctrl |= 1; + if (!_tcsicmp (f, _T("DCP"))) + ctrl |= 2; + if (!_tcsicmp (f, _T("4CH"))) + ctrl |= 8; + } + } else if (!_tcsnicmp (p, _T("TRACK"), 5)) { + int size; + TCHAR *tracktype; + + p += 5; + //pregap = 0; + index0 = -1; + tracknum = _tstoi (nextstring (&p)); + tracktype = nextstring (&p); + if (!tracktype) + break; + size = 2352; + if (!_tcsicmp (tracktype, _T("AUDIO"))) { + ctrl &= ~4; + } else { + ctrl |= 4; + if (!_tcsicmp (tracktype, _T("MODE1/2048"))) + size = 2048; + else if (!_tcsicmp (tracktype, _T("MODE1/2352"))) + size = 2352; + else if (!_tcsicmp (tracktype, _T("MODE2/2336")) || !_tcsicmp (tracktype, _T("CDI/2336"))) + size = 2336; + else if (!_tcsicmp (tracktype, _T("MODE2/2352")) || !_tcsicmp (tracktype, _T("CDI/2352"))) + size = 2352; + else { + write_log (_T("CUE: unknown tracktype '%s' ('%s')\n"), tracktype, fname); + } + } + if (tracknum >= 1 && tracknum <= 99) { + struct cdtoc *t = &cdu->toc[tracknum - 1]; + struct zfile *ztrack; + + if (tracknum > 1 && newfile) { + t--; + secoffset += t->filesize / t->size; + t++; + } + + newfile = 0; + ztrack = zfile_fopen (fname, _T("rb"), ZFD_ARCHIVE | ZFD_DELAYEDOPEN); + if (!ztrack) { + TCHAR tmp[MAX_DPATH]; + _tcscpy (tmp, fname); + p = tmp + _tcslen (tmp); + while (p > tmp) { + if (*p == '/' || *p == '\\') { + ztrack = zfile_fopen (p + 1, _T("rb"), ZFD_ARCHIVE | ZFD_DELAYEDOPEN); + if (ztrack) { + xfree (fname); + fname = my_strdup (p + 1); + } + break; + } + p--; + } + } + if (!ztrack) { + TCHAR tmp[MAX_DPATH]; + TCHAR *s2; + _tcscpy (tmp, zfile_getname (zcue)); + s2 = _tcsrchr (tmp, '\\'); + if (!s2) + s2 = _tcsrchr (tmp, '/'); + if (s2) { + s2[0] = 0; + _tcscat (tmp, _T("\\")); + _tcscat (tmp, fname); + ztrack = zfile_fopen (tmp, _T("rb"), ZFD_ARCHIVE | ZFD_DELAYEDOPEN); + } + } + t->track = tracknum; + t->ctrl = ctrl; + t->adr = 1; + t->handle = ztrack; + t->size = size; + t->fname = my_strdup (fname); + if (tracknum > cdu->tracks) + cdu->tracks = tracknum; + if (t->handle) + t->filesize = zfile_size (t->handle); + } + } else if (!_tcsnicmp (p, _T("PREGAP"), 6)) { + TCHAR *tt; + int tn; + p += 6; + tt = nextstring (&p); + tn = _tstoi (tt) * 60 * 75; + tn += _tstoi (tt + 3) * 75; + tn += _tstoi (tt + 6); + pregap += tn; + } else if (!_tcsnicmp (p, _T("INDEX"), 5)) { + int idxnum; + int tn = 0; + TCHAR *tt; + p += 5; + idxnum = _tstoi (nextstring (&p)); + tt = nextstring (&p); + tn = _tstoi (tt) * 60 * 75; + tn += _tstoi (tt + 3) * 75; + tn += _tstoi (tt + 6); + if (idxnum == 0) { + index0 = tn; + } else if (idxnum == 1 && tracknum >= 1 && tracknum <= 99) { + struct cdtoc *t = &cdu->toc[tracknum - 1]; + if (!t->address) { + t->address = tn + secoffset; + t->address += pregap; + if (tracknum > 1) { + offset += t->address - t[-1].address; + } else { + offset += t->address; + } + if (!secoffset) + t->offset = offset * t->size; + if (fnametypeid == AUDENC_PCM && t->handle) { + struct zfile *zf = t->handle; + uae_u8 buf[16] = { 0 }; + zfile_fread (buf, 12, 1, zf); + if (!memcmp (buf, "RIFF", 4) && !memcmp (buf + 8, "WAVE", 4)) { + int size; + for (;;) { + memset (buf, 0, sizeof buf); + if (zfile_fread (buf, 8, 1, zf) != 1) + break; + size = (buf[4] << 0) | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24); + if (!memcmp (buf, "data", 4)) + break; + if (size <= 0) + break; + zfile_fseek (zf, size, SEEK_CUR); + } + t->offset += zfile_ftell (zf); + t->filesize = size; + } + t->enctype = fnametypeid; + } else if (fnametypeid == AUDENC_MP3 && t->handle) { +// if (!mp3dec) { +// try { +// mp3dec = new mp3decoder(); +// } catch (exception) { } +// } +// if (mp3dec) { +// t->offset = 0; +// t->filesize = mp3dec->getsize (t->handle); +// if (t->filesize) +// t->enctype = fnametypeid; +// } + } else if (fnametypeid == AUDENC_FLAC && t->handle) { +// flac_get_size (t); +// if (t->filesize) +// t->enctype = fnametypeid; + } + } + } + } + } + + struct cdtoc *t = &cdu->toc[cdu->tracks - 1]; + int size = t->filesize; + if (!secoffset) + size -= offset * t->size; + if (size < 0) + size = 0; + cdu->toc[cdu->tracks].address = t->address + size / t->size; + + xfree (fname); + +// delete mp3dec; + + return cdu->tracks; +} + +static int parse_image (struct cdunit *cdu, const TCHAR *img) +{ + struct zfile *zcue; + int i; + const TCHAR *ext; + int secoffset; + + secoffset = 0; + cdu->tracks = 0; + if (!img) + return 0; + zcue = zfile_fopen (img, _T("rb"), ZFD_ARCHIVE | ZFD_CD | ZFD_DELAYEDOPEN); + if (!zcue) + return 0; + + ext = _tcsrchr (zfile_getname (zcue), '.'); + if (ext) { + TCHAR curdir[MAX_DPATH]; + TCHAR oldcurdir[MAX_DPATH], *p; + + ext++; + oldcurdir[0] = 0; + _tcscpy (curdir, img); + p = curdir + _tcslen (curdir); + while (p > curdir) { + if (*p == '/' || *p == '\\') + break; + p--; + } + *p = 0; + if (p > curdir) + my_setcurrentdir (curdir, oldcurdir); + + if (!_tcsicmp (ext, _T("cue"))) + parsecue (cdu, zcue, img); + else if (!_tcsicmp (ext, _T("ccd"))) + parseccd (cdu, zcue, img); + else if (!_tcsicmp (ext, _T("mds"))) + parsemds (cdu, zcue, img); + + if (oldcurdir[0]) + my_setcurrentdir (oldcurdir, NULL); + } + if (!cdu->tracks) { + uae_u64 siz = zfile_size (zcue); + if (siz >= 16384 && ((siz % 2048) == 0 || (siz % 2352) == 0)) { + struct cdtoc *t = &cdu->toc[0]; + cdu->tracks = 1; + t->ctrl = 4; + t->adr = 1; + t->fname = my_strdup (img); + t->handle = zcue; + t->size = (siz % 2048) == 0 ? 2048 : 2352; + t->filesize = siz; + write_log (_T("CD: plain CD image mounted!\n")); + cdu->toc[1].address = t->address + t->filesize / t->size; + zcue = NULL; + } + } + + if (!cdu->tracks) + write_log (_T("CD: couldn't mount '%s'!\n"), img); + + for (i = 0; i <= cdu->tracks; i++) { + struct cdtoc *t = &cdu->toc[i]; + uae_u32 msf = lsn2msf (t->address); + if (i < cdu->tracks) + write_log (_T("%2d: "), i + 1); + else + write_log (_T(" ")); + write_log (_T("%7d %02d:%02d:%02d"), + t->address, (msf >> 16) & 0xff, (msf >> 8) & 0xff, (msf >> 0) & 0xff); + if (i < cdu->tracks) + write_log (_T(" %s %x %10d %10d %s"), (t->ctrl & 4) ? _T("DATA ") : (t->subcode ? _T("CDA+SUB") : _T("CDA ")), + t->ctrl, t->offset, t->filesize, t->handle == NULL ? _T("[FILE ERROR]") : _T("")); + write_log (_T("\n")); + if (i < cdu->tracks) + write_log (_T(" - %s\n"), t->fname); + if (t->handle && !t->filesize) + t->filesize = zfile_size (t->handle); + } + + cdu->blocksize = 2048; + cdu->cdsize = cdu->toc[cdu->tracks].address * cdu->blocksize; + + + zfile_fclose (zcue); + return 1; +} + +static int ismedia (int unitnum, int quick) +{ + struct cdunit *cdu = &cdunits[unitnum]; + if (!cdu->enabled) + return -1; + return cdu->tracks > 0 ? 1 : 0; +} + +static struct device_info *info_device (int unitnum, struct device_info *di, int quick) +{ + struct cdunit *cdu = &cdunits[unitnum]; + memset (di, 0, sizeof (struct device_info)); + if (!cdu->enabled) + return NULL; + di->open = cdu->open; + di->removable = 1; + di->bus = unitnum; + di->target = 0; + di->lun = 0; + di->media_inserted = 0; + di->bytespersector = 2048; + di->mediapath[0] = 0; + di->cylinders = 1; + di->trackspercylinder = 1; + di->sectorspertrack = cdu->cdsize / di->bytespersector; + if (ismedia (unitnum, 1)) { + di->media_inserted = 1; + _tcscpy (di->mediapath, currprefs.cdslots[unitnum].name); + } + memset (&di->toc, 0, sizeof (struct cd_toc_head)); + command_toc (unitnum, &di->toc); + di->write_protected = 1; + di->type = INQ_ROMD; + di->unitnum = unitnum + 1; + if (di->mediapath[0]) { + _tcscpy (di->label, _T("IMG:")); + _tcscat (di->label, di->mediapath); + } else { + _tcscpy (di->label, _T("IMG:")); + } + di->backend = _T("IMAGE"); + return di; +} + +static void unload_image (struct cdunit *cdu) +{ + int i; + + for (i = 0; i < sizeof cdu->toc / sizeof (struct cdtoc); i++) { + struct cdtoc *t = &cdu->toc[i]; + zfile_fclose (t->handle); + if (t->handle != t->subhandle) + zfile_fclose (t->subhandle); + xfree (t->fname); + xfree (t->data); + xfree (t->subdata); + } + memset (cdu->toc, 0, sizeof cdu->toc); + cdu->tracks = 0; + cdu->cdsize = 0; +} + + +static int open_device (int unitnum, const TCHAR *ident, int flags) +{ + struct cdunit *cdu = &cdunits[unitnum]; + int ret = 0; + + if (!cdu->open) { + uae_sem_init (&cdu->sub_sem, 0, 1); + parse_image (cdu, ident); + cdu->open = true; + cdu->enabled = true; + cdu->cdda_volume[0] = 0x7fff; + cdu->cdda_volume[1] = 0x7fff; + if (cdimage_unpack_thread == 0) { + init_comm_pipe (&unpack_pipe, 10, 1); + uae_start_thread (_T("cdimage_unpack"), cdda_unpack_func, NULL, NULL); + while (cdimage_unpack_thread == 0) + Sleep (10); + } + ret = 1; + } + blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name); + return ret; +} + +static void close_device (int unitnum) +{ + struct cdunit *cdu = &cdunits[unitnum]; + if (cdu->open) { + cdda_stop (cdu); + cdu->open = false; + if (cdimage_unpack_thread) { + cdimage_unpack_thread = 0; + write_comm_pipe_u32 (&unpack_pipe, -1, 0); + write_comm_pipe_u32 (&unpack_pipe, -1, 1); + while (cdimage_unpack_thread == 0) + Sleep (10); + cdimage_unpack_thread = 0; + destroy_comm_pipe (&unpack_pipe); + } + unload_image (cdu); + uae_sem_destroy (&cdu->sub_sem); + } + blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name); +} + +static void close_bus (void) +{ + if (!bus_open) { + write_log (_T("IMAGE close_bus() when already closed!\n")); + return; + } + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + struct cdunit *cdu = &cdunits[i]; + if (cdu->open) + close_device (i); + cdu->enabled = false; + } + bus_open = 0; + write_log (_T("IMAGE driver closed.\n")); +} + +static int open_bus (int flags) +{ + if (bus_open) { + write_log (_T("IOCTL open_bus() more than once!\n")); + return 1; + } + bus_open = 1; + write_log (_T("Image driver open.\n")); + return 1; +} + +struct device_functions devicefunc_cdimage = { + _T("IMAGE"), + open_bus, close_bus, open_device, close_device, info_device, + 0, 0, 0, + command_pause, command_stop, command_play, command_volume, command_qcode, + command_toc, command_read, command_rawread, 0, + 0, ismedia, 0 +}; diff --git a/src/cdrom.cpp b/src/cdrom.cpp new file mode 100644 index 00000000..793760a7 --- /dev/null +++ b/src/cdrom.cpp @@ -0,0 +1,234 @@ +#include "sysconfig.h" +#include "sysdeps.h" + +/* CDROM MODE 1 EDC/ECC code (from Reed-Solomon library by Heiko Eissfeldt) */ + +/*****************************************************************/ +/* */ +/* CRC LOOKUP TABLE */ +/* ================ */ +/* The following CRC lookup table was generated automagically */ +/* by the Rocksoft^tm Model CRC Algorithm Table Generation */ +/* Program V1.0 using the following model parameters: */ +/* */ +/* Width : 4 bytes. */ +/* Poly : 0x8001801BL */ +/* Reverse : TRUE. */ +/* */ +/* For more information on the Rocksoft^tm Model CRC Algorithm, */ +/* see the document titled "A Painless Guide to CRC Error */ +/* Detection Algorithms" by Ross Williams */ +/* (ross@guest.adelaide.edu.au.). This document is likely to be */ +/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */ +/* */ +/*****************************************************************/ + +static const uae_u32 EDC_crctable[256] = +{ + 0x00000000L, 0x90910101L, 0x91210201L, 0x01B00300L, + 0x92410401L, 0x02D00500L, 0x03600600L, 0x93F10701L, + 0x94810801L, 0x04100900L, 0x05A00A00L, 0x95310B01L, + 0x06C00C00L, 0x96510D01L, 0x97E10E01L, 0x07700F00L, + 0x99011001L, 0x09901100L, 0x08201200L, 0x98B11301L, + 0x0B401400L, 0x9BD11501L, 0x9A611601L, 0x0AF01700L, + 0x0D801800L, 0x9D111901L, 0x9CA11A01L, 0x0C301B00L, + 0x9FC11C01L, 0x0F501D00L, 0x0EE01E00L, 0x9E711F01L, + 0x82012001L, 0x12902100L, 0x13202200L, 0x83B12301L, + 0x10402400L, 0x80D12501L, 0x81612601L, 0x11F02700L, + 0x16802800L, 0x86112901L, 0x87A12A01L, 0x17302B00L, + 0x84C12C01L, 0x14502D00L, 0x15E02E00L, 0x85712F01L, + 0x1B003000L, 0x8B913101L, 0x8A213201L, 0x1AB03300L, + 0x89413401L, 0x19D03500L, 0x18603600L, 0x88F13701L, + 0x8F813801L, 0x1F103900L, 0x1EA03A00L, 0x8E313B01L, + 0x1DC03C00L, 0x8D513D01L, 0x8CE13E01L, 0x1C703F00L, + 0xB4014001L, 0x24904100L, 0x25204200L, 0xB5B14301L, + 0x26404400L, 0xB6D14501L, 0xB7614601L, 0x27F04700L, + 0x20804800L, 0xB0114901L, 0xB1A14A01L, 0x21304B00L, + 0xB2C14C01L, 0x22504D00L, 0x23E04E00L, 0xB3714F01L, + 0x2D005000L, 0xBD915101L, 0xBC215201L, 0x2CB05300L, + 0xBF415401L, 0x2FD05500L, 0x2E605600L, 0xBEF15701L, + 0xB9815801L, 0x29105900L, 0x28A05A00L, 0xB8315B01L, + 0x2BC05C00L, 0xBB515D01L, 0xBAE15E01L, 0x2A705F00L, + 0x36006000L, 0xA6916101L, 0xA7216201L, 0x37B06300L, + 0xA4416401L, 0x34D06500L, 0x35606600L, 0xA5F16701L, + 0xA2816801L, 0x32106900L, 0x33A06A00L, 0xA3316B01L, + 0x30C06C00L, 0xA0516D01L, 0xA1E16E01L, 0x31706F00L, + 0xAF017001L, 0x3F907100L, 0x3E207200L, 0xAEB17301L, + 0x3D407400L, 0xADD17501L, 0xAC617601L, 0x3CF07700L, + 0x3B807800L, 0xAB117901L, 0xAAA17A01L, 0x3A307B00L, + 0xA9C17C01L, 0x39507D00L, 0x38E07E00L, 0xA8717F01L, + 0xD8018001L, 0x48908100L, 0x49208200L, 0xD9B18301L, + 0x4A408400L, 0xDAD18501L, 0xDB618601L, 0x4BF08700L, + 0x4C808800L, 0xDC118901L, 0xDDA18A01L, 0x4D308B00L, + 0xDEC18C01L, 0x4E508D00L, 0x4FE08E00L, 0xDF718F01L, + 0x41009000L, 0xD1919101L, 0xD0219201L, 0x40B09300L, + 0xD3419401L, 0x43D09500L, 0x42609600L, 0xD2F19701L, + 0xD5819801L, 0x45109900L, 0x44A09A00L, 0xD4319B01L, + 0x47C09C00L, 0xD7519D01L, 0xD6E19E01L, 0x46709F00L, + 0x5A00A000L, 0xCA91A101L, 0xCB21A201L, 0x5BB0A300L, + 0xC841A401L, 0x58D0A500L, 0x5960A600L, 0xC9F1A701L, + 0xCE81A801L, 0x5E10A900L, 0x5FA0AA00L, 0xCF31AB01L, + 0x5CC0AC00L, 0xCC51AD01L, 0xCDE1AE01L, 0x5D70AF00L, + 0xC301B001L, 0x5390B100L, 0x5220B200L, 0xC2B1B301L, + 0x5140B400L, 0xC1D1B501L, 0xC061B601L, 0x50F0B700L, + 0x5780B800L, 0xC711B901L, 0xC6A1BA01L, 0x5630BB00L, + 0xC5C1BC01L, 0x5550BD00L, 0x54E0BE00L, 0xC471BF01L, + 0x6C00C000L, 0xFC91C101L, 0xFD21C201L, 0x6DB0C300L, + 0xFE41C401L, 0x6ED0C500L, 0x6F60C600L, 0xFFF1C701L, + 0xF881C801L, 0x6810C900L, 0x69A0CA00L, 0xF931CB01L, + 0x6AC0CC00L, 0xFA51CD01L, 0xFBE1CE01L, 0x6B70CF00L, + 0xF501D001L, 0x6590D100L, 0x6420D200L, 0xF4B1D301L, + 0x6740D400L, 0xF7D1D501L, 0xF661D601L, 0x66F0D700L, + 0x6180D800L, 0xF111D901L, 0xF0A1DA01L, 0x6030DB00L, + 0xF3C1DC01L, 0x6350DD00L, 0x62E0DE00L, 0xF271DF01L, + 0xEE01E001L, 0x7E90E100L, 0x7F20E200L, 0xEFB1E301L, + 0x7C40E400L, 0xECD1E501L, 0xED61E601L, 0x7DF0E700L, + 0x7A80E800L, 0xEA11E901L, 0xEBA1EA01L, 0x7B30EB00L, + 0xE8C1EC01L, 0x7850ED00L, 0x79E0EE00L, 0xE971EF01L, + 0x7700F000L, 0xE791F101L, 0xE621F201L, 0x76B0F300L, + 0xE541F401L, 0x75D0F500L, 0x7460F600L, 0xE4F1F701L, + 0xE381F801L, 0x7310F900L, 0x72A0FA00L, 0xE231FB01L, + 0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L +}; + +/*****************************************************************/ +/* End of CRC Lookup Table */ +/*****************************************************************/ + +static uae_u8 rs_l12_alog[255] = { + 1, 2, 4, 8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143, 3, 6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140, 5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141, 7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138, 9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,}; + static uae_u8 rs_l12_log[256] = { + 0, 0, 1,25, 2,50,26,198, 3,223,51,238,27,104,199,75, 4,100,224,14,52,141,239,129,28,193,105,248,200, 8,76,113, 5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154, 9,120,77,228,114,166, 6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87, 7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175,}; + static uae_u8 DQ[2][43] = { + {190,96,250,132,59,81,159,154,200,7,111,245,10,20,41,156,168,79,173,231,229,171,210,240,17,67,215,43,120,8,199,74,102,220,251,95,175,87,166,113,75,198,25,}, + {97,251,133,60,82,160,155,201,8,112,246,11,21,42,157,169,80,174,232,230,172,211,241,18,68,216,44,121,9,200,75,103,221,252,96,176,88,167,114,76,199,26,1,}, + }; + static uae_u8 DP[2][24] = { + {231,229,171,210,240,17,67,215,43,120,8,199,74,102,220,251,95,175,87,166,113,75,198,25,}, + {230,172,211,241,18,68,216,44,121,9,200,75,103,221,252,96,176,88,167,114,76,199,26,1,}, + }; + + /* data sector definitions for RSPC */ + /* user data bytes per frame */ +#define L2_RAW (1024*2) + /* parity bytes for 16 bit units */ +#define L2_Q (26*2*2) +#define L2_P (43*2*2) +#define RS_L12_BITS 8 + + static uae_u32 build_edc (const uae_u8 *inout, int from, int upto) + { + const uae_u8 *p = inout + from; + uae_u32 result = 0; + for (; from <= upto; from++) + result = EDC_crctable[(result ^ *p++) & 0xff] ^ (result >> 8); + return result; + } + + static void encode_L2_Q(uae_u8 *inout) + { + uae_u8 *Q; + int i,j; + + Q = inout + 4 + L2_RAW + 4 + 8 + L2_P; + memset(Q, 0, L2_Q); + for (j = 0; j < 26; j++) { + for (i = 0; i < 43; i++) { + uae_u8 data; + /* LSB */ + data = inout[(j*43*2+i*2*44) % (4 + L2_RAW + 4 + 8 + L2_P)]; + if (data != 0) { + uae_u32 base = rs_l12_log[data]; + uae_u32 sum = base + DQ[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + Q[0] ^= rs_l12_alog[sum]; + sum = base + DQ[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + Q[26*2] ^= rs_l12_alog[sum]; + } + /* MSB */ + data = inout[(j*43*2+i*2*44+1) % (4 + L2_RAW + 4 + 8 + L2_P)]; + if (data != 0) { + uae_u32 base = rs_l12_log[data]; + uae_u32 sum = base+DQ[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + Q[1] ^= rs_l12_alog[sum]; + sum = base + DQ[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + Q[26*2+1] ^= rs_l12_alog[sum]; + } + } + Q += 2; + } + } + + static void encode_L2_P(uae_u8 inout[4 + L2_RAW + 4 + 8 + L2_P]) + { + uae_u8 *P; + int i,j; + + P = inout + 4 + L2_RAW + 4 + 8; + memset(P, 0, L2_P); + for (j = 0; j < 43; j++) { + for (i = 0; i < 24; i++) { + uae_u8 data; + /* LSB */ + data = inout[i*2*43]; + if (data != 0) { + uae_u32 base = rs_l12_log[data]; + uae_u32 sum = base + DP[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + P[0] ^= rs_l12_alog[sum]; + sum = base + DP[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + P[43*2] ^= rs_l12_alog[sum]; + } + /* MSB */ + data = inout[i*2*43+1]; + if (data != 0) { + uae_u32 base = rs_l12_log[data]; + uae_u32 sum = base + DP[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + P[1] ^= rs_l12_alog[sum]; + sum = base + DP[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + P[43*2+1] ^= rs_l12_alog[sum]; + } + } + P += 2; + inout += 2; + } + } + + static uae_u8 tobcd (uae_u8 v) + { + return ((v / 10) << 4) | (v % 10); + } + + void encode_l2 (uae_u8 *p, int address) + { + uae_u32 v; + + p[0] = 0x00; + memset (p + 1, 0xff, 11); + p[12] = tobcd ((uae_u8)(address / (60 * 75))); + p[13] = tobcd ((uae_u8)((address / 75) % 60)); + p[14] = tobcd ((uae_u8)(address % 75)); + p[15] = 1; /* MODE1 */ + v = build_edc (p, 0, 16 + 2048 - 1); + p[2064 + 0] = (uae_u8) (v >> 0); + p[2064 + 1] = (uae_u8) (v >> 8); + p[2064 + 2] = (uae_u8) (v >> 16); + p[2064 + 3] = (uae_u8) (v >> 24); + memset (p + 2064 + 4, 0, 8); + encode_L2_P (p + 12); + encode_L2_Q (p + 12); + } diff --git a/src/cfgfile.cpp b/src/cfgfile.cpp index 73e8207a..1dea5f3e 100644 --- a/src/cfgfile.cpp +++ b/src/cfgfile.cpp @@ -27,6 +27,7 @@ #include "filesys.h" #include "fsdb.h" #include "disk.h" +#include "blkdev.h" #include "sd-pandora/sound.h" #include "SDL_keysym.h" @@ -58,6 +59,10 @@ static const TCHAR *soundfiltermode2[] = { _T("standard"), _T("enhanced"), 0 }; static const TCHAR *lorestype1[] = { _T("lores"), _T("hires"), _T("superhires"), 0 }; static const TCHAR *lorestype2[] = { _T("true"), _T("false"), 0 }; static const TCHAR *abspointers[] = { _T("none"), _T("mousehack"), _T("tablet"), 0 }; +static const TCHAR *joyportmodes[] = { _T(""), _T("mouse"), _T("djoy"), _T("gamepad"), _T("ajoy"), _T("cdtvjoy"), _T("cd32joy"), _T("lightpen"), 0 }; +static const TCHAR *joyaf[] = { _T("none"), _T("normal"), _T("toggle"), 0 }; +static const TCHAR *cdmodes[] = { _T("disabled"), _T(""), _T("image"), _T("ioctl"), _T("spti"), _T("aspi"), 0 }; +static const TCHAR *cdconmodes[] = { _T(""), _T("uae"), _T("ide"), _T("scsi"), _T("cdtv"), _T("cd32"), 0 }; static const TCHAR *rtgtype[] = { _T("ZorroII"), _T("ZorroIII"), 0 }; static const TCHAR *obsolete[] = { @@ -345,6 +350,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_write_str (f, tmp, p->path_floppy); _stprintf (tmp, _T("%s.hardfile_path"), TARGET_NAME); cfgfile_write_str (f, tmp, p->path_hardfile); + _stprintf (tmp, _T("%s.cd_path"), TARGET_NAME); + cfgfile_write_str (f, tmp, p->path_cd); cfg_write (_T("; host-specific"), f); @@ -355,6 +362,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_write_str (f, _T("use_gui"), guimode1[p->start_gui]); cfgfile_write_rom (f, p->path_rom, p->romfile, _T("kickstart_rom_file")); cfgfile_write_rom (f, p->path_rom, p->romextfile, _T("kickstart_ext_rom_file")); + cfgfile_write_str (f, _T("flash_file"), p->flashfile); p->nr_floppies = 4; for (i = 0; i < 4; i++) { @@ -368,6 +376,27 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) p->nr_floppies = i; } + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + if (p->cdslots[i].name[0] || p->cdslots[i].inuse) { + TCHAR tmp2[MAX_DPATH]; + _stprintf (tmp, _T("cdimage%d"), i); + TCHAR *s = cfgfile_subst_path (p->path_cd, UNEXPANDED, p->cdslots[i].name); + _tcscpy (tmp2, s); + xfree (s); + if (p->cdslots[i].type != SCSI_UNIT_DEFAULT || _tcschr (p->cdslots[i].name, ',') || p->cdslots[i].delayed) { + _tcscat (tmp2, _T(",")); + if (p->cdslots[i].delayed) { + _tcscat (tmp2, _T("delay")); + _tcscat (tmp2, _T(":")); + } + if (p->cdslots[i].type != SCSI_UNIT_DEFAULT) { + _tcscat (tmp2, cdmodes[p->cdslots[i].type + 1]); + } + } + cfgfile_write_str (f, tmp, tmp2); + } + } + cfgfile_write (f, _T("nr_floppies"), _T("%d"), p->nr_floppies); cfgfile_write (f, _T("floppy_speed"), _T("%d"), p->floppy_speed); @@ -379,9 +408,48 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_write_str (f, _T("sound_interpol"), interpolmode[p->sound_interpol]); cfgfile_write_str (f, _T("sound_filter"), soundfiltermode1[p->sound_filter]); cfgfile_write_str (f, _T("sound_filter_type"), soundfiltermode2[p->sound_filter_type]); + if (p->sound_volume_cd >= 0) + cfgfile_write (f, _T("sound_volume_cd"), _T("%d"), p->sound_volume_cd); cfgfile_write (f, _T("cachesize"), _T("%d"), p->cachesize); + for (i = 0; i < MAX_JPORTS; i++) { + struct jport *jp = &p->jports[i]; + int v = jp->id; + TCHAR tmp1[MAX_DPATH], tmp2[MAX_DPATH]; + if (v == JPORT_CUSTOM) { + _tcscpy (tmp2, _T("custom")); + } else if (v == JPORT_NONE) { + _tcscpy (tmp2, _T("none")); + } else if (v < JSEM_JOYS) { + _stprintf (tmp2, _T("kbd%d"), v + 1); + } else if (v < JSEM_MICE) { + _stprintf (tmp2, _T("joy%d"), v - JSEM_JOYS); + } else { + _tcscpy (tmp2, _T("mouse")); + if (v - JSEM_MICE > 0) + _stprintf (tmp2, _T("mouse%d"), v - JSEM_MICE); + } + if (i < 2 || jp->id >= 0) { + _stprintf (tmp1, _T("joyport%d"), i); + cfgfile_write (f, tmp1, tmp2); + _stprintf (tmp1, _T("joyport%dautofire"), i); + cfgfile_write (f, tmp1, joyaf[jp->autofire]); + if (i < 2 && jp->mode > 0) { + _stprintf (tmp1, _T("joyport%dmode"), i); + cfgfile_write (f, tmp1, joyportmodes[jp->mode]); + } + if (jp->name[0]) { + _stprintf (tmp1, _T("joyportfriendlyname%d"), i); + cfgfile_write (f, tmp1, jp->name); + } + if (jp->configname[0]) { + _stprintf (tmp1, _T("joyportname%d"), i); + cfgfile_write (f, tmp1, jp->configname); + } + } + } + cfgfile_write_bool (f, _T("bsdsocket_emu"), p->socket_emu); cfgfile_write_bool (f, _T("synchronize_clock"), p->tod_hack); @@ -421,6 +489,10 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_dwrite (f, _T("chipset"), _T("ocs")); cfgfile_write_str (f, _T("collision_level"), collmode[p->collision_level]); + cfgfile_dwrite_bool (f, _T("cd32cd"), p->cs_cd32cd); + cfgfile_dwrite_bool (f, _T("cd32c2p"), p->cs_cd32c2p); + cfgfile_dwrite_bool (f, _T("cd32nvram"), p->cs_cd32nvram); + cfgfile_write (f, _T("fastmem_size"), _T("%d"), p->fastmem_size / 0x100000); cfgfile_write (f, _T("z3mem_size"), _T("%d"), p->z3fastmem_size / 0x100000); cfgfile_write (f, _T("z3mem_start"), _T("0x%x"), p->z3fastmem_start); @@ -688,6 +760,7 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) /* We special case the various path options here. */ if (cfgfile_path (option, value, _T("rom_path"), p->path_rom, sizeof p->path_rom / sizeof (TCHAR)) || cfgfile_path (option, value, _T("floppy_path"), p->path_floppy, sizeof p->path_floppy / sizeof (TCHAR)) + || cfgfile_path (option, value, _T("cd_path"), p->path_cd, sizeof p->path_cd / sizeof (TCHAR)) || cfgfile_path (option, value, _T("hardfile_path"), p->path_hardfile, sizeof p->path_hardfile / sizeof (TCHAR))) return 1; return target_parse_option (p, option, value); @@ -695,7 +768,80 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) return 0; } + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + TCHAR tmp[20]; + _stprintf (tmp, _T("cdimage%d"), i); + if (!_tcsicmp (option, tmp)) { + if (!_tcsicmp (value, _T("autodetect"))) { + p->cdslots[i].type = SCSI_UNIT_DEFAULT; + p->cdslots[i].inuse = true; + p->cdslots[i].name[0] = 0; + } else { + p->cdslots[i].delayed = false; + TCHAR *next = _tcsrchr (value, ','); + int type = SCSI_UNIT_DEFAULT; + int mode = 0; + int unitnum = 0; + for (;;) { + if (!next) + break; + *next++ = 0; + TCHAR *next2 = _tcschr (next, ':'); + if (next2) + *next2++ = 0; + int tmpval = 0; + if (!_tcsicmp (next, _T("delay"))) { + p->cdslots[i].delayed = true; + next = next2; + if (!next) + break; + next2 = _tcschr (next, ':'); + if (next2) + *next2++ = 0; + } + type = match_string (cdmodes, next); + if (type < 0) + type = SCSI_UNIT_DEFAULT; + else + type--; + next = next2; + if (!next) + break; + next2 = _tcschr (next, ':'); + if (next2) + *next2++ = 0; + mode = match_string (cdconmodes, next); + if (mode < 0) + mode = 0; + next = next2; + if (!next) + break; + next2 = _tcschr (next, ':'); + if (next2) + *next2++ = 0; + cfgfile_intval (option, next, tmp, &unitnum, 1); + } + if (_tcslen (value) > 0) { + TCHAR *s = cfgfile_subst_path (UNEXPANDED, p->path_cd, value); + _tcsncpy (p->cdslots[i].name, s, sizeof p->cdslots[i].name / sizeof (TCHAR)); + xfree (s); + } + p->cdslots[i].name[sizeof p->cdslots[i].name - 1] = 0; + p->cdslots[i].inuse = true; + p->cdslots[i].type = type; + } + // disable all following units + i++; + while (i < MAX_TOTAL_SCSI_DEVICES) { + p->cdslots[i].type = SCSI_UNIT_DISABLED; + i++; + } + return 1; + } + } + if (cfgfile_intval (option, value, _T("sound_frequency"), &p->sound_freq, 1) + || cfgfile_intval (option, value, _T("sound_volume_cd"), &p->sound_volume_cd, 1) || cfgfile_intval (option, value, _T("sound_stereo_separation"), &p->sound_stereo_separation, 1) || cfgfile_intval (option, value, _T("sound_stereo_mixing_delay"), &p->sound_mixed_stereo_delay, 1) @@ -754,6 +900,47 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) return 1; } + if (_tcscmp (option, _T("joyportfriendlyname0")) == 0 || _tcscmp (option, _T("joyportfriendlyname1")) == 0) { + inputdevice_joyport_config (p, value, _tcscmp (option, _T("joyportfriendlyname0")) == 0 ? 0 : 1, -1, 2); + return 1; + } + if (_tcscmp (option, _T("joyportfriendlyname2")) == 0 || _tcscmp (option, _T("joyportfriendlyname3")) == 0) { + inputdevice_joyport_config (p, value, _tcscmp (option, _T("joyportfriendlyname2")) == 0 ? 2 : 3, -1, 2); + return 1; + } + if (_tcscmp (option, _T("joyportname0")) == 0 || _tcscmp (option, _T("joyportname1")) == 0) { + inputdevice_joyport_config (p, value, _tcscmp (option, _T("joyportname0")) == 0 ? 0 : 1, -1, 1); + return 1; + } + if (_tcscmp (option, _T("joyportname2")) == 0 || _tcscmp (option, _T("joyportname3")) == 0) { + inputdevice_joyport_config (p, value, _tcscmp (option, _T("joyportname2")) == 0 ? 2 : 3, -1, 1); + return 1; + } + if (_tcscmp (option, _T("joyport0")) == 0 || _tcscmp (option, _T("joyport1")) == 0) { + inputdevice_joyport_config (p, value, _tcscmp (option, _T("joyport0")) == 0 ? 0 : 1, -1, 0); + return 1; + } + if (_tcscmp (option, _T("joyport2")) == 0 || _tcscmp (option, _T("joyport3")) == 0) { + inputdevice_joyport_config (p, value, _tcscmp (option, _T("joyport2")) == 0 ? 2 : 3, -1, 0); + return 1; + } + if (cfgfile_strval (option, value, _T("joyport0mode"), &p->jports[0].mode, joyportmodes, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport1mode"), &p->jports[1].mode, joyportmodes, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport2mode"), &p->jports[2].mode, joyportmodes, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport3mode"), &p->jports[3].mode, joyportmodes, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport0autofire"), &p->jports[0].autofire, joyaf, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport1autofire"), &p->jports[1].autofire, joyaf, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport2autofire"), &p->jports[2].autofire, joyaf, 0)) + return 1; + if (cfgfile_strval (option, value, _T("joyport3autofire"), &p->jports[3].autofire, joyaf, 0)) + return 1; + if (cfgfile_string (option, value, _T("statefile"), tmpbuf, sizeof (tmpbuf) / sizeof (TCHAR))) { _tcscpy (savestate_fname, tmpbuf); if (zfile_exists (savestate_fname)) { @@ -1090,6 +1277,9 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH if (cfgfile_yesno (option, value, _T("immediate_blits"), &p->immediate_blits) || cfgfile_yesno (option, value, _T("fast_copper"), &p->fast_copper) + || cfgfile_yesno (option, value, _T("cd32cd"), &p->cs_cd32cd) + || cfgfile_yesno (option, value, _T("cd32c2p"), &p->cs_cd32c2p) + || cfgfile_yesno (option, value, _T("cd32nvram"), &p->cs_cd32nvram) || cfgfile_yesno (option, value, _T("ntsc"), &p->ntscmode) || cfgfile_yesno (option, value, _T("cpu_compatible"), &p->cpu_compatible) || cfgfile_yesno (option, value, _T("cpu_24bit_addressing"), &p->address_space_24)) @@ -1115,7 +1305,8 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH if (cfgfile_strval (option, value, _T("collision_level"), &p->collision_level, collmode, 0)) return 1; if (cfgfile_string (option, value, _T("kickstart_rom_file"), p->romfile, sizeof p->romfile) - || cfgfile_string (option, value, _T("kickstart_ext_rom_file"), p->romextfile, sizeof p->romextfile)) + || cfgfile_string (option, value, _T("kickstart_ext_rom_file"), p->romextfile, sizeof p->romextfile) + || cfgfile_string (option, value, _T("flash_file"), p->flashfile, sizeof p->flashfile)) return 1; for (i = 0; i < 4; i++) { @@ -1523,6 +1714,44 @@ static void parse_sound_spec (struct uae_prefs *p, const TCHAR *spec) free (x0); } +static void parse_joy_spec (struct uae_prefs *p, const TCHAR *spec) +{ + int v0 = 2, v1 = 0; + if (_tcslen(spec) != 2) + goto bad; + + switch (spec[0]) { + case '0': v0 = JSEM_JOYS; break; + case '1': v0 = JSEM_JOYS + 1; break; + case 'M': case 'm': v0 = JSEM_MICE; break; + case 'A': case 'a': v0 = JSEM_KBDLAYOUT; break; + case 'B': case 'b': v0 = JSEM_KBDLAYOUT + 1; break; + case 'C': case 'c': v0 = JSEM_KBDLAYOUT + 2; break; + default: goto bad; + } + + switch (spec[1]) { + case '0': v1 = JSEM_JOYS; break; + case '1': v1 = JSEM_JOYS + 1; break; + case 'M': case 'm': v1 = JSEM_MICE; break; + case 'A': case 'a': v1 = JSEM_KBDLAYOUT; break; + case 'B': case 'b': v1 = JSEM_KBDLAYOUT + 1; break; + case 'C': case 'c': v1 = JSEM_KBDLAYOUT + 2; break; + default: goto bad; + } + if (v0 == v1) + goto bad; + /* Let's scare Pascal programmers */ + if (0) +bad: + write_log (_T("Bad joystick mode specification. Use -J xy, where x and y\n") + _T("can be 0 for joystick 0, 1 for joystick 1, M for mouse, and\n") + _T("a, b or c for different keyboard settings.\n")); + + p->jports[0].id = v0; + p->jports[1].id = v1; +} + static void parse_filesys_spec (struct uae_prefs *p, bool readonly, const TCHAR *spec) { TCHAR buf[256]; @@ -1654,6 +1883,7 @@ int parse_cmdline_option (struct uae_prefs *p, TCHAR c, const TCHAR *arg) case 'W': parse_hardfile_spec (p, arg); break; case 'S': parse_sound_spec (p, arg); break; case 'R': p->gfx_framerate = _tstoi (arg); break; + case 'J': parse_joy_spec (p, arg); break; case 'w': p->m68k_speed = _tstoi (arg); break; @@ -1738,6 +1968,16 @@ void default_prefs (struct uae_prefs *p, int type) p->start_gui = 1; p->all_lines = 0; + + memset (&p->jports[0], 0, sizeof (struct jport)); + memset (&p->jports[1], 0, sizeof (struct jport)); + memset (&p->jports[2], 0, sizeof (struct jport)); + memset (&p->jports[3], 0, sizeof (struct jport)); + p->jports[0].id = JSEM_MICE; + p->jports[1].id = JSEM_JOYS; + p->jports[2].id = -1; + p->jports[3].id = -1; + p->produce_sound = 3; p->sound_stereo = SND_STEREO; p->sound_stereo_separation = 7; @@ -1746,6 +1986,7 @@ void default_prefs (struct uae_prefs *p, int type) p->sound_interpol = 0; p->sound_filter = FILTER_SOUND_OFF; p->sound_filter_type = 0; + p->sound_volume_cd = 20; p->cachesize = DEFAULT_JIT_CACHE_SIZE; @@ -1782,6 +2023,8 @@ void default_prefs (struct uae_prefs *p, int type) p->fast_copper = 1; p->tod_hack = 1; + p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = false; + _tcscpy (p->floppyslots[0].df, _T("")); _tcscpy (p->floppyslots[1].df, _T("")); _tcscpy (p->floppyslots[2].df, _T("")); @@ -1797,10 +2040,12 @@ void default_prefs (struct uae_prefs *p, int type) _tcscpy (p->romfile, _T("kick.rom")); _tcscpy (p->romextfile, _T("")); + _tcscpy (p->flashfile, _T("")); sprintf (p->path_rom, _T("%s/kickstarts/"), start_path_data); sprintf (p->path_floppy, _T("%s/disks/"), start_path_data); sprintf (p->path_hardfile, _T("%s/"), start_path_data); + sprintf (p->path_cd, _T("%s/cd32/"), start_path_data); p->fpu_model = 0; p->cpu_model = 68000; @@ -1833,9 +2078,11 @@ void default_prefs (struct uae_prefs *p, int type) p->key_for_menu = SDLK_F12; p->key_for_input_switching = SDLK_F11; - target_default_options (p, type); - inputdevice_default_prefs (p); + + blkdev_default_prefs (p); + + target_default_options (p, type); } @@ -1981,3 +2228,50 @@ int bip_a4000 (struct uae_prefs *p, int rom) return configure_rom (p, roms, 0); } + + +int bip_cd32 (struct uae_prefs *p, int rom) +{ + int roms[2]; + + roms[0] = 64; + roms[1] = -1; + if (!configure_rom (p, roms, 0)) { + roms[0] = 18; + roms[1] = -1; + if (!configure_rom (p, roms, 0)) + return 0; + roms[0] = 19; + if (!configure_rom (p, roms, 0)) + return 0; + } +// if (config > 0) { +// roms[0] = 23; +// if (!configure_rom (p, roms, 0)) +// return 0; +// } + + p->cpu_model = 68020; + p->address_space_24 = 1; + p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE | CSMASK_AGA; + p->chipmem_size = 0x200000; + p->bogomem_size = 0; + p->m68k_speed = M68K_SPEED_14MHZ_CYCLES; + + p->cs_cd32c2p = 1; + p->cs_cd32cd = 1; + p->cs_cd32nvram = 1; + p->nr_floppies = 0; + p->floppyslots[0].dfxtype = DRV_NONE; + p->floppyslots[1].dfxtype = DRV_NONE; + fetch_datapath (p->flashfile, sizeof (p->flashfile) / sizeof (TCHAR)); + _tcscat (p->flashfile, _T("cd32.nvr")); + + p->cdslots[0].inuse = true; + p->cdslots[0].type = SCSI_UNIT_IMAGE; + + p->gfx_size.width = 384; + p->gfx_size.height = 256; + + return 1; +} diff --git a/src/cia.cpp b/src/cia.cpp index 178b3640..1c3181d2 100644 --- a/src/cia.cpp +++ b/src/cia.cpp @@ -22,6 +22,7 @@ #include "gui.h" #include "savestate.h" #include "inputdevice.h" +#include "akiko.h" #include "audio.h" #include "keyboard.h" @@ -50,7 +51,7 @@ static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed; static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm; static int ciaatlatch, ciabtlatch; -static bool oldled, oldovl; +static bool oldled, oldovl, oldcd32mute; static unsigned int ciabpra; @@ -512,6 +513,10 @@ static void bfe001_change (void) map_overlay (0); } } + if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) { + oldcd32mute = v & 1; + akiko_mute (oldcd32mute ? 0 : 1); + } } static uae_u8 ReadCIAA (unsigned int addr) @@ -528,7 +533,11 @@ static uae_u8 ReadCIAA (unsigned int addr) tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03; return tmp; case 1: - tmp = ciaaprb; +#ifdef INPUTDEVICE_SIMPLE + tmp = (ciaaprb & ciaadrb) | (ciaadrb ^ 0xff); +#else + tmp = handle_parport_joystick (0, ciaaprb, ciaadrb); +#endif if (ciaacrb & 2) { int pb7 = 0; if (ciaacrb & 4) @@ -600,7 +609,12 @@ static uae_u8 ReadCIAB (unsigned int addr) switch (reg) { case 0: +#ifdef INPUTDEVICE_SIMPLE + tmp = ((ciabpra & ciabdra) | (ciabdra ^ 0xff)) & 0x7; +#else tmp = 0; + tmp |= handle_parport_joystick (1, ciabpra, ciabdra); +#endif return tmp; case 1: tmp = ciabprb; @@ -678,6 +692,7 @@ static void WriteCIAA (uae_u16 addr,uae_u8 val) case 0: ciaapra = (ciaapra & ~0xc3) | (val & 0xc3); bfe001_change (); + handle_cd32_joystick_cia (ciaapra, ciaadra); break; case 1: ciaaprb = val; @@ -914,6 +929,7 @@ void CIA_reset (void) #endif kblostsynccnt = 0; oldovl = 1; + oldcd32mute = 1; oldled = true; if (!savestate_state) { @@ -942,6 +958,13 @@ void CIA_reset (void) oldovl = false; } } +#ifdef CD32 + if (!isrestore ()) { + akiko_reset (); + if (!akiko_init ()) + currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = 0; + } +#endif } /* CIA memory access */ diff --git a/src/custom.cpp b/src/custom.cpp index fc278b67..9c37a2c7 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -32,6 +32,8 @@ #include "gui.h" #include "picasso96.h" #include "drawing.h" +#include "akiko.h" +#include "blkdev.h" #define SPR0_HPOS 0x15 #define MAX_SPRITES 8 @@ -50,7 +52,7 @@ static int frh_count = 0; #define SPEEDUP_CYCLES_HAM 1000 #define SPEEDUP_TIMELIMIT_JIT -1000 #define SPEEDUP_TIMELIMIT_NONJIT -2000 -#define SPEEDUP_TIMELIMIT_HAM -6500 +#define SPEEDUP_TIMELIMIT_HAM -4000 int pissoff_value = SPEEDUP_CYCLES_JIT * CYCLE_UNIT; int speedup_timelimit = SPEEDUP_TIMELIMIT_JIT; @@ -58,7 +60,7 @@ static int rpt_did_reset; struct ev eventtab[ev_max]; struct ev2 eventtab2[ev2_max]; -static int vpos; +int vpos; static int vpos_count, vpos_count_diff; static int lof_store; // real bit in custom registers static int lof_current; // what display device thinks @@ -2213,6 +2215,11 @@ void compute_vsynctime (void) update_sound (vblank_hz, (bplcon0 & 4) ? -1 : lof_store); } +int current_maxvpos (void) +{ + return maxvpos + (lof_store ? 1 : 0); +} + static void compute_framesync (void) { if (abs (vblank_hz - 50) < 1 || abs (vblank_hz - 60) < 1) { @@ -2730,6 +2737,9 @@ void INTREQ (uae_u16 data) { INTREQ_0 (data); rethink_cias (); +#ifdef CD32 + rethink_akiko (); +#endif } static void ADKCON (int hpos, uae_u16 v) @@ -4063,6 +4073,7 @@ static void vsync_handler_pre (void) picasso_handle_vsync (); #endif + blkdev_vsync (); CIA_vsync_prehandler(); if (quit_program > 0) { @@ -4076,7 +4087,6 @@ static void vsync_handler_pre (void) timehack_alive--; inputdevice_vsync (); - filesys_vsync (); vsync_handle_redraw (); @@ -4282,6 +4292,10 @@ static void hsync_handler_pre (bool onvsync) hsync_record_line_state (next_lineno); } +#ifdef CD32 + AKIKO_hsync_handler (); +#endif + #ifdef PICASSO96 picasso_handle_hsync (); #endif @@ -5170,8 +5184,8 @@ uae_u8 *restore_custom (uae_u8 *src) RW; /* 004 VPOSR */ RW; /* 006 VHPOSR */ RW; /* 008 DSKDATR (dummy register) */ - RW; /* 00A JOY0DAT */ - RW; /* 00C JOY1DAT */ + JOYSET(0, RW); /* 00A JOY0DAT */ + JOYSET(1, RW); /* 00C JOY1DAT */ clxdat = RW; /* 00E CLXDAT */ RW; /* 010 ADKCONR -> see 09E */ RW; /* 012 POT0DAT */ @@ -5323,8 +5337,8 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full) SW (VPOSR()); /* 004 VPOSR */ SW (VHPOSR()); /* 006 VHPOSR */ SW (0); /* 008 DSKDATR */ - SW (JOY0DAT()); /* 00A JOY0DAT */ - SW (JOY1DAT()); /* 00C JOY1DAT */ + SW (JOYGET (0)); /* 00A JOY0DAT */ + SW (JOYGET (1)); /* 00C JOY1DAT */ SW (clxdat | 0x8000); /* 00E CLXDAT */ SW (ADKCONR()); /* 010 ADKCONR */ SW (POT0DAT()); /* 012 POT0DAT */ @@ -5523,6 +5537,39 @@ uae_u8 *save_custom_sprite(int num, int *len, uae_u8 *dstptr) return dstbak; } +uae_u8 *restore_custom_extra (uae_u8 *src) +{ + uae_u32 v = restore_u32 (); + + if (!(v & 1)) + v = 0; + + currprefs.cs_cd32c2p = changed_prefs.cs_cd32c2p = RBB; + currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = RBB; + currprefs.cs_cd32nvram = changed_prefs.cs_cd32nvram = RBB; + + return src; +} + +uae_u8 *save_custom_extra (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + + SL (1); + + SB (currprefs.cs_cd32c2p); + SB (currprefs.cs_cd32cd); + SB (currprefs.cs_cd32nvram); + + *len = dst - dstbak; + return dstbak; +} + #endif /* SAVESTATE */ void check_prefs_changed_custom (void) @@ -5533,6 +5580,9 @@ void check_prefs_changed_custom (void) currprefs.immediate_blits = changed_prefs.immediate_blits; currprefs.collision_level = changed_prefs.collision_level; currprefs.fast_copper = changed_prefs.fast_copper; + currprefs.cs_cd32cd = changed_prefs.cs_cd32cd; + currprefs.cs_cd32c2p = changed_prefs.cs_cd32c2p; + currprefs.cs_cd32nvram = changed_prefs.cs_cd32nvram; if (currprefs.chipset_mask != changed_prefs.chipset_mask || currprefs.ntscmode != changed_prefs.ntscmode) { diff --git a/src/drawing.cpp b/src/drawing.cpp index 267276f1..a4c25679 100644 --- a/src/drawing.cpp +++ b/src/drawing.cpp @@ -80,7 +80,7 @@ extern SDL_Surface *prSDLScreen; to contain two 16 bit words, with the appropriate mask if pf1 is in the foreground being at bit offset 0, the one used if pf2 is in front being at offset 16. */ -static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256]; +static int dblpf_ms1[256], dblpf_ms2[256]; static int dblpf_ind1[256], dblpf_ind2[256]; static int dblpf_2nd1[256], dblpf_2nd2[256]; @@ -129,7 +129,7 @@ uae_u16 spixels[MAX_SPR_PIXELS]; /* Eight bits for every pixel. */ union sps_union spixstate; -static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE * 2]; +static uae_u16 ham_linebuf[MAX_PIXELS_PER_LINE * 2]; uae_u8 *xlinebuffer; @@ -169,6 +169,7 @@ static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt; static int bplres; static int plf1pri, plf2pri, bplxor; static uae_u32 plf_sprite_mask; +static uae_u32 plf_sprite_mask_n16; static int sbasecol[2] = { 16, 16 }; bool picasso_requested_on; @@ -349,8 +350,8 @@ static void pfield_do_fill_line_0(int start, int stop) *b = col; } -static line_draw_func pfield_do_linetoscr=(line_draw_func)pfield_do_linetoscr_0; -static line_draw_func pfield_do_fill_line=(line_draw_func)pfield_do_fill_line_0; +static line_draw_func pfield_do_linetoscr = (line_draw_func)pfield_do_linetoscr_0; +static line_draw_func pfield_do_fill_line = (line_draw_func)pfield_do_fill_line_0; /* Initialize the variables necessary for drawing a line. * This involves setting up start/stop positions and display window @@ -398,17 +399,12 @@ static void pfield_init_linetoscr (void) playfield_end = visible_right_border; if (sprite_first_x < sprite_last_x) { -// if (sprite_first_x < 0) -// sprite_first_x = 0; -// if (sprite_last_x >= MAX_PIXELS_PER_LINE - 1) -// sprite_last_x = MAX_PIXELS_PER_LINE - 2; -// if (sprite_first_x < sprite_last_x) { - uae_u8 *p = spritepixels + sprite_first_x; - int len = sprite_last_x - sprite_first_x + 1; - int i; - /* clear previous sprite data storage line */ - memset (p, 0, len); -// } + uae_u8 *p = spritepixels + sprite_first_x; + int len = sprite_last_x - sprite_first_x + 1; + int i; + /* clear previous sprite data storage line */ + memset (p, 0, len); + sprite_last_x = 0; sprite_first_x = MAX_PIXELS_PER_LINE - 1; } @@ -465,8 +461,59 @@ static void dummy_worker (int start, int stop) { } + +STATIC_INLINE int DECODE_HAM8_1(int col, int pv) +{ + __asm__ __volatile__ ( + "ubfx %[pv], %[pv], #3, #5 \n\t" + "bfi %[col], %[pv], #0, #5 \n\t" + : [col] "+r" (col) , [pv] "+r" (pv) ); + return col; +} +STATIC_INLINE int DECODE_HAM8_2(int col, int pv) +{ + __asm__ __volatile__ ( + "ubfx %[pv], %[pv], #3, #5 \n\t" + "bfi %[col], %[pv], #11, #5 \n\t" + : [col] "+r" (col) , [pv] "+r" (pv) ); + return col; +} +STATIC_INLINE int DECODE_HAM8_3(int col, int pv) +{ + __asm__ __volatile__ ( + "ubfx %[pv], %[pv], #2, #6 \n\t" + "bfi %[col], %[pv], #5, #6 \n\t" + : [col] "+r" (col) , [pv] "+r" (pv) ); + return col; +} + +STATIC_INLINE int DECODE_HAM6_1(int col, int pv) +{ + __asm__ __volatile__ ( + "lsl %[pv], %[pv], #1 \n\t" + "bfi %[col], %[pv], #0, #5 \n\t" + : [col] "+r" (col) , [pv] "+r" (pv) ); + return (col); +} +STATIC_INLINE int DECODE_HAM6_2(int col, int pv) +{ + __asm__ __volatile__ ( + "lsl %[pv], %[pv], #1 \n\t" + "bfi %[col], %[pv], #11, #5 \n\t" + : [col] "+r" (col) , [pv] "+r" (pv) ); + return (col); +} +STATIC_INLINE int DECODE_HAM6_3(int col, int pv) +{ + __asm__ __volatile__ ( + "lsl %[pv], %[pv], #2 \n\t" + "bfi %[col], %[pv], #5, #6 \n\t" + : [col] "+r" (col) , [pv] "+r" (pv) ); + return (col); +} + static int ham_decode_pixel; -static unsigned int ham_lastcolor; +static uae_u16 ham_lastcolor; /* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER), * but don't draw anything in. This is done to prepare HAM_LASTCOLOR for later, @@ -478,15 +525,15 @@ static void init_ham_decoding (void) int unpainted_amiga = unpainted; ham_decode_pixel = ham_src_pixel; - ham_lastcolor = color_reg_get (&colors_for_drawing, 0); + ham_lastcolor = colors_for_drawing.acolors[0]; if (!bplham) { if (unpainted_amiga > 0) { int pv = pixdata.apixels[ham_decode_pixel + unpainted_amiga - 1]; if (currprefs.chipset_mask & CSMASK_AGA) - ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor]; + ham_lastcolor = colors_for_drawing.acolors[pv ^ bplxor]; else - ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; + ham_lastcolor = colors_for_drawing.acolors[pv]; } } else if (currprefs.chipset_mask & CSMASK_AGA) { if (bplplanecnt >= 7) { /* AGA mode HAM8 */ @@ -494,10 +541,10 @@ static void init_ham_decoding (void) int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor; switch (pv & 0x3) { - case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; - case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; - case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; - case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; + case 0x0: ham_lastcolor = colors_for_drawing.acolors[pv >> 2]; break; + case 0x1: ham_lastcolor = DECODE_HAM8_1(ham_lastcolor, pv); break; + case 0x2: ham_lastcolor = DECODE_HAM8_2(ham_lastcolor, pv); break; + case 0x3: ham_lastcolor = DECODE_HAM8_3(ham_lastcolor, pv); break; } } } else { /* AGA mode HAM6 */ @@ -505,10 +552,10 @@ static void init_ham_decoding (void) int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor; switch (pv & 0x30) { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; - case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; - case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; - case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; + case 0x00: ham_lastcolor = colors_for_drawing.acolors[pv]; break; + case 0x10: ham_lastcolor = DECODE_HAM6_1(ham_lastcolor, pv); break; + case 0x20: ham_lastcolor = DECODE_HAM6_2(ham_lastcolor, pv); break; + case 0x30: ham_lastcolor = DECODE_HAM6_3(ham_lastcolor, pv); break; } } } @@ -518,10 +565,10 @@ static void init_ham_decoding (void) int pv = pixdata.apixels[ham_decode_pixel++]; switch (pv & 0x30) { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; - case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; - case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; - case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + case 0x00: ham_lastcolor = colors_for_drawing.acolors[pv]; break; + case 0x10: ham_lastcolor = DECODE_HAM6_1(ham_lastcolor, pv); break; + case 0x20: ham_lastcolor = DECODE_HAM6_2(ham_lastcolor, pv); break; + case 0x30: ham_lastcolor = DECODE_HAM6_3(ham_lastcolor, pv); break; } } } @@ -536,9 +583,9 @@ static void decode_ham (int pix, int stoppos) while (todraw_amiga-- > 0) { int pv = pixdata.apixels[ham_decode_pixel]; if (currprefs.chipset_mask & CSMASK_AGA) - ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor]; + ham_lastcolor = colors_for_drawing.acolors[pv ^ bplxor]; else - ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; + ham_lastcolor = colors_for_drawing.acolors[pv]; ham_linebuf[ham_decode_pixel++] = ham_lastcolor; } @@ -548,10 +595,10 @@ static void decode_ham (int pix, int stoppos) int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor; switch (pv & 0x3) { - case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; - case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; - case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; - case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; + case 0x0: ham_lastcolor = colors_for_drawing.acolors[pv >> 2]; break; + case 0x1: ham_lastcolor = DECODE_HAM8_1(ham_lastcolor, pv); break; + case 0x2: ham_lastcolor = DECODE_HAM8_2(ham_lastcolor, pv); break; + case 0x3: ham_lastcolor = DECODE_HAM8_3(ham_lastcolor, pv); break; } ham_linebuf[ham_decode_pixel++] = ham_lastcolor; } @@ -560,10 +607,10 @@ static void decode_ham (int pix, int stoppos) int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor; switch (pv & 0x30) { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; - case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; - case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; - case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; + case 0x00: ham_lastcolor = colors_for_drawing.acolors[pv]; break; + case 0x10: ham_lastcolor = DECODE_HAM6_1(ham_lastcolor, pv); break; + case 0x20: ham_lastcolor = DECODE_HAM6_2(ham_lastcolor, pv); break; + case 0x30: ham_lastcolor = DECODE_HAM6_3(ham_lastcolor, pv); break; } ham_linebuf[ham_decode_pixel++] = ham_lastcolor; } @@ -574,10 +621,10 @@ static void decode_ham (int pix, int stoppos) int pv = pixdata.apixels[ham_decode_pixel]; switch (pv & 0x30) { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; - case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; - case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; - case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + case 0x00: ham_lastcolor = colors_for_drawing.acolors[pv]; break; + case 0x10: ham_lastcolor = DECODE_HAM6_1(ham_lastcolor, pv); break; + case 0x20: ham_lastcolor = DECODE_HAM6_2(ham_lastcolor, pv); break; + case 0x30: ham_lastcolor = DECODE_HAM6_3(ham_lastcolor, pv); break; } ham_linebuf[ham_decode_pixel++] = ham_lastcolor; } @@ -602,7 +649,6 @@ static void gen_pfield_tables (void) dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0; dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8; - dblpf_ms[i] = i == 0 ? 16 : 8; if (plane2 > 0) plane2 += 8; dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1); @@ -646,7 +692,6 @@ static void gen_pfield_tables (void) static void draw_sprites_normal_sp_lo_nat(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; int pos, window_pos; @@ -656,12 +701,10 @@ static void draw_sprites_normal_sp_lo_nat(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; col = sprite_col_nat[v] + 16; @@ -673,7 +716,6 @@ static void draw_sprites_normal_sp_lo_nat(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_ham_lo_nat(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; int pos, window_pos; @@ -683,16 +725,14 @@ static void draw_sprites_normal_ham_lo_nat(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; col = sprite_col_nat[v] + 16; - ham_linebuf[window_pos] = color_reg_get (&colors_for_drawing, col); + ham_linebuf[window_pos] = colors_for_drawing.acolors[col]; } window_pos++; } @@ -728,7 +768,6 @@ static void draw_sprites_normal_dp_lo_nat(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_sp_lo_at(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; uae_u8 *stbuf = spixstate.bytes + e->first_pixel; int pos, window_pos; @@ -740,12 +779,10 @@ static void draw_sprites_normal_sp_lo_at(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; int offs; @@ -763,7 +800,6 @@ static void draw_sprites_normal_sp_lo_at(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_ham_lo_at(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; uae_u8 *stbuf = spixstate.bytes + e->first_pixel; int pos, window_pos; @@ -775,12 +811,10 @@ static void draw_sprites_normal_ham_lo_at(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; int offs; @@ -790,7 +824,7 @@ static void draw_sprites_normal_ham_lo_at(struct sprite_entry *_GCCRES_ e) } else { col = sprite_col_nat[v] + 16; } - ham_linebuf[window_pos] = color_reg_get (&colors_for_drawing, col); + ham_linebuf[window_pos] = colors_for_drawing.acolors[col]; } window_pos++; } @@ -833,7 +867,6 @@ static void draw_sprites_normal_dp_lo_at(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_sp_hi_nat(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; int pos, window_pos; @@ -844,12 +877,10 @@ static void draw_sprites_normal_sp_hi_nat(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos ++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; col = sprite_col_nat[v] + 16; @@ -861,7 +892,6 @@ static void draw_sprites_normal_sp_hi_nat(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_ham_hi_nat(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; int pos, window_pos; @@ -872,17 +902,15 @@ static void draw_sprites_normal_ham_hi_nat(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos ++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; col = sprite_col_nat[v] + 16; col = col | (col << 8); - ham_linebuf[window_pos >> 1] = color_reg_get (&colors_for_drawing, col); + ham_linebuf[window_pos >> 1] = colors_for_drawing.acolors[col]; } window_pos += 2; } @@ -919,7 +947,6 @@ static void draw_sprites_normal_dp_hi_nat(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_sp_hi_at(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; uae_u8 *stbuf = spixstate.bytes + e->first_pixel; int pos, window_pos; @@ -932,12 +959,10 @@ static void draw_sprites_normal_sp_hi_at(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; int offs; @@ -955,7 +980,6 @@ static void draw_sprites_normal_sp_hi_at(struct sprite_entry *_GCCRES_ e) static void draw_sprites_normal_ham_hi_at(struct sprite_entry *_GCCRES_ e) { - int *shift_lookup = dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; uae_u8 *stbuf = spixstate.bytes + e->first_pixel; int pos, window_pos; @@ -968,12 +992,10 @@ static void draw_sprites_normal_ham_hi_at(struct sprite_entry *_GCCRES_ e) window_pos += pixels_offset; unsigned max=e->max; for (pos = e->pos; pos < max; pos++) { - int maskshift, plfmask; unsigned int v = buf[pos]; - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; if (v != 0) { unsigned int col; int offs; @@ -984,7 +1006,7 @@ static void draw_sprites_normal_ham_hi_at(struct sprite_entry *_GCCRES_ e) col = sprite_col_nat[v] + 16; } col = col | (col << 8); - ham_linebuf[window_pos >> 1] = color_reg_get (&colors_for_drawing, col); + ham_linebuf[window_pos >> 1] = colors_for_drawing.acolors[col]; } window_pos += 2; } @@ -1049,10 +1071,8 @@ static draw_sprites_func *draw_sprites_punt = draw_sprites_sp_lo; that many of the if statements will go away completely after inlining. */ /* NOTE: This function is called for AGA modes *only* */ -STATIC_INLINE void draw_sprites_aga_1 (struct sprite_entry *e, const int ham, const int dualpf, - const int doubling, const int skip, const int has_attach) +STATIC_INLINE void draw_sprites_aga_ham (struct sprite_entry *e, const int doubling, const int skip, const int has_attach) { - int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms; uae_u16 *buf = spixels + e->first_pixel; uae_u8 *stbuf = spixstate.bytes + e->first_pixel; int pos, window_pos; @@ -1067,82 +1087,162 @@ STATIC_INLINE void draw_sprites_aga_1 (struct sprite_entry *e, const int ham, co window_pos <<= 1; window_pos += pixels_offset; - if (dualpf && window_pos < sprite_first_x) + for (pos = e->pos; pos < e->max; pos += 1 << skip) { + unsigned int v = buf[pos]; + + if(v) { + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; + if (v != 0) { + unsigned int col; + int offs; + offs = sprite_bit[v]; + if (has_attach && (stbuf[pos] & offs)) { + col = sprite_col_at[v] + sbasecol[1]; + } else { + if(offs & 0x55) + col = sprite_col_nat[v] + sbasecol[0]; + else + col = sprite_col_nat[v] + sbasecol[1]; + } + + col = colors_for_drawing.acolors[col ^ bplxor]; + ham_linebuf[window_pos] = col; + if (doubling) + ham_linebuf[window_pos + 1] = col; + } + } + window_pos += 1 << doubling; + } +} + +STATIC_INLINE void draw_sprites_aga_dp (struct sprite_entry *e, const int doubling, const int skip, const int has_attach) +{ + int *shift_lookup = (bpldualpfpri ? dblpf_ms2 : dblpf_ms1); + uae_u16 *buf = spixels + e->first_pixel; + uae_u8 *stbuf = spixstate.bytes + e->first_pixel; + int pos, window_pos; + + buf -= e->pos; + stbuf -= e->pos; + + window_pos = e->pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res); + if (skip) + window_pos >>= 1; + else if (doubling) + window_pos <<= 1; + window_pos += pixels_offset; + + if (window_pos < sprite_first_x) sprite_first_x = window_pos; for (pos = e->pos; pos < e->max; pos += 1 << skip) { int maskshift, plfmask; unsigned int v = buf[pos]; - /* The value in the shift lookup table is _half_ the shift count we - need. This is because we can't shift 32 bits at once (undefined - behaviour in C). */ - maskshift = shift_lookup[pixdata.apixels[window_pos]]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; - if (v != 0) { - unsigned int col; - int offs; - offs = sprite_bit[v]; - if (has_attach && (stbuf[pos] & offs)) { - col = sprite_col_at[v] + sbasecol[1]; - } else { - if(offs & 0x55) - col = sprite_col_nat[v] + sbasecol[0]; - else - col = sprite_col_nat[v] + sbasecol[1]; - } - - if (dualpf) { - spritepixels[window_pos] = col; - if (doubling) - spritepixels[window_pos + 1] = col; - } else if (ham) { - col = color_reg_get (&colors_for_drawing, col); - col ^= bplxor; - ham_linebuf[window_pos] = col; - if (doubling) - ham_linebuf[window_pos + 1] = col; - } else { - col ^= bplxor; - if (doubling) - pixdata.apixels_w[window_pos >> 1] = col | (col << 8); - else - pixdata.apixels[window_pos] = col; - } - } - + if(v) { + /* The value in the shift lookup table is _half_ the shift count we + need. This is because we can't shift 32 bits at once (undefined + behaviour in C). */ + maskshift = shift_lookup[pixdata.apixels[window_pos]]; + plfmask = (plf_sprite_mask >> maskshift) >> maskshift; + v &= ~plfmask; + if (v != 0) { + unsigned int col; + int offs; + offs = sprite_bit[v]; + if (has_attach && (stbuf[pos] & offs)) { + col = sprite_col_at[v] + sbasecol[1]; + } else { + if(offs & 0x55) + col = sprite_col_nat[v] + sbasecol[0]; + else + col = sprite_col_nat[v] + sbasecol[1]; + } + + spritepixels[window_pos] = col; + if (doubling) + spritepixels[window_pos + 1] = col; + } + } + window_pos += 1 << doubling; } - if (dualpf && window_pos > sprite_last_x) + if (window_pos > sprite_last_x) sprite_last_x = window_pos; } -// ENTRY, ham, dualpf, doubling, skip, has_attach -STATIC_INLINE void draw_sprites_aga_sp_lo_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 0, 0, 1, 0); } -STATIC_INLINE void draw_sprites_aga_dp_lo_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 1, 0, 1, 0); } -STATIC_INLINE void draw_sprites_aga_ham_lo_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 1, 0, 0, 1, 0); } +STATIC_INLINE void draw_sprites_aga_sp (struct sprite_entry *e, const int doubling, const int skip, const int has_attach) +{ + uae_u16 *buf = spixels + e->first_pixel; + uae_u8 *stbuf = spixstate.bytes + e->first_pixel; + int pos, window_pos; -STATIC_INLINE void draw_sprites_aga_sp_lo_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 0, 0, 1, 1); } -STATIC_INLINE void draw_sprites_aga_dp_lo_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 1, 0, 1, 1); } -STATIC_INLINE void draw_sprites_aga_ham_lo_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 1, 0, 0, 1, 1); } + buf -= e->pos; + stbuf -= e->pos; -STATIC_INLINE void draw_sprites_aga_sp_hi_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 0, 0, 0, 0); } -STATIC_INLINE void draw_sprites_aga_dp_hi_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 1, 0, 0, 0); } -STATIC_INLINE void draw_sprites_aga_ham_hi_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 1, 0, 0, 0, 0); } + window_pos = e->pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res); + if (skip) + window_pos >>= 1; + else if (doubling) + window_pos <<= 1; + window_pos += pixels_offset; -STATIC_INLINE void draw_sprites_aga_sp_hi_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 0, 0, 0, 1); } -STATIC_INLINE void draw_sprites_aga_dp_hi_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 1, 0, 0, 1); } -STATIC_INLINE void draw_sprites_aga_ham_hi_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 1, 0, 0, 0, 1); } + for (pos = e->pos; pos < e->max; pos += 1 << skip) { + unsigned int v = buf[pos]; -STATIC_INLINE void draw_sprites_aga_sp_shi_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 0, 1, 0, 0); } -STATIC_INLINE void draw_sprites_aga_dp_shi_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 1, 1, 0, 0); } -STATIC_INLINE void draw_sprites_aga_ham_shi_nat(struct sprite_entry *e) { draw_sprites_aga_1 (e, 1, 0, 1, 0, 0); } + if(v) { + if(pixdata.apixels[window_pos]) + v &= plf_sprite_mask_n16; + if (v != 0) { + unsigned int col; + int offs; + offs = sprite_bit[v]; + if (has_attach && (stbuf[pos] & offs)) { + col = sprite_col_at[v] + sbasecol[1]; + } else { + if(offs & 0x55) + col = sprite_col_nat[v] + sbasecol[0]; + else + col = sprite_col_nat[v] + sbasecol[1]; + } + + col ^= bplxor; + if (doubling) + pixdata.apixels_w[window_pos >> 1] = col | (col << 8); + else + pixdata.apixels[window_pos] = col; + } + } + window_pos += 1 << doubling; + } +} -STATIC_INLINE void draw_sprites_aga_sp_shi_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 0, 1, 0, 1); } -STATIC_INLINE void draw_sprites_aga_dp_shi_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 0, 1, 1, 0, 1); } -STATIC_INLINE void draw_sprites_aga_ham_shi_at(struct sprite_entry *e) { draw_sprites_aga_1 (e, 1, 0, 1, 0, 1); } +// ENTRY, doubling, skip, has_attach +static void draw_sprites_aga_sp_lo_nat(struct sprite_entry *e) { draw_sprites_aga_sp (e, 0, 1, 0); } +static void draw_sprites_aga_dp_lo_nat(struct sprite_entry *e) { draw_sprites_aga_dp (e, 0, 1, 0); } +static void draw_sprites_aga_ham_lo_nat(struct sprite_entry *e) { draw_sprites_aga_ham (e, 0, 1, 0); } + +static void draw_sprites_aga_sp_lo_at(struct sprite_entry *e) { draw_sprites_aga_sp (e, 0, 1, 1); } +static void draw_sprites_aga_dp_lo_at(struct sprite_entry *e) { draw_sprites_aga_dp (e, 0, 1, 1); } +static void draw_sprites_aga_ham_lo_at(struct sprite_entry *e) { draw_sprites_aga_ham (e, 0, 1, 1); } + +static void draw_sprites_aga_sp_hi_nat(struct sprite_entry *e) { draw_sprites_aga_sp (e, 0, 0, 0); } +static void draw_sprites_aga_dp_hi_nat(struct sprite_entry *e) { draw_sprites_aga_dp (e, 0, 0, 0); } +static void draw_sprites_aga_ham_hi_nat(struct sprite_entry *e) { draw_sprites_aga_ham (e, 0, 0, 0); } + +static void draw_sprites_aga_sp_hi_at(struct sprite_entry *e) { draw_sprites_aga_sp (e, 0, 0, 1); } +static void draw_sprites_aga_dp_hi_at(struct sprite_entry *e) { draw_sprites_aga_dp (e, 0, 0, 1); } +static void draw_sprites_aga_ham_hi_at(struct sprite_entry *e) { draw_sprites_aga_ham (e, 0, 0, 1); } + +static void draw_sprites_aga_sp_shi_nat(struct sprite_entry *e) { draw_sprites_aga_sp (e, 1, 0, 0); } +static void draw_sprites_aga_dp_shi_nat(struct sprite_entry *e) { draw_sprites_aga_dp (e, 1, 0, 0); } +static void draw_sprites_aga_ham_shi_nat(struct sprite_entry *e) { draw_sprites_aga_ham (e, 1, 0, 0); } + +static void draw_sprites_aga_sp_shi_at(struct sprite_entry *e) { draw_sprites_aga_sp (e, 1, 0, 1); } +static void draw_sprites_aga_dp_shi_at(struct sprite_entry *e) { draw_sprites_aga_dp (e, 1, 0, 1); } +static void draw_sprites_aga_ham_shi_at(struct sprite_entry *e) { draw_sprites_aga_ham (e, 1, 0, 1); } static draw_sprites_func draw_sprites_aga_sp_lo[2]={ draw_sprites_aga_sp_lo_nat, draw_sprites_aga_sp_lo_at }; @@ -1565,6 +1665,7 @@ static void pfield_expand_dp_bplcon (void) plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7; plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri); plf_sprite_mask |= (0x0000FFFF << (4 * plf1pri)) & 0xFFFF; + plf_sprite_mask_n16 = ~(plf_sprite_mask >> 16); bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400; bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40; } @@ -1642,9 +1743,26 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun int lastpos = visible_left_border; int endpos = visible_right_border; + if(dip_for_drawing->nr_color_changes == 0) { + // No changes in line -> simple mode + if (lastpos < playfield_start) { + int t = endpos <= playfield_start ? endpos : playfield_start; + (*worker_border) (lastpos, t); + lastpos = t; + } + if (lastpos >= playfield_start && lastpos < playfield_end) { + int t = endpos <= playfield_end ? endpos : playfield_end; + (*worker_pfield) (lastpos, t); + lastpos = t; + } + if (endpos > lastpos) { + if (lastpos >= playfield_end) + (*worker_border) (lastpos, endpos); + } + return; + } + for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { - int regno = curr_color_changes[i].regno; - unsigned int value = curr_color_changes[i].value; int nextpos, nextpos_in_range; if (i == dip_for_drawing->last_color_change) nextpos = endpos; @@ -1675,6 +1793,8 @@ STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_fun lastpos = nextpos_in_range; } if (i != dip_for_drawing->last_color_change) { + int regno = curr_color_changes[i].regno; + unsigned int value = curr_color_changes[i].value; if (regno >= 0x1000) { pfield_expand_dp_bplconx (regno, value); } else { diff --git a/src/expansion.cpp b/src/expansion.cpp index 28d252f5..eb5d5bb6 100644 --- a/src/expansion.cpp +++ b/src/expansion.cpp @@ -1047,6 +1047,17 @@ void expamem_reset (void) card_map[cardno++] = expamem_map_fastcard; } +#ifdef CD32 + if (currprefs.cs_cd32cd && currprefs.fastmem_size == 0 && currprefs.chipmem_size <= 0x200000) { + int ids[] = { 23, -1 }; + //struct romlist *rl = getromlistbyids (ids); + //if (rl && !_tcscmp (rl->path, currprefs.cartfile)) { + // card_name[cardno] = _T("CD32MPEG"); + // card_init[cardno] = expamem_init_cd32fmv; + // card_map[cardno++] = expamem_map_cd32fmv; + //} + } +#endif #ifdef FILESYS if (do_mount) { card_name[cardno] = _T("UAEFS"); diff --git a/src/include/akiko.h b/src/include/akiko.h new file mode 100644 index 00000000..0ce3c5f9 --- /dev/null +++ b/src/include/akiko.h @@ -0,0 +1,15 @@ + + +#define AKIKO_BASE 0xb80000 +#define AKIKO_BASE_END 0xb80100 /* ?? */ + +extern void akiko_reset (void); +extern int akiko_init (void); +extern void akiko_free (void); + +extern void AKIKO_hsync_handler (void); +extern void akiko_mute (int); + +extern uae_u8 *extendedkickmemory; + +extern void rethink_akiko (void); diff --git a/src/include/blkdev.h b/src/include/blkdev.h new file mode 100644 index 00000000..32fc258b --- /dev/null +++ b/src/include/blkdev.h @@ -0,0 +1,205 @@ + +#define DEVICE_SCSI_BUFSIZE (65536 - 1024) + +#define SCSI_UNIT_DISABLED -1 +#define SCSI_UNIT_DEFAULT 0 +#define SCSI_UNIT_IMAGE 1 +//#define SCSI_UNIT_IOCTL 2 +//#define SCSI_UNIT_SPTI 3 +//#define SCSI_UNIT_ASPI 4 + +//#define device_debug write_log +#define device_debug + +#define INQ_DASD 0x00 /* Direct-access device (disk) */ +#define INQ_SEQD 0x01 /* Sequential-access device (tape) */ +#define INQ_PRTD 0x02 /* Printer device */ +#define INQ_PROCD 0x03 /* Processor device */ +#define INQ_OPTD 0x04 /* Write once device (optical disk) */ +#define INQ_WORM 0x04 /* Write once device (optical disk) */ +#define INQ_ROMD 0x05 /* CD-ROM device */ +#define INQ_SCAN 0x06 /* Scanner device */ +#define INQ_OMEM 0x07 /* Optical Memory device */ +#define INQ_JUKE 0x08 /* Medium Changer device (jukebox) */ +#define INQ_COMM 0x09 /* Communications device */ +#define INQ_IT8_1 0x0A /* IT8 */ +#define INQ_IT8_2 0x0B /* IT8 */ +#define INQ_STARR 0x0C /* Storage array device */ +#define INQ_ENCL 0x0D /* Enclosure services device */ +#define INQ_NODEV 0x1F /* Unknown or no device */ +#define INQ_NOTPR 0x1F /* Logical unit not present (SCSI-1) */ + +#define MAX_TOC_ENTRIES 103 +struct cd_toc +{ + uae_u8 adr, control; + uae_u8 tno; + uae_u8 point; + uae_u8 track; + int address; // LSN + int paddress; // LSN + uae_u8 zero; + uae_u8 crc[2]; +}; +struct cd_toc_head +{ + int first_track, first_track_offset; + int last_track, last_track_offset; + int lastaddress; // LSN + int tracks; + int points; + struct cd_toc toc[MAX_TOC_ENTRIES]; +}; + +#define SUB_ENTRY_SIZE 12 +#define SUB_CHANNEL_SIZE 96 +#define SUBQ_SIZE (4 + 12) + +#define AUDIO_STATUS_NOT_SUPPORTED 0x00 +#define AUDIO_STATUS_IN_PROGRESS 0x11 +#define AUDIO_STATUS_PAUSED 0x12 +#define AUDIO_STATUS_PLAY_COMPLETE 0x13 +#define AUDIO_STATUS_PLAY_ERROR 0x14 +#define AUDIO_STATUS_NO_STATUS 0x15 + +struct device_info { + bool open; + int type; + int media_inserted; + int removable; + int write_protected; + int cylinders; + int trackspercylinder; + int sectorspertrack; + int bytespersector; + int bus, target, lun; + int unitnum; + TCHAR label[MAX_DPATH]; + TCHAR mediapath[MAX_DPATH]; + TCHAR vendorid[10]; + TCHAR productid[18]; + TCHAR revision[6]; + TCHAR *backend; + struct cd_toc_head toc; +}; + +struct amigascsi +{ + uae_u8 *data; + uae_s32 len; + uae_u8 cmd[16]; + uae_s32 cmd_len; + uae_u8 flags; + uae_u8 sensedata[256]; + uae_u16 sense_len; + uae_u16 cmdactual; + uae_u8 status; + uae_u16 actual; + uae_u16 sactual; +}; + +typedef int (*check_bus_func)(int flags); +typedef int (*open_bus_func)(int flags); +typedef void (*close_bus_func)(void); +typedef int (*open_device_func)(int, const TCHAR*, int); +typedef void (*close_device_func)(int); +typedef struct device_info* (*info_device_func)(int, struct device_info*, int); +typedef uae_u8* (*execscsicmd_out_func)(int, uae_u8*, int); +typedef uae_u8* (*execscsicmd_in_func)(int, uae_u8*, int, int*); +typedef int (*execscsicmd_direct_func)(int, struct amigascsi*); + +typedef void (*play_subchannel_callback)(uae_u8*, int); +typedef int (*play_status_callback)(int); + +typedef int (*pause_func)(int, int); +typedef int (*stop_func)(int); +typedef int (*play_func)(int, int, int, int, play_status_callback, play_subchannel_callback); +typedef uae_u32 (*volume_func)(int, uae_u16, uae_u16); +typedef int (*qcode_func)(int, uae_u8*, int); +typedef int (*toc_func)(int, struct cd_toc_head*); +typedef int (*read_func)(int, uae_u8*, int, int); +typedef int (*rawread_func)(int, uae_u8*, int, int, int, uae_u32); +typedef int (*write_func)(int, uae_u8*, int, int); +typedef int (*isatapi_func)(int); +typedef int (*ismedia_func)(int, int); +typedef int (*scsiemu_func)(int, uae_u8*); + +struct device_functions { + const TCHAR *name; + open_bus_func openbus; + close_bus_func closebus; + open_device_func opendev; + close_device_func closedev; + info_device_func info; + execscsicmd_out_func exec_out; + execscsicmd_in_func exec_in; + execscsicmd_direct_func exec_direct; + + pause_func pause; + stop_func stop; + play_func play; + volume_func volume; + qcode_func qcode; + toc_func toc; + read_func read; + rawread_func rawread; + write_func write; + + isatapi_func isatapi; + ismedia_func ismedia; + + scsiemu_func scsiemu; + +}; + +//extern struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES]; + +extern int device_func_init(int flags); +extern void device_func_reset(void); +extern int sys_command_open (int unitnum); +extern void sys_command_close (int unitnum); +extern int sys_command_isopen (int unitnum); +extern struct device_info *sys_command_info (int unitnum, struct device_info *di, int); +extern int sys_command_cd_pause (int unitnum, int paused); +extern void sys_command_cd_stop (int unitnum); +extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int); +extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc); +extern uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right); +extern int sys_command_cd_qcode (int unitnum, uae_u8*); +extern int sys_command_cd_toc (int unitnum, struct cd_toc_head*); +extern int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size); +extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize); +extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u8 scsicmd9, uae_u8 subs); +extern int sys_command_read (int unitnum, uae_u8 *data, int block, int size); +extern int sys_command_write (int unitnum, uae_u8 *data, int block, int size); +extern int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as); +extern int sys_command_scsi_direct (int unitnum, uaecptr request); +extern int sys_command_ismedia (int unitnum, int quick); + +extern void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen); +extern void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen); + +extern void blkdev_vsync (void); + +extern int msf2lsn (int msf); +extern int lsn2msf (int lsn); +extern uae_u8 frombcd (uae_u8 v); +extern uae_u8 tobcd (uae_u8 v); +extern int fromlongbcd (uae_u8 *p); +extern void tolongbcd (uae_u8 *p, int v); + +extern void blkdev_default_prefs (struct uae_prefs *p); +extern void blkdev_fix_prefs (struct uae_prefs *p); +extern int isaudiotrack (struct cd_toc_head*, int block); +extern int isdatatrack (struct cd_toc_head*, int block); + +enum cd_standard_unit { CD_STANDARD_UNIT_DEFAULT, CD_STANDARD_UNIT_AUDIO, CD_STANDARD_UNIT_CDTV, CD_STANDARD_UNIT_CD32 }; + +extern int get_standard_cd_unit (enum cd_standard_unit csu); +extern void close_standard_cd_unit (int); +extern void blkdev_cd_change (int unitnum, const TCHAR *name); + +extern void blkdev_entergui (void); +extern void blkdev_exitgui (void); + +bool filesys_do_disk_change (int, bool); diff --git a/src/include/custom.h b/src/include/custom.h index 76fe6066..8f515288 100644 --- a/src/include/custom.h +++ b/src/include/custom.h @@ -38,6 +38,8 @@ extern unsigned long int hsync_counter; extern uae_u16 dmacon; extern uae_u16 intreq; +extern int vpos; + extern void update_copper (int until_hpos); STATIC_INLINE void do_copper (void) @@ -149,4 +151,6 @@ STATIC_INLINE int GET_PLANES(uae_u16 bplcon0) extern void fpscounter_reset (void); +extern int current_maxvpos (void); + #endif diff --git a/src/include/drawing.h b/src/include/drawing.h index 1664c789..a882fa92 100644 --- a/src/include/drawing.h +++ b/src/include/drawing.h @@ -4,8 +4,6 @@ * Copyright 1996-1998 Bernd Schmidt */ -#include "od-pandora/inputmode.h" - #define MAX_PLANES 8 /* According to the HRM, pixel data spends a couple of cycles somewhere in the chips diff --git a/src/include/gui.h b/src/include/gui.h index ae7c65ce..88f053c0 100644 --- a/src/include/gui.h +++ b/src/include/gui.h @@ -13,11 +13,10 @@ extern void gui_led (int, int); extern void gui_handle_events (void); extern void gui_filename (int, const TCHAR *); extern void gui_fps (int fps); -extern void gui_lock (void); -extern void gui_unlock (void); extern void gui_flicker_led (int, int, int); extern void gui_disk_image_change (int, const TCHAR *, bool writeprotected); extern unsigned int gui_ledstate; +extern void gui_display (int shortcut); extern bool no_gui; @@ -25,6 +24,9 @@ extern bool no_gui; #define HDLED_READ 1 #define HDLED_WRITE 2 +#define LED_CD_ACTIVE 1 +#define LED_CD_ACTIVE2 2 + #define LED_POWER 0 #define LED_DF0 1 #define LED_DF1 2 @@ -85,6 +87,10 @@ extern std::vector lstAvailableROMs; extern std::vector lstMRUDiskList; extern void AddFileToDiskList(const char *file, int moveToTop); +#define MAX_MRU_CDLIST 10 +extern std::vector lstMRUCDList; +extern void AddFileToCDList(const char *file, int moveToTop); + #define AMIGAWIDTH_COUNT 6 #define AMIGAHEIGHT_COUNT 6 extern const int amigawidth_values[AMIGAWIDTH_COUNT]; diff --git a/src/include/inputdevice.h b/src/include/inputdevice.h index 5e86316c..7bf0da63 100644 --- a/src/include/inputdevice.h +++ b/src/include/inputdevice.h @@ -7,38 +7,178 @@ * Copyright 2001-2002 Toni Wilen */ -extern void inputdevice_copyconfig (struct uae_prefs *src, struct uae_prefs *dst); -extern int inputdevice_config_change_test (void); +#define DIR_LEFT_BIT 0 +#define DIR_RIGHT_BIT 1 +#define DIR_UP_BIT 2 +#define DIR_DOWN_BIT 3 +#define DIR_LEFT (1 << DIR_LEFT_BIT) +#define DIR_RIGHT (1 << DIR_RIGHT_BIT) +#define DIR_UP (1 << DIR_UP_BIT) +#define DIR_DOWN (1 << DIR_DOWN_BIT) -extern int joy0button, joy1button; -extern int buttonstate[3]; +#define JOYBUTTON_1 0 /* fire/left mousebutton */ +#define JOYBUTTON_2 1 /* 2nd/right mousebutton */ +#define JOYBUTTON_3 2 /* 3rd/middle mousebutton */ +#define JOYBUTTON_CD32_PLAY 3 +#define JOYBUTTON_CD32_RWD 4 +#define JOYBUTTON_CD32_FFW 5 +#define JOYBUTTON_CD32_GREEN 6 +#define JOYBUTTON_CD32_YELLOW 7 +#define JOYBUTTON_CD32_RED 8 +#define JOYBUTTON_CD32_BLUE 9 -extern int buttonstate[3]; -static __inline__ uae_u8 handle_joystick_buttons (uae_u8 pra, uae_u8 dra) +#define IDTYPE_JOYSTICK 0 +#define IDTYPE_MOUSE 1 +#define IDTYPE_KEYBOARD 2 + +struct inputdevice_functions { + int (*init)(void); + void (*close)(void); + int (*acquire)(int,int); + void (*unacquire)(int); + void (*read)(void); + int (*get_num)(void); + TCHAR* (*get_friendlyname)(int); + TCHAR* (*get_uniquename)(int); + int (*get_widget_num)(int); + int (*get_widget_type)(int,int,TCHAR*,uae_u32*); + int (*get_widget_first)(int,int); + int (*get_flags)(int); +}; +extern struct inputdevice_functions inputdevicefunc_joystick; +extern struct inputdevice_functions inputdevicefunc_mouse; +extern struct inputdevice_functions inputdevicefunc_keyboard; + +struct uae_input_device_default_node { - uae_u8 but = 0; + int evt; + int flags; +}; - if (!(joy0button & 1)) - but |= 0x40; - if (!(joy1button & 1)) - but |= 0x80; - if (dra & 0x40) - but = (but & ~0x40) | (pra & 0x40); - if (dra & 0x80) - but = (but & ~0x80) | (pra & 0x80); +struct uae_input_device_kbr_default { + int scancode; + struct uae_input_device_default_node node[MAX_INPUT_SUB_EVENT]; +}; - return but; -} +struct inputevent { + const TCHAR *confname; + const TCHAR *name; + int allow_mask; + int type; + int unit; + int data; +}; + +#define MAX_INPUT_QUALIFIERS (8+4) + +/* event flags */ +#define ID_FLAG_AUTOFIRE 1 +#define ID_FLAG_TOGGLE 2 +#define ID_FLAG_GAMEPORTSCUSTOM1 4 +#define ID_FLAG_GAMEPORTSCUSTOM2 8 +#define ID_FLAG_INVERTTOGGLE 16 + +#define ID_FLAG_GAMEPORTSCUSTOM_MASK (ID_FLAG_GAMEPORTSCUSTOM1 | ID_FLAG_GAMEPORTSCUSTOM2) +#define ID_FLAG_AUTOFIRE_MASK (ID_FLAG_TOGGLE | ID_FLAG_INVERTTOGGLE | ID_FLAG_AUTOFIRE) +#define ID_FLAG_CANRELEASE 0x2000 +#define ID_FLAG_TOGGLED 0x4000 +#define ID_FLAG_CUSTOMEVENT_TOGGLED 0x8000 +#define ID_FLAG_QUALIFIER1 0x00010000 +#define ID_FLAG_QUALIFIER2 0x00020000 +#define ID_FLAG_QUALIFIER3 0x00040000 +#define ID_FLAG_QUALIFIER4 0x00080000 +#define ID_FLAG_QUALIFIER5 0x00100000 +#define ID_FLAG_QUALIFIER6 0x00200000 +#define ID_FLAG_QUALIFIER7 0x00400000 +#define ID_FLAG_QUALIFIER8 0x00800000 +#define ID_FLAG_QUALIFIER_SPECIAL 0x01000000 +#define ID_FLAG_QUALIFIER_SHIFT 0x02000000 +#define ID_FLAG_QUALIFIER_CONTROL 0x04000000 +#define ID_FLAG_QUALIFIER_ALT 0x08000000 +#define ID_FLAG_QUALIFIER_MASK 0x0fff0000 + +#define ID_FLAG_SAVE_MASK_CONFIG 0xff +#define ID_FLAG_SAVE_MASK_QUALIFIERS ID_FLAG_QUALIFIER_MASK +#define ID_FLAG_SAVE_MASK_FULL (ID_FLAG_SAVE_MASK_CONFIG | ID_FLAG_SAVE_MASK_QUALIFIERS) + +#define IDEV_WIDGET_NONE 0 +#define IDEV_WIDGET_BUTTON 1 +#define IDEV_WIDGET_AXIS 2 +#define IDEV_WIDGET_BUTTONAXIS 3 +#define IDEV_WIDGET_KEY 4 + +#define IDEV_MAPPED_AUTOFIRE_POSSIBLE 1 +#define IDEV_MAPPED_AUTOFIRE_SET 2 +#define IDEV_MAPPED_TOGGLE 4 +#define IDEV_MAPPED_INVERTTOGGLE 8 +#define IDEV_MAPPED_GAMEPORTSCUSTOM1 16 +#define IDEV_MAPPED_GAMEPORTSCUSTOM2 32 +#define IDEV_MAPPED_QUALIFIER1 0x00010000 +#define IDEV_MAPPED_QUALIFIER2 0x00020000 +#define IDEV_MAPPED_QUALIFIER3 0x00040000 +#define IDEV_MAPPED_QUALIFIER4 0x00080000 +#define IDEV_MAPPED_QUALIFIER5 0x00100000 +#define IDEV_MAPPED_QUALIFIER6 0x00200000 +#define IDEV_MAPPED_QUALIFIER7 0x00400000 +#define IDEV_MAPPED_QUALIFIER8 0x00800000 +#define IDEV_MAPPED_QUALIFIER_SPECIAL 0x01000000 +#define IDEV_MAPPED_QUALIFIER_SHIFT 0x02000000 +#define IDEV_MAPPED_QUALIFIER_CONTROL 0x04000000 +#define IDEV_MAPPED_QUALIFIER_ALT 0x08000000 +#define IDEV_MAPPED_QUALIFIER_MASK 0x0fff0000 + +#define ID_BUTTON_OFFSET 0 +#define ID_BUTTON_TOTAL 32 +#define ID_AXIS_OFFSET 32 +#define ID_AXIS_TOTAL 32 + +extern int inputdevice_set_mapping (int devnum, int num, const TCHAR *name, TCHAR *custom, int flags, int port, int sub); +extern int inputdevice_get_mapping (int devnum, int num, int *pflags, int *port, TCHAR *name, TCHAR *custom, int sub); +extern void inputdevice_copyconfig (const struct uae_prefs *src, struct uae_prefs *dst); +extern int inputdevice_config_change_test (void); +extern int inputdevice_get_widget_num (int devnum); +extern int inputdevice_get_widget_type (int devnum, int num, TCHAR *name); + +extern int input_get_default_mouse (struct uae_input_device *uid, int num, int port, int af); +extern int input_get_default_joystick (struct uae_input_device *uid, int num, int port, int af, int mode); +extern int input_get_default_joystick_analog (struct uae_input_device *uid, int num, int port, int af); +extern int input_get_default_keyboard (int num); + +#define DEFEVENT(A, B, C, D, E, F) INPUTEVENT_ ## A, +enum inputevents { +INPUTEVENT_ZERO, +#include "inputevents.def" +INPUTEVENT_END +}; +#undef DEFEVENT + +extern void handle_cd32_joystick_cia (uae_u8, uae_u8); +extern uae_u8 handle_parport_joystick (int port, uae_u8 pra, uae_u8 dra); +extern uae_u8 handle_joystick_buttons (uae_u8, uae_u8); -extern int is_tablet (void); extern int inputdevice_is_tablet (void); extern void input_mousehack_status (int mode, uaecptr diminfo, uaecptr dispinfo, uaecptr vp, uae_u32 moffset); extern void input_mousehack_mouseoffset (uaecptr pointerprefs); -extern void inputdevice_mouselimit(int x, int y); +extern void setmousebuttonstateall (int mouse, uae_u32 buttonbits, uae_u32 buttonmask); +extern void setjoybuttonstateall (int joy, uae_u32 buttonbits, uae_u32 buttonmask); +extern void setjoybuttonstate (int joy, int button, int state); +extern void setmousebuttonstate (int mouse, int button, int state); +extern void setjoystickstate (int joy, int axle, int state, int max); +extern int getjoystickstate (int mouse); void setmousestate (int mouse, int axis, int data, int isabs); +extern int getmousestate (int mouse); extern void inputdevice_updateconfig (struct uae_prefs *prefs); +extern void inputdevice_updateconfig_internal (struct uae_prefs *prefs); + +extern int inputdevice_translatekeycode (int keyboard, int scancode, int state); +extern void inputdevice_checkqualifierkeycode (int keyboard, int scancode, int state); +extern void inputdevice_setkeytranslation (struct uae_input_device_kbr_default **trans, int **kbmaps); +extern void inputdevice_do_keyboard (int code, int state); +extern int inputdevice_iskeymapped (int keyboard, int scancode); +extern struct inputevent *inputdevice_get_eventinfo (int evt); +extern bool inputdevice_get_eventname (const struct inputevent *ie, TCHAR *out); extern uae_u16 potgo_value; extern uae_u16 POTGOR (void); @@ -48,17 +188,57 @@ extern uae_u16 POT1DAT (void); extern void JOYTEST (uae_u16 v); extern uae_u16 JOY0DAT (void); extern uae_u16 JOY1DAT (void); +extern void JOYSET (int num, uae_u16 v); +extern uae_u16 JOYGET (int num); extern void inputdevice_vsync (void); extern void inputdevice_hsync (void); extern void inputdevice_reset (void); extern void write_inputdevice_config (struct uae_prefs *p, struct zfile *f); -extern void read_inputdevice_config (struct uae_prefs *p, TCHAR *option, TCHAR *value); +extern void read_inputdevice_config (struct uae_prefs *p, const TCHAR *option, TCHAR *value); extern void reset_inputdevice_config (struct uae_prefs *pr); +extern int inputdevice_joyport_config (struct uae_prefs *p, const TCHAR *value, int portnum, int mode, int type); +extern int inputdevice_getjoyportdevice (int port, int val); extern void inputdevice_init (void); extern void inputdevice_close (void); extern void inputdevice_default_prefs (struct uae_prefs *p); +extern void inputdevice_acquire (int allmode); +extern void inputdevice_unacquire (void); + +extern void inputdevice_add_inputcode (int code, int state); +extern void inputdevice_handle_inputcode (void); + extern void inputdevice_tablet_strobe (void); + +extern int input_getqualifiers (void); + +#define JSEM_MODE_DEFAULT 0 +#define JSEM_MODE_MOUSE 1 +#define JSEM_MODE_JOYSTICK 2 +#define JSEM_MODE_GAMEPAD 3 +#define JSEM_MODE_JOYSTICK_ANALOG 4 +#define JSEM_MODE_MOUSE_CDTV 5 +#define JSEM_MODE_JOYSTICK_CD32 6 +#define JSEM_MODE_LIGHTPEN 7 + +#define JSEM_KBDLAYOUT 0 +#define JSEM_JOYS 100 +#define JSEM_MICE 200 +#define JSEM_END 300 +#define JSEM_XARCADE1LAYOUT (JSEM_KBDLAYOUT + 3) +#define JSEM_XARCADE2LAYOUT (JSEM_KBDLAYOUT + 4) +#define JSEM_DECODEVAL(port,p) ((p)->jports[port].id) +#define JSEM_ISNUMPAD(port,p) (jsem_iskbdjoy(port,p) == JSEM_KBDLAYOUT) +#define JSEM_ISCURSOR(port,p) (jsem_iskbdjoy(port,p) == JSEM_KBDLAYOUT + 1) +#define JSEM_ISSOMEWHEREELSE(port,p) (jsem_iskbdjoy(port,p) == JSEM_KBDLAYOUT + 2) +#define JSEM_ISXARCADE1(port,p) (jsem_iskbdjoy(port,p) == JSEM_XARCADE1LAYOUT) +#define JSEM_ISXARCADE2(port,p) (jsem_iskbdjoy(port,p) == JSEM_XARCADE2LAYOUT) +#define JSEM_LASTKBD 5 +#define JSEM_ISANYKBD(port,p) (jsem_iskbdjoy(port,p) >= JSEM_KBDLAYOUT && jsem_iskbdjoy(port,p) < JSEM_KBDLAYOUT + JSEM_LASTKBD) + +extern int jsem_isjoy (int port, const struct uae_prefs *p); +extern int jsem_ismouse (int port, const struct uae_prefs *p); +extern int jsem_iskbdjoy (int port, const struct uae_prefs *p); diff --git a/src/include/joystick.h b/src/include/joystick.h index 853b7534..62fce1cb 100644 --- a/src/include/joystick.h +++ b/src/include/joystick.h @@ -6,10 +6,8 @@ * Copyright 1995 Bernd Schmidt */ -extern void read_joystick (int nr, unsigned int *dir, int *button); -extern void handle_joymouse(void); +extern void read_joystick (int nr, int *dir, int *button); extern void init_joystick (void); extern void close_joystick (void); -#define getjoystate(NR,DIR,BUT) read_joystick(NR,DIR,BUT) extern void joystick_setting_changed (void); diff --git a/src/include/keyboard.h b/src/include/keyboard.h index 413758e7..e0814624 100644 --- a/src/include/keyboard.h +++ b/src/include/keyboard.h @@ -123,3 +123,42 @@ extern void init_keyboard(void); #define AK_RESETWARNING 0x78 #define AK_INIT_POWERUP 0xfd #define AK_TERM_POWERUP 0xfe + +enum aks { AKS_ENTERGUI = 0x200, AKS_SCREENSHOT_FILE, AKS_SCREENSHOT_CLIPBOARD, AKS_FREEZEBUTTON, + AKS_FLOPPY0, AKS_FLOPPY1, AKS_FLOPPY2, AKS_FLOPPY3, + AKS_EFLOPPY0, AKS_EFLOPPY1, AKS_EFLOPPY2, AKS_EFLOPPY3, + AKS_TOGGLEDEFAULTSCREEN, + AKS_TOGGLEWINDOWEDFULLSCREEN, AKS_TOGGLEFULLWINDOWFULLSCREEN, AKS_TOGGLEWINDOWFULLWINDOW, + AKS_ENTERDEBUGGER, AKS_IRQ7, + AKS_PAUSE, AKS_WARP, AKS_INHIBITSCREEN, + AKS_STATEREWIND, AKS_STATECURRENT, AKS_STATECAPTURE, + AKS_VOLDOWN, AKS_VOLUP, AKS_VOLMUTE, + AKS_MVOLDOWN, AKS_MVOLUP, AKS_MVOLMUTE, + AKS_QUIT, AKS_HARDRESET, AKS_SOFTRESET, + AKS_STATESAVEQUICK, AKS_STATERESTOREQUICK, + AKS_STATESAVEQUICK1, AKS_STATERESTOREQUICK1, + AKS_STATESAVEQUICK2, AKS_STATERESTOREQUICK2, + AKS_STATESAVEQUICK3, AKS_STATERESTOREQUICK3, + AKS_STATESAVEQUICK4, AKS_STATERESTOREQUICK4, + AKS_STATESAVEQUICK5, AKS_STATERESTOREQUICK5, + AKS_STATESAVEQUICK6, AKS_STATERESTOREQUICK6, + AKS_STATESAVEQUICK7, AKS_STATERESTOREQUICK7, + AKS_STATESAVEQUICK8, AKS_STATERESTOREQUICK8, + AKS_STATESAVEQUICK9, AKS_STATERESTOREQUICK9, + AKS_STATESAVEDIALOG, AKS_STATERESTOREDIALOG, + AKS_DECREASEREFRESHRATE, + AKS_INCREASEREFRESHRATE, + AKS_ARCADIADIAGNOSTICS, AKS_ARCADIAPLY1, AKS_ARCADIAPLY2, AKS_ARCADIACOIN1, AKS_ARCADIACOIN2, + AKS_TOGGLEMOUSEGRAB, AKS_SWITCHINTERPOL, + AKS_INPUT_CONFIG_1,AKS_INPUT_CONFIG_2,AKS_INPUT_CONFIG_3,AKS_INPUT_CONFIG_4, + AKS_DISKSWAPPER_NEXT,AKS_DISKSWAPPER_PREV, + AKS_DISKSWAPPER_INSERT0,AKS_DISKSWAPPER_INSERT1,AKS_DISKSWAPPER_INSERT2,AKS_DISKSWAPPER_INSERT3, + AKS_DISK_PREV0, AKS_DISK_PREV1, AKS_DISK_PREV2, AKS_DISK_PREV3, + AKS_DISK_NEXT0, AKS_DISK_NEXT1, AKS_DISK_NEXT2, AKS_DISK_NEXT3, + AKS_CDTV_FRONT_PANEL_STOP, AKS_CDTV_FRONT_PANEL_PLAYPAUSE, AKS_CDTV_FRONT_PANEL_PREV, + AKS_CDTV_FRONT_PANEL_NEXT, AKS_CDTV_FRONT_PANEL_REW, AKS_CDTV_FRONT_PANEL_FF, + AKS_QUALIFIER1, AKS_QUALIFIER2, AKS_QUALIFIER3, AKS_QUALIFIER4, + AKS_QUALIFIER5, AKS_QUALIFIER6, AKS_QUALIFIER7, AKS_QUALIFIER8, + AKS_QUALIFIER_SPECIAL, AKS_QUALIFIER_SHIFT, AKS_QUALIFIER_CONTROL, + AKS_QUALIFIER_ALT +}; diff --git a/src/include/memory.h b/src/include/memory.h index 12a79ff0..8333c3ef 100644 --- a/src/include/memory.h +++ b/src/include/memory.h @@ -101,6 +101,7 @@ extern addrbank rtarea_bank; extern addrbank expamem_bank; extern addrbank fastmem_bank; extern addrbank gfxmem_bank; +extern addrbank akiko_bank; extern void rtarea_init (void); extern void rtarea_init_mem (void); diff --git a/src/include/options.h b/src/include/options.h index 7d33506c..d0f4cc68 100644 --- a/src/include/options.h +++ b/src/include/options.h @@ -21,6 +21,47 @@ struct strlist { #define DEFAULT_JIT_CACHE_SIZE 8192 +#define MAX_TOTAL_SCSI_DEVICES 8 + +/* maximum number native input devices supported (single type) */ +#define MAX_INPUT_DEVICES 8 +/* maximum number of native input device's buttons and axles supported */ +#define MAX_INPUT_DEVICE_EVENTS 256 +/* 4 different customization settings */ +#define MAX_INPUT_SETTINGS 4 +#define GAMEPORT_INPUT_SETTINGS 3 // last slot is for gameport panel mappings + +#define MAX_INPUT_SUB_EVENT 8 +#define MAX_INPUT_SUB_EVENT_ALL 9 +#define SPARE_SUB_EVENT 8 + +struct uae_input_device { + TCHAR *name; + TCHAR *configname; + uae_s16 eventid[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL]; + TCHAR *custom[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL]; + uae_u32 flags[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL]; + uae_s8 port[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL]; + uae_s16 extra[MAX_INPUT_DEVICE_EVENTS]; + uae_s8 enabled; +}; + +#define MAX_JPORTS 4 +#define NORMAL_JPORTS 2 +#define MAX_JPORTNAME 128 +struct jport { + int id; + int mode; // 0=def,1=mouse,2=joy,3=anajoy,4=lightpen + int autofire; + TCHAR name[MAX_JPORTNAME]; + TCHAR configname[MAX_JPORTNAME]; +}; +#define JPORT_NONE -1 +#define JPORT_CUSTOM -2 +#define JPORT_AF_NORMAL 1 +#define JPORT_AF_TOGGLE 2 +#define JPORT_AF_ALWAYS 3 + #define CONFIG_TYPE_HARDWARE 1 #define CONFIG_TYPE_HOST 2 #define CONFIG_BLEN 2560 @@ -29,6 +70,13 @@ struct strlist { #define TABLET_MOUSEHACK 1 #define TABLET_REAL 2 +struct cdslot +{ + TCHAR name[MAX_DPATH]; + bool inuse; + bool delayed; + int type; +}; struct floppyslot { TCHAR df[MAX_DPATH]; @@ -78,6 +126,7 @@ struct uae_prefs { int sound_interpol; int sound_filter; int sound_filter_type; + int sound_volume_cd; int cachesize; int optcount[10]; @@ -104,12 +153,19 @@ struct uae_prefs { int floppy_write_length; bool tod_hack; + bool cs_cd32cd; + bool cs_cd32c2p; + bool cs_cd32nvram; + TCHAR romfile[MAX_DPATH]; TCHAR romextfile[MAX_DPATH]; + TCHAR flashfile[MAX_DPATH]; + struct cdslot cdslots[MAX_TOTAL_SCSI_DEVICES]; TCHAR path_floppy[256]; TCHAR path_hardfile[256]; TCHAR path_rom[256]; + TCHAR path_cd[256]; int m68k_speed; int cpu_model; @@ -138,39 +194,33 @@ struct uae_prefs { int pandora_cpu_speed; int pandora_hide_idle_led; - int pandora_joyConf; - int pandora_joyPort; int pandora_tapDelay; - int pandora_customControls; - int pandora_custom_dpad; // 0-joystick, 1-mouse, 2-custom - int pandora_custom_A; - int pandora_custom_B; - int pandora_custom_X; - int pandora_custom_Y; - int pandora_custom_L; - int pandora_custom_R; - int pandora_custom_up; - int pandora_custom_down; - int pandora_custom_left; - int pandora_custom_right; - - int pandora_button1; - int pandora_button2; - int pandora_autofireButton1; - int pandora_jump; + int key_for_menu; int key_for_input_switching; - int Port1_selection; - int Port2_selection; /* input */ + struct jport jports[MAX_JPORTS]; + int input_selected_setting; int input_joymouse_multiplier; + int input_joymouse_deadzone; + int input_joystick_deadzone; + int input_joymouse_speed; + int input_analog_joystick_mult; + int input_analog_joystick_offset; int input_autofire_framecnt; + int input_mouse_speed; int input_tablet; + int input_keyboard_type; + struct uae_input_device joystick_settings[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES]; + struct uae_input_device mouse_settings[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES]; + struct uae_input_device keyboard_settings[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES]; + TCHAR input_config_name[GAMEPORT_INPUT_SETTINGS][256]; + }; /* Contains the filename of .uaerc */ @@ -201,6 +251,7 @@ extern int bip_a500plus (struct uae_prefs *p, int rom); extern int bip_a1200 (struct uae_prefs *p, int rom); extern int bip_a2000 (struct uae_prefs *p, int rom); extern int bip_a4000 (struct uae_prefs *p, int rom); +extern int bip_cd32 (struct uae_prefs *p, int rom); int parse_cmdline_option (struct uae_prefs *, TCHAR, const TCHAR *); diff --git a/src/include/savestate.h b/src/include/savestate.h index 9bba13f4..5ada5f59 100644 --- a/src/include/savestate.h +++ b/src/include/savestate.h @@ -73,6 +73,8 @@ extern void restore_disk_finish (void); extern uae_u8 *restore_custom (uae_u8 *); extern uae_u8 *save_custom (int *, uae_u8 *, int); +extern uae_u8 *restore_custom_extra (uae_u8 *); +extern uae_u8 *save_custom_extra (int *, uae_u8 *); extern uae_u8 *restore_custom_sprite (int num, uae_u8 *src); extern uae_u8 *save_custom_sprite (int num, int *len, uae_u8 *); @@ -103,12 +105,23 @@ extern void restore_p96_finish (void); extern uae_u8 *restore_keyboard (uae_u8 *); extern uae_u8 *save_keyboard (int *,uae_u8*); +extern uae_u8 *restore_akiko (uae_u8 *src); +extern uae_u8 *save_akiko (int *len, uae_u8*); +extern void restore_akiko_finish (void); + extern uae_u8 *restore_filesys (uae_u8 *src); extern uae_u8 *save_filesys (int num, int *len); extern uae_u8 *restore_filesys_common (uae_u8 *src); extern uae_u8 *save_filesys_common (int *len); extern int save_filesys_cando(void); +extern uae_u8 *save_cd (int num, int *len); +extern uae_u8 *restore_cd (int, uae_u8 *src); +extern void restore_cd_finish (void); + +extern uae_u8 *restore_input (uae_u8 *src); +extern uae_u8 *save_input (int *len, uae_u8 *dstptr); + extern void restore_cram (int, size_t); extern void restore_bram (int, size_t); extern void restore_fram (int, size_t); diff --git a/src/include/scsidev.h b/src/include/scsidev.h new file mode 100644 index 00000000..282f95d8 --- /dev/null +++ b/src/include/scsidev.h @@ -0,0 +1,30 @@ + /* + * UAE - The Un*x Amiga Emulator + * + * a SCSI device + * + * (c) 1995 Bernd Schmidt (hardfile.c) + * (c) 1999 Patrick Ohly + * (c) 2001-2005 Toni Wilen + */ + +uaecptr scsidev_startup (uaecptr resaddr); +void scsidev_install (void); +void scsidev_reset (void); +void scsidev_start_threads (void); +int scsi_do_disk_change (int unitnum, int insert, int *pollmode); +int scsi_do_disk_device_change (void); +uae_u32 scsi_get_cd_drive_mask (void); +uae_u32 scsi_get_cd_drive_media_mask (void); + +extern int log_scsi; + +#ifdef _WIN32 +#define UAESCSI_CDEMU 0 +#define UAESCSI_SPTI 1 +#define UAESCSI_SPTISCAN 2 +#define UAESCSI_ASPI_FIRST 3 +#define UAESCSI_ADAPTECASPI 3 +#define UAESCSI_NEROASPI 4 +#define UAESCSI_FROGASPI 5 +#endif \ No newline at end of file diff --git a/src/include/sysdeps.h b/src/include/sysdeps.h index ba42ae4e..b424de4c 100644 --- a/src/include/sysdeps.h +++ b/src/include/sysdeps.h @@ -274,6 +274,8 @@ extern TCHAR *my_strdup (const TCHAR*s); #if defined PANDORA +#include + #define FILEFLAG_DIR 0x1 #define FILEFLAG_ARCHIVE 0x2 #define FILEFLAG_WRITE 0x4 diff --git a/src/include/uae.h b/src/include/uae.h index 06b1eb8d..8e776657 100644 --- a/src/include/uae.h +++ b/src/include/uae.h @@ -18,7 +18,6 @@ extern void usage (void); extern void sleep_millis (int ms); extern void sleep_millis_main (int ms); extern void sleep_millis_busy (int ms); -extern int sleep_resolution; extern void uae_reset (int); @@ -52,6 +51,7 @@ struct bstring { }; extern void fetch_saveimagepath (TCHAR*, int, int); +extern void fetch_datapath (TCHAR *out, int size); #define uaerand() rand() #endif //UAE_UAE_H diff --git a/src/include/xwin.h b/src/include/xwin.h index b7fcef37..d663db7f 100644 --- a/src/include/xwin.h +++ b/src/include/xwin.h @@ -18,6 +18,7 @@ extern int graphics_setup (void); extern int graphics_init (void); extern void graphics_leave (void); extern void handle_events (void); +extern int handle_msgpump (void); extern void setup_brkhandler (void); STATIC_INLINE int isvsync_chipset (void) { diff --git a/src/inputdevice.cpp b/src/inputdevice.cpp index 56a93f85..8e3870ad 100644 --- a/src/inputdevice.cpp +++ b/src/inputdevice.cpp @@ -1,87 +1,979 @@ /* - * UAE - The Un*x Amiga Emulator - * - * joystick/mouse emulation - * - * Copyright 2001, 2002 Toni Wilen - * - */ +* UAE - The Un*x Amiga Emulator +* +* joystick/mouse emulation +* +* Copyright 2001-2010 Toni Wilen +* +* new fetures: +* - very configurable (and very complex to configure :) +* - supports multiple native input devices (joysticks and mice) +* - supports mapping joystick/mouse buttons to keys and vice versa +* - joystick mouse emulation (supports both ports) +* - supports parallel port joystick adapter +* - full cd32 pad support (supports both ports) +* - fully backward compatible with old joystick/mouse configuration +* +*/ #include "sysconfig.h" #include "sysdeps.h" #include "options.h" #include "memory.h" -#include "newcpu.h" -#include "custom.h" #include "keyboard.h" #include "inputdevice.h" #include "keybuf.h" +#include "newcpu.h" +#include "custom.h" #include "xwin.h" #include "drawing.h" #include "uae.h" #include "joystick.h" #include "picasso96.h" +#include "gui.h" +#include "savestate.h" -int joy0button, joy1button; -static unsigned int joy0dir, joy1dir; +extern int bootrom_header; -extern int bootrom_header, bootrom_items; +// 01 = host events +// 02 = joystick +// 04 = cia buttons +// 16 = potgo +// 32 = vsync + +#define IE_INVERT 0x80 +#define IE_CDTV 0x100 + +#define INPUTEVENT_JOY1_CD32_FIRST INPUTEVENT_JOY1_CD32_PLAY +#define INPUTEVENT_JOY2_CD32_FIRST INPUTEVENT_JOY2_CD32_PLAY +#define INPUTEVENT_JOY1_CD32_LAST INPUTEVENT_JOY1_CD32_BLUE +#define INPUTEVENT_JOY2_CD32_LAST INPUTEVENT_JOY2_CD32_BLUE + +/* event masks */ +#define AM_KEY 1 /* keyboard allowed */ +#define AM_JOY_BUT 2 /* joystick buttons allowed */ +#define AM_JOY_AXIS 4 /* joystick axis allowed */ +#define AM_MOUSE_BUT 8 /* mouse buttons allowed */ +#define AM_MOUSE_AXIS 16 /* mouse direction allowed */ +#define AM_AF 32 /* supports autofire */ +#define AM_INFO 64 /* information data for gui */ +#define AM_DUMMY 128 /* placeholder */ +#define AM_CUSTOM 256 /* custom event */ +#define AM_K (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT|AM_AF) /* generic button/switch */ +#define AM_KK (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT) + +#define DEFEVENT(A, B, C, D, E, F) {#A, B, C, D, E, F }, +static struct inputevent events[] = { + {0, 0, AM_K,0,0,0}, +#include "inputevents.def" + {0, 0, 0, 0, 0, 0} +}; +#undef DEFEVENT + +static int sublevdir[2][MAX_INPUT_SUB_EVENT]; + +static const int slotorder1[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static const int slotorder2[] = { 8, 1, 2, 3, 4, 5, 6, 7 }; + +struct uae_input_device2 { + uae_u32 buttonmask; + int states[MAX_INPUT_DEVICE_EVENTS / 2]; +}; + +static struct uae_input_device2 joysticks2[MAX_INPUT_DEVICES]; +static struct uae_input_device2 mice2[MAX_INPUT_DEVICES]; +static uae_u8 scancodeused[MAX_INPUT_DEVICES][256]; +static int qualifiers; + +static int joymodes[MAX_JPORTS]; +static int *joyinputs[MAX_JPORTS]; + +static int input_acquired; + +#ifdef INPUTDEVICE_SIMPLE +static int handle_input_event (int nr, int state, int max, int autofire); +#else +static int handle_input_event (int nr, int state, int max, int autofire, bool canstoprecord, bool playbackevent); +#endif + +static struct inputdevice_functions idev[3]; + +static int isdevice (struct uae_input_device *id) +{ + int i, j; + for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (id->eventid[i][j] > 0) + return 1; + } + } + return 0; +} + +static struct uae_input_device *joysticks; +static struct uae_input_device *mice; +static struct uae_input_device *keyboards; +static struct uae_input_device_kbr_default *keyboard_default, **keyboard_default_table; + +#define KBR_DEFAULT_MAP_FIRST 0 +#define KBR_DEFAULT_MAP_LAST 5 +#define KBR_DEFAULT_MAP_CD32_FIRST 6 +#define KBR_DEFAULT_MAP_CD32_LAST 8 + +#define KBR_DEFAULT_MAP_NP 0 +#define KBR_DEFAULT_MAP_CK 1 +#define KBR_DEFAULT_MAP_SE 2 +#define KBR_DEFAULT_MAP_NP3 3 +#define KBR_DEFAULT_MAP_CK3 4 +#define KBR_DEFAULT_MAP_SE3 5 +#define KBR_DEFAULT_MAP_CD32_NP 6 +#define KBR_DEFAULT_MAP_CD32_CK 7 +#define KBR_DEFAULT_MAP_CD32_SE 8 +#define KBR_DEFAULT_MAP_XA1 9 +#define KBR_DEFAULT_MAP_XA2 10 +#define KBR_DEFAULT_MAP_ARCADIA 11 +#define KBR_DEFAULT_MAP_ARCADIA_XA 12 +#define KBR_DEFAULT_MAP_CDTV 13 +static int **keyboard_default_kbmaps; + +static int mouse_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; +static int oldm_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; + +#define MOUSE_AXIS_TOTAL 4 + +static uae_s16 mouse_x[MAX_JPORTS], mouse_y[MAX_JPORTS]; +static uae_s16 mouse_delta[MAX_JPORTS][MOUSE_AXIS_TOTAL]; +static uae_s16 mouse_deltanoreset[MAX_JPORTS][MOUSE_AXIS_TOTAL]; +static int joybutton[MAX_JPORTS]; +static int joydir[MAX_JPORTS]; +#ifndef INPUTDEVICE_SIMPLE +static int joydirpot[MAX_JPORTS][2]; +#endif +static uae_s16 mouse_frame_x[MAX_JPORTS], mouse_frame_y[MAX_JPORTS]; + +static int mouse_port[NORMAL_JPORTS]; +static int cd32_shifter[NORMAL_JPORTS]; +static int cd32_pad_enabled[NORMAL_JPORTS]; +#ifndef INPUTDEVICE_SIMPLE +static int parport_joystick_enabled; +#endif +static int oleft[MAX_JPORTS], oright[MAX_JPORTS], otop[MAX_JPORTS], obot[MAX_JPORTS]; + +uae_u16 potgo_value; +#ifndef INPUTDEVICE_SIMPLE +static int pot_cap[NORMAL_JPORTS][2]; +#endif +static uae_u8 pot_dat[NORMAL_JPORTS][2]; +static int pot_dat_act[NORMAL_JPORTS][2]; +#ifndef INPUTDEVICE_SIMPLE +static int analog_port[NORMAL_JPORTS][2]; +#endif +static int digital_port[NORMAL_JPORTS][2]; +#define POTDAT_DELAY_PAL 8 +#define POTDAT_DELAY_NTSC 7 + +static int use_joysticks[MAX_INPUT_DEVICES]; +static int use_mice[MAX_INPUT_DEVICES]; +static int use_keyboards[MAX_INPUT_DEVICES]; + +#ifdef INPUTDEVICE_SIMPLE +#define INPUT_QUEUE_SIZE 6 +#else +#define INPUT_QUEUE_SIZE 16 +#endif +struct input_queue_struct { + int evt, storedstate, state, max, linecnt, nextlinecnt; +}; +static struct input_queue_struct input_queue[INPUT_QUEUE_SIZE]; + +uae_u8 *restore_input (uae_u8 *src) +{ + restore_u32 (); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { +#ifndef INPUTDEVICE_SIMPLE + pot_cap[i][j] = restore_u16 (); +#else + restore_u16(); +#endif + } + } + return src; +} +uae_u8 *save_input (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + save_u32 (0); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { +#ifndef INPUTDEVICE_SIMPLE + save_u16 (pot_cap[i][j]); +#else + save_u16(0); +#endif + } + } + *len = dst - dstbak; + return dstbak; +} + +static void freejport (struct uae_prefs *dst, int num) +{ + memset (&dst->jports[num], 0, sizeof (struct jport)); + dst->jports[num].id = -1; +} +static void copyjport (const struct uae_prefs *src, struct uae_prefs *dst, int num) +{ + freejport (dst, num); + _tcscpy (dst->jports[num].configname, src->jports[num].configname); + _tcscpy (dst->jports[num].name, src->jports[num].name); + dst->jports[num].id = src->jports[num].id; + dst->jports[num].mode = src->jports[num].mode; + dst->jports[num].autofire = src->jports[num].autofire; +} + +static bool write_config_head (struct zfile *f, int idnum, int devnum, TCHAR *name, struct uae_input_device *id, struct inputdevice_functions *idf) +{ + TCHAR tmp2[MAX_DPATH]; + + if (idnum == GAMEPORT_INPUT_SETTINGS) { + if (!isdevice (id)) + return false; + if (!id->enabled) + return false; + } + + TCHAR *s = NULL; + if (id->name) + s = id->name; + else if (devnum < idf->get_num ()) + s = idf->get_friendlyname (devnum); + if (s) { + _stprintf (tmp2, _T("input.%d.%s.%d.friendlyname"), idnum + 1, name, devnum); + cfgfile_write_str (f, tmp2, s); + } + + s = NULL; + if (id->configname) + s = id->configname; + else if (devnum < idf->get_num ()) + s = idf->get_uniquename (devnum); + if (s) { + _stprintf (tmp2, _T("input.%d.%s.%d.name"), idnum + 1, name, devnum); + cfgfile_write_str (f, tmp2, s); + } + + if (!isdevice (id)) { + _stprintf (tmp2, _T("input.%d.%s.%d.empty"), idnum + 1, name, devnum); + cfgfile_write_bool (f, tmp2, true); + if (id->enabled) { + _stprintf (tmp2, _T("input.%d.%s.%d.disabled"), idnum + 1, name, devnum); + cfgfile_write (f, tmp2, _T("%d"), id->enabled ? 0 : 1); + } + return false; + } + + if (idnum == GAMEPORT_INPUT_SETTINGS) { + _stprintf (tmp2, _T("input.%d.%s.%d.custom"), idnum + 1, name, devnum); + cfgfile_write_bool (f, tmp2, true); + } else { + _stprintf (tmp2, _T("input.%d.%s.%d.empty"), idnum + 1, name, devnum); + cfgfile_write_bool (f, tmp2, false); + _stprintf (tmp2, _T("input.%d.%s.%d.disabled"), idnum + 1, name, devnum); + cfgfile_write_bool (f, tmp2, id->enabled ? false : true); + } + return true; +} + +static bool write_slot (TCHAR *p, struct uae_input_device *uid, int i, int j) +{ + bool ok = false; + int flags = uid->flags[i][j]; + if (uid->custom[i][j] && _tcslen (uid->custom[i][j]) > 0) { + _stprintf (p, _T("'%s'.%d"), uid->custom[i][j], flags & ID_FLAG_SAVE_MASK_CONFIG); + ok = true; + } else if (uid->eventid[i][j] > 0) { + _stprintf (p, _T("%s.%d"), events[uid->eventid[i][j]].confname, flags & ID_FLAG_SAVE_MASK_CONFIG); + ok = true; + } else { + _tcscpy (p, _T("NULL")); + } + if (ok && (flags & ID_FLAG_SAVE_MASK_QUALIFIERS)) { + TCHAR *p2 = p + _tcslen (p); + *p2++ = '.'; + for (int i = 0; i < MAX_INPUT_QUALIFIERS; i++) { + if ((ID_FLAG_QUALIFIER1 << i) & flags) { + _stprintf (p2, _T("%c"), 'A' + i); + p2++; + } + } + } + return ok; +} + +static void kbrlabel (TCHAR *s) +{ + while (*s) { + *s = _totupper (*s); + if (*s == ' ') + *s = '_'; + s++; + } +} + +static void write_config2 (struct zfile *f, int idnum, int i, int offset, const TCHAR *extra, struct uae_input_device *id) +{ + TCHAR tmp2[200], tmp3[200], *p; + int evt, got, j, k; + TCHAR *custom; + const int *slotorder; + int io = i + offset; + + tmp2[0] = 0; + p = tmp2; + got = 0; + + slotorder = slotorder1; + // if gameports non-custom mapping in slot0 -> save slot4 as slot0 + if (id->port[io][0] && !(id->flags[io][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) + slotorder = slotorder2; + + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + + evt = id->eventid[io][slotorder[j]]; + custom = id->custom[io][slotorder[j]]; + if (custom == NULL && evt <= 0) { + for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) { + if (id->eventid[io][slotorder[k]] > 0 || id->custom[io][slotorder[k]] != NULL) + break; + } + if (k == MAX_INPUT_SUB_EVENT) + break; + } + if (id->port[io][0] > 0) { + if (!(id->flags[io][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK) && id->port[io][SPARE_SUB_EVENT] == 0) + break; + } + + if (p > tmp2) { + *p++ = ','; + *p = 0; + } + bool ok = write_slot (p, id, io, slotorder[j]); + p += _tcslen (p); + if (ok) { + if (id->port[io][slotorder[j]] > 0) { + _stprintf (p, _T(".%d"), id->port[io][slotorder[j]] - 1); + p += _tcslen (p); + if (idnum != GAMEPORT_INPUT_SETTINGS && j == 0 && id->port[io][SPARE_SUB_EVENT] && slotorder == slotorder1) { + *p++ = '.'; + write_slot (p, id, io, SPARE_SUB_EVENT); + p += _tcslen (p); + } + } + } + } + if (p > tmp2) { + _stprintf (tmp3, _T("input.%d.%s%d"), idnum + 1, extra, i); + cfgfile_write_str (f, tmp3, tmp2); + } +} + +static void write_kbr_config (struct zfile *f, int idnum, int devnum, struct uae_input_device *kbr, struct inputdevice_functions *idf) +{ + TCHAR tmp1[200], tmp2[200], tmp3[200], tmp4[200], tmp5[200], *p; + int i, j, k, evt, skip; + const int *slotorder; + + if (!keyboard_default) + return; + + if (!write_config_head (f, idnum, devnum, _T("keyboard"), kbr, idf)) + return; + + i = 0; + while (i < MAX_INPUT_DEVICE_EVENTS && kbr->extra[i] >= 0) { + + slotorder = slotorder1; + // if gameports non-custom mapping in slot0 -> save slot4 as slot0 + if (kbr->port[i][0] && !(kbr->flags[i][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) + slotorder = slotorder2; + + skip = 0; + k = 0; + while (keyboard_default[k].scancode >= 0) { + if (keyboard_default[k].scancode == kbr->extra[i]) { + skip = 1; + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (keyboard_default[k].node[j].evt != 0) { + if (keyboard_default[k].node[j].evt != kbr->eventid[i][slotorder[j]] || keyboard_default[k].node[j].flags != (kbr->flags[i][slotorder[j]] & ID_FLAG_SAVE_MASK_FULL)) + skip = 0; + } else if ((kbr->flags[i][slotorder[j]] & ID_FLAG_SAVE_MASK_FULL) != 0 || kbr->eventid[i][slotorder[j]] > 0) { + skip = 0; + } + } + break; + } + k++; + } + bool isdefaultspare = + kbr->port[i][SPARE_SUB_EVENT] && + keyboard_default[k].node[0].evt == kbr->eventid[i][SPARE_SUB_EVENT] && keyboard_default[k].node[0].flags == (kbr->flags[i][SPARE_SUB_EVENT] & ID_FLAG_SAVE_MASK_FULL); + + if (kbr->port[i][0] > 0 && !(kbr->flags[i][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK) && + (kbr->eventid[i][1] <= 0 && kbr->eventid[i][2] <= 0 && kbr->eventid[i][3] <= 0) && + (kbr->port[i][SPARE_SUB_EVENT] == 0 || isdefaultspare)) + skip = 1; + if (kbr->eventid[i][0] == 0 && (kbr->flags[i][0] & ID_FLAG_SAVE_MASK_FULL) == 0 && keyboard_default[k].scancode < 0) + skip = 1; + if (skip) { + i++; + continue; + } + tmp2[0] = 0; + p = tmp2; + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + TCHAR *custom = kbr->custom[i][slotorder[j]]; + evt = kbr->eventid[i][slotorder[j]]; + if (custom == NULL && evt <= 0) { + for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) { + if (kbr->eventid[i][slotorder[k]] > 0 || kbr->custom[i][slotorder[k]] != NULL) + break; + } + if (k == MAX_INPUT_SUB_EVENT) + break; + } + if (p > tmp2) { + *p++ = ','; + *p = 0; + } + bool ok = write_slot (p, kbr, i, slotorder[j]); + p += _tcslen (p); + if (ok) { + // save port number + SPARE SLOT if needed + if (kbr->port[i][slotorder[j]] > 0 && (kbr->flags[i][slotorder[j]] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) { + _stprintf (p, _T(".%d"), kbr->port[i][slotorder[j]] - 1); + p += _tcslen (p); + if (idnum != GAMEPORT_INPUT_SETTINGS && j == 0 && kbr->port[i][SPARE_SUB_EVENT] && !isdefaultspare && slotorder == slotorder1) { + *p++ = '.'; + write_slot (p, kbr, i, SPARE_SUB_EVENT); + p += _tcslen (p); + } + } + } + } + idf->get_widget_type (devnum, i, tmp5, NULL); + _stprintf (tmp3, _T("%d%s%s"), kbr->extra[i], tmp5[0] ? _T(".") : _T(""), tmp5[0] ? tmp5 : _T("")); + kbrlabel (tmp3); + _stprintf (tmp1, _T("keyboard.%d.button.%s"), devnum, tmp3); + _stprintf (tmp4, _T("input.%d.%s"), idnum + 1, tmp1); + cfgfile_write_str (f, tmp4, tmp2[0] ? tmp2 : _T("NULL")); + i++; + } +} + +static void write_config (struct zfile *f, int idnum, int devnum, TCHAR *name, struct uae_input_device *id, struct uae_input_device2 *id2, struct inputdevice_functions *idf) +{ + TCHAR tmp1[MAX_DPATH]; + int i; + + if (!write_config_head (f, idnum, devnum, name, id, idf)) + return; + + _stprintf (tmp1, _T("%s.%d.axis."), name, devnum); + for (i = 0; i < ID_AXIS_TOTAL; i++) + write_config2 (f, idnum, i, ID_AXIS_OFFSET, tmp1, id); + _stprintf (tmp1, _T("%s.%d.button.") ,name, devnum); + for (i = 0; i < ID_BUTTON_TOTAL; i++) + write_config2 (f, idnum, i, ID_BUTTON_OFFSET, tmp1, id); +} + +static const TCHAR *kbtypes[] = { _T("amiga"), _T("pc"), NULL }; void write_inputdevice_config (struct uae_prefs *p, struct zfile *f) { - cfgfile_write (f, "input.joymouse_speed_analog", "%d", p->input_joymouse_multiplier); - cfgfile_write (f, "input.autofire", "%d", p->input_autofire_framecnt); + int i, id; + + cfgfile_write (f, _T("input.config"), _T("%d"), p->input_selected_setting == GAMEPORT_INPUT_SETTINGS ? 0 : p->input_selected_setting + 1); + cfgfile_write (f, _T("input.joymouse_speed_analog"), _T("%d"), p->input_joymouse_multiplier); + cfgfile_write (f, _T("input.joymouse_speed_digital"), _T("%d"), p->input_joymouse_speed); + cfgfile_write (f, _T("input.joymouse_deadzone"), _T("%d"), p->input_joymouse_deadzone); + cfgfile_write (f, _T("input.joystick_deadzone"), _T("%d"), p->input_joystick_deadzone); + cfgfile_write (f, _T("input.analog_joystick_multiplier"), _T("%d"), p->input_analog_joystick_mult); + cfgfile_write (f, _T("input.analog_joystick_offset"), _T("%d"), p->input_analog_joystick_offset); + cfgfile_write (f, _T("input.mouse_speed"), _T("%d"), p->input_mouse_speed); + cfgfile_write (f, _T("input.autofire"), _T("%d"), p->input_autofire_framecnt); + cfgfile_dwrite_str (f, _T("input.keyboard_type"), kbtypes[p->input_keyboard_type]); + for (id = 0; id < MAX_INPUT_SETTINGS; id++) { + TCHAR tmp[MAX_DPATH]; + if (id < GAMEPORT_INPUT_SETTINGS) { + _stprintf (tmp, _T("input.%d.name"), id + 1); + cfgfile_dwrite_str (f, tmp, p->input_config_name[id]); + } + for (i = 0; i < MAX_INPUT_DEVICES; i++) + write_config (f, id, i, _T("joystick"), &p->joystick_settings[id][i], &joysticks2[i], &idev[IDTYPE_JOYSTICK]); + for (i = 0; i < MAX_INPUT_DEVICES; i++) + write_config (f, id, i, _T("mouse"), &p->mouse_settings[id][i], &mice2[i], &idev[IDTYPE_MOUSE]); + for (i = 0; i < MAX_INPUT_DEVICES; i++) + write_kbr_config (f, id, i, &p->keyboard_settings[id][i], &idev[IDTYPE_KEYBOARD]); + } } -static TCHAR *getstring (TCHAR **pp) +static int getqual (const TCHAR **pp) { - int i; - static TCHAR str[1000]; - TCHAR *p = *pp; + const TCHAR *p = *pp; + int mask = 0; - if (*p == 0) - return 0; - i = 0; - while (*p != 0 && *p !='.' && *p != ',') - str[i++] = *p++; - if (*p == '.' || *p == ',') - p++; - str[i] = 0; - *pp = p; - return str; + while (*p >= 'A' && *p <= 'Z') { + mask |= ID_FLAG_QUALIFIER1 << (*p - 'A'); + p++; + } + while (*p != 0 && *p !='.' && *p != ',') + p++; + if (*p == '.' || *p == ',') + p++; + *pp = p; + return mask; } -void reset_inputdevice_config (struct uae_prefs *pr) +static int getnum (const TCHAR **pp) { + const TCHAR *p = *pp; + int v; + + if (!_tcsnicmp (p, _T("false"), 5)) + v = 0; + if (!_tcsnicmp (p, _T("true"), 4)) + v = 1; + else + v = _tstol (p); + + while (*p != 0 && *p !='.' && *p != ',') + p++; + if (*p == '.' || *p == ',') + p++; + *pp = p; + return v; +} +static TCHAR *getstring (const TCHAR **pp) +{ + int i; + static TCHAR str[1000]; + const TCHAR *p = *pp; + + if (*p == 0) + return 0; + i = 0; + while (*p != 0 && *p !='.' && *p != ',' && i < 1000 - 1) + str[i++] = *p++; + if (*p == '.' || *p == ',') + p++; + str[i] = 0; + *pp = p; + return str; } -void read_inputdevice_config (struct uae_prefs *pr, TCHAR *option, TCHAR *value) +static void reset_inputdevice_settings (struct uae_input_device *uid) { - char *p; + for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) { + for (int i = 0; i < MAX_INPUT_SUB_EVENT_ALL; i++) { + uid->eventid[l][i] = 0; + uid->flags[l][i] = 0; + xfree (uid->custom[l][i]); + uid->custom[l][i] = NULL; + } + } +} +static void reset_inputdevice_slot (struct uae_prefs *prefs, int slot) +{ + for (int m = 0; m < MAX_INPUT_DEVICES; m++) { + reset_inputdevice_settings (&prefs->joystick_settings[slot][m]); + reset_inputdevice_settings (&prefs->mouse_settings[slot][m]); + reset_inputdevice_settings (&prefs->keyboard_settings[slot][m]); + } +} +void reset_inputdevice_config (struct uae_prefs *prefs) +{ + for (int i = 0; i< MAX_INPUT_SETTINGS; i++) + reset_inputdevice_slot (prefs, i); +} + +static void set_kbr_default_event (struct uae_input_device *kbr, struct uae_input_device_kbr_default *trans, int num) +{ + for (int i = 0; trans[i].scancode >= 0; i++) { + if (kbr->extra[num] == trans[i].scancode) { + int k; + for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) { + if (kbr->eventid[num][k] == 0) + break; + } + if (k == MAX_INPUT_SUB_EVENT) { + write_log (_T("corrupt default keyboard mappings\n")); + return; + } + int l = 0; + while (k < MAX_INPUT_SUB_EVENT && trans[i].node[l].evt) { + int evt = trans[i].node[l].evt; + if (evt < 0 || evt >= INPUTEVENT_SPC_LAST) + gui_message(_T("invalid event in default keyboard table!")); + kbr->eventid[num][k] = evt; + kbr->flags[num][k] = trans[i].node[l].flags; + l++; + k++; + } + break; + } + } +} + +static void clear_id (struct uae_input_device *id) +{ + int i, j; + for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (j = 0; j < MAX_INPUT_SUB_EVENT_ALL; j++) + xfree (id->custom[i][j]); + } + + TCHAR *cn = id->configname; + TCHAR *n = id->name; + memset (id, 0, sizeof (struct uae_input_device)); + id->configname = cn; + id->name = n; +} + +static void set_kbr_default (struct uae_prefs *p, int index, int devnum, struct uae_input_device_kbr_default *trans) +{ + int i, j; + struct uae_input_device *kbr; + struct inputdevice_functions *id = &idev[IDTYPE_KEYBOARD]; + uae_u32 scancode; + + if (!trans) + return; + for (j = 0; j < MAX_INPUT_DEVICES; j++) { + if (devnum >= 0 && devnum != j) + continue; + kbr = &p->keyboard_settings[index][j]; + for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + clear_id (kbr); + kbr->extra[i] = -1; + } + if (j < id->get_num ()) { + if (input_get_default_keyboard (j)) + kbr->enabled = 1; + for (i = 0; i < id->get_widget_num (j); i++) { + id->get_widget_type (j, i, 0, &scancode); + kbr->extra[i] = scancode; + set_kbr_default_event (kbr, trans, i); + } + } + } +} + +static void inputdevice_default_kb (struct uae_prefs *p, int num) +{ + if (num == GAMEPORT_INPUT_SETTINGS) { + if (p->jports[0].id != JPORT_CUSTOM || p->jports[1].id != JPORT_CUSTOM) + reset_inputdevice_slot (p, num); + } + set_kbr_default (p, num, -1, keyboard_default); +} +static void inputdevice_default_kb_all (struct uae_prefs *p) +{ + for (int i = 0; i < MAX_INPUT_SETTINGS; i++) + inputdevice_default_kb (p, i); +} + +static bool read_slot (TCHAR *parm, int num, int joystick, int button, struct uae_input_device *id, int keynum, int subnum, struct inputevent *ie, int flags, int port, TCHAR *custom) +{ + int mask; + + if (custom == NULL && ie->name == NULL) { + if (!_tcscmp (parm, _T("NULL"))) { + if (joystick < 0) { + id->eventid[keynum][subnum] = 0; + id->flags[keynum][subnum] = 0; + } else if (button) { + id->eventid[num + ID_BUTTON_OFFSET][subnum] = 0; + id->flags[num + ID_BUTTON_OFFSET][subnum] = 0; + } else { + id->eventid[num + ID_AXIS_OFFSET][subnum] = 0; + id->flags[num + ID_AXIS_OFFSET][subnum] = 0; + } + } + return false; + } + if (custom) + ie = &events[INPUTEVENT_SPC_CUSTOM_EVENT]; + + if (joystick < 0) { + if (!(ie->allow_mask & AM_K)) + return false; + id->eventid[keynum][subnum] = ie - events; + id->flags[keynum][subnum] = flags; + id->port[keynum][subnum] = port; + xfree (id->custom[keynum][subnum]); + id->custom[keynum][subnum] = custom; + } else if (button) { + if (joystick) + mask = AM_JOY_BUT; + else + mask = AM_MOUSE_BUT; + if (!(ie->allow_mask & mask)) + return false; + id->eventid[num + ID_BUTTON_OFFSET][subnum] = ie - events; + id->flags[num + ID_BUTTON_OFFSET][subnum] = flags; + id->port[num + ID_BUTTON_OFFSET][subnum] = port; + xfree (id->custom[num + ID_BUTTON_OFFSET][subnum]); + id->custom[num + ID_BUTTON_OFFSET][subnum] = custom; + } else { + if (joystick) + mask = AM_JOY_AXIS; + else + mask = AM_MOUSE_AXIS; + if (!(ie->allow_mask & mask)) + return false; + id->eventid[num + ID_AXIS_OFFSET][subnum] = ie - events; + id->flags[num + ID_AXIS_OFFSET][subnum] = flags; + id->port[num + ID_AXIS_OFFSET][subnum] = port; + xfree (id->custom[num + ID_AXIS_OFFSET][subnum]); + id->custom[num + ID_AXIS_OFFSET][subnum] = custom; + } + return true; +} + +static struct inputevent *readevent (const TCHAR *name, TCHAR **customp) +{ + int i = 1; + while (events[i].name) { + if (!_tcscmp (events[i].confname, name)) + return &events[i]; + i++; + } + if (_tcslen (name) > 2 && name[0] == '\'' && name[_tcslen (name) - 1] == '\'') { + TCHAR *custom = my_strdup (name + 1); + custom[_tcslen (custom) - 1] = 0; + *customp = custom; + } + return &events[0]; +} + +void read_inputdevice_config (struct uae_prefs *pr, const TCHAR *option, TCHAR *value) +{ + struct uae_input_device *id = 0; + struct inputevent *ie; + int devnum, num, button, joystick, subnum, idnum, keynum; + const TCHAR *p; + TCHAR *p2, *custom; option += 6; /* "input." */ p = getstring (&option); - if (!strcasecmp (p, "joymouse_speed_analog")) - pr->input_joymouse_multiplier = _tstol (value); - if (!strcasecmp (p, "autofire")) - pr->input_autofire_framecnt = _tstol (value); + if (!strcasecmp (p, _T("config"))) { + pr->input_selected_setting = _tstol (value) - 1; + if (pr->input_selected_setting == -1) + pr->input_selected_setting = GAMEPORT_INPUT_SETTINGS; + if (pr->input_selected_setting < 0 || pr->input_selected_setting > MAX_INPUT_SETTINGS) + pr->input_selected_setting = 0; + } + if (!strcasecmp (p, _T("joymouse_speed_analog"))) + pr->input_joymouse_multiplier = _tstol (value); + if (!strcasecmp (p, _T("joymouse_speed_digital"))) + pr->input_joymouse_speed = _tstol (value); + if (!strcasecmp (p, _T("joystick_deadzone"))) + pr->input_joystick_deadzone = _tstol (value); + if (!strcasecmp (p, _T("joymouse_deadzone"))) + pr->input_joymouse_deadzone = _tstol (value); + if (!strcasecmp (p, _T("mouse_speed"))) + pr->input_mouse_speed = _tstol (value); + if (!strcasecmp (p, _T("autofire"))) + pr->input_autofire_framecnt = _tstol (value); + if (!strcasecmp (p, _T("analog_joystick_multiplier"))) + pr->input_analog_joystick_mult = _tstol (value); + if (!strcasecmp (p, _T("analog_joystick_offset"))) + pr->input_analog_joystick_offset = _tstol (value); + if (!strcasecmp (p, _T("keyboard_type"))) { + cfgfile_strval (option, value, NULL, &pr->input_keyboard_type, kbtypes, 0); + keyboard_default = keyboard_default_table[pr->input_keyboard_type]; + inputdevice_default_kb_all (pr); + } + + idnum = _tstol (p); + if (idnum <= 0 || idnum > MAX_INPUT_SETTINGS) + return; + idnum--; + + if (!_tcscmp (option, _T("name"))) { + if (idnum < GAMEPORT_INPUT_SETTINGS) + _tcscpy (pr->input_config_name[idnum], value); + return; + } + + if (_tcsncmp (option, _T("mouse."), 6) == 0) { + p = option + 6; + } else if (_tcsncmp (option, _T("joystick."), 9) == 0) { + p = option + 9; + } else if (_tcsncmp (option, _T("keyboard."), 9) == 0) { + p = option + 9; + } else + return; + + devnum = getnum (&p); + if (devnum < 0 || devnum >= MAX_INPUT_DEVICES) + return; + + p2 = getstring (&p); + if (!p2) + return; + + if (_tcsncmp (option, _T("mouse."), 6) == 0) { + id = &pr->mouse_settings[idnum][devnum]; + joystick = 0; + } else if (_tcsncmp (option, _T("joystick."), 9) == 0) { + id = &pr->joystick_settings[idnum][devnum]; + joystick = 1; + } else if (_tcsncmp (option, _T("keyboard."), 9) == 0) { + id = &pr->keyboard_settings[idnum][devnum]; + joystick = -1; + } + if (!id) + return; + if (!_tcscmp (p2, _T("name"))) { + xfree (id->configname); + id->configname = my_strdup (value); + return; + } + if (!_tcscmp (p2, _T("friendlyname"))) { + xfree (id->name); + id->name = my_strdup (value); + return; + } + + if (!_tcscmp (p2, _T("custom"))) { + int iscustom; + p = value; + iscustom = getnum (&p); + if (idnum == GAMEPORT_INPUT_SETTINGS) { + clear_id (id); + if (joystick < 0) + set_kbr_default (pr, idnum, devnum, keyboard_default); + id->enabled = iscustom; + } else { + id->enabled = false; + } + return; + } + + if (!_tcscmp (p2, _T("empty"))) { + int empty; + p = value; + empty = getnum (&p); + clear_id (id); + if (!empty) { + if (joystick < 0) + set_kbr_default (pr, idnum, devnum, keyboard_default); + } + id->enabled = 1; + if (idnum == GAMEPORT_INPUT_SETTINGS) + id->enabled = 0; + return; + } + + if (!_tcscmp (p2, _T("disabled"))) { + int disabled; + p = value; + disabled = getnum (&p); + id->enabled = disabled == 0 ? 1 : 0; + if (idnum == GAMEPORT_INPUT_SETTINGS) + id->enabled = 0; + return; + } + + if (idnum == GAMEPORT_INPUT_SETTINGS && id->enabled == 0) + return; + + button = 0; + keynum = 0; + if (joystick < 0) { + num = getnum (&p); + for (keynum = 0; keynum < MAX_INPUT_DEVICE_EVENTS; keynum++) { + if (id->extra[keynum] == num) + break; + } + if (keynum >= MAX_INPUT_DEVICE_EVENTS) + return; + } else { + button = -1; + if (!_tcscmp (p2, _T("axis"))) + button = 0; + else if(!_tcscmp (p2, _T("button"))) + button = 1; + if (button < 0) + return; + num = getnum (&p); + } + p = value; + + custom = NULL; + for (subnum = 0; subnum < MAX_INPUT_SUB_EVENT; subnum++) { + int flags, port; + xfree (custom); + custom = NULL; + p2 = getstring (&p); + if (!p2) + break; + ie = readevent (p2, &custom); + flags = 0; + port = 0; + if (p[-1] == '.') + flags = getnum (&p) & ID_FLAG_SAVE_MASK_CONFIG; + if (p[-1] == '.') { + if (p[0] >= 'A' && p[0] <= 'Z') + flags |= getqual (&p); + if (p[-1] == '.') + port = getnum (&p) + 1; + } + if (idnum == GAMEPORT_INPUT_SETTINGS && port == 0) + continue; + if (p[-1] == '.' && idnum != GAMEPORT_INPUT_SETTINGS) { + p2 = getstring (&p); + if (p2) { + int flags2 = 0; + if (p[-1] == '.') + flags2 = getnum (&p) & ID_FLAG_SAVE_MASK_CONFIG; + if (p[-1] == '.' && p[0] >= 'A' && p[0] <= 'Z') + flags |= getqual (&p); + TCHAR *custom2 = NULL; + struct inputevent *ie2 = readevent (p2, &custom2); + read_slot (p2, num, joystick, button, id, keynum, SPARE_SUB_EVENT, ie2, flags2, MAX_JPORTS + 1, custom2); + } + } + + while (*p != 0) { + if (p[-1] == ',') + break; + p++; + } + if (!read_slot (p2, num, joystick, button, id, keynum, subnum, ie, flags, port, custom)) + continue; + custom = NULL; + } + xfree (custom); } -/* Mousehack stuff */ - -static int lastsampledmx, lastsampledmy; -static int mouse_x, mouse_y; -static int mouse_maxx, mouse_maxy; - static int mousehack_alive_cnt; static int lastmx, lastmy; static int mouseoffset_x, mouseoffset_y; -static int tablet_maxx, tablet_maxy, tablet_data; +static int tablet_data; -int mousehack_alive (void) +STATIC_INLINE int mousehack_alive (void) { - return mousehack_alive_cnt > 0 ? mousehack_alive_cnt : 0; + return mousehack_alive_cnt > 0 ? mousehack_alive_cnt : 0; } #define MH_E 0 @@ -111,368 +1003,3847 @@ int mousehack_alive (void) int inputdevice_is_tablet (void) { - int v; - if (!uae_boot_rom) - return 0; - if (currprefs.input_tablet == TABLET_OFF) - return 0; - if (currprefs.input_tablet == TABLET_MOUSEHACK) - return -1; - v = is_tablet (); - if (!v) - return 0; - if (kickstart_version < 37) - return v ? -1 : 0; - return v ? 1 : 0; + if (!uae_boot_rom) + return 0; + if (currprefs.input_tablet == TABLET_OFF) + return 0; + if (currprefs.input_tablet == TABLET_MOUSEHACK) + return -1; + return 0; } static int getmhoffset (void) { - if (!uae_boot_rom) - return 0; - return get_long (rtarea_base + bootrom_header + 7 * 4) + bootrom_header; + if (!uae_boot_rom) + return 0; + return get_long (rtarea_base + bootrom_header + 7 * 4) + bootrom_header; } static void mousehack_reset (void) { - int off; + int off; - mouseoffset_x = mouseoffset_y = 0; - mousehack_alive_cnt = 0; - tablet_data = 0; - off = getmhoffset (); - if (off) - rtarea[off + MH_E] = 0; + mouseoffset_x = mouseoffset_y = 0; + mousehack_alive_cnt = 0; + tablet_data = 0; + off = getmhoffset (); + if (off) + rtarea[off + MH_E] = 0; } static void mousehack_enable (void) { - int off, mode; + int off, mode; - if (!uae_boot_rom || currprefs.input_tablet == TABLET_OFF) - return; - off = getmhoffset (); - if (rtarea[off + MH_E]) - return; - mode = 0x80; - if (currprefs.input_tablet == TABLET_MOUSEHACK) - mode |= 1; - if (inputdevice_is_tablet () > 0) - mode |= 2; - write_log ("Mouse driver enabled (%s)\n", ((mode & 3) == 3 ? "tablet+mousehack" : ((mode & 3) == 2) ? "tablet" : "mousehack")); - rtarea[off + MH_E] = 0x80; + if (!uae_boot_rom || currprefs.input_tablet == TABLET_OFF) + return; + off = getmhoffset (); + if (rtarea[off + MH_E]) + return; + mode = 0x80; + if (currprefs.input_tablet == TABLET_MOUSEHACK) + mode |= 1; + if (inputdevice_is_tablet () > 0) + mode |= 2; +#ifndef INPUTDEVICE_SIMPLE + write_log (_T("Mouse driver enabled (%s)\n"), ((mode & 3) == 3 ? _T("tablet+mousehack") : ((mode & 3) == 2) ? _T("tablet") : _T("mousehack"))); +#endif + rtarea[off + MH_E] = 0x80; } void input_mousehack_mouseoffset (uaecptr pointerprefs) { - mouseoffset_x = (uae_s16)get_word (pointerprefs + 28); - mouseoffset_y = (uae_s16)get_word (pointerprefs + 30); + mouseoffset_x = (uae_s16)get_word (pointerprefs + 28); + mouseoffset_y = (uae_s16)get_word (pointerprefs + 30); } void input_mousehack_status (int mode, uaecptr diminfo, uaecptr dispinfo, uaecptr vp, uae_u32 moffset) { - if (mode == 0) { - uae_u8 v = rtarea[getmhoffset ()]; - v |= 0x40; - rtarea[getmhoffset ()] = v; - write_log ("Tablet driver running (%02x)\n", v); - } else if (mode == 2) { - if (mousehack_alive_cnt == 0) + if (mode == 0) { + uae_u8 v = rtarea[getmhoffset ()]; + v |= 0x40; + rtarea[getmhoffset ()] = v; + write_log (_T("Tablet driver running (%02x)\n"), v); + } else if (mode == 2) { + if (mousehack_alive_cnt == 0) mousehack_alive_cnt = -100; - else if (mousehack_alive_cnt > 0) + else if (mousehack_alive_cnt > 0) mousehack_alive_cnt = 100; - } + } } void inputdevice_tablet_strobe (void) { - uae_u8 *p; - uae_u32 off; + uae_u8 *p; + uae_u32 off; - mousehack_enable (); - if (!uae_boot_rom) - return; - if (!tablet_data) - return; - off = getmhoffset (); - p = rtarea + off; - p[MH_CNT]++; + mousehack_enable (); + if (!uae_boot_rom) + return; + if (!tablet_data) + return; + off = getmhoffset (); + p = rtarea + off; + p[MH_CNT]++; } -void getgfxoffset (int *dx, int *dy, int*,int*); - static void inputdevice_mh_abs (int x, int y) { - uae_u8 *p; - uae_u8 tmp[4]; - uae_u32 off; + uae_u8 *p; + uae_u8 tmp[4]; + uae_u32 off; - mousehack_enable (); - off = getmhoffset (); - p = rtarea + off; + mousehack_enable (); + off = getmhoffset (); + p = rtarea + off; - memcpy (tmp, p + MH_ABSX, 4); + memcpy (tmp, p + MH_ABSX, sizeof tmp); - x -= mouseoffset_x + 1; - y -= mouseoffset_y + 2; + x -= mouseoffset_x + 1; + y -= mouseoffset_y + 2; - p[MH_ABSX] = x >> 8; - p[MH_ABSX + 1] = x; - p[MH_ABSY] = y >> 8; - p[MH_ABSY + 1] = y; + p[MH_ABSX] = x >> 8; + p[MH_ABSX + 1] = x; + p[MH_ABSY] = y >> 8; + p[MH_ABSY + 1] = y; - if (!memcmp (tmp, p + MH_ABSX, 4)) - return; - rtarea[off + MH_E] = 0xc0 | 1; - p[MH_CNT]++; - tablet_data = 1; + if (!memcmp (tmp, p + MH_ABSX, sizeof tmp)) + return; + rtarea[off + MH_E] = 0xc0 | 1; + p[MH_CNT]++; + tablet_data = 1; } static void mousehack_helper (void) { - int x, y; + int x, y; - if (/*currprefs.input_magic_mouse == 0 ||*/ currprefs.input_tablet < TABLET_MOUSEHACK) - return; - x = lastmx; - y = lastmy; + if (currprefs.input_tablet < TABLET_MOUSEHACK) + return; + x = lastmx; + y = lastmy; #ifdef PICASSO96 - if (picasso_on) { - x -= picasso96_state.XOffset; - y -= picasso96_state.YOffset; - } else + if (picasso_on) { + x -= picasso96_state.XOffset; + y -= picasso96_state.YOffset; + } else #endif - { - x = coord_native_to_amiga_x (x); - y = coord_native_to_amiga_y (y) << 1; - } - inputdevice_mh_abs (x, y); + { + x = coord_native_to_amiga_x (x); + y = coord_native_to_amiga_y (y) << 1; + } + inputdevice_mh_abs (x, y); } - -static void update_mouse_xy(void) +STATIC_INLINE int getbuttonstate (int joy, int button) { - int diffx, diffy; + return (joybutton[joy] & (1 << button)) ? 1 : 0; +} - diffx = lastmx - lastsampledmx; - diffy = lastmy - lastsampledmy; - lastsampledmx = lastmx; - lastsampledmy = lastmy; +STATIC_INLINE int getvelocity (int num, int subnum, int pct) +{ + int val; + int v; - if (diffx > 127) - diffx = 127; - if (diffx < -127) - diffx = -127; - mouse_x += diffx; - - if (diffy > 127) - diffy = 127; - if (diffy < -127) - diffy = -127; - mouse_y += diffy; + if (pct > 1000) + pct = 1000; + val = mouse_delta[num][subnum]; + v = val * pct / 1000; + if (!v) { + if (val < -maxvpos / 2) + v = -2; + else if (val < 0) + v = -1; + else if (val > maxvpos / 2) + v = 2; + else if (val > 0) + v = 1; + } + if (!mouse_deltanoreset[num][subnum]) { + mouse_delta[num][subnum] -= v; + } + return v; +} + +static void mouseupdate (int pct, int vsync) +{ + int v, i; + int max = 120; + static int mxd, myd; + + if (vsync) { + mxd = 0; + myd = 0; + } + + for (i = 0; i < 2; i++) { + + if (mouse_port[i]) { + + v = getvelocity (i, 0, pct); + mxd += v; + mouse_x[i] += v; + + v = getvelocity (i, 1, pct); + myd += v; + mouse_y[i] += v; + +#ifndef INPUTDEVICE_SIMPLE + v = getvelocity (i, 2, pct); + if (v > 0) + record_key (0x7a << 1); + else if (v < 0) + record_key (0x7b << 1); +#endif + if (!mouse_deltanoreset[i][2]) + mouse_delta[i][2] = 0; + + if (mouse_frame_x[i] - mouse_x[i] > max) + mouse_x[i] = mouse_frame_x[i] - max; + if (mouse_frame_x[i] - mouse_x[i] < -max) + mouse_x[i] = mouse_frame_x[i] + max; + + if (mouse_frame_y[i] - mouse_y[i] > max) + mouse_y[i] = mouse_frame_y[i] - max; + if (mouse_frame_y[i] - mouse_y[i] < -max) + mouse_y[i] = mouse_frame_y[i] + max; + } + + if (!vsync) { + mouse_frame_x[i] = mouse_x[i]; + mouse_frame_y[i] = mouse_y[i]; + } + + } +} + +static int input_vpos, input_frame; +extern int vpos; +STATIC_INLINE void readinput (void) +{ + uae_u32 totalvpos; + int diff; + + totalvpos = input_frame * current_maxvpos () + vpos; + diff = totalvpos - input_vpos; + if (diff > 0) { + if (diff < 10) { + mouseupdate (0, 0); + } else { + mouseupdate (diff * 1000 / current_maxvpos (), 0); + } + } + input_vpos = totalvpos; + +} + +static void joymousecounter (int joy) +{ + int left = 1, right = 1, top = 1, bot = 1; + int b9, b8, b1, b0; + int cntx, cnty, ocntx, ocnty; + + if (joydir[joy] & DIR_LEFT) + left = 0; + if (joydir[joy] & DIR_RIGHT) + right = 0; + if (joydir[joy] & DIR_UP) + top = 0; + if (joydir[joy] & DIR_DOWN) + bot = 0; + + b0 = (bot ^ right) ? 1 : 0; + b1 = (right ^ 1) ? 2 : 0; + b8 = (top ^ left) ? 1 : 0; + b9 = (left ^ 1) ? 2 : 0; + + cntx = b0 | b1; + cnty = b8 | b9; + ocntx = mouse_x[joy] & 3; + ocnty = mouse_y[joy] & 3; + + if (cntx == 3 && ocntx == 0) + mouse_x[joy] -= 4; + else if (cntx == 0 && ocntx == 3) + mouse_x[joy] += 4; + mouse_x[joy] = (mouse_x[joy] & 0xfc) | cntx; + + if (cnty == 3 && ocnty == 0) + mouse_y[joy] -= 4; + else if (cnty == 0 && ocnty == 3) + mouse_y[joy] += 4; + mouse_y[joy] = (mouse_y[joy] & 0xfc) | cnty; +} + +STATIC_INLINE uae_u16 getjoystate (int joy) +{ + uae_u16 v; + + v = (uae_u8)mouse_x[joy] | (mouse_y[joy] << 8); + return v; } uae_u16 JOY0DAT (void) { - update_mouse_xy(); -#ifdef RASPBERRY - if (currprefs.pandora_custom_dpad == 1) - return ((uae_u8)mouse_x) | ((uae_u16)mouse_y << 8); - else - return joy0dir; -#else - return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8) + joy0dir; -#endif + uae_u16 v; + readinput (); + v = getjoystate (0); + return v; } uae_u16 JOY1DAT (void) { - return joy1dir; + uae_u16 v; + readinput (); + v = getjoystate (1); + return v; +} + +uae_u16 JOYGET (int num) +{ + uae_u16 v; + v = getjoystate (num); + return v; +} + +void JOYSET (int num, uae_u16 dat) +{ + mouse_x[num] = dat & 0xff; + mouse_y[num] = (dat >> 8) & 0xff; + mouse_frame_x[num] = mouse_x[num]; + mouse_frame_y[num] = mouse_y[num]; } void JOYTEST (uae_u16 v) { - mouse_x = (mouse_x & 3) | (v & 0xFC); - mouse_y = (mouse_y & 3) | ((v >> 8) & 0xFC); + mouse_x[0] &= 3; + mouse_y[0] &= 3; + mouse_x[1] &= 3; + mouse_y[1] &= 3; + mouse_x[0] |= v & 0xFC; + mouse_x[1] |= v & 0xFC; + mouse_y[0] |= (v >> 8) & 0xFC; + mouse_y[1] |= (v >> 8) & 0xFC; + mouse_frame_x[0] = mouse_x[0]; + mouse_frame_y[0] = mouse_y[0]; + mouse_frame_x[1] = mouse_x[1]; + mouse_frame_y[1] = mouse_y[1]; } +#ifndef INPUTDEVICE_SIMPLE +static uae_u8 parconvert (uae_u8 v, int jd, int shift) +{ + if (jd & DIR_UP) + v &= ~(1 << shift); + if (jd & DIR_DOWN) + v &= ~(2 << shift); + if (jd & DIR_LEFT) + v &= ~(4 << shift); + if (jd & DIR_RIGHT) + v &= ~(8 << shift); + return v; +} -uae_u16 potgo_value; +/* io-pins floating: dir=1 -> return data, dir=0 -> always return 1 */ +uae_u8 handle_parport_joystick (int port, uae_u8 pra, uae_u8 dra) +{ + uae_u8 v; + switch (port) + { + case 0: + v = (pra & dra) | (dra ^ 0xff); + if (parport_joystick_enabled) { + v = parconvert (v, joydir[2], 0); + v = parconvert (v, joydir[3], 4); + } + return v; + case 1: + v = ((pra & dra) | (dra ^ 0xff)) & 0x7; + if (parport_joystick_enabled) { + if (getbuttonstate (2, 0)) + v &= ~4; + if (getbuttonstate (3, 0)) + v &= ~1; + if (getbuttonstate (2, 1) || getbuttonstate (3, 1)) + v &= ~2; /* spare */ + } + return v; + default: + return 0; + } +} +#endif + +/* p5 is 1 or floating = cd32 2-button mode */ +STATIC_INLINE bool cd32padmode (uae_u16 p5dir, uae_u16 p5dat) +{ + if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir))) + return false; + return true; +} + +#ifndef INPUTDEVICE_SIMPLE +static bool is_joystick_pullup (int joy) +{ + return joymodes[joy] == JSEM_MODE_GAMEPAD; +} + +static void charge_cap (int joy, int idx, int charge) +{ + if (charge < -1 || charge > 1) + charge = charge * 80; + pot_cap[joy][idx] += charge; + if (pot_cap[joy][idx] < 0) + pot_cap[joy][idx] = 0; + if (pot_cap[joy][idx] > 511) + pot_cap[joy][idx] = 511; +} +#endif + +static void cap_check (void) +{ + int joy, i; + + for (joy = 0; joy < 2; joy++) { + for (i = 0; i < 2; i++) { +#ifndef INPUTDEVICE_SIMPLE + int charge = 0, dong, joypot; +#endif + uae_u16 pdir = 0x0200 << (joy * 4 + i * 2); /* output enable */ + uae_u16 pdat = 0x0100 << (joy * 4 + i * 2); /* data */ + uae_u16 p5dir = 0x0200 << (joy * 4); + uae_u16 p5dat = 0x0100 << (joy * 4); + int isbutton = getbuttonstate (joy, i == 0 ? JOYBUTTON_3 : JOYBUTTON_2); + + if (cd32_pad_enabled[joy]) { + // only red and blue can be read if CD32 pad and only if it is in normal pad mode + isbutton |= getbuttonstate (joy, JOYBUTTON_CD32_BLUE); + // CD32 pad 3rd button line (P5) is always floating + if (i == 0) + isbutton = 0; + if (cd32padmode (p5dir, p5dat)) + continue; + } + +#ifndef INPUTDEVICE_SIMPLE + joypot = joydirpot[joy][i]; + if (analog_port[joy][i] && pot_cap[joy][i] < joypot) + charge = 1; // slow charge via pot variable resistor + if ((is_joystick_pullup (joy) && digital_port[joy][i]) || (mouse_port[joy])) + charge = 1; // slow charge via pull-up resistor +#endif + if (!(potgo_value & pdir)) { // input? + if (pot_dat_act[joy][i]) + pot_dat[joy][i]++; + /* first 7 or 8 lines after potgo has been started = discharge cap */ + if (pot_dat_act[joy][i] == 1) { + if (pot_dat[joy][i] < (currprefs.ntscmode ? POTDAT_DELAY_NTSC : POTDAT_DELAY_PAL)) { +#ifndef INPUTDEVICE_SIMPLE + charge = -2; /* fast discharge delay */ +#endif + } else { + pot_dat_act[joy][i] = 2; + pot_dat[joy][i] = 0; + } + } +#ifndef INPUTDEVICE_SIMPLE + if (analog_port[joy][i] && pot_dat_act[joy][i] == 2 && pot_cap[joy][i] >= joypot) + pot_dat_act[joy][i] = 0; +#endif + if ((digital_port[joy][i] || mouse_port[joy]) && pot_dat_act[joy][i] == 2) { +#ifdef INPUTDEVICE_SIMPLE + if (!isbutton) +#else + if (pot_cap[joy][i] >= 10 && !isbutton) +#endif + pot_dat_act[joy][i] = 0; + } + } else { // output? +#ifndef INPUTDEVICE_SIMPLE + charge = (potgo_value & pdat) ? 2 : -2; /* fast (dis)charge if output */ +#endif + if (potgo_value & pdat) + pot_dat_act[joy][i] = 0; // instant stop if output+high + if (isbutton) + pot_dat[joy][i]++; // "free running" if output+low + } + +#ifndef INPUTDEVICE_SIMPLE + if (isbutton) + charge = -2; // button press overrides everything + + // CD32 pad in 2-button mode: blue button is not floating + if (cd32_pad_enabled[joy] && i == 1 && charge == 0) + charge = 2; + + /* official Commodore mouse has pull-up resistors in button lines + * NOTE: 3rd party mice may not have pullups! */ + if ((mouse_port[joy] && digital_port[joy][i]) && charge == 0) + charge = 2; + /* emulate pullup resistor if button mapped because there too many broken + * programs that read second button in input-mode (and most 2+ button pads have + * pullups) + */ + if ((is_joystick_pullup (joy) && digital_port[joy][i]) && charge == 0) + charge = 2; + + charge_cap (joy, i, charge); +#endif + } + } +} + +uae_u8 handle_joystick_buttons (uae_u8 pra, uae_u8 dra) +{ + uae_u8 but = 0; + int i; + + cap_check (); + for (i = 0; i < 2; i++) { + int mask = 0x40 << i; + if (cd32_pad_enabled[i]) { + uae_u16 p5dir = 0x0200 << (i * 4); + uae_u16 p5dat = 0x0100 << (i * 4); + but |= mask; + if (!cd32padmode (p5dir, p5dat)) { + if (getbuttonstate (i, JOYBUTTON_CD32_RED) || getbuttonstate (i, JOYBUTTON_1)) + but &= ~mask; + } + } else { + if (!getbuttonstate (i, JOYBUTTON_1)) + but |= mask; + if (dra & mask) + but = (but & ~mask) | (pra & mask); + } + } + + return but; +} + +/* joystick 1 button 1 is used as a output for incrementing shift register */ +void handle_cd32_joystick_cia (uae_u8 pra, uae_u8 dra) +{ + static int oldstate[2]; + int i; + + cap_check (); + for (i = 0; i < 2; i++) { + uae_u8 but = 0x40 << i; + uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */ + uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */ + if (cd32padmode (p5dir, p5dat)) { + if ((dra & but) && (pra & but) != oldstate[i]) { + if (!(pra & but)) { + cd32_shifter[i]--; + if (cd32_shifter[i] < 0) + cd32_shifter[i] = 0; + } + } + } + oldstate[i] = pra & but; + } +} + +/* joystick port 1 button 2 is input for button state */ +static uae_u16 handle_joystick_potgor (uae_u16 potgor) +{ + int i; + + cap_check (); + for (i = 0; i < 2; i++) { + uae_u16 p9dir = 0x0800 << (i * 4); /* output enable P9 */ + uae_u16 p9dat = 0x0400 << (i * 4); /* data P9 */ + uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */ + uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */ + + if (cd32_pad_enabled[i] && cd32padmode (p5dir, p5dat)) { + + /* p5 is floating in input-mode */ + potgor &= ~p5dat; + potgor |= potgo_value & p5dat; + if (!(potgo_value & p9dir)) + potgor |= p9dat; + /* (P5 output and 1) or floating -> shift register is kept reset (Blue button) */ + if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir))) + cd32_shifter[i] = 8; + /* shift at 1 == return one, >1 = return button states */ + if (cd32_shifter[i] == 0) + potgor &= ~p9dat; /* shift at zero == return zero */ + if (cd32_shifter[i] >= 2 && (joybutton[i] & ((1 << JOYBUTTON_CD32_PLAY) << (cd32_shifter[i] - 2)))) + potgor &= ~p9dat; + + } else { + + potgor &= ~p5dat; +#ifdef INPUTDEVICE_SIMPLE + if (getbuttonstate(i, JOYBUTTON_3) == 0) +#else + if (pot_cap[i][0] > 100) +#endif + potgor |= p5dat; + + if (!cd32_pad_enabled[i] || !cd32padmode (p5dir, p5dat)) { + potgor &= ~p9dat; +#ifdef INPUTDEVICE_SIMPLE + if(getbuttonstate(i, JOYBUTTON_2) == 0) +#else + if (pot_cap[i][1] > 100) +#endif + potgor |= p9dat; + } + + } + } + return potgor; +} + +static int inputdelay; + +void inputdevice_read (void) +{ + do { + handle_msgpump (); + idev[IDTYPE_MOUSE].read (); + idev[IDTYPE_JOYSTICK].read (); + idev[IDTYPE_KEYBOARD].read (); + } while (handle_msgpump ()); +} void inputdevice_hsync (void) { + static int cnt; + cap_check (); + + for (int i = 0; i < INPUT_QUEUE_SIZE; i++) { + struct input_queue_struct *iq = &input_queue[i]; + if (iq->linecnt > 0) { + iq->linecnt--; + if (iq->linecnt == 0) { + if (iq->state) + iq->state = 0; + else + iq->state = iq->storedstate; + if (iq->evt) +#ifdef INPUTDEVICE_SIMPLE + handle_input_event (iq->evt, iq->state, iq->max, 0); +#else + handle_input_event (iq->evt, iq->state, iq->max, 0, false, true); +#endif + iq->linecnt = iq->nextlinecnt; + } + } + } + + if ((++cnt & 63) == 63 ) { + inputdevice_read (); + } else if (inputdelay > 0) { + inputdelay--; + if (inputdelay == 0) + inputdevice_read (); + } } -uae_u16 POT1DAT (void) +STATIC_INLINE uae_u16 POTDAT (int joy) { - return 0; -} - -void POTGO (uae_u16 v) -{ - potgo_value = v; -} - -uae_u16 POTGOR (void) -{ - uae_u16 v = (potgo_value | (potgo_value >> 1)) & 0x5500; - - v |= (~potgo_value & 0xAA00) >> 1; - - if (joy0button & 2) - v &= 0xFBFF; - - if (joy0button & 4) - v &= 0xFEFF; - - if (joy1button & 2) - v &= 0xbfff; - - if (joy1button & 4) - v &= 0xefff; - - return v; + uae_u16 v = (pot_dat[joy][1] << 8) | pot_dat[joy][0]; + return v; } uae_u16 POT0DAT (void) { - static uae_u16 cnt = 0; - - if (joy0button & 2) - cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00); - - if (joy0button & 4) - cnt += 0x100; - - return cnt; + return POTDAT (0); +} +uae_u16 POT1DAT (void) +{ + return POTDAT (1); +} + +/* direction=input, data pin floating, last connected logic level or previous status +* written when direction was ouput +* otherwise it is currently connected logic level. +* direction=output, data pin is current value, forced to zero if joystick button is pressed +* it takes some tens of microseconds before data pin changes state +*/ + +void POTGO (uae_u16 v) +{ + int i, j; + + potgo_value = potgo_value & 0x5500; /* keep state of data bits */ + potgo_value |= v & 0xaa00; /* get new direction bits */ + for (i = 0; i < 8; i += 2) { + uae_u16 dir = 0x0200 << i; + if (v & dir) { + uae_u16 data = 0x0100 << i; + potgo_value &= ~data; + potgo_value |= v & data; + } + } + for (i = 0; i < 2; i++) { + if (cd32_pad_enabled[i]) { + uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */ + uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */ + if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir))) + cd32_shifter[i] = 8; + } + } + if (v & 1) { + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + pot_dat_act[i][j] = 1; + pot_dat[i][j] = 0; + } + } + } +} + +uae_u16 POTGOR (void) +{ + uae_u16 v; + + v = handle_joystick_potgor (potgo_value) & 0x5500; + return v; +} + +STATIC_INLINE int check_input_queue (int evt) +{ + struct input_queue_struct *iq; + int i; + for (i = 0; i < INPUT_QUEUE_SIZE; i++) { + iq = &input_queue[i]; + if (iq->evt == evt) + return i; + } + return -1; +} + +#ifdef INPUTDEVICE_SIMPLE +static void queue_input_event (int evt, int state, int max, int linecnt) +#else +static void queue_input_event (int evt, const TCHAR *custom, int state, int max, int linecnt, int autofire) +#endif +{ + struct input_queue_struct *iq; + int idx = check_input_queue (evt); + + if (state < 0 && idx >= 0) { + iq = &input_queue[idx]; + iq->nextlinecnt = -1; + iq->linecnt = -1; + iq->evt = 0; + if (iq->state == 0 && evt > 0) +#ifdef INPUTDEVICE_SIMPLE + handle_input_event (evt, 0, 1, 0); +#else + handle_input_event (evt, 0, 1, 0, false, false); +#endif + } else if (state >= 0 && idx < 0) { +#ifdef INPUTDEVICE_SIMPLE + if (evt == 0) +#else + if (evt == 0 && custom == NULL) +#endif + return; + for (idx = 0; idx < INPUT_QUEUE_SIZE; idx++) { + iq = &input_queue[idx]; + if (iq->linecnt < 0) + break; + } + if (idx == INPUT_QUEUE_SIZE) { + write_log (_T("input queue overflow\n")); + return; + } + iq->evt = evt; + iq->state = iq->storedstate = state; + iq->max = max; + iq->linecnt = linecnt; +#ifdef INPUTDEVICE_SIMPLE + iq->nextlinecnt = linecnt; +#else + iq->nextlinecnt = autofire > 0 ? linecnt : -1; +#endif + } +} + +static uae_u8 keybuf[256]; +static int inputcode_pending, inputcode_pending_state; + +void inputdevice_add_inputcode (int code, int state) +{ + inputcode_pending = code; + inputcode_pending_state = state; +} + +void inputdevice_do_keyboard (int code, int state) +{ + if (code < 0x80) { + uae_u8 key = code | (state ? 0x00 : 0x80); + keybuf[key & 0x7f] = (key & 0x80) ? 0 : 1; + if (record_key ((uae_u8)((key << 1) | (key >> 7)))) { + } + return; + } + inputdevice_add_inputcode (code, state); +} + +void inputdevice_handle_inputcode (void) +{ + int code = inputcode_pending; + int state = inputcode_pending_state; + + if (code == 0) + goto end; + + inputcode_pending = 0; + + if (!state) + return; + switch (code) + { + case AKS_ENTERGUI: + gui_display (-1); + break; + case AKS_QUIT: + uae_quit (); + break; + case AKS_SOFTRESET: + uae_reset (0); + break; + case AKS_HARDRESET: + uae_reset (1); + break; + } +end:; +} + +STATIC_INLINE int isqual (int evt) +{ + if (evt > INPUTEVENT_SPC_QUALIFIER_START && evt < INPUTEVENT_SPC_QUALIFIER_END) + return ID_FLAG_QUALIFIER1 << (evt - INPUTEVENT_SPC_QUALIFIER1); + return 0; +} + +#ifdef INPUTDEVICE_SIMPLE +static int handle_input_event (int nr, int state, int max, int autofire) +#else +static int handle_input_event (int nr, int state, int max, int autofire, bool canstopplayback, bool playbackevent) +#endif +{ + struct inputevent *ie; + int joy; + bool isaks = false; + + if (nr <= 0 || nr == INPUTEVENT_SPC_CUSTOM_EVENT) + return 0; + ie = &events[nr]; + if (isqual (nr)) + return 0; // qualifiers do nothing + if (ie->unit == 0 && ie->data >= 0x200) { + isaks = true; + if (!state) // release AKS_ does nothing + return 0; + } + + if (autofire) { +#ifdef INPUTDEVICE_SIMPLE + if (state) + queue_input_event (nr, state, max, currprefs.input_autofire_framecnt * 312); + else + queue_input_event (nr, -1, 0, 0); +#else + if (state) + queue_input_event (nr, NULL, state, max, currprefs.input_autofire_framecnt * 312, 1); + else + queue_input_event (nr, NULL, -1, 0, 0, 1); +#endif + } + switch (ie->unit) + { + case 1: /* ->JOY1 */ + case 2: /* ->JOY2 */ + case 3: /* ->Parallel port joystick adapter port #1 */ + case 4: /* ->Parallel port joystick adapter port #2 */ + joy = ie->unit - 1; + if (ie->type & 4) { + int old = joybutton[joy] & (1 << ie->data); + + if (state) { + joybutton[joy] |= 1 << ie->data; + } else { + joybutton[joy] &= ~(1 << ie->data); + } + + } else if (ie->type & 8) { + + /* real mouse / analog stick mouse emulation */ + int delta; + int deadzone = currprefs.input_joymouse_deadzone * max / 100; + int unit = ie->data & 0x7f; + + if (max) { + if (state <= deadzone && state >= -deadzone) { + state = 0; + mouse_deltanoreset[joy][unit] = 0; + } else if (state < 0) { + state += deadzone; + mouse_deltanoreset[joy][unit] = 1; + } else { + state -= deadzone; + mouse_deltanoreset[joy][unit] = 1; + } + max -= deadzone; + delta = state * currprefs.input_joymouse_multiplier / max; + } else { + delta = state; + mouse_deltanoreset[joy][unit] = 0; + } + + if (ie->data & IE_INVERT) + delta = -delta; + + if (max) + mouse_delta[joy][unit] = delta; + else + mouse_delta[joy][unit] += delta; + + max = 32; + } else if (ie->type & 32) { /* button mouse emulation vertical */ + + int speed = currprefs.input_joymouse_speed; + + if (state && (ie->data & DIR_UP)) { + mouse_delta[joy][1] = -speed; + mouse_deltanoreset[joy][1] = 1; + } else if (state && (ie->data & DIR_DOWN)) { + mouse_delta[joy][1] = speed; + mouse_deltanoreset[joy][1] = 1; + } else + mouse_deltanoreset[joy][1] = 0; + + } else if (ie->type & 64) { /* button mouse emulation horizontal */ + + int speed = currprefs.input_joymouse_speed; + + if (state && (ie->data & DIR_LEFT)) { + mouse_delta[joy][0] = -speed; + mouse_deltanoreset[joy][0] = 1; + } else if (state && (ie->data & DIR_RIGHT)) { + mouse_delta[joy][0] = speed; + mouse_deltanoreset[joy][0] = 1; + } else + mouse_deltanoreset[joy][0] = 0; + + } else if (ie->type & 128) { /* analog joystick / paddle */ +#ifndef INPUTDEVICE_SIMPLE + int deadzone = currprefs.input_joymouse_deadzone * max / 100; + int unit = ie->data & 0x7f; + if (max) { + if (state <= deadzone && state >= -deadzone) { + state = 0; + } else if (state < 0) { + state += deadzone; + } else { + state -= deadzone; + } + state = state * max / (max - deadzone); + } + if (ie->data & IE_INVERT) + state = -state; + + state = state * currprefs.input_analog_joystick_mult / max; + state += (128 * currprefs.input_analog_joystick_mult / 100) + currprefs.input_analog_joystick_offset; + if (state < 0) + state = 0; + if (state > 255) + state = 255; + joydirpot[joy][unit] = state; + mouse_deltanoreset[joy][0] = 1; + mouse_deltanoreset[joy][1] = 1; +#endif + } else { + + int left = oleft[joy], right = oright[joy], top = otop[joy], bot = obot[joy]; + if (ie->type & 16) { + /* button to axis mapping */ + if (ie->data & DIR_LEFT) { + left = oleft[joy] = state ? 1 : 0; + } + if (ie->data & DIR_RIGHT) { + right = oright[joy] = state ? 1 : 0; + } + if (ie->data & DIR_UP) { + top = otop[joy] = state ? 1 : 0; + } + if (ie->data & DIR_DOWN) { + bot = obot[joy] = state ? 1 : 0; + } + } else { + /* "normal" joystick axis */ + int deadzone = currprefs.input_joystick_deadzone * max / 100; + int neg, pos; + if (state < deadzone && state > -deadzone) + state = 0; + neg = state < 0 ? 1 : 0; + pos = state > 0 ? 1 : 0; + if (ie->data & DIR_LEFT) { + left = oleft[joy] = neg; + } + if (ie->data & DIR_RIGHT) { + right = oright[joy] = pos; + } + if (ie->data & DIR_UP) { + top = otop[joy] = neg; + } + if (ie->data & DIR_DOWN) { + bot = obot[joy] = pos; + } + } + mouse_deltanoreset[joy][0] = 1; + mouse_deltanoreset[joy][1] = 1; + joydir[joy] = 0; + if (left) + joydir[joy] |= DIR_LEFT; + if (right) + joydir[joy] |= DIR_RIGHT; + if (top) + joydir[joy] |= DIR_UP; + if (bot) + joydir[joy] |= DIR_DOWN; + if (joy == 0 || joy == 1) + joymousecounter (joy); + } + break; + case 0: /* ->KEY */ + inputdevice_do_keyboard (ie->data, state); + break; + } + return 1; +} + +static void inputdevice_checkconfig (void) +{ + if ( + currprefs.jports[0].id != changed_prefs.jports[0].id || + currprefs.jports[1].id != changed_prefs.jports[1].id || +#ifndef INPUTDEVICE_SIMPLE + currprefs.jports[2].id != changed_prefs.jports[2].id || + currprefs.jports[3].id != changed_prefs.jports[3].id || +#endif + currprefs.jports[0].mode != changed_prefs.jports[0].mode || + currprefs.jports[1].mode != changed_prefs.jports[1].mode || +#ifndef INPUTDEVICE_SIMPLE + currprefs.jports[2].mode != changed_prefs.jports[2].mode || + currprefs.jports[3].mode != changed_prefs.jports[3].mode || +#endif + currprefs.input_selected_setting != changed_prefs.input_selected_setting || + currprefs.input_joymouse_multiplier != changed_prefs.input_joymouse_multiplier || + currprefs.input_joymouse_deadzone != changed_prefs.input_joymouse_deadzone || + currprefs.input_joystick_deadzone != changed_prefs.input_joystick_deadzone || + currprefs.input_joymouse_speed != changed_prefs.input_joymouse_speed || + currprefs.input_autofire_framecnt != changed_prefs.input_autofire_framecnt || + currprefs.input_mouse_speed != changed_prefs.input_mouse_speed) { + + currprefs.input_selected_setting = changed_prefs.input_selected_setting; + currprefs.input_joymouse_multiplier = changed_prefs.input_joymouse_multiplier; + currprefs.input_joymouse_deadzone = changed_prefs.input_joymouse_deadzone; + currprefs.input_joystick_deadzone = changed_prefs.input_joystick_deadzone; + currprefs.input_joymouse_speed = changed_prefs.input_joymouse_speed; + currprefs.input_autofire_framecnt = changed_prefs.input_autofire_framecnt; + currprefs.input_mouse_speed = changed_prefs.input_mouse_speed; + + inputdevice_updateconfig (&currprefs); + } } void inputdevice_vsync (void) { - getjoystate (1, &joy1dir, &joy1button); - getjoystate (0, &joy0dir, &joy0button); + input_frame++; + mouseupdate (0, 1); + + inputdevice_read (); + inputdelay = uaerand () % (maxvpos <= 1 ? 1 : maxvpos - 1); + + inputdevice_handle_inputcode (); + if (mousehack_alive_cnt > 0) { + mousehack_alive_cnt--; + } else if (mousehack_alive_cnt < 0) { + mousehack_alive_cnt++; + if (mousehack_alive_cnt == 0) { + mousehack_alive_cnt = 100; + } + } + inputdevice_checkconfig (); } void inputdevice_reset (void) { mousehack_reset (); - lastmx = lastmy = 0; - lastsampledmx = lastsampledmy = 0; - potgo_value = 0; + if (inputdevice_is_tablet ()) + mousehack_enable (); +} + +static int getoldport (struct uae_input_device *id) +{ + int i, j; + + for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + int evt = id->eventid[i][j]; + if (evt > 0) { + int unit = events[evt].unit; + if (unit >= 1 && unit <= 4) + return unit; + } + } + } + return -1; +} + +static int switchdevice (struct uae_input_device *id, int num, bool buttonmode) +{ + int i, j; + int ismouse = 0; + int newport = 0; + int flags = 0; + TCHAR *name = NULL; + int otherbuttonpressed = 0; + + if (num >= 4) + return 0; + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + if (id == &joysticks[i]) { + name = idev[IDTYPE_JOYSTICK].get_uniquename (i); + newport = num == 0 ? 1 : 0; + flags = idev[IDTYPE_JOYSTICK].get_flags (i); + for (j = 0; j < MAX_INPUT_DEVICES; j++) { + if (j != i) { + struct uae_input_device2 *id2 = &joysticks2[j]; + if (id2->buttonmask) + otherbuttonpressed = 1; + } + } + } + if (id == &mice[i]) { + ismouse = 1; + name = idev[IDTYPE_MOUSE].get_uniquename (i); + newport = num == 0 ? 0 : 1; + flags = idev[IDTYPE_MOUSE].get_flags (i); + } + } + if (!name) + return 0; + if (buttonmode) { + if (num == 0 && otherbuttonpressed) + newport = newport ? 0 : 1; + } else { + newport = num ? 1 : 0; + } + /* "GamePorts" switch if in GamePorts mode or Input mode and GamePorts port was not NONE */ + if (currprefs.input_selected_setting == GAMEPORT_INPUT_SETTINGS || currprefs.jports[newport].id != JPORT_NONE) { + if ((num == 0 || num == 1) && currprefs.jports[newport].id != JPORT_CUSTOM) { + int om = jsem_ismouse (num, &currprefs); + int om1 = jsem_ismouse (0, &currprefs); + int om2 = jsem_ismouse (1, &currprefs); + if ((om1 >= 0 || om2 >= 0) && ismouse) + return 0; + if (flags) + return 0; + if (name) { + write_log (_T("inputdevice change '%s':%d->%d\n"), name, num, newport); + inputdevice_joyport_config (&changed_prefs, name, newport, -1, 2); + inputdevice_copyconfig (&changed_prefs, &currprefs); + return 1; + } + } + return 0; + } else { + int oldport = getoldport (id); + int k, evt; + struct inputevent *ie, *ie2; + + if (flags) + return 0; + if (oldport <= 0) + return 0; + newport++; + /* do not switch if switching mouse and any "supermouse" mouse enabled */ + if (ismouse) { + for (i = 0; i < MAX_INPUT_SETTINGS; i++) { + if (mice[i].enabled && idev[IDTYPE_MOUSE].get_flags (i)) + return 0; + } + } + for (i = 0; i < MAX_INPUT_SETTINGS; i++) { + if (getoldport (&joysticks[i]) == newport) + joysticks[i].enabled = 0; + if (getoldport (&mice[i]) == newport) + mice[i].enabled = 0; + } + id->enabled = 1; + for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + evt = id->eventid[i][j]; + if (evt <= 0) + continue; + ie = &events[evt]; + if (ie->unit == oldport) { + k = 1; + while (events[k].confname) { + ie2 = &events[k]; + if (ie2->type == ie->type && ie2->data == ie->data && ie2->allow_mask == ie->allow_mask && ie2->unit == newport) { + id->eventid[i][j] = k; + break; + } + k++; + } + } else if (ie->unit == newport) { + k = 1; + while (events[k].confname) { + ie2 = &events[k]; + if (ie2->type == ie->type && ie2->data == ie->data && ie2->allow_mask == ie->allow_mask && ie2->unit == oldport) { + id->eventid[i][j] = k; + break; + } + k++; + } + } + } + } + write_log (_T("inputdevice change '%s':%d->%d\n"), name, num, newport); + inputdevice_copyconfig (&currprefs, &changed_prefs); + inputdevice_copyconfig (&changed_prefs, &currprefs); + return 1; + } + return 0; +} + +int input_getqualifiers (void) +{ + return qualifiers; +} + +static bool checkqualifiers (int evt, int flags, int qualmask) +{ + flags &= ID_FLAG_QUALIFIER_MASK; + /* special set and new qualifier pressed? do not sent it to Amiga-side */ + if ((qualifiers & ID_FLAG_QUALIFIER_SPECIAL) && isqual (evt)) + return false; + if (!qualmask) // no qualifiers in any slot + return true; + if (flags == qualifiers || (flags && flags == (qualifiers & ~ID_FLAG_QUALIFIER_SPECIAL))) + return true; + return false; +} +static void setqualifiers (int evt, int state) +{ + int mask = isqual (evt); + if (!mask) + return; + if (state) + qualifiers |= mask; + else + qualifiers &= ~mask; +} +static int getqualmask (struct uae_input_device *id, int num, bool *qualonly) +{ + int mask = 0, mask2 = 0; + for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) { + int evt = id->eventid[num][i]; + mask |= id->flags[num][i]; + mask2 |= isqual (evt); + } + mask &= ID_FLAG_QUALIFIER_MASK; + *qualonly = false; + if (qualifiers & ID_FLAG_QUALIFIER_SPECIAL) { + // ID_FLAG_QUALIFIER_SPECIAL already active and this event has one or more qualifiers configured + *qualonly = mask2 != 0; + } + return mask; +} + +static void process_custom_event (struct uae_input_device *id, int offset, int state, int qualmask, int autofire) +{ + int idx, slotoffset, flags, custompos; + +#ifdef INPUTDEVICE_SIMPLE + queue_input_event (-1, -1, 0, 0); +#else + queue_input_event (-1, NULL, -1, 0, 0, 1); +#endif + if (!id) + return; + + slotoffset = 0; + if (!checkqualifiers (id->eventid[offset][slotoffset], id->flags[offset][slotoffset], qualmask)) { + slotoffset = 4; + if (!checkqualifiers (id->eventid[offset][slotoffset], id->flags[offset][slotoffset], qualmask)) + return; + } + + flags = id->flags[offset][slotoffset]; + custompos = (flags & ID_FLAG_CUSTOMEVENT_TOGGLED) ? 1 : 0; + + idx = -1; + if (state < 0) { + idx = 0; + custompos = 0; + } else { + idx = state > 0 ? 0 : 1; + if (custompos) + idx += 2; + if (state == 0) + custompos ^= 1; + } + + if (autofire) +#ifdef INPUTDEVICE_SIMPLE + queue_input_event (-1, 1, 1, currprefs.input_autofire_framecnt * 312); +#else + queue_input_event (-1, NULL, 1, 1, currprefs.input_autofire_framecnt * 312, 1); +#endif + if (state) { + id->flags[offset][slotoffset] &= ~ID_FLAG_CUSTOMEVENT_TOGGLED; + id->flags[offset][slotoffset] |= custompos ? ID_FLAG_CUSTOMEVENT_TOGGLED : 0; + } +} + +static void setbuttonstateall (struct uae_input_device *id, struct uae_input_device2 *id2, int button, int state) +{ + static frame_time_t switchdevice_timeout; + int i; + uae_u32 mask = 1 << button; + uae_u32 omask = id2->buttonmask & mask; + uae_u32 nmask = (state ? 1 : 0) << button; + int qualmask; + bool qualonly; + + if (!id->enabled) { + frame_time_t t = read_processor_time (); + if (state) { + switchdevice_timeout = t; + } else { + int port = button; + if (t - switchdevice_timeout >= syncbase) // 1s + port ^= 1; + switchdevice (id, port, true); + } + return; + } + if (button >= ID_BUTTON_TOTAL) + return; + + qualmask = getqualmask (id, ID_BUTTON_OFFSET + button, &qualonly); + + for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) { + uae_u32 *flagsp = &id->flags[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]]; + int evt = evt = id->eventid[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]]; + int flags = flagsp[0]; + int autofire = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0; +#ifndef INPUTDEVICE_SIMPLE + int toggle = (flags & ID_FLAG_TOGGLE) ? 1 : 0; + int inverttoggle = (flags & ID_FLAG_INVERTTOGGLE) ? 1 : 0; +#endif + + if (!state) { + if (i == 0) + process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire); + } + + setqualifiers (flags, state > 0); + if (qualonly) + continue; + +#ifndef INPUTDEVICE_SIMPLE + if (state < 0) { + if (!checkqualifiers (evt, flags, qualmask)) + continue; + handle_input_event (evt, 1, 1, 0, true, false); + queue_input_event (evt, NULL, 0, 1, 1, 0); /* send release event next frame */ + process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, 0); + } else if (inverttoggle) { + /* pressed = firebutton, not pressed = autofire */ + if (state) { + queue_input_event (evt, NULL, -1, 0, 0, 1); + handle_input_event (evt, 1, 1, 0, true, false); + } else { + handle_input_event (evt, 1, 1, autofire, true, false); + } + if (i == 0) + process_custom_event (id, ID_BUTTON_OFFSET + button, 1, qualmask, autofire); + } else if (toggle) { + if (!state) + continue; + if (omask & mask) + continue; + if (!checkqualifiers (evt, flags, qualmask)) + continue; + *flagsp ^= ID_FLAG_TOGGLED; + int toggled = (*flagsp & ID_FLAG_TOGGLED) ? 1 : 0; + handle_input_event (evt, toggled, 1, autofire, true, false); + if (i == 0) + process_custom_event (id, ID_BUTTON_OFFSET + button, toggled, qualmask, autofire); + } else { +#endif + if (!checkqualifiers (evt, flags, qualmask)) { + if (!state && !(flags & ID_FLAG_CANRELEASE)) { + continue; + } else if (state) { + continue; + } + } + if (!state) + *flagsp &= ~ID_FLAG_CANRELEASE; + else + *flagsp |= ID_FLAG_CANRELEASE; + if ((omask ^ nmask) & mask) { +#ifdef INPUTDEVICE_SIMPLE + handle_input_event (evt, state, 1, autofire); +#else + handle_input_event (evt, state, 1, autofire, true, false); +#endif + if (i == 0) + process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire); + } +#ifndef INPUTDEVICE_SIMPLE + } +#endif + } + + if ((omask ^ nmask) & mask) { + if (state) + id2->buttonmask |= mask; + else + id2->buttonmask &= ~mask; + } +} + + +/* - detect required number of joysticks and mice from configuration data +* - detect if CD32 pad emulation is needed +* - detect device type in ports (mouse or joystick) +*/ + +static int iscd32 (int ei) +{ + if (ei >= INPUTEVENT_JOY1_CD32_FIRST && ei <= INPUTEVENT_JOY1_CD32_LAST) { + cd32_pad_enabled[0] = 1; + return 1; + } + if (ei >= INPUTEVENT_JOY2_CD32_FIRST && ei <= INPUTEVENT_JOY2_CD32_LAST) { + cd32_pad_enabled[1] = 1; + return 2; + } + return 0; +} + +#ifndef INPUTDEVICE_SIMPLE +static int isparport (int ei) +{ + if (ei > INPUTEVENT_PAR_JOY1_START && ei < INPUTEVENT_PAR_JOY_END) { + parport_joystick_enabled = 1; + return 1; + } + return 0; +} +#endif + +static int ismouse (int ei) +{ + if (ei >= INPUTEVENT_MOUSE1_FIRST && ei <= INPUTEVENT_MOUSE1_LAST) { + mouse_port[0] = 1; + return 1; + } + if (ei >= INPUTEVENT_MOUSE2_FIRST && ei <= INPUTEVENT_MOUSE2_LAST) { + mouse_port[1] = 1; + return 2; + } + return 0; +} + +#ifndef INPUTDEVICE_SIMPLE +static int isanalog (int ei) +{ + if (ei == INPUTEVENT_JOY1_HORIZ_POT || ei == INPUTEVENT_JOY1_HORIZ_POT_INV) { + analog_port[0][0] = 1; + return 1; + } + if (ei == INPUTEVENT_JOY1_VERT_POT || ei == INPUTEVENT_JOY1_VERT_POT_INV) { + analog_port[0][1] = 1; + return 1; + } + if (ei == INPUTEVENT_JOY2_HORIZ_POT || ei == INPUTEVENT_JOY2_HORIZ_POT_INV) { + analog_port[1][0] = 1; + return 1; + } + if (ei == INPUTEVENT_JOY2_VERT_POT || ei == INPUTEVENT_JOY2_VERT_POT_INV) { + analog_port[1][1] = 1; + return 1; + } + return 0; +} +#endif + +static int isdigitalbutton (int ei) +{ + if (ei == INPUTEVENT_JOY1_2ND_BUTTON) { + digital_port[0][1] = 1; + return 1; + } + if (ei == INPUTEVENT_JOY1_3RD_BUTTON) { + digital_port[0][0] = 1; + return 1; + } + if (ei == INPUTEVENT_JOY2_2ND_BUTTON) { + digital_port[1][1] = 1; + return 1; + } + if (ei == INPUTEVENT_JOY2_3RD_BUTTON) { + digital_port[1][0] = 1; + return 1; + } + return 0; +} + +static void isqualifier (int ei) +{ +} + +static void scanevents (struct uae_prefs *p) +{ + int i, j, k, ei; + const struct inputevent *e; + int n_joy = idev[IDTYPE_JOYSTICK].get_num (); + int n_mouse = idev[IDTYPE_MOUSE].get_num (); + + cd32_pad_enabled[0] = cd32_pad_enabled[1] = 0; +#ifndef INPUTDEVICE_SIMPLE + parport_joystick_enabled = 0; +#endif + mouse_port[0] = mouse_port[1] = 0; + qualifiers = 0; + + for (i = 0; i < NORMAL_JPORTS; i++) { + for (j = 0; j < 2; j++) { + digital_port[i][j] = 0; +#ifndef INPUTDEVICE_SIMPLE + analog_port[i][j] = 0; + joydirpot[i][j] = 128 / (312 * 100 / currprefs.input_analog_joystick_mult) + (128 * currprefs.input_analog_joystick_mult / 100) + currprefs.input_analog_joystick_offset; +#endif + } + } + + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + use_joysticks[i] = 0; + use_mice[i] = 0; + for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) { + for (j = 0; j < ID_BUTTON_TOTAL; j++) { + + if ((joysticks[i].enabled && i < n_joy) || joysticks[i].enabled < 0) { + ei = joysticks[i].eventid[ID_BUTTON_OFFSET + j][k]; + e = &events[ei]; + iscd32 (ei); +#ifndef INPUTDEVICE_SIMPLE + isparport (ei); +#endif + ismouse (ei); + isdigitalbutton (ei); +#ifndef INPUTDEVICE_SIMPLE + isqualifier (ei); +#endif + if (joysticks[i].eventid[ID_BUTTON_OFFSET + j][k] > 0) + use_joysticks[i] = 1; + } + if ((mice[i].enabled && i < n_mouse) || mice[i].enabled < 0) { + ei = mice[i].eventid[ID_BUTTON_OFFSET + j][k]; + e = &events[ei]; + iscd32 (ei); +#ifndef INPUTDEVICE_SIMPLE + isparport (ei); +#endif + ismouse (ei); + isdigitalbutton (ei); +#ifndef INPUTDEVICE_SIMPLE + isqualifier (ei); +#endif + if (mice[i].eventid[ID_BUTTON_OFFSET + j][k] > 0) + use_mice[i] = 1; + } + + } + + for (j = 0; j < ID_AXIS_TOTAL; j++) { + + if ((joysticks[i].enabled && i < n_joy) || joysticks[i].enabled < 0) { + ei = joysticks[i].eventid[ID_AXIS_OFFSET + j][k]; + iscd32 (ei); +#ifndef INPUTDEVICE_SIMPLE + isparport (ei); +#endif + ismouse (ei); +#ifndef INPUTDEVICE_SIMPLE + isanalog (ei); +#endif + isdigitalbutton (ei); +#ifndef INPUTDEVICE_SIMPLE + isqualifier (ei); +#endif + if (ei > 0) + use_joysticks[i] = 1; + } + if ((mice[i].enabled && i < n_mouse) || mice[i].enabled < 0) { + ei = mice[i].eventid[ID_AXIS_OFFSET + j][k]; + iscd32 (ei); +#ifndef INPUTDEVICE_SIMPLE + isparport (ei); +#endif + ismouse (ei); +#ifndef INPUTDEVICE_SIMPLE + isanalog (ei); +#endif + isdigitalbutton (ei); +#ifndef INPUTDEVICE_SIMPLE + isqualifier (ei); +#endif + if (ei > 0) + use_mice[i] = 1; + } + } + } + } + memset (scancodeused, 0, sizeof scancodeused); + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + use_keyboards[i] = 0; + if (keyboards[i].enabled && i < idev[IDTYPE_KEYBOARD].get_num ()) { + j = 0; + while (j < MAX_INPUT_DEVICE_EVENTS && keyboards[i].extra[j] >= 0) { + use_keyboards[i] = 1; + for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) { + ei = keyboards[i].eventid[j][k]; + iscd32 (ei); +#ifndef INPUTDEVICE_SIMPLE + isparport (ei); +#endif + ismouse (ei); + isdigitalbutton (ei); +#ifndef INPUTDEVICE_SIMPLE + isqualifier (ei); +#endif + if (ei > 0) + scancodeused[i][keyboards[i].extra[j]] = ei; + } + j++; + } + } + } +} + +static int axistable[] = { + INPUTEVENT_MOUSE1_HORIZ, INPUTEVENT_MOUSE1_LEFT, INPUTEVENT_MOUSE1_RIGHT, + INPUTEVENT_MOUSE1_VERT, INPUTEVENT_MOUSE1_UP, INPUTEVENT_MOUSE1_DOWN, + INPUTEVENT_MOUSE2_HORIZ, INPUTEVENT_MOUSE2_LEFT, INPUTEVENT_MOUSE2_RIGHT, + INPUTEVENT_MOUSE2_VERT, INPUTEVENT_MOUSE2_UP, INPUTEVENT_MOUSE2_DOWN, + INPUTEVENT_JOY1_HORIZ, INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, + INPUTEVENT_JOY1_VERT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN, + INPUTEVENT_JOY2_HORIZ, INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, + INPUTEVENT_JOY2_VERT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN, + INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_LEFT, INPUTEVENT_LIGHTPEN_RIGHT, + INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_LIGHTPEN_UP, INPUTEVENT_LIGHTPEN_DOWN, + INPUTEVENT_PAR_JOY1_HORIZ, INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, + INPUTEVENT_PAR_JOY1_VERT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN, + INPUTEVENT_PAR_JOY2_HORIZ, INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, + INPUTEVENT_PAR_JOY2_VERT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN, + INPUTEVENT_MOUSE_CDTV_HORIZ, INPUTEVENT_MOUSE_CDTV_LEFT, INPUTEVENT_MOUSE_CDTV_RIGHT, + INPUTEVENT_MOUSE_CDTV_VERT, INPUTEVENT_MOUSE_CDTV_UP, INPUTEVENT_MOUSE_CDTV_DOWN, + -1 +}; + +int intputdevice_compa_get_eventtype (int evt, int **axistablep) +{ + for (int i = 0; axistable[i] >= 0; i += 3) { + *axistablep = &axistable[i]; + if (axistable[i] == evt) + return IDEV_WIDGET_AXIS; + if (axistable[i + 1] == evt) + return IDEV_WIDGET_BUTTONAXIS; + if (axistable[i + 2] == evt) + return IDEV_WIDGET_BUTTONAXIS; + } + *axistablep = NULL; + return IDEV_WIDGET_BUTTON; +} + +static int rem_port1[] = { + INPUTEVENT_MOUSE1_HORIZ, INPUTEVENT_MOUSE1_VERT, + INPUTEVENT_JOY1_HORIZ, INPUTEVENT_JOY1_VERT, +#ifndef INPUTDEVICE_SIMPLE + INPUTEVENT_JOY1_HORIZ_POT, INPUTEVENT_JOY1_VERT_POT, +#endif + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON, + INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW, + INPUTEVENT_JOY1_CD32_RWD, INPUTEVENT_JOY1_CD32_FFW, INPUTEVENT_JOY1_CD32_PLAY, + INPUTEVENT_MOUSE_CDTV_HORIZ, INPUTEVENT_MOUSE_CDTV_VERT, + INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, + -1 +}; +static int rem_port2[] = { + INPUTEVENT_MOUSE2_HORIZ, INPUTEVENT_MOUSE2_VERT, + INPUTEVENT_JOY2_HORIZ, INPUTEVENT_JOY2_VERT, +#ifndef INPUTDEVICE_SIMPLE + INPUTEVENT_JOY2_HORIZ_POT, INPUTEVENT_JOY2_VERT_POT, +#endif + INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON, + INPUTEVENT_JOY2_CD32_RED, INPUTEVENT_JOY2_CD32_BLUE, INPUTEVENT_JOY2_CD32_GREEN, INPUTEVENT_JOY2_CD32_YELLOW, + INPUTEVENT_JOY2_CD32_RWD, INPUTEVENT_JOY2_CD32_FFW, INPUTEVENT_JOY2_CD32_PLAY, + -1, -1, + -1, -1, + -1 +}; +static int rem_port3[] = { + INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN, + INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON, + -1 +}; +static int rem_port4[] = { + INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN, + INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON, + -1 +}; + +static int *rem_ports[] = { rem_port1, rem_port2, rem_port3, rem_port4 }; +static int af_port1[] = { + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_CD32_RED, + -1 +}; +static int af_port2[] = { + INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_CD32_RED, + -1 +}; +static int af_port3[] = { + INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON, + -1 +}; +static int af_port4[] = { + INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON, + -1 +}; +static int *af_ports[] = { af_port1, af_port2, af_port3, af_port4 }; +static int ip_joy1[] = { + INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN, + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, + -1 +}; +static int ip_joy2[] = { + INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN, + INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, + -1 +}; +static int ip_joypad1[] = { + INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN, + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON, + -1 +}; +static int ip_joypad2[] = { + INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN, + INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON, + -1 +}; +static int ip_joycd321[] = { + INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN, + INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW, + INPUTEVENT_JOY1_CD32_RWD, INPUTEVENT_JOY1_CD32_FFW, INPUTEVENT_JOY1_CD32_PLAY, + -1 +}; +static int ip_joycd322[] = { + INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN, + INPUTEVENT_JOY2_CD32_RED, INPUTEVENT_JOY2_CD32_BLUE, INPUTEVENT_JOY2_CD32_GREEN, INPUTEVENT_JOY2_CD32_YELLOW, + INPUTEVENT_JOY2_CD32_RWD, INPUTEVENT_JOY2_CD32_FFW, INPUTEVENT_JOY2_CD32_PLAY, + -1 +}; +static int ip_parjoy1[] = { + INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN, + INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON, + -1 +}; +static int ip_parjoy2[] = { + INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN, + INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON, + -1 +}; +static int ip_parjoy1default[] = { + INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN, + INPUTEVENT_PAR_JOY1_FIRE_BUTTON, + -1 +}; +static int ip_parjoy2default[] = { + INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN, + INPUTEVENT_PAR_JOY2_FIRE_BUTTON, + -1 +}; +static int ip_mouse1[] = { + INPUTEVENT_MOUSE1_LEFT, INPUTEVENT_MOUSE1_RIGHT, INPUTEVENT_MOUSE1_UP, INPUTEVENT_MOUSE1_DOWN, + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, + -1 +}; +static int ip_mouse2[] = { + INPUTEVENT_MOUSE2_LEFT, INPUTEVENT_MOUSE2_RIGHT, INPUTEVENT_MOUSE2_UP, INPUTEVENT_MOUSE2_DOWN, + INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, + -1 +}; +static int ip_mousecdtv[] = +{ + INPUTEVENT_MOUSE_CDTV_LEFT, INPUTEVENT_MOUSE_CDTV_RIGHT, INPUTEVENT_MOUSE_CDTV_UP, INPUTEVENT_MOUSE_CDTV_DOWN, + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, + -1 +}; +static int ip_mediacdtv[] = +{ + INPUTEVENT_KEY_CDTV_PLAYPAUSE, INPUTEVENT_KEY_CDTV_STOP, INPUTEVENT_KEY_CDTV_PREV, INPUTEVENT_KEY_CDTV_NEXT, + -1 +}; +static int ip_arcadia[] = { + INPUTEVENT_SPC_ARCADIA_DIAGNOSTICS, INPUTEVENT_SPC_ARCADIA_PLAYER1, INPUTEVENT_SPC_ARCADIA_PLAYER2, + INPUTEVENT_SPC_ARCADIA_COIN1, INPUTEVENT_SPC_ARCADIA_COIN2, + -1 +}; +static int ip_lightpen1[] = { + INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_JOY1_3RD_BUTTON, + -1 +}; +static int ip_lightpen2[] = { + INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_JOY2_3RD_BUTTON, + -1 +}; +static int ip_analog1[] = { + INPUTEVENT_JOY1_HORIZ_POT, INPUTEVENT_JOY1_VERT_POT, INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, + -1 +}; +static int ip_analog2[] = { + INPUTEVENT_JOY2_HORIZ_POT, INPUTEVENT_JOY2_VERT_POT, INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, + -1 +}; + +static int ip_arcadiaxa[] = { + -1 +}; + +static void checkcompakb (int *kb, int *srcmap) +{ + int found = 0, avail = 0; + int j, k; + + k = j = 0; + while (kb[j] >= 0) { + struct uae_input_device *uid = &keyboards[0]; + while (kb[j] >= 0 && srcmap[k] >= 0) { + int id = kb[j]; + for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) { + if (uid->extra[l] == id) { + avail++; + if (uid->eventid[l][0] == srcmap[k]) + found++; + break; + } + } + j++; + } + if (srcmap[k] < 0) + break; + j++; + k++; + } + if (avail != found || avail == 0) + return; + k = j = 0; + while (kb[j] >= 0) { + struct uae_input_device *uid = &keyboards[0]; + while (kb[j] >= 0) { + int id = kb[j]; + int evt0 = 0, evt1 = 0; + k = 0; + while (keyboard_default[k].scancode >= 0) { + if (keyboard_default[k].scancode == kb[j]) { + for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) { + if (uid->extra[l] == id) { + for (int m = 0; m < MAX_INPUT_SUB_EVENT && keyboard_default[k].node[m].evt; m++) { + uid->eventid[l][m] = keyboard_default[k].node[m].evt; + } + break; + } + } + break; + } + k++; + } + j++; + } + j++; + } +} + +static void setautofireevent (struct uae_input_device *uid, int num, int sub, int af, int index) +{ + if (!af) + return; + int *afp = af_ports[index]; + for (int k = 0; afp[k] >= 0; k++) { + if (afp[k] == uid->eventid[num][sub]) { + uid->flags[num][sub] &= ~ID_FLAG_AUTOFIRE_MASK; + if (af >= JPORT_AF_NORMAL) + uid->flags[num][sub] |= ID_FLAG_AUTOFIRE; +#ifndef INPUTDEVICE_SIMPLE + if (af == JPORT_AF_TOGGLE) + uid->flags[num][sub] |= ID_FLAG_TOGGLE; + if (af == JPORT_AF_ALWAYS) + uid->flags[num][sub] |= ID_FLAG_INVERTTOGGLE; +#endif + return; + } + } +} + +static void sparerestore (struct uae_input_device *uid, int num, int sub) +{ + uid->eventid[num][sub] = uid->eventid[num][SPARE_SUB_EVENT]; + uid->flags[num][sub] = uid->flags[num][SPARE_SUB_EVENT]; + uid->custom[num][sub] = uid->custom[num][SPARE_SUB_EVENT]; + uid->eventid[num][SPARE_SUB_EVENT] = 0; + uid->flags[num][SPARE_SUB_EVENT] = 0; + uid->port[num][SPARE_SUB_EVENT] = 0; + uid->custom[num][SPARE_SUB_EVENT] = 0; +} + +static void sparecopy (struct uae_input_device *uid, int num, int sub) +{ + uid->eventid[num][SPARE_SUB_EVENT] = uid->eventid[num][sub]; + uid->flags[num][SPARE_SUB_EVENT] = uid->flags[num][sub]; + uid->port[num][SPARE_SUB_EVENT] = MAX_JPORTS + 1; + xfree (uid->custom[num][SPARE_SUB_EVENT]); + uid->custom[num][SPARE_SUB_EVENT] = uid->custom[num][sub]; + uid->custom[num][sub] = NULL; +} + +static void setcompakb (int *kb, int *srcmap, int index, int af) +{ + int j, k; + k = j = 0; + while (kb[j] >= 0 && srcmap[k] >= 0) { + while (kb[j] >= 0) { + int id = kb[j]; + for (int m = 0; m < MAX_INPUT_DEVICES; m++) { + struct uae_input_device *uid = &keyboards[m]; + for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) { + if (uid->extra[l] == id) { + sparecopy (uid, l, 0); + uid->eventid[l][0] = srcmap[k]; + uid->flags[l][0] = 0; + uid->port[l][0] = index + 1; + xfree (uid->custom[l][0]); + uid->custom[l][0] = NULL; + setautofireevent (uid, l, 0, af, index); + break; + } + } + } + j++; + } + j++; + k++; + } +} + +int inputdevice_get_compatibility_input (struct uae_prefs *prefs, int index, int *typelist, int **inputlist, int **at) +{ + if (index >= MAX_JPORTS || joymodes[index] < 0) + return 0; + *typelist = joymodes[index]; + *inputlist = joyinputs[index]; + *at = axistable; + int cnt = 0; + for (int i = 0; joyinputs[index] && joyinputs[index][i] >= 0; i++, cnt++); + return cnt; +} + +static void clearevent (struct uae_input_device *uid, int evt) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (uid->eventid[i][j] == evt) { + uid->eventid[i][j] = 0; + uid->flags[i][j] = 0; + xfree (uid->custom[i][j]); + uid->custom[i][j] = NULL; + } + } + } +} +static void clearkbrevent (struct uae_input_device *uid, int evt) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (uid->eventid[i][j] == evt) { + uid->eventid[i][j] = 0; + uid->flags[i][j] = 0; + xfree (uid->custom[i][j]); + uid->custom[i][j] = NULL; + if (j == 0) + set_kbr_default_event (uid, keyboard_default, i); + } + } + } +} + +static void resetjport (struct uae_prefs *prefs, int index) +{ + int *p = rem_ports[index]; + while (*p >= 0) { + int evtnum = *p++; + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum); + clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum); + clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum); + } + for (int i = 0; axistable[i] >= 0; i += 3) { + if (evtnum == axistable[i] || evtnum == axistable[i + 1] || evtnum == axistable[i + 2]) { + for (int j = 0; j < 3; j++) { + int evtnum2 = axistable[i + j]; + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2); + clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2); + clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2); + } + } + break; + } + } + } +} + +static void remove_compa_config (struct uae_prefs *prefs, int index) +{ + int typelist, *inputlist, *atp; + + if (!inputdevice_get_compatibility_input (prefs, index, &typelist, &inputlist, &atp)) + return; + for (int i = 0; inputlist[i] >= 0; i++) { + int evtnum = inputlist[i]; + + int atpidx = 0; + while (*atp >= 0) { + if (*atp == evtnum) { + atp++; + atpidx = 2; + break; + } + if (atp[1] == evtnum || atp[2] == evtnum) { + atpidx = 1; + break; + } + atp += 3; + } + while (atpidx >= 0) { + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum); + clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum); + clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum); + } + evtnum = *atp++; + atpidx--; + } + } +} + +static void cleardevgp (struct uae_input_device *uid, int num, bool nocustom, int index) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (uid[num].port[i][j] == index + 1) { + if (nocustom && (uid[num].flags[i][j] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) + continue; + uid[num].eventid[i][j] = 0; + uid[num].flags[i][j] = 0; + xfree (uid[num].custom[i][j]); + uid[num].custom[i][j] = NULL; + uid[num].port[i][j] = 0; + if (uid[num].port[i][SPARE_SUB_EVENT]) + sparerestore (&uid[num], i, j); + } + } + } +} +static void cleardevkbrgp (struct uae_input_device *uid, int num, bool nocustom, int index) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (uid[num].port[i][j] == index + 1) { + if (nocustom && (uid[num].flags[i][j] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) + continue; + uid[num].eventid[i][j] = 0; + uid[num].flags[i][j] = 0; + xfree (uid[num].custom[i][j]); + uid[num].custom[i][j] = NULL; + uid[num].port[i][j] = 0; + if (uid[num].port[i][SPARE_SUB_EVENT]) { + sparerestore (&uid[num], i, j); + } else if (j == 0) { + set_kbr_default_event (&uid[num], keyboard_default, i); + } + } + } + } +} + +// remove all gameports mappings mapped to port 'index' +static void remove_custom_config (struct uae_prefs *prefs, bool nocustom, int index) +{ + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + cleardevgp (joysticks, l, nocustom, index); + cleardevgp (mice, l, nocustom, index); + cleardevkbrgp (keyboards, l, nocustom, index); + } +} + +// prepare port for custom mapping, remove all current Amiga side device mappings +void inputdevice_compa_prepare_custom (struct uae_prefs *prefs, int index, int newmode) +{ + int mode = prefs->jports[index].mode; + freejport (prefs, index); + resetjport (prefs, index); + if (newmode >= 0) { + mode = newmode; + } else if (mode == 0) { + mode = index == 0 ? JSEM_MODE_MOUSE : (prefs->cs_cd32cd ? JSEM_MODE_JOYSTICK_CD32 : JSEM_MODE_JOYSTICK); + } + prefs->jports[index].mode = mode; + prefs->jports[index].id = -2; + + remove_compa_config (prefs, index); + remove_custom_config (prefs, false, index); +} +// clear device before switching to new one +void inputdevice_compa_clear (struct uae_prefs *prefs, int index) +{ + freejport (prefs, index); + resetjport (prefs, index); + remove_compa_config (prefs, index); +} + +static void cleardev (struct uae_input_device *uid, int num) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + uid[num].eventid[i][j] = 0; + uid[num].flags[i][j] = 0; + xfree (uid[num].custom[i][j]); + uid[num].custom[i][j] = NULL; + } + } +} + +static void enablejoydevice (struct uae_input_device *uid, bool gameportsmode, int evtnum) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if ((gameportsmode && uid->eventid[i][j] == evtnum) || uid->port[i][j] > 0) { + uid->enabled = 1; + } + } + } +} + +static void setjoydevices (struct uae_prefs *prefs, bool gameportsmode, int port) +{ + for (int i = 0; joyinputs[port] && joyinputs[port][i] >= 0; i++) { + int evtnum = joyinputs[port][i]; + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + enablejoydevice (&joysticks[l], gameportsmode, evtnum); + enablejoydevice (&mice[l], gameportsmode, evtnum); + enablejoydevice (&keyboards[l], gameportsmode, evtnum); + } + for (int k = 0; axistable[k] >= 0; k += 3) { + if (evtnum == axistable[k] || evtnum == axistable[k + 1] || evtnum == axistable[k + 2]) { + for (int j = 0; j < 3; j++) { + int evtnum2 = axistable[k + j]; + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + enablejoydevice (&joysticks[l], gameportsmode, evtnum2); + enablejoydevice (&mice[l], gameportsmode, evtnum2); + enablejoydevice (&keyboards[l], gameportsmode, evtnum2); + } + } + break; + } + } + + } +} + +static void setjoyinputs (struct uae_prefs *prefs, int port) +{ + joyinputs[port] = NULL; + switch (joymodes[port]) + { + case JSEM_MODE_JOYSTICK: + if (port >= 2) + joyinputs[port] = port == 3 ? ip_parjoy2 : ip_parjoy1; + else + joyinputs[port] = port == 1 ? ip_joy2 : ip_joy1; + break; + case JSEM_MODE_GAMEPAD: + joyinputs[port] = port ? ip_joypad2 : ip_joypad1; + break; + case JSEM_MODE_JOYSTICK_CD32: + joyinputs[port] = port ? ip_joycd322 : ip_joycd321; + break; + case JSEM_MODE_JOYSTICK_ANALOG: + joyinputs[port] = port ? ip_analog2 : ip_analog1; + break; + case JSEM_MODE_MOUSE: + joyinputs[port] = port ? ip_mouse2 : ip_mouse1; + break; + case JSEM_MODE_LIGHTPEN: + joyinputs[port] = port ? ip_lightpen2 : ip_lightpen1; + break; + case JSEM_MODE_MOUSE_CDTV: + joyinputs[port] = ip_mousecdtv; + break; + } +} + +static void setautofire (struct uae_input_device *uid, int port, int af) +{ + int *afp = af_ports[port]; + for (int k = 0; afp[k] >= 0; k++) { + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (uid->eventid[i][j] == afp[k]) { + uid->flags[i][j] &= ~ID_FLAG_AUTOFIRE_MASK; + if (af >= JPORT_AF_NORMAL) + uid->flags[i][j] |= ID_FLAG_AUTOFIRE; +#ifndef INPUTDEVICE_SIMPLE + if (af == JPORT_AF_TOGGLE) + uid->flags[i][j] |= ID_FLAG_TOGGLE; + if (af == JPORT_AF_ALWAYS) + uid->flags[i][j] |= ID_FLAG_INVERTTOGGLE; +#endif + } + } + } + } +} + +static void setautofires (struct uae_prefs *prefs, int port, int af) +{ + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + setautofire (&joysticks[l], port, af); + setautofire (&mice[l], port, af); + setautofire (&keyboards[l], port, af); + } +} + +// merge gameport settings with current input configuration +static void compatibility_copy (struct uae_prefs *prefs, bool gameports) +{ + int used[MAX_INPUT_DEVICES] = { 0 }; + int i, joy; + + for (i = 0; i < MAX_JPORTS; i++) { + joymodes[i] = prefs->jports[i].mode; + joyinputs[i]= NULL; + // remove all mappings from this port, except if custom + if (prefs->jports[i].id != JPORT_CUSTOM) { + if (gameports) + remove_compa_config (prefs, i); + } + remove_custom_config (prefs, prefs->jports[i].id == JPORT_CUSTOM, i); + setjoyinputs (prefs, i); + } + + for (i = 0; i < 2; i++) { + int af = prefs->jports[i].autofire; + if (prefs->jports[i].id >= 0 && joymodes[i] <= 0) { + int mode = prefs->jports[i].mode; + if (jsem_ismouse (i, prefs) >= 0) { + switch (mode) + { + case JSEM_MODE_DEFAULT: + case JSEM_MODE_MOUSE: + default: + joymodes[i] = JSEM_MODE_MOUSE; + joyinputs[i] = i ? ip_mouse2 : ip_mouse1; + break; +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_LIGHTPEN: + joymodes[i] = JSEM_MODE_LIGHTPEN; + joyinputs[i] = i ? ip_lightpen2 : ip_lightpen1; + break; + case JSEM_MODE_MOUSE_CDTV: + joymodes[i] = JSEM_MODE_MOUSE_CDTV; + joyinputs[i] = ip_mousecdtv; + break; +#endif + } + } else if (jsem_isjoy (i, prefs) >= 0) { + switch (mode) + { + case JSEM_MODE_DEFAULT: + case JSEM_MODE_JOYSTICK: +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_GAMEPAD: +#endif + case JSEM_MODE_JOYSTICK_CD32: + default: + { + bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd); + if (iscd32) { + joymodes[i] = JSEM_MODE_JOYSTICK_CD32; + joyinputs[i] = i ? ip_joycd322 : ip_joycd321; +#ifndef INPUTDEVICE_SIMPLE + } else if (mode == JSEM_MODE_GAMEPAD) { + joymodes[i] = JSEM_MODE_GAMEPAD; + joyinputs[i] = i ? ip_joypad2 : ip_joypad1; +#endif + } else { + joymodes[i] = JSEM_MODE_JOYSTICK; + joyinputs[i] = i ? ip_joy2 : ip_joy1; + } + break; + } +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_JOYSTICK_ANALOG: + joymodes[i] = JSEM_MODE_JOYSTICK_ANALOG; + joyinputs[i] = i ? ip_analog2 : ip_analog1; + break; +#endif + case JSEM_MODE_MOUSE: + joymodes[i] = JSEM_MODE_MOUSE; + joyinputs[i] = i ? ip_mouse2 : ip_mouse1; + break; +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_LIGHTPEN: + joymodes[i] = JSEM_MODE_LIGHTPEN; + joyinputs[i] = i ? ip_lightpen2 : ip_lightpen1; + break; + case JSEM_MODE_MOUSE_CDTV: + joymodes[i] = JSEM_MODE_MOUSE_CDTV; + joyinputs[i] = ip_mousecdtv; + break; +#endif + } + } else if (prefs->jports[i].id >= 0) { + joymodes[i] = i ? JSEM_MODE_JOYSTICK : JSEM_MODE_MOUSE; + joyinputs[i] = i ? ip_joy2 : ip_mouse1; + } + } + } + +#ifndef INPUTDEVICE_SIMPLE + for (i = 2; i < MAX_JPORTS; i++) { + if (prefs->jports[i].id >= 0 && joymodes[i] <= 0) { + int mode = prefs->jports[i].mode; + if (jsem_isjoy (i, prefs) >= 0) { + joymodes[i] = JSEM_MODE_JOYSTICK; + joyinputs[i] = i == 3 ? ip_parjoy2 : ip_parjoy1; + } else if (prefs->jports[i].id >= 0) { + prefs->jports[i].mode = joymodes[i] = JSEM_MODE_JOYSTICK; + joyinputs[i] = i == 3 ? ip_parjoy2 : ip_parjoy1; + } + } + } +#endif + + for (i = 0; i < 2; i++) { + int af = prefs->jports[i].autofire; + if (prefs->jports[i].id >= 0) { + int mode = prefs->jports[i].mode; + if ((joy = jsem_ismouse (i, prefs)) >= 0) { + if (gameports) + cleardev (mice, joy); + switch (mode) + { + case JSEM_MODE_DEFAULT: + case JSEM_MODE_MOUSE: + default: + input_get_default_mouse (mice, joy, i, af); + joymodes[i] = JSEM_MODE_MOUSE; + break; + } + _tcsncpy (prefs->jports[i].name, idev[IDTYPE_MOUSE].get_friendlyname (joy), MAX_JPORTNAME - 1); + _tcsncpy (prefs->jports[i].configname, idev[IDTYPE_MOUSE].get_uniquename (joy), MAX_JPORTNAME - 1); + } + } + } + + for (i = 1; i >= 0; i--) { + int af = prefs->jports[i].autofire; + if (prefs->jports[i].id >= 0) { + int mode = prefs->jports[i].mode; + joy = jsem_isjoy (i, prefs); + if (joy >= 0) { + if (gameports) + cleardev (joysticks, joy); + switch (mode) + { + case JSEM_MODE_DEFAULT: + case JSEM_MODE_JOYSTICK: +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_GAMEPAD: +#endif + case JSEM_MODE_JOYSTICK_CD32: + default: + { + bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd); + input_get_default_joystick (joysticks, joy, i, af, mode); + if (iscd32) + joymodes[i] = JSEM_MODE_JOYSTICK_CD32; +#ifndef INPUTDEVICE_SIMPLE + else if (mode == JSEM_MODE_GAMEPAD) + joymodes[i] = JSEM_MODE_GAMEPAD; +#endif + else + joymodes[i] = JSEM_MODE_JOYSTICK; + break; + } +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_JOYSTICK_ANALOG: + input_get_default_joystick_analog (joysticks, joy, i, af); + joymodes[i] = JSEM_MODE_JOYSTICK_ANALOG; + break; +#endif + case JSEM_MODE_MOUSE: + input_get_default_mouse (joysticks, joy, i, af); + joymodes[i] = JSEM_MODE_MOUSE; + break; +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_MOUSE_CDTV: + joymodes[i] = JSEM_MODE_MOUSE_CDTV; + input_get_default_joystick (joysticks, joy, i, af, mode); + break; +#endif + } + _tcsncpy (prefs->jports[i].name, idev[IDTYPE_JOYSTICK].get_friendlyname (joy), MAX_JPORTNAME - 1); + _tcsncpy (prefs->jports[i].configname, idev[IDTYPE_JOYSTICK].get_uniquename (joy), MAX_JPORTNAME - 1); + used[joy] = 1; + } + } + } + + if (gameports) { + // replace possible old mappings with default keyboard mapping + for (i = KBR_DEFAULT_MAP_FIRST; i <= KBR_DEFAULT_MAP_LAST; i++) { + checkcompakb (keyboard_default_kbmaps[i], ip_joy2); + checkcompakb (keyboard_default_kbmaps[i], ip_joy1); +#ifndef INPUTDEVICE_SIMPLE + checkcompakb (keyboard_default_kbmaps[i], ip_joypad2); + checkcompakb (keyboard_default_kbmaps[i], ip_joypad1); + checkcompakb (keyboard_default_kbmaps[i], ip_parjoy2); + checkcompakb (keyboard_default_kbmaps[i], ip_parjoy1); +#endif + checkcompakb (keyboard_default_kbmaps[i], ip_mouse2); + checkcompakb (keyboard_default_kbmaps[i], ip_mouse1); + } + for (i = KBR_DEFAULT_MAP_CD32_FIRST; i <= KBR_DEFAULT_MAP_CD32_LAST; i++) { + checkcompakb (keyboard_default_kbmaps[i], ip_joycd321); + checkcompakb (keyboard_default_kbmaps[i], ip_joycd322); + } + } + + for (i = 0; i < 2; i++) { + if (prefs->jports[i].id >= 0) { + int *kb = NULL; + int mode = prefs->jports[i].mode; + int af = prefs->jports[i].autofire; + for (joy = 0; used[joy]; joy++); + if (JSEM_ISANYKBD (i, prefs)) { + bool cd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd); + if (JSEM_ISNUMPAD (i, prefs)) { + if (cd32) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_NP]; +#ifndef INPUTDEVICE_SIMPLE + else if (mode == JSEM_MODE_GAMEPAD) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP3]; +#endif + else + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP]; + } else if (JSEM_ISCURSOR (i, prefs)) { + if (cd32) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_CK]; +#ifndef INPUTDEVICE_SIMPLE + else if (mode == JSEM_MODE_GAMEPAD) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK3]; +#endif + else + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK]; + } else if (JSEM_ISSOMEWHEREELSE (i, prefs)) { + if (cd32) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_SE]; +#ifndef INPUTDEVICE_SIMPLE + else if (mode == JSEM_MODE_GAMEPAD) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE3]; +#endif + else + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE]; + } else if (JSEM_ISXARCADE1 (i, prefs)) { + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA1]; + } else if (JSEM_ISXARCADE2 (i, prefs)) { + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA2]; + } + if (kb) { + switch (mode) + { + case JSEM_MODE_JOYSTICK: +#ifndef INPUTDEVICE_SIMPLE + case JSEM_MODE_GAMEPAD: +#endif + case JSEM_MODE_JOYSTICK_CD32: + case JSEM_MODE_DEFAULT: + if (cd32) { + setcompakb (kb, i ? ip_joycd322 : ip_joycd321, i, af); + joymodes[i] = JSEM_MODE_JOYSTICK_CD32; +#ifndef INPUTDEVICE_SIMPLE + } else if (mode == JSEM_MODE_GAMEPAD) { + setcompakb (kb, i ? ip_joypad2 : ip_joypad1, i, af); + joymodes[i] = JSEM_MODE_GAMEPAD; +#endif + } else { + setcompakb (kb, i ? ip_joy2 : ip_joy1, i, af); + joymodes[i] = JSEM_MODE_JOYSTICK; + } + break; + case JSEM_MODE_MOUSE: + setcompakb (kb, i ? ip_mouse2 : ip_mouse1, i, af); + joymodes[i] = JSEM_MODE_MOUSE; + break; + } + used[joy] = 1; + } + } + } + } + +#ifndef INPUTDEVICE_SIMPLE + // parport + for (i = 2; i < MAX_JPORTS; i++) { + int af = prefs->jports[i].autofire; + if (prefs->jports[i].id >= 0) { + int *kb = NULL; + joy = jsem_isjoy (i, prefs); + if (joy >= 0) { + if (gameports) + cleardev (joysticks, joy); + input_get_default_joystick (joysticks, joy, i, af, 0); + _tcsncpy (prefs->jports[i].name, idev[IDTYPE_JOYSTICK].get_friendlyname (joy), MAX_JPORTNAME - 1); + _tcsncpy (prefs->jports[i].configname, idev[IDTYPE_JOYSTICK].get_uniquename (joy), MAX_JPORTNAME - 1); + used[joy] = 1; + joymodes[i] = JSEM_MODE_JOYSTICK; + } + } + } + for (i = 2; i < MAX_JPORTS; i++) { + if (prefs->jports[i].id >= 0) { + int *kb = NULL; + for (joy = 0; used[joy]; joy++); + if (JSEM_ISANYKBD (i, prefs)) { + if (JSEM_ISNUMPAD (i, prefs)) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP]; + else if (JSEM_ISCURSOR (i, prefs)) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK]; + else if (JSEM_ISSOMEWHEREELSE (i, prefs)) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE]; + else if (JSEM_ISXARCADE1 (i, prefs)) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA1]; + else if (JSEM_ISXARCADE2 (i, prefs)) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA2]; + if (kb) { + setcompakb (kb, i == 3 ? ip_parjoy2default : ip_parjoy1default, i, prefs->jports[i].autofire); + used[joy] = 1; + joymodes[i] = JSEM_MODE_JOYSTICK; + } + } + } + } +#endif + + for (i = 0; i < MAX_JPORTS; i++) { + if (gameports) + setautofires (prefs, i, prefs->jports[i].autofire); + } + + for (i = 0; i < MAX_JPORTS; i++) { + setjoyinputs (prefs, i); + setjoydevices (prefs, gameports, i); + } +} + +static void disableifempty2 (struct uae_input_device *uid) +{ + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + if (uid->eventid[i][j] > 0 || uid->custom[i][j] != NULL) + return; + } + } + uid->enabled = false; +} +static void disableifempty (struct uae_prefs *prefs) +{ + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + disableifempty2 (&joysticks[l]); + disableifempty2 (&mice[l]); + disableifempty2 (&keyboards[l]); + } +} + +static void matchdevices (struct inputdevice_functions *inf, struct uae_input_device *uid) +{ + int i, j; + + for (i = 0; i < inf->get_num (); i++) { + TCHAR *aname1 = inf->get_friendlyname (i); + TCHAR *aname2 = inf->get_uniquename (i); + int match = -1; + for (j = 0; j < MAX_INPUT_DEVICES; j++) { + if (aname2 && uid[j].configname) { + bool matched = false; + TCHAR bname[MAX_DPATH]; + TCHAR bname2[MAX_DPATH]; + TCHAR *p1 ,*p2; + _tcscpy (bname, uid[j].configname); + _tcscpy (bname2, aname2); + // strip possible local guid part + p1 = _tcschr (bname, '{'); + p2 = _tcschr (bname2, '{'); + if (!p1 && !p2) { + // check possible directinput names too + p1 = _tcschr (bname, ' '); + p2 = _tcschr (bname2, ' '); + } + if (!_tcscmp (bname, bname2)) { + matched = true; + } else if (p1 && p2 && p1 - bname == p2 - bname2) { + *p1 = 0; + *p2 = 0; + if (bname && !_tcscmp (bname2, bname)) + matched = true; + } + if (matched) { + if (match >= 0) + match = -2; + else + match = j; + } + if (match == -2) + break; + } + } + // multiple matches -> use complete local-only id string for comparisons + if (match == -2) { + for (j = 0; j < MAX_INPUT_DEVICES; j++) { + TCHAR *bname2 = uid[j].configname; + if (aname2 && bname2 && !_tcscmp (aname2, bname2)) { + match = j; + break; + } + } + } + if (match < 0) { + // no match, try friend names + for (j = 0; j < MAX_INPUT_DEVICES; j++) { + TCHAR *bname1 = uid[j].name; + if (aname1 && bname1 && !_tcscmp (aname1, bname1)) { + match = j; + break; + } + } + } + if (match >= 0) { + j = match; + if (j != i) { + struct uae_input_device *tmp = xmalloc (struct uae_input_device, 1); + memcpy (tmp, &uid[j], sizeof (struct uae_input_device)); + memcpy (&uid[j], &uid[i], sizeof (struct uae_input_device)); + memcpy (&uid[i], tmp, sizeof (struct uae_input_device)); + xfree (tmp); + } + } + } + for (i = 0; i < inf->get_num (); i++) { + if (uid[i].name == NULL) + uid[i].name = my_strdup (inf->get_friendlyname (i)); + if (uid[i].configname == NULL) + uid[i].configname = my_strdup (inf->get_uniquename (i)); + } +} + +static void matchdevices_all (struct uae_prefs *prefs) +{ + int i; + for (i = 0; i < MAX_INPUT_SETTINGS; i++) { + matchdevices (&idev[IDTYPE_MOUSE], prefs->mouse_settings[i]); + matchdevices (&idev[IDTYPE_JOYSTICK], prefs->joystick_settings[i]); + matchdevices (&idev[IDTYPE_KEYBOARD], prefs->keyboard_settings[i]); + } +} + +bool inputdevice_set_gameports_mapping (struct uae_prefs *prefs, int devnum, int num, int evtnum, int flags, int port) +{ + TCHAR name[256]; + struct inputevent *ie; + + ie = inputdevice_get_eventinfo (evtnum); + if (!inputdevice_get_eventname (ie, name)) + return false; + joysticks = prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS]; + mice = prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS]; + keyboards = prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS]; + + int sub = 0; + if (inputdevice_get_widget_type (devnum, num, NULL) != IDEV_WIDGET_KEY) { + for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) { + if (!inputdevice_get_mapping (devnum, num, NULL, NULL, NULL, NULL, sub)) + break; + } + } + if (sub >= MAX_INPUT_SUB_EVENT) + sub = MAX_INPUT_SUB_EVENT - 1; + inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, sub); + + joysticks = prefs->joystick_settings[prefs->input_selected_setting]; + mice = prefs->mouse_settings[prefs->input_selected_setting]; + keyboards = prefs->keyboard_settings[prefs->input_selected_setting]; + if (prefs->input_selected_setting != GAMEPORT_INPUT_SETTINGS) { + int xflags, xport; + TCHAR xname[MAX_DPATH], xcustom[MAX_DPATH]; + inputdevice_get_mapping (devnum, num, &xflags, &xport, xname, xcustom, 0); + if (xport == 0) + inputdevice_set_mapping (devnum, num, xname, xcustom, xflags, MAX_JPORTS + 1, SPARE_SUB_EVENT); + inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, 0); + } + return true; +} + +static void resetinput (void) +{ + cd32_shifter[0] = cd32_shifter[1] = 8; + for (int i = 0; i < MAX_JPORTS; i++) { + oleft[i] = 0; + oright[i] = 0; + otop[i] = 0; + obot[i] = 0; + joybutton[i] = 0; + joydir[i] = 0; + mouse_deltanoreset[i][0] = 0; + mouse_delta[i][0] = 0; + mouse_deltanoreset[i][1] = 0; + mouse_delta[i][1] = 0; + mouse_deltanoreset[i][2] = 0; + mouse_delta[i][2] = 0; + } + memset (keybuf, 0, sizeof keybuf); + for (int i = 0; i < INPUT_QUEUE_SIZE; i++) + input_queue[i].linecnt = input_queue[i].nextlinecnt = -1; + + for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) { + sublevdir[0][i] = i; + sublevdir[1][i] = MAX_INPUT_SUB_EVENT - i - 1; + } +} + +void inputdevice_updateconfig_internal (struct uae_prefs *prefs) +{ + int i; + + keyboard_default = keyboard_default_table[currprefs.input_keyboard_type]; + + copyjport (&changed_prefs, &currprefs, 0); + copyjport (&changed_prefs, &currprefs, 1); + copyjport (&changed_prefs, &currprefs, 2); + copyjport (&changed_prefs, &currprefs, 3); + + resetinput (); + + joysticks = prefs->joystick_settings[prefs->input_selected_setting]; + mice = prefs->mouse_settings[prefs->input_selected_setting]; + keyboards = prefs->keyboard_settings[prefs->input_selected_setting]; + + matchdevices_all (prefs); + + memset (joysticks2, 0, sizeof joysticks2); + memset (mice2, 0, sizeof mice2); + + joysticks = prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS]; + mice = prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS]; + keyboards = prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS]; + for (i = 0; i < MAX_INPUT_SETTINGS; i++) { + joysticks[i].enabled = 0; + mice[i].enabled = 0; + } + compatibility_copy (prefs, true); + joysticks = prefs->joystick_settings[prefs->input_selected_setting]; + mice = prefs->mouse_settings[prefs->input_selected_setting]; + keyboards = prefs->keyboard_settings[prefs->input_selected_setting]; + if (prefs->input_selected_setting != GAMEPORT_INPUT_SETTINGS) { + compatibility_copy (prefs, false); + } + + disableifempty (prefs); + scanevents (prefs); } void inputdevice_updateconfig (struct uae_prefs *prefs) { - joystick_setting_changed (); + inputdevice_updateconfig_internal (prefs); } +// set default prefs to all input configuration settings void inputdevice_default_prefs (struct uae_prefs *p) { + inputdevice_init (); + + p->input_selected_setting = GAMEPORT_INPUT_SETTINGS; #ifdef PANDORA_SPECIFIC p->input_joymouse_multiplier = 20; #else p->input_joymouse_multiplier = 2; #endif + p->input_joymouse_deadzone = 33; + p->input_joystick_deadzone = 33; + p->input_joymouse_speed = 10; + p->input_analog_joystick_mult = 15; + p->input_analog_joystick_offset = -1; + p->input_mouse_speed = 100; p->input_autofire_framecnt = 8; + p->input_keyboard_type = 0; + keyboard_default = keyboard_default_table[p->input_keyboard_type]; + inputdevice_default_kb_all (p); +} + +// set default keyboard and keyboard>joystick layouts +void inputdevice_setkeytranslation (struct uae_input_device_kbr_default **trans, int **kbmaps) +{ + keyboard_default_table = trans; + keyboard_default_kbmaps = kbmaps; +} + +// return true if keyboard/scancode pair is mapped +int inputdevice_iskeymapped (int keyboard, int scancode) +{ + struct uae_input_device *na = &keyboards[keyboard]; + + if (!keyboards || scancode < 0) + return 0; + return scancodeused[keyboard][scancode]; +} + +static int inputdevice_translatekeycode_2 (int keyboard, int scancode, int state, bool qualifiercheckonly) +{ + struct uae_input_device *na = &keyboards[keyboard]; + int j, k; + int handled = 0; + + if (!keyboards || scancode < 0) + return handled; + + if (!state) + process_custom_event (NULL, 0, 0, 0, 0); + + j = 0; + while (j < MAX_INPUT_DEVICE_EVENTS && na->extra[j] >= 0) { + if (na->extra[j] == scancode) { + bool qualonly; + int qualmask = getqualmask (na, j, &qualonly); + if (qualonly) + qualifiercheckonly = true; + for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {/* send key release events in reverse order */ + uae_u32 *flagsp = &na->flags[j][sublevdir[state == 0 ? 1 : 0][k]]; + int evt = na->eventid[j][sublevdir[state == 0 ? 1 : 0][k]]; + int flags = *flagsp; + int autofire = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0; +#ifndef INPUTDEVICE_SIMPLE + int toggle = (flags & ID_FLAG_TOGGLE) ? 1 : 0; + int inverttoggle = (flags & ID_FLAG_INVERTTOGGLE) ? 1 : 0; + int toggled; +#endif + + setqualifiers (evt, state > 0); + if (qualifiercheckonly) + continue; + +#ifndef INPUTDEVICE_SIMPLE + if (inverttoggle) { + na->flags[j][sublevdir[state == 0 ? 1 : 0][k]] &= ~ID_FLAG_TOGGLED; + if (state) { + queue_input_event (evt, NULL, -1, 0, 0, 1); + handled |= handle_input_event (evt, 1, 1, 0, true, false); + } else { + handled |= handle_input_event (evt, 1, 1, autofire, true, false); + } + if (k == 0) + process_custom_event (na, j, state, qualmask, autofire); + } else if (toggle) { + if (!state) + continue; + if (!checkqualifiers (evt, flags, qualmask)) + continue; + *flagsp ^= ID_FLAG_TOGGLED; + toggled = (*flagsp & ID_FLAG_TOGGLED) ? 1 : 0; + handled |= handle_input_event (evt, toggled, 1, autofire, true, false); + if (k == 0) + process_custom_event (na, j, state, qualmask, autofire); + } else { +#endif + if (!checkqualifiers (evt, flags, qualmask)) { + if (!state && !(flags & ID_FLAG_CANRELEASE)) + continue; + else if (state) + continue; + } + if (state) + *flagsp |= ID_FLAG_CANRELEASE; + else + *flagsp &= ~ID_FLAG_CANRELEASE; +#ifdef INPUTDEVICE_SIMPLE + handled |= handle_input_event (evt, state, 1, autofire); +#else + handled |= handle_input_event (evt, state, 1, autofire, true, false); +#endif + if (k == 0) + process_custom_event (na, j, state, qualmask, autofire); +#ifndef INPUTDEVICE_SIMPLE + } +#endif + } + return handled; + } + j++; + } + return handled; +} + +// main keyboard press/release entry point +int inputdevice_translatekeycode (int keyboard, int scancode, int state) +{ + if (inputdevice_translatekeycode_2 (keyboard, scancode, state, false)) + return 1; + return 0; +} +void inputdevice_checkqualifierkeycode (int keyboard, int scancode, int state) +{ + inputdevice_translatekeycode_2 (keyboard, scancode, state, true); } void inputdevice_init (void) { - lastsampledmx = 0; - lastsampledmy = 0; - - init_joystick (); - inputmode_init(); - init_keyboard(); + idev[IDTYPE_JOYSTICK] = inputdevicefunc_joystick; + idev[IDTYPE_JOYSTICK].init (); + idev[IDTYPE_MOUSE] = inputdevicefunc_mouse; + idev[IDTYPE_MOUSE].init (); + idev[IDTYPE_KEYBOARD] = inputdevicefunc_keyboard; + idev[IDTYPE_KEYBOARD].init (); } void inputdevice_close (void) { - close_joystick (); - inputmode_close(); + idev[IDTYPE_JOYSTICK].close (); + idev[IDTYPE_MOUSE].close (); + idev[IDTYPE_KEYBOARD].close (); +} + +static struct uae_input_device *get_uid (const struct inputdevice_functions *id, int devnum) +{ + struct uae_input_device *uid = 0; + if (id == &idev[IDTYPE_JOYSTICK]) { + uid = &joysticks[devnum]; + } else if (id == &idev[IDTYPE_MOUSE]) { + uid = &mice[devnum]; + } else if (id == &idev[IDTYPE_KEYBOARD]) { + uid = &keyboards[devnum]; + } + return uid; +} + +static int get_event_data (const struct inputdevice_functions *id, int devnum, int num, int *eventid, TCHAR **custom, int *flags, int *port, int sub) +{ + const struct uae_input_device *uid = get_uid (id, devnum); + int type = id->get_widget_type (devnum, num, 0, 0); + int i; + if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) { + i = num - id->get_widget_first (devnum, IDEV_WIDGET_BUTTON) + ID_BUTTON_OFFSET; + *eventid = uid->eventid[i][sub]; + if (flags) + *flags = uid->flags[i][sub]; + if (port) + *port = uid->port[i][sub]; + if (custom) + *custom = uid->custom[i][sub]; + return i; + } else if (type == IDEV_WIDGET_AXIS) { + i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET; + *eventid = uid->eventid[i][sub]; + if (flags) + *flags = uid->flags[i][sub]; + if (port) + *port = uid->port[i][sub]; + if (custom) + *custom = uid->custom[i][sub]; + return i; + } else if (type == IDEV_WIDGET_KEY) { + i = num - id->get_widget_first (devnum, type); + *eventid = uid->eventid[i][sub]; + if (flags) + *flags = uid->flags[i][sub]; + if (port) + *port = uid->port[i][sub]; + if (custom) + *custom = uid->custom[i][sub]; + return i; + } + return -1; +} + +static int put_event_data (const struct inputdevice_functions *id, int devnum, int num, int eventid, TCHAR *custom, int flags, int port, int sub) +{ + struct uae_input_device *uid = get_uid (id, devnum); + int type = id->get_widget_type (devnum, num, 0, 0); + int i, ret; + + ret = -1; + if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) { + i = num - id->get_widget_first (devnum, IDEV_WIDGET_BUTTON) + ID_BUTTON_OFFSET; + uid->eventid[i][sub] = eventid; + uid->flags[i][sub] = flags; + uid->port[i][sub] = port; + xfree (uid->custom[i][sub]); + ret = i; + } else if (type == IDEV_WIDGET_AXIS) { + i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET; + uid->eventid[i][sub] = eventid; + uid->flags[i][sub] = flags; + uid->port[i][sub] = port; + xfree (uid->custom[i][sub]); + ret = i; + } else if (type == IDEV_WIDGET_KEY) { + i = num - id->get_widget_first (devnum, type); + uid->eventid[i][sub] = eventid; + uid->flags[i][sub] = flags; + uid->port[i][sub] = port; + xfree (uid->custom[i][sub]); + ret = i; + } + if (ret < 0) + return -1; + if (uid->custom[i][sub]) + uid->eventid[i][sub] = INPUTEVENT_SPC_CUSTOM_EVENT; + return ret; +} + +static int is_event_used (const struct inputdevice_functions *id, int devnum, int isnum, int isevent) +{ + struct uae_input_device *uid = get_uid (id, devnum); + int num, evt, sub; + + for (num = 0; num < id->get_widget_num (devnum); num++) { + for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) { + if (get_event_data (id, devnum, num, &evt, NULL, NULL, NULL, sub) >= 0) { + if (evt == isevent && isnum != num) + return 1; + } + } + } + return 0; +} + +// device based index from global device index +int inputdevice_get_device_index (int devnum) +{ + if (devnum < idev[IDTYPE_JOYSTICK].get_num ()) + return devnum; + else if (devnum < idev[IDTYPE_JOYSTICK].get_num () + idev[IDTYPE_MOUSE].get_num ()) + return devnum - idev[IDTYPE_JOYSTICK].get_num (); + else if (devnum < idev[IDTYPE_JOYSTICK].get_num () + idev[IDTYPE_MOUSE].get_num () + idev[IDTYPE_KEYBOARD].get_num ()) + return devnum - idev[IDTYPE_JOYSTICK].get_num () - idev[IDTYPE_MOUSE].get_num (); + else + return -1; +} + +static int getdevnum (int type, int devnum) +{ + if (type == IDTYPE_JOYSTICK) + return devnum; + if (type == IDTYPE_MOUSE) + return idev[IDTYPE_JOYSTICK].get_num () + devnum; + if (type == IDTYPE_KEYBOARD) + return idev[IDTYPE_JOYSTICK].get_num () + idev[IDTYPE_MOUSE].get_num () + devnum; + return -1; +} + +static int gettype (int devnum) +{ + if (devnum < idev[IDTYPE_JOYSTICK].get_num ()) + return IDTYPE_JOYSTICK; + else if (devnum < idev[IDTYPE_JOYSTICK].get_num () + idev[IDTYPE_MOUSE].get_num ()) + return IDTYPE_MOUSE; + else if (devnum < idev[IDTYPE_JOYSTICK].get_num () + idev[IDTYPE_MOUSE].get_num () + idev[IDTYPE_KEYBOARD].get_num ()) + return IDTYPE_KEYBOARD; + else + return -1; +} + +static struct inputdevice_functions *getidf (int devnum) +{ + int type = gettype (devnum); + if (type < 0) + return NULL; + return &idev[type]; +} + +struct inputevent *inputdevice_get_eventinfo (int evt) +{ + return &events[evt]; +} + + +/* returns number of devices of type "type" */ +int inputdevice_get_device_total (int type) +{ + return idev[type].get_num (); +} +/* returns the name of device */ +TCHAR *inputdevice_get_device_name (int type, int devnum) +{ + return idev[type].get_friendlyname (devnum); +} +/* returns the name of device */ +TCHAR *inputdevice_get_device_name2 (int devnum) +{ + return getidf (devnum)->get_friendlyname (inputdevice_get_device_index (devnum)); +} +/* returns machine readable name of device */ +TCHAR *inputdevice_get_device_unique_name (int type, int devnum) +{ + return idev[type].get_uniquename (devnum); +} +/* returns state (enabled/disabled) */ +int inputdevice_get_device_status (int devnum) +{ + const struct inputdevice_functions *idf = getidf (devnum); + if (idf == NULL) + return -1; + struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum)); + return uid->enabled; +} + +/* set state (enabled/disabled) */ +void inputdevice_set_device_status (int devnum, int enabled) +{ + const struct inputdevice_functions *idf = getidf (devnum); + int num = inputdevice_get_device_index (devnum); + struct uae_input_device *uid = get_uid (idf, num); + if (enabled) { // disable incompatible devices ("super device" vs "raw device") + for (int i = 0; i < idf->get_num (); i++) { + if (idf->get_flags (i) != idf->get_flags (num)) { + struct uae_input_device *uid2 = get_uid (idf, i); + uid2->enabled = 0; + } + } + } + uid->enabled = enabled; +} + +/* returns number of axis/buttons and keys from selected device */ +int inputdevice_get_widget_num (int devnum) +{ + const struct inputdevice_functions *idf = getidf (devnum); + return idf->get_widget_num (inputdevice_get_device_index (devnum)); +} + +// return name of event, do not use ie->name directly +bool inputdevice_get_eventname (const struct inputevent *ie, TCHAR *out) +{ + if (!out) + return false; + _tcscpy (out, ie->name); + return true; +} + +int inputdevice_iterate (int devnum, int num, TCHAR *name, int *af) +{ + const struct inputdevice_functions *idf = getidf (devnum); + static int id_iterator; + struct inputevent *ie; + int mask, data, flags, type; + int devindex = inputdevice_get_device_index (devnum); + + *af = 0; + *name = 0; + for (;;) { + ie = &events[++id_iterator]; + if (!ie->confname) { + id_iterator = 0; + return 0; + } + mask = 0; + type = idf->get_widget_type (devindex, num, NULL, NULL); + if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) { + if (idf == &idev[IDTYPE_JOYSTICK]) { + mask |= AM_JOY_BUT; + } else { + mask |= AM_MOUSE_BUT; + } + } else if (type == IDEV_WIDGET_AXIS) { + if (idf == &idev[IDTYPE_JOYSTICK]) { + mask |= AM_JOY_AXIS; + } else { + mask |= AM_MOUSE_AXIS; + } + } else if (type == IDEV_WIDGET_KEY) { + mask |= AM_K; + } + if (ie->allow_mask & AM_INFO) { + struct inputevent *ie2 = ie + 1; + while (!(ie2->allow_mask & AM_INFO)) { + if (is_event_used (idf, devindex, ie2 - ie, -1)) { + ie2++; + continue; + } + if (ie2->allow_mask & mask) + break; + ie2++; + } + if (!(ie2->allow_mask & AM_INFO)) + mask |= AM_INFO; + } + if (!(ie->allow_mask & mask)) + continue; + get_event_data (idf, devindex, num, &data, NULL, &flags, NULL, 0); + inputdevice_get_eventname (ie, name); + *af = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0; + return 1; + } +} + +// return mapped event from devnum/num/sub +int inputdevice_get_mapping (int devnum, int num, int *pflags, int *pport, TCHAR *name, TCHAR *custom, int sub) +{ + const struct inputdevice_functions *idf = getidf (devnum); + const struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum)); + int flags = 0, flag, port, data; + int devindex = inputdevice_get_device_index (devnum); + TCHAR *customp = NULL; + + if (name) + _tcscpy (name, _T("")); + if (custom) + custom[0] = 0; + if (pflags) + *pflags = 0; + if (pport) + *pport = 0; + if (uid == 0 || num < 0) + return 0; + if (get_event_data (idf, devindex, num, &data, &customp, &flag, &port, sub) < 0) + return 0; + if (customp && custom) + _tcscpy (custom, customp); + if (flag & ID_FLAG_AUTOFIRE) + flags |= IDEV_MAPPED_AUTOFIRE_SET; +#ifndef INPUTDEVICE_SIMPLE + if (flag & ID_FLAG_TOGGLE) + flags |= IDEV_MAPPED_TOGGLE; + if (flag & ID_FLAG_INVERTTOGGLE) + flags |= IDEV_MAPPED_INVERTTOGGLE; +#endif + if (flag & ID_FLAG_GAMEPORTSCUSTOM1) + flags |= IDEV_MAPPED_GAMEPORTSCUSTOM1; +#ifndef INPUTDEVICE_SIMPLE + if (flag & ID_FLAG_GAMEPORTSCUSTOM2) + flags |= IDEV_MAPPED_GAMEPORTSCUSTOM2; +#endif + if (flag & ID_FLAG_QUALIFIER_MASK) + flags |= flag & ID_FLAG_QUALIFIER_MASK; + if (pflags) + *pflags = flags; + if (pport) + *pport = port; + if (!data) + return 0; + if (events[data].allow_mask & AM_AF) + flags |= IDEV_MAPPED_AUTOFIRE_POSSIBLE; + if (pflags) + *pflags = flags; + inputdevice_get_eventname (&events[data], name); + return data; +} + +// set event name/custom/flags to devnum/num/sub +int inputdevice_set_mapping (int devnum, int num, const TCHAR *name, TCHAR *custom, int flags, int port, int sub) +{ + const struct inputdevice_functions *idf = getidf (devnum); + const struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum)); + int eid, data, flag, portp, amask; + TCHAR ename[256]; + int devindex = inputdevice_get_device_index (devnum); + TCHAR *customp = NULL; + + if (uid == 0 || num < 0) + return 0; + if (name) { + eid = 1; + while (events[eid].name) { + inputdevice_get_eventname (&events[eid], ename); + if (!_tcscmp(ename, name)) + break; + eid++; + } + if (!events[eid].name) + return 0; + if (events[eid].allow_mask & AM_INFO) + return 0; + } else { + eid = 0; + } + if (get_event_data (idf, devindex, num, &data, &customp, &flag, &portp, sub) < 0) + return 0; + if (data >= 0) { + amask = events[eid].allow_mask; + flag &= ~(ID_FLAG_AUTOFIRE_MASK | ID_FLAG_GAMEPORTSCUSTOM_MASK | IDEV_MAPPED_QUALIFIER_MASK); + if (amask & AM_AF) { + flag |= (flags & IDEV_MAPPED_AUTOFIRE_SET) ? ID_FLAG_AUTOFIRE : 0; +#ifndef INPUTDEVICE_SIMPLE + flag |= (flags & IDEV_MAPPED_TOGGLE) ? ID_FLAG_TOGGLE : 0; + flag |= (flags & IDEV_MAPPED_INVERTTOGGLE) ? ID_FLAG_INVERTTOGGLE : 0; +#endif + } + flag |= (flags & IDEV_MAPPED_GAMEPORTSCUSTOM1) ? ID_FLAG_GAMEPORTSCUSTOM1 : 0; +#ifndef INPUTDEVICE_SIMPLE + flag |= (flags & IDEV_MAPPED_GAMEPORTSCUSTOM2) ? ID_FLAG_GAMEPORTSCUSTOM2 : 0; +#endif + flag |= flags & IDEV_MAPPED_QUALIFIER_MASK; + if (port >= 0) + portp = port; + put_event_data (idf, devindex, num, eid, custom, flag, portp, sub); + return 1; + } + return 0; +} + +int inputdevice_get_widget_type (int devnum, int num, TCHAR *name) +{ + const struct inputdevice_functions *idf = getidf (devnum); + return idf->get_widget_type (inputdevice_get_device_index (devnum), num, name, 0); +} + +static int config_change; + +void inputdevice_config_change (void) +{ + config_change = 1; } int inputdevice_config_change_test (void) { - return 1; + int v = config_change; + config_change = 0; + return v; } -void inputdevice_copyconfig (struct uae_prefs *src, struct uae_prefs *dst) +// copy configuration #src to configuration #dst +void inputdevice_copyconfig (const struct uae_prefs *src, struct uae_prefs *dst) { + int i, j; + + dst->input_selected_setting = src->input_selected_setting; dst->input_joymouse_multiplier = src->input_joymouse_multiplier; + dst->input_joymouse_deadzone = src->input_joymouse_deadzone; + dst->input_joystick_deadzone = src->input_joystick_deadzone; + dst->input_joymouse_speed = src->input_joymouse_speed; + dst->input_mouse_speed = src->input_mouse_speed; dst->input_autofire_framecnt = src->input_autofire_framecnt; dst->input_tablet = src->input_tablet; - dst->pandora_joyConf = src->pandora_joyConf; - dst->pandora_joyPort = src->pandora_joyPort; dst->pandora_tapDelay = src->pandora_tapDelay; - dst->pandora_customControls = src->pandora_customControls; - dst->pandora_custom_dpad = src->pandora_custom_dpad; - dst->pandora_custom_A = src->pandora_custom_A; - dst->pandora_custom_B = src->pandora_custom_B; - dst->pandora_custom_X = src->pandora_custom_X; - dst->pandora_custom_Y = src->pandora_custom_Y; - dst->pandora_custom_L = src->pandora_custom_L; - dst->pandora_custom_R = src->pandora_custom_R; - dst->pandora_custom_up = src->pandora_custom_up; - dst->pandora_custom_down = src->pandora_custom_down; - dst->pandora_custom_left = src->pandora_custom_left; - dst->pandora_custom_right = src->pandora_custom_right; - dst->pandora_button1 = src->pandora_button1; - dst->pandora_button2 = src->pandora_button2; - dst->pandora_autofireButton1 = src->pandora_autofireButton1; - dst->pandora_jump = src->pandora_jump; + copyjport (src, dst, 0); + copyjport (src, dst, 1); + copyjport (src, dst, 2); + copyjport (src, dst, 3); - dst->key_for_menu = src->key_for_menu; - dst->key_for_input_switching = src->key_for_input_switching; + for (i = 0; i < MAX_INPUT_SETTINGS; i++) { + for (j = 0; j < MAX_INPUT_DEVICES; j++) { + memcpy (&dst->joystick_settings[i][j], &src->joystick_settings[i][j], sizeof (struct uae_input_device)); + memcpy (&dst->mouse_settings[i][j], &src->mouse_settings[i][j], sizeof (struct uae_input_device)); + memcpy (&dst->keyboard_settings[i][j], &src->keyboard_settings[i][j], sizeof (struct uae_input_device)); + } + } inputdevice_updateconfig (dst); } -void inputdevice_mouselimit(int x, int y) +static void swapjoydevice (struct uae_input_device *uid, int **swaps) { - mouse_maxx = x; - mouse_maxy = y; + for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + bool found = false; + for (int k = 0; k < 2 && !found; k++) { + int evtnum; + for (int kk = 0; (evtnum = swaps[k][kk]) >= 0 && !found; kk++) { + if (uid->eventid[i][j] == evtnum) { + uid->eventid[i][j] = swaps[1 - k][kk]; + found = true; + } else { + for (int jj = 0; axistable[jj] >= 0; jj += 3) { + if (evtnum == axistable[jj] || evtnum == axistable[jj + 1] || evtnum == axistable[jj + 2]) { + for (int ii = 0; ii < 3; ii++) { + if (uid->eventid[i][j] == axistable[jj + ii]) { + int evtnum2 = swaps[1 - k][kk]; + for (int m = 0; axistable[m] >= 0; m += 3) { + if (evtnum2 == axistable[m] || evtnum2 == axistable[m + 1] || evtnum2 == axistable[m + 2]) { + uid->eventid[i][j] = axistable[m + ii]; + found = true; + } + } + } + } + } + } + } + } + } + } + } +} + +// swap gameports ports, remember to handle customized ports too +void inputdevice_swap_compa_ports (struct uae_prefs *prefs, int portswap) +{ + struct jport tmp; + if ((prefs->jports[portswap].id == JPORT_CUSTOM || prefs->jports[portswap + 1].id == JPORT_CUSTOM)) { + int *swaps[2]; + swaps[0] = rem_ports[portswap]; + swaps[1] = rem_ports[portswap + 1]; + for (int l = 0; l < MAX_INPUT_DEVICES; l++) { + swapjoydevice (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], swaps); + swapjoydevice (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], swaps); + swapjoydevice (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], swaps); + } + } + memcpy (&tmp, &prefs->jports[portswap], sizeof (struct jport)); + memcpy (&prefs->jports[portswap], &prefs->jports[portswap + 1], sizeof (struct jport)); + memcpy (&prefs->jports[portswap + 1], &tmp, sizeof (struct jport)); + inputdevice_updateconfig (prefs); +} + +// swap device "devnum" ports 0<>1 and 2<>3 +void inputdevice_swap_ports (struct uae_prefs *p, int devnum) +{ + const struct inputdevice_functions *idf = getidf (devnum); + struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum)); + int i, j, k, event, unit; + const struct inputevent *ie, *ie2; + + for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) { + for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) { + event = uid->eventid[i][j]; + if (event <= 0) + continue; + ie = &events[event]; + if (ie->unit <= 0) + continue; + unit = ie->unit; + k = 1; + while (events[k].confname) { + ie2 = &events[k]; + if (ie2->type == ie->type && ie2->data == ie->data && ie2->unit - 1 == ((ie->unit - 1) ^ 1) && + ie2->allow_mask == ie->allow_mask && uid->port[i][j] == 0) { + uid->eventid[i][j] = k; + break; + } + k++; + } + } + } +} + +//memcpy (p->joystick_settings[dst], p->joystick_settings[src], sizeof (struct uae_input_device) * MAX_INPUT_DEVICES); +static void copydev (struct uae_input_device *dst, struct uae_input_device *src) +{ + for (int i = 0; i < MAX_INPUT_DEVICES; i++) { + for (int j = 0; j < MAX_INPUT_DEVICE_EVENTS; j++) { + for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) { + xfree (dst[i].custom[j][k]); + } + } + xfree (dst[i].configname); + xfree (dst[i].name); + } + memcpy (dst, src, sizeof (struct uae_input_device) * MAX_INPUT_DEVICES); + for (int i = 0; i < MAX_INPUT_DEVICES; i++) { + for (int j = 0; j < MAX_INPUT_DEVICE_EVENTS; j++) { + for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) { + if (dst[i].custom) + dst[i].custom[j][k] = my_strdup (dst[i].custom[j][k]); + } + } + dst[i].configname = my_strdup (dst[i].configname); + dst[i].name = my_strdup (dst[i].name); + } +} + +// copy whole configuration #x-slot to another +// +1 = default +// +2 = default (pc keyboard) +void inputdevice_copy_single_config (struct uae_prefs *p, int src, int dst, int devnum, int selectedwidget) +{ + if (src >= MAX_INPUT_SETTINGS) { + if (gettype (devnum) == IDTYPE_KEYBOARD) { + p->input_keyboard_type = src > MAX_INPUT_SETTINGS ? 1 : 0; + keyboard_default = keyboard_default_table[p->input_keyboard_type]; + inputdevice_default_kb (p, dst); + } + } + if (src == dst) + return; + if (src < MAX_INPUT_SETTINGS) { + if (devnum < 0 || gettype (devnum) == IDTYPE_JOYSTICK) + copydev (p->joystick_settings[dst], p->joystick_settings[src]); + if (devnum < 0 || gettype (devnum) == IDTYPE_MOUSE) + copydev (p->mouse_settings[dst], p->mouse_settings[src]); + if (devnum < 0 || gettype (devnum) == IDTYPE_KEYBOARD) + copydev (p->keyboard_settings[dst], p->keyboard_settings[src]); + } +} + +void inputdevice_acquire (int allmode) +{ + int i; + + for (i = 0; i < MAX_INPUT_DEVICES; i++) + idev[IDTYPE_JOYSTICK].unacquire (i); + for (i = 0; i < MAX_INPUT_DEVICES; i++) + idev[IDTYPE_MOUSE].unacquire (i); + for (i = 0; i < MAX_INPUT_DEVICES; i++) + idev[IDTYPE_KEYBOARD].unacquire (i); + + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + if ((use_joysticks[i] && allmode >= 0) || (allmode && !idev[IDTYPE_JOYSTICK].get_flags (i))) + idev[IDTYPE_JOYSTICK].acquire (i, 0); + } + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + if ((use_mice[i] && allmode >= 0) || (allmode && !idev[IDTYPE_MOUSE].get_flags (i))) + idev[IDTYPE_MOUSE].acquire (i, allmode < 0); + } + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + if ((use_keyboards[i] && allmode >= 0) || (allmode < 0 && !idev[IDTYPE_KEYBOARD].get_flags (i))) + idev[IDTYPE_KEYBOARD].acquire (i, allmode < 0); + } + + if (input_acquired) + return; + + idev[IDTYPE_JOYSTICK].acquire (-1, 0); + idev[IDTYPE_MOUSE].acquire (-1, 0); + idev[IDTYPE_KEYBOARD].acquire (-1, 0); + input_acquired = 1; +} + +void inputdevice_unacquire (void) +{ + int i; + + for (i = 0; i < MAX_INPUT_DEVICES; i++) + idev[IDTYPE_JOYSTICK].unacquire (i); + for (i = 0; i < MAX_INPUT_DEVICES; i++) + idev[IDTYPE_MOUSE].unacquire (i); + for (i = 0; i < MAX_INPUT_DEVICES; i++) + idev[IDTYPE_KEYBOARD].unacquire (i); + + if (!input_acquired) + return; + + input_acquired = 0; + idev[IDTYPE_JOYSTICK].unacquire (-1); + idev[IDTYPE_MOUSE].unacquire (-1); + idev[IDTYPE_KEYBOARD].unacquire (-1); +} + +/* Call this function when host machine's joystick/joypad/etc button state changes +* This function translates button events to Amiga joybutton/joyaxis/keyboard events +*/ + +/* button states: +* state = -1 -> mouse wheel turned or similar (button without release) +* state = 1 -> button pressed +* state = 0 -> button released +*/ + +void setjoybuttonstate (int joy, int button, int state) +{ + setbuttonstateall (&joysticks[joy], &joysticks2[joy], button, state ? 1 : 0); +} + +#ifndef INPUTDEVICE_SIMPLE +/* buttonmask = 1 = normal toggle button, 0 = mouse wheel turn or similar +*/ +void setjoybuttonstateall (int joy, uae_u32 buttonbits, uae_u32 buttonmask) +{ + int i; + + for (i = 0; i < ID_BUTTON_TOTAL; i++) { + if (buttonmask & (1 << i)) + setbuttonstateall (&joysticks[joy], &joysticks2[joy], i, (buttonbits & (1 << i)) ? 1 : 0); + else if (buttonbits & (1 << i)) + setbuttonstateall (&joysticks[joy], &joysticks2[joy], i, -1); + } +} +/* mouse buttons (just like joystick buttons) +*/ +void setmousebuttonstateall (int mouse, uae_u32 buttonbits, uae_u32 buttonmask) +{ + int i; + + for (i = 0; i < ID_BUTTON_TOTAL; i++) { + if (buttonmask & (1 << i)) + setbuttonstateall (&mice[mouse], &mice2[mouse], i, (buttonbits & (1 << i)) ? 1 : 0); + else if (buttonbits & (1 << i)) + setbuttonstateall (&mice[mouse], &mice2[mouse], i, -1); + } +} +#endif + +void setmousebuttonstate (int mouse, int button, int state) +{ + setbuttonstateall (&mice[mouse], &mice2[mouse], button, state); +} + + +/* same for joystick axis (analog or digital) +* (0 = center, -max = full left/top, max = full right/bottom) +*/ +void setjoystickstate (int joy, int axis, int state, int max) +{ + struct uae_input_device *id = &joysticks[joy]; + struct uae_input_device2 *id2 = &joysticks2[joy]; + int deadzone = currprefs.input_joymouse_deadzone * max / 100; + int i, v1, v2; + + v1 = state; + v2 = id2->states[axis]; + if (v1 < deadzone && v1 > -deadzone) + v1 = 0; + if (v2 < deadzone && v2 > -deadzone) + v2 = 0; + if (v1 == v2) + return; + if (!joysticks[joy].enabled) { + if (v1) + switchdevice (&joysticks[joy], axis * 2 + (v1 < 0 ? 0 : 1), false); + return; + } + for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) +#ifdef INPUTDEVICE_SIMPLE + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i] & ID_FLAG_AUTOFIRE); +#else + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i] & ID_FLAG_AUTOFIRE, true, false); +#endif + id2->states[axis] = state; +} +int getjoystickstate (int joy) +{ + return joysticks[joy].enabled; } void setmousestate (int mouse, int axis, int data, int isabs) { - if(currprefs.input_tablet > 0) { - // Use mousehack to set position - if(isabs) { - if (axis == 0) - lastmx = data; - else - lastmy = data; - } else { - if(axis == 0) { - lastmx += data; - if(lastmx < 0) - lastmx = 0; - else if (lastmx >= mouse_maxx) - lastmx = mouse_maxx - 1; - } else { - lastmy += data; - if(lastmy < 0) - lastmy = 0; - else if (lastmy >= mouse_maxy) - lastmy = mouse_maxy - 1; - } - } + int i, v, diff; + int *mouse_p, *oldm_p; + double d; + struct uae_input_device *id = &mice[mouse]; + static double fract[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; - if (axis) - mousehack_helper (); - } else { - // Set mouseposition without hack - if(axis == 0) { - lastmx += data; - } else { - lastmy += data; - } - } + if (!mice[mouse].enabled) { + return; + } + d = 0; + mouse_p = &mouse_axis[mouse][axis]; + oldm_p = &oldm_axis[mouse][axis]; + if (!isabs) { + // eat relative movements while in mousehack mode + if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive ()) + return; + *oldm_p = *mouse_p; + *mouse_p += data; + d = (*mouse_p - *oldm_p) * currprefs.input_mouse_speed / 100.0; + } else { + d = data - *oldm_p; + *oldm_p = data; + *mouse_p += d; + if (axis == 0) + lastmx = data; + else + lastmy = data; + if (axis) + mousehack_helper (); + if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive ()) + return; + } + v = (int)d; + fract[mouse][axis] += d - v; + diff = (int)fract[mouse][axis]; + v += diff; + fract[mouse][axis] -= diff; + for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) +#ifdef INPUTDEVICE_SIMPLE + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, 0); +#else + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, 0, true, false); +#endif +} + +int getmousestate (int joy) +{ + return mice[joy].enabled; +} + +int jsem_isjoy (int port, const struct uae_prefs *p) +{ + int v = JSEM_DECODEVAL (port, p); + if (v < JSEM_JOYS) + return -1; + v -= JSEM_JOYS; + if (v >= inputdevice_get_device_total (IDTYPE_JOYSTICK)) + return -1; + return v; +} + +int jsem_ismouse (int port, const struct uae_prefs *p) +{ + int v = JSEM_DECODEVAL (port, p); + if (v < JSEM_MICE) + return -1; + v -= JSEM_MICE; + if (v >= inputdevice_get_device_total (IDTYPE_MOUSE)) + return -1; + return v; +} + +int jsem_iskbdjoy (int port, const struct uae_prefs *p) +{ + int v = JSEM_DECODEVAL (port, p); + if (v < JSEM_KBDLAYOUT) + return -1; + v -= JSEM_KBDLAYOUT; + if (v >= JSEM_LASTKBD) + return -1; + return v; +} + +int inputdevice_joyport_config (struct uae_prefs *p, const TCHAR *value, int portnum, int mode, int type) +{ + switch (type) + { + case 1: + case 2: + { + int i, j; + for (j = 0; j < MAX_JPORTS; j++) { + struct inputdevice_functions *idf; + int type = IDTYPE_MOUSE; + int idnum = JSEM_MICE; + if (j > 0) { + type = IDTYPE_JOYSTICK; + idnum = JSEM_JOYS; + } + idf = &idev[type]; + for (i = 0; i < idf->get_num (); i++) { + TCHAR *name1 = idf->get_friendlyname (i); + TCHAR *name2 = idf->get_uniquename (i); + if ((name1 && !_tcscmp (name1, value)) || (name2 && !_tcscmp (name2, value))) { + p->jports[portnum].id = idnum + i; + if (mode >= 0) + p->jports[portnum].mode = mode; + return 1; + } + } + } + } + break; + case 0: + { + int start = JPORT_NONE, got = 0, max = -1; + const TCHAR *pp = 0; + if (_tcsncmp (value, _T("kbd"), 3) == 0) { + start = JSEM_KBDLAYOUT; + pp = value + 3; + got = 1; + max = JSEM_LASTKBD; + } else if (_tcsncmp (value, _T("joy"), 3) == 0) { + start = JSEM_JOYS; + pp = value + 3; + got = 1; + max = idev[IDTYPE_JOYSTICK].get_num (); + } else if (_tcsncmp (value, _T("mouse"), 5) == 0) { + start = JSEM_MICE; + pp = value + 5; + got = 1; + max = idev[IDTYPE_MOUSE].get_num (); + } else if (_tcscmp (value, _T("none")) == 0) { + got = 2; + } else if (_tcscmp (value, _T("custom")) == 0) { + got = 2; + start = JPORT_CUSTOM; + } + if (got) { + if (pp && max != 0) { + int v = _tstol (pp); + if (start >= 0) { + if (start == JSEM_KBDLAYOUT && v > 0) + v--; + if (v >= 0) { + if (v >= max) + v = 0; + start += v; + got = 2; + } + } + } + if (got == 2) { + p->jports[portnum].id = start; + if (mode >= 0) + p->jports[portnum].mode = mode; + return 1; + } + } + } + break; + } + return 0; +} + +int inputdevice_getjoyportdevice (int port, int val) +{ + int idx; + if (val == JPORT_CUSTOM) { + idx = inputdevice_get_device_total (IDTYPE_JOYSTICK) + JSEM_LASTKBD; + if (port < 2) + idx += inputdevice_get_device_total (IDTYPE_MOUSE); + } else if (val < 0) { + idx = -1; + } else if (val >= JSEM_MICE) { + idx = val - JSEM_MICE; + if (idx >= inputdevice_get_device_total (IDTYPE_MOUSE)) + idx = 0; + else + idx += inputdevice_get_device_total (IDTYPE_JOYSTICK); + idx += JSEM_LASTKBD; + } else if (val >= JSEM_JOYS) { + idx = val - JSEM_JOYS; + if (idx >= inputdevice_get_device_total (IDTYPE_JOYSTICK)) + idx = 0; + idx += JSEM_LASTKBD; + } else { + idx = val - JSEM_KBDLAYOUT; + } + return idx; } diff --git a/src/inputevents.def b/src/inputevents.def new file mode 100644 index 00000000..1ecd01ad --- /dev/null +++ b/src/inputevents.def @@ -0,0 +1,397 @@ +/* joystick/mouse port 1 */ + +DEFEVENT(JOYPORT1_START,_T("Joystick port 1"), AM_INFO, 0,1,0) + +DEFEVENT(MOUSE1_FIRST, _T(""), AM_DUMMY, 0,0,0) + +DEFEVENT(MOUSE1_HORIZ,_T("Mouse1 Horizontal"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,1,0) +DEFEVENT(MOUSE1_VERT,_T("Mouse1 Vertical"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,1,1) +DEFEVENT(MOUSE1_HORIZ_INV,_T("Mouse1 Horizontal (inverted)"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,1,0|IE_INVERT) +DEFEVENT(MOUSE1_VERT_INV,_T("Mouse1 Vertical (inverted)"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,1,1|IE_INVERT) +DEFEVENT(MOUSE1_UP,_T("Mouse1 Up"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,32,1,DIR_UP) +DEFEVENT(MOUSE1_DOWN,_T("Mouse1 Down"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,32,1,DIR_DOWN) +DEFEVENT(MOUSE1_LEFT,_T("Mouse1 Left"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,64,1,DIR_LEFT) +DEFEVENT(MOUSE1_RIGHT,_T("Mouse1 Right"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,64,1,DIR_RIGHT) +DEFEVENT(MOUSE1_WHEEL,_T("Mouse1 Wheel"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,1,2) + +DEFEVENT(MOUSE1_LAST, _T(""), AM_DUMMY, 0,0,0) + +DEFEVENT(MOUSE_CDTV_HORIZ,_T("CDTV Mouse Horizontal"),AM_JOY_AXIS,8,1,0|IE_CDTV) +DEFEVENT(MOUSE_CDTV_VERT,_T("CDTV Mouse Vertical"),AM_JOY_AXIS,8,1,1|IE_CDTV) +DEFEVENT(MOUSE_CDTV_UP,_T("CDTV Mouse Up"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,32,1,DIR_UP|IE_CDTV) +DEFEVENT(MOUSE_CDTV_DOWN,_T("CDTV Mouse Down"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,32,1,DIR_DOWN|IE_CDTV) +DEFEVENT(MOUSE_CDTV_LEFT,_T("CDTV Mouse Left"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,64,1,DIR_LEFT|IE_CDTV) +DEFEVENT(MOUSE_CDTV_RIGHT,_T("CDTV Mouse Right"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,64,1,DIR_RIGHT|IE_CDTV) + +DEFEVENT(JOY1_HORIZ,_T("Joy1 Horizontal"),AM_JOY_AXIS,0,1,DIR_LEFT|DIR_RIGHT) +DEFEVENT(JOY1_VERT,_T("Joy1 Vertical"),AM_JOY_AXIS,0,1,DIR_UP|DIR_DOWN) +DEFEVENT(JOY1_HORIZ_POT,_T("Joy1 Horizontal (Analog)"),AM_JOY_AXIS,128,1,1) +DEFEVENT(JOY1_VERT_POT,_T("Joy1 Vertical (Analog)"),AM_JOY_AXIS,128,1,0) +DEFEVENT(JOY1_HORIZ_POT_INV,_T("Joy1 Horizontal (Analog, inverted)"),AM_JOY_AXIS,128,1,1|IE_INVERT) +DEFEVENT(JOY1_VERT_POT_INV,_T("Joy1 Vertical (Analog, inverted)"),AM_JOY_AXIS,128,1,0|IE_INVERT) + +DEFEVENT(JOY1_LEFT,_T("Joy1 Left"),AM_K,16,1,DIR_LEFT) +DEFEVENT(JOY1_RIGHT,_T("Joy1 Right"),AM_K,16,1,DIR_RIGHT) +DEFEVENT(JOY1_UP,_T("Joy1 Up"),AM_K,16,1,DIR_UP) +DEFEVENT(JOY1_DOWN,_T("Joy1 Down"),AM_K,16,1,DIR_DOWN) +DEFEVENT(JOY1_LEFT_UP,_T("Joy1 Left+Up"),AM_K,16,1,DIR_LEFT|DIR_UP) +DEFEVENT(JOY1_LEFT_DOWN,_T("Joy1 Left+Down"),AM_K,16,1,DIR_LEFT|DIR_DOWN) +DEFEVENT(JOY1_RIGHT_UP,_T("Joy1 Right+Up"),AM_K,16,1,DIR_RIGHT|DIR_UP) +DEFEVENT(JOY1_RIGHT_DOWN,_T("Joy1 Right+Down"),AM_K,16,1,DIR_RIGHT|DIR_DOWN) + +DEFEVENT(JOY1_FIRE_BUTTON,_T("Joy1 Fire/Mouse1 Left Button"),AM_K,4,1,JOYBUTTON_1) +DEFEVENT(JOY1_2ND_BUTTON,_T("Joy1 2nd Button/Mouse1 Right Button"),AM_K,4,1,JOYBUTTON_2) +DEFEVENT(JOY1_3RD_BUTTON,_T("Joy1 3rd Button/Mouse1 Middle Button"),AM_K,4,1,JOYBUTTON_3) +DEFEVENT(JOY1_CD32_PLAY,_T("Joy1 CD32 Play"),AM_K,4,1,JOYBUTTON_CD32_PLAY) +DEFEVENT(JOY1_CD32_RWD,_T("Joy1 CD32 RWD"),AM_K,4,1,JOYBUTTON_CD32_RWD) +DEFEVENT(JOY1_CD32_FFW,_T("Joy1 CD32 FFW"),AM_K,4,1,JOYBUTTON_CD32_FFW) +DEFEVENT(JOY1_CD32_GREEN,_T("Joy1 CD32 Green"),AM_K,4,1,JOYBUTTON_CD32_GREEN) +DEFEVENT(JOY1_CD32_YELLOW,_T("Joy1 CD32 Yellow"),AM_K,4,1,JOYBUTTON_CD32_YELLOW) +DEFEVENT(JOY1_CD32_RED,_T("Joy1 CD32 Red"),AM_K,4,1,JOYBUTTON_CD32_RED) +DEFEVENT(JOY1_CD32_BLUE,_T("Joy1 CD32 Blue"),AM_K,4,1,JOYBUTTON_CD32_BLUE) + +/* joystick/mouse port 2 */ + +DEFEVENT(JOYPORT2_START,_T("Joystick port 2"), AM_INFO, 0,2,0) + +DEFEVENT(MOUSE2_FIRST, _T(""), AM_DUMMY, 0,0,0) + +DEFEVENT(MOUSE2_HORIZ,_T("Mouse2 Horizontal"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,2,0) +DEFEVENT(MOUSE2_VERT,_T("Mouse2 Vertical"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,2,1) +DEFEVENT(MOUSE2_HORIZ_INV,_T("Mouse2 Horizontal (inverted)"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,2,0|IE_INVERT) +DEFEVENT(MOUSE2_VERT_INV,_T("Mouse2 Vertical (inverted)"),AM_MOUSE_AXIS|AM_JOY_AXIS,8,2,1|IE_INVERT) +DEFEVENT(MOUSE2_UP,_T("Mouse2 Up"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,32,2,DIR_UP) +DEFEVENT(MOUSE2_DOWN,_T("Mouse2 Down"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,32,2,DIR_DOWN) +DEFEVENT(MOUSE2_LEFT,_T("Mouse2 Left"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,64,2,DIR_LEFT) +DEFEVENT(MOUSE2_RIGHT,_T("Mouse2 Right"),AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT,64,2,DIR_RIGHT) + +DEFEVENT(MOUSE2_LAST, _T(""), AM_DUMMY, 0,0,0) + +DEFEVENT(JOY2_HORIZ,_T("Joy2 Horizontal"),AM_JOY_AXIS,0,2,DIR_LEFT|DIR_RIGHT) +DEFEVENT(JOY2_VERT,_T("Joy2 Vertical"),AM_JOY_AXIS,0,2,DIR_UP|DIR_DOWN) +DEFEVENT(JOY2_HORIZ_POT,_T("Joy2 Horizontal (Analog)"),AM_JOY_AXIS,128,2,1) +DEFEVENT(JOY2_VERT_POT,_T("Joy2 Vertical (Analog)"),AM_JOY_AXIS,128,2,0) +DEFEVENT(JOY2_HORIZ_POT_INV,_T("Joy2 Horizontal (Analog, inverted)"),AM_JOY_AXIS,128,2,1|IE_INVERT) +DEFEVENT(JOY2_VERT_POT_INV,_T("Joy2 Vertical (Analog, inverted)"),AM_JOY_AXIS,128,2,0|IE_INVERT) + +DEFEVENT(JOY2_LEFT,_T("Joy2 Left"),AM_K,16,2,DIR_LEFT) +DEFEVENT(JOY2_RIGHT,_T("Joy2 Right"),AM_K,16,2,DIR_RIGHT) +DEFEVENT(JOY2_UP,_T("Joy2 Up"),AM_K,16,2,DIR_UP) +DEFEVENT(JOY2_DOWN,_T("Joy2 Down"),AM_K,16,2,DIR_DOWN) +DEFEVENT(JOY2_LEFT_UP,_T("Joy2 Left+Up"),AM_K,16,2,DIR_LEFT|DIR_UP) +DEFEVENT(JOY2_LEFT_DOWN,_T("Joy2 Left+Down"),AM_K,16,2,DIR_LEFT|DIR_DOWN) +DEFEVENT(JOY2_RIGHT_UP,_T("Joy2 Right+Up"),AM_K,16,2,DIR_RIGHT|DIR_UP) +DEFEVENT(JOY2_RIGHT_DOWN,_T("Joy2 Right+Down"),AM_K,16,2,DIR_RIGHT|DIR_DOWN) + +DEFEVENT(JOY2_FIRE_BUTTON,_T("Joy2 Fire/Mouse2 Left Button"),AM_K,4,2,JOYBUTTON_1) +DEFEVENT(JOY2_2ND_BUTTON,_T("Joy2 2nd Button/Mouse2 Right Button"),AM_K,4,2,JOYBUTTON_2) +DEFEVENT(JOY2_3RD_BUTTON,_T("Joy2 3rd Button/Mouse2 Middle Button"),AM_K,4,2,JOYBUTTON_3) +DEFEVENT(JOY2_CD32_PLAY,_T("Joy2 CD32 Play"),AM_K,4,2,JOYBUTTON_CD32_PLAY) +DEFEVENT(JOY2_CD32_RWD,_T("Joy2 CD32 RWD"),AM_K,4,2,JOYBUTTON_CD32_RWD) +DEFEVENT(JOY2_CD32_FFW,_T("Joy2 CD32 FFW"),AM_K,4,2,JOYBUTTON_CD32_FFW) +DEFEVENT(JOY2_CD32_GREEN,_T("Joy2 CD32 Green"),AM_K,4,2,JOYBUTTON_CD32_GREEN) +DEFEVENT(JOY2_CD32_YELLOW,_T("Joy2 CD32 Yellow"),AM_K,4,2,JOYBUTTON_CD32_YELLOW) +DEFEVENT(JOY2_CD32_RED,_T("Joy2 CD32 Red"),AM_K,4,2,JOYBUTTON_CD32_RED) +DEFEVENT(JOY2_CD32_BLUE,_T("Joy2 CD32 Blue"),AM_K,4,2,JOYBUTTON_CD32_BLUE) + +DEFEVENT(LIGHTPEN_HORIZ,_T("Lightpen Horizontal"),AM_MOUSE_AXIS|AM_JOY_AXIS,0,5,0) +DEFEVENT(LIGHTPEN_VERT,_T("Lightpen Vertical"),AM_MOUSE_AXIS|AM_JOY_AXIS,0,5,1) +DEFEVENT(LIGHTPEN_LEFT,_T("Lightpen Left"),AM_K,1,5,DIR_LEFT) +DEFEVENT(LIGHTPEN_RIGHT,_T("Lightpen Right"),AM_K,1,5,DIR_RIGHT) +DEFEVENT(LIGHTPEN_UP,_T("Lightpen Up"),AM_K,1,5,DIR_UP) +DEFEVENT(LIGHTPEN_DOWN,_T("Lightpen Down"),AM_K,1,5,DIR_DOWN) + +/* parallel port joystick adapter */ + +DEFEVENT(PAR_JOY1_START, _T("Parallel port joystick adapter"), AM_INFO, 0,3,0) + +DEFEVENT(PAR_JOY1_HORIZ,_T("Parallel Joy1 Horizontal"),AM_JOY_AXIS,0,3,DIR_LEFT|DIR_RIGHT) +DEFEVENT(PAR_JOY1_VERT,_T("Parallel Joy1 Vertical"),AM_JOY_AXIS,0,3,DIR_UP|DIR_DOWN) +DEFEVENT(PAR_JOY1_LEFT,_T("Parallel Joy1 Left"),AM_K,16,3,DIR_LEFT) +DEFEVENT(PAR_JOY1_RIGHT,_T("Parallel Joy1 Right"),AM_K,16,3,DIR_RIGHT) +DEFEVENT(PAR_JOY1_UP,_T("Parallel Joy1 Up"),AM_K,16,3,DIR_UP) +DEFEVENT(PAR_JOY1_DOWN,_T("Parallel Joy1 Down"),AM_K,16,3,DIR_DOWN) +DEFEVENT(PAR_JOY1_LEFT_UP,_T("Parallel Joy1 Left+Up"),AM_K,16,3,DIR_LEFT|DIR_UP) +DEFEVENT(PAR_JOY1_LEFT_DOWN,_T("Parallel Joy1 Left+Down"),AM_K,16,3,DIR_LEFT|DIR_DOWN) +DEFEVENT(PAR_JOY1_RIGHT_UP,_T("Parallel Joy1 Right+Up"),AM_K,16,3,DIR_RIGHT|DIR_UP) +DEFEVENT(PAR_JOY1_RIGHT_DOWN,_T("Parallel Joy1 Right+Down"),AM_K,16,3,DIR_RIGHT|DIR_DOWN) +DEFEVENT(PAR_JOY1_FIRE_BUTTON,_T("Parallel Joy1 Fire Button"),AM_K,4,3,JOYBUTTON_1) +DEFEVENT(PAR_JOY1_2ND_BUTTON,_T("Parallel Joy1 Spare/2nd Button"),AM_K,4,3,JOYBUTTON_2) + +DEFEVENT(PAR_JOY2_START, _T(""), AM_DUMMY, 0,4,0) + +DEFEVENT(PAR_JOY2_HORIZ,_T("Parallel Joy2 Horizontal"),AM_JOY_AXIS,0,4,DIR_LEFT|DIR_RIGHT) +DEFEVENT(PAR_JOY2_VERT,_T("Parallel Joy2 Vertical"),AM_JOY_AXIS,0,4,DIR_UP|DIR_DOWN) +DEFEVENT(PAR_JOY2_LEFT,_T("Parallel Joy2 Left"),AM_K,16,4,DIR_LEFT) +DEFEVENT(PAR_JOY2_RIGHT,_T("Parallel Joy2 Right"),AM_K,16,4,DIR_RIGHT) +DEFEVENT(PAR_JOY2_UP,_T("Parallel Joy2 Up"),AM_K,16,4,DIR_UP) +DEFEVENT(PAR_JOY2_DOWN,_T("Parallel Joy2 Down"),AM_K,16,4,DIR_DOWN) +DEFEVENT(PAR_JOY2_LEFT_UP,_T("Parallel Joy2 Left+Up"),AM_K,16,4,DIR_LEFT|DIR_UP) +DEFEVENT(PAR_JOY2_LEFT_DOWN,_T("Parallel Joy2 Left+Down"),AM_K,16,4,DIR_LEFT|DIR_DOWN) +DEFEVENT(PAR_JOY2_RIGHT_UP,_T("Parallel Joy2 Right+Up"),AM_K,16,4,DIR_RIGHT|DIR_UP) +DEFEVENT(PAR_JOY2_RIGHT_DOWN,_T("Parallel Joy2 Right+Down"),AM_K,16,4,DIR_RIGHT|DIR_DOWN) +DEFEVENT(PAR_JOY2_FIRE_BUTTON,_T("Parallel Joy2 Fire Button"),AM_K,4,4,JOYBUTTON_1) +DEFEVENT(PAR_JOY2_2ND_BUTTON,_T("Parallel Joy2 Spare/2nd Button"),AM_K,4,4,JOYBUTTON_2) + +DEFEVENT(PAR_JOY_END, _T(""), AM_DUMMY, 0,0,0) + +/* qualifiers */ + +DEFEVENT(SPC_QUALIFIER_START,_T("Qualifiers"),AM_INFO, 0,0,0) + +DEFEVENT(SPC_QUALIFIER1,_T("Qualifier 1"),AM_KK,0,0,AKS_QUALIFIER1) +DEFEVENT(SPC_QUALIFIER2,_T("Qualifier 2"),AM_KK,0,0,AKS_QUALIFIER2) +DEFEVENT(SPC_QUALIFIER3,_T("Qualifier 3"),AM_KK,0,0,AKS_QUALIFIER3) +DEFEVENT(SPC_QUALIFIER4,_T("Qualifier 4"),AM_KK,0,0,AKS_QUALIFIER4) +DEFEVENT(SPC_QUALIFIER5,_T("Qualifier 5"),AM_KK,0,0,AKS_QUALIFIER5) +DEFEVENT(SPC_QUALIFIER6,_T("Qualifier 6"),AM_KK,0,0,AKS_QUALIFIER6) +DEFEVENT(SPC_QUALIFIER7,_T("Qualifier 7"),AM_KK,0,0,AKS_QUALIFIER7) +DEFEVENT(SPC_QUALIFIER8,_T("Qualifier 8"),AM_KK,0,0,AKS_QUALIFIER8) +DEFEVENT(SPC_QUALIFIER_SPECIAL,_T("Qualifier Special"),AM_KK,0,0,AKS_QUALIFIER_SPECIAL) +DEFEVENT(SPC_QUALIFIER_SHIFT,_T("Qualifier Shift"),AM_KK,0,0,AKS_QUALIFIER_SHIFT) +DEFEVENT(SPC_QUALIFIER_CONTROL,_T("Qualifier Control"),AM_KK,0,0,AKS_QUALIFIER_CONTROL) +DEFEVENT(SPC_QUALIFIER_ALT,_T("Qualifier Alt"),AM_KK,0,0,AKS_QUALIFIER_ALT) + +DEFEVENT(SPC_QUALIFIER_END, _T(""), AM_DUMMY, 0,0,0) + +/* keys */ + +DEFEVENT(KEY_START,_T("Keyboard"),AM_INFO, 0,0,0) + +DEFEVENT(KEY_F1,_T("F1"),AM_K,0,0,AK_F1) +DEFEVENT(KEY_F2,_T("F2"),AM_K,0,0,AK_F2) +DEFEVENT(KEY_F3,_T("F3"),AM_K,0,0,AK_F3) +DEFEVENT(KEY_F4,_T("F4"),AM_K,0,0,AK_F4) +DEFEVENT(KEY_F5,_T("F5"),AM_K,0,0,AK_F5) +DEFEVENT(KEY_F6,_T("F6"),AM_K,0,0,AK_F6) +DEFEVENT(KEY_F7,_T("F7"),AM_K,0,0,AK_F7) +DEFEVENT(KEY_F8,_T("F8"),AM_K,0,0,AK_F8) +DEFEVENT(KEY_F9,_T("F9"),AM_K,0,0,AK_F9) +DEFEVENT(KEY_F10,_T("F10"),AM_K,0,0,AK_F10) + +/* "special" keys */ + +DEFEVENT(KEY_ESC,_T("ESC"),AM_K,0,0,AK_ESC) +DEFEVENT(KEY_TAB,_T("Tab"),AM_K,0,0,AK_TAB) +DEFEVENT(KEY_CTRL,_T("CTRL"),AM_K,0,0,AK_CTRL) +DEFEVENT(KEY_CAPS_LOCK,_T("Caps Lock"),AM_K,0,0,AK_CAPSLOCK) +DEFEVENT(KEY_SHIFT_LEFT,_T("Left Shift"),AM_K,0,0,AK_LSH) +DEFEVENT(KEY_ALT_LEFT,_T("Left Alt"),AM_K,0,0,AK_LALT) +DEFEVENT(KEY_AMIGA_LEFT,_T("Left Amiga"),AM_K,0,0,AK_LAMI) +DEFEVENT(KEY_AMIGA_RIGHT,_T("Right Amiga"),AM_K,0,0,AK_RAMI) +DEFEVENT(KEY_ALT_RIGHT,_T("Right Alt"),AM_K,0,0,AK_RALT) +DEFEVENT(KEY_SHIFT_RIGHT,_T("Right Shift"),AM_K,0,0,AK_RSH) +DEFEVENT(KEY_SPACE,_T("Space"),AM_K,0,0,AK_SPC) +DEFEVENT(KEY_CURSOR_UP,_T("Cursor Up"),AM_K,0,0,AK_UP) +DEFEVENT(KEY_CURSOR_DOWN,_T("Cursor Down"),AM_K,0,0,AK_DN) +DEFEVENT(KEY_CURSOR_LEFT,_T("Cursor Left"),AM_K,0,0,AK_LF) +DEFEVENT(KEY_CURSOR_RIGHT,_T("Cursor Right"),AM_K,0,0,AK_RT) +DEFEVENT(KEY_HELP,_T("Help"),AM_K,0,0,AK_HELP) +DEFEVENT(KEY_DEL,_T("Del"),AM_K,0,0,AK_DEL) +DEFEVENT(KEY_BACKSPACE,_T("Backspace"),AM_K,0,0,AK_BS) +DEFEVENT(KEY_RETURN,_T("Return"),AM_K,0,0,AK_RET) + +DEFEVENT(KEY_A,_T("A"),AM_K,0,0,AK_A) +DEFEVENT(KEY_B,_T("B"),AM_K,0,0,AK_B) +DEFEVENT(KEY_C,_T("C"),AM_K,0,0,AK_C) +DEFEVENT(KEY_D,_T("D"),AM_K,0,0,AK_D) +DEFEVENT(KEY_E,_T("E"),AM_K,0,0,AK_E) +DEFEVENT(KEY_F,_T("F"),AM_K,0,0,AK_F) +DEFEVENT(KEY_G,_T("G"),AM_K,0,0,AK_G) +DEFEVENT(KEY_H,_T("H"),AM_K,0,0,AK_H) +DEFEVENT(KEY_I,_T("I"),AM_K,0,0,AK_I) +DEFEVENT(KEY_J,_T("J"),AM_K,0,0,AK_J) +DEFEVENT(KEY_K,_T("K"),AM_K,0,0,AK_K) +DEFEVENT(KEY_L,_T("L"),AM_K,0,0,AK_L) +DEFEVENT(KEY_M,_T("M"),AM_K,0,0,AK_M) +DEFEVENT(KEY_N,_T("N"),AM_K,0,0,AK_N) +DEFEVENT(KEY_O,_T("O"),AM_K,0,0,AK_O) +DEFEVENT(KEY_P,_T("P"),AM_K,0,0,AK_P) +DEFEVENT(KEY_Q,_T("Q"),AM_K,0,0,AK_Q) +DEFEVENT(KEY_R,_T("R"),AM_K,0,0,AK_R) +DEFEVENT(KEY_S,_T("S"),AM_K,0,0,AK_S) +DEFEVENT(KEY_T,_T("T"),AM_K,0,0,AK_T) +DEFEVENT(KEY_U,_T("U"),AM_K,0,0,AK_U) +DEFEVENT(KEY_V,_T("V"),AM_K,0,0,AK_V) +DEFEVENT(KEY_W,_T("W"),AM_K,0,0,AK_W) +DEFEVENT(KEY_X,_T("X"),AM_K,0,0,AK_X) +DEFEVENT(KEY_Y,_T("Y"),AM_K,0,0,AK_Y) +DEFEVENT(KEY_Z,_T("Z"),AM_K,0,0,AK_Z) + +/* numpad */ + +DEFEVENT(KEY_ENTER,_T("Numpad Enter"),AM_K,0,0,AK_ENT) +DEFEVENT(KEY_NP_0,_T("Numpad 0"),AM_K,0,0,AK_NP0) +DEFEVENT(KEY_NP_1,_T("Numpad 1"),AM_K,0,0,AK_NP1) +DEFEVENT(KEY_NP_2,_T("Numpad 2"),AM_K,0,0,AK_NP2) +DEFEVENT(KEY_NP_3,_T("Numpad 3"),AM_K,0,0,AK_NP3) +DEFEVENT(KEY_NP_4,_T("Numpad 4"),AM_K,0,0,AK_NP4) +DEFEVENT(KEY_NP_5,_T("Numpad 5"),AM_K,0,0,AK_NP5) +DEFEVENT(KEY_NP_6,_T("Numpad 6"),AM_K,0,0,AK_NP6) +DEFEVENT(KEY_NP_7,_T("Numpad 7"),AM_K,0,0,AK_NP7) +DEFEVENT(KEY_NP_8,_T("Numpad 8"),AM_K,0,0,AK_NP8) +DEFEVENT(KEY_NP_9,_T("Numpad 9"),AM_K,0,0,AK_NP9) +DEFEVENT(KEY_NP_PERIOD,_T("Numpad Period"),AM_K,0,0,AK_NPDEL) +DEFEVENT(KEY_NP_ADD,_T("Numpad Plus"),AM_K,0,0,AK_NPADD) +DEFEVENT(KEY_NP_SUB,_T("Numpad Minus"),AM_K,0,0,AK_NPSUB) +DEFEVENT(KEY_NP_MUL,_T("Numpad Multiply"),AM_K,0,0,AK_NPMUL) +DEFEVENT(KEY_NP_DIV,_T("Numpad Divide"),AM_K,0,0,AK_NPDIV) +DEFEVENT(KEY_NP_LPAREN,_T("Numpad Left Parenthesis"),AM_K,0,0,AK_NPLPAREN) +DEFEVENT(KEY_NP_RPAREN,_T("Numpad Right Parenthesis"),AM_K,0,0,AK_NPRPAREN) +DEFEVENT(KEY_2B,_T("Keycode 0x2b"),AM_K,0,0,0x2b) +DEFEVENT(KEY_30,_T("Keycode 0x30"),AM_K,0,0,0x30) + +DEFEVENT(KEY_BACKQUOTE,_T("Back Quote"),AM_K,0,0,AK_BACKQUOTE) +DEFEVENT(KEY_1,_T("1"),AM_K,0,0,AK_1) +DEFEVENT(KEY_2,_T("2"),AM_K,0,0,AK_2) +DEFEVENT(KEY_3,_T("3"),AM_K,0,0,AK_3) +DEFEVENT(KEY_4,_T("4"),AM_K,0,0,AK_4) +DEFEVENT(KEY_5,_T("5"),AM_K,0,0,AK_5) +DEFEVENT(KEY_6,_T("6"),AM_K,0,0,AK_6) +DEFEVENT(KEY_7,_T("7"),AM_K,0,0,AK_7) +DEFEVENT(KEY_8,_T("8"),AM_K,0,0,AK_8) +DEFEVENT(KEY_9,_T("9"),AM_K,0,0,AK_9) +DEFEVENT(KEY_0,_T("0"),AM_K,0,0,AK_0) +DEFEVENT(KEY_SUB,_T("Minus"),AM_K,0,0,AK_MINUS) +DEFEVENT(KEY_EQUALS,_T("Equals"),AM_K,0,0,AK_EQUAL) +DEFEVENT(KEY_BACKSLASH,_T("Backslash"),AM_K,0,0,AK_BACKSLASH) + +DEFEVENT(KEY_LEFTBRACKET,_T("Left Bracket"),AM_K,0,0,AK_LBRACKET) +DEFEVENT(KEY_RIGHTBRACKET,_T("Right Bracket"),AM_K,0,0,AK_RBRACKET) +DEFEVENT(KEY_SEMICOLON,_T("Semicolon"),AM_K,0,0,AK_SEMICOLON) +DEFEVENT(KEY_SINGLEQUOTE,_T("Single Quote"),AM_K,0,0,AK_QUOTE) +DEFEVENT(KEY_COMMA,_T("Comma"),AM_K,0,0,AK_COMMA) +DEFEVENT(KEY_PERIOD,_T("Period"),AM_K,0,0,AK_PERIOD) +DEFEVENT(KEY_DIV,_T("Slash"),AM_K,0,0,AK_SLASH) + +// DEFEVENT(KEY_,_T(""),AM_K,0,0,0x) + +/* mouse wheel "keys" */ + +DEFEVENT(MOUSEWHEEL_DOWN,_T("Mouse Wheel Down"),AM_K,0,0,0x7a) +DEFEVENT(MOUSEWHEEL_UP,_T("Mouse Wheel Up"),AM_K,0,0,0x7b) + +/* misc */ + +DEFEVENT(KEY_CDTV_STOP,_T("CDTV Stop"),AM_K,0,0,0x72) +DEFEVENT(KEY_CDTV_PLAYPAUSE,_T("CDTV Play/Pause"),AM_K,0,0,0x73) +DEFEVENT(KEY_CDTV_PREV,_T("CDTV Previous"),AM_K,0,0,0x74) +DEFEVENT(KEY_CDTV_NEXT,_T("CDTV Next"),AM_K,0,0,0x75) +DEFEVENT(KEY_CDTV_REW,_T("CDTV Rewind"),AM_K,0,0,0x76) +DEFEVENT(KEY_CDTV_FF,_T("CDTV Fast Forward"),AM_K,0,0,0x77) + +DEFEVENT(KEY_0E,_T("Keycode 0x0E"),AM_K,0,0,0x0e) + +DEFEVENT(KEY_1C,_T("Keycode 0x1C"),AM_K,0,0,0x1c) + +DEFEVENT(KEY_2C,_T("Keycode 0x2C"),AM_K,0,0,0x2C) + +DEFEVENT(KEY_3B,_T("Keycode 0x3B"),AM_K,0,0,0x3b) + +DEFEVENT(KEY_68,_T("Keycode 0x68"),AM_K,0,0,0x68) +DEFEVENT(KEY_69,_T("Keycode 0x69"),AM_K,0,0,0x69) +DEFEVENT(KEY_6A,_T("Keycode 0x6A"),AM_K,0,0,0x6a) +DEFEVENT(KEY_6C,_T("Keycode 0x6C"),AM_K,0,0,0x6c) + +DEFEVENT(KEY_INSERT,_T("Insert (PC)"),AM_K,0,0,0x47) +DEFEVENT(KEY_PAGEUP,_T("Page Up (PC)"),AM_K,0,0,0x48) +DEFEVENT(KEY_PAGEDOWN,_T("Page Down (PC)"),AM_K,0,0,0x49) +DEFEVENT(KEY_F11,_T("F11 (PC)"),AM_K,0,0,0x4b) +DEFEVENT(KEY_APPS,_T("Apps (PC)"),AM_K,0,0,0x6b) +DEFEVENT(KEY_SYSRQ,_T("PrtScr/SysRq (PC)"),AM_K,0,0,0x6d) +DEFEVENT(KEY_PAUSE,_T("Pause/Break (PC)"),AM_K,0,0,0x6e) +DEFEVENT(KEY_F12,_T("F12 (PC)"),AM_K,0,0,0x6f) +DEFEVENT(KEY_HOME,_T("Home (PC)"),AM_K,0,0,0x70) +DEFEVENT(KEY_END,_T("End (PC)"),AM_K,0,0,0x71) + +DEFEVENT(KEY_78,_T("Keycode 0x78 (Reset Warning)"),AM_K,0,0,0x78) +DEFEVENT(KEY_79,_T("Keycode 0x79"),AM_K,0,0,0x79) +DEFEVENT(KEY_7A,_T("Keycode 0x7A"),AM_K,0,0,0x7a) +DEFEVENT(KEY_7B,_T("Keycode 0x7B"),AM_K,0,0,0x7b) +DEFEVENT(KEY_7C,_T("Keycode 0x7C"),AM_K,0,0,0x7c) +DEFEVENT(KEY_7D,_T("Keycode 0x7D"),AM_K,0,0,0x7d) +DEFEVENT(KEY_7E,_T("Keycode 0x7E"),AM_K,0,0,0x7e) +DEFEVENT(KEY_7F,_T("Keycode 0x7F"),AM_K,0,0,0x7f) + +/* special */ + +DEFEVENT(SPC_CUSTOM_EVENT,_T(""),AM_K,0,0,0) +DEFEVENT(SPC_ENTERGUI,_T("Enter GUI"),AM_K,0,0,AKS_ENTERGUI) +DEFEVENT(SPC_SCREENSHOT,_T("Screenshot (file)"),AM_K,0,0,AKS_SCREENSHOT_FILE) +DEFEVENT(SPC_SCREENSHOT_CLIPBOARD,_T("Screenshot (clipboard)"),AM_K,0,0,AKS_SCREENSHOT_CLIPBOARD) +DEFEVENT(SPC_FREEZEBUTTON,_T("Activate Cartridge"),AM_K,0,0,AKS_FREEZEBUTTON) +DEFEVENT(SPC_FLOPPY0,_T("Change disk in DF0:"),AM_K,0,0,AKS_FLOPPY0) +DEFEVENT(SPC_FLOPPY1,_T("Change disk in DF1:"),AM_K,0,0,AKS_FLOPPY1) +DEFEVENT(SPC_FLOPPY2,_T("Change disk in DF2:"),AM_K,0,0,AKS_FLOPPY2) +DEFEVENT(SPC_FLOPPY3,_T("Change disk in DF3:"),AM_K,0,0,AKS_FLOPPY3) +DEFEVENT(SPC_EFLOPPY0,_T("Eject disk in DF0:"),AM_K,0,0,AKS_EFLOPPY0) +DEFEVENT(SPC_EFLOPPY1,_T("Eject disk in DF1:"),AM_K,0,0,AKS_EFLOPPY1) +DEFEVENT(SPC_EFLOPPY2,_T("Eject disk in DF2:"),AM_K,0,0,AKS_EFLOPPY2) +DEFEVENT(SPC_EFLOPPY3,_T("Eject disk in DF3:"),AM_K,0,0,AKS_EFLOPPY3) +DEFEVENT(SPC_PAUSE,_T("Pause emulation"),AM_K,0,0,AKS_PAUSE) +DEFEVENT(SPC_WARP,_T("Warp mode"),AM_K,0,0,AKS_WARP) +DEFEVENT(SPC_INHIBITSCREEN,_T("Toggle screen updates"),AM_K,0,0,AKS_INHIBITSCREEN) +DEFEVENT(SPC_IRQ7,_T("Level 7 interrupt"),AM_K,0,0,AKS_IRQ7) + +DEFEVENT(SPC_STATEREWIND,_T("Load previous state capture checkpoint"),AM_K,0,0,AKS_STATEREWIND) +DEFEVENT(SPC_STATECURRENT,_T("Load current state capture checkpoint"),AM_K,0,0,AKS_STATECURRENT) +DEFEVENT(SPC_STATECAPTURE,_T("Save state capture checkpoint"),AM_K,0,0,AKS_STATECAPTURE) + +DEFEVENT(SPC_VOLUME_DOWN,_T("Decrease volume level"),AM_K,0,0,AKS_VOLDOWN) +DEFEVENT(SPC_VOLUME_UP,_T("Increase volume level"),AM_K,0,0,AKS_VOLUP) +DEFEVENT(SPC_VOLUME_MUTE,_T("Mute/unmute volume"),AM_K,0,0,AKS_VOLMUTE) +DEFEVENT(SPC_MASTER_VOLUME_DOWN,_T("Decrease master volume level"),AM_K,0,0,AKS_MVOLDOWN) +DEFEVENT(SPC_MASTER_VOLUME_UP,_T("Increase master volume level"),AM_K,0,0,AKS_MVOLUP) +DEFEVENT(SPC_MASTER_VOLUME_MUTE,_T("Mute/unmute master volume"),AM_K,0,0,AKS_MVOLMUTE) +DEFEVENT(SPC_QUIT,_T("Quit emulator"),AM_K,0,0,AKS_QUIT) +DEFEVENT(SPC_SOFTRESET,_T("Reset emulation"),AM_K,0,0,AKS_SOFTRESET) +DEFEVENT(SPC_HARDRESET,_T("Hard reset emulation"),AM_K,0,0,AKS_HARDRESET) +DEFEVENT(SPC_ENTERDEBUGGER,_T("Activate the built-in debugger"),AM_K,0,0,AKS_ENTERDEBUGGER) +DEFEVENT(SPC_STATESAVE,_T("Quick save state"),AM_K,0,0,AKS_STATESAVEQUICK) +DEFEVENT(SPC_STATERESTORE,_T("Quick restore state"),AM_K,0,0,AKS_STATERESTOREQUICK) +DEFEVENT(SPC_STATESAVEDIALOG,_T("Save state"),AM_K,0,0,AKS_STATESAVEDIALOG) +DEFEVENT(SPC_STATERESTOREDIALOG,_T("Restore state"),AM_K,0,0,AKS_STATERESTOREDIALOG) +DEFEVENT(SPC_TOGGLEFULLSCREEN,_T("Toggle windowed/fullscreen"),AM_K,0,0,AKS_TOGGLEWINDOWEDFULLSCREEN) +DEFEVENT(SPC_TOGGLEFULLWINDOWFULLSCREEN,_T("Toggle full-window/fullscreen"),AM_K,0,0,AKS_TOGGLEFULLWINDOWFULLSCREEN) +DEFEVENT(SPC_TOGGLEWINDOWFULLWINDOW,_T("Toggle window/full-window"),AM_K,0,0,AKS_TOGGLEWINDOWFULLWINDOW) +DEFEVENT(SPC_TOGGLEDEFAULTSCREEN,_T("Toggle window/default screen"),AM_K,0,0,AKS_TOGGLEDEFAULTSCREEN) +DEFEVENT(SPC_TOGGLEMOUSEGRAB,_T("Toggle between mouse grabbed and un-grabbed"),AM_K,0,0,AKS_TOGGLEMOUSEGRAB) +DEFEVENT(SPC_DECREASE_REFRESHRATE,_T("Decrease emulation speed"),AM_K,0,0,AKS_DECREASEREFRESHRATE) +DEFEVENT(SPC_INCREASE_REFRESHRATE,_T("Increase emulation speed"),AM_K,0,0,AKS_INCREASEREFRESHRATE) +DEFEVENT(SPC_SWITCHINTERPOL,_T("Switch between audio interpolation methods"),AM_K,0,0,AKS_SWITCHINTERPOL) + +DEFEVENT(SPC_DISKSWAPPER_NEXT,_T("Next slot in Disk Swapper"),AM_K,0,0,AKS_DISKSWAPPER_NEXT) +DEFEVENT(SPC_DISKSWAPPER_PREV,_T("Previous slot in Disk Swapper"),AM_K,0,0,AKS_DISKSWAPPER_PREV) +DEFEVENT(SPC_DISKSWAPPER_INSERT0,_T("Insert disk in current Disk Swapper slot in DF0:"),AM_K,0,0,AKS_DISKSWAPPER_INSERT0) +DEFEVENT(SPC_DISKSWAPPER_INSERT1,_T("Insert disk in current Disk Swapper slot in DF1:"),AM_K,0,0,AKS_DISKSWAPPER_INSERT1) +DEFEVENT(SPC_DISKSWAPPER_INSERT2,_T("Insert disk in current Disk Swapper slot in DF2:"),AM_K,0,0,AKS_DISKSWAPPER_INSERT2) +DEFEVENT(SPC_DISKSWAPPER_INSERT3,_T("Insert disk in current Disk Swapper slot in DF3:"),AM_K,0,0,AKS_DISKSWAPPER_INSERT3) + +DEFEVENT(SPC_DISK_PREV0,_T("Previous disk image in DF0:"),AM_K,0,0,AKS_DISK_PREV0) +DEFEVENT(SPC_DISK_PREV1,_T("Previous disk image in DF1:"),AM_K,0,0,AKS_DISK_PREV1) +DEFEVENT(SPC_DISK_PREV2,_T("Previous disk image in DF2:"),AM_K,0,0,AKS_DISK_PREV2) +DEFEVENT(SPC_DISK_PREV3,_T("Previous disk image in DF3:"),AM_K,0,0,AKS_DISK_PREV3) +DEFEVENT(SPC_DISK_NEXT0,_T("Next disk image in DF0:"),AM_K,0,0,AKS_DISK_NEXT0) +DEFEVENT(SPC_DISK_NEXT1,_T("Next disk image in DF1:"),AM_K,0,0,AKS_DISK_NEXT1) +DEFEVENT(SPC_DISK_NEXT2,_T("Next disk image in DF2:"),AM_K,0,0,AKS_DISK_NEXT2) +DEFEVENT(SPC_DISK_NEXT3,_T("Next disk image in DF3:"),AM_K,0,0,AKS_DISK_NEXT3) + +DEFEVENT(SPC_INPUT_CONFIG1,_T("Select Input Configuration #1"),AM_K,0,0,AKS_INPUT_CONFIG_1) +DEFEVENT(SPC_INPUT_CONFIG2,_T("Select Input Configuration #2"),AM_K,0,0,AKS_INPUT_CONFIG_2) +DEFEVENT(SPC_INPUT_CONFIG3,_T("Select Input Configuration #3"),AM_K,0,0,AKS_INPUT_CONFIG_3) +DEFEVENT(SPC_INPUT_CONFIG4,_T("Select GamePorts Input Configuration"),AM_K,0,0,AKS_INPUT_CONFIG_4) + +DEFEVENT(SPC_ARCADIA_DIAGNOSTICS,_T("Arcadia diagnostics DIP switch"),AM_K,0,0,AKS_ARCADIADIAGNOSTICS) +DEFEVENT(SPC_ARCADIA_PLAYER1,_T("Arcadia player 1"),AM_K,0,0,AKS_ARCADIAPLY1) +DEFEVENT(SPC_ARCADIA_PLAYER2,_T("Arcadia player 2"),AM_K,0,0,AKS_ARCADIAPLY2) +DEFEVENT(SPC_ARCADIA_COIN1,_T("Arcadia coin player 1"),AM_K,0,0,AKS_ARCADIACOIN1) +DEFEVENT(SPC_ARCADIA_COIN2,_T("Arcadia coin player 2"),AM_K,0,0,AKS_ARCADIACOIN2) + +DEFEVENT(SPC_CDTV_FRONT_PANEL_STOP,_T("CDTV Front Panel Stop"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_STOP) +DEFEVENT(SPC_CDTV_FRONT_PANEL_PLAYPAUSE,_T("CDTV Front Panel Play/Pause"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_PLAYPAUSE) +DEFEVENT(SPC_CDTV_FRONT_PANEL_PREV,_T("CDTV Front Panel Previous"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_PREV) +DEFEVENT(SPC_CDTV_FRONT_PANEL_NEXT,_T("CDTV Front Panel Next"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_NEXT) +DEFEVENT(SPC_CDTV_FRONT_PANEL_REW,_T("CDTV Front Panel Rewind"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_REW) +DEFEVENT(SPC_CDTV_FRONT_PANEL_FF,_T("CDTV Front Panel Fast Forward"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_FF) + +DEFEVENT(SPC_LAST, _T(""), AM_DUMMY, 0,0,0) diff --git a/src/jit/codegen_arm.cpp b/src/jit/codegen_arm.cpp index f5a88736..4a258cb8 100644 --- a/src/jit/codegen_arm.cpp +++ b/src/jit/codegen_arm.cpp @@ -78,6 +78,7 @@ extern void __clear_cache (char*, char*); #define REG_WORK1 R2_INDEX #define REG_WORK2 R3_INDEX +#define REG_WORK3 R12_INDEX //#define REG_DATAPTR R10_INDEX @@ -102,13 +103,12 @@ uae_u8 call_saved[]={0,0,0,0, 1,1,1,1, 1,1,1,1, 0,1,1,1}; - Special registers (such like the stack pointer) should not be "preserved" by pushing, even though they are "saved" across function calls */ -static const uae_u8 need_to_preserve[]={0,0,0,0, 1,1,1,1, 1,1,1,1, 1,0,0,0}; +static const uae_u8 need_to_preserve[]={0,0,0,0, 1,1,1,1, 1,1,1,1, 0,0,0,0}; static const uae_u32 PRESERVE_MASK = ((1<> 8), 24); +#endif } static inline void SIGNED16_IMM_2_REG(W4 r, IMM v) { +#ifdef ARMV6T2 + MOVW_ri16(r, v); + SXTH_rr(r, r); +#else uae_s32 offs = data_long_offs((uae_s32)(uae_s16) v); LDR_rRI(r, RPC_INDEX, offs); +#endif } static inline void UNSIGNED8_REG_2_REG(W4 d, RR4 s) { @@ -163,11 +172,17 @@ LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) { - if(i >= 0 && i < 256) { + if(CHECK32(i)) { ADD_rri(d, d, i); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, i); + if(i >> 16) + MOVT_ri16(REG_WORK1, i >> 16); +#else uae_s32 offs = data_long_offs(i); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif ADD_rrr(d, d, REG_WORK1); } } @@ -175,9 +190,19 @@ LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) { - uae_s32 offs = data_long_offs(offset); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] - ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 + if(CHECK32(offset)) { + ADD_rri(d, s, offset); + } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, offset); + if(offset >> 16) + MOVT_ri16(REG_WORK1, offset >> 16); +#else + uae_s32 offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif + ADD_rrr(d, s, REG_WORK1); + } } LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) @@ -216,19 +241,35 @@ LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) { - BIC_rri(d, d, 0xff); // bic %[d], %[d], #0xff - ORR_rri(d, d, (s & 0xff)); // orr %[d], %[d], #%[s] + BIC_rri(d, d, 0xff); + ORR_rri(d, d, (s & 0xff)); } LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) { - BFI_rrii(d, s, 0, 7); // bfi %[d], %[s], 0, 7 + BFI_rrii(d, s, 0, 7); } LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) { +#ifdef ARMV6T2 + if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { + MOVW_ri16(REG_WORK2, s); + if(s >> 16) + MOVT_ri16(REG_WORK2, s >> 16); + uae_s32 idx = d - (uae_u32) ®s; + STR_rRI(REG_WORK2, R_REGSTRUCT, idx); + } else { + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); + MOVW_ri16(REG_WORK2, s); + if(s >> 16) + MOVT_ri16(REG_WORK2, s >> 16); + STR_rR(REG_WORK2, REG_WORK1); + } +#else if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { uae_s32 offs = data_long_offs(s); LDR_rRI(REG_WORK2, RPC_INDEX, offs); @@ -245,13 +286,22 @@ LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] } +#endif } LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) { - uae_s32 offs = data_word_offs(s); - LDR_rRI(REG_WORK2, RPC_INDEX, offs); + if(CHECK32(s)) { + MOV_ri(REG_WORK2, s); + } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, s); +#else + uae_s32 offs = data_word_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif + } PKHBT_rrr(d, REG_WORK2, d); } @@ -263,9 +313,14 @@ LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) uae_s32 idx = d - (uae_u32) ®s; STR_rRI(s, R_REGSTRUCT, idx); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); +#else uae_s32 offs = data_long_offs(d); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] - STR_rR(s, REG_WORK1); // str r3, [r2] + LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif + STR_rR(s, REG_WORK1); } } LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) @@ -284,12 +339,17 @@ LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) { - if(i >= 0 && i<256) { + if(CHECK32(i)) { SUB_rri(d, d, i); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, i); + if(i >> 16) + MOVT_ri16(REG_WORK1, i >> 16); +#else uae_s32 offs = data_long_offs(i); LDR_rRI(REG_WORK1, RPC_INDEX, offs); - +#endif SUB_rrr(d, d, REG_WORK1); } } @@ -305,25 +365,17 @@ LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) SUBS_rri(REG_WORK2, REG_WORK2, (i & 0xff) << 16); PKHTB_rrrASRi(d, d, REG_WORK2, 16); - MRS_CPSR(REG_WORK1); // mrs r2, CPSR - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 - MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); } LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) -LOWFUNC(WRITE,NONE,2,raw_test_eq_w_rr,(RR2 d, RR2 s)) -{ - // Only EQ/NE relevant for caller -> compare without handle carry - LSL_rri(REG_WORK2, d, 16); - TST_rrLSLi(REG_WORK2, s, 16); -} -LENDFUNC(WRITE,NONE,2,raw_test_eq_w_rr,(RR2 d, RR2 s)) - static inline void raw_dec_sp(int off) { if (off) { - if(off >= 0 && off < 256) { + if(CHECK32(off)) { SUB_rri(RSP_INDEX, RSP_INDEX, off); } else { LDR_rRI(REG_WORK1, RPC_INDEX, 4); @@ -338,7 +390,7 @@ static inline void raw_dec_sp(int off) static inline void raw_inc_sp(int off) { if (off) { - if(off >= 0 && off < 256) { + if(CHECK32(off)) { ADD_rri(RSP_INDEX, RSP_INDEX, off); } else { LDR_rRI(REG_WORK1, RPC_INDEX, 4); @@ -381,13 +433,13 @@ static inline void raw_flags_init(void) { static inline void raw_flags_to_reg(int r) { MRS_CPSR(r); - STR_rRI(r, R_REGSTRUCT, 16 * 4); + STR_rRI(r, R_REGSTRUCT, 16 * 4); // Flags are next to 8 Dregs and 8 Aregs in struct regstruct raw_flags_evicted(r); } static inline void raw_reg_to_flags(int r) { - MSR_CPSR_r(r); + MSR_CPSRf_r(r); } static inline void raw_load_flagreg(uae_u32 t, uae_u32 r) @@ -410,11 +462,11 @@ static inline void raw_fflags_into_flags(int r) static inline void raw_fp_init(void) { #ifdef USE_JIT_FPU - int i; + int i; - for (i=0;i=1) { -// emit_byte(0xde); -// emit_byte(0xd9); - live.tos-=2; - } - while (live.tos>=0) { -// emit_byte(0xdd); -// emit_byte(0xd8); - live.tos--; - } - raw_fp_init(); + while (live.tos>=1) { + live.tos-=2; + } + while (live.tos>=0) { + live.tos--; + } + raw_fp_init(); #endif } @@ -504,31 +552,51 @@ LENDFUNC(WRITE,NONE,2,raw_SUB_l_rri,(RW4 d, RR4 s, IMM i)) LOWFUNC(WRITE,NONE,2,raw_LDR_l_ri,(RW4 d, IMM i)) { +#ifdef ARMV6T2 + MOVW_ri16(d, i); + if(i >> 16) + MOVT_ri16(d, i >> 16); +#else uae_s32 offs = data_long_offs(i); LDR_rRI(d, RPC_INDEX, offs); +#endif } LENDFUNC(WRITE,NONE,2,raw_LDR_l_ri,(RW4 d, IMM i)) // // compuemu_support used raw calls // +LOWFUNC(WRITE,NONE,2,compemu_raw_MERGE_rr,(RW4 d, RR4 s)) +{ + PKHBT_rrr(d, d, s); +} +LENDFUNC(WRITE,NONE,2,compemu_raw_MERGE_rr,(RW4 d, RR4 s)) + LOWFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) { - data_check_end(8, 24); - uae_s32 target = data_long(d, 24); - uae_s32 offs = get_data_offset(target); - - LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d - LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); + LDR_rR(REG_WORK2, REG_WORK1); + + MOVW_ri16(REG_WORK3, s); + if(s >> 16) + MOVT_ri16(REG_WORK3, s >> 16); + ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK3); + + STR_rR(REG_WORK2, REG_WORK1); +#else + uae_s32 offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); + LDR_rR(REG_WORK2, REG_WORK1); offs = data_long_offs(s); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; s + LDR_rRI(REG_WORK3, RPC_INDEX, offs); - ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK3); - offs = get_data_offset(target); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d - STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + STR_rR(REG_WORK2, REG_WORK1); +#endif } LENDFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) @@ -539,16 +607,26 @@ LOWFUNC(WRITE,NONE,2,compemu_raw_and_TAGMASK,(RW4 d)) } LENDFUNC(WRITE,NONE,2,compemu_raw_and_TAGMASK,(RW4 d)) -LOWFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) -{ - REV_rr(r,r); // rev %[r],%[r] -} -LENDFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) - LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) { clobber_flags(); + #ifdef ARMV6T2 + if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { + MOVW_ri16(REG_WORK2, s); + if(s >> 16) + MOVT_ri16(REG_WORK2, s >> 16); + uae_s32 idx = d - (uae_u32) & regs; + LDR_rRI(REG_WORK1, R_REGSTRUCT, idx); + } else { + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); + LDR_rR(REG_WORK1, REG_WORK1); + MOVW_ri16(REG_WORK2, s); + if(s >> 16) + MOVT_ri16(REG_WORK2, s >> 16); + } +#else if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { uae_s32 offs = data_long_offs(s); LDR_rRI(REG_WORK2, RPC_INDEX, offs); @@ -563,45 +641,43 @@ LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) offs = data_long_offs(s); LDR_rRI(REG_WORK2, RPC_INDEX, offs); } +#endif + CMP_rr(REG_WORK1, REG_WORK2); } LENDFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) LOWFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) { - if(offset >= 0 && offset < 256) { + if(CHECK32(offset)) { ADD_rri(d, s, offset); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, offset); + if(offset >> 16) + MOVT_ri16(REG_WORK1, offset >> 16); +#else uae_s32 offs = data_long_offs(offset); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif ADD_rrr(d, s, REG_WORK1); } } LENDFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) -LOWFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) -{ - int shft; - switch(factor) { - case 1: shft=0; break; - case 2: shft=1; break; - case 4: shft=2; break; - case 8: shft=3; break; - default: abort(); - } - - ADD_rrrLSLi(d, s, index, shft); -} -LENDFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) - LOWFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) { if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { uae_s32 idx = d - (uae_u32) & regs; STRB_rRI(s, R_REGSTRUCT, idx); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); +#else uae_s32 offs = data_long_offs(d); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif STRB_rR(s, REG_WORK1); } } @@ -609,6 +685,22 @@ LENDFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) { +#ifdef ARMV6T2 + if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { + MOVW_ri16(REG_WORK2, s); + if(s >> 16) + MOVT_ri16(REG_WORK2, s >> 16); + uae_s32 idx = d - (uae_u32) & regs; + STR_rRI(REG_WORK2, R_REGSTRUCT, idx); + } else { + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); + MOVW_ri16(REG_WORK2, s); + if(s >> 16) + MOVT_ri16(REG_WORK2, s >> 16); + STR_rR(REG_WORK2, REG_WORK1); + } +#else if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { uae_s32 offs = data_long_offs(s); LDR_rRI(REG_WORK2, RPC_INDEX, offs); @@ -622,6 +714,7 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) LDR_rRI(REG_WORK2, RPC_INDEX, offs); STR_rR(REG_WORK2, REG_WORK1); } +#endif } LENDFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) @@ -631,8 +724,13 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) uae_s32 idx = d - (uae_u32) & regs; STR_rRI(s, R_REGSTRUCT, idx); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); +#else uae_s32 offs = data_long_offs(d); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif STR_rR(s, REG_WORK1); } } @@ -640,8 +738,14 @@ LENDFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) { +#ifdef ARMV6T2 + MOVW_ri16(d, s); + if(s >> 16) + MOVT_ri16(d, s >> 16); +#else uae_s32 offs = data_long_offs(s); LDR_rRI(d, RPC_INDEX, offs); +#endif } LENDFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) @@ -651,8 +755,13 @@ LOWFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) uae_s32 idx = s - (uae_u32) & regs; LDR_rRI(d, R_REGSTRUCT, idx); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, s); + MOVT_ri16(REG_WORK1, s >> 16); +#else uae_s32 offs = data_long_offs(s); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif LDR_rR(d, REG_WORK1); } } @@ -670,8 +779,13 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) uae_s32 idx = d - (uae_u32) & regs; STRH_rRI(s, R_REGSTRUCT, idx); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); +#else uae_s32 offs = data_long_offs(d); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif STRH_rR(s, REG_WORK1); } } @@ -681,15 +795,20 @@ LOWFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) { clobber_flags(); - if(s >= 0 && s < 254) { + if(CHECK32(s)) { if(d >= (uae_u32) ®s && d < ((uae_u32) ®s) + sizeof(struct regstruct)) { uae_s32 idx = d - (uae_u32) & regs; LDR_rRI(REG_WORK2, R_REGSTRUCT, idx); SUBS_rri(REG_WORK2, REG_WORK2, s); STR_rRI(REG_WORK2, R_REGSTRUCT, idx); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); +#else uae_s32 offs = data_long_offs(d); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif LDR_rR(REG_WORK2, REG_WORK1); SUBS_rri(REG_WORK2, REG_WORK2, s); STR_rR(REG_WORK2, REG_WORK1); @@ -699,25 +818,36 @@ LOWFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) uae_s32 idx = d - (uae_u32) & regs; LDR_rRI(REG_WORK2, R_REGSTRUCT, idx); +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, s); + if(s >> 16) + MOVT_ri16(REG_WORK1, s >> 16); +#else uae_s32 offs = data_long_offs(s); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); - STR_rRI(REG_WORK2, R_REGSTRUCT, idx); } else { - data_check_end(8, 24); - uae_s32 target = data_long(d, 24); - uae_s32 offs = get_data_offset(target); +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, d); + MOVT_ri16(REG_WORK1, d >> 16); + LDR_rR(REG_WORK2, REG_WORK1); + + MOVW_ri16(REG_WORK3, s); + if(s >> 16) + MOVT_ri16(REG_WORK3, s >> 16); +#else + uae_s32 offs = data_long_offs(d); LDR_rRI(REG_WORK1, RPC_INDEX, offs); LDR_rR(REG_WORK2, REG_WORK1); offs = data_long_offs(s); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); + LDR_rRI(REG_WORK3, RPC_INDEX, offs); +#endif - SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); - - offs = get_data_offset(target); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK3); STR_rR(REG_WORK2, REG_WORK1); } } @@ -731,16 +861,15 @@ LOWFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) } LENDFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) -LOWFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) -{ - UXTH_rr(d, s); -} -LENDFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) - static inline void compemu_raw_call(uae_u32 t) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, t); + MOVT_ri16(REG_WORK1, t >> 16); +#else uae_s32 offs = data_long_offs(t); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif PUSH(RLR_INDEX); BLX_r(REG_WORK1); POP(RLR_INDEX); @@ -758,26 +887,23 @@ static inline void compemu_raw_jcc_l_oponly(int cc) switch (cc) { case 9: // LS BEQ_i(0); // beq - BCC_i(2); // bcc + BCC_i(1); // bcc //: - LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; - BX_r(REG_WORK1); // bx r2 + LDR_rRI(RPC_INDEX, RPC_INDEX, -4); // ldr pc, [pc] ; break; case 8: // HI - BEQ_i(3); // beq - BCS_i(2); // bcs + BEQ_i(2); // beq + BCS_i(1); // bcs //: - LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; - BX_r(REG_WORK1); // bx r2 + LDR_rRI(RPC_INDEX, RPC_INDEX, -4); // ldr pc, [pc] ; break; default: - CC_LDR_rRI(cc, REG_WORK1, RPC_INDEX, 4); // ldrlt r2, [pc, #4] ; - CC_BX_r(cc, REG_WORK1); // bxlt r2 - B_i(0); // b + CC_B_i(cc^1, 1); + LDR_rRI(RPC_INDEX, RPC_INDEX, -4); break; } // emit of target will be done by caller @@ -785,14 +911,19 @@ static inline void compemu_raw_jcc_l_oponly(int cc) static inline void compemu_raw_jl(uae_u32 t) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, t); + MOVT_ri16(REG_WORK1, t >> 16); + CC_BX_r(NATIVE_CC_LT, REG_WORK1); +#else uae_s32 offs = data_long_offs(t); CC_LDR_rRI(NATIVE_CC_LT, RPC_INDEX, RPC_INDEX, offs); +#endif } static inline void compemu_raw_jmp(uae_u32 t) { - LDR_rR(REG_WORK1, RPC_INDEX); - BX_r(REG_WORK1); + LDR_rRI(RPC_INDEX, RPC_INDEX, -4); emit_long(t); } @@ -819,21 +950,19 @@ static inline void compemu_raw_jmp_r(RR4 r) static inline void compemu_raw_jnz(uae_u32 t) { +#ifdef ARMV6T2 + BEQ_i(1); + LDR_rRI(RPC_INDEX, RPC_INDEX, -4); + emit_long(t); +#else uae_s32 offs = data_long_offs(t); - CC_LDR_rRI(NATIVE_CC_NE, RPC_INDEX, RPC_INDEX, offs); // ldrne pc, [pc, offs] + CC_LDR_rRI(NATIVE_CC_NE, RPC_INDEX, RPC_INDEX, offs); +#endif } static inline void compemu_raw_jz_b_oponly(void) { - BNE_i(2); // bne jp - LDRSB_rRI(REG_WORK1, RPC_INDEX, 3); // ldrsb r2,[pc,#3] - ADD_rrr(RPC_INDEX, RPC_INDEX, REG_WORK1); // add pc,pc,r2 - - emit_byte(0); - emit_byte(0); - emit_byte(0); - - // + BEQ_i(0); // Real distance set by caller } static inline void compemu_raw_branch(IMM d) @@ -846,8 +975,13 @@ static inline void compemu_raw_branch(IMM d) LOWFUNC(NONE,NONE,1,compemu_raw_init_r_regstruct,(IMM s)) { +#ifdef ARMV6T2 + MOVW_ri16(R_REGSTRUCT, s); + MOVT_ri16(R_REGSTRUCT, s >> 16); +#else uae_s32 offs = data_long_offs(s); LDR_rRI(R_REGSTRUCT, RPC_INDEX, offs); +#endif } LENDFUNC(NONE,NONE,1,compemu_raw_init_r_regstruct,(IMM s)) @@ -860,25 +994,31 @@ LOWFUNC(NONE,NONE,2,compemu_raw_endblock_pc_inreg,(RR4 rr_pc, IMM cycles)) // countdown -= scaled_cycles(totcycles); uae_s32 offs = (uae_u32)&countdown - (uae_u32)®s; LDR_rRI(REG_WORK1, R_REGSTRUCT, offs); - if(cycles >= 0 && cycles < 256) { + if(CHECK32(cycles)) { SUBS_rri(REG_WORK1, REG_WORK1, cycles); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, cycles); + if(cycles >> 16) + MOVT_ri16(REG_WORK2, cycles >> 16); +#else int offs2 = data_long_offs(cycles); LDR_rRI(REG_WORK2, RPC_INDEX, offs2); +#endif SUBS_rrr(REG_WORK1, REG_WORK1, REG_WORK2); } STR_rRI(REG_WORK1, R_REGSTRUCT, offs); - CC_B_i(NATIVE_CC_MI, 3); + + CC_B_i(NATIVE_CC_MI, 2); BFC_rii(rr_pc, 16, 31); // apply TAGMASK - offs = data_long_offs((uintptr)cache_tags); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); - LDR_rRR_LSLi(REG_WORK1, REG_WORK1, rr_pc, 2); - BX_r(REG_WORK1); + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // + LDR_rRR_LSLi(RPC_INDEX, REG_WORK1, rr_pc, 2); - offs = data_long_offs((uintptr)popall_do_nothing); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); - BX_r(REG_WORK1); + LDR_rRI(RPC_INDEX, RPC_INDEX, 0); // + + emit_long((uintptr)cache_tags); + emit_long((uintptr)popall_do_nothing); } LENDFUNC(NONE,NONE,2,compemu_raw_endblock_pc_inreg,(RR4 rr_pc, IMM cycles)) @@ -890,26 +1030,30 @@ LOWFUNC(NONE,NONE,2,compemu_raw_endblock_pc_isconst,(IMM cycles, IMM v)) // countdown -= scaled_cycles(totcycles); uae_s32 offs = (uae_u32)&countdown - (uae_u32)®s; LDR_rRI(REG_WORK1, R_REGSTRUCT, offs); - if(cycles >= 0 && cycles < 256) { + if(CHECK32(cycles)) { SUBS_rri(REG_WORK1, REG_WORK1, cycles); } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, cycles); + if(cycles >> 16) + MOVT_ri16(REG_WORK2, cycles >> 16); +#else int offs2 = data_long_offs(cycles); LDR_rRI(REG_WORK2, RPC_INDEX, offs2); +#endif SUBS_rrr(REG_WORK1, REG_WORK1, REG_WORK2); } STR_rRI(REG_WORK1, R_REGSTRUCT, offs); - CC_B_i(NATIVE_CC_MI, 1); - LDR_rRI(REG_WORK1, RPC_INDEX, 16); // get target - BX_r(REG_WORK1); + CC_LDR_rRI(NATIVE_CC_MI^1, RPC_INDEX, RPC_INDEX, 16); // - offs = data_long_offs(v); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // offs = (uae_u32)®s.pc_p - (uae_u32)®s; STR_rRI(REG_WORK1, R_REGSTRUCT, offs); - offs = data_long_offs((uintptr)popall_do_nothing); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); - BX_r(REG_WORK1); + LDR_rRI(RPC_INDEX, RPC_INDEX, 0); // + + emit_long(v); + emit_long((uintptr)popall_do_nothing); // } diff --git a/src/jit/codegen_arm.h b/src/jit/codegen_arm.h index 491a9514..85d4a7a7 100644 --- a/src/jit/codegen_arm.h +++ b/src/jit/codegen_arm.h @@ -85,6 +85,23 @@ 0\ ) +#define CHECK32(c) ((c & 0xffffff00) == 0 || \ + (c & 0x3fffffc0) == 0 || \ + (c & 0x0ffffff0) == 0 || \ + (c & 0x03fffffc) == 0 || \ + (c & 0x00ffffff) == 0 || \ + (c & 0xc03fffff) == 0 || \ + (c & 0xf00fffff) == 0 || \ + (c & 0xfc03ffff) == 0 || \ + (c & 0xff00ffff) == 0 || \ + (c & 0xffc03fff) == 0 || \ + (c & 0xfff00fff) == 0 || \ + (c & 0xfffc03ff) == 0 || \ + (c & 0xffff00ff) == 0 || \ + (c & 0xffffc03f) == 0 || \ + (c & 0xfffff00f) == 0 || \ + (c & 0xfffffc03) == 0) + #define SHIFT_IMM(c) (0x02000000 | (IMM32((c)))) #define UNSHIFTED_IMM8(c) (0x02000000 | (c)) @@ -613,7 +630,7 @@ enum { #define RSBS_rrrRORr(Rd,Rn,Rm,Rs) CC_RSBS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) #define RSBS_rrrRRX(Rd,Rn,Rm) CC_RSBS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) -#define CC_ADD_rri8(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,UNSHIFT_IMM8(i)) +#define CC_ADD_rri8(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,UNSHIFTED_IMM8(i)) #define CC_ADD_rri8RORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_IMM8_ROR(Rm,i)) #define CC_ADD_rri(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_IMM(i)) @@ -918,8 +935,8 @@ enum { #define BICS_rrrRRX(Rd,Rn,Rm) CC_BICS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) /* Branch instructions */ -#define CC_B_i(cc,i) _W(((cc) << 28) | (10 << 24) | (i)) -#define CC_BL_i(cc,i) _W(((cc) << 28) | (11 << 24) | (i)) +#define CC_B_i(cc,i) _W(((cc) << 28) | (10 << 24) | (i & 0x00ffffff)) +#define CC_BL_i(cc,i) _W(((cc) << 28) | (11 << 24) | (i & 0x00ffffff)) #define CC_BLX_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (3 << 4) | (0xfff << 8) | (r)) #define CC_BX_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (1 << 4) | (0xfff << 8) | (r)) #define CC_BXJ_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (2 << 4) | (0xfff << 8) | (r)) @@ -952,11 +969,11 @@ enum { #define CC_MRS_SPSR(cc,Rd) _W(((cc) << 28) | (0x14 << 20) | ((Rd) << 12) | (0xf << 16)) #define MRS_SPSR(Rd) CC_MRS_SPSR(NATIVE_CC_AL,Rd) -#define CC_MSR_CPSR_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x9 << 16) | (0xf << 12) | SHIFT_IMM(i)) -#define CC_MSR_CPSR_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x9 << 16) | (0xf << 12) | (Rm)) - -#define MSR_CPSR_i(i) CC_MSR_CPSR_i(NATIVE_CC_AL,(i)) -#define MSR_CPSR_r(Rm) CC_MSR_CPSR_r(NATIVE_CC_AL,(Rm)) +// Never use these, they are for system level and slower... +//#define CC_MSR_CPSR_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x9 << 16) | (0xf << 12) | SHIFT_IMM(i)) +//#define CC_MSR_CPSR_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x9 << 16) | (0xf << 12) | (Rm)) +//#define MSR_CPSR_i(i) CC_MSR_CPSR_i(NATIVE_CC_AL,(i)) +//#define MSR_CPSR_r(Rm) CC_MSR_CPSR_r(NATIVE_CC_AL,(Rm)) #define CC_MSR_CPSRf_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x8 << 16) | (0xf << 12) | SHIFT_IMM(i)) #define CC_MSR_CPSRf_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x8 << 16) | (0xf << 12) | (Rm)) @@ -964,11 +981,11 @@ enum { #define MSR_CPSRf_i(i) CC_MSR_CPSRf_i(NATIVE_CC_AL,(i)) #define MSR_CPSRf_r(Rm) CC_MSR_CPSRf_r(NATIVE_CC_AL,(Rm)) -#define CC_MSR_CPSRc_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x1 << 16) | (0xf << 12) | SHIFT_IMM(i)) -#define CC_MSR_CPSRc_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x1 << 16) | (0xf << 12) | (Rm)) - -#define MSR_CPSRc_i(i) CC_MSR_CPSRc_i(NATIVE_CC_AL,(i)) -#define MSR_CPSRc_r(Rm) CC_MSR_CPSRc_r(NATIVE_CC_AL,(Rm)) +// Never use these, they are for system level and slower... +//#define CC_MSR_CPSRc_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x1 << 16) | (0xf << 12) | SHIFT_IMM(i)) +//#define CC_MSR_CPSRc_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x1 << 16) | (0xf << 12) | (Rm)) +//#define MSR_CPSRc_i(i) CC_MSR_CPSRc_i(NATIVE_CC_AL,(i)) +//#define MSR_CPSRc_r(Rm) CC_MSR_CPSRc_r(NATIVE_CC_AL,(Rm)) /* Load Store instructions */ @@ -1303,6 +1320,18 @@ enum { #define CC_UBFX_rrii(cc,Rd,Rn,lsb,width) _W(((cc) << 28) | (0x3f << 21) | ((width-1) << 16) | (Rd << 12) | ((lsb) << 7) | (0x5 << 4) | (Rn)) #define UBFX_rrii(Rd,Rn,lsb,width) CC_UBFX_rrii(NATIVE_CC_AL,Rd,Rn,lsb,width) +#define CC_SXTAB_rrr(cc,Rd,Rn,Rm) _W(((cc) << 28) | (0x6a << 20) | (Rn << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTAB_rrr(Rd,Rn,Rm) CC_SXTAB_rrr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SXTAH_rrr(cc,Rd,Rn,Rm) _W(((cc) << 28) | (0x6b << 20) | (Rn << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTAH_rrr(Rd,Rn,Rm) CC_SXTAH_rrr(NATIVE_CC_AL,Rd,Rn,Rm) + +// ARMv6T2 +#define CC_MOVW_ri16(cc,Rd,i) _W(((cc) << 28) | (0x30 << 20) | (((i >> 12) & 0xf) << 16) | (Rd << 12) | (i & 0x0fff)) +#define MOVW_ri16(Rd,i) CC_MOVW_ri16(NATIVE_CC_AL,Rd,i) + +#define CC_MOVT_ri16(cc,Rd,i) _W(((cc) << 28) | (0x34 << 20) | (((i >> 12) & 0xf) << 16) | (Rd << 12) | (i & 0x0fff)) +#define MOVT_ri16(Rd,i) CC_MOVT_ri16(NATIVE_CC_AL,Rd,i) // Floatingpoint diff --git a/src/jit/compemu_midfunc_arm.cpp b/src/jit/compemu_midfunc_arm.cpp index 1a0dc7cb..ec13f6d2 100644 --- a/src/jit/compemu_midfunc_arm.cpp +++ b/src/jit/compemu_midfunc_arm.cpp @@ -88,7 +88,7 @@ MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) return; } - r=rmw(r, 4, 4); + r = rmw(r, 4, 4); raw_shll_l_ri(r, i); unlock2(r); } @@ -109,8 +109,7 @@ MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) s = readreg(s, 2); d = writereg(d, 4); } - else { /* If we try to lock this twice, with different sizes, we - are int trouble! */ + else { /* If we try to lock this twice, with different sizes, we are int trouble! */ s = d = rmw(s, 4, 2); } SIGNED16_REG_2_REG(d, s); @@ -166,7 +165,7 @@ MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) } s = readreg(s, 4); - d = writereg(d ,4); + d = writereg(d, 4); raw_lea_l_brr(d, s, offset); unlock2(d); unlock2(s); @@ -179,10 +178,10 @@ MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) COMPCALL(lea_l_rr_indexed)(d, s, index, factor); return; } + s = readreg(s, 4); index = readreg(index, 4); d = writereg(d, 4); - raw_lea_l_brr_indexed(d, s, index, factor, offset); unlock2(d); unlock2(index); @@ -192,10 +191,9 @@ MENDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) { - s=readreg(s, 4); - index=readreg(index, 4); - d=writereg(d, 4); - + s = readreg(s, 4); + index = readreg(index, 4); + d = writereg(d, 4); raw_lea_l_rr_indexed(d, s, index, factor); unlock2(d); unlock2(index); @@ -237,8 +235,8 @@ MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) COMPCALL(mov_l_mi)(d, live.state[s].val); return; } + s = readreg(s, 4); - raw_mov_l_mr(d, s); unlock2(s); } @@ -254,7 +252,6 @@ MENDFUNC(2,mov_l_ri,(W4 d, IMM s)) MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) { d = writereg(d, 2); - raw_mov_w_ri(d, s); unlock2(d); } @@ -263,27 +260,11 @@ MENDFUNC(2,mov_w_ri,(W2 d, IMM s)) MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) { d = writereg(d, 1); - raw_mov_b_ri(d, s); unlock2(d); } MENDFUNC(2,mov_b_ri,(W1 d, IMM s)) -MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) -{ - // Only EQ/NE relevant for caller -> much simpler compare in raw... - - clobber_flags(); - - d = readreg(d, 2); - s = readreg(s, 2); - - raw_test_eq_w_rr(d, s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,test_w_rr,(RR2 d, RR2 s)) - MIDFUNC(2,add_l,(RW4 d, RR4 s)) { if (isconst(s)) { @@ -291,11 +272,9 @@ MIDFUNC(2,add_l,(RW4 d, RR4 s)) return; } - s=readreg(s, 4); - d=rmw(d, 4, 4); - + s = readreg(s, 4); + d = rmw(d, 4, 4); raw_add_l(d, s); - unlock2(d); unlock2(s); } @@ -311,7 +290,6 @@ MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) } d = rmw(d, 4, 4); - raw_sub_l_ri(d, i); unlock2(d); } @@ -323,7 +301,6 @@ MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) clobber_flags(); d = rmw(d, 2, 2); - raw_sub_w_ri(d, i); unlock2(d); } @@ -338,7 +315,7 @@ MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) return; } - d=rmw(d, 4, 4); + d = rmw(d, 4, 4); raw_add_l_ri(d, i); unlock2(d); } @@ -424,11 +401,9 @@ MIDFUNC(2,arm_ADD_l,(RW4 d, RR4 s)) return; } - s=readreg(s, 4); - d=rmw(d, 4, 4); - + s = readreg(s, 4); + d = rmw(d, 4, 4); raw_ADD_l_rr(d, s); - unlock2(d); unlock2(s); } @@ -445,7 +420,7 @@ MIDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) d = rmw(d, 4, 4); - if(i >= 0 && i < 256) { + if(CHECK32(i)) { raw_ADD_l_rri(d, d, i); } else { raw_LDR_l_ri(REG_WORK1, i); @@ -465,8 +440,7 @@ MIDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) return; } - d=rmw(d, 4, 4); - + d = rmw(d, 4, 4); raw_ADD_l_rri(d, d, i); unlock2(d); } @@ -481,18 +455,16 @@ MIDFUNC(2,arm_SUB_l_ri8,(RW4 d, IMM i)) return; } - d=rmw(d, 4, 4); - + d = rmw(d, 4, 4); raw_SUB_l_rri(d, d, i); unlock2(d); } -MENDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) +MENDFUNC(2,arm_SUB_l_ri8,(RW4 d, IMM i)) // Other static inline void flush_cpu_icache(void *start, void *stop) { - register void *_beg __asm ("a1") = start; register void *_end __asm ("a2") = stop; register void *_flg __asm ("a3") = 0; diff --git a/src/jit/compemu_midfunc_arm.h b/src/jit/compemu_midfunc_arm.h index bd21cda0..78eacc57 100644 --- a/src/jit/compemu_midfunc_arm.h +++ b/src/jit/compemu_midfunc_arm.h @@ -54,7 +54,6 @@ DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s)); DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s)); DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s)); DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s)); -DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s)); DECLARE_MIDFUNC(add_l(RW4 d, RR4 s)); DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i)); DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i)); diff --git a/src/jit/compemu_midfunc_arm2.cpp b/src/jit/compemu_midfunc_arm2.cpp index 8a40f17a..3ebe1c1c 100644 --- a/src/jit/compemu_midfunc_arm2.cpp +++ b/src/jit/compemu_midfunc_arm2.cpp @@ -52,11 +52,18 @@ const uae_u32 ARM_CCR_MAP[] = { 0, ARM_C_FLAG, // 1 C #define DUPLICACTE_CARRY \ if (needed_flags & FLAG_X) { \ int x = writereg(FLAGX, 4); \ - MOV_ri(x, 1); \ - CC_MOV_ri(NATIVE_CC_CC, x, 0); \ + MOV_ri(x, 0); \ + ADC_rri(x, x, 0); \ unlock2(x); \ } +#define DUPLICACTE_CARRY_FROM_REG(r) \ + if (needed_flags & FLAG_X) { \ + int x = writereg(FLAGX, 4); \ + UBFX_rrii(x, r, 29, 1); \ + unlock2(x); \ + } + /* * ADD * Operand Syntax: , Dn @@ -81,7 +88,7 @@ MIDFUNC(3,jnf_ADD_imm,(W4 d, RR4 s, IMM v)) s = readreg(s, 4); d = writereg(d, 4); - if(v >= 0 && v < 256) { + if(CHECK32(v)) { ADD_rri(d, s, v); } else { compemu_raw_mov_l_ri(REG_WORK1, v); @@ -173,8 +180,13 @@ MIDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) s = readreg(s, 4); d = writereg(d, 4); +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, v); + LSL_rri(REG_WORK1, REG_WORK1, 16); +#else uae_s32 offs = data_long_offs(v << 16); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif ADDS_rrrLSLi(d, REG_WORK1, s, 16); ASR_rri(d, d, 16); @@ -212,7 +224,7 @@ MIDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) s = readreg(s, 4); d = writereg(d, 4); - if(v >= 0 && v < 256) { + if(CHECK32(v)) { ADDS_rri(d, s, v); } else { compemu_raw_mov_l_ri(REG_WORK2, v); @@ -261,8 +273,7 @@ MIDFUNC(2,jnf_ADDA_b,(W4 d, RR1 s)) s = readreg(s, 4); d = rmw(d, 4, 4); - SIGNED8_REG_2_REG(REG_WORK1, s); - ADD_rrr(d, d, REG_WORK1); + SXTAB_rrr(d, d, s); unlock2(d); unlock2(s); @@ -274,8 +285,7 @@ MIDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) s = readreg(s, 4); d = rmw(d, 4, 4); - SIGNED16_REG_2_REG(REG_WORK1, s); - ADD_rrr(d, d, REG_WORK1); + SXTAH_rrr(d, d, s); unlock2(d); unlock2(s); @@ -319,10 +329,9 @@ MIDFUNC(3,jnf_ADDX,(W4 d, RR4 s, RR4 v)) clobber_flags(); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); ADC_rrr(d, s, v); @@ -340,14 +349,13 @@ MIDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); - - CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); + MVN_ri(REG_WORK1, 0); BFI_rrii(REG_WORK1, s, 24, 31); ADCS_rrrLSLi(d, REG_WORK1, v, 24); @@ -356,7 +364,7 @@ MIDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) MRS_CPSR(REG_WORK1); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -372,14 +380,13 @@ MIDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); - - CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); + MVN_ri(REG_WORK1, 0); BFI_rrii(REG_WORK1, s, 16, 31); ADCS_rrrLSLi(d, REG_WORK1, v, 16); @@ -388,7 +395,7 @@ MIDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) MRS_CPSR(REG_WORK1); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -404,20 +411,19 @@ MIDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); - - CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); + ADCS_rrr(d, s, v); MRS_CPSR(REG_WORK1); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -772,10 +778,11 @@ MIDFUNC(2,jff_ASLW,(W4 d, RR4 s)) MSR_CPSRf_i(0); LSLS_rri(d, s, 17); - DUPLICACTE_CARRY + + MRS_CPSR(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) // Calculate V flag - MRS_CPSR(REG_WORK1); CC_ORR_rri(NATIVE_CC_MI, REG_WORK1, REG_WORK1, ARM_V_FLAG); CC_EOR_rri(NATIVE_CC_CS, REG_WORK1, REG_WORK1, ARM_V_FLAG); MSR_CPSRf_r(REG_WORK1); @@ -1136,12 +1143,11 @@ MIDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) uae_u32 v = (1 << s); MRS_CPSR(REG_WORK1); - TST_ri(d, v); - BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); - CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); EOR_rri(d, d, v); - + UBFX_rrii(REG_WORK2, d, s, 1); + BFI_rrii(REG_WORK1, REG_WORK2, 30, 30); + MSR_CPSRf_r(REG_WORK1); + unlock2(d); } MENDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) @@ -1152,11 +1158,10 @@ MIDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) uae_u32 v = (1 << s); MRS_CPSR(REG_WORK1); - TST_ri(d, v); - BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); - CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); EOR_rri(d, d, v); + UBFX_rrii(REG_WORK2, d, s, 1); + BFI_rrii(REG_WORK1, REG_WORK2, 30, 30); + MSR_CPSRf_r(REG_WORK1); unlock2(d); } @@ -1179,9 +1184,9 @@ MIDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); EOR_rrr(d, d, REG_WORK2); - + unlock2(d); unlock2(s); } @@ -1205,7 +1210,7 @@ MIDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); EOR_rrr(d, d, REG_WORK2); unlock2(d); @@ -1291,7 +1296,7 @@ MIDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) TST_ri(d, v); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); BIC_rri(d, d, v); unlock2(d); @@ -1307,7 +1312,7 @@ MIDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) TST_ri(d, v); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); BIC_rri(d, d, v); unlock2(d); @@ -1331,7 +1336,7 @@ MIDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) TST_rr(d,REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); BIC_rrr(d, d, REG_WORK2); unlock2(d); @@ -1357,7 +1362,7 @@ MIDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); BIC_rrr(d, d ,REG_WORK2); unlock2(d); @@ -1443,7 +1448,7 @@ MIDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) TST_ri(d, v); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); ORR_rri(d, d, v); unlock2(d); @@ -1459,7 +1464,7 @@ MIDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) TST_ri(d, v); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); ORR_rri(d, d, v); unlock2(d); @@ -1483,7 +1488,7 @@ MIDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); ORR_rrr(d, d, REG_WORK2); unlock2(d); @@ -1509,7 +1514,7 @@ MIDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); ORR_rrr(d, d, REG_WORK2); unlock2(d); @@ -1539,7 +1544,7 @@ MIDFUNC(2,jff_BTST_b_imm,(RR4 d, IMM s)) TST_ri(d, (1 << s)); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(d); } @@ -1553,7 +1558,7 @@ MIDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) TST_ri(d, (1 << s)); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(d); } @@ -1576,7 +1581,7 @@ MIDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(d); unlock2(s); @@ -1601,7 +1606,7 @@ MIDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) TST_rr(d, REG_WORK2); BIC_rri(REG_WORK1, REG_WORK1, ARM_Z_FLAG); CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(d); unlock2(s); @@ -1633,7 +1638,7 @@ MIDFUNC(1,jff_CLR,(W4 d)) { d = writereg(d, 4); MOV_ri(d, 0); - MSR_CPSR_i(ARM_Z_FLAG); + MSR_CPSRf_i(ARM_Z_FLAG); unlock2(d); } MENDFUNC(1,jff_CLR,(W4 d)) @@ -1661,7 +1666,7 @@ MIDFUNC(2,jff_CMP_b,(RR1 d, RR1 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(s); unlock2(d); @@ -1678,7 +1683,7 @@ MIDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(s); unlock2(d); @@ -1694,7 +1699,7 @@ MIDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(s); unlock2(d); @@ -1724,7 +1729,7 @@ MIDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(s); unlock2(d); @@ -1740,7 +1745,7 @@ MIDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(s); unlock2(d); @@ -2623,9 +2628,12 @@ MIDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) { d = writereg(d, 4); - SIGNED8_IMM_2_REG(d, (uae_u8)s); MSR_CPSRf_i(0); - TST_rr(d, d); + if (s & 0x80) { + MVNS_ri(d, (uae_u8) ~s); + } else { + MOVS_ri(d, (uae_u8) s); + } unlock2(d); } @@ -2723,8 +2731,7 @@ MIDFUNC(3,jnf_MVMEL_w,(W4 d, RR4 s, IMM offset)) d = writereg(d, 4); LDRH_rRI(REG_WORK1, s, offset); - REV16_rr(REG_WORK1, REG_WORK1); - SIGNED16_REG_2_REG(d, REG_WORK1); + REVSH_rr(d, REG_WORK1); unlock2(d); unlock2(s); @@ -2798,8 +2805,13 @@ MIDFUNC(2,jnf_MOVE16,(RR4 d, RR4 s)) BIC_rri(s, s, 0x0000000F); BIC_rri(d, d, 0x0000000F); +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK1, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif ADD_rrr(s, s, REG_WORK1); ADD_rrr(d, d, REG_WORK1); @@ -3124,8 +3136,8 @@ MIDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -3142,8 +3154,8 @@ MIDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -3159,8 +3171,8 @@ MIDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -3189,11 +3201,10 @@ MIDFUNC(2,jnf_NEGX_b,(W4 d, RR4 s)) d = writereg(d, 4); clobber_flags(); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); SIGNED8_REG_2_REG(REG_WORK1, s); RSC_rri(d, REG_WORK1, 0); @@ -3212,11 +3223,10 @@ MIDFUNC(2,jnf_NEGX_w,(W4 d, RR4 s)) clobber_flags(); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); SIGNED16_REG_2_REG(REG_WORK1, s); RSC_rri(d, REG_WORK1, 0); @@ -3235,11 +3245,10 @@ MIDFUNC(2,jnf_NEGX_l,(W4 d, RR4 s)) clobber_flags(); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); RSC_rri(d, s, 0); @@ -3255,15 +3264,14 @@ MIDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + SIGNED8_REG_2_REG(REG_WORK1, s); RSCS_rri(d, REG_WORK1, 0); @@ -3271,7 +3279,7 @@ MIDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -3285,15 +3293,14 @@ MIDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + SIGNED16_REG_2_REG(REG_WORK1, s); RSCS_rri(d, REG_WORK1, 0); @@ -3301,7 +3308,7 @@ MIDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -3315,22 +3322,21 @@ MIDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + RSCS_rri(d, s, 0); MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -3553,8 +3559,7 @@ MIDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) d = writereg(d, 4); if(i & 0x1f) { - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); ROR_rri(d, d, (32 - (i & 0x1f))); } else { MOV_rr(d, s); @@ -3597,10 +3602,8 @@ MIDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) TST_rr(d, d); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); } else { TST_rr(d, d); } @@ -3615,8 +3618,7 @@ MIDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) s = readreg(s, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); MSR_CPSRf_i(0); if (i) { if(i & 0x1f) @@ -3625,10 +3627,8 @@ MIDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) TST_rr(d, d); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); } else { TST_rr(d, d); } @@ -3651,10 +3651,8 @@ MIDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) MOVS_rr(d, s); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); } else { MOVS_rr(d, s); } @@ -3701,8 +3699,7 @@ MIDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) AND_rri(REG_WORK1, i, 0x1f); RSB_rri(REG_WORK1, REG_WORK1, 32); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); ROR_rrr(d, d, REG_WORK1); unlock2(d); @@ -3753,10 +3750,8 @@ MIDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) RORS_rrr(d, d, REG_WORK1); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - ORR_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); unlock2(d); unlock2(s); @@ -3778,16 +3773,13 @@ MIDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) AND_rri(REG_WORK1, i, 0x1f); RSB_rri(REG_WORK1, REG_WORK1, 32); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); MSR_CPSRf_i(0); RORS_rrr(d, d, REG_WORK1); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - ORR_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); unlock2(d); unlock2(s); @@ -3813,10 +3805,8 @@ MIDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) RORS_rrr(d, s, REG_WORK1); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - ORR_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); unlock2(d); unlock2(s); @@ -3842,8 +3832,7 @@ MIDFUNC(2,jnf_ROLW,(W4 d, RR4 s)) s = readreg(s, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); ROR_rri(d, d, (32 - 1)); unlock2(d); @@ -3856,16 +3845,13 @@ MIDFUNC(2,jff_ROLW,(W4 d, RR4 s)) s = readreg(s, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); MSR_CPSRf_i(0); RORS_rri(d, d, (32 - 1)); MRS_CPSR(REG_WORK2); - TST_ri(d, 1); - ORR_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG); - CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK2); + BFI_rrii(REG_WORK2, d, 29, 29); // Handle C flag + MSR_CPSRf_r(REG_WORK2); unlock2(d); unlock2(s); @@ -3967,10 +3953,9 @@ MIDFUNC(2,jnf_ROXLW,(W4 d, RR4 s)) clobber_flags(); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); LSL_rri(d, s, 1); ADC_rri(d, d, 0); @@ -3987,10 +3972,9 @@ MIDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); LSL_rri(d, s, 1); ADC_rri(d, d, 0); @@ -4048,8 +4032,7 @@ MIDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) d = writereg(d, 4); if(i & 0x0f) { - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); ROR_rri(d, d, i & 0x0f); } else { MOV_ri(d, s); @@ -4086,10 +4069,9 @@ MIDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) } else if (i > 0x07) { TST_rr(d, d); // We need to copy MSB to carry - MRS_CPSR(REG_WORK1); - BIC_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MRS_CPSR(REG_WORK1); // carry is cleared CC_ORR_rri(NATIVE_CC_MI, REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); } else { TST_rr(d, d); } @@ -4104,18 +4086,16 @@ MIDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) s = readreg(s, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); MSR_CPSRf_i(0); if(i & 0x0f) { RORS_rri(d, d, i & 0x0f); } else if (i > 0x0f) { TST_rr(d, d); // We need to copy MSB to carry - MRS_CPSR(REG_WORK1); - BIC_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MRS_CPSR(REG_WORK1); // carry is cleared CC_ORR_rri(NATIVE_CC_MI, REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); } else { TST_rr(d, d); } @@ -4136,10 +4116,9 @@ MIDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) } else if (i > 0x1f) { MOVS_ri(d, s); // We need to copy MSB to carry - MRS_CPSR(REG_WORK1); - BIC_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MRS_CPSR(REG_WORK1); // carry is cleared CC_ORR_rri(NATIVE_CC_MI, REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); } else { MOVS_ri(d, s); } @@ -4180,8 +4159,7 @@ MIDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) i = readreg(i, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); ROR_rrr(d, d, i); unlock2(d); @@ -4243,8 +4221,7 @@ MIDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) i = readreg(i, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); MSR_CPSRf_i(0); AND_rri(REG_WORK1, i, 63); RORS_rrr(d, d, REG_WORK1); @@ -4294,8 +4271,7 @@ MIDFUNC(2,jnf_RORW,(W4 d, RR4 s)) s = readreg(s, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); ROR_rri(d, d, 1); unlock2(d); @@ -4308,8 +4284,7 @@ MIDFUNC(2,jff_RORW,(W4 d, RR4 s)) s = readreg(s, 4); d = writereg(d, 4); - LSL_rri(d, s, 16); - ORR_rrrLSRi(d, d, d, 16); + PKHBT_rrrLSLi(d, s, s, 16); MSR_CPSRf_i(0); RORS_rri(d, d, 1); @@ -4413,10 +4388,9 @@ MIDFUNC(2,jnf_ROXRW,(W4 d, RR4 s)) clobber_flags(); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); + // Restore X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); LSL_rri(d, s, 16); RRX_rr(d, d); @@ -4434,18 +4408,14 @@ MIDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - MSR_CPSR_r(REG_WORK1); + // Restore X to carry (clears also V flag, don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + MSR_CPSRf_r(REG_WORK1); LSL_rri(d, s, 16); ORR_rrrLSRi(d, d, d, 16); RRXS_rr(d, d); LSR_rri(d, d, 16); - MRS_CPSR(REG_WORK1); - BIC_rri(REG_WORK1, REG_WORK1, ARM_V_FLAG); - MSR_CPSR_r(REG_WORK1); // Duplicate carry MOV_ri(x, 1); @@ -4624,8 +4594,8 @@ MIDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -4649,8 +4619,8 @@ MIDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -4663,16 +4633,24 @@ MIDFUNC(3,jff_SUB_w_imm,(W4 d, RR2 s, IMM v)) s = readreg(s, 4); d = writereg(d, 4); - uae_s32 offs = data_word_offs(v); - LDR_rRI(REG_WORK1, RPC_INDEX, offs); + if(CHECK32(v)) { + MOV_ri(REG_WORK1, v); + } else { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK1, v); +#else + uae_s32 offs = data_word_offs(v); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); +#endif + } LSL_rri(REG_WORK2, s, 16); SUBS_rrrLSLi(d, REG_WORK2, REG_WORK1, 16); ASR_rri(d, d, 16); MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -4696,8 +4674,8 @@ MIDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -4715,8 +4693,8 @@ MIDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -4738,8 +4716,8 @@ MIDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - DUPLICACTE_CARRY + MSR_CPSRf_r(REG_WORK1); + DUPLICACTE_CARRY_FROM_REG(REG_WORK1) unlock2(d); unlock2(s); @@ -4807,11 +4785,10 @@ MIDFUNC(3,jnf_SUBX,(W4 d, RR4 s, RR4 v)) clobber_flags(); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); SBC_rrr(d, s, v); @@ -4829,15 +4806,14 @@ MIDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + LSL_rri(REG_WORK1, s, 24); SBCS_rrrLSLi(d, REG_WORK1, v, 24); ASR_rri(d, d, 24); @@ -4846,7 +4822,7 @@ MIDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -4862,15 +4838,14 @@ MIDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + LSL_rri(REG_WORK1, s, 16); SBCS_rrrLSLi(d,REG_WORK1,v, 16); ASR_rri(d, d, 16); @@ -4879,7 +4854,7 @@ MIDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -4895,22 +4870,21 @@ MIDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) d = writereg(d, 4); int x = rmw(FLAGX, 4, 4); - // Restore inverted X to carry - MRS_CPSR(REG_WORK1); - BFI_rrii(REG_WORK1, x, 29, 29); - EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); - MSR_CPSR_r(REG_WORK1); - MVN_ri(REG_WORK2, 0); CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + // Restore inverted X to carry (don't care about other flags) + LSL_rri(REG_WORK1, x, 29); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + SBCS_rrr(d, s, v); MRS_CPSR(REG_WORK1); EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); UBFX_rrii(x, REG_WORK1, 29, 1); // Duplicate carry - MSR_CPSR_r(REG_WORK1); + MSR_CPSRf_r(REG_WORK1); unlock2(x); unlock2(d); @@ -5019,8 +4993,13 @@ MENDFUNC(1,jff_TST_l,(RR4 s)) */ MIDFUNC(2,jnf_MEM_WRITE_OFF_b,(RR4 adr, RR4 b)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); b = readreg(b, 4); @@ -5034,8 +5013,13 @@ MENDFUNC(2,jnf_MEM_WRITE_OFF_b,(RR4 adr, RR4 b)) MIDFUNC(2,jnf_MEM_WRITE_OFF_w,(RR4 adr, RR4 w)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); w = readreg(w, 4); @@ -5050,8 +5034,13 @@ MENDFUNC(2,jnf_MEM_WRITE_OFF_w,(RR4 adr, RR4 w)) MIDFUNC(2,jnf_MEM_WRITE_OFF_l,(RR4 adr, RR4 l)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); l = readreg(l, 4); @@ -5067,8 +5056,13 @@ MENDFUNC(2,jnf_MEM_WRITE_OFF_l,(RR4 adr, RR4 l)) MIDFUNC(2,jnf_MEM_READ_OFF_b,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5082,8 +5076,13 @@ MENDFUNC(2,jnf_MEM_READ_OFF_b,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_READ_OFF_w,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5098,8 +5097,13 @@ MENDFUNC(2,jnf_MEM_READ_OFF_w,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_READ_OFF_l,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5115,8 +5119,13 @@ MENDFUNC(2,jnf_MEM_READ_OFF_l,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_WRITE24_OFF_b,(RR4 adr, RR4 b)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); b = readreg(b, 4); @@ -5131,16 +5140,20 @@ MENDFUNC(2,jnf_MEM_WRITE24_OFF_b,(RR4 adr, RR4 b)) MIDFUNC(2,jnf_MEM_WRITE24_OFF_w,(RR4 adr, RR4 w)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); w = readreg(w, 4); BIC_rri(REG_WORK1, adr, 0xff000000); - ADD_rrr(REG_WORK2, REG_WORK1, REG_WORK2); - REV16_rr(REG_WORK1, w); - STRH_rR(REG_WORK1, REG_WORK2); + REV16_rr(REG_WORK3, w); + STRH_rRR(REG_WORK3, REG_WORK1, REG_WORK2); unlock2(w); unlock2(adr); @@ -5149,16 +5162,20 @@ MENDFUNC(2,jnf_MEM_WRITE24_OFF_w,(RR4 adr, RR4 w)) MIDFUNC(2,jnf_MEM_WRITE24_OFF_l,(RR4 adr, RR4 l)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); l = readreg(l, 4); BIC_rri(REG_WORK1, adr, 0xff000000); - ADD_rrr(REG_WORK2, REG_WORK1, REG_WORK2); - REV_rr(REG_WORK1, l); - STR_rR(REG_WORK1, REG_WORK2); + REV_rr(REG_WORK3, l); + STR_rRR(REG_WORK3, REG_WORK1, REG_WORK2); unlock2(l); unlock2(adr); @@ -5168,8 +5185,13 @@ MENDFUNC(2,jnf_MEM_WRITE24_OFF_l,(RR4 adr, RR4 l)) MIDFUNC(2,jnf_MEM_READ24_OFF_b,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5184,8 +5206,13 @@ MENDFUNC(2,jnf_MEM_READ24_OFF_b,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_READ24_OFF_w,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5201,8 +5228,13 @@ MENDFUNC(2,jnf_MEM_READ24_OFF_w,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_READ24_OFF_l,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5219,8 +5251,13 @@ MENDFUNC(2,jnf_MEM_READ24_OFF_l,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_GETADR_OFF,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5234,8 +5271,13 @@ MENDFUNC(2,jnf_MEM_GETADR_OFF,(W4 d, RR4 adr)) MIDFUNC(2,jnf_MEM_GETADR24_OFF,(W4 d, RR4 adr)) { +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, NATMEM_OFFSETX); + MOVT_ri16(REG_WORK2, NATMEM_OFFSETX >> 16); +#else uae_s32 offs = get_data_natmem(); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif adr = readreg(adr, 4); d = writereg(d, 4); @@ -5254,8 +5296,13 @@ MIDFUNC(2,jnf_MEM_GETBANKFUNC,(W4 d, RR4 adr, IMM offset)) adr = readreg(adr, 4); d = writereg(d, 4); +#ifdef ARMV6T2 + MOVW_ri16(REG_WORK2, (uae_u32)mem_banks); + MOVT_ri16(REG_WORK2, (uae_u32)mem_banks >> 16); +#else uae_s32 offs = data_long_offs((uae_u32)mem_banks); LDR_rRI(REG_WORK2, RPC_INDEX, offs); +#endif LSR_rri(REG_WORK1, adr, 16); LDR_rRR_LSLi(d, REG_WORK2, REG_WORK1, 2); LDR_rRI(d, d, offset); diff --git a/src/jit/compemu_support.cpp b/src/jit/compemu_support.cpp index 0031d69d..ca09d870 100644 --- a/src/jit/compemu_support.cpp +++ b/src/jit/compemu_support.cpp @@ -99,24 +99,24 @@ uae_u8* comp_pc_p; // gb-- Extra data for Basilisk II/JIT #ifdef JIT_DEBUG -static int JITDebug = 0; // Enable runtime disassemblers through mon? +static int JITDebug = 0; // Enable runtime disassemblers through mon? #else -const int JITDebug = 0; // Don't use JIT debug mode at all +const int JITDebug= 0; // Don't use JIT debug mode at all #endif #if USE_INLINING -static int follow_const_jumps = 1; // Flag: translation through constant jumps +static int follow_const_jumps = 1; // Flag: translation through constant jumps #else -const int follow_const_jumps = 0; +const int follow_const_jumps = 0; #endif -static uae_u32 current_cache_size = 0; // Cache grows upwards: how much has been consumed already -static int lazy_flush = 1; // Flag: lazy translation cache invalidation -static int avoid_fpu = 1; // Flag: compile FPU instructions ? -const int tune_alignment = 1; // Tune code alignments for running CPU ? -const int tune_nop_fillers = 1; // Tune no-op fillers for architecture -static int setzflg_uses_bsf = 0; // setzflg virtual instruction can use native BSF instruction correctly? -static int align_loops = 0; // Align the start of loops -static int align_jumps = 0; // Align the start of jumps +static uae_u32 current_cache_size = 0; // Cache grows upwards: how much has been consumed already +static int lazy_flush = 1; // Flag: lazy translation cache invalidation +static int avoid_fpu = 1; // Flag: compile FPU instructions ? +const int tune_alignment = 1; // Tune code alignments for running CPU ? +const int tune_nop_fillers = 1; // Tune no-op fillers for architecture +static int setzflg_uses_bsf = 0; // setzflg virtual instruction can use native BSF instruction correctly? +static int align_loops = 0; // Align the start of loops +static int align_jumps = 0; // Align the start of jumps op_properties prop[65536]; @@ -142,23 +142,23 @@ static uintptr current_block_start_target; uae_u32 needed_flags; static uintptr next_pc_p; static uintptr taken_pc_p; -static int branch_cc; +static int branch_cc; static int redo_current_block; -int segvcount=0; -static uae_u8* current_compile_p=NULL; +int segvcount = 0; +static uae_u8* current_compile_p = NULL; static uae_u8* max_compile_start; -uae_u8* compiled_code=NULL; +uae_u8* compiled_code = NULL; const int POPALLSPACE_SIZE = 2048; /* That should be enough space */ -static uae_u8 *popallspace=NULL; +static uae_u8 *popallspace = NULL; -void* pushall_call_handler=NULL; -static void* popall_do_nothing=NULL; -static void* popall_exec_nostats=NULL; -static void* popall_execute_normal=NULL; -static void* popall_cache_miss=NULL; -static void* popall_recompile_block=NULL; -static void* popall_check_checksum=NULL; +void* pushall_call_handler = NULL; +static void* popall_do_nothing = NULL; +static void* popall_exec_nostats = NULL; +static void* popall_execute_normal = NULL; +static void* popall_cache_miss = NULL; +static void* popall_recompile_block = NULL; +static void* popall_check_checksum = NULL; /* The 68k only ever executes from even addresses. So right now, we waste half the entries in this array @@ -271,12 +271,12 @@ STATIC_INLINE blockinfo* get_blockinfo(uae_u32 cl) STATIC_INLINE blockinfo* get_blockinfo_addr(void* addr) { - blockinfo* bi=get_blockinfo(cacheline(addr)); + blockinfo* bi = get_blockinfo(cacheline(addr)); while (bi) { - if (bi->pc_p==addr) + if (bi->pc_p == addr) return bi; - bi=bi->next_same_cl; + bi = bi->next_same_cl; } return NULL; } @@ -288,24 +288,24 @@ STATIC_INLINE blockinfo* get_blockinfo_addr(void* addr) STATIC_INLINE void remove_from_cl_list(blockinfo* bi) { - uae_u32 cl=cacheline(bi->pc_p); + uae_u32 cl = cacheline(bi->pc_p); if (bi->prev_same_cl_p) - *(bi->prev_same_cl_p)=bi->next_same_cl; + *(bi->prev_same_cl_p) = bi->next_same_cl; if (bi->next_same_cl) - bi->next_same_cl->prev_same_cl_p=bi->prev_same_cl_p; + bi->next_same_cl->prev_same_cl_p = bi->prev_same_cl_p; if (cache_tags[cl+1].bi) - cache_tags[cl].handler=cache_tags[cl+1].bi->handler_to_use; + cache_tags[cl].handler = cache_tags[cl+1].bi->handler_to_use; else - cache_tags[cl].handler=(cpuop_func *)popall_execute_normal; + cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; } STATIC_INLINE void remove_from_list(blockinfo* bi) { if (bi->prev_p) - *(bi->prev_p)=bi->next; + *(bi->prev_p) = bi->next; if (bi->next) - bi->next->prev_p=bi->prev_p; + bi->next->prev_p = bi->prev_p; } STATIC_INLINE void remove_from_lists(blockinfo* bi) @@ -316,16 +316,16 @@ STATIC_INLINE void remove_from_lists(blockinfo* bi) STATIC_INLINE void add_to_cl_list(blockinfo* bi) { - uae_u32 cl=cacheline(bi->pc_p); + uae_u32 cl = cacheline(bi->pc_p); if (cache_tags[cl+1].bi) - cache_tags[cl+1].bi->prev_same_cl_p=&(bi->next_same_cl); - bi->next_same_cl=cache_tags[cl+1].bi; + cache_tags[cl+1].bi->prev_same_cl_p = &(bi->next_same_cl); + bi->next_same_cl = cache_tags[cl+1].bi; - cache_tags[cl+1].bi=bi; - bi->prev_same_cl_p=&(cache_tags[cl+1].bi); + cache_tags[cl+1].bi = bi; + bi->prev_same_cl_p = &(cache_tags[cl+1].bi); - cache_tags[cl].handler=bi->handler_to_use; + cache_tags[cl].handler = bi->handler_to_use; } STATIC_INLINE void raise_in_cl_list(blockinfo* bi) @@ -337,31 +337,31 @@ STATIC_INLINE void raise_in_cl_list(blockinfo* bi) STATIC_INLINE void add_to_active(blockinfo* bi) { if (active) - active->prev_p=&(bi->next); - bi->next=active; + active->prev_p = &(bi->next); + bi->next = active; - active=bi; - bi->prev_p=&active; + active = bi; + bi->prev_p = &active; } STATIC_INLINE void add_to_dormant(blockinfo* bi) { if (dormant) - dormant->prev_p=&(bi->next); - bi->next=dormant; + dormant->prev_p = &(bi->next); + bi->next = dormant; - dormant=bi; - bi->prev_p=&dormant; + dormant = bi; + bi->prev_p = &dormant; } STATIC_INLINE void remove_dep(dependency* d) { if (d->prev_p) - *(d->prev_p)=d->next; + *(d->prev_p) = d->next; if (d->next) - d->next->prev_p=d->prev_p; - d->prev_p=NULL; - d->next=NULL; + d->next->prev_p = d->prev_p; + d->prev_p = NULL; + d->next = NULL; } /* This block's code is about to be thrown away, so it no longer @@ -383,21 +383,21 @@ STATIC_INLINE void adjust_jmpdep(dependency* d, cpuop_func* a) STATIC_INLINE void set_dhtu(blockinfo* bi, cpuop_func* dh) { - D2(panicbug("bi is %p\n",bi)); - if (dh!=bi->direct_handler_to_use) { - dependency* x=bi->deplist; - D2(panicbug("bi->deplist=%p\n",bi->deplist)); + D2(panicbug("bi is %p\n", bi)); + if (dh != bi->direct_handler_to_use) { + dependency* x = bi->deplist; + D2(panicbug("bi->deplist=%p\n", bi->deplist)); while (x) { - D2(panicbug("x is %p\n",x)); - D2(panicbug("x->next is %p\n",x->next)); - D2(panicbug("x->prev_p is %p\n",x->prev_p)); + D2(panicbug("x is %p\n", x)); + D2(panicbug("x->next is %p\n", x->next)); + D2(panicbug("x->prev_p is %p\n", x->prev_p)); if (x->jmp_off) { - adjust_jmpdep(x,dh); + adjust_jmpdep(x, dh); } - x=x->next; + x = x->next; } - bi->direct_handler_to_use=(cpuop_func*)dh; + bi->direct_handler_to_use = (cpuop_func*)dh; } } @@ -405,37 +405,37 @@ STATIC_INLINE void invalidate_block(blockinfo* bi) { int i; - bi->optlevel=0; - bi->count=currprefs.optcount[0]-1; - bi->handler=NULL; - bi->handler_to_use=(cpuop_func *)popall_execute_normal; - bi->direct_handler=NULL; - set_dhtu(bi,bi->direct_pen); - bi->needed_flags=0xff; + bi->optlevel = 0; + bi->count = currprefs.optcount[0]-1; + bi->handler = NULL; + bi->handler_to_use = (cpuop_func *)popall_execute_normal; + bi->direct_handler = NULL; + set_dhtu(bi, bi->direct_pen); + bi->needed_flags = 0xff; - bi->status=BI_INVALID; - for (i=0;i<2;i++) { - bi->dep[i].jmp_off=NULL; - bi->dep[i].target=NULL; + bi->status = BI_INVALID; + for (i=0; i<2; i++) { + bi->dep[i].jmp_off = NULL; + bi->dep[i].target = NULL; } remove_deps(bi); } STATIC_INLINE void create_jmpdep(blockinfo* bi, int i, uae_u32* jmpaddr, uae_u32 target) { - blockinfo* tbi=get_blockinfo_addr((void*)(uintptr)target); + blockinfo* tbi = get_blockinfo_addr((void*)(uintptr)target); Dif(!tbi) { jit_abort (_T("JIT: Could not create jmpdep!\n")); } - bi->dep[i].jmp_off=jmpaddr; - bi->dep[i].source=bi; - bi->dep[i].target=tbi; - bi->dep[i].next=tbi->deplist; + bi->dep[i].jmp_off = jmpaddr; + bi->dep[i].source = bi; + bi->dep[i].target = tbi; + bi->dep[i].next = tbi->deplist; if (bi->dep[i].next) - bi->dep[i].next->prev_p=&(bi->dep[i].next); - bi->dep[i].prev_p=&(tbi->deplist); - tbi->deplist=&(bi->dep[i]); + bi->dep[i].next->prev_p = &(bi->dep[i].next); + bi->dep[i].prev_p = &(tbi->deplist); + tbi->deplist = &(bi->dep[i]); } STATIC_INLINE void block_need_recompile(blockinfo * bi) @@ -443,12 +443,12 @@ STATIC_INLINE void block_need_recompile(blockinfo * bi) uae_u32 cl = cacheline(bi->pc_p); set_dhtu(bi,bi->direct_pen); - bi->direct_handler=bi->direct_pen; + bi->direct_handler = bi->direct_pen; bi->handler_to_use = (cpuop_func *)popall_execute_normal; bi->handler = (cpuop_func *)popall_execute_normal; if (bi == cache_tags[cl + 1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; + cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; bi->status = BI_NEED_RECOMP; } @@ -477,7 +477,7 @@ STATIC_INLINE void mark_callers_recompile(blockinfo * bi) /* nothing */ } else { - D2(panicbug(_T("Status %d in mark_callers\n"),cbi->status)); // FIXME? + D2(panicbug(_T("Status %d in mark_callers\n"), cbi->status)); // FIXME? } } x = next; @@ -486,21 +486,20 @@ STATIC_INLINE void mark_callers_recompile(blockinfo * bi) STATIC_INLINE blockinfo* get_blockinfo_addr_new(void* addr, int setstate) { - blockinfo* bi=get_blockinfo_addr(addr); + blockinfo* bi = get_blockinfo_addr(addr); int i; if (!bi) { - for (i=0;ipc_p=(uae_u8 *)addr; + bi = hold_bi[i]; + hold_bi[i] = NULL; + bi->pc_p = (uae_u8 *)addr; invalidate_block(bi); add_to_active(bi); add_to_cl_list(bi); - } } } @@ -668,7 +667,7 @@ bool check_prefs_changed_comp (void) { bool changed = 0; - if (currprefs.cachesize!=changed_prefs.cachesize) { + if (currprefs.cachesize != changed_prefs.cachesize) { currprefs.cachesize = changed_prefs.cachesize; alloc_cache(); changed = 1; @@ -684,34 +683,16 @@ static uae_u8* target; STATIC_INLINE void emit_byte(uae_u8 x) { - *target++=x; -} - -STATIC_INLINE void emit_word(uae_u16 x) -{ - *((uae_u16*)target)=x; - target+=2; + *target++ = x; } STATIC_INLINE void emit_long(uae_u32 x) { - *((uae_u32*)target)=x; - target+=4; + *((uae_u32*)target) = x; + target += 4; } -STATIC_INLINE void emit_quad(uae_u64 x) -{ - *((uae_u64*)target)=x; - target+=8; -} - -STATIC_INLINE void emit_block(const uae_u8 *block, uae_u32 blocklen) -{ - memcpy((uae_u8 *)target,block,blocklen); - target+=blocklen; -} - -#define MAX_COMPILE_PTR max_compile_start +#define MAX_COMPILE_PTR max_compile_start STATIC_INLINE uae_u32 reverse32(uae_u32 v) { @@ -725,7 +706,7 @@ STATIC_INLINE uae_u32 reverse32(uae_u32 v) void set_target(uae_u8* t) { - target=t; + target = t; } STATIC_INLINE uae_u8* get_target_noopt(void) @@ -742,7 +723,7 @@ STATIC_INLINE uae_u8* get_target(void) /******************************************************************** * New version of data buffer: interleave data and code * ********************************************************************/ -#if defined(CPU_arm) +#if defined(CPU_arm) && !defined(ARMV6T2) #define DATA_BUFFER_SIZE 768 // Enlarge POPALLSPACE_SIZE if this value is greater than 768 #define DATA_BUFFER_MAXOFFSET 4096 - 32 // max range between emit of data and use of data @@ -751,7 +732,6 @@ static uae_u8* data_endpos = 0; #ifdef DEBUG_DATA_BUFFER static uae_u32 data_wasted = 0; static uae_u32 data_buffers_used = 0; -static uae_u32 data_emit_natmem = 0; #endif static uae_s32 data_natmem_pos = 0; @@ -780,9 +760,9 @@ STATIC_INLINE void data_check_end(uae_s32 n, uae_s32 codesize) STATIC_INLINE uae_s32 data_word_offs(uae_u16 x) { data_check_end(4, 4); - *((uae_u16*)data_writepos)=x; + *((uae_u16*)data_writepos) = x; data_writepos += 2; - *((uae_u16*)data_writepos)=0; + *((uae_u16*)data_writepos) = 0; data_writepos += 2; return (uae_s32)data_writepos - (uae_s32)get_target_noopt() - 12; } @@ -790,7 +770,7 @@ STATIC_INLINE uae_s32 data_word_offs(uae_u16 x) STATIC_INLINE uae_s32 data_long(uae_u32 x, uae_s32 codesize) { data_check_end(4, codesize); - *((uae_u32*)data_writepos)=x; + *((uae_u32*)data_writepos) = x; data_writepos += 4; return (uae_s32)data_writepos - 4; } @@ -798,7 +778,7 @@ STATIC_INLINE uae_s32 data_long(uae_u32 x, uae_s32 codesize) STATIC_INLINE uae_s32 data_long_offs(uae_u32 x) { data_check_end(4, 4); - *((uae_u32*)data_writepos)=x; + *((uae_u32*)data_writepos) = x; data_writepos += 4; return (uae_s32)data_writepos - (uae_s32)get_target_noopt() - 12; } @@ -813,9 +793,6 @@ STATIC_INLINE uae_s32 get_data_natmem(void) if(data_natmem_pos == 0 || (uae_s32)get_target_noopt() - data_natmem_pos >= DATA_BUFFER_MAXOFFSET) { data_natmem_pos = data_long(NATMEM_OFFSETX, 4); -#ifdef DEBUG_DATA_BUFFER - data_emit_natmem++; -#endif } return get_data_offset(data_natmem_pos); } @@ -846,48 +823,48 @@ STATIC_INLINE void clobber_flags(void); static void make_flags_live_internal(void) { - if (live.flags_in_flags==VALID) + if (live.flags_in_flags == VALID) return; - Dif (live.flags_on_stack==TRASH) { + Dif (live.flags_on_stack == TRASH) { jit_abort (_T("JIT: Want flags, got something on stack, but it is TRASH\n")); } - if (live.flags_on_stack==VALID) { + if (live.flags_on_stack == VALID) { int tmp; - tmp=readreg_specific(FLAGTMP,4,FLAG_NREG2); + tmp = readreg_specific(FLAGTMP, 4, FLAG_NREG2); raw_reg_to_flags(tmp); unlock2(tmp); - live.flags_in_flags=VALID; + live.flags_in_flags = VALID; return; } jit_abort (_T("JIT: Huh? live.flags_in_flags=%d, live.flags_on_stack=%d, but need to make live\n"), - live.flags_in_flags,live.flags_on_stack); + live.flags_in_flags, live.flags_on_stack); } static void flags_to_stack(void) { - if (live.flags_on_stack==VALID) + if (live.flags_on_stack == VALID) return; if (!live.flags_are_important) { - live.flags_on_stack=VALID; + live.flags_on_stack = VALID; return; } - Dif (live.flags_in_flags!=VALID) + Dif (live.flags_in_flags != VALID) jit_abort(_T("flags_to_stack != VALID")); else { int tmp; - tmp=writereg_specific(FLAGTMP,4,FLAG_NREG1); + tmp = writereg_specific(FLAGTMP, 4, FLAG_NREG1); raw_flags_to_reg(tmp); unlock2(tmp); } - live.flags_on_stack=VALID; + live.flags_on_stack = VALID; } STATIC_INLINE void clobber_flags(void) { - if (live.flags_in_flags==VALID && live.flags_on_stack!=VALID) + if (live.flags_in_flags == VALID && live.flags_on_stack != VALID) flags_to_stack(); - live.flags_in_flags=TRASH; + live.flags_in_flags = TRASH; } /* Prepare for leaving the compiled stuff */ @@ -923,40 +900,33 @@ STATIC_INLINE void do_load_reg(int n, int r) STATIC_INLINE void set_status(int r, int status) { - live.state[r].status=status; + live.state[r].status = status; } STATIC_INLINE int isinreg(int r) { - return live.state[r].status==CLEAN || live.state[r].status==DIRTY; + return live.state[r].status == CLEAN || live.state[r].status == DIRTY; } -STATIC_INLINE void adjust_nreg(int r, uae_u32 val) +static void tomem(int r) { - if (!val) - return; - compemu_raw_lea_l_brr(r,r,val); -} + int rr = live.state[r].realreg; -static void tomem(int r) -{ - int rr=live.state[r].realreg; - - if (live.state[r].status==DIRTY) { + if (live.state[r].status == DIRTY) { switch (live.state[r].dirtysize) { - case 1: compemu_raw_mov_b_mr((uintptr)live.state[r].mem,rr); break; - case 2: compemu_raw_mov_w_mr((uintptr)live.state[r].mem,rr); break; - case 4: compemu_raw_mov_l_mr((uintptr)live.state[r].mem,rr); break; + case 1: compemu_raw_mov_b_mr((uintptr)live.state[r].mem, rr); break; + case 2: compemu_raw_mov_w_mr((uintptr)live.state[r].mem, rr); break; + case 4: compemu_raw_mov_l_mr((uintptr)live.state[r].mem, rr); break; default: abort(); } - set_status(r,CLEAN); - live.state[r].dirtysize=0; + set_status(r, CLEAN); + live.state[r].dirtysize = 0; } } STATIC_INLINE int isconst(int r) { - return live.state[r].status==ISCONST; + return live.state[r].status == ISCONST; } int is_const(int r) @@ -969,9 +939,9 @@ STATIC_INLINE void writeback_const(int r) if (!isconst(r)) return; - compemu_raw_mov_l_mi((uintptr)live.state[r].mem,live.state[r].val); - live.state[r].val=0; - set_status(r,INMEM); + compemu_raw_mov_l_mi((uintptr)live.state[r].mem, live.state[r].val); + live.state[r].val = 0; + set_status(r, INMEM); } STATIC_INLINE void tomem_c(int r) @@ -990,37 +960,37 @@ static void evict(int r) if (!isinreg(r)) return; tomem(r); - rr=live.state[r].realreg; + rr = live.state[r].realreg; Dif (live.nat[rr].locked && - live.nat[rr].nholds==1) { - jit_abort (_T("JIT: register %d in nreg %d is locked!\n"),r,live.state[r].realreg); + live.nat[rr].nholds == 1) { + jit_abort (_T("JIT: register %d in nreg %d is locked!\n"), r, live.state[r].realreg); } live.nat[rr].nholds--; - if (live.nat[rr].nholds!=live.state[r].realind) { /* Was not last */ - int topreg=live.nat[rr].holds[live.nat[rr].nholds]; - int thisind=live.state[r].realind; - live.nat[rr].holds[thisind]=topreg; - live.state[topreg].realind=thisind; + if (live.nat[rr].nholds != live.state[r].realind) { /* Was not last */ + int topreg = live.nat[rr].holds[live.nat[rr].nholds]; + int thisind = live.state[r].realind; + live.nat[rr].holds[thisind] = topreg; + live.state[topreg].realind = thisind; } - live.state[r].realreg=-1; - set_status(r,INMEM); + live.state[r].realreg = -1; + set_status(r, INMEM); } STATIC_INLINE void free_nreg(int r) { - int i=live.nat[r].nholds; + int i = live.nat[r].nholds; while (i) { int vr; --i; - vr=live.nat[r].holds[i]; + vr = live.nat[r].holds[i]; evict(vr); } - Dif (live.nat[r].nholds!=0) { - jit_abort (_T("JIT: Failed to free nreg %d, nholds is %d\n"),r,live.nat[r].nholds); + Dif (live.nat[r].nholds != 0) { + jit_abort (_T("JIT: Failed to free nreg %d, nholds is %d\n"), r, live.nat[r].nholds); } } @@ -1029,10 +999,10 @@ STATIC_INLINE void isclean(int r) { if (!isinreg(r)) return; - live.state[r].validsize=4; - live.state[r].dirtysize=0; - live.state[r].val=0; - set_status(r,CLEAN); + live.state[r].validsize = 4; + live.state[r].dirtysize = 0; + live.state[r].val = 0; + set_status(r, CLEAN); } STATIC_INLINE void disassociate(int r) @@ -1044,8 +1014,8 @@ STATIC_INLINE void disassociate(int r) STATIC_INLINE void set_const(int r, uae_u32 val) { disassociate(r); - live.state[r].val=val; - set_status(r,ISCONST); + live.state[r].val = val; + set_status(r, ISCONST); } static int alloc_reg_hinted(int r, int size, int willclobber, int hint) @@ -1053,99 +1023,95 @@ static int alloc_reg_hinted(int r, int size, int willclobber, int hint) int bestreg; uae_s32 when; int i; - uae_s32 badness=0; /* to shut up gcc */ - bestreg=-1; - when=2000000000; + uae_s32 badness = 0; /* to shut up gcc */ + bestreg = -1; + when = 2000000000; /* XXX use a regalloc_order table? */ - for (i=0;i0) { + if (live.nat[bestreg].nholds > 0) { free_nreg(bestreg); } if (isinreg(r)) { - int rr=live.state[r].realreg; + int rr = live.state[r].realreg; /* This will happen if we read a partially dirty register at a bigger size */ - Dif (willclobber || live.state[r].validsize>=size) + Dif (willclobber || live.state[r].validsize >= size) jit_abort(_T("willclobber || live.state[r].validsize>=size")); - Dif (live.nat[rr].nholds!=1) + Dif (live.nat[rr].nholds != 1) jit_abort(_T("live.nat[rr].nholds!=1")); - if (size==4 && live.state[r].validsize==2) { - compemu_raw_mov_l_rm(bestreg,(uintptr)live.state[r].mem); - compemu_raw_bswap_32(bestreg); - compemu_raw_zero_extend_16_rr(rr,rr); - compemu_raw_zero_extend_16_rr(bestreg,bestreg); - compemu_raw_bswap_32(bestreg); - compemu_raw_lea_l_rr_indexed(rr,rr,bestreg,1); - live.state[r].validsize=4; - live.nat[rr].touched=touchcnt++; + if (size == 4 && live.state[r].validsize == 2) { + compemu_raw_mov_l_rm(bestreg, (uintptr)live.state[r].mem); + compemu_raw_MERGE_rr(rr, bestreg); + live.state[r].validsize = 4; + live.nat[rr].touched = touchcnt++; return rr; } - if (live.state[r].validsize==1) { + if (live.state[r].validsize == 1) { /* Nothing yet */ } evict(r); } if (!willclobber) { - if (live.state[r].status!=UNDEF) { + if (live.state[r].status != UNDEF) { if (isconst(r)) { - compemu_raw_mov_l_ri(bestreg,live.state[r].val); - live.state[r].val=0; - live.state[r].dirtysize=4; - set_status(r,DIRTY); + compemu_raw_mov_l_ri(bestreg, live.state[r].val); + live.state[r].val = 0; + live.state[r].dirtysize = 4; + set_status(r, DIRTY); } else { do_load_reg(bestreg, r); - live.state[r].dirtysize=0; - set_status(r,CLEAN); + live.state[r].dirtysize = 0; + set_status(r, CLEAN); } } else { - live.state[r].val=0; - live.state[r].dirtysize=0; - set_status(r,CLEAN); + live.state[r].val = 0; + live.state[r].dirtysize = 0; + set_status(r, CLEAN); } - live.state[r].validsize=4; + live.state[r].validsize = 4; } else { /* this is the easiest way, but not optimal. FIXME! */ /* Now it's trickier, but hopefully still OK */ - if (!isconst(r) || size==4) { - live.state[r].validsize=size; - live.state[r].dirtysize=size; - live.state[r].val=0; - set_status(r,DIRTY); + if (!isconst(r) || size == 4) { + live.state[r].validsize = size; + live.state[r].dirtysize = size; + live.state[r].val = 0; + set_status(r, DIRTY); } else { - if (live.state[r].status!=UNDEF) - compemu_raw_mov_l_ri(bestreg,live.state[r].val); - live.state[r].val=0; - live.state[r].validsize=4; - live.state[r].dirtysize=4; - set_status(r,DIRTY); + if (live.state[r].status != UNDEF) + compemu_raw_mov_l_ri(bestreg, live.state[r].val); + live.state[r].val = 0; + live.state[r].validsize = 4; + live.state[r].dirtysize = 4; + set_status(r, DIRTY); } } - live.state[r].realreg=bestreg; - live.state[r].realind=live.nat[bestreg].nholds; - live.nat[bestreg].touched=touchcnt++; - live.nat[bestreg].holds[live.nat[bestreg].nholds]=r; + live.state[r].realreg = bestreg; + live.state[r].realind = live.nat[bestreg].nholds; + live.nat[bestreg].touched = touchcnt++; + live.nat[bestreg].holds[live.nat[bestreg].nholds] = r; live.nat[bestreg].nholds++; return bestreg; @@ -1167,96 +1133,96 @@ static void setlock(int r) static void mov_nregs(int d, int s) { - int nd=live.nat[d].nholds; + int nd = live.nat[d].nholds; int i; - if (s==d) + if (s == d) return; - if (nd>0) + if (nd > 0) free_nreg(d); - compemu_raw_mov_l_rr(d,s); + compemu_raw_mov_l_rr(d, s); - for (i=0;i=size) { - n=live.state[r].realreg; + if (isinreg(r) && live.state[r].validsize >= size) { + n = live.state[r].realreg; - answer=n; + answer = n; - if (answer<0) + if (answer < 0) evict(r); } /* either the value was in memory to start with, or it was evicted and is in memory now */ - if (answer<0) { - answer=alloc_reg_hinted(r,spec>=0?4:size,0,spec); + if (answer < 0) { + answer = alloc_reg_hinted(r, spec >= 0 ? 4 : size, 0, spec); } - if (spec>=0 && spec!=answer) { + if (spec >= 0 && spec != answer) { /* Too bad */ - mov_nregs(spec,answer); - answer=spec; + mov_nregs(spec, answer); + answer = spec; } live.nat[answer].locked++; - live.nat[answer].touched=touchcnt++; + live.nat[answer].touched = touchcnt++; return answer; } @@ -1298,12 +1264,12 @@ STATIC_INLINE int readreg_general(int r, int size, int spec) static int readreg(int r, int size) { - return readreg_general(r,size,-1); + return readreg_general(r, size, -1); } static int readreg_specific(int r, int size, int spec) { - return readreg_general(r,size,spec); + return readreg_general(r, size, spec); } /* writereg_general(r, size, spec) @@ -1320,103 +1286,98 @@ static int readreg_specific(int r, int size, int spec) STATIC_INLINE int writereg_general(int r, int size, int spec) { int n; - int answer=-1; + int answer = -1; - make_exclusive(r,size,spec); + make_exclusive(r, size, spec); if (isinreg(r)) { - int nvsize=size>live.state[r].validsize?size:live.state[r].validsize; - int ndsize=size>live.state[r].dirtysize?size:live.state[r].dirtysize; - n=live.state[r].realreg; + int nvsize = size > live.state[r].validsize ? size : live.state[r].validsize; + int ndsize = size > live.state[r].dirtysize ? size : live.state[r].dirtysize; + n = live.state[r].realreg; - Dif (live.nat[n].nholds!=1) + Dif (live.nat[n].nholds != 1) jit_abort(_T("live.nat[%d].nholds!=1"), n); - live.state[r].dirtysize=ndsize; - live.state[r].validsize=nvsize; - answer=n; + live.state[r].dirtysize = ndsize; + live.state[r].validsize = nvsize; + answer = n; - if (answer<0) + if (answer < 0) evict(r); } /* either the value was in memory to start with, or it was evicted and is in memory now */ - if (answer<0) { - answer=alloc_reg_hinted(r,size,1,spec); + if (answer < 0) { + answer = alloc_reg_hinted(r, size, 1, spec); } - if (spec>=0 && spec!=answer) { - mov_nregs(spec,answer); - answer=spec; + if (spec >= 0 && spec != answer) { + mov_nregs(spec, answer); + answer = spec; } - if (live.state[r].status==UNDEF) - live.state[r].validsize=4; - live.state[r].dirtysize=size>live.state[r].dirtysize?size:live.state[r].dirtysize; - live.state[r].validsize=size>live.state[r].validsize?size:live.state[r].validsize; + if (live.state[r].status == UNDEF) + live.state[r].validsize = 4; + live.state[r].dirtysize = size > live.state[r].dirtysize ? size : live.state[r].dirtysize; + live.state[r].validsize = size > live.state[r].validsize ? size : live.state[r].validsize; live.nat[answer].locked++; - live.nat[answer].touched=touchcnt++; - if (size==4) { - live.state[r].val=0; + live.nat[answer].touched = touchcnt++; + if (size == 4) { + live.state[r].val = 0; } else { Dif (live.state[r].val) { jit_abort (_T("JIT: Problem with val\n")); } } - set_status(r,DIRTY); + set_status(r, DIRTY); return answer; } static int writereg(int r, int size) { - return writereg_general(r,size,-1); + return writereg_general(r, size, -1); } static int writereg_specific(int r, int size, int spec) { - return writereg_general(r,size,spec); + return writereg_general(r, size, spec); } -STATIC_INLINE int rmw_general(int r, int wsize, int rsize, int spec) +STATIC_INLINE int rmw_general(int r, int wsize, int rsize) { int n; - int answer=-1; + int answer = -1; - if (live.state[r].status==UNDEF) { - D(panicbug("JIT: WARNING: Unexpected read of undefined register %d\n",r)); + if (live.state[r].status == UNDEF) { + D(panicbug("JIT: WARNING: Unexpected read of undefined register %d\n", r)); } - make_exclusive(r,0,spec); + make_exclusive(r, 0, -1); - Dif (wsize=rsize) { + if (isinreg(r) && live.state[r].validsize >= rsize) { n = live.state[r].realreg; - Dif (live.nat[n].nholds!=1) + Dif (live.nat[n].nholds != 1) jit_abort(_T("live.nat[n].nholds!=1"), n); answer = n; - if (answer<0) + if (answer < 0) evict(r); } /* either the value was in memory to start with, or it was evicted and is in memory now */ - if (answer<0) { - answer=alloc_reg_hinted(r,spec>=0?4:rsize,0,spec); + if (answer < 0) { + answer = alloc_reg_hinted(r, rsize, 0, -1); } - if (spec>=0 && spec!=answer) { - /* Too bad */ - mov_nregs(spec,answer); - answer=spec; - } - if (wsize>live.state[r].dirtysize) - live.state[r].dirtysize=wsize; - if (wsize>live.state[r].validsize) - live.state[r].validsize=wsize; - set_status(r,DIRTY); + if (wsize > live.state[r].dirtysize) + live.state[r].dirtysize = wsize; + if (wsize > live.state[r].validsize) + live.state[r].validsize = wsize; + set_status(r, DIRTY); live.nat[answer].locked++; - live.nat[answer].touched=touchcnt++; + live.nat[answer].touched = touchcnt++; Dif (live.state[r].val) { jit_abort (_T("JIT: Problem with val(rmw)\n")); @@ -1426,12 +1387,7 @@ STATIC_INLINE int rmw_general(int r, int wsize, int rsize, int spec) static int rmw(int r, int wsize, int rsize) { - return rmw_general(r,wsize,rsize,-1); -} - -static int rmw_specific(int r, int wsize, int rsize, int spec) -{ - return rmw_general(r,wsize,rsize,spec); + return rmw_general(r, wsize, rsize); } /******************************************************************** @@ -1441,32 +1397,32 @@ static int rmw_specific(int r, int wsize, int rsize, int spec) #ifdef USE_JIT_FPU static void f_tomem(int r) { - if (live.fate[r].status==DIRTY) { + if (live.fate[r].status == DIRTY) { #if USE_LONG_DOUBLE - raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); + raw_fmov_ext_mr((uintptr)live.fate[r].mem, live.fate[r].realreg); #else - raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); + raw_fmov_mr((uintptr)live.fate[r].mem, live.fate[r].realreg); #endif - live.fate[r].status=CLEAN; + live.fate[r].status = CLEAN; } } static void f_tomem_drop(int r) { - if (live.fate[r].status==DIRTY) { + if (live.fate[r].status == DIRTY) { #if USE_LONG_DOUBLE - raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); + raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem, live.fate[r].realreg); #else - raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); + raw_fmov_mr_drop((uintptr)live.fate[r].mem, live.fate[r].realreg); #endif - live.fate[r].status=INMEM; + live.fate[r].status = INMEM; } } STATIC_INLINE int f_isinreg(int r) { - return live.fate[r].status==CLEAN || live.fate[r].status==DIRTY; + return live.fate[r].status == CLEAN || live.fate[r].status == DIRTY; } static void f_evict(int r) @@ -1475,8 +1431,8 @@ static void f_evict(int r) if (!f_isinreg(r)) return; - rr=live.fate[r].realreg; - if (live.fat[rr].nholds==1) + rr = live.fate[r].realreg; + if (live.fat[rr].nholds == 1) f_tomem_drop(r); else f_tomem(r); @@ -1741,7 +1697,7 @@ static void fflags_into_flags_internal(uae_u32 tmp) uae_u32 get_const(int r) { Dif (!isconst(r)) { - jit_abort(_T("Register %d should be constant, but isn't\n"),r); + jit_abort(_T("Register %d should be constant, but isn't\n"), r); } return live.state[r].val; } @@ -1820,9 +1776,9 @@ void compiler_exit(void) emul_end_time = clock(); #endif -#if defined(CPU_arm) +#if defined(CPU_arm) && !defined(ARMV6T2) #ifdef DEBUG_DATA_BUFFER - printf("data_wasted = %d bytes in %d blocks; natmem emits: %d\n", data_wasted, data_buffers_used, data_emit_natmem); + printf("data_wasted = %d bytes in %d blocks\n", data_wasted, data_buffers_used); #endif #endif @@ -1880,89 +1836,90 @@ void compiler_exit(void) void init_comp(void) { int i; - uae_s8* au=always_used; + uae_s8* au = always_used; #ifdef RECORD_REGISTER_USAGE - for (i=0;i<16;i++) + for (i=0; i<16; i++) reg_count_local[i] = 0; #endif - for (i=0;i=(uae_u32)kickmemory && - addr<(uae_u32)kickmemory+8*65536); + return (addr >= (uae_u32)kickmemory && + addr < (uae_u32)kickmemory + 8 * 65536); } static void flush_all(void) { int i; - for (i=0;i0) + if (!call_saved[i] && live.nat[i].nholds > 0) free_nreg(i); } #ifdef USE_JIT_FPU - for (i=0;i0) + for (i = 0; i < N_FREGS; i++) + if (live.fat[i].nholds > 0) f_free_nreg(i); #endif - live.flags_in_flags=TRASH; /* Note: We assume we already rescued the + live.flags_in_flags = TRASH; /* Note: We assume we already rescued the flags at the very start of the call_r functions! */ } @@ -2122,9 +2080,9 @@ static void prepare_for_call_2(void) void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond) { - next_pc_p=not_taken; - taken_pc_p=taken; - branch_cc=cond; + next_pc_p = not_taken; + taken_pc_p = taken; + branch_cc = cond; } /* Note: get_handler may fail in 64 Bit environments, if direct_handler_to_use is @@ -2132,7 +2090,7 @@ void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond) */ static uintptr get_handler(uintptr addr) { - blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0); + blockinfo* bi = get_blockinfo_addr_new((void*)(uintptr) addr, 0); return (uintptr)bi->direct_handler_to_use; } @@ -2140,7 +2098,7 @@ static uintptr get_handler(uintptr addr) * if that assumption is wrong! No branches, no second chances, just * straight go-for-it attitude */ -static void writemem_real(int address, int source,int size) +static void writemem_real(int address, int source, int size) { if(currprefs.address_space_24) { @@ -2170,30 +2128,30 @@ STATIC_INLINE void writemem(int address, int source, int offset, int size, int t void writebyte(int address, int source, int tmp) { - if (special_mem&S_WRITE) - writemem_special(address,source,20,1,tmp); + if (special_mem & S_WRITE) + writemem_special(address, source, 20, 1, tmp); else - writemem_real(address,source,1); + writemem_real(address, source, 1); } void writeword(int address, int source, int tmp) { - if (special_mem&S_WRITE) - writemem_special(address,source,16,2,tmp); + if (special_mem & S_WRITE) + writemem_special(address, source, 16, 2, tmp); else - writemem_real(address,source,2); + writemem_real(address, source, 2); } void writelong(int address, int source, int tmp) { - if (special_mem&S_WRITE) - writemem_special(address,source,12,4,tmp); + if (special_mem & S_WRITE) + writemem_special(address, source, 12, 4, tmp); else - writemem_real(address,source,4); + writemem_real(address, source, 4); } // Now the same for clobber variant -STATIC_INLINE void writemem_real_clobber(int address, int source,int size) +STATIC_INLINE void writemem_real_clobber(int address, int source, int size) { if(currprefs.address_space_24) { @@ -2216,10 +2174,10 @@ STATIC_INLINE void writemem_real_clobber(int address, int source,int size) void writelong_clobber(int address, int source, int tmp) { - if (special_mem&S_WRITE) - writemem_special(address,source,12,4,tmp); + if (special_mem & S_WRITE) + writemem_special(address, source, 12, 4, tmp); else - writemem_real_clobber(address,source,4); + writemem_real_clobber(address, source, 4); } @@ -2257,32 +2215,32 @@ STATIC_INLINE void readmem(int address, int dest, int offset, int size, int tmp) void readbyte(int address, int dest, int tmp) { - if (special_mem&S_READ) - readmem_special(address,dest,8,1,tmp); + if (special_mem & S_READ) + readmem_special(address, dest, 8, 1, tmp); else - readmem_real(address,dest,1); + readmem_real(address, dest, 1); } void readword(int address, int dest, int tmp) { - if (special_mem&S_READ) - readmem_special(address,dest,4,2,tmp); + if (special_mem & S_READ) + readmem_special(address, dest, 4, 2, tmp); else - readmem_real(address,dest,2); + readmem_real(address, dest, 2); } void readlong(int address, int dest, int tmp) { - if (special_mem&S_READ) - readmem_special(address,dest,0,4,tmp); + if (special_mem & S_READ) + readmem_special(address, dest, 0, 4, tmp); else - readmem_real(address,dest,4); + readmem_real(address, dest, 4); } /* This one might appear a bit odd... */ STATIC_INLINE void get_n_addr_old(int address, int dest, int tmp) { - readmem(address,dest,24,4,tmp); + readmem(address, dest, 24, 4, tmp); } STATIC_INLINE void get_n_addr_real(int address, int dest) @@ -2305,7 +2263,7 @@ void get_n_addr_jmp(int address, int dest, int tmp) { /* For this, we need to get the same address as the rest of UAE would --- otherwise we end up translating everything twice */ - get_n_addr(address,dest,tmp); + get_n_addr(address, dest, tmp); } /* base is a register, but dp is an actual value. @@ -2316,10 +2274,10 @@ void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp) int regd_shift=(dp >> 9) & 3; if (dp & 0x100) { - int ignorebase=(dp&0x80); - int ignorereg=(dp&0x40); - int addbase=0; - int outer=0; + int ignorebase = (dp&0x80); + int ignorereg = (dp&0x40); + int addbase = 0; + int outer = 0; if ((dp & 0x30) == 0x20) addbase = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); if ((dp & 0x30) == 0x30) addbase = comp_get_ilong((m68k_pc_offset+=4)-4); @@ -2330,47 +2288,47 @@ void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp) if ((dp & 0x4) == 0) { /* add regd *before* the get_long */ if (!ignorereg) { if ((dp & 0x800) == 0) - sign_extend_16_rr(target,reg); + sign_extend_16_rr(target, reg); else - mov_l_rr(target,reg); - shll_l_ri(target,regd_shift); + mov_l_rr(target, reg); + shll_l_ri(target, regd_shift); } else - mov_l_ri(target,0); + mov_l_ri(target, 0); /* target is now regd */ if (!ignorebase) - add_l(target,base); - add_l_ri(target,addbase); - if (dp&0x03) readlong(target,target,tmp); + add_l(target, base); + add_l_ri(target, addbase); + if (dp&0x03) readlong(target, target, tmp); } else { /* do the getlong first, then add regd */ if (!ignorebase) { - mov_l_rr(target,base); - add_l_ri(target,addbase); + mov_l_rr(target, base); + add_l_ri(target, addbase); } else - mov_l_ri(target,addbase); - if (dp&0x03) readlong(target,target,tmp); + mov_l_ri(target, addbase); + if (dp&0x03) readlong(target, target, tmp); if (!ignorereg) { if ((dp & 0x800) == 0) - sign_extend_16_rr(tmp,reg); + sign_extend_16_rr(tmp, reg); else - mov_l_rr(tmp,reg); - shll_l_ri(tmp,regd_shift); + mov_l_rr(tmp, reg); + shll_l_ri(tmp, regd_shift); /* tmp is now regd */ - add_l(target,tmp); + add_l(target, tmp); } } - add_l_ri(target,outer); + add_l_ri(target, outer); } else { /* 68000 version */ if ((dp & 0x800) == 0) { /* Sign extend */ sign_extend_16_rr(target, reg); - lea_l_brr_indexed(target, base, target, 1<csi; @@ -2437,21 +2395,21 @@ static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2) uae_s32 len = csi->length; uintptr tmp = (uintptr)csi->start_p; #else - uae_s32 len=bi->len; - uintptr tmp=(uintptr)bi->min_pcp; + uae_s32 len = bi->len; + uintptr tmp = (uintptr)bi->min_pcp; #endif uae_u32* pos; - len+=(tmp&3); + len += (tmp&3); tmp &= ~((uintptr)3); - pos=(uae_u32*)tmp; + pos = (uae_u32*)tmp; if (len >= 0 && len <= MAX_CHECKSUM_LEN) { while (len>0) { - k1+=*pos; - k2^=*pos; + k1 += *pos; + k2 ^= *pos; pos++; - len-=4; + len -= 4; } } @@ -2460,18 +2418,18 @@ static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2) } #endif - *c1=k1; - *c2=k2; + *c1 = k1; + *c2 = k2; } int check_for_cache_miss(void) { - blockinfo* bi=get_blockinfo_addr(regs.pc_p); + blockinfo* bi = get_blockinfo_addr(regs.pc_p); if (bi) { - int cl=cacheline(regs.pc_p); - if (bi!=cache_tags[cl+1].bi) { + int cl = cacheline(regs.pc_p); + if (bi != cache_tags[cl+1].bi) { raise_in_cl_list(bi); return 1; } @@ -2485,7 +2443,7 @@ static void recompile_block(void) /* An existing block's countdown code has expired. We need to make sure that execute_normal doesn't refuse to recompile due to a perceived cache miss... */ - blockinfo* bi=get_blockinfo_addr(regs.pc_p); + blockinfo* bi = get_blockinfo_addr(regs.pc_p); Dif (!bi) jit_abort(_T("recompile_block")); @@ -2496,10 +2454,10 @@ static void recompile_block(void) static void cache_miss(void) { - blockinfo* bi=get_blockinfo_addr(regs.pc_p); + blockinfo* bi = get_blockinfo_addr(regs.pc_p); #if COMP_DEBUG - uae_u32 cl=cacheline(regs.pc_p); - blockinfo* bi2=get_blockinfo(cl); + uae_u32 cl = cacheline(regs.pc_p); + blockinfo* bi2 = get_blockinfo(cl); #endif if (!bi) { @@ -2507,8 +2465,8 @@ static void cache_miss(void) return; } #if COMP_DEBUG - Dif (!bi2 || bi==bi2) { - jit_abort (_T("Unexplained cache miss %p %p\n"),bi,bi2); + Dif (!bi2 || bi == bi2) { + jit_abort (_T("Unexplained cache miss %p %p\n"), bi, bi2); } #endif raise_in_cl_list(bi); @@ -2519,42 +2477,42 @@ static int called_check_checksum(blockinfo* bi); STATIC_INLINE int block_check_checksum(blockinfo* bi) { - uae_u32 c1,c2; - int isgood; + uae_u32 c1,c2; + int isgood; - if (bi->status!=BI_NEED_CHECK) + if (bi->status != BI_NEED_CHECK) return 1; /* This block is in a checked state */ // checksum_count++; if (bi->c1 || bi->c2) - calc_checksum(bi,&c1,&c2); + calc_checksum(bi, &c1, &c2); else { - c1=c2=1; /* Make sure it doesn't match */ + c1 = c2 = 1; /* Make sure it doesn't match */ } - isgood=(c1==bi->c1 && c2==bi->c2); + isgood = (c1 == bi->c1 && c2 == bi->c2); - if (isgood) { + if (isgood) { /* This block is still OK. So we reactivate. Of course, that means we have to move it into the needs-to-be-flushed list */ - bi->handler_to_use=bi->handler; - set_dhtu(bi,bi->direct_handler); + bi->handler_to_use = bi->handler; + set_dhtu(bi, bi->direct_handler); - bi->status=BI_CHECKING; - isgood=called_check_checksum(bi) != 0; + bi->status = BI_CHECKING; + isgood = called_check_checksum(bi) != 0; } if (isgood) { - D2(bug("JIT: reactivate %p/%p (%x %x/%x %x)",bi,bi->pc_p, c1,c2,bi->c1,bi->c2)); + D2(bug("JIT: reactivate %p/%p (%x %x/%x %x)", bi, bi->pc_p, c1, c2, bi->c1, bi->c2)); remove_from_list(bi); add_to_active(bi); raise_in_cl_list(bi); - bi->status=BI_ACTIVE; + bi->status = BI_ACTIVE; } else { /* This block actually changed. We need to invalidate it, and set it up to be recompiled */ - D2(bug("JIT: discard %p/%p (%x %x/%x %x)",bi,bi->pc_p, c1,c2,bi->c1,bi->c2)); + D2(bug("JIT: discard %p/%p (%x %x/%x %x)", bi, bi->pc_p, c1, c2, bi->c1, bi->c2)); invalidate_block(bi); raise_in_cl_list(bi); } @@ -2563,12 +2521,12 @@ STATIC_INLINE int block_check_checksum(blockinfo* bi) static int called_check_checksum(blockinfo* bi) { - int isgood=1; + int isgood = 1; int i; - for (i=0;i<2 && isgood;i++) { + for (i = 0; i < 2 && isgood; i++) { if (bi->dep[i].jmp_off) { - isgood=block_check_checksum(bi->dep[i].target); + isgood = block_check_checksum(bi->dep[i].target); } } return isgood; @@ -2576,9 +2534,9 @@ static int called_check_checksum(blockinfo* bi) static void check_checksum(void) { - blockinfo* bi=get_blockinfo_addr(regs.pc_p); - uae_u32 cl=cacheline(regs.pc_p); - blockinfo* bi2=get_blockinfo(cl); + blockinfo* bi = get_blockinfo_addr(regs.pc_p); + uae_u32 cl = cacheline(regs.pc_p); + blockinfo* bi2 = get_blockinfo(cl); /* These are not the droids you are looking for... */ if (!bi) { @@ -2588,7 +2546,7 @@ static void check_checksum(void) execute_normal(); return; } - if (bi!=bi2) { + if (bi != bi2) { /* The block was hit accidentally, but it does exist. Cache miss */ cache_miss(); return; @@ -2601,18 +2559,18 @@ static void check_checksum(void) STATIC_INLINE void match_states(blockinfo* bi) { int i; - smallstate* s=&(bi->env); + smallstate* s = &(bi->env); - if (bi->status==BI_NEED_CHECK) { + if (bi->status == BI_NEED_CHECK) { block_check_checksum(bi); } - if (bi->status==BI_ACTIVE || - bi->status==BI_FINALIZING) { /* Deal with the *promises* the + if (bi->status == BI_ACTIVE || + bi->status == BI_FINALIZING) { /* Deal with the *promises* the block makes (about not using certain vregs) */ - for (i=0;i<16;i++) { - if (s->virt[i]==L_UNNEEDED) { - D2(panicbug("unneeded reg %d at %p\n",i,target)); + for (i = 0; i < 16; i++) { + if (s->virt[i] == L_UNNEEDED) { + D2(panicbug("unneeded reg %d at %p\n", i, target)); COMPCALL(forget_about)(i); // FIXME } } @@ -2620,18 +2578,18 @@ STATIC_INLINE void match_states(blockinfo* bi) flush(1); /* And now deal with the *demands* the block makes */ - for (i=0;inat[i]; - if (v>=0) { + for (i = 0; i < N_REGS; i++) { + int v = s->nat[i]; + if (v >= 0) { // printf("Loading reg %d into %d at %p\n",v,i,target); - readreg_specific(v,4,i); + readreg_specific(v, 4, i); // do_load_reg(i,v); // setlock(i); } } - for (i=0;inat[i]; - if (v>=0) { + for (i = 0; i < N_REGS; i++) { + int v = s->nat[i]; + if (v >= 0) { unlock2(i); } } @@ -2639,27 +2597,27 @@ STATIC_INLINE void match_states(blockinfo* bi) STATIC_INLINE void create_popalls(void) { - int i,r; + int i, r; if (popallspace == NULL) popallspace = (uae_u8*)cache_alloc (POPALLSPACE_SIZE); int stack_space = STACK_OFFSET; - for (i=0;idirect_pen=(cpuop_func *)get_target(); - compemu_raw_mov_l_rm(0,(uintptr)&(bi->pc_p)); - compemu_raw_mov_l_mr((uintptr)®s.pc_p,0); + bi->direct_pen = (cpuop_func *)get_target(); + compemu_raw_mov_l_rm(0, (uintptr)&(bi->pc_p)); + compemu_raw_mov_l_mr((uintptr)®s.pc_p, 0); compemu_raw_jmp((uintptr)popall_execute_normal); #ifndef ALIGN_NOT_NEEDED align_target(align_jumps); #endif - bi->direct_pcc=(cpuop_func *)get_target(); - compemu_raw_mov_l_rm(0,(uintptr)&(bi->pc_p)); - compemu_raw_mov_l_mr((uintptr)®s.pc_p,0); + bi->direct_pcc = (cpuop_func *)get_target(); + compemu_raw_mov_l_rm(0, (uintptr)&(bi->pc_p)); + compemu_raw_mov_l_mr((uintptr)®s.pc_p, 0); compemu_raw_jmp((uintptr)popall_check_checksum); flush_cpu_icache((void *)current_compile_p, (void *)target); - current_compile_p=get_target(); + current_compile_p = get_target(); - bi->deplist=NULL; - for (i=0;i<2;i++) { - bi->dep[i].prev_p=NULL; - bi->dep[i].next=NULL; + bi->deplist = NULL; + for (i = 0; i < 2; i++) { + bi->dep[i].prev_p = NULL; + bi->dep[i].next = NULL; } - bi->env=default_ss; - bi->status=BI_INVALID; - bi->havestate=0; + bi->env = default_ss; + bi->status = BI_INVALID; + bi->havestate = 0; //bi->env=empty_ss; } @@ -2798,8 +2756,8 @@ void build_comp(void) { int i; unsigned long opcode; - const struct comptbl* tbl=op_smalltbl_0_comp_ff; - const struct comptbl* nftbl=op_smalltbl_0_comp_nf; + const struct comptbl* tbl = op_smalltbl_0_comp_ff; + const struct comptbl* nftbl = op_smalltbl_0_comp_nf; int count; #ifdef NOFLAGS_SUPPORT struct comptbl *nfctbl = (currprefs.cpu_level >= 5 ? op_smalltbl_0_nf @@ -2858,7 +2816,7 @@ void build_comp(void) #ifdef NOFLAGS_SUPPORT cpuop_func *nfcf; #endif - int isaddx,cflow; + int isaddx, cflow; int cpu_level = (currprefs.cpu_model - 68000) / 10; if (cpu_level > 4) @@ -2896,7 +2854,7 @@ void build_comp(void) } #endif - count=0; + count = 0; for (opcode = 0; opcode < 65536; opcode++) { if (compfunctbl[cft_map(opcode)]) count++; @@ -2908,19 +2866,19 @@ void build_comp(void) alloc_cache(); reset_lists(); - for (i=0;ipc_p)].handler=(cpuop_func *)popall_execute_normal; - cache_tags[cacheline(bi->pc_p)+1].bi=NULL; - dbi=bi; bi=bi->next; + cache_tags[cacheline(bi->pc_p)].handler = (cpuop_func *)popall_execute_normal; + cache_tags[cacheline(bi->pc_p)+1].bi = NULL; + dbi = bi; + bi = bi->next; free_blockinfo(dbi); } - bi=dormant; + bi = dormant; while(bi) { - cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func *)popall_execute_normal; - cache_tags[cacheline(bi->pc_p)+1].bi=NULL; - dbi=bi; bi=bi->next; + cache_tags[cacheline(bi->pc_p)].handler = (cpuop_func *)popall_execute_normal; + cache_tags[cacheline(bi->pc_p)+1].bi = NULL; + dbi = bi; + bi = bi->next; free_blockinfo(dbi); } @@ -2955,11 +2915,11 @@ static void flush_icache_hard(uaecptr ptr, int n) if (!compiled_code) return; -#if defined(CPU_arm) +#if defined(CPU_arm) && !defined(ARMV6T2) reset_data_buffer(); #endif - current_compile_p=compiled_code; + current_compile_p = compiled_code; set_special(regs, 0); /* To get out of compiled code */ } @@ -2977,35 +2937,35 @@ STATIC_INLINE void flush_icache_lazy(uaecptr ptr, int n) if (!active) return; - bi=active; + bi = active; while (bi) { - uae_u32 cl=cacheline(bi->pc_p); - if (bi->status==BI_INVALID || - bi->status==BI_NEED_RECOMP) { - if (bi==cache_tags[cl+1].bi) + uae_u32 cl = cacheline(bi->pc_p); + if (bi->status == BI_INVALID || + bi->status == BI_NEED_RECOMP) { + if (bi == cache_tags[cl+1].bi) cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; bi->handler_to_use = (cpuop_func *)popall_execute_normal; set_dhtu(bi,bi->direct_pen); - bi->status=BI_INVALID; + bi->status = BI_INVALID; } else { - if (bi==cache_tags[cl+1].bi) + if (bi == cache_tags[cl+1].bi) cache_tags[cl].handler = (cpuop_func *)popall_check_checksum; bi->handler_to_use = (cpuop_func *)popall_check_checksum; set_dhtu(bi,bi->direct_pcc); - bi->status=BI_NEED_CHECK; + bi->status = BI_NEED_CHECK; } - bi2=bi; - bi=bi->next; + bi2 = bi; + bi = bi->next; } /* bi2 is now the last entry in the active list */ - bi2->next=dormant; + bi2->next = dormant; if (dormant) - dormant->prev_p=&(bi2->next); + dormant->prev_p = &(bi2->next); - dormant=active; - active->prev_p=&dormant; - active=NULL; + dormant = active; + active->prev_p = &dormant; + active = NULL; } int failure; @@ -3051,7 +3011,7 @@ void compiler_dumpstate(void) void compile_block(cpu_history* pc_hist, int blocklen, int totcycles) { - if (letit && compiled_code && currprefs.cpu_model>=68020) { + if (letit && compiled_code && currprefs.cpu_model >= 68020) { #ifdef PROFILE_COMPILE_TIME compile_count++; clock_t start_time = clock(); @@ -3063,92 +3023,92 @@ void compile_block(cpu_history* pc_hist, int blocklen, int totcycles) /* OK, here we need to 'compile' a block */ int i; int r; - int was_comp=0; + int was_comp = 0; uae_u8 liveflags[MAXRUN+1]; #if USE_CHECKSUM_INFO bool trace_in_rom = isinrom((uintptr)pc_hist[0].location); - uintptr max_pcp=(uintptr)pc_hist[blocklen - 1].location; - uintptr min_pcp=max_pcp; + uintptr max_pcp = (uintptr)pc_hist[blocklen - 1].location; + uintptr min_pcp = max_pcp; #else - uintptr max_pcp=(uintptr)pc_hist[0].location; - uintptr min_pcp=max_pcp; + uintptr max_pcp = (uintptr)pc_hist[0].location; + uintptr min_pcp = max_pcp; #endif - uae_u32 cl=cacheline(pc_hist[0].location); - void* specflags=(void*)®s.spcflags; - blockinfo* bi=NULL; + uae_u32 cl = cacheline(pc_hist[0].location); + void* specflags = (void*)®s.spcflags; + blockinfo* bi = NULL; blockinfo* bi2; - int extra_len=0; + int extra_len = 0; - redo_current_block=0; - if (current_compile_p>=MAX_COMPILE_PTR) + redo_current_block = 0; + if (current_compile_p >= MAX_COMPILE_PTR) flush_icache_hard(0, 3); alloc_blockinfos(); - bi=get_blockinfo_addr_new(pc_hist[0].location,0); - bi2=get_blockinfo(cl); + bi = get_blockinfo_addr_new(pc_hist[0].location, 0); + bi2 = get_blockinfo(cl); - optlev=bi->optlevel; - if (bi->status!=BI_INVALID) { - Dif (bi!=bi2) { + optlev = bi->optlevel; + if (bi->status != BI_INVALID) { + Dif (bi != bi2) { /* I don't think it can happen anymore. Shouldn't, in any case. So let's make sure... */ jit_abort (_T("JIT: WOOOWOO count=%d, ol=%d %p %p\n"), - bi->count,bi->optlevel,bi->handler_to_use, + bi->count, bi->optlevel, bi->handler_to_use, cache_tags[cl].handler); } - Dif (bi->count!=-1 && bi->status!=BI_NEED_RECOMP) { - panicbug("bi->count=%d, bi->status=%d,bi->optlevel=%d\n",bi->count,bi->status,bi->optlevel); + Dif (bi->count != -1 && bi->status != BI_NEED_RECOMP) { + panicbug("bi->count=%d, bi->status=%d,bi->optlevel=%d\n", bi->count, bi->status, bi->optlevel); /* What the heck? We are not supposed to be here! */ jit_abort(_T("BI_TARGETTED")); } } - if (bi->count==-1) { + if (bi->count == -1) { optlev++; while (!currprefs.optcount[optlev]) optlev++; - bi->count=currprefs.optcount[optlev]-1; + bi->count = currprefs.optcount[optlev] - 1; } - current_block_pc_p=(uintptr)pc_hist[0].location; + current_block_pc_p = (uintptr)pc_hist[0].location; remove_deps(bi); /* We are about to create new code */ - bi->optlevel=optlev; - bi->pc_p=(uae_u8*)pc_hist[0].location; + bi->optlevel = optlev; + bi->pc_p = (uae_u8*)pc_hist[0].location; #if USE_CHECKSUM_INFO free_checksum_info_chain(bi->csi); bi->csi = NULL; #endif - liveflags[blocklen]=0x1f; /* All flags needed afterwards */ - i=blocklen; + liveflags[blocklen] = 0x1f; /* All flags needed afterwards */ + i = blocklen; while (i--) { - uae_u16* currpcp=pc_hist[i].location; - uae_u32 op=DO_GET_OPCODE(currpcp); + uae_u16* currpcp = pc_hist[i].location; + uae_u32 op = DO_GET_OPCODE(currpcp); #if USE_CHECKSUM_INFO - trace_in_rom = trace_in_rom && isinrom((uintptr)currpcp); - if (follow_const_jumps && is_const_jump(op)) { - checksum_info *csi = alloc_checksum_info(); - csi->start_p = (uae_u8 *)min_pcp; - csi->length = max_pcp - min_pcp + LONGEST_68K_INST; - csi->next = bi->csi; - bi->csi = csi; - max_pcp = (uintptr)currpcp; - } - min_pcp = (uintptr)currpcp; + trace_in_rom = trace_in_rom && isinrom((uintptr)currpcp); + if (follow_const_jumps && is_const_jump(op)) { + checksum_info *csi = alloc_checksum_info(); + csi->start_p = (uae_u8 *)min_pcp; + csi->length = max_pcp - min_pcp + LONGEST_68K_INST; + csi->next = bi->csi; + bi->csi = csi; + max_pcp = (uintptr)currpcp; + } + min_pcp = (uintptr)currpcp; #else - if ((uintptr)currpcpmax_pcp) - max_pcp=(uintptr)currpcp; + if ((uintptr)currpcp < min_pcp) + min_pcp=(uintptr)currpcp; + if ((uintptr)currpcp > max_pcp) + max_pcp=(uintptr)currpcp; #endif - liveflags[i]=((liveflags[i+1]& - (~prop[op].set_flags))| + liveflags[i] = ((liveflags[i+1] & + (~prop[op].set_flags)) | prop[op].use_flags); - if (prop[op].is_addx && (liveflags[i+1]&FLAG_Z)==0) - liveflags[i]&= ~FLAG_Z; + if (prop[op].is_addx && (liveflags[i+1] & FLAG_Z) == 0) + liveflags[i] &= ~FLAG_Z; } #if USE_CHECKSUM_INFO @@ -3159,318 +3119,286 @@ void compile_block(cpu_history* pc_hist, int blocklen, int totcycles) bi->csi = csi; #endif - bi->needed_flags=liveflags[0]; + bi->needed_flags = liveflags[0]; /* This is the non-direct handler */ #ifndef ALIGN_NOT_NEEDED align_target(align_loops); #endif - was_comp=0; + was_comp = 0; - bi->direct_handler=(cpuop_func *)get_target(); + bi->direct_handler = (cpuop_func *)get_target(); set_dhtu(bi,bi->direct_handler); - bi->status=BI_COMPILING; - current_block_start_target=(uintptr)get_target(); + bi->status = BI_COMPILING; + current_block_start_target = (uintptr)get_target(); - if (bi->count>=0) { /* Need to generate countdown code */ - compemu_raw_mov_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); - compemu_raw_sub_l_mi((uintptr)&(bi->count),1); + if (bi->count >= 0) { /* Need to generate countdown code */ + compemu_raw_mov_l_mi((uintptr)®s.pc_p, (uintptr)pc_hist[0].location); + compemu_raw_sub_l_mi((uintptr)&(bi->count), 1); compemu_raw_jl((uintptr)popall_recompile_block); } - if (optlev==0) { /* No need to actually translate */ + if (optlev == 0) { /* No need to actually translate */ /* Execute normally without keeping stats */ - compemu_raw_mov_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); + compemu_raw_mov_l_mi((uintptr)®s.pc_p, (uintptr)pc_hist[0].location); compemu_raw_jmp((uintptr)popall_exec_nostats); } else { -// reg_alloc_run=0; - next_pc_p=0; - taken_pc_p=0; - branch_cc=0; // Only to be initialized. Will be set together with next_pc_p + next_pc_p = 0; + taken_pc_p = 0; + branch_cc = 0; // Only to be initialized. Will be set together with next_pc_p - comp_pc_p=(uae_u8*)pc_hist[0].location; + comp_pc_p = (uae_u8*)pc_hist[0].location; init_comp(); - was_comp=1; + was_comp = 1; #ifdef JIT_DEBUG if (JITDebug) { - compemu_raw_mov_l_mi((uintptr)&last_regs_pc_p,(uintptr)pc_hist[0].location); - compemu_raw_mov_l_mi((uintptr)&last_compiled_block_addr,current_block_start_target); + compemu_raw_mov_l_mi((uintptr)&last_regs_pc_p, (uintptr)pc_hist[0].location); + compemu_raw_mov_l_mi((uintptr)&last_compiled_block_addr, current_block_start_target); } #endif - for (i=0;i1) { - failure=0; - if (!was_comp) { - comp_pc_p=(uae_u8*)pc_hist[i].location; - init_comp(); + comptbl=nfcompfunctbl; } - was_comp=1; - - comptbl[opcode](opcode); - freescratch(); - if (!(liveflags[i+1] & FLAG_CZNV)) { - /* We can forget about flags */ - dont_care_flags(); + else { + cputbl = cpufunctbl; + comptbl = compfunctbl; } + + failure = 1; // gb-- defaults to failure state + if (comptbl[opcode] && optlev > 1) { + failure = 0; + if (!was_comp) { + comp_pc_p = (uae_u8*)pc_hist[i].location; + init_comp(); + } + was_comp = 1; + + comptbl[opcode](opcode); + freescratch(); + if (!(liveflags[i+1] & FLAG_CZNV)) { + /* We can forget about flags */ + dont_care_flags(); + } #if INDIVIDUAL_INST - flush(1); - nop(); - flush(1); - was_comp=0; + flush(1); + nop(); + flush(1); + was_comp = 0; #endif - } - if (failure) { - if (was_comp) { - flush(1); - was_comp=0; - } - compemu_raw_mov_l_ri(REG_PAR1,(uae_u32)opcode); - compemu_raw_mov_l_ri(REG_PAR2,(uae_u32)®s); - - compemu_raw_mov_l_mi((uintptr)®s.pc_p, (uintptr)pc_hist[i].location); - compemu_raw_call((uintptr)cputbl[opcode]); + } + if (failure) { + if (was_comp) { + flush(1); + was_comp = 0; + } + compemu_raw_mov_l_ri(REG_PAR1, (uae_u32)opcode); + compemu_raw_mov_l_ri(REG_PAR2, (uae_u32)®s); + compemu_raw_mov_l_mi((uintptr)®s.pc_p, (uintptr)pc_hist[i].location); + compemu_raw_call((uintptr)cputbl[opcode]); #ifdef PROFILE_UNTRANSLATED_INSNS - // raw_cputbl_count[] is indexed with plain opcode (in m68k order) - compemu_raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1); -#endif - - if (ineeded_flags; - - if (x==0xff || 1) { /* To be on the safe side */ - uae_u16* next=(uae_u16*)next_pc_p; - uae_u32 op=DO_GET_OPCODE(next); - - x=0x1f; - x&=(~prop[op].set_flags); - x|=prop[op].use_flags; - } - - x|=bi2->needed_flags; - if (!(x & FLAG_CZNV)) { - /* We can forget about flags */ - dont_care_flags(); - extra_len+=2; /* The next instruction now is part of this - block */ - } - - } + // raw_cputbl_count[] is indexed with plain opcode (in m68k order) + compemu_raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)], 1); #endif - if (next_pc_p) { /* A branch was registered */ - uintptr t1=next_pc_p; - uintptr t2=taken_pc_p; - int cc=branch_cc; + if (i < blocklen - 1) { + uae_s8* branchadd; + + compemu_raw_mov_l_rm(0, (uintptr)specflags); + compemu_raw_test_l_rr(0, 0); +#if defined(CPU_arm) && !defined(ARMV6T2) + data_check_end(8, 56); +#endif + compemu_raw_jz_b_oponly(); + branchadd = (uae_s8 *)get_target(); + compemu_raw_sub_l_mi((uintptr)&countdown, scaled_cycles(totcycles)); + compemu_raw_jmp((uintptr)popall_do_nothing); + *(branchadd - 4) = (((uintptr)get_target() - (uintptr)branchadd) - 4) >> 2; + D(bug(" branchadd(byte) to 0x%08x: 0x%02x\n", branchadd, *branchadd)); + } + } + } - uae_u32* branchadd; - uae_u32* tba; - bigstate tmp; - blockinfo* tbi; - - if (taken_pc_pcsi); - bi->csi = NULL; - add_to_dormant(bi); - } - else { - calc_checksum(bi,&(bi->c1),&(bi->c2)); - add_to_active(bi); - } + remove_from_list(bi); + if (trace_in_rom) { + // No need to checksum that block trace on cache invalidation + free_checksum_info_chain(bi->csi); + bi->csi = NULL; + add_to_dormant(bi); + } + else { + calc_checksum(bi, &(bi->c1), &(bi->c2)); + add_to_active(bi); + } #else - if (next_pc_p+extra_len>=max_pcp && - next_pc_p+extra_lenlen=max_pcp-min_pcp; - bi->min_pcp=min_pcp; - - remove_from_list(bi); - if (isinrom(min_pcp) && isinrom(max_pcp)) { - add_to_dormant(bi); /* No need to checksum it on cache flush. - Please don't start changing ROMs in - flight! */ - } - else { - calc_checksum(bi,&(bi->c1),&(bi->c2)); - add_to_active(bi); - } + if (next_pc_p + extra_len >= max_pcp && next_pc_p + extra_len < max_pcp + LONGEST_68K_INST) + max_pcp = next_pc_p + extra_len; /* extra_len covers flags magic */ + else + max_pcp += LONGEST_68K_INST; + + bi->len = max_pcp - min_pcp; + bi->min_pcp = min_pcp; + + remove_from_list(bi); + if (isinrom(min_pcp) && isinrom(max_pcp)) { + add_to_dormant(bi); /* No need to checksum it on cache flush. + Please don't start changing ROMs in + flight! */ + } + else { + calc_checksum(bi, &(bi->c1), &(bi->c2)); + add_to_active(bi); + } #endif - current_cache_size += get_target() - (uae_u8 *)current_compile_p; + current_cache_size += get_target() - (uae_u8 *)current_compile_p; #ifdef JIT_DEBUG - if (JITDebug) - bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target; + if (JITDebug) + bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target; #endif #ifndef ALIGN_NOT_NEEDED - align_target(align_jumps); + align_target(align_jumps); #endif - /* This is the non-direct handler */ - bi->handler= - bi->handler_to_use=(cpuop_func *)get_target(); - compemu_raw_cmp_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); - compemu_raw_jnz((uintptr)popall_cache_miss); - comp_pc_p=(uae_u8*)pc_hist[0].location; + /* This is the non-direct handler */ + bi->handler = + bi->handler_to_use = (cpuop_func *)get_target(); + compemu_raw_cmp_l_mi((uintptr)®s.pc_p, (uintptr)pc_hist[0].location); + compemu_raw_jnz((uintptr)popall_cache_miss); + comp_pc_p = (uae_u8*)pc_hist[0].location; - bi->status=BI_FINALIZING; - init_comp(); - match_states(bi); - flush(1); + bi->status=BI_FINALIZING; + init_comp(); + match_states(bi); + flush(1); + + compemu_raw_jmp((uintptr)bi->direct_handler); - compemu_raw_jmp((uintptr)bi->direct_handler); + flush_cpu_icache((void *)current_block_start_target, (void *)target); + current_compile_p = get_target(); + raise_in_cl_list(bi); - flush_cpu_icache((void *)current_block_start_target, (void *)target); - current_compile_p=get_target(); - raise_in_cl_list(bi); + /* We will flush soon, anyway, so let's do it now */ + if (current_compile_p >= MAX_COMPILE_PTR) + flush_icache_hard(0, 3); - /* We will flush soon, anyway, so let's do it now */ - if (current_compile_p>=MAX_COMPILE_PTR) - flush_icache_hard(0, 3); - - bi->status=BI_ACTIVE; - if (redo_current_block) - block_need_recompile(bi); + bi->status = BI_ACTIVE; + if (redo_current_block) + block_need_recompile(bi); #ifdef PROFILE_COMPILE_TIME - compile_time += (clock() - start_time); + compile_time += (clock() - start_time); #endif } } diff --git a/src/kb-sdl/keyboard.cpp b/src/kb-sdl/keyboard.cpp index 5f477320..7e42cbc2 100644 --- a/src/kb-sdl/keyboard.cpp +++ b/src/kb-sdl/keyboard.cpp @@ -169,7 +169,7 @@ static int kc_decode (SDL_keysym *prKeySym) // In case are in unknown driver type... we can still rely on keysym... -#ifdef PANDORA +#ifdef PANDORA_SPECIFIC // Special handling of Pandora keyboard: // Some keys requires shift on Amiga, so we simulate shift... @@ -358,7 +358,7 @@ static int decode_de (SDL_keysym *prKeySym) case SDLK_w: return AK_W; case SDLK_y: return AK_Z; case SDLK_z: return AK_Y; - case SDLK_COLON: return SIMULATE_SHIFT | AK_SEMICOLON; + case SDLK_COLON: return AK_SEMICOLON; /* German umlaut oe */ case SDLK_WORLD_86: return AK_SEMICOLON; /* German umlaut ae */ @@ -393,7 +393,7 @@ static int decode_us (SDL_keysym *prKeySym) case SDLK_y: return AK_Y; case SDLK_w: return AK_W; case SDLK_z: return AK_Z; - case SDLK_COLON: return SIMULATE_SHIFT | AK_SEMICOLON; + case SDLK_COLON: return AK_SEMICOLON; case SDLK_LEFTBRACKET: return AK_LBRACKET; case SDLK_RIGHTBRACKET: return AK_RBRACKET; case SDLK_COMMA: return AK_COMMA; diff --git a/src/keybuf.cpp b/src/keybuf.cpp index 85adaaea..e4bcd08b 100644 --- a/src/keybuf.cpp +++ b/src/keybuf.cpp @@ -21,8 +21,8 @@ #include "keyboard.h" #include "memory.h" #include "newcpu.h" -#include "custom.h" #include "inputdevice.h" +#include "custom.h" #include "savestate.h" static int kpb_first, kpb_last; @@ -68,10 +68,6 @@ int record_key (int kc) return 1; } -void joystick_setting_changed (void) -{ -} - void keybuf_init (void) { kpb_first = kpb_last = 0; diff --git a/src/linetoscr.c b/src/linetoscr.c index 66760e27..a7cfa0c6 100644 --- a/src/linetoscr.c +++ b/src/linetoscr.c @@ -3,6 +3,22 @@ * colors_for_drawing.acolors (non AGA) contains 16-bit color information in both words * colors_for_drawing.acolors (AGA) contains 16-bit color information in one word */ + +STATIC_INLINE uae_u32 merge_words(uae_u32 val, uae_u32 val2) +{ + __asm__ __volatile__ ( + "pkhbt %[o], %[o], %[d], lsl #16 \n\t" + : [o] "+r" (val) : [d] "r" (val2) ); + return val; +} + +STATIC_INLINE uae_u32 double_word(uae_u32 val) +{ + __asm__ __volatile__ ( + "pkhbt %[o], %[o], %[o], lsl #16 \n\t" + : [o] "+r" (val) ); + return val; +} static int NOINLINE linetoscr_16 (int spix, int dpix, int stoppos) { @@ -11,7 +27,7 @@ static int NOINLINE linetoscr_16 (int spix, int dpix, int stoppos) if (dp_for_drawing->ham_seen) { int rem; if (((long)&buf[dpix]) & 2) { - buf[dpix++] = xcolors[ham_linebuf[spix++]]; + buf[dpix++] = ham_linebuf[spix++]; } if (dpix >= stoppos) return spix; @@ -19,23 +35,15 @@ static int NOINLINE linetoscr_16 (int spix, int dpix, int stoppos) if (rem) stoppos--; while (dpix < stoppos) { - uae_u32 dpix_val; uae_u32 out_val; - out_val = xcolors[ham_linebuf[spix++]]; - dpix_val = xcolors[ham_linebuf[spix++]]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif + out_val = *((uae_u32 *)&ham_linebuf[spix]); + spix += 2; *((uae_u32 *)&buf[dpix]) = out_val; dpix += 2; } if (rem) { - buf[dpix++] = xcolors[ham_linebuf[spix++]]; + buf[dpix++] = ham_linebuf[spix++]; } } else if (bpldualpf) { int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; @@ -59,14 +67,7 @@ static int NOINLINE linetoscr_16 (int spix, int dpix, int stoppos) out_val = colors_for_drawing.acolors[lookup[spix_val]]; spix_val = pixdata.apixels[spix++]; dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -106,14 +107,7 @@ static int NOINLINE linetoscr_16 (int spix, int dpix, int stoppos) dpix_val = colors_for_drawing.acolors[spix_val]; else dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -147,14 +141,7 @@ static int NOINLINE linetoscr_16 (int spix, int dpix, int stoppos) out_val = colors_for_drawing.acolors[spix_val]; spix_val = pixdata.apixels[spix++]; dpix_val = colors_for_drawing.acolors[spix_val]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -173,7 +160,8 @@ static int NOINLINE linetoscr_16_stretch1 (int spix, int dpix, int stoppos) if (dp_for_drawing->ham_seen) { while (dpix < stoppos) { - *((uae_u32 *)&buf[dpix]) = xcolors[ham_linebuf[spix++]]; + uae_u32 out_val = ham_linebuf[spix++]; + *((uae_u32 *)&buf[dpix]) = double_word(out_val); dpix += 2; } } else if (bpldualpf) { @@ -194,15 +182,8 @@ static int NOINLINE linetoscr_16_stretch1 (int spix, int dpix, int stoppos) if (spix_val <= 31) out_val = colors_for_drawing.acolors[spix_val]; else - out_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x0777]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (out_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[o], lsl #16 \n\t" - : [o] "+r" (out_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + out_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x0777]; + *((uae_u32 *)&buf[dpix]) = double_word(out_val); dpix += 2; } } else { @@ -226,7 +207,7 @@ static int NOINLINE linetoscr_16_shrink1 (int spix, int dpix, int stoppos) int rem; if (((long)&buf[dpix]) & 2) { uae_u32 dpix_val; - dpix_val = xcolors[ham_linebuf[spix]]; + dpix_val = ham_linebuf[spix]; spix += 2; buf[dpix++] = dpix_val; } @@ -239,23 +220,18 @@ static int NOINLINE linetoscr_16_shrink1 (int spix, int dpix, int stoppos) uae_u32 dpix_val; uae_u32 out_val; - out_val = xcolors[ham_linebuf[spix]]; + out_val = ham_linebuf[spix]; spix += 2; - dpix_val = xcolors[ham_linebuf[spix]]; + dpix_val = ham_linebuf[spix]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif + out_val = merge_words(out_val, dpix_val); + *((uae_u32 *)&buf[dpix]) = out_val; dpix += 2; } if (rem) { uae_u32 dpix_val; - dpix_val = xcolors[ham_linebuf[spix]]; + dpix_val = ham_linebuf[spix]; spix += 2; buf[dpix++] = dpix_val; } @@ -286,14 +262,7 @@ static int NOINLINE linetoscr_16_shrink1 (int spix, int dpix, int stoppos) spix_val = pixdata.apixels[spix]; dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -339,14 +308,7 @@ static int NOINLINE linetoscr_16_shrink1 (int spix, int dpix, int stoppos) else dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -384,14 +346,7 @@ static int NOINLINE linetoscr_16_shrink1 (int spix, int dpix, int stoppos) spix_val = pixdata.apixels[spix]; dpix_val = colors_for_drawing.acolors[spix_val]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -406,6 +361,7 @@ static int NOINLINE linetoscr_16_shrink1 (int spix, int dpix, int stoppos) } #ifdef AGA + static int NOINLINE linetoscr_16_aga (int spix, int dpix, int stoppos) { uae_u16 *buf = (uae_u16 *) xlinebuffer; @@ -414,7 +370,7 @@ static int NOINLINE linetoscr_16_aga (int spix, int dpix, int stoppos) if (dp_for_drawing->ham_seen) { int rem; if (((long)&buf[dpix]) & 2) { - buf[dpix++] = CONVERT_RGB (ham_linebuf[spix]); + buf[dpix++] = ham_linebuf[spix]; spix++; } if (dpix >= stoppos) @@ -423,25 +379,15 @@ static int NOINLINE linetoscr_16_aga (int spix, int dpix, int stoppos) if (rem) stoppos--; while (dpix < stoppos) { - uae_u32 dpix_val; uae_u32 out_val; - out_val = CONVERT_RGB (ham_linebuf[spix]); - spix++; - dpix_val = CONVERT_RGB (ham_linebuf[spix]); - spix++; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif + out_val = *((uae_u32 *)&ham_linebuf[spix]); + spix += 2; *((uae_u32 *)&buf[dpix]) = out_val; dpix += 2; } if (rem) { - buf[dpix++] = CONVERT_RGB (ham_linebuf[spix]); + buf[dpix++] = ham_linebuf[spix]; spix++; } } else if (bpldualpf) { @@ -496,14 +442,7 @@ static int NOINLINE linetoscr_16_aga (int spix, int dpix, int stoppos) dpix_val = colors_for_drawing.acolors[val]; } spix++; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -557,14 +496,7 @@ static int NOINLINE linetoscr_16_aga (int spix, int dpix, int stoppos) dpix_val = CONVERT_RGB (c); } else dpix_val = colors_for_drawing.acolors[spix_val]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -599,14 +531,7 @@ static int NOINLINE linetoscr_16_aga (int spix, int dpix, int stoppos) out_val = colors_for_drawing.acolors[spix_val]; spix_val = pixdata.apixels[spix++] ^ xor_val; dpix_val = colors_for_drawing.acolors[spix_val]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -628,19 +553,9 @@ static int NOINLINE linetoscr_16_stretch1_aga (int spix, int dpix, int stoppos) if (dp_for_drawing->ham_seen) { while (dpix < stoppos) { - uae_u32 spix_val; uae_u32 out_val; - - spix_val = pixdata.apixels[spix++] ^ xor_val; - out_val = CONVERT_RGB (ham_linebuf[spix]); -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (out_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[o], lsl #16 \n\t" - : [o] "+r" (out_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + out_val = ham_linebuf[spix++]; + *((uae_u32 *)&buf[dpix]) = double_word(out_val); dpix += 2; } } else if (bpldualpf) { @@ -661,14 +576,7 @@ static int NOINLINE linetoscr_16_stretch1_aga (int spix, int dpix, int stoppos) out_val = colors_for_drawing.acolors[val]; } spix++; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (out_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[o], lsl #16 \n\t" - : [o] "+r" (out_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = double_word(out_val); dpix += 2; } } else if (bplehb) { @@ -682,14 +590,7 @@ static int NOINLINE linetoscr_16_stretch1_aga (int spix, int dpix, int stoppos) out_val = CONVERT_RGB (c); } else out_val = colors_for_drawing.acolors[spix_val]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (out_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[o], lsl #16 \n\t" - : [o] "+r" (out_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = double_word(out_val); dpix += 2; } } else { @@ -699,14 +600,7 @@ static int NOINLINE linetoscr_16_stretch1_aga (int spix, int dpix, int stoppos) spix_val = pixdata.apixels[spix++] ^ xor_val; out_val = colors_for_drawing.acolors[spix_val]; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (out_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[o], lsl #16 \n\t" - : [o] "+r" (out_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = double_word(out_val); dpix += 2; } } @@ -724,7 +618,7 @@ static int NOINLINE linetoscr_16_shrink1_aga (int spix, int dpix, int stoppos) if (dp_for_drawing->ham_seen) { int rem; if (((long)&buf[dpix]) & 2) { - buf[dpix++] = CONVERT_RGB (ham_linebuf[spix]); + buf[dpix++] = ham_linebuf[spix]; spix += 2; } if (dpix >= stoppos) @@ -736,22 +630,16 @@ static int NOINLINE linetoscr_16_shrink1_aga (int spix, int dpix, int stoppos) uae_u32 dpix_val; uae_u32 out_val; - out_val = CONVERT_RGB (ham_linebuf[spix]); + out_val = ham_linebuf[spix]; spix += 2; - dpix_val = CONVERT_RGB (ham_linebuf[spix]); + dpix_val = ham_linebuf[spix]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif + out_val = merge_words(out_val, dpix_val); *((uae_u32 *)&buf[dpix]) = out_val; dpix += 2; } if (rem) { - buf[dpix++] = CONVERT_RGB (ham_linebuf[spix]); + buf[dpix++] = ham_linebuf[spix]; spix += 2; } } else if (bpldualpf) { @@ -806,14 +694,7 @@ static int NOINLINE linetoscr_16_shrink1_aga (int spix, int dpix, int stoppos) dpix_val = colors_for_drawing.acolors[val]; } spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -870,14 +751,7 @@ static int NOINLINE linetoscr_16_shrink1_aga (int spix, int dpix, int stoppos) } else dpix_val = colors_for_drawing.acolors[spix_val]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { @@ -916,14 +790,7 @@ static int NOINLINE linetoscr_16_shrink1_aga (int spix, int dpix, int stoppos) spix_val = pixdata.apixels[spix] ^ xor_val; dpix_val = colors_for_drawing.acolors[spix_val]; spix += 2; -#ifndef ARMV6_ASSEMBLY - out_val = (out_val & 0xFFFF) | (dpix_val << 16); -#else - __asm__ __volatile__ ( - "pkhbt %[o], %[o], %[d], lsl #16 \n\t" - : [o] "+r" (out_val) : [d] "r" (dpix_val) ); -#endif - *((uae_u32 *)&buf[dpix]) = out_val; + *((uae_u32 *)&buf[dpix]) = merge_words(out_val, dpix_val); dpix += 2; } if (rem) { diff --git a/src/main.cpp b/src/main.cpp index 7e29bf67..e647440a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,8 +32,10 @@ #include "bsdsocket.h" #include "drawing.h" #include "native2amiga.h" +#include "akiko.h" #include "savestate.h" #include "filesys.h" +#include "blkdev.h" #include "uaeresource.h" #ifdef JIT #include "jit/compemu.h" @@ -273,12 +275,16 @@ void fixup_prefs (struct uae_prefs *p) #if !defined (BSDSOCKET) p->socket_emu = 0; #endif + + blkdev_fix_prefs (p); + target_fixup_options (p); } int quit_program = 0; static int restart_program; static TCHAR restart_config[MAX_DPATH]; +static int default_config; void uae_reset (int hardreset) { @@ -302,6 +308,7 @@ void uae_restart (int opengui, TCHAR *cfgfile) uae_quit (); restart_program = opengui > 0 ? 1 : (opengui == 0 ? 2 : 3); restart_config[0] = 0; + default_config = 0; if (cfgfile) _tcscpy (restart_config, cfgfile); } @@ -404,7 +411,7 @@ static void parse_cmdline_and_init_file (int argc, TCHAR **argv) _tcscat (optionsfile, restart_config); - if (! target_cfgfile_load (&currprefs, optionsfile, 0, 0)) { + if (! target_cfgfile_load (&currprefs, optionsfile, 0, default_config)) { write_log (_T("failed to load config '%s'\n"), optionsfile); } fixup_prefs (&currprefs); @@ -463,6 +470,9 @@ void do_leave_program (void) inputdevice_close (); DISK_free (); close_sound (); +#ifdef CD32 + akiko_free (); +#endif gui_exit (); #ifdef USE_SDL SDL_Quit (); @@ -477,6 +487,7 @@ void do_leave_program (void) #ifdef BSDSOCKET bsdlib_reset (); #endif + device_func_reset (); memory_cleanup (); cfgfile_addcfgparam (0); machdep_free (); @@ -498,7 +509,7 @@ static int real_main2 (int argc, TCHAR **argv) printf("Uae4arm v0.5 for Raspberry Pi by Chips\n"); #endif #ifdef PANDORA - SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE | SDL_INIT_VIDEO); + SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_VIDEO); #else #ifdef USE_SDL SDL_Init (SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE); @@ -532,6 +543,7 @@ static int real_main2 (int argc, TCHAR **argv) inputdevice_init(); changed_prefs = currprefs; + no_gui = ! currprefs.start_gui; if (restart_program == 2) no_gui = 1; @@ -616,6 +628,8 @@ void real_main (int argc, TCHAR **argv) fetch_configurationpath (restart_config, sizeof (restart_config) / sizeof (TCHAR)); _tcscat (restart_config, OPTIONSFILENAME); _tcscat (restart_config, ".uae"); + default_config = 1; + while (restart_program) { changed_prefs = currprefs; real_main2 (argc, argv); diff --git a/src/memory.cpp b/src/memory.cpp index 34165cc1..9c3355a0 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -21,6 +21,7 @@ #include "savestate.h" #include "crc32.h" #include "gui.h" +#include "akiko.h" #ifdef JIT /* Set by each memory handler that does not simply access real memory. */ @@ -718,7 +719,9 @@ static bool load_extendedkickstart (const TCHAR *romextfile, int type) extendedkickmem_size = 524288; off = 0; if (type == 0) { - if (size > 300000) { + if (currprefs.cs_cd32cd) { + extendedkickmem_type = EXTENDED_ROM_CD32; + } else if (size > 300000) { extendedkickmem_type = EXTENDED_ROM_CD32; } else if (need_uae_boot_rom () != 0xf00000) { extendedkickmem_type = EXTENDED_ROM_CDTV; @@ -1138,6 +1141,9 @@ void memory_reset (void) map_banks (&bogomem_bank, 0xC0, t, 0); } map_banks (&clock_bank, 0xDC, 1, 0); + if (currprefs.cs_cd32c2p || currprefs.cs_cd32cd || currprefs.cs_cd32nvram) { + map_banks (&akiko_bank, AKIKO_BASE >> 16, 1, 0); + } map_banks (&kickmem_bank, 0xF8, 8, 0); /* map beta Kickstarts at 0x200000/0xC00000/0xF00000 */ @@ -1162,6 +1168,11 @@ void memory_reset (void) case EXTENDED_ROM_KS: map_banks (&extendedkickmem_bank, 0xE0, 8, 0); break; +#ifdef CD32 + case EXTENDED_ROM_CD32: + map_banks (&extendedkickmem_bank, 0xE0, 8, 0); + break; +#endif } #ifdef AUTOCONFIG if (need_uae_boot_rom ()) @@ -1170,6 +1181,10 @@ void memory_reset (void) if ((cloanto_rom) && !extendedkickmem_type) map_banks (&kickmem_bank, 0xE0, 8, 0); + + if (extendedkickmem_type == EXTENDED_ROM_CD32 || extendedkickmem_type == EXTENDED_ROM_KS) + map_banks (&extendedkickmem_bank, 0xb0, 8, 0); + write_log (_T("memory init end\n")); } diff --git a/src/od-pandora/cda_play.cpp b/src/od-pandora/cda_play.cpp new file mode 100644 index 00000000..23d6a48c --- /dev/null +++ b/src/od-pandora/cda_play.cpp @@ -0,0 +1,68 @@ +#include "sysconfig.h" +#include "sysdeps.h" + +#include "cda_play.h" +#include "sd-pandora/sound.h" +#include "uae.h" + + +cda_audio::~cda_audio() +{ + cdaudio_active = false; + wait(0); + wait(1); + for (int i = 0; i < 2; i++) { + xfree (buffers[i]); + buffers[i] = NULL; + } +} + +cda_audio::cda_audio(int num_sectors) +{ + active = false; + playing = false; + volume[0] = volume[1] = 0; + + bufsize = num_sectors * 2352; + for (int i = 0; i < 2; i++) { + buffers[i] = xcalloc (uae_u8, num_sectors * 4096); + } + this->num_sectors = num_sectors; + active = true; + playing = true; + cdaudio_active = true; +} + +void cda_audio::setvolume(int master, int left, int right) +{ + for (int j = 0; j < 2; j++) { + volume[j] = j == 0 ? left : right; + volume[j] = (100 - master) * volume[j] / 100; + if (volume[j]) + volume[j]++; + if (volume[j] >= 32768) + volume[j] = 32768; + } +} + +bool cda_audio::play(int bufnum) +{ + if (!active) { + return false; + } + + uae_s16 *p = (uae_s16*)(buffers[bufnum]); + for (int i = 0; i < num_sectors * 2352 / 4; i++) { + PUT_CDAUDIO_WORD_STEREO(p[i * 2 + 0] * volume[0] / 32768, p[i * 2 + 1] * volume[1] / 32768); + check_cdaudio_buffers(); + } + + return cdaudio_catchup(); +} + +void cda_audio::wait(int bufnum) +{ + if (!active || !playing) { + return; + } +} diff --git a/src/od-pandora/cda_play.h b/src/od-pandora/cda_play.h new file mode 100644 index 00000000..71d32ac8 --- /dev/null +++ b/src/od-pandora/cda_play.h @@ -0,0 +1,18 @@ +class cda_audio { +private: + int bufsize; + int volume[2]; + bool playing; + bool active; + +public: + uae_u8 *buffers[2]; + int num_sectors; + + cda_audio(int num_sectors); + ~cda_audio(); + void setvolume(int master, int left, int right); + bool play(int bufnum); + void wait(void); + void wait(int bufnum); +}; diff --git a/src/od-pandora/config.h b/src/od-pandora/config.h index 62eb6d60..b86eab17 100644 --- a/src/od-pandora/config.h +++ b/src/od-pandora/config.h @@ -43,25 +43,9 @@ #define RELY_ON_LOADSEG_DETECTION */ -#undef USE_COMPILER -#undef RELY_ON_LOADSEG_DETECTION - /*************************************************************************** * Operating system/machine specific options * Configure these for your CPU. The default settings should work on any * machine, but may not give optimal performance everywhere. * (These don't do very much yet, except HAVE_RDTSC */ - -/* - * Define this on PPro's, K6's and maybe other non-x86 CPUs. -#undef MULTIPLICATION_PROFITABLE - */ - -/* - * PPros don't like branches. With this option, UAE tries to avoid them in some - * places. -#undef BRANCHES_ARE_EXPENSIVE - */ - -#define MUSIC_VOLUME 80 diff --git a/src/od-pandora/exectasks.h b/src/od-pandora/exectasks.h deleted file mode 100644 index f6a93ca0..00000000 --- a/src/od-pandora/exectasks.h +++ /dev/null @@ -1,17 +0,0 @@ - /* - * UAE - The Un*x Amiga Emulator - * - * exec.library multitasking emulation - * - * Copyright 1996 Bernd Schmidt - */ - -struct switch_struct { - int dummy; -}; -/* Looks weird. I think I had a report once that some compiler chokes if - * the statement is empty. */ -#define EXEC_SWITCH_TASKS(run, ready) do { int i = 0; i++; } while(0) - -#define EXEC_SETUP_SWS(t) do { int i = 0; i++; } while(0) - diff --git a/src/od-pandora/gp2x.h b/src/od-pandora/gp2x.h deleted file mode 100644 index fdddb057..00000000 --- a/src/od-pandora/gp2x.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _GP2X_H -#define _GP2X_H - -#define GP2X_BUTTON_Y 0 -#define GP2X_BUTTON_A 1 -#define GP2X_BUTTON_X 2 -#define GP2X_BUTTON_B 3 -#define GP2X_BUTTON_R 8 -#define GP2X_BUTTON_L 7 -#define GP2X_BUTTON_START 5 -#define GP2X_BUTTON_SELECT 4 - -#define GP2X_UP (1<<0) -#define GP2X_UP_LEFT (1<<1) -#define GP2X_LEFT (1<<2) -#define GP2X_DOWN_LEFT (1<<3) -#define GP2X_DOWN (1<<4) -#define GP2X_DOWN_RIGHT (1<<5) -#define GP2X_RIGHT (1<<6) -#define GP2X_UP_RIGHT (1<<7) -#define GP2X_A (1<<12) -#define GP2X_B (1<<13) -#define GP2X_X (1<<15) -#define GP2X_Y (1<<14) -#define GP2X_L (1<<10) -#define GP2X_R (1<<11) -#define GP2X_SELECT (1<<9) -#define GP2X_START (1<<8) -#define GP2X_VOL_UP (1<<16) -#define GP2X_VOL_DOWN (1<<17) -#define GP2X_PUSH (1<<27) - -#endif diff --git a/src/od-pandora/gui/Navigation.cpp b/src/od-pandora/gui/Navigation.cpp index ebacc413..89ee1f37 100644 --- a/src/od-pandora/gui/Navigation.cpp +++ b/src/od-pandora/gui/Navigation.cpp @@ -24,24 +24,25 @@ typedef struct static NavigationMap navMap[] = { -// active move left move right move up move down +// active move left move right move up move down // main_window - { "Paths", "SystemROMs", "SystemROMs", "Reset", "Configurations" }, - { "Configurations", "ConfigList", "ConfigList", "Paths", "CPU and FPU" }, - { "CPU and FPU", "7 Mhz", "68000", "Configurations", "Chipset" }, - { "Chipset", "Fast copper", "OCS", "CPU and FPU", "ROM" }, - { "ROM", "MainROM", "cboMainROM", "Chipset", "RAM" }, - { "RAM", "Chipmem", "Chipmem", "ROM", "Floppy drives" }, - { "Floppy drives", "cmdSel0", "DF0:", "RAM", "Hard drives" }, - { "Hard drives", "cmdDel0", "cmdProp0", "Floppy drives", "Display" }, - { "Display", "sldWidth", "sldWidth", "Hard drives", "Sound" }, - { "Sound", "sndDisable", "sndDisable", "Display", "Input" }, - { "Input", "cboCtrlConfig", "cboCtrlConfig", "Sound", "Miscellaneous" }, - { "Miscellaneous", "StatusLine", "StatusLine", "Input", "Savestates" }, - { "Savestates", "State0", "State0", "Miscellaneous", "Reset" }, - { "Reset", "Start", "Quit", "Savestates", "Paths" }, - { "Quit", "Reset", "Start", "Savestates", "Paths" }, - { "Start", "Quit", "Reset", "Savestates", "Paths" }, + { "Paths", "SystemROMs", "SystemROMs", "Reset", "Configurations" }, + { "Configurations", "ConfigList", "ConfigList", "Paths", "CPU and FPU" }, + { "CPU and FPU", "7 Mhz", "68000", "Configurations", "Chipset" }, + { "Chipset", "Fast copper", "OCS", "CPU and FPU", "ROM" }, + { "ROM", "MainROM", "cboMainROM", "Chipset", "RAM" }, + { "RAM", "Chipmem", "Chipmem", "ROM", "Floppy drives" }, + { "Floppy drives", "cmdSel0", "DF0:", "RAM", "Hard drives / CD" }, + { "Hard drives / CD", "cmdCreateHDF", "cmdAddDir", "Floppy drives", "Display" }, + { "Display", "sldWidth", "sldWidth", "Hard drives / CD", "Sound" }, + { "Sound", "sndDisable", "sndDisable", "Display", "Input" }, + { "Input", "cboPort0", "cboPort0", "Sound", "Miscellaneous" }, + { "Miscellaneous", "StatusLine", "StatusLine", "Input", "Savestates" }, + { "Savestates", "State0", "State0", "Miscellaneous", "Reset" }, + { "Reset", "Start", "Quit", "Savestates", "Paths" }, + { "Quit", "Reset", "Restart", "Savestates", "Paths" }, + { "Restart", "Quit", "Start", "Savestates", "Paths" }, + { "Start", "Restart", "Reset", "Savestates", "Paths" }, // PanelPaths { "SystemROMs", "Paths", "Paths", "RescanROMs", "ConfigPath" }, @@ -130,21 +131,26 @@ static NavigationMap navMap[] = { "CreateDD", "SaveForDisk", "CreateHD", "DriveSpeed", "cboType0" }, { "CreateHD", "CreateDD", "Floppy drives", "DriveSpeed", "cmdEject0" }, -// active move left move right move up move down +// active move left move right move up move down // PanelHD - { "cmdProp0", "Hard drives", "cmdDel0", "cmdAddDir", "cmdProp1" }, - { "cmdDel0", "cmdProp0", "Hard drives", "cmdAddHDF", "cmdDel1" }, - { "cmdProp1", "Hard drives", "cmdDel1", "cmdProp0", "cmdProp2" }, - { "cmdDel1", "cmdProp1", "Hard drives", "cmdDel0", "cmdDel2" }, - { "cmdProp2", "Hard drives", "cmdDel2", "cmdProp1", "cmdProp3" }, - { "cmdDel2", "cmdProp2", "Hard drives", "cmdDel1", "cmdDel3" }, - { "cmdProp3", "Hard drives", "cmdDel3", "cmdProp2", "cmdProp4" }, - { "cmdDel3", "cmdProp3", "Hard drives", "cmdDel2", "cmdDel4" }, - { "cmdProp4", "Hard drives", "cmdDel4", "cmdProp3", "cmdAddDir" }, - { "cmdDel4", "cmdProp4", "Hard drives", "cmdDel3", "cmdAddHDF" }, - { "cmdAddDir", "Hard drives", "cmdAddHDF", "cmdProp4", "cmdProp0" }, - { "cmdAddHDF", "cmdAddDir", "cmdCreateHDF", "cmdDel4", "cmdDel0" }, - { "cmdCreateHDF", "cmdAddHDF", "Hard drives", "cmdDel4", "cmdDel0" }, + { "cmdProp0", "Hard drives / CD", "cmdDel0", "CDVol", "cmdProp1" }, + { "cmdDel0", "cmdProp0", "Hard drives / CD", "CDVol", "cmdDel1" }, + { "cmdProp1", "Hard drives / CD", "cmdDel1", "cmdProp0", "cmdProp2" }, + { "cmdDel1", "cmdProp1", "Hard drives / CD", "cmdDel0", "cmdDel2" }, + { "cmdProp2", "Hard drives / CD", "cmdDel2", "cmdProp1", "cmdProp3" }, + { "cmdDel2", "cmdProp2", "Hard drives / CD", "cmdDel1", "cmdDel3" }, + { "cmdProp3", "Hard drives / CD", "cmdDel3", "cmdProp2", "cmdProp4" }, + { "cmdDel3", "cmdProp3", "Hard drives / CD", "cmdDel2", "cmdDel4" }, + { "cmdProp4", "Hard drives / CD", "cmdDel4", "cmdProp3", "cmdAddDir" }, + { "cmdDel4", "cmdProp4", "Hard drives / CD", "cmdDel3", "cmdAddHDF" }, + { "cmdAddDir", "Hard drives / CD", "cmdAddHDF", "cmdProp4", "CD drive" }, + { "cmdAddHDF", "cmdAddDir", "cmdCreateHDF", "cmdDel4", "CD drive" }, + { "cmdCreateHDF", "cmdAddHDF", "Hard drives / CD", "cmdDel4", "CD drive" }, + { "CD drive", "Hard drives / CD", "cdEject", "cmdAddDir", "cboCD" }, + { "cdEject", "CD drive", "CDSelect", "cmdCreateHDF", "cboCD" }, + { "CDSelect", "cdEject", "Hard drives / CD", "cmdCreateHDF", "cboCD" }, + { "cboCD", "Hard drives / CD", "Hard drives / CD", "CD drive", "CDVol" }, + { "CDVol", "", "", "cboCD", "cmdProp0" }, #ifndef RASPBERRY // PanelDisplay @@ -175,45 +181,25 @@ static NavigationMap navMap[] = { "sldSeparation", "", "", "cboFilter", "sldStereoDelay" }, { "sldStereoDelay", "", "", "sldSeparation", "sndDisable" }, -#ifndef RASPBERRY +// active move left move right move up move down // PanelInput - { "cboCtrlConfig", "Input", "Input", "cboLeft", "cboJoystick" }, - { "cboJoystick", "Input", "cboAutofire", "cboCtrlConfig", "cboTapDelay" }, - { "cboAutofire", "cboJoystick", "Input", "cboCtrlConfig", "cboTapDelay" }, - { "cboTapDelay", "Input", "Input", "cboJoystick", "MouseSpeed" }, - { "MouseSpeed", "", "", "cboTapDelay", "cboDPAD" }, - { "MouseHack", "MouseSpeed", "Input", "cboTapDelay", "CustomCtrl" }, - { "cboDPAD", "Input", "CustomCtrl", "MouseSpeed", "cboA" }, - { "CustomCtrl", "cboDPAD", "Input", "MouseHack", "cboB" }, - { "cboA", "Input", "cboB", "cboDPAD", "cboX" }, - { "cboB", "cboA", "Input", "CustomCtrl", "cboY" }, + { "cboPort0", "Input", "Input", "cboLeft", "cboPort1" }, + { "cboPort1", "Input", "cboAutofire", "cboPort0", "MouseSpeed" }, + { "cboAutofire", "cboPort1", "Input", "cboPort0", "cboTapDelay" }, + { "MouseSpeed", "", "", "cboPort1", "MouseHack" }, + { "MouseHack", "Input", "cboTapDelay", "MouseSpeed", "CustomCtrl" }, + { "cboTapDelay", "MouseHack", "Input", "cboAutofire", "cboB" }, + { "CustomCtrl", "Input", "Input", "MouseHack", "cboA" }, + { "cboA", "Input", "cboB", "CustomCtrl", "cboX" }, + { "cboB", "cboA", "Input", "cboTapDelay", "cboY" }, { "cboX", "Input", "cboY", "cboA", "cboL" }, { "cboY", "cboX", "Input", "cboB", "cboR" }, { "cboL", "Input", "cboR", "cboX", "cboUp" }, { "cboR", "cboL", "Input", "cboY", "cboDown" }, { "cboUp", "Input", "cboDown", "cboL", "cboLeft" }, { "cboDown", "cboUp", "Input", "cboR", "cboRight" }, - { "cboLeft", "Input", "cboRight", "cboUp", "cboCtrlConfig" }, - { "cboRight", "cboLeft", "Input", "cboDown", "cboCtrlConfig" }, -#else -// PanelInput - { "cboCtrlConfig", "Input", "Input", "cboLeft", "cboJoystick" }, - { "cboJoystick", "Input", "cboAutofire", "cboCtrlConfig", "MouseSpeed" }, - { "cboAutofire", "cboJoystick", "Input", "cboCtrlConfig", "MouseSpeed" }, - { "MouseSpeed", "", "", "cboJoystick", "cboDPAD" }, - { "cboDPAD", "Input", "CustomCtrl", "MouseSpeed", "cboA" }, - { "CustomCtrl", "cboDPAD", "Input", "MouseSpeed", "cboB" }, - { "cboA", "Input", "cboB", "cboDPAD", "cboX" }, - { "cboB", "cboA", "Input", "CustomCtrl", "cboY" }, - { "cboX", "Input", "cboY", "cboA", "cboL" }, - { "cboY", "cboX", "Input", "cboB", "cboR" }, - { "cboL", "Input", "cboR", "cboX", "cboUp" }, - { "cboR", "cboL", "Input", "cboY", "cboDown" }, - { "cboUp", "Input", "cboDown", "cboL", "cboLeft" }, - { "cboDown", "cboUp", "Input", "cboR", "cboRight" }, - { "cboLeft", "Input", "cboRight", "cboUp", "cboCtrlConfig" }, - { "cboRight", "cboLeft", "Input", "cboDown", "cboCtrlConfig" }, -#endif + { "cboLeft", "Input", "cboRight", "cboUp", "cboPort0" }, + { "cboRight", "cboLeft", "Input", "cboDown", "cboPort0" }, // PanelMisc { "StatusLine", "Miscellaneous", "Miscellaneous", "BSDSocket", "HideIdle" }, diff --git a/src/od-pandora/gui/PanelConfig.cpp b/src/od-pandora/gui/PanelConfig.cpp index 864fcfc7..ab963b33 100644 --- a/src/od-pandora/gui/PanelConfig.cpp +++ b/src/od-pandora/gui/PanelConfig.cpp @@ -10,6 +10,7 @@ #include "config.h" #include "options.h" #include "uae.h" +#include "blkdev.h" #include "gui.h" #include "target.h" #include "gui_handling.h" @@ -47,6 +48,27 @@ bool LoadConfigByName(const char *name) return false; } +void load_buildin_config(int id) +{ + if(changed_prefs.cdslots[0].inuse) + gui_force_rtarea_hdchange(); + discard_prefs(&changed_prefs, 0); + default_prefs(&changed_prefs, 0); + switch(id) { + case BUILDINID_A500: + bip_a500(&changed_prefs, -1); + break; + + case BUILDINID_A1200: + bip_a1200(&changed_prefs, -1); + break; + + case BUILDINID_CD32: + bip_cd32(&changed_prefs, -1); + break; + } +} + void SetLastActiveConfig(const char *filename) { extractFileName(filename, last_active_config); @@ -107,7 +129,12 @@ class ConfigButtonActionListener : public gcn::ActionListener // Load selected configuration //----------------------------------------------- i = lstConfigs->getSelected(); - target_cfgfile_load(&changed_prefs, ConfigFilesList[i]->FullPath, 0, 0); + if(ConfigFilesList[i]->BuildInID != BUILDINID_NONE) { + load_buildin_config(ConfigFilesList[i]->BuildInID); + strcpy(changed_prefs.description, ConfigFilesList[i]->Description); + } else { + target_cfgfile_load(&changed_prefs, ConfigFilesList[i]->FullPath, 0, 0); + } strncpy(last_active_config, ConfigFilesList[i]->Name, MAX_PATH); DisableResume(); RefreshAllPanels(); @@ -141,7 +168,7 @@ class ConfigButtonActionListener : public gcn::ActionListener //----------------------------------------------- char msg[256]; i = lstConfigs->getSelected(); - if(i >= 0 && strcmp(ConfigFilesList[i]->Name, OPTIONSFILENAME)) + if(i >= 0 && ConfigFilesList[i]->BuildInID == BUILDINID_NONE && strcmp(ConfigFilesList[i]->Name, OPTIONSFILENAME)) { snprintf(msg, 256, "Do you want to delete '%s' ?", ConfigFilesList[i]->Name); if(ShowMessage("Delete Configuration", msg, "", "Yes", "No")) @@ -176,7 +203,12 @@ class ConfigsListActionListener : public gcn::ActionListener //----------------------------------------------- // Selected same config again -> load and start it //----------------------------------------------- - target_cfgfile_load(&changed_prefs, ConfigFilesList[selected_item]->FullPath, 0, 0); + if(ConfigFilesList[selected_item]->BuildInID != BUILDINID_NONE) { + load_buildin_config(ConfigFilesList[selected_item]->BuildInID); + strcpy(changed_prefs.description, ConfigFilesList[selected_item]->Description); + } else { + target_cfgfile_load(&changed_prefs, ConfigFilesList[selected_item]->FullPath, 0, 0); + } strncpy(last_active_config, ConfigFilesList[selected_item]->Name, MAX_PATH); DisableResume(); RefreshAllPanels(); diff --git a/src/od-pandora/gui/PanelHD.cpp b/src/od-pandora/gui/PanelHD.cpp index 048104bd..7a56961e 100644 --- a/src/od-pandora/gui/PanelHD.cpp +++ b/src/od-pandora/gui/PanelHD.cpp @@ -15,6 +15,7 @@ #include "uae.h" #include "autoconf.h" #include "filesys.h" +#include "blkdev.h" #include "gui.h" #include "target.h" #include "gui_handling.h" @@ -33,6 +34,9 @@ static const int COLUMN_SIZE[] = { 50 // Bootpri }; +static const char *cdfile_filter[] = { ".cue", ".ccd", ".iso", "\0" }; +static void AdjustDropDownControls(void); + static gcn::Label* lblList[COL_COUNT]; static gcn::Container* listEntry[MAX_HD_DEVICES]; static gcn::TextField* listCells[MAX_HD_DEVICES][COL_COUNT]; @@ -41,7 +45,14 @@ static gcn::ImageButton* listCmdDelete[MAX_HD_DEVICES]; static gcn::Button* cmdAddDirectory; static gcn::Button* cmdAddHardfile; static gcn::Button* cmdCreateHardfile; - +static gcn::UaeCheckBox* chkCD; +static gcn::UaeDropDown* cboCDFile; +static gcn::Button* cmdCDEject; +static gcn::Button* cmdCDSelect; +static gcn::Label* lblCDVol; +static gcn::Label* lblCDVolInfo; +static gcn::Slider* sldCDVol; + static int GetHDType(int index) { @@ -58,6 +69,28 @@ static int GetHDType(int index) } +class CDfileListModel : public gcn::ListModel +{ + public: + CDfileListModel() + { + } + + int getNumberOfElements() + { + return lstMRUCDList.size(); + } + + std::string getElementAt(int i) + { + if(i < 0 || i >= lstMRUCDList.size()) + return "---"; + return lstMRUCDList[i]; + } +}; +static CDfileListModel cdfileList; + + class HDRemoveActionListener : public gcn::ActionListener { public: @@ -150,6 +183,125 @@ class CreateHardfileActionListener : public gcn::ActionListener CreateHardfileActionListener* createHardfileActionListener; +class CDCheckActionListener : public gcn::ActionListener +{ + public: + void action(const gcn::ActionEvent& actionEvent) + { + if(changed_prefs.cdslots[0].inuse) { + changed_prefs.cdslots[0].inuse = false; + changed_prefs.cdslots[0].type = SCSI_UNIT_DISABLED; + } else { + changed_prefs.cdslots[0].inuse = true; + changed_prefs.cdslots[0].type = SCSI_UNIT_IMAGE; + } + RefreshPanelHD(); + } +}; +CDCheckActionListener* cdCheckActionListener; + + +class CDButtonActionListener : public gcn::ActionListener +{ + public: + void action(const gcn::ActionEvent& actionEvent) + { + if (actionEvent.getSource() == cmdCDEject) + { + //--------------------------------------- + // Eject CD from drive + //--------------------------------------- + strcpy(changed_prefs.cdslots[0].name, ""); + AdjustDropDownControls(); + } + else if(actionEvent.getSource() == cmdCDSelect) + { + char tmp[MAX_DPATH]; + + if(strlen(changed_prefs.cdslots[0].name) > 0) + strncpy(tmp, changed_prefs.cdslots[0].name, MAX_DPATH); + else + strncpy(tmp, currentDir, MAX_DPATH); + + if(SelectFile("Select CD image file", tmp, cdfile_filter)) + { + if(strncmp(changed_prefs.cdslots[0].name, tmp, MAX_DPATH)) + { + strncpy(changed_prefs.cdslots[0].name, tmp, sizeof(changed_prefs.cdslots[0].name)); + changed_prefs.cdslots[0].inuse = true; + changed_prefs.cdslots[0].type = SCSI_UNIT_IMAGE; + AddFileToCDList(tmp, 1); + extractPath(tmp, currentDir); + + AdjustDropDownControls(); + } + } + cmdCDSelect->requestFocus(); + } + RefreshPanelHD(); + } +}; +CDButtonActionListener* cdButtonActionListener; + + +class GenericActionListener : public gcn::ActionListener +{ + public: + void action(const gcn::ActionEvent& actionEvent) + { + if (actionEvent.getSource() == sldCDVol) + { + int newvol = 100 - (int) sldCDVol->getValue(); + if(changed_prefs.sound_volume_cd != newvol) + { + changed_prefs.sound_volume_cd = newvol; + RefreshPanelHD(); + } + } + } +}; +GenericActionListener* genericActionListener; + + +static bool bIgnoreListChange = false; +class CDFileActionListener : public gcn::ActionListener +{ + public: + void action(const gcn::ActionEvent& actionEvent) + { + //--------------------------------------- + // CD image from list selected + //--------------------------------------- + if(!bIgnoreListChange) + { + int idx = cboCDFile->getSelected(); + + if(idx < 0) + { + strcpy(changed_prefs.cdslots[0].name, ""); + AdjustDropDownControls(); + } + else + { + if(cdfileList.getElementAt(idx).compare(changed_prefs.cdslots[0].name)) + { + strncpy(changed_prefs.cdslots[0].name, cdfileList.getElementAt(idx).c_str(), sizeof(changed_prefs.cdslots[0].name)); + changed_prefs.cdslots[0].inuse = true; + changed_prefs.cdslots[0].type = SCSI_UNIT_IMAGE; + lstMRUCDList.erase(lstMRUCDList.begin() + idx); + lstMRUCDList.insert(lstMRUCDList.begin(), changed_prefs.cdslots[0].name); + bIgnoreListChange = true; + cboCDFile->setSelected(0); + bIgnoreListChange = false; + } + } + } + RefreshPanelHD(); + } +}; +static CDFileActionListener* cdFileActionListener; + + void InitPanelHD(const struct _ConfigCategory& category) { int row, col; @@ -214,6 +366,44 @@ void InitPanelHD(const struct _ConfigCategory& category) cmdCreateHardfile->setId("cmdCreateHDF"); cmdCreateHardfile->addActionListener(createHardfileActionListener); + cdCheckActionListener = new CDCheckActionListener(); + cdButtonActionListener = new CDButtonActionListener(); + cdFileActionListener = new CDFileActionListener(); + genericActionListener = new GenericActionListener(); + + chkCD = new gcn::UaeCheckBox("CD drive"); + chkCD->addActionListener(cdCheckActionListener); + + cmdCDEject = new gcn::Button("Eject"); + cmdCDEject->setSize(SMALL_BUTTON_WIDTH * 2, SMALL_BUTTON_HEIGHT); + cmdCDEject->setBaseColor(gui_baseCol); + cmdCDEject->setId("cdEject"); + cmdCDEject->addActionListener(cdButtonActionListener); + + cmdCDSelect = new gcn::Button("..."); + cmdCDSelect->setSize(SMALL_BUTTON_WIDTH, SMALL_BUTTON_HEIGHT); + cmdCDSelect->setBaseColor(gui_baseCol); + cmdCDSelect->setId("CDSelect"); + cmdCDSelect->addActionListener(cdButtonActionListener); + + cboCDFile = new gcn::UaeDropDown(&cdfileList); + cboCDFile->setSize(category.panel->getWidth() - 2 * DISTANCE_BORDER, DROPDOWN_HEIGHT); + cboCDFile->setBaseColor(gui_baseCol); + cboCDFile->setId("cboCD"); + cboCDFile->addActionListener(cdFileActionListener); + + lblCDVol = new gcn::Label("CD Volume:"); + lblCDVol->setSize(80, LABEL_HEIGHT); + lblCDVol->setAlignment(gcn::Graphics::RIGHT); + sldCDVol = new gcn::Slider(0, 100); + sldCDVol->setSize(200, SLIDER_HEIGHT); + sldCDVol->setBaseColor(gui_baseCol); + sldCDVol->setMarkerLength(20); + sldCDVol->setStepLength(10); + sldCDVol->setId("CDVol"); + sldCDVol->addActionListener(genericActionListener); + lblCDVolInfo = new gcn::Label("80 %"); + posX = DISTANCE_BORDER + 2 + SMALL_BUTTON_WIDTH + 34; for(col=0; colgetHeight() + 4; } - posY = category.panel->getHeight() - DISTANCE_BORDER - BUTTON_HEIGHT; + posY += DISTANCE_NEXT_Y; category.panel->add(cmdAddDirectory, DISTANCE_BORDER, posY); category.panel->add(cmdAddHardfile, DISTANCE_BORDER + cmdAddDirectory->getWidth() + DISTANCE_NEXT_X, posY); category.panel->add(cmdCreateHardfile, cmdAddHardfile->getX() + cmdAddHardfile->getWidth() + DISTANCE_NEXT_X, posY); + + posY += cmdAddDirectory->getHeight() + 2 * DISTANCE_NEXT_Y; + category.panel->add(chkCD, DISTANCE_BORDER, posY + 2); + category.panel->add(cmdCDEject, category.panel->getWidth() - cmdCDEject->getWidth() - DISTANCE_NEXT_X - cmdCDSelect->getWidth() - DISTANCE_BORDER, posY); + category.panel->add(cmdCDSelect, category.panel->getWidth() - cmdCDSelect->getWidth() - DISTANCE_BORDER, posY); + posY += cmdCDSelect->getHeight() + DISTANCE_NEXT_Y; + category.panel->add(cboCDFile, DISTANCE_BORDER, posY); + posY += cboCDFile->getHeight() + DISTANCE_NEXT_Y; + + category.panel->add(lblCDVol, DISTANCE_BORDER, posY); + category.panel->add(sldCDVol, DISTANCE_BORDER + lblCDVol->getWidth() + 8, posY); + category.panel->add(lblCDVolInfo, sldCDVol->getX() + sldCDVol->getWidth() + 12, posY); + posY += sldCDVol->getHeight() + DISTANCE_NEXT_Y; RefreshPanelHD(); } @@ -267,6 +470,19 @@ void ExitPanelHD(void) delete cmdAddHardfile; delete cmdCreateHardfile; + delete chkCD; + delete cmdCDEject; + delete cmdCDSelect; + delete cboCDFile; + delete lblCDVol; + delete lblCDVolInfo; + delete sldCDVol; + + delete cdCheckActionListener; + delete cdButtonActionListener; + delete cdFileActionListener; + delete genericActionListener; + delete hdRemoveActionListener; delete hdEditActionListener; delete addVirtualHDActionListener; @@ -275,6 +491,24 @@ void ExitPanelHD(void) } +static void AdjustDropDownControls(void) +{ + int i; + + cboCDFile->clearSelected(); + if((changed_prefs.cdslots[0].inuse) && strlen(changed_prefs.cdslots[0].name) > 0) + { + for(i = 0; i < lstMRUCDList.size(); ++i) + { + if(!lstMRUCDList[i].compare(changed_prefs.cdslots[0].name)) + { + cboCDFile->setSelected(i); + break; + } + } + } +} + void RefreshPanelHD(void) { int row, col; @@ -283,6 +517,8 @@ void RefreshPanelHD(void) struct uaedev_config_info *uci; int nosize = 0, type; + AdjustDropDownControls(); + for(row=0; rowsetEnabled(false); } } + + chkCD->setSelected(changed_prefs.cdslots[0].inuse); + cmdCDEject->setEnabled(changed_prefs.cdslots[0].inuse); + cmdCDSelect->setEnabled(changed_prefs.cdslots[0].inuse); + cboCDFile->setEnabled(changed_prefs.cdslots[0].inuse); + sldCDVol->setEnabled(changed_prefs.cdslots[0].inuse); + + sldCDVol->setValue(100 - changed_prefs.sound_volume_cd); + snprintf(tmp, 32, "%d %%", 100 - changed_prefs.sound_volume_cd); + lblCDVolInfo->setCaption(tmp); } diff --git a/src/od-pandora/gui/PanelInput.cpp b/src/od-pandora/gui/PanelInput.cpp index f49ebd7c..48ddff28 100644 --- a/src/od-pandora/gui/PanelInput.cpp +++ b/src/od-pandora/gui/PanelInput.cpp @@ -18,15 +18,18 @@ #include "gui.h" #include "target.h" #include "gui_handling.h" +#include "keyboard.h" +#include "inputdevice.h" static const char *mousespeed_list[] = { ".25", ".5", "1x", "2x", "4x" }; static const int mousespeed_values[] = { 2, 5, 10, 20, 40 }; -static gcn::Label *lblCtrlConfig; -static gcn::UaeDropDown* cboCtrlConfig; -static gcn::Label *lblJoystick; -static gcn::UaeDropDown* cboJoystick; +static gcn::Label *lblPort0; +static gcn::UaeDropDown* cboPort0; +static gcn::Label *lblPort1; +static gcn::UaeDropDown* cboPort1; + static gcn::Label *lblAutofire; static gcn::UaeDropDown* cboAutofire; static gcn::Label* lblMouseSpeed; @@ -39,8 +42,6 @@ static gcn::UaeCheckBox* chkMouseHack; #endif static gcn::UaeCheckBox* chkCustomCtrl; -static gcn::Label *lblDPAD; -static gcn::UaeDropDown* cboDPAD; static gcn::Label *lblA; static gcn::UaeDropDown* cboA; static gcn::Label *lblB; @@ -92,28 +93,16 @@ class StringListModel : public gcn::ListModel } }; -const char *ctrlConfigValues[] = { - "A=Autofire, X=Fire, Y=Space, B=2nd", - "A=Fire, X=Autofire, Y=Space, B=2nd", - "A=Autofire, X=Jump, Y=Fire, B=2nd", - "A=Fire, X=Jump, Y=Autofire, B=2nd" -}; -StringListModel ctrlConfigList(ctrlConfigValues, 4); +static const char *inputport_list[] = { "Nubs as mouse", "dPad as mouse", "dPad as joystick", "dPad as CD32 contr.", "none" }; +StringListModel ctrlPortList(inputport_list, 5); -const char *joystickValues[] = { "Port0", "Port1", "Both" }; -StringListModel joystickList(joystickValues, 3); +const char *autofireValues[] = { "Off", "Slow", "Medium", "Fast" }; +StringListModel autofireList(autofireValues, 4); -const char *autofireValues[] = { "Light", "Medium", "Heavy" }; -StringListModel autofireList(autofireValues, 3); #ifndef RASPBERRY const char *tapDelayValues[] = { "Normal", "Short", "None" }; StringListModel tapDelayList(tapDelayValues, 3); -const char *dPADValues[] = { "Joystick", "Mouse", "Custom" }; -#else -const char *dPADValues[] = { "Joystick", "Keyboard", "Custom" }; #endif -StringListModel dPADList(dPADValues, 3); - static const int ControlKey_SDLKeyValues[] = { SDLK_F11 , SDLK_F12, SDLK_LALT , SDLK_LCTRL }; @@ -139,6 +128,31 @@ const char *mappingValues[] = { "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "NULL" }; StringListModel mappingList(mappingValues, 105); +static int amigaKey[] = + { -8, -7, -6, -5, -4, -3, -2, -1, /* 0 - 7 */ + 0, AK_UP, AK_DN, AK_LF, AK_RT, AK_NP0, AK_NP1, AK_NP2, /* 8 - 15 */ + AK_NP3, AK_NP4, AK_NP5, AK_NP6, AK_NP7, AK_NP8, AK_NP9, AK_ENT, /* 16 - 23 */ + AK_NPDIV, AK_NPMUL, AK_NPSUB, AK_NPADD, AK_NPDEL, AK_NPLPAREN, AK_NPRPAREN, AK_SPC, /* 24 - 31 */ + AK_BS, AK_TAB, AK_RET, AK_ESC, AK_DEL, AK_LSH, AK_RSH, AK_CAPSLOCK, /* 32 - 39 */ + AK_CTRL, AK_LALT, AK_RALT, AK_LAMI, AK_RAMI, AK_HELP, AK_LBRACKET, AK_RBRACKET, /* 40 - 47 */ + AK_SEMICOLON, AK_COMMA, AK_PERIOD, AK_SLASH, AK_BACKSLASH, AK_QUOTE, AK_NUMBERSIGN, AK_LTGT, /* 48 - 55 */ + AK_BACKQUOTE, AK_MINUS, AK_EQUAL, AK_A, AK_B, AK_C, AK_D, AK_E, /* 56 - 63 */ + AK_F, AK_G, AK_H, AK_I, AK_J, AK_K, AK_L, AK_M, /* 64 - 71 */ + AK_N, AK_O, AK_P, AK_Q, AK_R, AK_S, AK_T, AK_U, /* 72 - 79 */ + AK_V, AK_W, AK_X, AK_Y, AK_Z, AK_1, AK_2, AK_3, /* 80 - 87 */ + AK_4, AK_5, AK_6, AK_7, AK_8, AK_9, AK_0, AK_F1, /* 88 - 95 */ + AK_F2, AK_F3, AK_F4, AK_F5, AK_F6, AK_F7, AK_F8, AK_F9, /* 96 - 104 */ + AK_F10, 0 }; /* 105 - 106 */ +extern int customControlMap[SDLK_LAST]; + +static int GetAmigaKeyIndex(int key) +{ + for(int i=0; i < 106; ++i) { + if(amigaKey[i] == key) + return i; + } + return 8; // Default: no key +} class InputActionListener : public gcn::ActionListener @@ -146,17 +160,37 @@ class InputActionListener : public gcn::ActionListener public: void action(const gcn::ActionEvent& actionEvent) { - if (actionEvent.getSource() == cboCtrlConfig) - changed_prefs.pandora_joyConf = cboCtrlConfig->getSelected(); - - else if (actionEvent.getSource() == cboJoystick) - changed_prefs.pandora_joyPort = (cboJoystick->getSelected() + 1) % 3; + if (actionEvent.getSource() == cboPort0) { + // Handle new device in port 0 + switch(cboPort0->getSelected()) { + case 0: changed_prefs.jports[0].id = JSEM_MICE; changed_prefs.jports[0].mode = JSEM_MODE_MOUSE; break; + case 1: changed_prefs.jports[0].id = JSEM_MICE + 1; changed_prefs.jports[0].mode = JSEM_MODE_MOUSE; break; + case 2: changed_prefs.jports[0].id = JSEM_JOYS; changed_prefs.jports[0].mode = JSEM_MODE_JOYSTICK; break; + case 3: changed_prefs.jports[0].id = JSEM_JOYS; changed_prefs.jports[0].mode = JSEM_MODE_JOYSTICK_CD32; break; + case 4: changed_prefs.jports[0].id = -1; changed_prefs.jports[0].mode = JSEM_MODE_DEFAULT; break; + } + inputdevice_updateconfig(&changed_prefs); + } + + else if (actionEvent.getSource() == cboPort1) { + // Handle new device in port 1 + switch(cboPort1->getSelected()) { + case 0: changed_prefs.jports[1].id = JSEM_MICE; changed_prefs.jports[1].mode = JSEM_MODE_MOUSE; break; + case 1: changed_prefs.jports[1].id = JSEM_MICE + 1; changed_prefs.jports[1].mode = JSEM_MODE_MOUSE; break; + case 2: changed_prefs.jports[1].id = JSEM_JOYS; changed_prefs.jports[1].mode = JSEM_MODE_JOYSTICK; break; + case 3: changed_prefs.jports[1].id = JSEM_JOYS; changed_prefs.jports[1].mode = JSEM_MODE_JOYSTICK_CD32; break; + case 4: changed_prefs.jports[1].id = -1; changed_prefs.jports[1].mode = JSEM_MODE_DEFAULT; break; + } + inputdevice_updateconfig(&changed_prefs); + } else if (actionEvent.getSource() == cboAutofire) { if(cboAutofire->getSelected() == 0) + changed_prefs.input_autofire_framecnt = 0; + else if(cboAutofire->getSelected() == 1) changed_prefs.input_autofire_framecnt = 12; - else if (cboAutofire->getSelected() == 1) + else if (cboAutofire->getSelected() == 2) changed_prefs.input_autofire_framecnt = 8; else changed_prefs.input_autofire_framecnt = 4; @@ -186,38 +220,35 @@ class InputActionListener : public gcn::ActionListener else if (actionEvent.getSource() == chkCustomCtrl) changed_prefs.pandora_customControls = chkCustomCtrl->isSelected() ? 1 : 0; - else if (actionEvent.getSource() == cboDPAD) - changed_prefs.pandora_custom_dpad = cboDPAD->getSelected(); - else if (actionEvent.getSource() == cboA) - changed_prefs.pandora_custom_A = cboA->getSelected() - 8; + customControlMap[SDLK_HOME] = amigaKey[cboA->getSelected()]; else if (actionEvent.getSource() == cboB) - changed_prefs.pandora_custom_B = cboB->getSelected() - 8; + customControlMap[SDLK_END] = amigaKey[cboB->getSelected()]; else if (actionEvent.getSource() == cboX) - changed_prefs.pandora_custom_X = cboX->getSelected() - 8; + customControlMap[SDLK_PAGEDOWN] = amigaKey[cboX->getSelected()]; else if (actionEvent.getSource() == cboY) - changed_prefs.pandora_custom_Y = cboY->getSelected() - 8; + customControlMap[SDLK_PAGEUP] = amigaKey[cboY->getSelected()]; else if (actionEvent.getSource() == cboL) - changed_prefs.pandora_custom_L = cboL->getSelected() - 8; + customControlMap[SDLK_RSHIFT] = amigaKey[cboL->getSelected()]; else if (actionEvent.getSource() == cboR) - changed_prefs.pandora_custom_R = cboR->getSelected() - 8; + customControlMap[SDLK_RCTRL] = amigaKey[cboR->getSelected()]; else if (actionEvent.getSource() == cboUp) - changed_prefs.pandora_custom_up = cboUp->getSelected() - 8; + customControlMap[SDLK_UP] = amigaKey[cboUp->getSelected()]; else if (actionEvent.getSource() == cboDown) - changed_prefs.pandora_custom_down = cboDown->getSelected() - 8; + customControlMap[SDLK_DOWN] = amigaKey[cboDown->getSelected()]; else if (actionEvent.getSource() == cboLeft) - changed_prefs.pandora_custom_left = cboLeft->getSelected() - 8; + customControlMap[SDLK_LEFT] = amigaKey[cboLeft->getSelected()]; else if (actionEvent.getSource() == cboRight) - changed_prefs.pandora_custom_right = cboRight->getSelected() - 8; + customControlMap[SDLK_RIGHT] = amigaKey[cboRight->getSelected()]; else if (actionEvent.getSource() == KeyForMenu) changed_prefs.key_for_menu = ControlKey_SDLKeyValues[KeyForMenu->getSelected()] ; @@ -234,23 +265,23 @@ void InitPanelInput(const struct _ConfigCategory& category) { inputActionListener = new InputActionListener(); - lblCtrlConfig = new gcn::Label("Control Config:"); - lblCtrlConfig->setSize(100, LABEL_HEIGHT); - lblCtrlConfig->setAlignment(gcn::Graphics::RIGHT); - cboCtrlConfig = new gcn::UaeDropDown(&ctrlConfigList); - cboCtrlConfig->setSize(280, DROPDOWN_HEIGHT); - cboCtrlConfig->setBaseColor(gui_baseCol); - cboCtrlConfig->setId("cboCtrlConfig"); - cboCtrlConfig->addActionListener(inputActionListener); + lblPort0 = new gcn::Label("Port0:"); + lblPort0->setSize(100, LABEL_HEIGHT); + lblPort0->setAlignment(gcn::Graphics::RIGHT); + cboPort0 = new gcn::UaeDropDown(&ctrlPortList); + cboPort0->setSize(160, DROPDOWN_HEIGHT); + cboPort0->setBaseColor(gui_baseCol); + cboPort0->setId("cboPort0"); + cboPort0->addActionListener(inputActionListener); - lblJoystick = new gcn::Label("Joystick:"); - lblJoystick->setSize(100, LABEL_HEIGHT); - lblJoystick->setAlignment(gcn::Graphics::RIGHT); - cboJoystick = new gcn::UaeDropDown(&joystickList); - cboJoystick->setSize(80, DROPDOWN_HEIGHT); - cboJoystick->setBaseColor(gui_baseCol); - cboJoystick->setId("cboJoystick"); - cboJoystick->addActionListener(inputActionListener); + lblPort1 = new gcn::Label("Port1:"); + lblPort1->setSize(100, LABEL_HEIGHT); + lblPort1->setAlignment(gcn::Graphics::RIGHT); + cboPort1 = new gcn::UaeDropDown(&ctrlPortList); + cboPort1->setSize(160, DROPDOWN_HEIGHT); + cboPort1->setBaseColor(gui_baseCol); + cboPort1->setId("cboPort1"); + cboPort1->addActionListener(inputActionListener); lblAutofire = new gcn::Label("Autofire Rate:"); lblAutofire->setSize(100, LABEL_HEIGHT); @@ -290,15 +321,6 @@ void InitPanelInput(const struct _ConfigCategory& category) chkCustomCtrl->setId("CustomCtrl"); chkCustomCtrl->addActionListener(inputActionListener); - lblDPAD = new gcn::Label("Keyb DPAD:"); - lblDPAD->setSize(100, LABEL_HEIGHT); - lblDPAD->setAlignment(gcn::Graphics::RIGHT); - cboDPAD = new gcn::UaeDropDown(&dPADList); - cboDPAD->setSize(80, DROPDOWN_HEIGHT); - cboDPAD->setBaseColor(gui_baseCol); - cboDPAD->setId("cboDPAD"); - cboDPAD->addActionListener(inputActionListener); - lblA = new gcn::Label(":"); lblA->setSize(100, LABEL_HEIGHT); lblA->setAlignment(gcn::Graphics::RIGHT); @@ -410,31 +432,27 @@ void InitPanelInput(const struct _ConfigCategory& category) int posY = DISTANCE_BORDER; - category.panel->add(lblCtrlConfig, DISTANCE_BORDER, posY); - category.panel->add(cboCtrlConfig, DISTANCE_BORDER + lblCtrlConfig->getWidth() + 8, posY); - posY += cboCtrlConfig->getHeight() + DISTANCE_NEXT_Y; - category.panel->add(lblJoystick, DISTANCE_BORDER, posY); - category.panel->add(cboJoystick, DISTANCE_BORDER + lblJoystick->getWidth() + 8, posY); + category.panel->add(lblPort0, DISTANCE_BORDER, posY); + category.panel->add(cboPort0, DISTANCE_BORDER + lblPort0->getWidth() + 8, posY); + posY += cboPort0->getHeight() + DISTANCE_NEXT_Y; + category.panel->add(lblPort1, DISTANCE_BORDER, posY); + category.panel->add(cboPort1, DISTANCE_BORDER + lblPort1->getWidth() + 8, posY); category.panel->add(lblAutofire, 300, posY); category.panel->add(cboAutofire, 300 + lblAutofire->getWidth() + 8, posY); posY += cboAutofire->getHeight() + DISTANCE_NEXT_Y; -#ifndef RASPBERRY - category.panel->add(lblTapDelay, DISTANCE_BORDER, posY); - category.panel->add(cboTapDelay, DISTANCE_BORDER + lblTapDelay->getWidth() + 8, posY); - posY += cboTapDelay->getHeight() + DISTANCE_NEXT_Y; -#endif + category.panel->add(lblMouseSpeed, DISTANCE_BORDER, posY); category.panel->add(sldMouseSpeed, DISTANCE_BORDER + lblMouseSpeed->getWidth() + 8, posY); category.panel->add(lblMouseSpeedInfo, sldMouseSpeed->getX() + sldMouseSpeed->getWidth() + 12, posY); -#ifndef RASPBERRY - category.panel->add(chkMouseHack, 320, posY); -#endif posY += sldMouseSpeed->getHeight() + DISTANCE_NEXT_Y; - - category.panel->add(lblDPAD, DISTANCE_BORDER, posY); - category.panel->add(cboDPAD, DISTANCE_BORDER + lblDPAD->getWidth() + 8, posY); - category.panel->add(chkCustomCtrl, 320, posY); - posY += cboDPAD->getHeight() + DISTANCE_NEXT_Y; +#ifndef RASPBERRY + category.panel->add(chkMouseHack, DISTANCE_BORDER + lblA->getWidth() + 8, posY); + category.panel->add(lblTapDelay, 300, posY); + category.panel->add(cboTapDelay, 300 + lblTapDelay->getWidth() + 8, posY); + posY += cboTapDelay->getHeight() + DISTANCE_NEXT_Y; +#endif + category.panel->add(chkCustomCtrl, DISTANCE_BORDER + lblA->getWidth() + 8, posY); + posY += chkCustomCtrl->getHeight() + DISTANCE_NEXT_Y; category.panel->add(lblA, DISTANCE_BORDER, posY); category.panel->add(cboA, DISTANCE_BORDER + lblA->getWidth() + 8, posY); category.panel->add(lblB, 300, posY); @@ -475,10 +493,11 @@ void InitPanelInput(const struct _ConfigCategory& category) void ExitPanelInput(void) { - delete lblCtrlConfig; - delete cboCtrlConfig; - delete lblJoystick; - delete cboJoystick; + delete lblPort0; + delete cboPort0; + delete lblPort1; + delete cboPort1; + delete lblAutofire; delete cboAutofire; delete lblMouseSpeed; @@ -490,8 +509,6 @@ void ExitPanelInput(void) delete chkMouseHack; #endif delete chkCustomCtrl; - delete lblDPAD; - delete cboDPAD; delete lblA; delete cboA; delete lblB; @@ -527,15 +544,52 @@ void RefreshPanelInput(void) { int i; - cboCtrlConfig->setSelected(changed_prefs.pandora_joyConf); - cboJoystick->setSelected((changed_prefs.pandora_joyPort + 2) % 3); + // Set current device in port 0 + switch(changed_prefs.jports[0].id) { + case JSEM_MICE: + cboPort0->setSelected(0); + break; + case JSEM_MICE + 1: + cboPort0->setSelected(1); + break; + case JSEM_JOYS: + if(changed_prefs.jports[0].mode != JSEM_MODE_JOYSTICK_CD32) + cboPort0->setSelected(2); + else + cboPort0->setSelected(3); + break; + default: + cboPort0->setSelected(4); + break; + } + + // Set current device in port 1 + switch(changed_prefs.jports[1].id) { + case JSEM_MICE: + cboPort1->setSelected(0); + break; + case JSEM_MICE + 1: + cboPort1->setSelected(1); + break; + case JSEM_JOYS: + if(changed_prefs.jports[1].mode != JSEM_MODE_JOYSTICK_CD32) + cboPort1->setSelected(2); + else + cboPort1->setSelected(3); + break; + default: + cboPort1->setSelected(4); + break; + } - if (changed_prefs.input_autofire_framecnt == 12) - cboAutofire->setSelected(0); - else if (changed_prefs.input_autofire_framecnt == 8) + if (changed_prefs.input_autofire_framecnt == 0) + cboAutofire->setSelected(0); + else if (changed_prefs.input_autofire_framecnt == 12) cboAutofire->setSelected(1); - else + else if (changed_prefs.input_autofire_framecnt == 8) cboAutofire->setSelected(2); + else + cboAutofire->setSelected(3); for(i=0; i<5; ++i) { @@ -557,17 +611,16 @@ void RefreshPanelInput(void) chkMouseHack->setSelected(changed_prefs.input_tablet == TABLET_MOUSEHACK); #endif chkCustomCtrl->setSelected(changed_prefs.pandora_customControls); - cboDPAD->setSelected(changed_prefs.pandora_custom_dpad); - cboA->setSelected(changed_prefs.pandora_custom_A + 8); - cboB->setSelected(changed_prefs.pandora_custom_B + 8); - cboX->setSelected(changed_prefs.pandora_custom_X + 8); - cboY->setSelected(changed_prefs.pandora_custom_Y + 8); - cboL->setSelected(changed_prefs.pandora_custom_L + 8); - cboR->setSelected(changed_prefs.pandora_custom_R + 8); - cboUp->setSelected(changed_prefs.pandora_custom_up + 8); - cboDown->setSelected(changed_prefs.pandora_custom_down + 8); - cboLeft->setSelected(changed_prefs.pandora_custom_left + 8); - cboRight->setSelected(changed_prefs.pandora_custom_right + 8); + cboA->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_HOME])); + cboB->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_END])); + cboX->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_PAGEDOWN])); + cboY->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_PAGEUP])); + cboL->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_RSHIFT])); + cboR->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_RCTRL])); + cboUp->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_UP])); + cboDown->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_DOWN])); + cboLeft->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_LEFT])); + cboRight->setSelected(GetAmigaKeyIndex(customControlMap[SDLK_RIGHT])); for(i=0; i<4; ++i) { diff --git a/src/od-pandora/gui/gui_handling.h b/src/od-pandora/gui/gui_handling.h index 130a2969..6dc1e620 100644 --- a/src/od-pandora/gui/gui_handling.h +++ b/src/od-pandora/gui/gui_handling.h @@ -37,10 +37,16 @@ extern SDL_Surface* gui_screen; extern char currentDir[MAX_DPATH]; extern char last_loaded_config[MAX_DPATH]; +#define BUILDINID_NONE 0 +#define BUILDINID_A500 1 +#define BUILDINID_A1200 2 +#define BUILDINID_CD32 3 + typedef struct { char Name[MAX_DPATH]; char FullPath[MAX_DPATH]; char Description[MAX_DPATH]; + int BuildInID; } ConfigFileInfo; extern std::vector ConfigFilesList; diff --git a/src/od-pandora/gui/main_window.cpp b/src/od-pandora/gui/main_window.cpp index 45cb9212..8ac675af 100644 --- a/src/od-pandora/gui/main_window.cpp +++ b/src/od-pandora/gui/main_window.cpp @@ -27,7 +27,7 @@ ConfigCategory categories[] = { { "ROM", "data/chip.ico", NULL, NULL, InitPanelROM, ExitPanelROM, RefreshPanelROM }, { "RAM", "data/chip.ico", NULL, NULL, InitPanelRAM, ExitPanelRAM, RefreshPanelRAM }, { "Floppy drives", "data/35floppy.ico", NULL, NULL, InitPanelFloppy, ExitPanelFloppy, RefreshPanelFloppy }, - { "Hard drives", "data/drive.ico", NULL, NULL, InitPanelHD, ExitPanelHD, RefreshPanelHD }, + { "Hard drives / CD", "data/drive.ico", NULL, NULL, InitPanelHD, ExitPanelHD, RefreshPanelHD }, { "Display", "data/screen.ico", NULL, NULL, InitPanelDisplay, ExitPanelDisplay, RefreshPanelDisplay }, { "Sound", "data/sound.ico", NULL, NULL, InitPanelSound, ExitPanelSound, RefreshPanelSound }, { "Input", "data/joystick.ico", NULL, NULL, InitPanelInput, ExitPanelInput, RefreshPanelInput }, diff --git a/src/od-pandora/inputmode.cpp b/src/od-pandora/inputmode.cpp deleted file mode 100644 index 31106aca..00000000 --- a/src/od-pandora/inputmode.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include "sysconfig.h" -#include "sysdeps.h" -#include "config.h" -#include "options.h" -#include "gp2x.h" -#include "inputmode.h" -#include "uae.h" -#include "target.h" - -extern SDL_Surface *prSDLScreen; - -static SDL_Surface *inputMode[3]; - - -void inputmode_close(void) -{ - for(int i=0; i<3; ++i) - { - if(inputMode[i] != NULL) - { - SDL_FreeSurface(inputMode[i]); - inputMode[i] = NULL; - } - } -} - - -void inputmode_init(void) -{ - int i; - char tmpchar[256]; - SDL_Surface* tmp; - - if(inputMode[0] == NULL) - { - snprintf(tmpchar, 256, "%s/data/joystick.bmp", start_path_data); - tmp = SDL_LoadBMP(tmpchar); - - if (tmp) - { - inputMode[0] = SDL_DisplayFormat(tmp); - SDL_FreeSurface(tmp); - } - } - - if(inputMode[1] == NULL) - { - snprintf(tmpchar, 256, "%s/data/mouse.bmp", start_path_data); - tmp = SDL_LoadBMP(tmpchar); - - if (tmp) - { - inputMode[1] = SDL_DisplayFormat(tmp); - SDL_FreeSurface(tmp); - } - } - - if(inputMode[2] == NULL) - { - snprintf(tmpchar, 256, "%s/data/remapping.bmp", start_path_data); - tmp = SDL_LoadBMP(tmpchar); - - if (tmp) - { - inputMode[2] = SDL_DisplayFormat(tmp); - SDL_FreeSurface(tmp); - } - } - - show_inputmode = 0; -} - - -void inputmode_redraw(void) -{ - SDL_Rect r; - SDL_Surface* surface; - - r.x=(prSDLScreen->w-160)/2; - r.y=(prSDLScreen->h-160)/2; - r.w=160; - r.h=160; - - if (inputMode[0] && inputMode[1] && inputMode[2]) - { - surface = inputMode[currprefs.pandora_custom_dpad]; - - SDL_BlitSurface(surface,NULL,prSDLScreen,&r); - } -} - - -void set_joyConf(struct uae_prefs *p) -{ - if(p->pandora_joyConf == 0) - { - p->pandora_button1 = GP2X_BUTTON_X; - p->pandora_button2 = GP2X_BUTTON_A; - p->pandora_jump = -1; - p->pandora_autofireButton1 = GP2X_BUTTON_B; - } - else if(p->pandora_joyConf == 1) - { - p->pandora_button1 = GP2X_BUTTON_B; - p->pandora_button2 = GP2X_BUTTON_A; - p->pandora_jump = -1; - p->pandora_autofireButton1 = GP2X_BUTTON_X; - } - else if(p->pandora_joyConf == 2) - { - p->pandora_button1 = GP2X_BUTTON_Y; - p->pandora_button2 = GP2X_BUTTON_A; - p->pandora_jump = GP2X_BUTTON_X; - p->pandora_autofireButton1 = GP2X_BUTTON_B; - } - else if(changed_prefs.pandora_joyConf == 3) - { - p->pandora_button1 = GP2X_BUTTON_B; - p->pandora_button2 = GP2X_BUTTON_A; - p->pandora_jump = GP2X_BUTTON_X; - p->pandora_autofireButton1 = GP2X_BUTTON_Y; - } -} - - -int is_tablet (void) -{ - return 0; -} diff --git a/src/od-pandora/inputmode.h b/src/od-pandora/inputmode.h deleted file mode 100644 index 23d45ac5..00000000 --- a/src/od-pandora/inputmode.h +++ /dev/null @@ -1,11 +0,0 @@ - -#define SIMULATE_SHIFT 0x200 -#define SIMULATE_RELEASED_SHIFT 0x400 - -void inputmode_close(void); -void inputmode_init(void); -void inputmode_redraw(void); - -void set_joyConf(struct uae_prefs *p); - -extern int show_inputmode; diff --git a/src/od-pandora/joystick.cpp b/src/od-pandora/joystick.cpp deleted file mode 100644 index e6c001e7..00000000 --- a/src/od-pandora/joystick.cpp +++ /dev/null @@ -1,337 +0,0 @@ - /* - * UAE - The Un*x Amiga Emulator - * - * Joystick emulation for Linux and BSD. They share too much code to - * split this file. - * - * Copyright 1997 Bernd Schmidt - * Copyright 1998 Krister Walfridsson - */ - -#include "sysconfig.h" -#include "sysdeps.h" - -#include "config.h" -#include "uae.h" -#include "options.h" -#include "memory.h" -#include "newcpu.h" -#include "custom.h" -#include "joystick.h" -#include "inputdevice.h" -#include "SDL.h" - -#ifdef GP2X -#include "gp2x.h" -#include "xwin.h" -#if defined(PANDORA) || defined (ANDROIDSDL) -extern int dpadUp; -extern int dpadDown; -extern int dpadLeft; -extern int dpadRight; -extern int buttonA; -extern int buttonB; -extern int buttonX; -extern int buttonY; -extern int triggerL; -extern int triggerR; -#endif - -static int delay=0; -#endif - - -int nr_joysticks; -char JoystickName[4][40]; - -static SDL_Joystick *uae4all_joy0 = 0, *uae4all_joy1 = 0 , *uae4all_joy2 = 0, *uae4all_joy3 = 0; - -void read_joystick(int nr, unsigned int *dir, int *button) -{ - int left = 0, right = 0, top = 0, bot = 0; - SDL_Joystick *joy = nr == 1 ? uae4all_joy0 : uae4all_joy1; - - if(nr == 0) - { - static int last_buttonstate0 = 0; - static int delay_leftmouse = 0; - - if(last_buttonstate0 != buttonstate[0]) - { - last_buttonstate0 = buttonstate[0]; - if(buttonstate[0]) - { - // Left mousebutton click -> delay click - delay_leftmouse = 2; - } - } - if(delay_leftmouse) - { - --delay_leftmouse; - *button = (buttonstate[2] ? 2 : 0) | (buttonstate[1] ? 4 : 0); - } - else - *button = (buttonstate[0] ? 1 : 0) | (buttonstate[2] ? 2 : 0) | (buttonstate[1] ? 4 : 0); - } - else - *button = 0; - -#ifndef RASPBERRY - if(currprefs.pandora_joyPort != 0) - { - // Only one joystick active - if((nr == 0 && currprefs.pandora_joyPort == 2) || (nr == 1 && currprefs.pandora_joyPort == 1)) - return; - } -#endif - - *dir = 0; - - SDL_JoystickUpdate (); - - - if (nr != 1) - { - // get joystick direction via joystick or Hat - int hat = SDL_JoystickGetHat(joy,0); - int val = SDL_JoystickGetAxis(joy, 0); - if ((hat & SDL_HAT_RIGHT) || (val > 6000)) right=1; - if ((hat & SDL_HAT_LEFT) || (val < -6000)) left=1; - val = SDL_JoystickGetAxis(joy, 1); - if ((hat & SDL_HAT_UP) || (val < -6000)) top=1; - if ((hat & SDL_HAT_DOWN) || (val > 6000)) bot=1; - - *button |= (SDL_JoystickGetButton(joy, 0)) & 1; - *button |= ((SDL_JoystickGetButton(joy, 1)) & 1) << 1; - - #ifdef SIX_AXIS_WORKAROUND - *button |= (SDL_JoystickGetButton(joy, 13)) & 1; - *button |= ((SDL_JoystickGetButton(joy, 14)) & 1) << 1; - - if ( SDL_JoystickGetButton(joy, 4)) top =1; - if ( SDL_JoystickGetButton(joy, 5)) right=1; - if ( SDL_JoystickGetButton(joy, 6)) bot =1; - if ( SDL_JoystickGetButton(joy, 7)) left =1; - #endif - - // Go over custom management which is only available for first joystick. - goto no_custom; - } - - -#ifdef PANDORA_SPECIFIC - if (!triggerR /*R+dpad = arrow keys*/ && currprefs.pandora_custom_dpad==0) -#endif - { - // get joystick direction via dPad or joystick or Hat - int hat = SDL_JoystickGetHat(joy,0); - int val = SDL_JoystickGetAxis(joy, 0); - if (((hat & SDL_HAT_RIGHT) && currprefs.pandora_custom_dpad < 2) || (dpadRight && currprefs.pandora_custom_dpad < 2) || val > 6000) right=1; - if (((hat & SDL_HAT_LEFT) && currprefs.pandora_custom_dpad < 2) || (dpadLeft && currprefs.pandora_custom_dpad < 2) || val < -6000) left=1; - val = SDL_JoystickGetAxis(joy, 1); - if (((hat & SDL_HAT_UP) && currprefs.pandora_custom_dpad < 2) || (dpadUp && currprefs.pandora_custom_dpad < 2) || val < -6000) top=1; - if (((hat & SDL_HAT_DOWN) && currprefs.pandora_custom_dpad < 2) || (dpadDown && currprefs.pandora_custom_dpad < 2) || val > 6000) bot=1; - - if (currprefs.pandora_joyConf) - { - if ((buttonX && currprefs.pandora_jump > -1) || SDL_JoystickGetButton(joy, currprefs.pandora_jump)) - top = 1; - } - } - - - - if(currprefs.pandora_customControls) - { - // get joystick direction via custom keys - if((currprefs.pandora_custom_A==-5 && buttonA) || (currprefs.pandora_custom_B==-5 && buttonB) || (currprefs.pandora_custom_X==-5 && buttonX) || (currprefs.pandora_custom_Y==-5 && buttonY) || (currprefs.pandora_custom_L==-5 && triggerL) || (currprefs.pandora_custom_R==-5 && triggerR)) - top = 1; - else if(currprefs.pandora_custom_dpad == 2) - { - if((currprefs.pandora_custom_up==-5 && dpadUp) || (currprefs.pandora_custom_down==-5 && dpadDown) || (currprefs.pandora_custom_left==-5 && dpadLeft) || (currprefs.pandora_custom_right==-5 && dpadRight)) - top = 1; - } - - if((currprefs.pandora_custom_A==-6 && buttonA) || (currprefs.pandora_custom_B==-6 && buttonB) || (currprefs.pandora_custom_X==-6 && buttonX) || (currprefs.pandora_custom_Y==-6 && buttonY) || (currprefs.pandora_custom_L==-6 && triggerL) || (currprefs.pandora_custom_R==-6 && triggerR)) - bot = 1; - else if(currprefs.pandora_custom_dpad == 2) - { - if((currprefs.pandora_custom_up==-6 && dpadUp) || (currprefs.pandora_custom_down==-6 && dpadDown) || (currprefs.pandora_custom_left==-6 && dpadLeft) || (currprefs.pandora_custom_right==-6 && dpadRight)) - bot = 1; - } - - if((currprefs.pandora_custom_A==-7 && buttonA) || (currprefs.pandora_custom_B==-7 && buttonB) || (currprefs.pandora_custom_X==-7 && buttonX) || (currprefs.pandora_custom_Y==-7 && buttonY) || (currprefs.pandora_custom_L==-7 && triggerL) || (currprefs.pandora_custom_R==-7 && triggerR)) - left = 1; - else if(currprefs.pandora_custom_dpad == 2) - { - if((currprefs.pandora_custom_up==-7 && dpadUp) || (currprefs.pandora_custom_down==-7 && dpadDown) || (currprefs.pandora_custom_left==-7 && dpadLeft) || (currprefs.pandora_custom_right==-7 && dpadRight)) - left = 1; - } - - if((currprefs.pandora_custom_A==-8 && buttonA) || (currprefs.pandora_custom_B==-8 && buttonB) || (currprefs.pandora_custom_X==-8 && buttonX) || (currprefs.pandora_custom_Y==-8 && buttonY) || (currprefs.pandora_custom_L==-8 && triggerL) || (currprefs.pandora_custom_R==-8 && triggerR)) - right = 1; - else if(currprefs.pandora_custom_dpad == 2) - { - if((currprefs.pandora_custom_up==-8 && dpadUp) || (currprefs.pandora_custom_down==-8 && dpadDown) || (currprefs.pandora_custom_left==-8 && dpadLeft) || (currprefs.pandora_custom_right==-8 && dpadRight)) - right = 1; - } - } - - - if(currprefs.pandora_custom_dpad == 0) // dPad as joystick - { - // Handle autofire (only available if no custom controls active) - if(!currprefs.pandora_customControls && - (((currprefs.pandora_autofireButton1==GP2X_BUTTON_B && buttonA) - || (currprefs.pandora_autofireButton1==GP2X_BUTTON_X && buttonX) - || (currprefs.pandora_autofireButton1==GP2X_BUTTON_Y && buttonY)) - && delay > currprefs.input_autofire_framecnt)) - { - if(!buttonB) - *button |= 1; - delay=0; - *button |= (buttonB & 1) << 1; - } - } - - if(currprefs.pandora_customControls) - { - // get joystick button via custom controls - if((currprefs.pandora_custom_A==-3 && buttonA) || (currprefs.pandora_custom_B==-3 && buttonB) || (currprefs.pandora_custom_X==-3 && buttonX) || (currprefs.pandora_custom_Y==-3 && buttonY) || (currprefs.pandora_custom_L==-3 && triggerL) || (currprefs.pandora_custom_R==-3 && triggerR)) - *button |= 1; - else if(currprefs.pandora_custom_dpad == 2) - { - if((currprefs.pandora_custom_up==-3 && dpadUp) || (currprefs.pandora_custom_down==-3 && dpadDown) || (currprefs.pandora_custom_left==-3 && dpadLeft) || (currprefs.pandora_custom_right==-3 && dpadRight)) - *button |= 1; - } - - if((currprefs.pandora_custom_A==-4 && buttonA) || (currprefs.pandora_custom_B==-4 && buttonB) || (currprefs.pandora_custom_X==-4 && buttonX) || (currprefs.pandora_custom_Y==-4 && buttonY) || (currprefs.pandora_custom_L==-4 && triggerL) || (currprefs.pandora_custom_R==-4 && triggerR)) - *button |= 1 << 1; - else if(currprefs.pandora_custom_dpad == 2) - { - if((currprefs.pandora_custom_up==-4 && dpadUp) || (currprefs.pandora_custom_down==-4 && dpadDown) || (currprefs.pandora_custom_left==-4 && dpadLeft) || (currprefs.pandora_custom_right==-4 && dpadRight)) - *button |= 1 << 1; - } - delay++; - } - else - { - // get joystick button via ABXY or joystick - if (!currprefs.pandora_customControls) - { - if (!currprefs.pandora_button1 == 3 && currprefs.pandora_joyConf < 2) - { - *button |= ((currprefs.pandora_button1==GP2X_BUTTON_B && buttonA) || (currprefs.pandora_button1==GP2X_BUTTON_X && buttonX) || (currprefs.pandora_button1==GP2X_BUTTON_Y && buttonY) || SDL_JoystickGetButton(joy, currprefs.pandora_button1)) & 1; - } - else - { - *button |= ((currprefs.pandora_button1==GP2X_BUTTON_B && buttonA) || (currprefs.pandora_button1==GP2X_BUTTON_X && buttonX)) & 1; - } - delay++; - } - - if (!SDL_JoystickGetButton(joy, 1)) - *button |= ((buttonB || SDL_JoystickGetButton(joy, currprefs.pandora_button2)) & 1) << 1; - - } - - - #ifdef RASPBERRY - if(!currprefs.pandora_customControls || currprefs.pandora_custom_A == 0) - *button |= (SDL_JoystickGetButton(joy, 0)) & 1; - if(!currprefs.pandora_customControls || currprefs.pandora_custom_B == 0) - *button |= ((SDL_JoystickGetButton(joy, 1)) & 1) << 1; - #endif - - #ifdef SIX_AXIS_WORKAROUND - *button |= (SDL_JoystickGetButton(joy, 13)) & 1; - *button |= ((SDL_JoystickGetButton(joy, 14)) & 1) << 1; - if (!currprefs.pandora_customControls && SDL_JoystickGetButton(joy, 4)) top=1; - if (!currprefs.pandora_customControls && SDL_JoystickGetButton(joy, 5)) right=1; - if (!currprefs.pandora_customControls && SDL_JoystickGetButton(joy, 6)) bot=1; - if (!currprefs.pandora_customControls && SDL_JoystickGetButton(joy, 7)) left=1; - #endif - -no_custom: - - // normal joystick movement - if (left) - top = !top; - if (right) - bot = !bot; - *dir = bot | (right << 1) | (top << 8) | (left << 9); -} - -void handle_joymouse(void) -{ - int y = 1024; - int mouseScale = currprefs.input_joymouse_multiplier / 2; - - if (buttonY) // slow mouse active - mouseScale = currprefs.input_joymouse_multiplier / 10; - - if (dpadLeft) { - setmousestate(0, 0, -mouseScale, 0); - y = 0; - } - if (dpadRight) { - setmousestate(0, 0, mouseScale, 0); - y = 0; - } - if (dpadUp) { - y = -mouseScale; - } - if (dpadDown) { - y = mouseScale; - } - if(y < 1024) - setmousestate(0, 1, y, 0); -} - -void init_joystick(void) -{ - nr_joysticks = SDL_NumJoysticks (); - if (nr_joysticks > 4) - nr_joysticks = 4; - if (nr_joysticks > 0) - { - uae4all_joy0 = SDL_JoystickOpen (0); - strncpy(JoystickName[0],SDL_JoystickName(0),40); - printf("Joystick0 : %s\n",JoystickName[0]); - printf(" Buttons: %i Axis: %i Hats: %i\n",SDL_JoystickNumButtons(uae4all_joy0),SDL_JoystickNumAxes(uae4all_joy0),SDL_JoystickNumHats(uae4all_joy0)); - } - if (nr_joysticks > 1) - { - uae4all_joy1 = SDL_JoystickOpen (1); - strncpy(JoystickName[1],SDL_JoystickName(1),40); - printf("Joystick1 : %s\n",JoystickName[1]); - printf(" Buttons: %i Axis: %i Hats: %i\n",SDL_JoystickNumButtons(uae4all_joy1),SDL_JoystickNumAxes(uae4all_joy1),SDL_JoystickNumHats(uae4all_joy1)); - } - if (nr_joysticks > 2) - { - uae4all_joy2 = SDL_JoystickOpen (2); - strncpy(JoystickName[2],SDL_JoystickName(2),40); - printf("Joystick2 : %s\n",JoystickName[2]); - printf(" Buttons: %i Axis: %i Hats: %i\n",SDL_JoystickNumButtons(uae4all_joy2),SDL_JoystickNumAxes(uae4all_joy2),SDL_JoystickNumHats(uae4all_joy2)); - } - if (nr_joysticks > 3) - { - uae4all_joy3 = SDL_JoystickOpen (3); - strncpy(JoystickName[3],SDL_JoystickName(3),40); - printf("Joystick3 : %s\n",JoystickName[3]); - printf(" Buttons: %i Axis: %i Hats: %i\n",SDL_JoystickNumButtons(uae4all_joy3),SDL_JoystickNumAxes(uae4all_joy3),SDL_JoystickNumHats(uae4all_joy3)); - } - -} - -void close_joystick(void) -{ - if (nr_joysticks > 0) - SDL_JoystickClose (uae4all_joy0); - if (nr_joysticks > 1) - SDL_JoystickClose (uae4all_joy1); - if (nr_joysticks > 2) - SDL_JoystickClose (uae4all_joy2); - if (nr_joysticks > 3) - SDL_JoystickClose (uae4all_joy3); -} diff --git a/src/od-pandora/keyboard.cpp b/src/od-pandora/keyboard.cpp index 20b9b043..65a94c95 100644 --- a/src/od-pandora/keyboard.cpp +++ b/src/od-pandora/keyboard.cpp @@ -8,270 +8,283 @@ #include "custom.h" #include "xwin.h" #include "drawing.h" +#include "inputdevice.h" #include "keyboard.h" #include "keybuf.h" #include "gui.h" #include -/* Decode KeySyms. This function knows about all keys that are common - * between different keyboard languages. */ -static int kc_decode (SDL_keysym *prKeySym) -{ -#ifdef PANDORA - // Special handling of Pandora keyboard: - // Some keys requires shift on Amiga, so we simulate shift... +static struct uae_input_device_kbr_default keytrans_amiga[] = { - switch (prKeySym->sym) + { SDLK_a, INPUTEVENT_KEY_A }, + { SDLK_b, INPUTEVENT_KEY_B }, + { SDLK_c, INPUTEVENT_KEY_C }, + { SDLK_d, INPUTEVENT_KEY_D }, + { SDLK_e, INPUTEVENT_KEY_E }, + { SDLK_f, INPUTEVENT_KEY_F }, + { SDLK_g, INPUTEVENT_KEY_G }, + { SDLK_h, INPUTEVENT_KEY_H }, + { SDLK_i, INPUTEVENT_KEY_I }, + { SDLK_j, INPUTEVENT_KEY_J }, + { SDLK_k, INPUTEVENT_KEY_K }, + { SDLK_l, INPUTEVENT_KEY_L }, + { SDLK_m, INPUTEVENT_KEY_M }, + { SDLK_n, INPUTEVENT_KEY_N }, + { SDLK_o, INPUTEVENT_KEY_O }, + { SDLK_p, INPUTEVENT_KEY_P }, + { SDLK_q, INPUTEVENT_KEY_Q }, + { SDLK_r, INPUTEVENT_KEY_R }, + { SDLK_s, INPUTEVENT_KEY_S }, + { SDLK_t, INPUTEVENT_KEY_T }, + { SDLK_u, INPUTEVENT_KEY_U }, + { SDLK_v, INPUTEVENT_KEY_W }, + { SDLK_w, INPUTEVENT_KEY_V }, + { SDLK_x, INPUTEVENT_KEY_X }, + { SDLK_y, INPUTEVENT_KEY_Y }, + { SDLK_z, INPUTEVENT_KEY_Z }, + + { SDLK_0, INPUTEVENT_KEY_0 }, + { SDLK_1, INPUTEVENT_KEY_1 }, + { SDLK_2, INPUTEVENT_KEY_2 }, + { SDLK_3, INPUTEVENT_KEY_3 }, + { SDLK_4, INPUTEVENT_KEY_4 }, + { SDLK_5, INPUTEVENT_KEY_5 }, + { SDLK_6, INPUTEVENT_KEY_6 }, + { SDLK_7, INPUTEVENT_KEY_7 }, + { SDLK_8, INPUTEVENT_KEY_8 }, + { SDLK_9, INPUTEVENT_KEY_9 }, + + { SDLK_BACKSPACE, INPUTEVENT_KEY_BACKSPACE }, + { SDLK_TAB, INPUTEVENT_KEY_TAB }, + { SDLK_RETURN, INPUTEVENT_KEY_RETURN }, + { SDLK_ESCAPE, INPUTEVENT_KEY_ESC }, + { SDLK_SPACE, INPUTEVENT_KEY_SPACE }, + { SDLK_QUOTE, INPUTEVENT_KEY_SINGLEQUOTE }, + { SDLK_COMMA, INPUTEVENT_KEY_COMMA }, + { SDLK_MINUS, INPUTEVENT_KEY_SUB }, + { SDLK_PERIOD, INPUTEVENT_KEY_PERIOD }, + { SDLK_SLASH, INPUTEVENT_KEY_DIV }, + + { SDLK_SEMICOLON, INPUTEVENT_KEY_SEMICOLON }, + { SDLK_EQUALS, INPUTEVENT_KEY_EQUALS }, + { SDLK_LEFTBRACKET, INPUTEVENT_KEY_LEFTBRACKET }, + { SDLK_BACKSLASH, INPUTEVENT_KEY_BACKSLASH }, + { SDLK_RIGHTBRACKET, INPUTEVENT_KEY_RIGHTBRACKET }, + { SDLK_BACKQUOTE, INPUTEVENT_KEY_BACKQUOTE }, + { SDLK_DELETE, INPUTEVENT_KEY_DEL }, + + { -1, 0 } +}; + +static struct uae_input_device_kbr_default *keytrans[] = { + keytrans_amiga, + keytrans_amiga, + keytrans_amiga +}; + +static int kb_none[] = { -1 }; +static int *kbmaps[] = { kb_none, kb_none, kb_none, kb_none, kb_none, + kb_none, kb_none, kb_none, kb_none, kb_none }; + + +void keyboard_settrans (void) +{ + inputdevice_setkeytranslation (keytrans, kbmaps); +} + + +int translate_pandora_keys(int symbol, int *modifier) +{ + switch(symbol) { - case SDLK_QUESTION: - return SIMULATE_SHIFT | AK_SLASH; - case SDLK_HASH: - return SIMULATE_SHIFT | AK_3; - case SDLK_DOLLAR: - return SIMULATE_SHIFT | AK_4; - case SDLK_QUOTEDBL: - return SIMULATE_SHIFT | AK_QUOTE; - case SDLK_PLUS: - return SIMULATE_SHIFT | AK_EQUAL; - case SDLK_AT: - return SIMULATE_SHIFT | AK_2; - case SDLK_LEFTPAREN: - return SIMULATE_SHIFT | AK_9; - case SDLK_RIGHTPAREN: - return SIMULATE_SHIFT | AK_0; + case SDLK_UP: + if(*modifier == KMOD_RCTRL) { // Right shoulder + dPad -> cursor keys + *modifier = KMOD_NONE; + return AK_UP; + } + break; + + case SDLK_DOWN: + if(*modifier == KMOD_RCTRL) { // Right shoulder + dPad -> cursor keys + *modifier = KMOD_NONE; + return AK_DN; + } + break; + + case SDLK_LEFT: + if(*modifier == KMOD_RCTRL) { // Right shoulder + dPad -> cursor keys + *modifier = KMOD_NONE; + return AK_LF; + } + break; + + case SDLK_RIGHT: + if(*modifier == KMOD_RCTRL) { // Right shoulder + dPad -> cursor keys + *modifier = KMOD_NONE; + return AK_RT; + } + break; + + case SDLK_HOME: + if(*modifier == KMOD_RCTRL) { // Right shoulder + button A -> CTRL + *modifier = KMOD_NONE; + return AK_CTRL; + } + break; + + case SDLK_END: + if(*modifier == KMOD_RCTRL) { // Right shoulder + button B -> left ALT + *modifier = KMOD_NONE; + return AK_LALT; + } + break; + + case SDLK_PAGEDOWN: + if(*modifier == KMOD_RCTRL) { // Right shoulder + button X -> HELP + *modifier = KMOD_NONE; + return AK_HELP; + } + break; + + case SDLK_PAGEUP: // button Y -> Space + *modifier = KMOD_NONE; + return AK_SPC; + + case SDLK_F1: + *modifier = KMOD_NONE; + return AK_F1; + + case SDLK_F2: + *modifier = KMOD_NONE; + return AK_F2; + + case SDLK_F3: + *modifier = KMOD_NONE; + return AK_F3; + + case SDLK_F4: + *modifier = KMOD_NONE; + return AK_F4; + + case SDLK_F5: + *modifier = KMOD_NONE; + return AK_F5; + + case SDLK_F6: + *modifier = KMOD_NONE; + return AK_F6; + + case SDLK_F7: + *modifier = KMOD_NONE; + return AK_F7; + + case SDLK_F8: + *modifier = KMOD_NONE; + return AK_F8; + + case SDLK_F9: + *modifier = KMOD_NONE; + return AK_F9; + + case SDLK_F10: + *modifier = KMOD_NONE; + return AK_F10; + case SDLK_EXCLAIM: - return SIMULATE_SHIFT | AK_1; + *modifier = KMOD_SHIFT; + return AK_1; + + case SDLK_QUOTEDBL: + *modifier = KMOD_SHIFT; + return AK_QUOTE; + + case SDLK_HASH: + *modifier = KMOD_SHIFT; + return AK_3; + + case SDLK_DOLLAR: + *modifier = KMOD_SHIFT; + return AK_4; + + case SDLK_AMPERSAND: + *modifier = KMOD_SHIFT; + return AK_7; + + case SDLK_LEFTPAREN: + *modifier = KMOD_SHIFT; + return AK_9; + + case SDLK_RIGHTPAREN: + *modifier = KMOD_SHIFT; + return AK_0; + + case SDLK_ASTERISK: + *modifier = KMOD_SHIFT; + return AK_8; + + case SDLK_PLUS: + *modifier = KMOD_SHIFT; + return AK_EQUAL; + + case SDLK_COLON: + *modifier = KMOD_SHIFT; + return AK_SEMICOLON; + + case SDLK_QUESTION: + *modifier = KMOD_SHIFT; + return AK_SLASH; + + case SDLK_AT: + *modifier = KMOD_SHIFT; + return AK_2; + + case SDLK_CARET: + *modifier = KMOD_SHIFT; + return AK_6; + case SDLK_UNDERSCORE: - return SIMULATE_SHIFT | AK_MINUS; - case SDLK_2: - if(prKeySym->mod == KMOD_LSHIFT) - return SIMULATE_SHIFT | AK_LBRACKET; - break; - case SDLK_3: - if(prKeySym->mod == KMOD_LSHIFT) - return SIMULATE_SHIFT | AK_RBRACKET; - break; - case SDLK_4: - if(prKeySym->mod == KMOD_LSHIFT) - return SIMULATE_SHIFT | AK_BACKQUOTE; - break; - case SDLK_9: - if(prKeySym->mod == KMOD_LSHIFT) - return SIMULATE_RELEASED_SHIFT | AK_LBRACKET; - break; - case SDLK_0: - if(prKeySym->mod == KMOD_LSHIFT) - return SIMULATE_RELEASED_SHIFT | AK_RBRACKET; - break; + *modifier = KMOD_SHIFT; + return AK_MINUS; + case 124: // code for '|' - return SIMULATE_SHIFT | AK_BACKSLASH; + *modifier = KMOD_SHIFT; + return AK_BACKSLASH; + + case SDLK_2: + if(*modifier == KMOD_LSHIFT) { // '{' + *modifier = KMOD_SHIFT; + return AK_LBRACKET; + } + break; + + case SDLK_3: + if(*modifier == KMOD_LSHIFT) { // '}' + *modifier = KMOD_SHIFT; + return AK_RBRACKET; + } + break; + + case SDLK_4: + if(*modifier == KMOD_LSHIFT) { // '~' + *modifier = KMOD_SHIFT; + return AK_BACKQUOTE; + } + break; + + case SDLK_9: + if(*modifier == KMOD_LSHIFT) { // '[' + *modifier = KMOD_NONE; + return AK_LBRACKET; + } + break; + + case SDLK_0: + if(*modifier == KMOD_LSHIFT) { // ']' + *modifier = KMOD_NONE; + return AK_RBRACKET; + } + break; } -#endif - switch (prKeySym->sym) - { - case SDLK_b: return AK_B; - case SDLK_c: return AK_C; - case SDLK_d: return AK_D; - case SDLK_e: return AK_E; - case SDLK_f: return AK_F; - case SDLK_g: return AK_G; - case SDLK_h: return AK_H; - case SDLK_i: return AK_I; - case SDLK_j: return AK_J; - case SDLK_k: return AK_K; - case SDLK_l: return AK_L; - case SDLK_n: return AK_N; - case SDLK_o: return AK_O; - case SDLK_p: return AK_P; - case SDLK_r: return AK_R; - case SDLK_s: return AK_S; - case SDLK_t: return AK_T; - case SDLK_u: return AK_U; - case SDLK_v: return AK_V; - case SDLK_x: return AK_X; - - case SDLK_0: return AK_0; - case SDLK_1: return AK_1; - case SDLK_2: return AK_2; - case SDLK_3: return AK_3; - case SDLK_4: return AK_4; - case SDLK_5: return AK_5; - case SDLK_6: return AK_6; - case SDLK_7: return AK_7; - case SDLK_8: return AK_8; - case SDLK_9: return AK_9; - - case SDLK_KP0: return AK_NP0; - case SDLK_KP1: return AK_NP1; - case SDLK_KP2: return AK_NP2; - case SDLK_KP3: return AK_NP3; - case SDLK_KP4: return AK_NP4; - case SDLK_KP5: return AK_NP5; - case SDLK_KP6: return AK_NP6; - case SDLK_KP7: return AK_NP7; - case SDLK_KP8: return AK_NP8; - case SDLK_KP9: return AK_NP9; - case SDLK_KP_DIVIDE: return AK_NPDIV; - case SDLK_KP_MULTIPLY: return AK_NPMUL; - case SDLK_KP_MINUS: return AK_NPSUB; - case SDLK_KP_PLUS: return AK_NPADD; - case SDLK_KP_PERIOD: return AK_NPDEL; - case SDLK_KP_ENTER: return AK_ENT; - - case SDLK_F1: return AK_F1; - case SDLK_F2: return AK_F2; - case SDLK_F3: return AK_F3; - case SDLK_F4: return AK_F4; - case SDLK_F5: return AK_F5; - case SDLK_F6: return AK_F6; - case SDLK_F7: return AK_F7; - case SDLK_F8: return AK_F8; - case SDLK_F9: return AK_F9; - case SDLK_F10: return AK_F10; - - case SDLK_BACKSPACE: return AK_BS; - case SDLK_DELETE: return AK_DEL; - case SDLK_LCTRL: return AK_CTRL; - case SDLK_RCTRL: return AK_RCTRL; - case SDLK_TAB: return AK_TAB; - case SDLK_LALT: return AK_LALT; - case SDLK_RALT: return AK_RALT; - case SDLK_RMETA: return AK_RAMI; - case SDLK_LMETA: return AK_LAMI; - case SDLK_RETURN: return AK_RET; - case SDLK_SPACE: return AK_SPC; - case SDLK_LSHIFT: return AK_LSH; - case SDLK_RSHIFT: return AK_RSH; - case SDLK_ESCAPE: return AK_ESC; - - case SDLK_INSERT: return AK_HELP; - case SDLK_HOME: return AK_NPLPAREN; - case SDLK_END: return AK_NPRPAREN; - case SDLK_CAPSLOCK: return AK_CAPSLOCK; - - case SDLK_UP: return AK_UP; - case SDLK_DOWN: return AK_DN; - case SDLK_LEFT: return AK_LF; - case SDLK_RIGHT: return AK_RT; - - case SDLK_PAGEUP: return AK_RAMI; /* PgUp mapped to right amiga */ - case SDLK_PAGEDOWN: return AK_LAMI; /* PgDn mapped to left amiga */ - - default: return -1; - } -} - -/* - * Handle keys specific to French (and Belgian) keymaps. - * - * Number keys are broken - */ -static int decode_fr (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) { - case SDLK_a: return AK_Q; - case SDLK_m: return AK_SEMICOLON; - case SDLK_q: return AK_A; - case SDLK_y: return AK_Y; - case SDLK_w: return AK_Z; - case SDLK_z: return AK_W; - case SDLK_LEFTBRACKET: return AK_LBRACKET; - case SDLK_RIGHTBRACKET: return AK_RBRACKET; - case SDLK_COMMA: return AK_M; - case SDLK_LESS: - case SDLK_GREATER: return AK_LTGT; - case SDLK_PERIOD: - case SDLK_SEMICOLON: return AK_COMMA; - case SDLK_RIGHTPAREN: return AK_MINUS; - case SDLK_EQUALS: return AK_SLASH; - case SDLK_HASH: return AK_NUMBERSIGN; - case SDLK_SLASH: return AK_PERIOD; // Is it true ? - case SDLK_MINUS: return AK_EQUAL; - case SDLK_BACKSLASH: return AK_SLASH; - case SDLK_COLON: return AK_PERIOD; - case SDLK_EXCLAIM: return AK_BACKSLASH; // Not really... - default: printf("Unknown key: %i\n",prKeySym->sym); return -1; - } -} - -/* - * Handle keys specific to German keymaps. - */ -static int decode_de (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) { - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_w: return AK_W; - case SDLK_y: return AK_Z; - case SDLK_z: return AK_Y; - case SDLK_COLON: return SIMULATE_SHIFT | AK_SEMICOLON; - /* German umlaut oe */ - case SDLK_WORLD_86: return AK_SEMICOLON; - /* German umlaut ae */ - case SDLK_WORLD_68: return AK_QUOTE; - /* German umlaut ue */ - case SDLK_WORLD_92: return AK_LBRACKET; - case SDLK_PLUS: - case SDLK_ASTERISK: return AK_RBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_LESS: - case SDLK_GREATER: return AK_LTGT; - case SDLK_HASH: return AK_NUMBERSIGN; - /* German sharp s */ - case SDLK_WORLD_63: return AK_MINUS; - case SDLK_QUOTE: return AK_EQUAL; - case SDLK_CARET: return AK_BACKQUOTE; - case SDLK_MINUS: return AK_SLASH; - default: return -1; - } -} - - -static int decode_us (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* US specific */ - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_y: return AK_Y; - case SDLK_w: return AK_W; - case SDLK_z: return AK_Z; - case SDLK_COLON: return SIMULATE_SHIFT | AK_SEMICOLON; - case SDLK_LEFTBRACKET: return AK_LBRACKET; - case SDLK_RIGHTBRACKET: return AK_RBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_SLASH: return AK_SLASH; - case SDLK_SEMICOLON: return AK_SEMICOLON; - case SDLK_MINUS: return AK_MINUS; - case SDLK_EQUALS: return AK_EQUAL; - /* this doesn't work: */ - case SDLK_BACKQUOTE: return AK_QUOTE; - case SDLK_QUOTE: return AK_BACKQUOTE; - case SDLK_BACKSLASH: return AK_BACKSLASH; - default: return -1; - } -} - -int keycode2amiga(SDL_keysym *prKeySym) -{ - int iAmigaKeycode = kc_decode(prKeySym); - if (iAmigaKeycode == -1) - return decode_us(prKeySym); - return iAmigaKeycode; -} - -int getcapslockstate (void) -{ - return 0; -} - -void setcapslockstate (int state) -{ + return 0; } diff --git a/src/od-pandora/menu/menu_config.cpp b/src/od-pandora/menu/menu_config.cpp index 2224bbb7..c5f4ca46 100644 --- a/src/od-pandora/menu/menu_config.cpp +++ b/src/od-pandora/menu/menu_config.cpp @@ -10,17 +10,16 @@ #include "memory.h" #include "newcpu.h" #include "custom.h" -#include "od-pandora/gp2x.h" #include "uae.h" #include "disk.h" -#include "../inputmode.h" +#include "SDL.h" + +extern int customControlMap[SDLK_LAST]; static int kickstart; static int presetModeId = 2; -int saveMenu_n_savestate = 0; - static void SetPresetMode(int mode, struct uae_prefs *p) { @@ -457,8 +456,6 @@ int loadconfig_old(struct uae_prefs *p, const char *orgpath) fscanf(f,"gp2xclock=%d\n", &dummy); int joybuffer = 0; fscanf(f,"joyconf=%d\n",&joybuffer); - p->pandora_joyConf = (joybuffer & 0x0f); - p->pandora_joyPort = ((joybuffer >> 4) & 0x0f); fscanf(f,"autofireRate=%d\n",&p->input_autofire_framecnt); fscanf(f,"autofire=%d\n", &dummy); fscanf(f,"stylusOffset=%d\n",&dummy); @@ -486,17 +483,17 @@ int loadconfig_old(struct uae_prefs *p, const char *orgpath) fscanf(f,"cutLeft=%d\n", &dummy); fscanf(f,"cutRight=%d\n", &dummy); fscanf(f,"customControls=%d\n",&p->pandora_customControls); - fscanf(f,"custom_dpad=%d\n",&p->pandora_custom_dpad); - fscanf(f,"custom_up=%d\n",&p->pandora_custom_up); - fscanf(f,"custom_down=%d\n",&p->pandora_custom_down); - fscanf(f,"custom_left=%d\n",&p->pandora_custom_left); - fscanf(f,"custom_right=%d\n",&p->pandora_custom_right); - fscanf(f,"custom_A=%d\n",&p->pandora_custom_A); - fscanf(f,"custom_B=%d\n",&p->pandora_custom_B); - fscanf(f,"custom_X=%d\n",&p->pandora_custom_X); - fscanf(f,"custom_Y=%d\n",&p->pandora_custom_Y); - fscanf(f,"custom_L=%d\n",&p->pandora_custom_L); - fscanf(f,"custom_R=%d\n",&p->pandora_custom_R); + fscanf(f,"custom_dpad=%d\n",&dummy); + fscanf(f,"custom_up=%d\n",&customControlMap[SDLK_UP]); + fscanf(f,"custom_down=%d\n",&customControlMap[SDLK_DOWN]); + fscanf(f,"custom_left=%d\n",&customControlMap[SDLK_LEFT]); + fscanf(f,"custom_right=%d\n",&customControlMap[SDLK_RIGHT]); + fscanf(f,"custom_A=%d\n",&customControlMap[SDLK_HOME]); + fscanf(f,"custom_B=%d\n",&customControlMap[SDLK_END]); + fscanf(f,"custom_X=%d\n",&customControlMap[SDLK_PAGEDOWN]); + fscanf(f,"custom_Y=%d\n",&customControlMap[SDLK_PAGEUP]); + fscanf(f,"custom_L=%d\n",&customControlMap[SDLK_RSHIFT]); + fscanf(f,"custom_R=%d\n",&customControlMap[SDLK_RCTRL]); fscanf(f,"cpu=%d\n", &cpu_level); if(cpu_level > 0) // M68000 // Was old format @@ -661,7 +658,6 @@ int loadconfig_old(struct uae_prefs *p, const char *orgpath) SetPresetMode(presetModeId, p); CheckKickstart(p); - set_joyConf(p); return 1; } diff --git a/src/od-pandora/pandora.cpp b/src/od-pandora/pandora.cpp index 27f088e8..28e2c720 100644 --- a/src/od-pandora/pandora.cpp +++ b/src/od-pandora/pandora.cpp @@ -35,12 +35,13 @@ #include "savestate.h" #include "traps.h" #include "bsdsocket.h" +#include "blkdev.h" #include "native2amiga.h" #include "rtgmodes.h" #include "uaeresource.h" #include "rommgr.h" +#include "akiko.h" #include -#include "gp2x.h" #include "pandora_rp9.h" /* @@ -97,43 +98,26 @@ void dbg_list_threads(void) extern void signal_segv(int signum, siginfo_t* info, void*ptr); extern void gui_force_rtarea_hdchange(void); -extern int doStylusRightClick; -extern int mouseMoving; -extern int justClicked; -extern int fcounter; +static int delayed_mousebutton = 0; +static int doStylusRightClick; -extern int keycode2amiga(SDL_keysym *prKeySym); extern int loadconfig_old(struct uae_prefs *p, const char *orgpath); extern void SetLastActiveConfig(const char *filename); -/* Joystick */ -int JoystickButton[20]; -int JoystickQuit[2]; - -/* Keyboard and mouse */ -int buttonstate[3]; - /* Keyboard */ -int uae4all_keystate[256]; -#ifdef PANDORA -static int shiftWasPressed = 0; -#endif +int customControlMap[SDLK_LAST]; char start_path_data[MAX_DPATH]; char currentDir[MAX_DPATH]; -int show_inputmode = 0; #ifdef CAPSLOCK_DEBIAN_WORKAROUND static int capslock = 0; #endif -int sleep_resolution = 1000 / 1; static char config_path[MAX_DPATH]; static char rom_path[MAX_DPATH]; static char rp9_path[MAX_DPATH]; char last_loaded_config[MAX_DPATH] = { '\0' }; -static bool slow_mouse = false; - static bool cpuSpeedChanged = false; static int lastCpuSpeed = 600; int defaultCpuSpeed = 600; @@ -146,6 +130,9 @@ void reinit_amiga(void) { write_log("reinit_amiga() called\n"); DISK_free (); +#ifdef CD32 + akiko_free (); +#endif #ifdef FILESYS filesys_cleanup (); hardfile_reset(); @@ -156,6 +143,7 @@ void reinit_amiga(void) #endif expansion_cleanup (); #endif + device_func_reset (); memory_cleanup (); /* At this point, there might run some threads from bsdsocket.*/ @@ -315,33 +303,12 @@ void target_default_options (struct uae_prefs *p, int type) p->pandora_cpu_speed = defaultCpuSpeed; p->pandora_hide_idle_led = 0; - p->pandora_joyConf = 0; - p->pandora_joyPort = 2; p->pandora_tapDelay = 10; - - p->pandora_customControls = 0; -#ifdef RASPBERRY - p->pandora_custom_dpad = 1; -#else - p->pandora_custom_dpad = 0; -#endif - p->pandora_custom_up = 0; - p->pandora_custom_down = 0; - p->pandora_custom_left = 0; - p->pandora_custom_right = 0; - p->pandora_custom_A = 0; - p->pandora_custom_B = 0; - p->pandora_custom_X = 0; - p->pandora_custom_Y = 0; - p->pandora_custom_L = 0; - p->pandora_custom_R = 0; + p->pandora_customControls = 0; - p->pandora_button1 = GP2X_BUTTON_X; - p->pandora_button2 = GP2X_BUTTON_A; - p->pandora_autofireButton1 = GP2X_BUTTON_B; - p->pandora_jump = -1; + p->picasso96_modeflags = RGBFF_CLUT | RGBFF_R5G6B5 | RGBFF_R8G8B8A8; - p->picasso96_modeflags = RGBFF_CLUT | RGBFF_R5G6B5 | RGBFF_R8G8B8A8; + memset(customControlMap, 0, sizeof(customControlMap)); } @@ -349,27 +316,20 @@ void target_save_options (struct zfile *f, struct uae_prefs *p) { cfgfile_write (f, "pandora.cpu_speed", "%d", p->pandora_cpu_speed); cfgfile_write (f, "pandora.hide_idle_led", "%d", p->pandora_hide_idle_led); - cfgfile_write (f, "pandora.joy_conf", "%d", p->pandora_joyConf); - cfgfile_write (f, "pandora.joy_port", "%d", p->pandora_joyPort); cfgfile_write (f, "pandora.tap_delay", "%d", p->pandora_tapDelay); cfgfile_write (f, "pandora.custom_controls", "%d", p->pandora_customControls); - cfgfile_write (f, "pandora.custom_dpad", "%d", p->pandora_custom_dpad); - cfgfile_write (f, "pandora.custom_up", "%d", p->pandora_custom_up); - cfgfile_write (f, "pandora.custom_down", "%d", p->pandora_custom_down); - cfgfile_write (f, "pandora.custom_left", "%d", p->pandora_custom_left); - cfgfile_write (f, "pandora.custom_right", "%d", p->pandora_custom_right); - cfgfile_write (f, "pandora.custom_a", "%d", p->pandora_custom_A); - cfgfile_write (f, "pandora.custom_b", "%d", p->pandora_custom_B); - cfgfile_write (f, "pandora.custom_x", "%d", p->pandora_custom_X); - cfgfile_write (f, "pandora.custom_y", "%d", p->pandora_custom_Y); - cfgfile_write (f, "pandora.custom_l", "%d", p->pandora_custom_L); - cfgfile_write (f, "pandora.custom_r", "%d", p->pandora_custom_R); + cfgfile_write (f, "pandora.custom_up", "%d", customControlMap[SDLK_UP]); + cfgfile_write (f, "pandora.custom_down", "%d", customControlMap[SDLK_DOWN]); + cfgfile_write (f, "pandora.custom_left", "%d", customControlMap[SDLK_LEFT]); + cfgfile_write (f, "pandora.custom_right", "%d", customControlMap[SDLK_RIGHT]); + cfgfile_write (f, "pandora.custom_a", "%d", customControlMap[SDLK_HOME]); + cfgfile_write (f, "pandora.custom_b", "%d", customControlMap[SDLK_END]); + cfgfile_write (f, "pandora.custom_x", "%d", customControlMap[SDLK_PAGEDOWN]); + cfgfile_write (f, "pandora.custom_y", "%d", customControlMap[SDLK_PAGEUP]); + cfgfile_write (f, "pandora.custom_l", "%d", customControlMap[SDLK_RSHIFT]); + cfgfile_write (f, "pandora.custom_r", "%d", customControlMap[SDLK_RCTRL]); cfgfile_write (f, "pandora.move_x", "%d", p->pandora_horizontal_offset); cfgfile_write (f, "pandora.move_y", "%d", p->pandora_vertical_offset); - cfgfile_write (f, "pandora.button1", "%d", p->pandora_button1); - cfgfile_write (f, "pandora.button2", "%d", p->pandora_button2); - cfgfile_write (f, "pandora.autofire_button", "%d", p->pandora_autofireButton1); - cfgfile_write (f, "pandora.jump", "%d", p->pandora_jump); } @@ -382,31 +342,31 @@ int target_parse_option (struct uae_prefs *p, const char *option, const char *va { int result = (cfgfile_intval (option, value, "cpu_speed", &p->pandora_cpu_speed, 1) || cfgfile_intval (option, value, "hide_idle_led", &p->pandora_hide_idle_led, 1) - || cfgfile_intval (option, value, "joy_conf", &p->pandora_joyConf, 1) - || cfgfile_intval (option, value, "joy_port", &p->pandora_joyPort, 1) || cfgfile_intval (option, value, "tap_delay", &p->pandora_tapDelay, 1) || cfgfile_intval (option, value, "custom_controls", &p->pandora_customControls, 1) - || cfgfile_intval (option, value, "custom_dpad", &p->pandora_custom_dpad, 1) - || cfgfile_intval (option, value, "custom_up", &p->pandora_custom_up, 1) - || cfgfile_intval (option, value, "custom_down", &p->pandora_custom_down, 1) - || cfgfile_intval (option, value, "custom_left", &p->pandora_custom_left, 1) - || cfgfile_intval (option, value, "custom_right", &p->pandora_custom_right, 1) - || cfgfile_intval (option, value, "custom_a", &p->pandora_custom_A, 1) - || cfgfile_intval (option, value, "custom_b", &p->pandora_custom_B, 1) - || cfgfile_intval (option, value, "custom_x", &p->pandora_custom_X, 1) - || cfgfile_intval (option, value, "custom_y", &p->pandora_custom_Y, 1) - || cfgfile_intval (option, value, "custom_l", &p->pandora_custom_L, 1) - || cfgfile_intval (option, value, "custom_r", &p->pandora_custom_R, 1) + || cfgfile_intval (option, value, "custom_up", &customControlMap[SDLK_UP], 1) + || cfgfile_intval (option, value, "custom_down", &customControlMap[SDLK_DOWN], 1) + || cfgfile_intval (option, value, "custom_left", &customControlMap[SDLK_LEFT], 1) + || cfgfile_intval (option, value, "custom_right", &customControlMap[SDLK_RIGHT], 1) + || cfgfile_intval (option, value, "custom_a", &customControlMap[SDLK_HOME], 1) + || cfgfile_intval (option, value, "custom_b", &customControlMap[SDLK_END], 1) + || cfgfile_intval (option, value, "custom_x", &customControlMap[SDLK_PAGEDOWN], 1) + || cfgfile_intval (option, value, "custom_y", &customControlMap[SDLK_PAGEUP], 1) + || cfgfile_intval (option, value, "custom_l", &customControlMap[SDLK_RSHIFT], 1) + || cfgfile_intval (option, value, "custom_r", &customControlMap[SDLK_RCTRL], 1) || cfgfile_intval (option, value, "move_x", &p->pandora_horizontal_offset, 1) || cfgfile_intval (option, value, "move_y", &p->pandora_vertical_offset, 1) - || cfgfile_intval (option, value, "button1", &p->pandora_button1, 1) - || cfgfile_intval (option, value, "button2", &p->pandora_button2, 1) - || cfgfile_intval (option, value, "autofire_button", &p->pandora_autofireButton1, 1) - || cfgfile_intval (option, value, "jump", &p->pandora_jump, 1) ); } +void fetch_datapath (char *out, int size) +{ + strncpy(out, start_path_data, size); + strncat(out, "/", size); +} + + void fetch_saveimagepath (char *out, int size, int dir) { strncpy(out, start_path_data, size); @@ -463,7 +423,11 @@ int target_cfgfile_load (struct uae_prefs *p, const char *filename, int type, in int i; int result = 0; + if(emulating && changed_prefs.cdslots[0].inuse) + gui_force_rtarea_hdchange(); + discard_prefs(p, type); + default_prefs(p, 0); char *ptr = strstr(filename, ".rp9"); if(ptr > 0) @@ -471,10 +435,7 @@ int target_cfgfile_load (struct uae_prefs *p, const char *filename, int type, in // Load rp9 config result = rp9_parse_file(p, filename); if(result) - { - set_joyConf(p); extractFileName(filename, last_loaded_config); - } } else { @@ -485,10 +446,7 @@ int target_cfgfile_load (struct uae_prefs *p, const char *filename, int type, in result = cfgfile_load(p, filename, &type, 0, 1); } if(result) - { - set_joyConf(p); extractFileName(filename, last_loaded_config); - } else result = loadconfig_old(p, filename); } @@ -504,10 +462,11 @@ int target_cfgfile_load (struct uae_prefs *p, const char *filename, int type, in AddFileToDiskList(p->floppyslots[i].df, 1); } - inputdevice_updateconfig (p); - - SetLastActiveConfig(filename); + if(!isdefault) + inputdevice_updateconfig (p); + SetLastActiveConfig(filename); + if(count_HDs(p) > 0) // When loading a config with HDs, always do a hardreset gui_force_rtarea_hdchange(); } @@ -652,6 +611,14 @@ void saveAdfDir(void) fputs(buffer, f); } + snprintf(buffer, MAX_DPATH, "MRUCDList=%d\n", lstMRUCDList.size()); + fputs(buffer, f); + for(i=0; i TABLET_OFF) { - int x, y; - SDL_GetMouseState(&x, &y); - setmousestate(0, 0, x, 1); - setmousestate(0, 1, y, 1); + int keycode; + int modifier; + + if(delayed_mousebutton) { + --delayed_mousebutton; + if(delayed_mousebutton == 0) + setmousebuttonstate (0, 0, 1); } -#endif - - while (SDL_PollEvent(&rEvent)) - { + + while (SDL_PollEvent(&rEvent)) { + got = 1; + switch (rEvent.type) { case SDL_QUIT: uae_quit(); break; - - case SDL_KEYDOWN: - if(rEvent.key.keysym.sym==SDLK_PAGEUP) - slow_mouse=true; -#ifdef PANDORA_SPECIFIC - if(currprefs.pandora_custom_dpad == 1) // dPad as mouse, why these emulation of key presses? - { - if(rEvent.key.keysym.sym==SDLK_RSHIFT) - { - uae4all_keystate[AK_LALT] = 1; - record_key(AK_LALT << 1); - } - if(rEvent.key.keysym.sym==SDLK_RCTRL || rEvent.key.keysym.sym==SDLK_END || rEvent.key.keysym.sym==SDLK_HOME) - { - uae4all_keystate[AK_RALT] = 1; - record_key(AK_RALT << 1); - } - if(rEvent.key.keysym.sym==SDLK_PAGEDOWN) - { - uae4all_keystate[AK_DN] = 1; - record_key(AK_DN << 1); - } - } -#endif - if (rEvent.key.keysym.sym==currprefs.key_for_input_switching) - { - // state moves thus: - // joystick mode - // mouse mode (with mouse buttons on L and R) - // remapping mode (with whatever's been supplied) - // back to start of state - - currprefs.pandora_custom_dpad++; -#ifdef RASPBERRY - if(currprefs.pandora_custom_dpad > 1) -#else - if(currprefs.pandora_custom_dpad > 2) -#endif - currprefs.pandora_custom_dpad = 0; - changed_prefs.pandora_custom_dpad = currprefs.pandora_custom_dpad; - - show_inputmode = 1; - } - - if (rEvent.key.keysym.sym==SDLK_RSHIFT || rEvent.key.keysym.sym==SDLK_RCTRL) - doStylusRightClick = 1; -#ifdef PANDORA_SPECIFIC - if (rEvent.key.keysym.sym!=SDLK_UP && rEvent.key.keysym.sym!=SDLK_DOWN && rEvent.key.keysym.sym!=SDLK_LEFT && - rEvent.key.keysym.sym!=SDLK_RIGHT && rEvent.key.keysym.sym!=SDLK_PAGEUP && rEvent.key.keysym.sym!=SDLK_PAGEDOWN && - rEvent.key.keysym.sym!=SDLK_HOME && rEvent.key.keysym.sym!=SDLK_END && rEvent.key.keysym.sym!=SDLK_LALT && - rEvent.key.keysym.sym!=SDLK_LCTRL && rEvent.key.keysym.sym!=SDLK_RSHIFT && rEvent.key.keysym.sym!=SDLK_RCTRL) -#endif - { - iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym)); -#ifdef CAPSLOCK_DEBIAN_WORKAROUND - if (iAmigaKeyCode == AK_CAPSLOCK && uae4all_keystate[AK_CAPSLOCK] == 1) {iAmigaKeyCode = -1; capslock = 1;} -#endif - if (iAmigaKeyCode >= 0) - { -#ifdef PANDORA - if(iAmigaKeyCode & SIMULATE_SHIFT) - { - // We need to simulate shift - iAmigaKeyCode = iAmigaKeyCode & 0x1ff; - shiftWasPressed = uae4all_keystate[AK_LSH]; - if(!shiftWasPressed) - { - uae4all_keystate[AK_LSH] = 1; - record_key(AK_LSH << 1); - } - } - if(iAmigaKeyCode & SIMULATE_RELEASED_SHIFT) - { - // We need to simulate released shift - iAmigaKeyCode = iAmigaKeyCode & 0x1ff; - shiftWasPressed = uae4all_keystate[AK_LSH]; - if(shiftWasPressed) - { - uae4all_keystate[AK_LSH] = 0; - record_key((AK_LSH << 1) | 1); - } - } -#endif - if (!uae4all_keystate[iAmigaKeyCode]) - { - uae4all_keystate[iAmigaKeyCode] = 1; - record_key(iAmigaKeyCode << 1); - } - } - } - break; - - case SDL_KEYUP: - if(rEvent.key.keysym.sym==SDLK_PAGEUP) - slow_mouse = false; -#ifdef PANDORA_SPECIFIC - if(currprefs.pandora_custom_dpad == 1) // dPad as mouse, why these emulation of key presses? - { - if(rEvent.key.keysym.sym==SDLK_RSHIFT) - { - uae4all_keystate[AK_LALT] = 0; - record_key((AK_LALT << 1) | 1); - } - if(rEvent.key.keysym.sym==SDLK_RCTRL || rEvent.key.keysym.sym==SDLK_END || rEvent.key.keysym.sym==SDLK_HOME) - { - uae4all_keystate[AK_RALT] = 0; - record_key((AK_RALT << 1) | 1); - } - if(rEvent.key.keysym.sym==SDLK_PAGEDOWN) - { - uae4all_keystate[AK_DN] = 0; - record_key((AK_DN << 1) | 1); - } - } -#endif - if (rEvent.key.keysym.sym==SDLK_RSHIFT || rEvent.key.keysym.sym==SDLK_RCTRL) - { - doStylusRightClick = 0; - mouseMoving = 0; - justClicked = 0; - fcounter = 0; - buttonstate[2] = 0; - } - - if (rEvent.key.keysym.sym==currprefs.key_for_input_switching) - { - show_inputmode = 0; - } -#ifdef PANDORA_SPECIFIC - if (rEvent.key.keysym.sym!=SDLK_UP && rEvent.key.keysym.sym!=SDLK_DOWN && rEvent.key.keysym.sym!=SDLK_LEFT && - rEvent.key.keysym.sym!=SDLK_RIGHT && rEvent.key.keysym.sym!=SDLK_PAGEUP && rEvent.key.keysym.sym!=SDLK_PAGEDOWN && - rEvent.key.keysym.sym!=SDLK_HOME && rEvent.key.keysym.sym!=SDLK_END && rEvent.key.keysym.sym!=SDLK_LALT && - rEvent.key.keysym.sym!=SDLK_LCTRL && rEvent.key.keysym.sym!=SDLK_RSHIFT && rEvent.key.keysym.sym!=SDLK_RCTRL) -#endif - { - iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym)); -#ifdef CAPSLOCK_DEBIAN_WORKAROUND - if (iAmigaKeyCode == AK_CAPSLOCK) if (capslock==0) iAmigaKeyCode = -1; else capslock = 0; -#endif - if (iAmigaKeyCode >= 0) - { -#ifdef PANDORA - if(iAmigaKeyCode & SIMULATE_SHIFT) - { - // We needed to simulate shift - iAmigaKeyCode = iAmigaKeyCode & 0x1ff; - if(!shiftWasPressed) - { - uae4all_keystate[AK_LSH] = 0; - record_key((AK_LSH << 1) | 1); - shiftWasPressed = 0; - } - } - if(iAmigaKeyCode & SIMULATE_RELEASED_SHIFT) - { - // We needed to simulate released shift - iAmigaKeyCode = iAmigaKeyCode & 0x1ff; - if(shiftWasPressed) - { - uae4all_keystate[AK_LSH] = 1; - record_key(AK_LSH << 1); - shiftWasPressed = 0; - } - } -#endif - uae4all_keystate[iAmigaKeyCode] = 0; - record_key((iAmigaKeyCode << 1) | 1); - } - } - break; - - case SDL_MOUSEBUTTONDOWN: - if (currprefs.pandora_custom_dpad < 2) - buttonstate[(rEvent.button.button-1)%3] = 1; - break; - - case SDL_MOUSEBUTTONUP: - if (currprefs.pandora_custom_dpad < 2) - buttonstate[(rEvent.button.button-1)%3] = 0; - break; + case SDL_KEYDOWN: + + if(rEvent.key.keysym.sym == currprefs.key_for_menu) + inputdevice_add_inputcode (AKS_ENTERGUI, 1); + switch(rEvent.key.keysym.sym) + { + + case SDLK_LSHIFT: // Shift key + inputdevice_do_keyboard(AK_LSH, 1); + break; + + case SDLK_RSHIFT: // Left shoulder button + case SDLK_RCTRL: // Right shoulder button + if(currprefs.input_tablet > TABLET_OFF) { + // Holding left or right shoulder button -> stylus does right mousebutton + doStylusRightClick = 1; + } + // Fall through... + + default: + if(currprefs.pandora_customControls) { + keycode = customControlMap[rEvent.key.keysym.sym]; + if(keycode < 0) { + // Simulate mouse or joystick + SimulateMouseOrJoy(keycode, 1); + break; + } + else if(keycode > 0) { + // Send mapped key press + inputdevice_do_keyboard(keycode, 1); + break; + } + } + else + + modifier = rEvent.key.keysym.mod; + keycode = translate_pandora_keys(rEvent.key.keysym.sym, &modifier); + if(keycode) + { + if(modifier == KMOD_SHIFT) + inputdevice_do_keyboard(AK_LSH, 1); + else + inputdevice_do_keyboard(AK_LSH, 0); + inputdevice_do_keyboard(keycode, 1); + } else { + inputdevice_translatekeycode(0, rEvent.key.keysym.sym, 1); + } + break; + } + break; + + case SDL_KEYUP: + switch(rEvent.key.keysym.sym) + { + + case SDLK_LSHIFT: // Shift key + inputdevice_do_keyboard(AK_LSH, 0); + break; + + case SDLK_RSHIFT: // Left shoulder button + case SDLK_RCTRL: // Right shoulder button + if(currprefs.input_tablet > TABLET_OFF) { + // Release left or right shoulder button -> stylus does left mousebutton + doStylusRightClick = 0; + } + // Fall through... + + default: + if(currprefs.pandora_customControls) { + keycode = customControlMap[rEvent.key.keysym.sym]; + if(keycode < 0) { + // Simulate mouse or joystick + SimulateMouseOrJoy(keycode, 0); + break; + } + else if(keycode > 0) { + // Send mapped key release + inputdevice_do_keyboard(keycode, 0); + break; + } + } + + modifier = rEvent.key.keysym.mod; + keycode = translate_pandora_keys(rEvent.key.keysym.sym, &modifier); + if(keycode) + { + inputdevice_do_keyboard(keycode, 0); + if(modifier == KMOD_SHIFT) + inputdevice_do_keyboard(AK_LSH, 0); + } else { + inputdevice_translatekeycode(0, rEvent.key.keysym.sym, 0); + } + break; + } + break; + + case SDL_MOUSEBUTTONDOWN: + if(currprefs.jports[0].id == JSEM_MICE || currprefs.jports[1].id == JSEM_MICE) { + if(rEvent.button.button == SDL_BUTTON_LEFT) { + if(currprefs.input_tablet > TABLET_OFF && !doStylusRightClick) { + // Delay mousebutton, we need new position first... + delayed_mousebutton = currprefs.pandora_tapDelay << 1; + } else { + setmousebuttonstate (0, doStylusRightClick, 1); + } + } + else if(rEvent.button.button == SDL_BUTTON_RIGHT) + setmousebuttonstate (0, 1, 1); + } + break; + + case SDL_MOUSEBUTTONUP: + if(currprefs.jports[0].id == JSEM_MICE || currprefs.jports[1].id == JSEM_MICE) { + if(rEvent.button.button == SDL_BUTTON_LEFT) { + setmousebuttonstate (0, doStylusRightClick, 0); + } + else if(rEvent.button.button == SDL_BUTTON_RIGHT) + setmousebuttonstate (0, 1, 0); + } + break; + case SDL_MOUSEMOTION: if(currprefs.input_tablet == TABLET_OFF) { - int x, y; - int mouseScale = slow_mouse ? 1 : currprefs.input_joymouse_multiplier / 2; - x = rEvent.motion.xrel; - y = rEvent.motion.yrel; + if(currprefs.jports[0].id == JSEM_MICE || currprefs.jports[1].id == JSEM_MICE) { + int x, y; + int mouseScale = currprefs.input_joymouse_multiplier / 2; + x = rEvent.motion.xrel; + y = rEvent.motion.yrel; #ifdef PANDORA_SPECIFIC - if(rEvent.motion.x == 0 && x > -4) - x = -4; - if(rEvent.motion.y == 0 && y > -4) - y = -4; - if(rEvent.motion.x == currprefs.gfx_size.width - 1 && x < 4) - x = 4; - if(rEvent.motion.y == currprefs.gfx_size.height - 1 && y < 4) - y = 4; + if(rEvent.motion.x == 0 && x > -4) + x = -4; + if(rEvent.motion.y == 0 && y > -4) + y = -4; + if(rEvent.motion.x == currprefs.gfx_size.width - 1 && x < 4) + x = 4; + if(rEvent.motion.y == currprefs.gfx_size.height - 1 && y < 4) + y = 4; #endif - setmousestate(0, 0, x * mouseScale, 0); - setmousestate(0, 1, y * mouseScale, 0); - } - break; - - case SDL_JOYBUTTONDOWN: /* Handle Joystick Button Presses */ - // Handle custom only for first joystick - if (rEvent.jbutton.which != 0) - break; - if (rEvent.jbutton.button == 8) JoystickQuit[0] = 1; //Next if statements are for buttons 8 & 9 together to quit emulator - if (rEvent.jbutton.button == 9) JoystickQuit[1] = 1; - if (JoystickQuit[0] && JoystickQuit[1]) - { - JoystickQuit[0] = 0; - JoystickQuit[1] = 0; - uae_quit(); - break; - } - if (rEvent.jbutton.button > 5 && currprefs.pandora_custom_dpad < 3) break; //Ignore buttons num above 5 if Custom DPad is not on special - if ((rEvent.jbutton.button == 0 || rEvent.jbutton.button == 1) && !currprefs.pandora_customControls) break; //Ignore buttons 0 & 1 if custom controls are not active to stop double triggering - JoystickButton[rEvent.jbutton.button] = 1; - break; - - case SDL_JOYBUTTONUP: /* Handle Joystick Button Releases */ - // Handle custom only for first joystick - if (rEvent.jbutton.which != 0) - break; - if (rEvent.jbutton.button == 8) JoystickQuit[0] = 0; - if (rEvent.jbutton.button == 9) JoystickQuit[1] = 0; - if (rEvent.jbutton.button > 5 && currprefs.pandora_custom_dpad < 3) break; //Ignore buttons num above 5 if Custom DPad is not on special - if ((rEvent.jbutton.button == 0 || rEvent.jbutton.button == 1) && !currprefs.pandora_customControls) break; //Ignore buttons 0 & 1 if custom controls are not active to stop double triggering - JoystickButton[rEvent.jbutton.button] = 0; - break; - - if (currprefs.pandora_custom_dpad == 2 ) - { - case SDL_JOYHATMOTION: - // Handle custom only for first joystick - if (rEvent.jbutton.which != 0) - break; - if (rEvent.jhat.value & SDL_HAT_UP) JoystickButton[6] = 1; else JoystickButton[6] = 0; - if (rEvent.jhat.value & SDL_HAT_DOWN) JoystickButton[7] = 1; else JoystickButton[7] = 0; - if (rEvent.jhat.value & SDL_HAT_LEFT) JoystickButton[8] = 1; else JoystickButton[8] = 0; - if (rEvent.jhat.value & SDL_HAT_RIGHT) JoystickButton[9] = 1; else JoystickButton[9] = 0; - break; - } - + setmousestate(0, 0, x * mouseScale, 0); + setmousestate(0, 1, y * mouseScale, 0); + } + } + break; } - } + } + return got; +} + + +void handle_events (void) +{ + /* Handle GUI events */ + gui_handle_events (); } diff --git a/src/od-pandora/pandora_filesys.cpp b/src/od-pandora/pandora_filesys.cpp index 32c7b2c6..1ba2b6d1 100644 --- a/src/od-pandora/pandora_filesys.cpp +++ b/src/od-pandora/pandora_filesys.cpp @@ -7,6 +7,17 @@ #include "zfile.h" +int my_setcurrentdir (const TCHAR *curdir, TCHAR *oldcur) +{ + int ret = 0; + if (oldcur) + getcwd(oldcur, MAX_DPATH); + if (curdir) + chdir (curdir); + return ret; +} + + int my_mkdir (const char*name) { return mkdir(name, 0777); diff --git a/src/od-pandora/pandora_gfx.cpp b/src/od-pandora/pandora_gfx.cpp index 05c9af28..92a028c3 100644 --- a/src/od-pandora/pandora_gfx.cpp +++ b/src/od-pandora/pandora_gfx.cpp @@ -10,7 +10,6 @@ #include "xwin.h" #include "drawing.h" #include "inputdevice.h" -#include "od-pandora/inputmode.h" #include "savestate.h" #include "picasso96.h" @@ -24,8 +23,6 @@ #include #endif -extern int stylusClickOverride; - /* SDL variable for output of emulation */ SDL_Surface *prSDLScreen = NULL; @@ -43,8 +40,6 @@ struct MultiDisplay Displays[MAX_DISPLAYS]; int screen_is_picasso = 0; -static int curr_layer_width = 0; - static SDL_Surface *current_screenshot = NULL; static char screenshot_filename_default[255]={ '/', 't', 'm', 'p', '/', 'n', 'u', 'l', 'l', '.', 'p', 'n', 'g', '\0' @@ -63,11 +58,6 @@ int delay_savestate_frame = 0; #endif -int justClicked = 0; -int mouseMoving = 0; -int fcounter = 0; -int doStylusRightClick = 0; - static unsigned long previous_synctime = 0; static unsigned long next_synctime = 0; @@ -169,15 +159,6 @@ static void CalcPandoraWidth(struct uae_prefs *p) } -void getgfxoffset (int *dxp, int *dyp, int *mxp, int *myp) -{ - *dxp = 0; - *dyp = 0; - *mxp = 1; - *myp = 1; -} - - static void open_screen(struct uae_prefs *p) { char layersize[20]; @@ -187,13 +168,11 @@ static void open_screen(struct uae_prefs *p) if(!screen_is_picasso) { CalcPandoraWidth(p); - if(curr_layer_width != p->gfx_size_fs.width) - { - snprintf(layersize, 20, "%dx480", p->gfx_size_fs.width); + + snprintf(layersize, 20, "%dx480", p->gfx_size_fs.width); #ifndef WIN32 - setenv("SDL_OMAP_LAYER_SIZE", layersize, 1); + setenv("SDL_OMAP_LAYER_SIZE", layersize, 1); #endif - } } else { @@ -235,8 +214,6 @@ static void open_screen(struct uae_prefs *p) { InitAmigaVidMode(p); init_row_map(); - - inputdevice_mouselimit(prSDLScreen->w, prSDLScreen->h); } } @@ -302,9 +279,6 @@ void unlockscr (void) void flush_screen () { - if (show_inputmode) - inputmode_redraw(); - if (savestate_state == STATE_DOSAVE) { if(delay_savestate_frame > 0) @@ -342,40 +316,6 @@ void flush_screen () next_synctime = next_synctime + time_per_frame * (1 + currprefs.gfx_framerate); init_row_map(); - - if(stylusClickOverride) - { - justClicked = 0; - mouseMoving = 0; - } - else - { - if(justClicked) - { - buttonstate[0] = 0; - buttonstate[2] = 0; - justClicked = 0; - } - - if(mouseMoving) - { - if(fcounter >= currprefs.pandora_tapDelay) - { - if(doStylusRightClick) - { - buttonstate[2] = 1; - } - else - { - buttonstate[0] = 1; - mouseMoving = 0; - justClicked = 1; - fcounter = 0; - } - } - fcounter++; - } - } } @@ -487,15 +427,10 @@ int GetSurfacePixelFormat(void) int graphics_init (void) { - int i,j; - graphics_subinit (); if (!init_colors ()) return 0; - - buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; - keyboard_init(); return 1; } @@ -617,6 +552,7 @@ static int save_thumb(char *path) #ifdef PICASSO96 + int picasso_palette (void) { int i, changed; diff --git a/src/od-pandora/pandora_gui.cpp b/src/od-pandora/pandora_gui.cpp index 0377c2de..4133d32a 100644 --- a/src/od-pandora/pandora_gui.cpp +++ b/src/od-pandora/pandora_gui.cpp @@ -29,33 +29,15 @@ #include "savestate.h" #include "filesys.h" #include "autoconf.h" +#include "blkdev.h" #include #include "td-sdl/thread.h" int emulating = 0; -extern bool switch_autofire; -static int justMovedUp=0, justMovedDown=0, justMovedLeft=0, justMovedRight=0; -static int justPressedA=0, justPressedB=0, justPressedX=0, justPressedY=0; -static int justPressedL=0, justPressedR=0; -int stylusClickOverride=0; - - -extern SDL_Surface *prSDLScreen; extern int screen_is_picasso; -int dpadUp=0; -int dpadDown=0; -int dpadLeft=0; -int dpadRight=0; -int buttonA=0; -int buttonB=0; -int buttonX=0; -int buttonY=0; -int triggerL=0; -int triggerR=0; - struct gui_msg { int num; const char *msg; @@ -82,6 +64,7 @@ struct gui_msg gui_msglist[] = { std::vector ConfigFilesList; std::vector lstAvailableROMs; std::vector lstMRUDiskList; +std::vector lstMRUCDList; void AddFileToDiskList(const char *file, int moveToTop) @@ -108,6 +91,30 @@ void AddFileToDiskList(const char *file, int moveToTop) } +void AddFileToCDList(const char *file, int moveToTop) +{ + int i; + + for(i=0; i= lstMRUCDList.size()) + lstMRUCDList.insert(lstMRUCDList.begin(), file); + + while(lstMRUCDList.size() > MAX_MRU_CDLIST) + lstMRUCDList.pop_back(); +} + + void ClearAvailableROMList(void) { while(lstAvailableROMs.size() > 0) @@ -304,6 +311,30 @@ void ReadConfigFileList(void) ClearConfigFileList(); + // Add built-in configs: A500 + ConfigFileInfo *buildin = new ConfigFileInfo(); + strcpy(buildin->FullPath, ""); + strcpy(buildin->Name, "Amiga 500"); + strcpy(buildin->Description, _T("Built-in, A500, OCS, 512KB")); + buildin->BuildInID = BUILDINID_A500; + ConfigFilesList.push_back(buildin); + + // A1200 + buildin = new ConfigFileInfo(); + strcpy(buildin->FullPath, ""); + strcpy(buildin->Name, "Amiga 1200"); + strcpy(buildin->Description, _T("Built-in, A1200")); + buildin->BuildInID = BUILDINID_A1200; + ConfigFilesList.push_back(buildin); + + // CD32 + buildin = new ConfigFileInfo(); + strcpy(buildin->FullPath, ""); + strcpy(buildin->Name, "CD32"); + strcpy(buildin->Description, _T("Built-in")); + buildin->BuildInID = BUILDINID_CD32; + ConfigFilesList.push_back(buildin); + // Read rp9 files fetch_rp9path(path, MAX_PATH); ReadDirectory(path, NULL, &files); @@ -316,6 +347,7 @@ void ReadConfigFileList(void) strncpy(tmp->Name, files[i].c_str(), MAX_DPATH); removeFileExtension(tmp->Name); strcpy(tmp->Description, _T("rp9")); + tmp->BuildInID = BUILDINID_NONE; ConfigFilesList.push_back(tmp); } @@ -331,6 +363,7 @@ void ReadConfigFileList(void) strncpy(tmp->Name, files[i].c_str(), MAX_DPATH); removeFileExtension(tmp->Name); cfgfile_get_description(tmp->FullPath, tmp->Description); + tmp->BuildInID = BUILDINID_NONE; ConfigFilesList.push_back(tmp); } @@ -347,6 +380,7 @@ void ReadConfigFileList(void) strncpy(tmp->Name, files[i].c_str(), MAX_DPATH); removeFileExtension(tmp->Name); strcpy(tmp->Description, "Old style configuration file"); + tmp->BuildInID = BUILDINID_NONE; for(int j=0; jName, tmp->Name)) @@ -390,15 +424,31 @@ static void gui_to_prefs (void) } +static void after_leave_gui(void) +{ + // Check if we have to set or clear autofire + int new_af = (changed_prefs.input_autofire_framecnt == 0) ? 0 : 1; + int update = 0; + int num; + + for(num = 0; num < 2; ++num) { + if(changed_prefs.jports[num].id == JSEM_JOYS && changed_prefs.jports[num].autofire != new_af) { + changed_prefs.jports[num].autofire = new_af; + update = 1; + } + } + if(update) + inputdevice_updateconfig(&changed_prefs); + + inputdevice_copyconfig (&changed_prefs, &currprefs); + inputdevice_config_change_test(); +} + + int gui_init (void) { int ret = 0; -#ifndef ANDROIDSDL - SDL_JoystickEventState(SDL_ENABLE); - SDL_JoystickOpen(0); -#endif - emulating=0; if(lstAvailableROMs.size() == 0) @@ -416,8 +466,8 @@ int gui_init (void) setCpuSpeed(); update_display(&changed_prefs); - inputdevice_copyconfig (&changed_prefs, &currprefs); - inputdevice_config_change_test(); + after_leave_gui(); + emulating=1; return ret; } @@ -484,16 +534,17 @@ int gui_update (void) strcat(savestate_fname,".uss"); strcat(screenshot_filename,".png"); } - return 0; + return 0; } -static void goMenu(void) +void gui_display (int shortcut) { if (quit_program != 0) return; emulating=1; pause_sound(); + blkdev_entergui(); if(lstAvailableROMs.size() == 0) RescanROMs(); @@ -510,9 +561,9 @@ static void goMenu(void) /* Clear menu garbage at the bottom of the screen */ black_screen_now(); resume_sound(); + blkdev_exitgui(); - inputdevice_copyconfig (&changed_prefs, &currprefs); - inputdevice_config_change_test (); + after_leave_gui(); gui_update (); @@ -520,30 +571,7 @@ static void goMenu(void) fpscounter_reset(); } - -static int customKey[256] = - { 0, AK_UP, AK_DN, AK_LF, AK_RT, AK_NP0, AK_NP1, AK_NP2, /* 0 - 7 */ - AK_NP3, AK_NP4, AK_NP5, AK_NP6, AK_NP7, AK_NP8, AK_NP9, AK_ENT, /* 8 - 15 */ - AK_NPDIV, AK_NPMUL, AK_NPSUB, AK_NPADD, AK_NPDEL, AK_NPLPAREN, AK_NPRPAREN, AK_SPC, /* 16 - 23 */ - AK_BS, AK_TAB, AK_RET, AK_ESC, AK_DEL, AK_LSH, AK_RSH, AK_CAPSLOCK, /* 24 - 31 */ - AK_CTRL, AK_LALT, AK_RALT, AK_LAMI, AK_RAMI, AK_HELP, AK_LBRACKET, AK_RBRACKET, /* 32 - 39 */ - AK_SEMICOLON, AK_COMMA, AK_PERIOD, AK_SLASH, AK_BACKSLASH, AK_QUOTE, AK_NUMBERSIGN, AK_LTGT, /* 40 - 47 */ - AK_BACKQUOTE, AK_MINUS, AK_EQUAL, AK_A, AK_B, AK_C, AK_D, AK_E, /* 48 - 55 */ - AK_F, AK_G, AK_H, AK_I, AK_J, AK_K, AK_L, AK_M, /* 56 - 63 */ - AK_N, AK_O, AK_P, AK_Q, AK_R, AK_S, AK_T, AK_U, /* 64 - 71 */ - AK_V, AK_W, AK_X, AK_Y, AK_Z, AK_1, AK_2, AK_3, /* 72 - 79 */ - AK_4, AK_5, AK_6, AK_7, AK_8, AK_9, AK_0, AK_F1, /* 80 - 87 */ - AK_F2, AK_F3, AK_F4, AK_F5, AK_F6, AK_F7, AK_F8, AK_F9, /* 88 - 95 */ - AK_F10, 0 }; /* 96 - 97 */ -static int getMapping(int customId) -{ - if(customId > 96) - return 0; - else - return customKey[customId]; -} - void moveVertical(int value) { changed_prefs.pandora_vertical_offset += value; @@ -556,77 +584,21 @@ void moveVertical(int value) void gui_handle_events (void) { int i; - int key = 0; Uint8 *keystate = SDL_GetKeyState(NULL); + int triggerL = keystate[SDLK_RSHIFT]; + int triggerR = keystate[SDLK_RCTRL]; -#if 1 - buttonA = JoystickButton[0]; - buttonB = JoystickButton[1]; - buttonX = JoystickButton[2]; - buttonY = JoystickButton[3]; - triggerL = JoystickButton[4]; - triggerR = JoystickButton[5]; - dpadUp = JoystickButton[6]; - dpadDown = JoystickButton[7]; - dpadLeft = JoystickButton[8]; - dpadRight= JoystickButton[9]; - - if (currprefs.pandora_custom_dpad != 1) - { - dpadUp |= keystate[SDLK_UP]; - dpadDown |= keystate[SDLK_DOWN]; - dpadLeft |= keystate[SDLK_LEFT]; - dpadRight|= keystate[SDLK_RIGHT]; - buttonA |= keystate[SDLK_HOME]; - buttonB |= keystate[SDLK_END]; - buttonX |= keystate[SDLK_PAGEDOWN]; - buttonY |= keystate[SDLK_PAGEUP]; - triggerL |= keystate[SDLK_RSHIFT]; - triggerR |= keystate[SDLK_RCTRL]; - } -#else - if(keystate[SDLK_HOME] || JoystickButton[0]) //Updated with Joystick input - buttonA = 1; else buttonA = 0; - if(keystate[SDLK_END] || JoystickButton[1]) - buttonB = 1; else buttonB = 0; - if(keystate[SDLK_PAGEDOWN] || JoystickButton[2]) - buttonX = 1; else buttonX = 0; - if(keystate[SDLK_PAGEUP] || JoystickButton[3]) - buttonY = 1; else buttonY = 0; - if(keystate[SDLK_RSHIFT] || JoystickButton[4]) - triggerL = 1; else triggerL = 0; - if(keystate[SDLK_RCTRL] || JoystickButton[5]) - triggerR = 1; else triggerR = 0; - if(keystate[SDLK_UP] || JoystickButton[6]) - dpadUp = 1; else dpadUp = 0; - if(keystate[SDLK_DOWN] || JoystickButton[7]) - dpadDown = 1; else dpadDown = 0; - if(keystate[SDLK_LEFT] || JoystickButton[8]) - dpadLeft = 1; else dpadLeft = 0; - if(keystate[SDLK_RIGHT] || JoystickButton[9]) - dpadRight = 1; else dpadRight = 0; -#endif - - if(keystate[currprefs.key_for_menu]) - goMenu(); - if(uae4all_keystate[AK_CTRL] && uae4all_keystate[AK_LAMI] && uae4all_keystate[AK_RAMI]) - uae_reset(0); - -#ifdef PANDORA_SPECIFIC - //L + R + // L + R if(triggerL && triggerR) { //up - if(dpadUp) - { + if(keystate[SDLK_UP]) moveVertical(1); - } //down - else if(dpadDown) - { + else if(keystate[SDLK_DOWN]) moveVertical(-1); - } + //1 else if(keystate[SDLK_1]) { @@ -711,34 +683,35 @@ void gui_handle_events (void) } update_display(&changed_prefs); } + // r + else if(keystate[SDLK_r]) + { + // Change resolution (lores/hires) + if(currprefs.gfx_size.width > 600) + changed_prefs.gfx_size.width = currprefs.gfx_size.width / 2; + else + changed_prefs.gfx_size.width = currprefs.gfx_size.width * 2; + update_display(&changed_prefs); + } } else if(triggerL) { if(keystate[SDLK_c]) - { - keystate[SDLK_c]=0; currprefs.pandora_customControls = !currprefs.pandora_customControls; - } + else if(keystate[SDLK_d]) - { - keystate[SDLK_d]=0; changed_prefs.leds_on_screen = !currprefs.leds_on_screen; - } + else if(keystate[SDLK_f]) - { - keystate[SDLK_f]=0; changed_prefs.gfx_framerate ? changed_prefs.gfx_framerate = 0 : changed_prefs.gfx_framerate = 1; - } + else if(keystate[SDLK_s]) - { - keystate[SDLK_s]=0; savestate_state = STATE_DOSAVE; - } + else if(keystate[SDLK_l]) { FILE *f=fopen(savestate_fname, "rb"); - keystate[SDLK_l]=0; if(f) { fclose(f); @@ -746,663 +719,6 @@ void gui_handle_events (void) } } } - -#endif - if(currprefs.pandora_customControls) - { - if(currprefs.pandora_custom_dpad == 2) // dPad is custom - { - //UP - if(dpadUp) - { - if(!justMovedUp) - { - if(currprefs.pandora_custom_up == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_up == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_up > 0) - { - key = getMapping(currprefs.pandora_custom_up); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justMovedUp=1; - } - } - else if(justMovedUp) - { - if(currprefs.pandora_custom_up == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_up == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_up > 0) - { - key = getMapping(currprefs.pandora_custom_up); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justMovedUp=0; - } - - //DOWN - if(dpadDown) - { - if(!justMovedDown) - { - if(currprefs.pandora_custom_down == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_down == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_down > 0) - { - key = getMapping(currprefs.pandora_custom_down); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justMovedDown=1; - } - } - else if(justMovedDown) - { - if(currprefs.pandora_custom_down == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_down == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_down > 0) - { - key = getMapping(currprefs.pandora_custom_down); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justMovedDown=0; - } - - //LEFT - if(dpadLeft) - { - if(!justMovedLeft) - { - if(currprefs.pandora_custom_left == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_left == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_left > 0) - { - key = getMapping(currprefs.pandora_custom_left); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justMovedLeft=1; - } - } - else if(justMovedLeft) - { - if(currprefs.pandora_custom_left == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_left == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_left > 0) - { - key = getMapping(currprefs.pandora_custom_left); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justMovedLeft=0; - } - - //RIGHT - if(dpadRight) - { - if(!justMovedRight) - { - if(currprefs.pandora_custom_right == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_right == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_right > 0) - { - key = getMapping(currprefs.pandora_custom_right); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justMovedRight=1; - } - } - else if(justMovedRight) - { - if(currprefs.pandora_custom_right == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_right == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_right > 0) - { - key = getMapping(currprefs.pandora_custom_right); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justMovedRight=0; - } - } - - //(A) - if(buttonA) - { - if(!justPressedA) - { - if(currprefs.pandora_custom_A == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_A == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_A > 0) - { - key = getMapping(currprefs.pandora_custom_A); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justPressedA=1; - } - } - else if(justPressedA) - { - if(currprefs.pandora_custom_A == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_A == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_A > 0) - { - key = getMapping(currprefs.pandora_custom_A); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justPressedA=0; - } - - //(B) - if(buttonB) - { - if(!justPressedB) - { - if(currprefs.pandora_custom_B == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_B == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_B > 0) - { - key = getMapping(currprefs.pandora_custom_B); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justPressedB=1; - } - } - else if(justPressedB) - { - if(currprefs.pandora_custom_B == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_B == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_B > 0) - { - key = getMapping(currprefs.pandora_custom_B); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justPressedB=0; - } - - //(X) - if(buttonX) - { - if(!justPressedX) - { - if(currprefs.pandora_custom_X == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_X == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_X > 0) - { - key = getMapping(currprefs.pandora_custom_X); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justPressedX=1; - } - } - else if(justPressedX) - { - if(currprefs.pandora_custom_X == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_X == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_X > 0) - { - key = getMapping(currprefs.pandora_custom_X); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justPressedX=0; - } - - //(Y) - if(buttonY) - { - if(!justPressedY) - { - if(currprefs.pandora_custom_Y == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_Y == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_Y > 0) - { - key = getMapping(currprefs.pandora_custom_Y); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justPressedY=1; - } - } - else if(justPressedY) - { - if(currprefs.pandora_custom_Y == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_Y == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_Y > 0) - { - key = getMapping(currprefs.pandora_custom_Y); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justPressedY=0; - } - - //(L) - if(triggerL) - { - if(!justPressedL) - { - if(currprefs.pandora_custom_L == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_L == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_L > 0) - { - key = getMapping(currprefs.pandora_custom_L); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justPressedL=1; - } - } - else if(justPressedL) - { - if(currprefs.pandora_custom_L == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_L == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_L > 0) - { - key = getMapping(currprefs.pandora_custom_L); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justPressedL=0; - } - - //(R) - if(triggerR) - { - if(!justPressedR) - { - if(currprefs.pandora_custom_R == -1) buttonstate[0]=1; - else if(currprefs.pandora_custom_R == -2) buttonstate[2]=1; - else if(currprefs.pandora_custom_R > 0) - { - key = getMapping(currprefs.pandora_custom_R); - uae4all_keystate[key] = 1; - record_key(key << 1); - } - justPressedR=1; - } - } - else if(justPressedR) - { - if(currprefs.pandora_custom_R == -1) buttonstate[0]=0; - else if(currprefs.pandora_custom_R == -2) buttonstate[2]=0; - else if(currprefs.pandora_custom_R > 0) - { - key = getMapping(currprefs.pandora_custom_R); - uae4all_keystate[key] = 0; - record_key((key << 1) | 1); - } - justPressedR=0; - } - } - -#ifdef RASPBERRY - - else if(currprefs.pandora_joyConf < 2) - { - // Y-Button mapped to Space - if(buttonY) - { - if(!justPressedY) - { - //SPACE - uae4all_keystate[AK_SPC] = 1; - record_key(AK_SPC << 1); - justPressedY=1; - } - } - else if(justPressedY) - { - //SPACE - uae4all_keystate[AK_SPC] = 0; - record_key((AK_SPC << 1) | 1); - justPressedY=0; - } - } - -#endif - -#ifdef PANDORA_SPECIFIC - else // Custom controls not active - { - if(currprefs.pandora_custom_dpad < 2 && triggerR) - { - //R+dpad = arrow keys in joystick and mouse mode - //dpad up - if(dpadUp) - { - if(!justMovedUp) - { - //arrow up - uae4all_keystate[AK_UP] = 1; - record_key(AK_UP << 1); - justMovedUp=1; - } - } - else if(justMovedUp) - { - //arrow up - uae4all_keystate[AK_UP] = 0; - record_key((AK_UP << 1) | 1); - justMovedUp=0; - } - //dpad down - if(dpadDown) - { - if(!justMovedDown) - { - //arrow down - uae4all_keystate[AK_DN] = 1; - record_key(AK_DN << 1); - justMovedDown=1; - } - } - else if(justMovedDown) - { - //arrow down - uae4all_keystate[AK_DN] = 0; - record_key((AK_DN << 1) | 1); - justMovedDown=0; - } - //dpad left - if(dpadLeft) - { - if(!justMovedLeft) - { - //arrow left - uae4all_keystate[AK_LF] = 1; - record_key(AK_LF << 1); - justMovedLeft=1; - } - } - else if(justMovedLeft) - { - //arrow left - uae4all_keystate[AK_LF] = 0; - record_key((AK_LF << 1) | 1); - justMovedLeft=0; - } - //dpad right - if (dpadRight) - { - if(!justMovedRight) - { - //arrow right - uae4all_keystate[AK_RT] = 1; - record_key(AK_RT << 1); - justMovedRight=1; - } - } - else if(justMovedRight) - { - //arrow right - uae4all_keystate[AK_RT] = 0; - record_key((AK_RT << 1) | 1); - justMovedRight=0; - } - } - - switch(currprefs.pandora_custom_dpad) - { - case 0: // dPad is joystick - // R-trigger emulates some Amiga-Keys - if(triggerR) - { - //(A) button - if(buttonA) - { - if(!justPressedA) - { - //CTRL - uae4all_keystate[AK_CTRL] = 1; - record_key(AK_CTRL << 1); - justPressedA=1; - } - } - else if(justPressedA) - { - uae4all_keystate[AK_CTRL] = 0; - record_key((AK_CTRL << 1) | 1); - justPressedA=0; - } - //(B) button - if(buttonB) - { - if(!justPressedB) - { - //left ALT - uae4all_keystate[AK_LALT] = 1; - record_key(AK_LALT << 1); - justPressedB=1; - } - } - else if(justPressedB) - { - uae4all_keystate[AK_LALT] = 0; - record_key((AK_LALT << 1) | 1); - justPressedB=0; - } - //(X) button - if(buttonX) - { - if(!justPressedX) - { - //HELP - uae4all_keystate[AK_HELP] = 1; - record_key(AK_HELP << 1); - justPressedX=1; - } - } - else if(justPressedX) - { - //HELP - uae4all_keystate[AK_HELP] = 0; - record_key((AK_HELP << 1) | 1); - justPressedX=0; - } - } - // L-trigger emulates left and right mouse button - else if(triggerL) - { - //(A) button - if(buttonA) - { - if(!justPressedA) - { - //left mouse-button down - buttonstate[0] = 1; - justPressedA=1; - } - } - else if(justPressedA) - { - //left mouse-button up - buttonstate[0] = 0; - justPressedA=0; - } - //(B) button - if(buttonB) - { - if(!justPressedB) - { - //right mouse-button down - buttonstate[2] = 1; - justPressedB=1; - } - } - else if(justPressedB) - { - //right mouse-button up - buttonstate[2] = 0; - justPressedB=0; - } - } - - else if(currprefs.pandora_joyConf < 2) - { - // Y-Button mapped to Space - if(buttonY) - { - if(!justPressedY) - { - //SPACE - uae4all_keystate[AK_SPC] = 1; - record_key(AK_SPC << 1); - justPressedY=1; - } - } - else if(justPressedY) - { - //SPACE - uae4all_keystate[AK_SPC] = 0; - record_key((AK_SPC << 1) | 1); - justPressedY=0; - } - } - - break; - - case 1: // dPad is mouse - // A and B emulates mouse buttons - if(buttonA) - { - if(!justPressedA) - { - //left mouse-button down - buttonstate[0] = 1; - justPressedA=1; - } - } - else if(justPressedA) - { - //left mouse-button up - buttonstate[0] = 0; - justPressedA=0; - } - //(B) button - if(buttonB) - { - if(!justPressedB) - { - //right mouse-button down - buttonstate[2] = 1; - justPressedB=1; - } - } - else if(justPressedB) - { - //right mouse-button up - buttonstate[2] = 0; - justPressedB=0; - } - - // Y emulates Space - if(buttonY) - { - if(!justPressedY) - { - //SPACE - uae4all_keystate[AK_SPC] = 1; - record_key(AK_SPC << 1); - justPressedY=1; - } - } - else if(justPressedY) - { - //SPACE - uae4all_keystate[AK_SPC] = 0; - record_key((AK_SPC << 1) | 1); - justPressedY=0; - } - - break; - - case 2: // dPad is custom (stylus) -> dPad decides which mouse button is clicked - //dpad up - if (dpadUp) - { - if(!justMovedUp) - { - //left and right mouse-buttons down - buttonstate[0] = 1; - buttonstate[2] = 1; - stylusClickOverride = 1; - justMovedUp=1; - } - } - else if(justMovedUp) - { - //left and right mouse-buttons up - buttonstate[0] = 0; - buttonstate[2] = 0; - stylusClickOverride = 0; - justMovedUp=0; - } - //dpad down - if (dpadDown) - { - if(!justMovedDown) - { - //no clicks with stylus now - stylusClickOverride=1; - justMovedDown=1; - } - } - else if(justMovedDown) - { - //clicks active again - stylusClickOverride=0; - justMovedDown=0; - } - //dpad left - if (dpadLeft) - { - if(!justMovedLeft) - { - //left mouse-button down - buttonstate[0] = 1; - stylusClickOverride = 1; - justMovedLeft=1; - } - } - else if(justMovedLeft) - { - //left mouse-button up - buttonstate[0] = 0; - stylusClickOverride = 0; - justMovedLeft=0; - } - //dpad right - if (dpadRight) - { - if(!justMovedRight) - { - //right mouse-button down - buttonstate[2] = 1; - stylusClickOverride = 1; - justMovedRight=1; - } - } - else if(justMovedRight) - { - //right mouse-button up - buttonstate[2] = 0; - stylusClickOverride = 0; - justMovedRight=0; - } - - break; - } - } -#endif } void gui_disk_image_change (int unitnum, const char *name, bool writeprotected) @@ -1485,14 +801,6 @@ int translate_message (int msg, TCHAR *out) return 0; } -void gui_lock (void) -{ -} - -void gui_unlock (void) -{ -} - void FilterFiles(std::vector *files, const char *filter[]) { diff --git a/src/od-pandora/pandora_input.cpp b/src/od-pandora/pandora_input.cpp new file mode 100644 index 00000000..50301f81 --- /dev/null +++ b/src/od-pandora/pandora_input.cpp @@ -0,0 +1,486 @@ +#include "sysconfig.h" +#include "sysdeps.h" +#include "options.h" +#include "keyboard.h" +#include "inputdevice.h" +#include + + +static int joyXviaCustom = 0; +static int joyYviaCustom = 0; +static int joyBut1viaCustom = 0; +static int joyBut2viaCustom = 0; +static int mouseBut1viaCustom = 0; +static int mouseBut2viaCustom = 0; + + +#define MAX_MOUSE_BUTTONS 2 +#define MAX_MOUSE_AXES 2 +#define FIRST_MOUSE_AXIS 0 +#define FIRST_MOUSE_BUTTON MAX_MOUSE_AXES + + +static int init_mouse (void) +{ + return 1; +} + +static void close_mouse (void) +{ +} + +static int acquire_mouse (int num, int flags) +{ + return 1; +} + +static void unacquire_mouse (int num) +{ +} + +static int get_mouse_num (void) +{ + return 2; +} + +static TCHAR *get_mouse_friendlyname (int mouse) +{ + if(mouse == 0) + return "Nubs as mouse"; + else + return "dPad as mouse"; +} + +static TCHAR *get_mouse_uniquename (int mouse) +{ + if(mouse == 0) + return "MOUSE0"; + else + return "MOUSE1"; +} + +static int get_mouse_widget_num (int mouse) +{ + return MAX_MOUSE_AXES + MAX_MOUSE_BUTTONS; +} + +static int get_mouse_widget_first (int mouse, int type) +{ + switch (type) { + case IDEV_WIDGET_BUTTON: + return FIRST_MOUSE_BUTTON; + case IDEV_WIDGET_AXIS: + return FIRST_MOUSE_AXIS; + case IDEV_WIDGET_BUTTONAXIS: + return MAX_MOUSE_AXES + MAX_MOUSE_BUTTONS; + } + return -1; +} + +static int get_mouse_widget_type (int mouse, int num, TCHAR *name, uae_u32 *code) +{ + if (num >= MAX_MOUSE_AXES && num < MAX_MOUSE_AXES + MAX_MOUSE_BUTTONS) { + if (name) + sprintf (name, "Button %d", num + 1 - MAX_MOUSE_AXES); + return IDEV_WIDGET_BUTTON; + } else if (num < MAX_MOUSE_AXES) { + if (name) { + if(num == 0) + sprintf (name, "X Axis"); + else if (num == 1) + sprintf (name, "Y Axis"); + else + sprintf (name, "Axis %d", num + 1); + } + return IDEV_WIDGET_AXIS; + } + return IDEV_WIDGET_NONE; +} + +static void read_mouse (void) +{ + if(currprefs.input_tablet > TABLET_OFF) { + // Mousehack active + int x, y; + SDL_GetMouseState(&x, &y); + setmousestate(0, 0, x, 1); + setmousestate(0, 1, y, 1); + } + + if(currprefs.jports[0].id == JSEM_MICE + 1 || currprefs.jports[1].id == JSEM_MICE + 1) { + // dPad is mouse + Uint8 *keystate = SDL_GetKeyState(NULL); + int mouseScale = currprefs.input_joymouse_multiplier / 4; + + if(keystate[SDLK_LEFT]) + setmousestate(1, 0, -mouseScale, 0); + if(keystate[SDLK_RIGHT]) + setmousestate(1, 0, mouseScale, 0); + if(keystate[SDLK_UP]) + setmousestate(1, 1, -mouseScale, 0); + if(keystate[SDLK_DOWN]) + setmousestate(1, 1, mouseScale, 0); + + if(!mouseBut1viaCustom) + setmousebuttonstate (1, 0, keystate[SDLK_HOME]); // A button -> left mouse + if(!mouseBut2viaCustom) + setmousebuttonstate (1, 1, keystate[SDLK_END]); // B button -> right mouse + } + + // Nubs as mouse handled in handle_msgpump() +} + + +static int get_mouse_flags (int num) +{ + return 0; +} + +struct inputdevice_functions inputdevicefunc_mouse = { + init_mouse, close_mouse, acquire_mouse, unacquire_mouse, read_mouse, + get_mouse_num, get_mouse_friendlyname, get_mouse_uniquename, + get_mouse_widget_num, get_mouse_widget_type, + get_mouse_widget_first, + get_mouse_flags +}; + +static void setid (struct uae_input_device *uid, int i, int slot, int sub, int port, int evt) +{ + uid->eventid[slot][SPARE_SUB_EVENT] = uid->eventid[slot][sub]; + uid->flags[slot][SPARE_SUB_EVENT] = uid->flags[slot][sub]; + uid->port[slot][SPARE_SUB_EVENT] = MAX_JPORTS + 1; + + uid[i].eventid[slot][sub] = evt; + uid[i].port[slot][sub] = port + 1; +} + +static void setid_af (struct uae_input_device *uid, int i, int slot, int sub, int port, int evt, int af) +{ + setid (uid, i, slot, sub, port, evt); + uid[i].flags[slot][sub] &= ~ID_FLAG_AUTOFIRE_MASK; + if (af >= JPORT_AF_NORMAL) + uid[i].flags[slot][sub] |= ID_FLAG_AUTOFIRE; +} + +int input_get_default_mouse (struct uae_input_device *uid, int i, int port, int af) +{ + setid (uid, i, ID_AXIS_OFFSET + 0, 0, port, port ? INPUTEVENT_MOUSE2_HORIZ : INPUTEVENT_MOUSE1_HORIZ); + setid (uid, i, ID_AXIS_OFFSET + 1, 0, port, port ? INPUTEVENT_MOUSE2_VERT : INPUTEVENT_MOUSE1_VERT); + setid_af (uid, i, ID_BUTTON_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON, af); + setid (uid, i, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_2ND_BUTTON : INPUTEVENT_JOY1_2ND_BUTTON); + + if (i == 0) + return 1; + return 0; +} + + +static int init_kb (void) +{ + return 1; +} + +static void close_kb (void) +{ +} + +static int acquire_kb (int num, int flags) +{ + return 1; +} + +static void unacquire_kb (int num) +{ +} + +static void read_kb (void) +{ +} + +static int get_kb_num (void) +{ + return 1; +} + +static TCHAR *get_kb_friendlyname (int kb) +{ + return strdup("Default Keyboard"); +} + +static TCHAR *get_kb_uniquename (int kb) +{ + return strdup("KEYBOARD0"); +} + +static int get_kb_widget_num (int kb) +{ + return 255; +} + +static int get_kb_widget_first (int kb, int type) +{ + return 0; +} + +static int get_kb_widget_type (int kb, int num, TCHAR *name, uae_u32 *code) +{ + if(code) + *code = num; + return IDEV_WIDGET_KEY; +} + +static int get_kb_flags (int num) +{ + return 0; +} + +struct inputdevice_functions inputdevicefunc_keyboard = { + init_kb, close_kb, acquire_kb, unacquire_kb, read_kb, + get_kb_num, get_kb_friendlyname, get_kb_uniquename, + get_kb_widget_num, get_kb_widget_type, + get_kb_widget_first, + get_kb_flags +}; + +int input_get_default_keyboard (int num) +{ + if (num == 0) { + return 1; + } + return 0; +} + + +#define MAX_JOY_BUTTONS 7 +#define MAX_JOY_AXES 2 +#define FIRST_JOY_AXIS 0 +#define FIRST_JOY_BUTTON MAX_JOY_AXES + + +static int get_joystick_num (void) +{ + return 1; +} + +static int init_joystick (void) +{ + return 1; +} + +static void close_joystick (void) +{ +} + +static int acquire_joystick (int num, int flags) +{ + return 1; +} + +static void unacquire_joystick (int num) +{ +} + +static TCHAR *get_joystick_friendlyname (int joy) +{ + return "dPad as joystick"; +} + +static TCHAR *get_joystick_uniquename (int joy) +{ + return "JOY0"; +} + +static int get_joystick_widget_num (int joy) +{ + return MAX_JOY_AXES + MAX_JOY_BUTTONS; +} + +static int get_joystick_widget_first (int joy, int type) +{ + switch (type) { + case IDEV_WIDGET_BUTTON: + return FIRST_JOY_BUTTON; + case IDEV_WIDGET_AXIS: + return FIRST_JOY_AXIS; + case IDEV_WIDGET_BUTTONAXIS: + return MAX_JOY_AXES + MAX_JOY_BUTTONS; + } + return -1; +} + +static int get_joystick_widget_type (int joy, int num, TCHAR *name, uae_u32 *code) +{ + if (num >= MAX_JOY_AXES && num < MAX_JOY_AXES + MAX_JOY_BUTTONS) { + if (name) { + switch(num) + { + case FIRST_JOY_BUTTON: + sprintf (name, "Button X/CD32 red"); + break; + case FIRST_JOY_BUTTON + 1: + sprintf (name, "Button B/CD32 blue"); + break; + case FIRST_JOY_BUTTON + 2: + sprintf (name, "Button A/CD32 green"); + break; + case FIRST_JOY_BUTTON + 3: + sprintf (name, "Button Y/CD32 yellow"); + break; + case FIRST_JOY_BUTTON + 4: + sprintf (name, "CD32 start"); + break; + case FIRST_JOY_BUTTON + 5: + sprintf (name, "CD32 ffw"); + break; + case FIRST_JOY_BUTTON + 6: + sprintf (name, "CD32 rwd"); + break; + } + } + return IDEV_WIDGET_BUTTON; + } else if (num < MAX_JOY_AXES) { + if (name) { + if(num == 0) + sprintf (name, "X Axis"); + else if (num == 1) + sprintf (name, "Y Axis"); + else + sprintf (name, "Axis %d", num + 1); + } + return IDEV_WIDGET_AXIS; + } + return IDEV_WIDGET_NONE; +} + +static int get_joystick_flags (int num) +{ + return 0; +} + + +static void read_joystick (void) +{ + if(currprefs.jports[0].id == JSEM_JOYS || currprefs.jports[1].id == JSEM_JOYS) { + Uint8 *keystate = SDL_GetKeyState(NULL); + + if(!keystate[SDLK_RCTRL]) { // Right shoulder + dPad -> cursor keys + int axis = (keystate[SDLK_LEFT] ? -32767 : (keystate[SDLK_RIGHT] ? 32767 : 0)); + if(!joyXviaCustom) + setjoystickstate (0, 0, axis, 32767); + axis = (keystate[SDLK_UP] ? -32767 : (keystate[SDLK_DOWN] ? 32767 : 0)); + if(!joyYviaCustom) + setjoystickstate (0, 1, axis, 32767); + } + if(!joyBut1viaCustom) + setjoybuttonstate (0, 0, keystate[SDLK_PAGEDOWN]); + if(!joyBut2viaCustom) + setjoybuttonstate (0, 1, keystate[SDLK_END]); + setjoybuttonstate (0, 2, keystate[SDLK_HOME]); + setjoybuttonstate (0, 3, keystate[SDLK_PAGEUP]); + + int cd32_start = 0, cd32_ffw = 0, cd32_rwd = 0; + if(keystate[SDLK_LALT]) { // Pandora Start button + if(keystate[SDLK_RSHIFT]) // Left shoulder + cd32_rwd = 1; + else if (keystate[SDLK_RCTRL]) // Right shoulder + cd32_ffw = 1; + else + cd32_start = 1; + } + setjoybuttonstate (0, 6, cd32_start); + setjoybuttonstate (0, 5, cd32_ffw); + setjoybuttonstate (0, 4, cd32_rwd); + } +} + +struct inputdevice_functions inputdevicefunc_joystick = { + init_joystick, close_joystick, acquire_joystick, unacquire_joystick, + read_joystick, get_joystick_num, get_joystick_friendlyname, get_joystick_uniquename, + get_joystick_widget_num, get_joystick_widget_type, + get_joystick_widget_first, + get_joystick_flags +}; + +int input_get_default_joystick (struct uae_input_device *uid, int num, int port, int af, int mode) +{ + int h, v; + + h = port ? INPUTEVENT_JOY2_HORIZ : INPUTEVENT_JOY1_HORIZ;; + v = port ? INPUTEVENT_JOY2_VERT : INPUTEVENT_JOY1_VERT; + + setid (uid, num, ID_AXIS_OFFSET + 0, 0, port, h); + setid (uid, num, ID_AXIS_OFFSET + 1, 0, port, v); + + setid_af (uid, num, ID_BUTTON_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON, af); + setid (uid, num, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_2ND_BUTTON : INPUTEVENT_JOY1_2ND_BUTTON); + setid (uid, num, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_3RD_BUTTON : INPUTEVENT_JOY1_3RD_BUTTON); + + if (mode == JSEM_MODE_JOYSTICK_CD32) { + setid_af (uid, num, ID_BUTTON_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_CD32_RED : INPUTEVENT_JOY1_CD32_RED, af); + setid_af (uid, num, ID_BUTTON_OFFSET + 0, 1, port, port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON, af); + setid (uid, num, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_CD32_BLUE : INPUTEVENT_JOY1_CD32_BLUE); + setid (uid, num, ID_BUTTON_OFFSET + 1, 1, port, port ? INPUTEVENT_JOY2_2ND_BUTTON : INPUTEVENT_JOY1_2ND_BUTTON); + setid (uid, num, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_CD32_GREEN : INPUTEVENT_JOY1_CD32_GREEN); + setid (uid, num, ID_BUTTON_OFFSET + 3, 0, port, port ? INPUTEVENT_JOY2_CD32_YELLOW : INPUTEVENT_JOY1_CD32_YELLOW); + setid (uid, num, ID_BUTTON_OFFSET + 4, 0, port, port ? INPUTEVENT_JOY2_CD32_RWD : INPUTEVENT_JOY1_CD32_RWD); + setid (uid, num, ID_BUTTON_OFFSET + 5, 0, port, port ? INPUTEVENT_JOY2_CD32_FFW : INPUTEVENT_JOY1_CD32_FFW); + setid (uid, num, ID_BUTTON_OFFSET + 6, 0, port, port ? INPUTEVENT_JOY2_CD32_PLAY : INPUTEVENT_JOY1_CD32_PLAY); + } + if (num == 0) { + return 1; + } + return 0; +} + +int input_get_default_joystick_analog (struct uae_input_device *uid, int num, int port, int af) +{ + return 0; +} + + +void SimulateMouseOrJoy(int code, int keypressed) +{ + switch(code) { + case -1: // left mousebutton + mouseBut1viaCustom = keypressed; + setmousebuttonstate (0, 0, keypressed); + setmousebuttonstate (1, 0, keypressed); + break; + + case -2: // right mousebutton + mouseBut2viaCustom = keypressed; + setmousebuttonstate (0, 1, keypressed); + setmousebuttonstate (1, 1, keypressed); + break; + + case -3: // joystick button 1 + joyBut1viaCustom = keypressed; + setjoybuttonstate (0, 0, keypressed); + break; + + case -4: // joystick button 2 + joyBut2viaCustom = keypressed; + setjoybuttonstate (0, 1, keypressed); + break; + + case -5: // joystick up + joyYviaCustom = keypressed; + setjoystickstate (0, 1, keypressed ? -32767 : 0, 32767); + break; + + case -6: // joystick down + joyYviaCustom = keypressed; + setjoystickstate (0, 1, keypressed ? 32767 : 0, 32767); + break; + + case -7: // joystick left + joyXviaCustom = keypressed; + setjoystickstate (0, 0, keypressed ? -32767 : 0, 32767); + break; + + case -8: // joystick right + joyXviaCustom = keypressed; + setjoystickstate (0, 0, keypressed ? 32767 : 0, 32767); + break; + } +} diff --git a/src/od-pandora/pandora_rp9.cpp b/src/od-pandora/pandora_rp9.cpp index d2bfb43b..11de6343 100644 --- a/src/od-pandora/pandora_rp9.cpp +++ b/src/od-pandora/pandora_rp9.cpp @@ -332,7 +332,7 @@ static void parse_boot(struct uae_prefs *p, xmlNode *node) { if(strcmp((const char *) attr, "hdf") == 0) { - // Build-in hdf required + // Built-in hdf required xmlChar *content = xmlNodeGetContent(curr_node); if(content != NULL) { diff --git a/src/od-pandora/sysconfig.h b/src/od-pandora/sysconfig.h index 72fb299b..f749f76b 100644 --- a/src/od-pandora/sysconfig.h +++ b/src/od-pandora/sysconfig.h @@ -16,7 +16,7 @@ /* #define ENFORCER */ /* UAE Enforcer */ #define ECS_DENISE /* ECS DENISE new features */ #define AGA /* AGA chipset emulation (ECS_DENISE must be enabled) */ -/* #define CD32 */ /* CD32 emulation */ +#define CD32 /* CD32 emulation */ /* #define CDTV */ /* CDTV emulation */ /* #define PARALLEL_PORT */ /* parallel port emulation */ /* #define SERIAL_PORT */ /* serial port emulation */ @@ -52,6 +52,7 @@ /* #define CUSTOM_SIMPLE */ /* simplified custom chipset emulation */ /* #define CPUEMU_68000_ONLY */ /* drop 68010+ commands from CPUEMU_0 */ /* #define ADDRESS_SPACE_24BIT */ +#define INPUTDEVICE_SIMPLE /* simplified inputdevice for faster emulation */ #define SIZEOF_VOID_P 4 @@ -465,6 +466,8 @@ typedef unsigned char boolean; #define FALSE 0 #define TRUE 1 +#define Sleep(x) usleep(x*1000) + /* Some defines to make it easier to compare files with WinUAE */ #define _T(x) x #define TCHAR char diff --git a/src/od-pandora/target.h b/src/od-pandora/target.h index 8c17b0fe..e62ac864 100644 --- a/src/od-pandora/target.h +++ b/src/od-pandora/target.h @@ -13,8 +13,6 @@ #define OPTIONSFILENAME "uaeconfig" extern int emulating; -extern int JoystickButton[20]; //Joystick Button state -extern int uae4all_keystate[256]; extern int z3_start_adr; extern int rtg_start_adr; @@ -31,7 +29,9 @@ void graphics_subshutdown (void); void pandora_stop_sound(void); -void keyboard_init(void); +void keyboard_settrans (void); +int translate_pandora_keys(int symbol, int *modifier); +void SimulateMouseOrJoy(int code, int keypressed); void reinit_amiga(void); int count_HDs(struct uae_prefs *p); diff --git a/src/od-rasp/rasp_gfx.cpp b/src/od-rasp/rasp_gfx.cpp index b369579b..d8cdb1c7 100644 --- a/src/od-rasp/rasp_gfx.cpp +++ b/src/od-rasp/rasp_gfx.cpp @@ -10,7 +10,6 @@ #include "custom.h" #include "xwin.h" #include "drawing.h" -#include "od-pandora/inputmode.h" #include "savestate.h" #include "picasso96.h" @@ -282,8 +281,6 @@ static void open_screen(struct uae_prefs *p) { InitAmigaVidMode(p); init_row_map(); - - inputdevice_mouselimit(prSDLScreen->w, prSDLScreen->h); } //framecnt = 1; // Don't draw frame before reset done } @@ -353,10 +350,10 @@ void flush_screen () { //SDL_UnlockSurface (prSDLScreen); - if (show_inputmode) - { - inputmode_redraw(); - } + //if (show_inputmode) + //{ + // inputmode_redraw(); + //} if (savestate_state == STATE_DOSAVE) @@ -539,8 +536,8 @@ int graphics_init (void) if (!init_colors ()) return 0; - buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; - keyboard_init(); + //buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; + //keyboard_init(); return 1; } diff --git a/src/savestate.cpp b/src/savestate.cpp index 474ac564..72dea996 100644 --- a/src/savestate.cpp +++ b/src/savestate.cpp @@ -456,6 +456,10 @@ void restore_state (const TCHAR *filename) end = restore_cia (1, chunk); else if (!_tcscmp (name, _T("CHIP"))) end = restore_custom (chunk); + else if (!_tcscmp (name, _T("CINP"))) + end = restore_input (chunk); + else if (!_tcscmp (name, _T("CHPX"))) + end = restore_custom_extra (chunk); else if (!_tcscmp (name, _T("AUD0"))) end = restore_audio (0, chunk); else if (!_tcscmp (name, _T("AUD1"))) @@ -504,6 +508,12 @@ void restore_state (const TCHAR *filename) else if (!_tcscmp (name, _T("FSYC"))) end = restore_filesys_common (chunk); #endif +#ifdef CD32 + else if (!_tcscmp (name, _T("CD32"))) + end = restore_akiko (chunk); +#endif + else if (!_tcsncmp (name, _T("CDU"), 3)) + end = restore_cd (name[3] - '0', chunk); else { end = chunk + len; write_log (_T("unknown chunk '%s' size %d bytes\n"), name, len); @@ -646,6 +656,10 @@ static int save_state_internal (struct zfile *f, const TCHAR *description, int c save_chunk (f, dst, len, _T("CHIP"), 0); xfree (dst); + dst = save_custom_extra (&len, 0); + save_chunk (f, dst, len, _T("CHPX"), 0); + xfree (dst); + dst = save_blitter_new (&len, 0); save_chunk (f, dst, len, _T("BLTX"), 0); xfree (dst); @@ -655,6 +669,10 @@ static int save_state_internal (struct zfile *f, const TCHAR *description, int c xfree (dst); } + dst = save_input (&len, 0); + save_chunk (f, dst, len, _T("CINP"), 0); + xfree (dst); + dst = save_custom_agacolors (&len, 0); save_chunk (f, dst, len, _T("AGAC"), 0); xfree (dst); @@ -706,6 +724,11 @@ static int save_state_internal (struct zfile *f, const TCHAR *description, int c xfree (dst); } while ((dst = save_rom (0, &len, 0))); +#ifdef CD32 + dst = save_akiko (&len, NULL); + save_chunk (f, dst, len, _T("CD32"), 0); + xfree (dst); +#endif #ifdef FILESYS dst = save_filesys_common (&len); if (dst) { @@ -720,6 +743,14 @@ static int save_state_internal (struct zfile *f, const TCHAR *description, int c } #endif + for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + dst = save_cd (i, &len); + if (dst) { + _stprintf (name, _T("CDU%d"), i); + save_chunk (f, dst, len, name, 0); + } + } + zfile_fwrite (endhunk, 1, 8, f); return 1; diff --git a/src/sd-pandora/sound.cpp b/src/sd-pandora/sound.cpp index d83df8ee..45b406d1 100644 --- a/src/sd-pandora/sound.cpp +++ b/src/sd-pandora/sound.cpp @@ -23,7 +23,7 @@ #include "custom.h" #include "audio.h" #include "gensound.h" -#include "sounddep/sound.h" +#include "sd-pandora/sound.h" #include "savestate.h" @@ -32,6 +32,14 @@ uae_u16 *sndbufpt = sndbuffer[0]; uae_u16 *render_sndbuff = sndbuffer[0]; uae_u16 *finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN*2; +uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * 2]; +uae_u16 *cdbufpt = cdaudio_buffer[0]; +uae_u16 *render_cdbuff = cdaudio_buffer[0]; +uae_u16 *finish_cdbuff = cdaudio_buffer[0] + CDAUDIO_BUFFER_LEN * 2; +bool cdaudio_active = false; +static int cdwrcnt = 0; +static int cdrdcnt = 0; + static int have_sound = 0; static int lastfreq; @@ -59,6 +67,7 @@ static int sound_thread_active = 0, sound_thread_exit = 0; static sem_t sound_sem; static sem_t sound_out_sem; static int output_cnt = 0; +static int wrcnt = 0; static void *sound_thread(void *unused) { @@ -81,17 +90,41 @@ static void *sound_thread(void *unused) cnt = output_cnt; sem_post(&sound_out_sem); - if(currprefs.sound_stereo) - write(sounddev, sndbuffer[cnt&3], SNDBUFFER_LEN*2); + if(currprefs.sound_stereo) { + if(cdaudio_active && currprefs.sound_freq == 44100 && cdrdcnt < cdwrcnt) { + for(int i=0; i cdrdcnt + CDAUDIO_BUFFERS - 10) && (sound_thread_active != 0) && (quit_program == 0)) { + sleep_millis(10); + } + return (sound_thread_active != 0); } @@ -258,7 +310,10 @@ void reset_sound (void) if (!have_sound) return; - memset(sndbuffer, 0, 2 * 4 * (SNDBUFFER_LEN+32)*DEFAULT_SOUND_CHANNELS); + init_soundbuffer_usage(); + + clear_sound_buffers(); + clear_cdaudio_buffers(); } void sound_volume (int dir) diff --git a/src/sd-pandora/sound.h b/src/sd-pandora/sound.h index 035cdd71..cf9a0983 100644 --- a/src/sd-pandora/sound.h +++ b/src/sd-pandora/sound.h @@ -21,6 +21,8 @@ extern uae_u16 *finish_sndbuff; extern int sndbufsize; extern void finish_sound_buffer (void); extern void restart_sound_buffer (void); +extern void finish_cdaudio_buffer (void); +extern bool cdaudio_catchup(void); extern int init_sound(void); extern void close_sound (void); extern int setup_sound (void); @@ -48,3 +50,21 @@ STATIC_INLINE void clear_sound_buffers (void) #define FILTER_SOUND_TYPE_A500 0 #define FILTER_SOUND_TYPE_A1200 1 + + +#define CDAUDIO_BUFFERS 32 +#define CDAUDIO_BUFFER_LEN 2048 +extern uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * 2]; +extern uae_u16 *cdbufpt; +extern uae_u16 *render_cdbuff; +extern uae_u16 *finish_cdbuff; +extern bool cdaudio_active; + +#define check_cdaudio_buffers() { if (cdbufpt >= finish_cdbuff) finish_cdaudio_buffer (); } + +STATIC_INLINE void clear_cdaudio_buffers (void) +{ + memset (cdaudio_buffer, 0, CDAUDIO_BUFFERS * (CDAUDIO_BUFFER_LEN + 32) * 2); +} + +#define PUT_CDAUDIO_WORD_STEREO(l,r) do { *((uae_u32 *)cdbufpt) = (r << 16) | (l & 0xffff); cdbufpt = cdbufpt + 2; } while (0) diff --git a/src/sd-sdl/sound_sdl_new.cpp b/src/sd-sdl/sound_sdl_new.cpp index 21c5d2f7..4b002d10 100644 --- a/src/sd-sdl/sound_sdl_new.cpp +++ b/src/sd-sdl/sound_sdl_new.cpp @@ -41,6 +41,14 @@ uae_u16 *sndbufpt = sndbuffer[0]; uae_u16 *render_sndbuff = sndbuffer[0]; uae_u16 *finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN*2; +uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * 2]; +uae_u16 *cdbufpt = cdaudio_buffer[0]; +uae_u16 *render_cdbuff = cdaudio_buffer[0]; +uae_u16 *finish_cdbuff = cdaudio_buffer[0] + CDAUDIO_BUFFER_LEN * 2; +bool cdaudio_active = false; +static int cdwrcnt = 0; +static int cdrdcnt = 0; + #ifdef NO_SOUND @@ -104,6 +112,8 @@ static sem_t sound_sem, callback_sem; #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) static int cnt = 0; +static int wrcnt = 0; + static void sound_thread_mixer(void *ud, Uint8 *stream, int len) { if (sound_thread_exit) return; @@ -118,10 +128,21 @@ static void sound_thread_mixer(void *ud, Uint8 *stream, int len) //__android_log_print(ANDROID_LOG_INFO, "UAE4ALL2","Sound callback cnt %d buf %d\n", cnt, cnt%SOUND_BUFFERS_COUNT); if(currprefs.sound_stereo) - memcpy(stream, sndbuffer[cnt%SOUND_BUFFERS_COUNT], MIN(SNDBUFFER_LEN*2, len)); + { + + if(cdaudio_active && currprefs.sound_freq == 44100 && cdrdcnt < cdwrcnt) + { + for(int i=0; i cdrdcnt + CDAUDIO_BUFFERS - 10) && (sound_thread_active != 0) && (quit_program == 0)) { + sleep_millis(10); + } + return (sound_thread_active != 0); } /* Try to determine whether sound is available. This is only for GUI purposes. */ @@ -386,7 +442,10 @@ void reset_sound (void) if (!have_sound) return; - memset(sndbuffer, 0, 2 * 4 * (SNDBUFFER_LEN+32)*DEFAULT_SOUND_CHANNELS); + init_soundbuffer_usage(); + + clear_sound_buffers(); + clear_cdaudio_buffers(); }