From b0dc24689f3a35970ff778fdae960321ff70c06c Mon Sep 17 00:00:00 2001 From: dborth Date: Mon, 30 Nov 2009 08:14:38 +0000 Subject: [PATCH] revert trunk --- Makefile.gc | 11 +- Makefile.wii | 9 +- source/ngc/audio.cpp | 19 +- source/ngc/filebrowser.cpp | 65 +- source/ngc/freeze.cpp | 205 +- source/ngc/freeze.h | 16 + source/ngc/menu.cpp | 2 + source/ngc/s9xconfig.cpp | 23 +- source/ngc/s9xsupport.cpp | 72 +- source/ngc/snes9xGX.cpp | 18 +- source/ngc/snes9xGX.h | 8 +- source/ngc/sram.cpp | 17 - source/snes9x/{dsp.cpp => 3d.h} | 90 +- source/snes9x/65c816.h | 160 +- source/snes9x/apu.cpp | 1054 ++++ source/snes9x/{apu => }/apu.h | 154 +- source/snes9x/apu/SNES_SPC.cpp | 564 --- source/snes9x/apu/SNES_SPC.h | 287 -- source/snes9x/apu/SNES_SPC_misc.cpp | 407 -- source/snes9x/apu/SNES_SPC_state.cpp | 142 - source/snes9x/apu/SPC_CPU.h | 1220 ----- source/snes9x/apu/SPC_DSP.cpp | 1062 ---- source/snes9x/apu/SPC_DSP.h | 317 -- source/snes9x/apu/SPC_Filter.cpp | 68 - source/snes9x/apu/SPC_Filter.h | 47 - source/snes9x/apu/apu.cpp | 633 --- source/snes9x/apu/blargg_common.h | 187 - source/snes9x/apu/blargg_config.h | 24 - source/snes9x/apu/blargg_endian.h | 185 - source/snes9x/apu/blargg_source.h | 100 - source/snes9x/apu/license.txt | 504 -- source/snes9x/apu/resampler.h | 161 - source/snes9x/apu/ring_buffer.h | 111 - source/snes9x/apudebug.cpp | 509 ++ source/snes9x/{reader.cpp => apumem.h} | 275 +- source/snes9x/bsx.cpp | 543 +- source/snes9x/bsx.h | 20 +- source/snes9x/c4.cpp | 238 +- source/snes9x/c4.h | 65 +- source/snes9x/c4emu.cpp | 1914 ++++--- source/snes9x/cheats.cpp | 706 +-- source/snes9x/cheats.h | 121 +- source/snes9x/cheats2.cpp | 317 +- source/snes9x/clip.cpp | 378 +- source/snes9x/controls.cpp | 5605 +++++++++----------- source/snes9x/controls.h | 467 +- source/snes9x/copyright.h | 233 + source/snes9x/cpu.cpp | 340 +- source/snes9x/cpuaddr.h | 675 +-- source/snes9x/cpuexec.cpp | 124 +- source/snes9x/cpuexec.h | 152 +- source/snes9x/cpumacro.h | 1178 ++--- source/snes9x/cpuops.cpp | 5616 ++++++++++----------- source/snes9x/cpuops.h | 12 +- source/snes9x/crosshairs.cpp | 897 ++-- source/snes9x/crosshairs.h | 99 +- source/snes9x/data.cpp | 613 +++ source/snes9x/display.h | 106 +- source/snes9x/dma.cpp | 1710 +++---- source/snes9x/dma.h | 36 +- source/snes9x/dsp.h | 602 --- source/snes9x/dsp1.cpp | 2492 +++------ source/snes9x/{reader.h => dsp1.h} | 88 +- source/snes9x/dsp1emu.c.inc | 1394 +++++ source/snes9x/{dsp2.cpp => dsp2emu.c.inc} | 452 +- source/snes9x/{dsp3.cpp => dsp3emu.c.inc} | 1122 ++-- source/snes9x/dsp4.cpp | 2204 -------- source/snes9x/dsp4emu.c.inc | 2396 +++++++++ source/snes9x/font.h | 281 +- source/snes9x/fxdbg.cpp | 1546 ++---- source/snes9x/fxemu.cpp | 1285 ++--- source/snes9x/fxemu.h | 98 +- source/snes9x/fxinst.cpp | 5574 ++++++-------------- source/snes9x/fxinst.h | 542 +- source/snes9x/getset.h | 1443 +++--- source/snes9x/gfx.cpp | 3755 +++++++------- source/snes9x/gfx.h | 322 +- source/snes9x/globals.cpp | 395 +- source/snes9x/language.h | 46 +- source/snes9x/memmap.cpp | 2707 ++++------ source/snes9x/memmap.h | 82 +- source/snes9x/messages.h | 81 +- source/snes9x/missing.h | 130 +- source/snes9x/movie.cpp | 1171 ----- source/snes9x/movie.h | 241 - source/snes9x/obc1.cpp | 106 +- source/snes9x/obc1.h | 20 +- source/snes9x/pixform.h | 383 +- source/snes9x/port.h | 336 +- source/snes9x/ppu.cpp | 4179 +++++++++------ source/snes9x/ppu.h | 1064 ++-- source/snes9x/s9xdebug.cpp | 2307 +++++++++ source/snes9x/{logger.h => s9xdebug.h} | 29 +- source/snes9x/sa1.cpp | 1712 +++---- source/snes9x/sa1.h | 245 +- source/snes9x/sa1cpu.cpp | 209 +- source/snes9x/sar.h | 47 +- source/snes9x/screenshot.cpp | 299 -- source/snes9x/screenshot.h | 9 +- source/snes9x/sdd1.cpp | 96 +- source/snes9x/sdd1.h | 13 +- source/snes9x/sdd1emu.cpp | 7 +- source/snes9x/sdd1emu.h | 17 +- source/snes9x/seta.cpp | 18 +- source/snes9x/seta.h | 110 +- source/snes9x/seta010.cpp | 763 ++- source/snes9x/seta011.cpp | 143 +- source/snes9x/seta018.cpp | 187 +- source/snes9x/snapshot.cpp | 4086 ++++++++------- source/snes9x/snapshot.h | 37 +- source/snes9x/snes9x.cpp | 1264 +++++ source/snes9x/snes9x.h | 487 +- source/snes9x/soundux.cpp | 2442 +++++++++ source/snes9x/soundux.h | 352 ++ source/snes9x/spc700.cpp | 2650 ++++++++++ source/snes9x/{logger.cpp => spc700.h} | 142 +- source/snes9x/spc7110.cpp | 2503 ++++++++- source/snes9x/spc7110.h | 192 +- source/snes9x/spc7110dec.cpp | 529 -- source/snes9x/spc7110dec.h | 67 - source/snes9x/spc7110emu.cpp | 643 --- source/snes9x/spc7110emu.h | 136 - source/snes9x/srtc.cpp | 499 +- source/snes9x/srtc.h | 84 +- source/snes9x/srtcemu.cpp | 225 - source/snes9x/srtcemu.h | 30 - source/snes9x/tile.cpp | 2009 ++++---- source/snes9x/tile.h | 7 +- 128 files changed, 46156 insertions(+), 45867 deletions(-) rename source/snes9x/{dsp.cpp => 3d.h} (83%) create mode 100644 source/snes9x/apu.cpp rename source/snes9x/{apu => }/apu.h (65%) delete mode 100644 source/snes9x/apu/SNES_SPC.cpp delete mode 100644 source/snes9x/apu/SNES_SPC.h delete mode 100644 source/snes9x/apu/SNES_SPC_misc.cpp delete mode 100644 source/snes9x/apu/SNES_SPC_state.cpp delete mode 100644 source/snes9x/apu/SPC_CPU.h delete mode 100644 source/snes9x/apu/SPC_DSP.cpp delete mode 100644 source/snes9x/apu/SPC_DSP.h delete mode 100644 source/snes9x/apu/SPC_Filter.cpp delete mode 100644 source/snes9x/apu/SPC_Filter.h delete mode 100644 source/snes9x/apu/apu.cpp delete mode 100644 source/snes9x/apu/blargg_common.h delete mode 100644 source/snes9x/apu/blargg_config.h delete mode 100644 source/snes9x/apu/blargg_endian.h delete mode 100644 source/snes9x/apu/blargg_source.h delete mode 100644 source/snes9x/apu/license.txt delete mode 100644 source/snes9x/apu/resampler.h delete mode 100644 source/snes9x/apu/ring_buffer.h create mode 100644 source/snes9x/apudebug.cpp rename source/snes9x/{reader.cpp => apumem.h} (66%) create mode 100644 source/snes9x/copyright.h create mode 100644 source/snes9x/data.cpp delete mode 100644 source/snes9x/dsp.h rename source/snes9x/{reader.h => dsp1.h} (84%) create mode 100644 source/snes9x/dsp1emu.c.inc rename source/snes9x/{dsp2.cpp => dsp2emu.c.inc} (57%) rename source/snes9x/{dsp3.cpp => dsp3emu.c.inc} (52%) delete mode 100644 source/snes9x/dsp4.cpp create mode 100644 source/snes9x/dsp4emu.c.inc delete mode 100644 source/snes9x/movie.cpp delete mode 100644 source/snes9x/movie.h create mode 100644 source/snes9x/s9xdebug.cpp rename source/snes9x/{logger.h => s9xdebug.h} (92%) delete mode 100644 source/snes9x/screenshot.cpp create mode 100644 source/snes9x/snes9x.cpp create mode 100644 source/snes9x/soundux.cpp create mode 100644 source/snes9x/soundux.h create mode 100644 source/snes9x/spc700.cpp rename source/snes9x/{logger.cpp => spc700.h} (74%) delete mode 100644 source/snes9x/spc7110dec.cpp delete mode 100644 source/snes9x/spc7110dec.h delete mode 100644 source/snes9x/spc7110emu.cpp delete mode 100644 source/snes9x/spc7110emu.h delete mode 100644 source/snes9x/srtcemu.cpp delete mode 100644 source/snes9x/srtcemu.h diff --git a/Makefile.gc b/Makefile.gc index b8e3a9b..580f199 100644 --- a/Makefile.gc +++ b/Makefile.gc @@ -19,16 +19,19 @@ TARGET := snes9xgx-gc TARGETDIR := executables BUILD := build_gc SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts \ - source/ngc/gui source/ngc source/snes9x source/snes9x/apu \ - source/sz + source/ngc/gui source/ngc source/snes9x source/sz INCLUDES := source/snes9x source/ngc #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) -DNO_SOUND \ - -DZLIB -DRIGHTSHIFT_IS_SAR -DCPU_SHUTDOWN -DCORRECT_VRAM_READS \ +CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ + -DNGC -DNO_SOUND \ + -DNO_ASM -DRIGHTSHIFT_IS_SAR \ + -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ + -DSPC700_C -DSDD1_DECOMP \ + -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ -fomit-frame-pointer \ -Wno-unused-parameter -Wno-strict-aliasing \ diff --git a/Makefile.wii b/Makefile.wii index bab2927..d3dc5c9 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -19,8 +19,7 @@ TARGET := snes9xgx-wii TARGETDIR := executables BUILD := build_wii SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts \ - source/ngc/gui source/ngc source/snes9x source/snes9x/apu \ - source/sz source/unzip + source/ngc/gui source/ngc source/snes9x source/sz source/unzip INCLUDES := source/snes9x source/ngc source/unzip #--------------------------------------------------------------------------------- @@ -28,7 +27,11 @@ INCLUDES := source/snes9x source/ngc source/unzip #--------------------------------------------------------------------------------- CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ - -DZLIB -DRIGHTSHIFT_IS_SAR -DCPU_SHUTDOWN -DCORRECT_VRAM_READS \ + -DNGC \ + -DNO_ASM -DRIGHTSHIFT_IS_SAR \ + -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ + -DSPC700_C -DSDD1_DECOMP \ + -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ -fomit-frame-pointer \ -Wno-unused-parameter -Wno-strict-aliasing \ diff --git a/source/ngc/audio.cpp b/source/ngc/audio.cpp index 788b7cd..dc95f37 100644 --- a/source/ngc/audio.cpp +++ b/source/ngc/audio.cpp @@ -18,11 +18,14 @@ #include "snes9x.h" #include "memmap.h" +#include "s9xdebug.h" #include "cpuexec.h" #include "ppu.h" -#include "apu/apu.h" +#include "apu.h" #include "display.h" #include "gfx.h" +#include "soundux.h" +#include "spc700.h" #include "spc7110.h" #include "controls.h" @@ -39,7 +42,6 @@ static int whichab = 0; /*** Audio buffer flip switch ***/ static lwpq_t audioqueue; static lwp_t athread; static uint8 astack[AUDIOSTACK]; -static mutex_t audiomutex = LWP_MUTEX_NULL; /**************************************************************************** * Audio Threading @@ -56,9 +58,8 @@ AudioThread (void *arg) memset (soundbuffer[whichab], 0, AUDIOBUFFER); else { - LWP_MutexLock(audiomutex); + so.samples_mixed_so_far = so.play_position = 0; S9xMixSamples (soundbuffer[whichab], AUDIOBUFFER >> 1); - LWP_MutexUnlock(audiomutex); } LWP_ThreadSleep (audioqueue); } @@ -84,13 +85,6 @@ GCMixSamples () } } -static void FinalizeSamplesCallback (void *data) -{ - LWP_MutexLock(audiomutex); - S9xFinalizeSamples(); - LWP_MutexUnlock(audiomutex); -} - /**************************************************************************** * InitAudio ***************************************************************************/ @@ -104,7 +98,6 @@ InitAudio () #else ASND_Init(); #endif - LWP_MutexInit(&audiomutex, false); LWP_CreateThread (&athread, AudioThread, NULL, astack, AUDIOSTACK, 70); } @@ -124,11 +117,9 @@ SwitchAudioMode(int mode) AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ); AUDIO_RegisterDMACallback(GCMixSamples); #endif - S9xSetSamplesAvailableCallback(FinalizeSamplesCallback, NULL); } else // menu { - S9xSetSamplesAvailableCallback(NULL, NULL); #ifndef NO_SOUND ASND_Init(); ASND_Pause(0); diff --git a/source/ngc/filebrowser.cpp b/source/ngc/filebrowser.cpp index 7cbd3e2..bbd125d 100644 --- a/source/ngc/filebrowser.cpp +++ b/source/ngc/filebrowser.cpp @@ -453,39 +453,6 @@ int BrowserLoadSz() return szfiles; } -int WiiFileLoader() -{ - int size; - char filepath[1024]; - - memset(Memory.NSRTHeader, 0, sizeof(Memory.NSRTHeader)); - Memory.HeaderCount = 0; - - if(!inSz) - { - if(!MakeFilePath(filepath, FILE_ROM)) - return 0; - - size = LoadFile ((char *)Memory.ROM, filepath, browserList[browser.selIndex].length, NOTSILENT); - } - else - { - size = LoadSzFile(szpath, (unsigned char *)Memory.ROM); - - if(size <= 0) - { - browser.selIndex = 0; - BrowserChangeFolder(); - } - } - - if(size <= 0) - return 0; - - SNESROMSize = Memory.HeaderRemove(size, Memory.HeaderCount, Memory.ROM); - return SNESROMSize; -} - /**************************************************************************** * BrowserLoadFile * @@ -493,9 +460,11 @@ int WiiFileLoader() ***************************************************************************/ int BrowserLoadFile() { + char filepath[1024]; int loaded = 0; + int device; - + if(!FindDevice(browser.dir, &device)) return 0; @@ -508,7 +477,24 @@ int BrowserLoadFile() SNESROMSize = 0; S9xDeleteCheats(); - Memory.LoadROM("ROM"); + + if(!inSz) + { + if(!MakeFilePath(filepath, FILE_ROM)) + goto done; + + SNESROMSize = LoadFile ((char *)Memory.ROM, filepath, browserList[browser.selIndex].length, NOTSILENT); + } + else + { + SNESROMSize = LoadSzFile(szpath, (unsigned char *)Memory.ROM); + + if(SNESROMSize <= 0) + { + browser.selIndex = 0; + BrowserChangeFolder(); + } + } if (SNESROMSize <= 0) { @@ -516,12 +502,21 @@ int BrowserLoadFile() } else { + // load UPS/IPS/PPF patch + WiiLoadPatch(); + + Memory.LoadROM ("BLANK.SMC"); + Memory.LoadSRAM ("BLANK"); + // load SRAM or snapshot if (GCSettings.AutoLoad == 1) LoadSRAMAuto(SILENT); else if (GCSettings.AutoLoad == 2) LoadSnapshotAuto(SILENT); + // setup cheats + WiiSetupCheats(); + ResetBrowser(); loaded = 1; } diff --git a/source/ngc/freeze.cpp b/source/ngc/freeze.cpp index 3cb0900..dfc9792 100644 --- a/source/ngc/freeze.cpp +++ b/source/ngc/freeze.cpp @@ -7,41 +7,121 @@ * Tantric 2008-2009 * * freeze.cpp + * + * Snapshots Memory File System + * + * This is a single global memory file controller. + * Don't even think of opening two at the same time! ***************************************************************************/ #include #include #include +#include +#include +#include +#include #include "snes9x.h" -#include "port.h" #include "memmap.h" +#include "soundux.h" #include "snapshot.h" +#include "srtc.h" #include "snes9xGX.h" +#include "freeze.h" #include "fileop.h" #include "filebrowser.h" #include "menu.h" #include "video.h" #include "pngu.h" -bool8 S9xOpenSnapshotFile(const char *filepath, bool8 readonly, STREAM *file) +extern void S9xSRTCPreSaveState (); +extern void NGCFreezeStruct (); +extern bool8 S9xUnfreezeGame (const char *filename); + +static int bufoffset; + +/**************************************************************************** + * GetMem + * + * Return x bytes from memory buffer + ***************************************************************************/ +int +GetMem (char *buffer, int len) { - return FALSE; + memcpy (buffer, savebuffer + bufoffset, len); + bufoffset += len; + + return len; } -void S9xCloseSnapshotFile(STREAM s) +/**************************************************************************** + * PutMem + * + * Put some values in memory buffer + ***************************************************************************/ +static void +PutMem (char *buffer, int len) { - + memcpy (savebuffer + bufoffset, buffer, len); + bufoffset += len; } +void +NGCFreezeBlock (char *name, uint8 * block, int size) +{ + char buffer[512]; + sprintf (buffer, "%s:%06d:", name, size); + PutMem (buffer, strlen (buffer)); + PutMem ((char *) block, size); +} + +/**************************************************************************** + * NGCFreezeMembuffer + * + * Copies a snapshot of Snes9x state into memory + ***************************************************************************/ +static int +NGCFreezeMemBuffer () +{ + int i; + char buffer[1024]; + + bufoffset = 0; + + S9xUpdateRTC (); + S9xSRTCPreSaveState (); + + for (i = 0; i < 8; i++) + { + SoundData.channels[i].previous16[0] = + (int16) SoundData.channels[i].previous[0]; + SoundData.channels[i].previous16[1] = + (int16) SoundData.channels[i].previous[1]; + } + + sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); + PutMem (buffer, strlen (buffer)); + sprintf (buffer, "NAM:%06d:%s%c", (int) strlen (Memory.ROMFilename) + 1, + Memory.ROMFilename, 0); + + PutMem (buffer, strlen (buffer) + 1); + + NGCFreezeStruct (); + + return 0; +} + + /**************************************************************************** * SaveSnapshot ***************************************************************************/ - int SaveSnapshot (char * filepath, bool silent) { + int offset = 0; // bytes written (actual) + int woffset = 0; // bytes written (expected) int imgSize = 0; // image screenshot bytes written int device; @@ -73,21 +153,28 @@ SaveSnapshot (char * filepath, bool silent) FreeSaveBuffer (); } - STREAM fp = OPEN_STREAM(filepath, "wb"); - - if(!fp) + S9xSetSoundMute (TRUE); + S9xPrepareSoundForSnapshotSave (FALSE); + + AllocSaveBuffer (); + // copy freeze mem into savebuffer - bufoffset contains # bytes written + NGCFreezeMemBuffer (); + woffset = bufoffset; + + S9xPrepareSoundForSnapshotSave (TRUE); + S9xSetSoundMute (FALSE); + + offset = SaveFile(filepath, woffset, silent); + + FreeSaveBuffer (); + + if(offset > 0) // save successful! { if(!silent) - ErrorPrompt("Save failed!"); - return 0; + InfoPrompt("Save successful"); + return 1; } - - S9xFreezeToStream(fp); - CLOSE_STREAM(fp); - - if(!silent) - InfoPrompt("Save successful"); - return 1; + return 0; } int @@ -101,48 +188,76 @@ SaveSnapshotAuto (bool silent) return SaveSnapshot(filepath, silent); } +/**************************************************************************** + * NGCUnFreezeBlock + ***************************************************************************/ +int +NGCUnFreezeBlock (char *name, uint8 * block, int size) +{ + char buffer[20], *e; + int len = 0; + int rem = 0; + + GetMem (buffer, 11); + + if (strncmp (buffer, name, 3) != 0 || buffer[3] != ':' || + buffer[10] != ':' || (len = strtol (&buffer[4], &e, 10)) == 0 || + e != buffer + 10) + { + bufoffset -= 11; // go back to where we started + return WRONG_FORMAT; + } + + if (len > size) + { + rem = len - size; + len = size; + } + + ZeroMemory (block, size); + + GetMem ((char *) block, len); + + if (rem) + { + bufoffset += rem; + } + + return SUCCESS; +} + /**************************************************************************** * LoadSnapshot ***************************************************************************/ int LoadSnapshot (char * filepath, bool silent) { + int offset = 0; + int result = 0; + bufoffset = 0; int device; if(!FindDevice(filepath, &device)) return 0; + + AllocSaveBuffer(); - STREAM fp = OPEN_STREAM(filepath, "rb"); + offset = LoadFile(filepath, silent); - if(!fp) + if(offset > 0) + { + if (S9xUnfreezeGame ("AGAME") == SUCCESS) + result = 1; + else + ErrorPrompt("Error thawing"); + } + else { if(!silent) - ErrorPrompt("Unable to open snapshot!"); - return 0; + ErrorPrompt("Freeze file not found"); } - - int result = S9xUnfreezeFromStream(fp); - CLOSE_STREAM(fp); - - if (result == SUCCESS) - return 1; -/* - switch (result) - { - case WRONG_FORMAT: - S9xMessage(S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); - break; - - case WRONG_VERSION: - S9xMessage(S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); - break; - - case SNAPSHOT_INCONSISTENT: - S9xMessage(S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); - break; - } -*/ - return 0; + FreeSaveBuffer(); + return result; } int diff --git a/source/ngc/freeze.h b/source/ngc/freeze.h index 55cf43d..6f105b7 100644 --- a/source/ngc/freeze.h +++ b/source/ngc/freeze.h @@ -7,11 +7,27 @@ * Tantric August 2008 * * freeze.h + * + * Snapshots Memory File System + * + * This is a single global memory file controller. + * Don't even think of opening two at the same time! ***************************************************************************/ #ifndef _FREEZE_H_ #define _FREEZE_H_ +typedef struct +{ + char filename[512]; /*** Way over size - but who cares -;) ***/ + int filehandle; + int currpos; + int length; + int mode; + char *buffer; /*** Memspace for read / write ***/ +} +MEMFILE; + int SaveSnapshot (char * filepath, bool silent); int SaveSnapshotAuto (bool silent); int LoadSnapshot (char * filepath, bool silent); diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 82b854b..47e1ce4 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -41,6 +41,8 @@ #include "gui/gui.h" #include "menu.h" +extern SCheatData Cheat; + #define THREAD_SLEEP 100 #ifdef HW_RVL diff --git a/source/ngc/s9xconfig.cpp b/source/ngc/s9xconfig.cpp index 7371a97..3259301 100644 --- a/source/ngc/s9xconfig.cpp +++ b/source/ngc/s9xconfig.cpp @@ -103,21 +103,28 @@ DefaultSettings () memset (&Settings, 0, sizeof (Settings)); // General + Settings.MouseMaster = false; Settings.SuperScopeMaster = false; Settings.MultiPlayer5Master = false; Settings.JustifierMaster = false; Settings.ShutdownMaster = true; // needs to be on for ActRaiser 2 - Settings.BlockInvalidVRAMAccessMaster = false; - Settings.HDMATimingHack = 100; Settings.ApplyCheats = true; - Settings.DontSaveOopsSnapshot = true; - // Sound + Settings.BlockInvalidVRAMAccess = false; + Settings.HDMATimingHack = 100; + + // Sound defaults. On GC this is 32Khz/16bit/Stereo/InterpolatedSound + Settings.APUEnabled = true; + Settings.NextAPUEnabled = true; Settings.SoundPlaybackRate = 32000; Settings.Stereo = true; Settings.SixteenBitSound = true; + Settings.SoundEnvelopeHeightReading = true; Settings.SoundSync = true; + Settings.FixFrequency = false; + Settings.DisableSampleCaching = true; + Settings.InterpolatedSound = true; Settings.ReverseStereo = true; // Graphics @@ -133,14 +140,22 @@ DefaultSettings () Settings.FrameTimePAL = 20000; Settings.FrameTimeNTSC = 16667; + // SDD1 - Star Ocean Returns + Settings.SDD1Pack = true; + Settings.ForceNTSC = 0; Settings.ForcePAL = 0; Settings.ForceHiROM = 0; Settings.ForceLoROM = 0; Settings.ForceHeader = 0; Settings.ForceNoHeader = 0; + Settings.ForceTransparency = 0; Settings.ForceInterleaved = 0; Settings.ForceInterleaved2 = 0; Settings.ForceInterleaveGD24 = 0; Settings.ForceNotInterleaved = 0; + Settings.ForceNoSuperFX = 0; + Settings.ForceSuperFX = 0; + Settings.ForceDSP1 = 0; + Settings.ForceNoDSP1 = 0; } diff --git a/source/ngc/s9xsupport.cpp b/source/ngc/s9xsupport.cpp index 6bdc9f7..dea79a7 100644 --- a/source/ngc/s9xsupport.cpp +++ b/source/ngc/s9xsupport.cpp @@ -21,8 +21,15 @@ #include "snes9x.h" #include "memmap.h" +#include "s9xdebug.h" +#include "cpuexec.h" +#include "ppu.h" +#include "apu.h" #include "display.h" -#include "apu/apu.h" +#include "gfx.h" +#include "soundux.h" +#include "spc700.h" +#include "spc7110.h" #include "controls.h" #include "snes9xGX.h" @@ -56,14 +63,11 @@ void S9xAutoSaveSRAM() /*** Sound based functions ***/ void S9xToggleSoundChannel(int c) { - static int sound_switch = 255; - - if (c == 8) - sound_switch = 255; - else - sound_switch ^= 1 << c; - - S9xSetSoundControl (sound_switch); + if (c == 8) + so.sound_switch = 255; + else + so.sound_switch ^= 1 << c; + S9xSetSoundControl(so.sound_switch); } /**************************************************************************** @@ -71,12 +75,25 @@ void S9xToggleSoundChannel(int c) * * Main initialisation for Wii sound system ***************************************************************************/ -bool8 S9xOpenSoundDevice(int buffer_size) +bool8 S9xOpenSoundDevice(int mode, bool8 stereo, int buffer_size) { + so.stereo = TRUE; + so.playback_rate = 32000; + so.sixteen_bit = TRUE; + so.encoded = 0; + so.buffer_size = 4096; + so.sound_switch = 255; + S9xSetPlaybackRate(so.playback_rate); + InitAudio(); return TRUE; } +/*** Deprecated function. NGC uses threaded sound ***/ +void S9xGenerateSound() +{ +} + /* eke-eke */ void S9xInitSync() { @@ -196,6 +213,21 @@ bool S9xPollPointer(uint32 id, int16 * x, int16 * y) return 0; } +void S9xLoadSDD1Data() +{ + Memory.FreeSDD1Data(); + + Settings.SDD1Pack = FALSE; + + if (strncmp(Memory.ROMName, "Star Ocean", 10) == 0) + Settings.SDD1Pack = TRUE; + + if (strncmp(Memory.ROMName, "STREET FIGHTER ALPHA2", 21) == 0) + Settings.SDD1Pack = TRUE; + + return; +} + /**************************************************************************** * Note that these are DUMMY functions, and only allow Snes9x to * compile. Where possible, they will return an error signal. @@ -231,18 +263,12 @@ const char * S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype) return NULL; } -const char * S9xBasename(const char *name) +char * S9xBasename(char *name) { ExitApp(); return name; } -const char * S9xStringInput (const char * s) -{ - ExitApp(); - return s; -} - void _splitpath(char const *buf, char *drive, char *dir, char *fname, char *ext) { ExitApp(); @@ -253,15 +279,3 @@ void _makepath(char *filename, const char *drive, const char *dir, { ExitApp(); } - -int dup(int fildes) -{ - ExitApp(); - return 1; -} - -int access(const char *pathname, int mode) -{ - ExitApp(); - return 1; -} diff --git a/source/ngc/snes9xGX.cpp b/source/ngc/snes9xGX.cpp index 561ff37..a921da9 100644 --- a/source/ngc/snes9xGX.cpp +++ b/source/ngc/snes9xGX.cpp @@ -31,7 +31,15 @@ #include "snes9x.h" #include "memmap.h" -#include "apu/apu.h" +#include "s9xdebug.h" +#include "cpuexec.h" +#include "ppu.h" +#include "apu.h" +#include "display.h" +#include "gfx.h" +#include "soundux.h" +#include "spc700.h" +#include "spc7110.h" #include "controls.h" #include "snes9xGX.h" @@ -337,7 +345,7 @@ void USBGeckoOutput() int main(int argc, char *argv[]) { - USBGeckoOutput(); // uncomment to enable USB gecko output + //USBGeckoOutput(); // uncomment to enable USB gecko output __exception_setreload(8); #ifdef HW_DOL @@ -377,7 +385,6 @@ main(int argc, char *argv[]) S9xUnmapAllControls (); SetDefaultButtonMap (); - S9xReportControllers(); // Allocate SNES Memory if (!Memory.Init ()) @@ -390,14 +397,15 @@ main(int argc, char *argv[]) // Set Pixel Renderer to match 565 S9xSetRenderPixelFormat (RGB565); - // Initialise Sound System - S9xInitSound (512, 0); + // Initialise Snes Sound System + S9xInitSound (5, TRUE, 1024); // Initialise Graphics setGFX (); if (!S9xGraphicsInit ()) ExitApp(); + S9xSetSoundMute (TRUE); S9xInitSync(); // initialize frame sync // Initialize font system diff --git a/source/ngc/snes9xGX.h b/source/ngc/snes9xGX.h index 7d08a55..83ffb9a 100644 --- a/source/ngc/snes9xGX.h +++ b/source/ngc/snes9xGX.h @@ -28,7 +28,7 @@ #define SILENT 1 const char pathPrefix[9][8] = -{ "", "sd:/", "usb:/", "dvd:/", "smb:/", "carda:/", "cardb:/" }; +{ "", "sd:/", "usb:/", "dvd:/", "smb:/", "mca:/", "mcb:/", "carda:/", "cardb:/" }; enum { DEVICE_AUTO, @@ -36,6 +36,8 @@ enum { DEVICE_USB, DEVICE_DVD, DEVICE_SMB, + DEVICE_MC_SLOTA, + DEVICE_MC_SLOTB, DEVICE_SD_SLOTA, DEVICE_SD_SLOTB }; @@ -77,6 +79,7 @@ struct SGCSettings{ float zoomHor; // horizontal zoom amount float zoomVert; // vertical zoom amount + int VerifySaves; int videomode; // 0 - automatic, 1 - NTSC (480i), 2 - Progressive (480p), 3 - PAL (50Hz), 4 - PAL (60Hz) int render; // 0 - original, 1 - filtered, 2 - unfiltered int FilterMethod; // convert to RenderFilter @@ -101,4 +104,7 @@ extern int ExitRequested; extern char appPath[]; extern FreeTypeGX *fontSystem[]; +void WiiSetupCheats(); +void WiiLoadPatch(); + #endif diff --git a/source/ngc/sram.cpp b/source/ngc/sram.cpp index 134add8..a43ddc0 100644 --- a/source/ngc/sram.cpp +++ b/source/ngc/sram.cpp @@ -54,14 +54,6 @@ LoadSRAM (char * filepath, bool silent) if (len - size == 512) memmove(Memory.SRAM, Memory.SRAM + 512, size); - if (Settings.SRTC || Settings.SPC7110RTC) - { - int pathlen = strlen(filepath); - filepath[pathlen-3] = 'r'; - filepath[pathlen-2] = 't'; - filepath[pathlen-1] = 'c'; - LoadFile((char *)RTCData.reg, filepath, 20, silent); - } result = true; } else if(!silent) @@ -128,15 +120,6 @@ SaveSRAM (char * filepath, bool silent) if (size > 0) { offset = SaveFile((char *)Memory.SRAM, filepath, size, silent); - - if (Settings.SRTC || Settings.SPC7110RTC) - { - int pathlen = strlen(filepath); - filepath[pathlen-3] = 'r'; - filepath[pathlen-2] = 't'; - filepath[pathlen-1] = 'c'; - SaveFile((char *)RTCData.reg, filepath, 20, silent); - } if (offset > 0) { diff --git a/source/snes9x/dsp.cpp b/source/snes9x/3d.h similarity index 83% rename from source/snes9x/dsp.cpp rename to source/snes9x/3d.h index 49eba75..0122ce2 100644 --- a/source/snes9x/dsp.cpp +++ b/source/snes9x/3d.h @@ -159,55 +159,67 @@ **********************************************************************************/ -#include "snes9x.h" -#include "memmap.h" -#ifdef DEBUGGER -#include "missing.h" + + +#ifndef _3D_H_ +#define _3D_H_ + +#if defined(USE_OPENGL) +#include +#include + +#ifdef __linux__ +#include #endif -uint8 (*GetDSP) (uint16) = NULL; -void (*SetDSP) (uint8, uint16) = NULL; - - -void S9xResetDSP (void) +typedef struct { - memset(&DSP1, 0, sizeof(DSP1)); - DSP1.waiting4command = TRUE; - DSP1.first_parameter = TRUE; + bool8 packed_pixels_extension_present; + bool8 draw_cube; + uint32 version; + // Texture format + GLint internal_format; + GLint format; + GLint type; - memset(&DSP2, 0, sizeof(DSP2)); - DSP2.waiting4command = TRUE; + GLint max_texture_size;// 256 or 512 + GLint texture_size; + uint32 num_textures; // 1 if max_texture_size == 256, 2 otherwise + GLuint textures [2]; + bool8 initialized; +} OpenGLData; - memset(&DSP3, 0, sizeof(DSP3)); - DSP3_Reset(); +extern OpenGLData OpenGL; - memset(&DSP4, 0, sizeof(DSP4)); - DSP4.waiting4command = TRUE; -} +bool8 S9xOpenGLInit (); +bool8 S9xOpenGLInit2 (); +void S9xOpenGLPutImage (int width, int height); +void S9xOpenGLDeinit (); -uint8 S9xGetDSP (uint16 address) -{ -#ifdef DEBUGGER - if (Settings.TraceDSP) - { - sprintf(String, "DSP read: 0x%04X", address); - S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); - } #endif - return ((*GetDSP)(address)); -} +#ifdef USE_GLIDE +#include -void S9xSetDSP (uint8 byte, uint16 address) +typedef struct { -#ifdef DEBUGGER - missing.unknowndsp_write = address; - if (Settings.TraceDSP) - { - sprintf(String, "DSP write: 0x%04X=0x%02X", address, byte); - S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); - } + bool8 voodoo_present; + GrVertex sq[4]; + GrTexInfo texture; + int32 texture_mem_size; + int32 texture_mem_start; + float x_offset, y_offset; + float x_scale, y_scale; + float voodoo_width; + float voodoo_height; +} GlideData; + +extern GlideData Glide; +bool8 S9xGlideEnable (bool8 enable); +void S9xGlideDeinit (); +bool8 S9xGlideInit (); +bool8 S9xVoodooInitialise (); +#endif + #endif - (*SetDSP)(byte, address); -} diff --git a/source/snes9x/65c816.h b/source/snes9x/65c816.h index 75bc917..bee73da 100644 --- a/source/snes9x/65c816.h +++ b/source/snes9x/65c816.h @@ -159,102 +159,104 @@ **********************************************************************************/ -#ifndef _65C816_H_ -#define _65C816_H_ -#define Carry 1 -#define Zero 2 -#define IRQ 4 -#define Decimal 8 -#define IndexFlag 16 -#define MemoryFlag 32 -#define Overflow 64 -#define Negative 128 -#define Emulation 256 -#define SetCarry() (ICPU._Carry = 1) -#define ClearCarry() (ICPU._Carry = 0) -#define SetZero() (ICPU._Zero = 0) -#define ClearZero() (ICPU._Zero = 1) -#define SetIRQ() (Registers.PL |= IRQ) -#define ClearIRQ() (Registers.PL &= ~IRQ) -#define SetDecimal() (Registers.PL |= Decimal) -#define ClearDecimal() (Registers.PL &= ~Decimal) -#define SetIndex() (Registers.PL |= IndexFlag) -#define ClearIndex() (Registers.PL &= ~IndexFlag) -#define SetMemory() (Registers.PL |= MemoryFlag) -#define ClearMemory() (Registers.PL &= ~MemoryFlag) -#define SetOverflow() (ICPU._Overflow = 1) -#define ClearOverflow() (ICPU._Overflow = 0) -#define SetNegative() (ICPU._Negative = 0x80) -#define ClearNegative() (ICPU._Negative = 0) +#ifndef _65c816_h_ +#define _65c816_h_ -#define CheckCarry() (ICPU._Carry) -#define CheckZero() (ICPU._Zero == 0) -#define CheckIRQ() (Registers.PL & IRQ) -#define CheckDecimal() (Registers.PL & Decimal) -#define CheckIndex() (Registers.PL & IndexFlag) -#define CheckMemory() (Registers.PL & MemoryFlag) -#define CheckOverflow() (ICPU._Overflow) -#define CheckNegative() (ICPU._Negative & 0x80) -#define CheckEmulation() (Registers.P.W & Emulation) +#define AL A.B.l +#define AH A.B.h +#define XL X.B.l +#define XH X.B.h +#define YL Y.B.l +#define YH Y.B.h +#define SL S.B.l +#define SH S.B.h +#define DL D.B.l +#define DH D.B.h +#define PL P.B.l +#define PH P.B.h -#define SetFlags(f) (Registers.P.W |= (f)) -#define ClearFlags(f) (Registers.P.W &= ~(f)) -#define CheckFlag(f) (Registers.PL & (f)) +#define Carry 1 +#define Zero 2 +#define IRQ 4 +#define Decimal 8 +#define IndexFlag 16 +#define MemoryFlag 32 +#define Overflow 64 +#define Negative 128 +#define Emulation 256 + +#define ClearCarry() (ICPU._Carry = 0) +#define SetCarry() (ICPU._Carry = 1) +#define SetZero() (ICPU._Zero = 0) +#define ClearZero() (ICPU._Zero = 1) +#define SetIRQ() (Registers.PL |= IRQ) +#define ClearIRQ() (Registers.PL &= ~IRQ) +#define SetDecimal() (Registers.PL |= Decimal) +#define ClearDecimal() (Registers.PL &= ~Decimal) +#define SetIndex() (Registers.PL |= IndexFlag) +#define ClearIndex() (Registers.PL &= ~IndexFlag) +#define SetMemory() (Registers.PL |= MemoryFlag) +#define ClearMemory() (Registers.PL &= ~MemoryFlag) +#define SetOverflow() (ICPU._Overflow = 1) +#define ClearOverflow() (ICPU._Overflow = 0) +#define SetNegative() (ICPU._Negative = 0x80) +#define ClearNegative() (ICPU._Negative = 0) + +#define CheckZero() (ICPU._Zero == 0) +#define CheckCarry() (ICPU._Carry) +#define CheckIRQ() (Registers.PL & IRQ) +#define CheckDecimal() (Registers.PL & Decimal) +#define CheckIndex() (Registers.PL & IndexFlag) +#define CheckMemory() (Registers.PL & MemoryFlag) +#define CheckOverflow() (ICPU._Overflow) +#define CheckNegative() (ICPU._Negative & 0x80) +#define CheckEmulation() (Registers.P.W & Emulation) + +#define ClearFlags(f) (Registers.P.W &= ~(f)) +#define SetFlags(f) (Registers.P.W |= (f)) +#define CheckFlag(f) (Registers.PL & (f)) typedef union { #ifdef LSB_FIRST - struct { uint8 l, h; } B; + struct { uint8 l,h; } B; #else - struct { uint8 h, l; } B; + struct { uint8 h,l; } B; #endif - uint16 W; -} pair; + uint16 W; +} pair; -typedef union -{ +typedef union { #ifdef LSB_FIRST - struct { uint8 xPCl, xPCh, xPB, z; } B; - struct { uint16 xPC, d; } W; + struct { uint8 xPCl, xPCh, xPB, z; } B; + struct { uint16 xPC, d; } W; #else - struct { uint8 z, xPB, xPCh, xPCl; } B; - struct { uint16 d, xPC; } W; + struct { uint8 z, xPB, xPCh, xPCl; } B; + struct { uint16 d, xPC; } W; #endif - uint32 xPBPC; -} PC_t; + uint32 xPBPC; +} PC_t; -struct SRegisters -{ - uint8 DB; - pair P; - pair A; - pair D; - pair S; - pair X; - pair Y; - PC_t PC; +struct SRegisters{ + uint8 DB; + pair P; + pair A; + pair D; + pair S; + pair X; + pair Y; + PC_t PC; }; -#define AL A.B.l -#define AH A.B.h -#define XL X.B.l -#define XH X.B.h -#define YL Y.B.l -#define YH Y.B.h -#define SL S.B.l -#define SH S.B.h -#define DL D.B.l -#define DH D.B.h -#define PL P.B.l -#define PH P.B.h -#define PBPC PC.xPBPC -#define PCw PC.W.xPC -#define PCh PC.B.xPCh -#define PCl PC.B.xPCl -#define PB PC.B.xPB +#define PBPC PC.xPBPC +#define PCw PC.W.xPC +#define PCh PC.B.xPCh +#define PCl PC.B.xPCl +#define PB PC.B.xPB -extern struct SRegisters Registers; +EXTERN_C struct SRegisters Registers; #endif + diff --git a/source/snes9x/apu.cpp b/source/snes9x/apu.cpp new file mode 100644 index 0000000..eab62d7 --- /dev/null +++ b/source/snes9x/apu.cpp @@ -0,0 +1,1054 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#include +#ifdef __DJGPP +#include +#undef TRUE +#endif + +#include "snes9x.h" +#include "spc700.h" +#include "apu.h" +#include "soundux.h" +#include "display.h" +#ifdef DEBUGGER +#include "cpuexec.h" +#endif + +/* For note-triggered SPC dump support */ +#include "snapshot.h" + +extern int32 env_counter_table[32]; + +int spc_is_dumping=0; +int spc_is_dumping_temp; +uint8 spc_dump_dsp[0x100]; + +#ifdef DEBUGGER +void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0, + int i4 = 0, int i5 = 0, int i6 = 0, int i7 = 0); +#endif + +bool8 S9xInitAPU () +{ + IAPU.RAM = (uint8 *) memalign(32, 0x10000); + + if (!IAPU.RAM) + { + S9xDeinitAPU (); + return (FALSE); + } + + memset(IAPU.RAM, 0, 0x10000); + + return (TRUE); +} + +void S9xDeinitAPU () +{ + if (IAPU.RAM) + { + free ((char *) IAPU.RAM); + IAPU.RAM = NULL; + } +} + +EXTERN_C uint8 APUROM [64]; + +void S9xResetAPU () +{ + int i; + + Settings.APUEnabled = Settings.NextAPUEnabled; + + if(Settings.APUEnabled) + APU.Flags &= ~HALTED_FLAG; + + ZeroMemory(spc_dump_dsp, 0x100); + ZeroMemory(IAPU.RAM, 0x100); + memset(IAPU.RAM+0x20, 0xFF, 0x20); + memset(IAPU.RAM+0x60, 0xFF, 0x20); + memset(IAPU.RAM+0xA0, 0xFF, 0x20); + memset(IAPU.RAM+0xE0, 0xFF, 0x20); + + for(i=1;i<256;i++) + { + memcpy(IAPU.RAM+(i<<8), IAPU.RAM, 0x100); + } + + ZeroMemory (APU.OutPorts, 4); + IAPU.DirectPage = IAPU.RAM; + memmove (APU.ExtraRAM, &IAPU.RAM [0xffc0], sizeof (APUROM)); + memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); + APU.Cycles = 0; + APU.OldCycles = -99999999; // For shapshot compatibility + APURegisters.YA.W = 0; + APURegisters.X = 0; + APURegisters.S = 0xef; + APURegisters.P = 0x02; + S9xAPUUnpackStatus (); + APURegisters.PC = 0; + IAPU.APUExecuting = Settings.APUEnabled; +#ifdef SPC700_SHUTDOWN + IAPU.WaitAddress1 = NULL; + IAPU.WaitAddress2 = NULL; + IAPU.WaitCounter = 0; +#endif + APU.NextAPUTimerPos = 0; + APU.APUTimerCounter = 0; + APU.ShowROM = TRUE; + IAPU.RAM [0xf1] = 0x80; + + for (i = 0; i < 3; i++) + { + APU.TimerEnabled [i] = FALSE; + APU.TimerValueWritten [i] = 0; + APU.TimerTarget [i] = 0; + APU.Timer [i] = 0; + } + for (int j = 0; j < 0x80; j++) + APU.DSP [j] = 0; + + IAPU.TwoCycles = IAPU.OneCycle * 2; + + for (i = 0; i < 256; i++) + S9xAPUCycles [i] = S9xAPUCycleLengths [i] * IAPU.OneCycle; + + APU.DSP [APU_ENDX] = 0; + APU.DSP [APU_KOFF] = 0; + APU.DSP [APU_KON] = 0; + APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED; + APU.KeyedChannels = 0; + + S9xResetSound (TRUE); + S9xSetEchoEnable (0); + + IAPU.OUTXNotifier = false; + IAPU.ENVXNotifier = false; +} + +void S9xSetAPUDSP (uint8 byte) +{ + uint8 reg = IAPU.RAM [0xf2]; + static uint8 KeyOn; + static uint8 KeyOnPrev; + + spc_dump_dsp[reg] = byte; + + switch (reg) + { + case APU_FLG: + if (byte & APU_SOFT_RESET) + { + APU.DSP [reg] = APU_MUTE | APU_ECHO_DISABLED | (byte & 0x1f); + APU.DSP [APU_ENDX] = 0; + APU.DSP [APU_KOFF] = 0; + APU.DSP [APU_KON] = 0; + S9xSetEchoWriteEnable (FALSE); +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] DSP reset\n", ICPU.Scanline); +#endif + // Kill sound + S9xResetSound (FALSE); + } + else + { + S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED)); + if (byte & APU_MUTE) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Mute sound\n", ICPU.Scanline); +#endif + S9xSetSoundMute (TRUE); + } + else + S9xSetSoundMute (FALSE); + + SoundData.noise_rate = env_counter_table[byte & 0x1f]; + } + break; + case APU_NON: + if (byte != APU.DSP [APU_NON]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Noise:", ICPU.Scanline); +#endif + uint8 mask = 1; + for (int c = 0; c < 8; c++, mask <<= 1) + { + int type; + if (byte & mask) + { + type = SOUND_NOISE; +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + { + if (APU.DSP [reg] & mask) + S9xTraceSoundDSP ("%d,", c); + else + S9xTraceSoundDSP ("%d(on),", c); + } +#endif + } + else + { + type = SOUND_SAMPLE; +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + { + if (APU.DSP [reg] & mask) + S9xTraceSoundDSP ("%d(off),", c); + } +#endif + } + S9xSetSoundType (c, type); + } +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("\n"); +#endif + } + break; + case APU_MVOL_LEFT: + if (byte != APU.DSP [APU_MVOL_LEFT]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Master volume left:%d\n", + ICPU.Scanline, (signed char) byte); +#endif + S9xSetMasterVolume ((signed char) byte, + (signed char) APU.DSP [APU_MVOL_RIGHT]); + } + break; + case APU_MVOL_RIGHT: + if (byte != APU.DSP [APU_MVOL_RIGHT]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Master volume right:%d\n", + ICPU.Scanline, (signed char) byte); +#endif + S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT], + (signed char) byte); + } + break; + case APU_EVOL_LEFT: + if (byte != APU.DSP [APU_EVOL_LEFT]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Echo volume left:%d\n", + ICPU.Scanline, (signed char) byte); +#endif + S9xSetEchoVolume ((signed char) byte, + (signed char) APU.DSP [APU_EVOL_RIGHT]); + } + break; + case APU_EVOL_RIGHT: + if (byte != APU.DSP [APU_EVOL_RIGHT]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Echo volume right:%d\n", + ICPU.Scanline, (signed char) byte); +#endif + S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT], + (signed char) byte); + } + break; + case APU_ENDX: +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Reset ENDX\n", ICPU.Scanline); +#endif + byte = 0; + break; + + case APU_KOFF: + // if (byte) + { + uint8 mask = 1; +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Key off:", ICPU.Scanline); +#endif + for (int c = 0; c < 8; c++, mask <<= 1) + { + if ((byte & mask) != 0) + { +#ifdef DEBUGGER + + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("%d,", c); +#endif + if (APU.KeyedChannels & mask) + { + { + KeyOnPrev&=~mask; + APU.KeyedChannels &= ~mask; + APU.DSP [APU_KON] &= ~mask; + //APU.DSP [APU_KOFF] |= mask; + S9xSetSoundKeyOff (c); + } + } + } + else if((KeyOnPrev&mask)!=0) + { + KeyOnPrev&=~mask; + APU.KeyedChannels |= mask; + //APU.DSP [APU_KON] |= mask; + APU.DSP [APU_KOFF] &= ~mask; + APU.DSP [APU_ENDX] &= ~mask; + S9xPlaySample (c); + } + } +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("\n"); +#endif + } + //KeyOnPrev=0; + APU.DSP [APU_KOFF] = byte; + return; + case APU_KON: + if (spc_is_dumping) + { + if (byte & ~spc_is_dumping_temp) + { + APURegisters.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus(); +#ifndef NGC + S9xSPCDump (S9xGetFilenameInc((".spc"), SPC_DIR)); +#endif + spc_is_dumping = 0; + } + } + if (byte) + { + uint8 mask = 1; +#ifdef DEBUGGER + + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Key on:", ICPU.Scanline); +#endif + for (int c = 0; c < 8; c++, mask <<= 1) + { + if ((byte & mask) != 0) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("%d,", c); +#endif + // Pac-In-Time requires that channels can be key-on + // regardeless of their current state. + if((APU.DSP [APU_KOFF] & mask) ==0) + { + KeyOnPrev&=~mask; + APU.KeyedChannels |= mask; + //APU.DSP [APU_KON] |= mask; + //APU.DSP [APU_KOFF] &= ~mask; + APU.DSP [APU_ENDX] &= ~mask; + S9xPlaySample (c); + } + else KeyOn|=mask; + } + } +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("\n"); +#endif + } + spc_is_dumping_temp = byte; + return; + + case APU_VOL_LEFT + 0x00: + case APU_VOL_LEFT + 0x10: + case APU_VOL_LEFT + 0x20: + case APU_VOL_LEFT + 0x30: + case APU_VOL_LEFT + 0x40: + case APU_VOL_LEFT + 0x50: + case APU_VOL_LEFT + 0x60: + case APU_VOL_LEFT + 0x70: + // At Shin Megami Tensei suggestion 6/11/00 + // if (byte != APU.DSP [reg]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d volume left: %d\n", + ICPU.Scanline, reg>>4, (signed char) byte); +#endif + S9xSetSoundVolume (reg >> 4, (signed char) byte, + (signed char) APU.DSP [reg + 1]); + } + break; + case APU_VOL_RIGHT + 0x00: + case APU_VOL_RIGHT + 0x10: + case APU_VOL_RIGHT + 0x20: + case APU_VOL_RIGHT + 0x30: + case APU_VOL_RIGHT + 0x40: + case APU_VOL_RIGHT + 0x50: + case APU_VOL_RIGHT + 0x60: + case APU_VOL_RIGHT + 0x70: + // At Shin Megami Tensei suggestion 6/11/00 + // if (byte != APU.DSP [reg]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d volume right: %d\n", + ICPU.Scanline, reg >>4, (signed char) byte); +#endif + S9xSetSoundVolume (reg >> 4, (signed char) APU.DSP [reg - 1], + (signed char) byte); + } + break; + + case APU_P_LOW + 0x00: + case APU_P_LOW + 0x10: + case APU_P_LOW + 0x20: + case APU_P_LOW + 0x30: + case APU_P_LOW + 0x40: + case APU_P_LOW + 0x50: + case APU_P_LOW + 0x60: + case APU_P_LOW + 0x70: +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d freq low: %d\n", + ICPU.Scanline, reg>>4, byte); +#endif + S9xSetSoundHertz (reg >> 4, ((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 8); + break; + + case APU_P_HIGH + 0x00: + case APU_P_HIGH + 0x10: + case APU_P_HIGH + 0x20: + case APU_P_HIGH + 0x30: + case APU_P_HIGH + 0x40: + case APU_P_HIGH + 0x50: + case APU_P_HIGH + 0x60: + case APU_P_HIGH + 0x70: +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d freq high: %d\n", + ICPU.Scanline, reg>>4, byte); +#endif + S9xSetSoundHertz (reg >> 4, + (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8); + break; + + case APU_SRCN + 0x00: + case APU_SRCN + 0x10: + case APU_SRCN + 0x20: + case APU_SRCN + 0x30: + case APU_SRCN + 0x40: + case APU_SRCN + 0x50: + case APU_SRCN + 0x60: + case APU_SRCN + 0x70: +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d sample number: %d\n", + ICPU.Scanline, reg>>4, byte); +#endif + break; + + case APU_ADSR1 + 0x00: + case APU_ADSR1 + 0x10: + case APU_ADSR1 + 0x20: + case APU_ADSR1 + 0x30: + case APU_ADSR1 + 0x40: + case APU_ADSR1 + 0x50: + case APU_ADSR1 + 0x60: + case APU_ADSR1 + 0x70: + if (byte != APU.DSP [reg]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d adsr1: %02x\n", + ICPU.Scanline, reg>>4, byte); +#endif + { + S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, + APU.DSP [reg + 1]); + } + } + break; + + case APU_ADSR2 + 0x00: + case APU_ADSR2 + 0x10: + case APU_ADSR2 + 0x20: + case APU_ADSR2 + 0x30: + case APU_ADSR2 + 0x40: + case APU_ADSR2 + 0x50: + case APU_ADSR2 + 0x60: + case APU_ADSR2 + 0x70: + if (byte != APU.DSP [reg]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d adsr2: %02x\n", + ICPU.Scanline, reg>>4, byte); +#endif + { + S9xFixEnvelope (reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1], + byte); + } + } + break; + + case APU_GAIN + 0x00: + case APU_GAIN + 0x10: + case APU_GAIN + 0x20: + case APU_GAIN + 0x30: + case APU_GAIN + 0x40: + case APU_GAIN + 0x50: + case APU_GAIN + 0x60: + case APU_GAIN + 0x70: + if (byte != APU.DSP [reg]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] %d gain: %02x\n", + ICPU.Scanline, reg>>4, byte); +#endif + { + S9xFixEnvelope (reg >> 4, byte, APU.DSP [reg - 2], + APU.DSP [reg - 1]); + } + } + break; + + case APU_ENVX + 0x00: + case APU_ENVX + 0x10: + case APU_ENVX + 0x20: + case APU_ENVX + 0x30: + case APU_ENVX + 0x40: + case APU_ENVX + 0x50: + case APU_ENVX + 0x60: + case APU_ENVX + 0x70: + break; + + case APU_OUTX + 0x00: + case APU_OUTX + 0x10: + case APU_OUTX + 0x20: + case APU_OUTX + 0x30: + case APU_OUTX + 0x40: + case APU_OUTX + 0x50: + case APU_OUTX + 0x60: + case APU_OUTX + 0x70: + break; + + case APU_DIR: +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + S9xTraceSoundDSP ("[%d] Sample directory to: %02x\n", + ICPU.Scanline, byte); +#endif + break; + + case APU_PMON: + if (byte != APU.DSP [APU_PMON]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + { + S9xTraceSoundDSP ("[%d] FreqMod:", ICPU.Scanline); + uint8 mask = 1; + for (int c = 0; c < 8; c++, mask <<= 1) + { + if (byte & mask) + { + if (APU.DSP [reg] & mask) + S9xTraceSoundDSP ("%d", c); + else + S9xTraceSoundDSP ("%d(on),", c); + } + else + { + if (APU.DSP [reg] & mask) + S9xTraceSoundDSP ("%d(off),", c); + } + } + S9xTraceSoundDSP ("\n"); + } +#endif + S9xSetFrequencyModulationEnable (byte); + } + break; + + case APU_EON: + if (byte != APU.DSP [APU_EON]) + { +#ifdef DEBUGGER + if (Settings.TraceSoundDSP) + { + S9xTraceSoundDSP ("[%d] Echo:", ICPU.Scanline); + uint8 mask = 1; + for (int c = 0; c < 8; c++, mask <<= 1) + { + if (byte & mask) + { + if (APU.DSP [reg] & mask) + S9xTraceSoundDSP ("%d", c); + else + S9xTraceSoundDSP ("%d(on),", c); + } + else + { + if (APU.DSP [reg] & mask) + S9xTraceSoundDSP ("%d(off),", c); + } + } + S9xTraceSoundDSP ("\n"); + } +#endif + S9xSetEchoEnable (byte); + } + break; + + case APU_EFB: + S9xSetEchoFeedback ((signed char) byte); + break; + + case APU_ESA: + break; + + case APU_EDL: + S9xSetEchoDelay (byte & 0xf); + break; + + case APU_C0: + case APU_C1: + case APU_C2: + case APU_C3: + case APU_C4: + case APU_C5: + case APU_C6: + case APU_C7: + S9xSetFilterCoefficient (reg >> 4, (signed char) byte); + break; + default: + // XXX + //printf ("Write %02x to unknown APU register %02x\n", byte, reg); + break; + } + + KeyOnPrev|=KeyOn; + KeyOn=0; + + if (reg < 0x80) + APU.DSP [reg] = byte; +} + +void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2) +{ + if (adsr1 & 0x80) + { + if (S9xSetSoundMode (channel, MODE_ADSR)) + S9xSetSoundADSR (channel, adsr1 & 0xf, (adsr1 >> 4) & 7, + adsr2 & 0x1f, (adsr2 >> 5) & 7); + } + else + { + if ((gain & 0x80) == 0) + { + if (S9xSetSoundMode (channel, MODE_GAIN)) + S9xSetEnvelopeHeight (channel, (gain & 0x7f) << ENV_SHIFT); + } + else + { + if (gain & 0x40) + { + if (S9xSetSoundMode (channel, (gain & 0x20) ? + MODE_INCREASE_BENT_LINE : MODE_INCREASE_LINEAR)) + S9xSetEnvelopeRate (channel, env_counter_table[gain & 0x1f], ENV_MAX); + } + else + { + if (S9xSetSoundMode (channel, (gain & 0x20) ? + MODE_DECREASE_EXPONENTIAL : MODE_DECREASE_LINEAR)) + S9xSetEnvelopeRate (channel, env_counter_table[gain & 0x1f], 0); + } + } + } +} + +void S9xSetAPUControl (uint8 byte) +{ + //if (byte & 0x40) + //printf ("*** Special SPC700 timing enabled\n"); + if ((byte & 1) != 0 && !APU.TimerEnabled [0]) + { + APU.Timer [0] = 0; + IAPU.RAM [0xfd] = 0; + if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) + APU.TimerTarget [0] = 0x100; + } + if ((byte & 2) != 0 && !APU.TimerEnabled [1]) + { + APU.Timer [1] = 0; + IAPU.RAM [0xfe] = 0; + if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) + APU.TimerTarget [1] = 0x100; + } + if ((byte & 4) != 0 && !APU.TimerEnabled [2]) + { + APU.Timer [2] = 0; + IAPU.RAM [0xff] = 0; + if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) + APU.TimerTarget [2] = 0x100; + } + APU.TimerEnabled [0] = byte & 1; + APU.TimerEnabled [1] = (byte & 2) >> 1; + APU.TimerEnabled [2] = (byte & 4) >> 2; + + if (byte & 0x10) + IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0; + + if (byte & 0x20) + IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0; + + if (byte & 0x80) + { + if (!APU.ShowROM) + { + memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + APU.ShowROM = TRUE; + } + } + else + { + if (APU.ShowROM) + { + APU.ShowROM = FALSE; + memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM)); + } + } + IAPU.RAM [0xf1] = byte; +} + +void S9xSetAPUTimer (uint16 Address, uint8 byte) +{ + IAPU.RAM [Address] = byte; + + switch (Address) + { + case 0xfa: + if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) + APU.TimerTarget [0] = 0x100; + APU.TimerValueWritten [0] = TRUE; + break; + case 0xfb: + if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) + APU.TimerTarget [1] = 0x100; + APU.TimerValueWritten [1] = TRUE; + break; + case 0xfc: + if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) + APU.TimerTarget [2] = 0x100; + APU.TimerValueWritten [2] = TRUE; + break; + } +} + +void S9xAPUExecute (void) +{ + while ((CPU.Cycles << SNES_APU_ACCURACY) >= APU.NextAPUTimerPos) + { + // catch up the APU timers + if (IAPU.APUExecuting) + { + while (APU.Cycles < APU.NextAPUTimerPos) + APU_EXECUTE1(); + } + else + APU.Cycles = APU.NextAPUTimerPos; + + APU.NextAPUTimerPos += SNES_APUTIMER2_CYCLE_SCALED; + + if (APU.TimerEnabled [2]) + { + APU.Timer [2] ++; + if (APU.Timer [2] >= APU.TimerTarget [2]) + { + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] = 0; + #ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; + #endif + } + } + + if (++APU.APUTimerCounter == 8) + { + APU.APUTimerCounter = 0; + + if (APU.TimerEnabled [0]) + { + APU.Timer [0]++; + if (APU.Timer [0] >= APU.TimerTarget [0]) + { + IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; + APU.Timer [0] = 0; + #ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; + #endif + } + } + + if (APU.TimerEnabled [1]) + { + APU.Timer [1]++; + if (APU.Timer [1] >= APU.TimerTarget [1]) + { + IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; + APU.Timer [1] = 0; + #ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; + #endif + } + } + } + } + + // catch up the current cycles + if (IAPU.APUExecuting) + { + while (APU.Cycles < (CPU.Cycles << SNES_APU_ACCURACY)) + APU_EXECUTE1(); + } + else + APU.Cycles = (CPU.Cycles << SNES_APU_ACCURACY); +} + +uint8 S9xGetAPUDSP () +{ + uint8 reg = IAPU.RAM [0xf2] & 0x7f; + uint8 byte = APU.DSP [reg]; + + switch (reg) + { + case APU_KON: + IAPU.KONNotifier = true; + break; + case APU_KOFF: + IAPU.KOFFNotifier = true; + break; + + case APU_OUTX + 0x00: + case APU_OUTX + 0x10: + case APU_OUTX + 0x20: + case APU_OUTX + 0x30: + case APU_OUTX + 0x40: + case APU_OUTX + 0x50: + case APU_OUTX + 0x60: + case APU_OUTX + 0x70: + { + IAPU.OUTXNotifier = true; + + if(Settings.FakeMuteFix) + { + // hack that is off by default: fixes Terranigma desync + return (0); + } + else + { + if (SoundData.channels [reg >> 4].state == SOUND_SILENT) + return (0); + return (int8) (SoundData.channels [reg >> 4].out_sample >> 8); + } + } + + case APU_ENVX + 0x00: + case APU_ENVX + 0x10: + case APU_ENVX + 0x20: + case APU_ENVX + 0x30: + case APU_ENVX + 0x40: + case APU_ENVX + 0x50: + case APU_ENVX + 0x60: + case APU_ENVX + 0x70: + { + IAPU.ENVXNotifier = true; + + return (S9xGetEnvelopeHeight (reg >> 4)); + } + + case APU_ENDX: + IAPU.ENDXNotifier = true; + // To fix speech in Magical Drop 2 6/11/00 + // APU.DSP [APU_ENDX] = 0; + break; + + default: + break; + } + + return (byte); +} diff --git a/source/snes9x/apu/apu.h b/source/snes9x/apu.h similarity index 65% rename from source/snes9x/apu/apu.h rename to source/snes9x/apu.h index cdd5931..4a368bb 100644 --- a/source/snes9x/apu/apu.h +++ b/source/snes9x/apu.h @@ -159,43 +159,139 @@ **********************************************************************************/ -#ifndef _APU_H_ -#define _APU_H_ -#include "snes9x.h" -#include "SNES_SPC.h" -typedef void (*apu_callback) (void *); +#ifndef _apu_h_ +#define _apu_h_ -#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8) +#include "spc700.h" -bool8 S9xInitAPU (void); -void S9xDeinitAPU (void); +struct SIAPU +{ + uint8 *PC; + uint8 *RAM; + uint8 *DirectPage; + bool8 APUExecuting; + uint8 Bit; + uint32 Address; + uint8 *WaitAddress1; + uint8 *WaitAddress2; + uint32 WaitCounter; + uint8 *ShadowRAM; // unused + uint8 *CachedSamples; // unused + uint8 _Carry; + uint8 _Zero; + uint8 _Overflow; + uint32 TimerErrorCounter; + uint32 Scanline; + int32 OneCycle; + int32 TwoCycles; + bool8 KONNotifier; + bool8 KOFFNotifier; + bool8 OUTXNotifier; + bool8 ENVXNotifier; + bool8 ENDXNotifier; +}; + +struct SAPU +{ + int32 OldCycles; // unused + bool8 ShowROM; + uint32 Flags; + uint8 KeyedChannels; + uint8 OutPorts [4]; + uint8 DSP [0x80]; + uint8 ExtraRAM [64]; + uint16 Timer [3]; + uint16 TimerTarget [3]; + bool8 TimerEnabled [3]; + bool8 TimerValueWritten [3]; + int32 Cycles; + int32 NextAPUTimerPos; + int32 APUTimerCounter; +}; + +EXTERN_C struct SAPU APU; +EXTERN_C struct SIAPU IAPU; +extern int spc_is_dumping; +extern int spc_is_dumping_temp; +extern uint8 spc_dump_dsp[0x100]; +STATIC inline void S9xAPUUnpackStatus() +{ + IAPU._Zero = ((APURegisters.P & Zero) == 0) | (APURegisters.P & Negative); + IAPU._Carry = (APURegisters.P & Carry); + IAPU._Overflow = (APURegisters.P & Overflow) >> 6; +} + +STATIC inline void S9xAPUPackStatus() +{ + APURegisters.P &= ~(Zero | Negative | Carry | Overflow); + APURegisters.P |= IAPU._Carry | ((IAPU._Zero == 0) << 1) | + (IAPU._Zero & 0x80) | (IAPU._Overflow << 6); +} + +START_EXTERN_C void S9xResetAPU (void); -void S9xSoftResetAPU (void); -uint8 S9xAPUReadPort (int); -void S9xAPUWritePort (int, uint8); +bool8 S9xInitAPU (); +void S9xDeinitAPU (); +void S9xDecacheSamples (); +int S9xTraceAPU (); +int S9xAPUOPrint (char *buffer, uint16 Address); +void S9xSetAPUControl (uint8 byte); +void S9xSetAPUDSP (uint8 byte); +uint8 S9xGetAPUDSP (); +void S9xSetAPUTimer (uint16 Address, uint8 byte); void S9xAPUExecute (void); -void S9xAPUEndScanline (void); -void S9xAPUSetReferenceTime (int32); -void S9xAPUTimingSetSpeedup (int); -void S9xAPULoadState (uint8 *); -void S9xAPUSaveState (uint8 *); -void S9xDumpSPCSnapshot (void); +bool8 S9xInitSound (int quality, bool8 stereo, int buffer_size); +void S9xOpenCloseSoundTracingFile (bool8); +void S9xPrintAPUState (); +extern int32 S9xAPUCycles [256]; // Scaled cycle lengths +extern int32 S9xAPUCycleLengths [256]; // Raw data. +extern void (*S9xApuOpcodes [256]) (void); +END_EXTERN_C -bool8 S9xInitSound (int, int); -bool8 S9xOpenSoundDevice (int); -bool8 S9xSyncSound (void); -int S9xGetSampleCount (void); -void S9xSetSoundControl (uint8); -void S9xSetSoundMute (bool8); -void S9xLandSamples (void); -void S9xFinalizeSamples (void); -void S9xClearSamples (void); -bool8 S9xMixSamples (uint8 *, int); -void S9xSetSamplesAvailableCallback (apu_callback, void *); +#define APU_VOL_LEFT 0x00 +#define APU_VOL_RIGHT 0x01 +#define APU_P_LOW 0x02 +#define APU_P_HIGH 0x03 +#define APU_SRCN 0x04 +#define APU_ADSR1 0x05 +#define APU_ADSR2 0x06 +#define APU_GAIN 0x07 +#define APU_ENVX 0x08 +#define APU_OUTX 0x09 -extern SNES_SPC *spc_core; +#define APU_MVOL_LEFT 0x0c +#define APU_MVOL_RIGHT 0x1c +#define APU_EVOL_LEFT 0x2c +#define APU_EVOL_RIGHT 0x3c +#define APU_KON 0x4c +#define APU_KOFF 0x5c +#define APU_FLG 0x6c +#define APU_ENDX 0x7c +#define APU_EFB 0x0d +#define APU_PMON 0x2d +#define APU_NON 0x3d +#define APU_EON 0x4d +#define APU_DIR 0x5d +#define APU_ESA 0x6d +#define APU_EDL 0x7d + +#define APU_C0 0x0f +#define APU_C1 0x1f +#define APU_C2 0x2f +#define APU_C3 0x3f +#define APU_C4 0x4f +#define APU_C5 0x5f +#define APU_C6 0x6f +#define APU_C7 0x7f + +#define APU_SOFT_RESET 0x80 +#define APU_MUTE 0x40 +#define APU_ECHO_DISABLED 0x20 + +#define FREQUENCY_MASK 0x3fff #endif + diff --git a/source/snes9x/apu/SNES_SPC.cpp b/source/snes9x/apu/SNES_SPC.cpp deleted file mode 100644 index fb3b147..0000000 --- a/source/snes9x/apu/SNES_SPC.cpp +++ /dev/null @@ -1,564 +0,0 @@ -// Core SPC emulation: CPU, timers, SMP registers, memory - -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SNES_SPC.h" - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -// (n ? n : 256) -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) - -// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which -// do crazy echo buffer accesses. -#ifndef SPC_MORE_ACCURACY - #define SPC_MORE_ACCURACY 0 -#endif - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - - -//// Timers - -#if SPC_DISABLE_TEMPO - #define TIMER_DIV( t, n ) ((n) >> t->prescaler) - #define TIMER_MUL( t, n ) ((n) << t->prescaler) -#else - #define TIMER_DIV( t, n ) ((n) / t->prescaler) - #define TIMER_MUL( t, n ) ((n) * t->prescaler) -#endif - -SNES_SPC::Timer* SNES_SPC::run_timer_( Timer* t, rel_time_t time ) -{ - int elapsed = TIMER_DIV( t, time - t->next_time ) + 1; - t->next_time += TIMER_MUL( t, elapsed ); - - if ( t->enabled ) - { - int remain = IF_0_THEN_256( t->period - t->divider ); - int divider = t->divider + elapsed; - int over = elapsed - remain; - if ( over >= 0 ) - { - int n = over / t->period; - t->counter = (t->counter + 1 + n) & 0x0F; - divider = over - n * t->period; - } - t->divider = (uint8_t) divider; - } - return t; -} - -inline SNES_SPC::Timer* SNES_SPC::run_timer( Timer* t, rel_time_t time ) -{ - if ( time >= t->next_time ) - t = run_timer_( t, time ); - return t; -} - - -//// ROM - -void SNES_SPC::enable_rom( int enable ) -{ - if ( m.rom_enabled != enable ) - { - m.rom_enabled = enable; - if ( enable ) - memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram ); - memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size ); - // TODO: ROM can still get overwritten when DSP writes to echo buffer - } -} - - -//// DSP - -#if SPC_LESS_ACCURATE - int const max_reg_time = 29; - - signed char const SNES_SPC::reg_times_ [256] = - { - -1, 0,-11,-10,-15,-11, -2, -2, 4, 3, 14, 14, 26, 26, 14, 22, - 2, 3, 0, 1,-12, 0, 1, 1, 7, 6, 14, 14, 27, 14, 14, 23, - 5, 6, 3, 4, -1, 3, 4, 4, 10, 9, 14, 14, 26, -5, 14, 23, - 8, 9, 6, 7, 2, 6, 7, 7, 13, 12, 14, 14, 27, -4, 14, 24, - 11, 12, 9, 10, 5, 9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24, - 14, 15, 12, 13, 8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24, - 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25, - 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25, - - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - }; - - #define RUN_DSP( time, offset ) \ - int count = (time) - (offset) - m.dsp_time;\ - if ( count >= 0 )\ - {\ - int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\ - m.dsp_time += clock_count;\ - dsp.run( clock_count );\ - } -#else - #define RUN_DSP( time, offset ) \ - {\ - int count = (time) - m.dsp_time;\ - if ( !SPC_MORE_ACCURACY || count )\ - {\ - assert( count > 0 );\ - m.dsp_time = (time);\ - dsp.run( count );\ - }\ - } -#endif - -int SNES_SPC::dsp_read( rel_time_t time ) -{ - RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] ); - - int result = dsp.read( REGS [r_dspaddr] & 0x7F ); - - #ifdef SPC_DSP_READ_HOOK - SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result ); - #endif - - return result; -} - -inline void SNES_SPC::dsp_write( int data, rel_time_t time ) -{ - RUN_DSP( time, reg_times [REGS [r_dspaddr]] ) - #if SPC_LESS_ACCURATE - else if ( m.dsp_time == skipping_time ) - { - int r = REGS [r_dspaddr]; - if ( r == SPC_DSP::r_kon ) - m.skipped_kon |= data & ~dsp.read( SPC_DSP::r_koff ); - - if ( r == SPC_DSP::r_koff ) - { - m.skipped_koff |= data; - m.skipped_kon &= ~data; - } - } - #endif - - #ifdef SPC_DSP_WRITE_HOOK - SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data ); - #endif - - if ( REGS [r_dspaddr] <= 0x7F ) - dsp.write( REGS [r_dspaddr], data ); - else if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to DSP register > $7F\n" ); -} - - -//// Memory access extras - -#if SPC_MORE_ACCURACY - #define MEM_ACCESS( time, addr ) \ - {\ - if ( time >= m.dsp_time )\ - {\ - RUN_DSP( time, max_reg_time );\ - }\ - } -#elif !defined (NDEBUG) - // Debug-only check for read/write within echo buffer, since this might result in - // inaccurate emulation due to the DSP not being caught up to the present. - - bool SNES_SPC::check_echo_access( int addr ) - { - if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) - { - int start = 0x100 * dsp.read( SPC_DSP::r_esa ); - int size = 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); - int end = start + (size ? size : 4); - if ( start <= addr && addr < end ) - { - if ( !m.echo_accessed ) - { - m.echo_accessed = 1; - return true; - } - } - } - return false; - } - - #define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) ); -#else - #define MEM_ACCESS( time, addr ) -#endif - - -//// CPU write - -#if SPC_MORE_ACCURACY -static unsigned char const glitch_probs [3] [256] = -{ - 0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B, - 0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08, - 0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09, - 0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01, - 0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05, - 0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07, - 0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07, - 0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01, - 0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09, - 0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08, - 0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03, - 0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03, - 0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07, - 0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02, - 0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02, - 0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01, - - 0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07, - 0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06, - 0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09, - 0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03, - 0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07, - 0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03, - 0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06, - 0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03, - 0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05, - 0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04, - 0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05, - 0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01, - 0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05, - 0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01, - 0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03, - 0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01, - - 0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A, - 0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A, - 0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A, - 0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09, - 0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09, - 0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02, - 0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07, - 0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04, - 0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A, - 0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07, - 0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04, - 0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02, - 0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06, - 0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03, - 0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02, - 0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03, -}; -#endif - -// divided into multiple functions to keep rarely-used functionality separate -// so often-used functionality can be optimized better by compiler - -// If write isn't preceded by read, data has this added to it -int const no_read_before_write = 0x2000; - -void SNES_SPC::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) -{ - switch ( addr ) - { - case r_t0target: - case r_t1target: - case r_t2target: { - Timer* t = &m.timers [addr - r_t0target]; - int period = IF_0_THEN_256( data ); - if ( t->period != period ) - { - t = run_timer( t, time ); - #if SPC_MORE_ACCURACY - // Insane behavior when target is written just after counter is - // clocked and counter matches new period and new period isn't 1, 2, 4, or 8 - if ( t->divider == (period & 0xFF) && - t->next_time == time + TIMER_MUL( t, 1 ) && - ((period - 1) | ~0x0F) & period ) - { - //dprintf( "SPC pathological timer target write\n" ); - - // If the period is 3, 5, or 9, there's a probability this behavior won't occur, - // based on the previous period - int prob = 0xFF; - int old_period = t->period & 0xFF; - if ( period == 3 ) prob = glitch_probs [0] [old_period]; - if ( period == 5 ) prob = glitch_probs [1] [old_period]; - if ( period == 9 ) prob = glitch_probs [2] [old_period]; - - // The glitch suppresses incrementing of one of the counter bits, based on - // the lowest set bit in the new period - int b = 1; - while ( !(period & b) ) - b <<= 1; - - if ( (rand() >> 4 & 0xFF) <= prob ) - t->divider = (t->divider - b) & 0xFF; - } - #endif - t->period = period; - } - break; - } - - case r_t0out: - case r_t1out: - case r_t2out: - if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); - - if ( data < no_read_before_write / 2 ) - run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0; - break; - - // Registers that act like RAM - case 0x8: - case 0x9: - REGS_IN [addr] = (uint8_t) data; - break; - - case r_test: - if ( (uint8_t) data != 0x0A ) - dprintf( "SPC wrote to test register\n" ); - break; - - case r_control: - // port clears - if ( data & 0x10 ) - { - REGS_IN [r_cpuio0] = 0; - REGS_IN [r_cpuio1] = 0; - } - if ( data & 0x20 ) - { - REGS_IN [r_cpuio2] = 0; - REGS_IN [r_cpuio3] = 0; - } - - // timers - { - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - int enabled = data >> i & 1; - if ( t->enabled != enabled ) - { - t = run_timer( t, time ); - t->enabled = enabled; - if ( enabled ) - { - t->divider = 0; - t->counter = 0; - } - } - } - } - enable_rom( data & 0x80 ); - break; - } -} - -void SNES_SPC::cpu_write_smp_reg( int data, rel_time_t time, int addr ) -{ - if ( addr == r_dspdata ) // 99% - dsp_write( data, time ); - else - cpu_write_smp_reg_( data, time, addr ); -} - -void SNES_SPC::cpu_write_high( int data, int i, rel_time_t time ) -{ - if ( i < rom_size ) - { - m.hi_ram [i] = (uint8_t) data; - if ( m.rom_enabled ) - RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM - } - else - { - assert( RAM [i + rom_addr] == (uint8_t) data ); - RAM [i + rom_addr] = cpu_pad_fill; // restore overwritten padding - cpu_write( data, i + rom_addr - 0x10000, time ); - } -} - -int const bits_in_int = CHAR_BIT * sizeof (int); - -void SNES_SPC::cpu_write( int data, int addr, rel_time_t time ) -{ - MEM_ACCESS( time, addr ) - - // RAM - RAM [addr] = (uint8_t) data; - int reg = addr - 0xF0; - if ( reg >= 0 ) // 64% - { - // $F0-$FF - if ( reg < reg_count ) // 87% - { - REGS [reg] = (uint8_t) data; - - // Ports - #ifdef SPC_PORT_WRITE_HOOK - if ( (unsigned) (reg - r_cpuio0) < port_count ) - SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0), - (uint8_t) data, ®S [r_cpuio0] ); - #endif - - // Registers other than $F2 and $F4-$F7 - //if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 ) - // TODO: this is a bit on the fragile side - if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36% - cpu_write_smp_reg( data, time, reg ); - } - // High mem/address wrap-around - else - { - reg -= rom_addr - 0xF0; - if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around - cpu_write_high( data, reg, time ); - } - } -} - - -//// CPU read - -inline int SNES_SPC::cpu_read_smp_reg( int reg, rel_time_t time ) -{ - int result = REGS_IN [reg]; - reg -= r_dspaddr; - // DSP addr and data - if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3 - { - result = REGS [r_dspaddr]; - if ( (unsigned) reg == 1 ) - result = dsp_read( time ); // 0xF3 - } - return result; -} - -int SNES_SPC::cpu_read( int addr, rel_time_t time ) -{ - MEM_ACCESS( time, addr ) - - // RAM - int result = RAM [addr]; - int reg = addr - 0xF0; - if ( reg >= 0 ) // 40% - { - reg -= 0x10; - if ( (unsigned) reg >= 0xFF00 ) // 21% - { - reg += 0x10 - r_t0out; - - // Timers - if ( (unsigned) reg < timer_count ) // 90% - { - Timer* t = &m.timers [reg]; - if ( time >= t->next_time ) - t = run_timer_( t, time ); - result = t->counter; - t->counter = 0; - } - // Other registers - else if ( reg < 0 ) // 10% - { - result = cpu_read_smp_reg( reg + r_t0out, time ); - } - else // 1% - { - assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 ); - result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time ); - } - } - } - - return result; -} - - -//// Run - -// Prefix and suffix for CPU emulator function -#define SPC_CPU_RUN_FUNC \ -BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ -{\ - rel_time_t rel_time = m.spc_time - end_time;\ - assert( rel_time <= 0 );\ - m.spc_time = end_time;\ - m.dsp_time += rel_time;\ - m.timers [0].next_time += rel_time;\ - m.timers [1].next_time += rel_time;\ - m.timers [2].next_time += rel_time; - -#define SPC_CPU_RUN_FUNC_END \ - m.spc_time += rel_time;\ - m.dsp_time -= rel_time;\ - m.timers [0].next_time -= rel_time;\ - m.timers [1].next_time -= rel_time;\ - m.timers [2].next_time -= rel_time;\ - assert( m.spc_time <= end_time );\ - return ®S [r_cpuio0];\ -} - -int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks - -void SNES_SPC::end_frame( time_t end_time ) -{ - // Catch CPU up to as close to end as possible. If final instruction - // would exceed end, does NOT execute it and leaves m.spc_time < end. - if ( end_time > m.spc_time ) - run_until_( end_time ); - - m.spc_time -= end_time; - m.extra_clocks += end_time; - - // Greatest number of clocks early that emulation can stop early due to - // not being able to execute current instruction without going over - // allowed time. - assert( -cpu_lag_max <= m.spc_time && m.spc_time <= 0 ); - - // Catch timers up to CPU - for ( int i = 0; i < timer_count; i++ ) - run_timer( &m.timers [i], 0 ); - - // Catch DSP up to CPU - if ( m.dsp_time < 0 ) - { - RUN_DSP( 0, max_reg_time ); - } - - // Save any extra samples beyond what should be generated - if ( m.buf_begin ) - save_extra(); -} - -// Inclusion here allows static memory access functions and better optimization -#include "SPC_CPU.h" diff --git a/source/snes9x/apu/SNES_SPC.h b/source/snes9x/apu/SNES_SPC.h deleted file mode 100644 index 74bfe0b..0000000 --- a/source/snes9x/apu/SNES_SPC.h +++ /dev/null @@ -1,287 +0,0 @@ -// SNES SPC-700 APU emulator - -// snes_spc 0.9.0 -#ifndef SNES_SPC_H -#define SNES_SPC_H - -#include "SPC_DSP.h" -#include "blargg_endian.h" - -struct SNES_SPC { -public: - typedef BOOST::uint8_t uint8_t; - - // Must be called once before using - blargg_err_t init(); - - // Sample pairs generated per second - enum { sample_rate = 32000 }; - -// Emulator use - - // Sets IPL ROM data. Library does not include ROM data. Most SPC music files - // don't need ROM, but a full emulator must provide this. - enum { rom_size = 0x40 }; - void init_rom( uint8_t const rom [rom_size] ); - - // Sets destination for output samples - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since last set - int sample_count() const; - - // Resets SPC to power-on state. This resets your output buffer, so you must - // call set_output() after this. - void reset(); - - // Emulates pressing reset switch on SNES. This resets your output buffer, so - // you must call set_output() after this. - void soft_reset(); - - // 1024000 SPC clocks per second, sample pair every 32 clocks - typedef int time_t; - enum { clock_rate = 1024000 }; - enum { clocks_per_sample = 32 }; - - // Emulated port read/write at specified time - enum { port_count = 4 }; - int read_port ( time_t, int port ); - void write_port( time_t, int port, int data ); - - // Runs SPC to end_time and starts a new time frame at 0 - void end_frame( time_t end_time ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - - // If true, prevents channels and global volumes from being phase-negated. - // Only supported by fast DSP. - void disable_surround( bool disable = true ); - - // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. - enum { tempo_unit = 0x100 }; - void set_tempo( int ); - -// SPC music files - - // Loads SPC data into emulator - enum { spc_min_file_size = 0x10180 }; - enum { spc_file_size = 0x10200 }; - blargg_err_t load_spc( void const* in, long size ); - - // Clears echo region. Useful after loading an SPC as many have garbage in echo. - void clear_echo(); - - // Plays for count samples and write samples to out. Discards samples if out - // is NULL. Count must be a multiple of 2 since output is stereo. - blargg_err_t play( int count, sample_t* out ); - - // Skips count samples. Several times faster than play() when using fast DSP. - blargg_err_t skip( int count ); - -// State save/load (only available with accurate DSP) - -#if !SPC_NO_COPY_STATE_FUNCS - // Saves/loads state - enum { state_size = 68 * 1024L }; // maximum space needed when saving - typedef SPC_DSP::copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Writes minimal header to spc_out - static void init_header( void* spc_out ); - - // Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out. - // Does not set up SPC header; use init_header() for that. - void save_spc( void* spc_out ); - - // Returns true if new key-on events occurred since last check. Useful for - // trimming silence while saving an SPC. - bool check_kon(); -#endif - -//// Snes9x Accessor - - void dsp_set_spc_snapshot_callback( void (*callback) (void) ); - void dsp_dump_spc_snapshot( void ); - void dsp_set_stereo_switch( int ); - uint8_t dsp_reg_value( int, int ); - int dsp_envx_value( int ); - -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::uint16_t uint16_t; - - // Time relative to m_spc_time. Speeds up code a bit by eliminating need to - // constantly add m_spc_time to time from CPU. CPU uses time that ends at - // 0 to eliminate reloading end time every instruction. It pays off. - typedef int rel_time_t; - - struct Timer - { - rel_time_t next_time; // time of next event - int prescaler; - int period; - int divider; - int enabled; - int counter; - }; - enum { reg_count = 0x10 }; - enum { timer_count = 3 }; - enum { extra_size = SPC_DSP::extra_size }; - - enum { signature_size = 35 }; - -private: - SPC_DSP dsp; - - #if SPC_LESS_ACCURATE - static signed char const reg_times_ [256]; - signed char reg_times [256]; - #endif - - struct state_t - { - Timer timers [timer_count]; - - uint8_t smp_regs [2] [reg_count]; - - struct - { - int pc; - int a; - int x; - int y; - int psw; - int sp; - } cpu_regs; - - rel_time_t dsp_time; - time_t spc_time; - bool echo_accessed; - - int tempo; - int skipped_kon; - int skipped_koff; - const char* cpu_error; - - int extra_clocks; - sample_t* buf_begin; - sample_t const* buf_end; - sample_t* extra_pos; - sample_t extra_buf [extra_size]; - - int rom_enabled; - uint8_t rom [rom_size]; - uint8_t hi_ram [rom_size]; - - unsigned char cycle_table [256]; - - struct - { - // padding to neutralize address overflow - union { - uint8_t padding1 [0x100]; - uint16_t align; // makes compiler align data for 16-bit access - } padding1 [1]; - uint8_t ram [0x10000]; - uint8_t padding2 [0x100]; - } ram; - }; - state_t m; - - enum { rom_addr = 0xFFC0 }; - - enum { skipping_time = 127 }; - - // Value that padding should be filled with - enum { cpu_pad_fill = 0xFF }; - - enum { - r_test = 0x0, r_control = 0x1, - r_dspaddr = 0x2, r_dspdata = 0x3, - r_cpuio0 = 0x4, r_cpuio1 = 0x5, - r_cpuio2 = 0x6, r_cpuio3 = 0x7, - r_f8 = 0x8, r_f9 = 0x9, - r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC, - r_t0out = 0xD, r_t1out = 0xE, r_t2out = 0xF - }; - - void timers_loaded(); - void enable_rom( int enable ); - void reset_buf(); - void save_extra(); - void load_regs( uint8_t const in [reg_count] ); - void ram_loaded(); - void regs_loaded(); - void reset_time_regs(); - void reset_common( int timer_counter_init ); - - Timer* run_timer_ ( Timer* t, rel_time_t ); - Timer* run_timer ( Timer* t, rel_time_t ); - int dsp_read ( rel_time_t ); - void dsp_write ( int data, rel_time_t ); - void cpu_write_smp_reg_( int data, rel_time_t, int addr ); - void cpu_write_smp_reg ( int data, rel_time_t, int addr ); - void cpu_write_high ( int data, int i, rel_time_t ); - void cpu_write ( int data, int addr, rel_time_t ); - int cpu_read_smp_reg ( int i, rel_time_t ); - int cpu_read ( int addr, rel_time_t ); - unsigned CPU_mem_bit ( uint8_t const* pc, rel_time_t ); - - bool check_echo_access ( int addr ); - uint8_t* run_until_( time_t end_time ); - - struct spc_file_t - { - char signature [signature_size]; - uint8_t has_id666; - uint8_t version; - uint8_t pcl, pch; - uint8_t a; - uint8_t x; - uint8_t y; - uint8_t psw; - uint8_t sp; - char text [212]; - uint8_t ram [0x10000]; - uint8_t dsp [128]; - uint8_t unused [0x40]; - uint8_t ipl_rom [0x40]; - }; - - static char const signature [signature_size + 1]; - - void save_regs( uint8_t out [reg_count] ); -}; - -#include - -inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; } - -inline int SNES_SPC::read_port( time_t t, int port ) -{ - assert( (unsigned) port < port_count ); - return run_until_( t ) [port]; -} - -inline void SNES_SPC::write_port( time_t t, int port, int data ) -{ - assert( (unsigned) port < port_count ); - run_until_( t ) [0x10 + port] = data; -} - -inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); } - -inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); } - -#if !SPC_NO_COPY_STATE_FUNCS -inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } -#endif - -#endif diff --git a/source/snes9x/apu/SNES_SPC_misc.cpp b/source/snes9x/apu/SNES_SPC_misc.cpp deleted file mode 100644 index 5a313a0..0000000 --- a/source/snes9x/apu/SNES_SPC_misc.cpp +++ /dev/null @@ -1,407 +0,0 @@ -// SPC emulation support: init, sample buffering, reset, SPC loading - -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SNES_SPC.h" - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -// (n ? n : 256) -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) - - -//// Init - -blargg_err_t SNES_SPC::init() -{ - memset( &m, 0, sizeof m ); - dsp.init( RAM ); - - m.tempo = tempo_unit; - - // Most SPC music doesn't need ROM, and almost all the rest only rely - // on these two bytes - m.rom [0x3E] = 0xFF; - m.rom [0x3F] = 0xC0; - - static unsigned char const cycle_table [128] = - {// 01 23 45 67 89 AB CD EF - 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0 - 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1 - 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2 - 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3 - 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4 - 0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5 - 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6 - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7 - 0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8 - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9 - 0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B - 0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C - 0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D - 0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E - 0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F - }; - - // unpack cycle table - for ( int i = 0; i < 128; i++ ) - { - int n = cycle_table [i]; - m.cycle_table [i * 2 + 0] = n >> 4; - m.cycle_table [i * 2 + 1] = n & 0x0F; - } - - #if SPC_LESS_ACCURATE - memcpy( reg_times, reg_times_, sizeof reg_times ); - #endif - - reset(); - return 0; -} - -void SNES_SPC::init_rom( uint8_t const in [rom_size] ) -{ - memcpy( m.rom, in, sizeof m.rom ); -} - -void SNES_SPC::set_tempo( int t ) -{ - m.tempo = t; - int const timer2_shift = 4; // 64 kHz - int const other_shift = 3; // 8 kHz - - #if SPC_DISABLE_TEMPO - m.timers [2].prescaler = timer2_shift; - m.timers [1].prescaler = timer2_shift + other_shift; - m.timers [0].prescaler = timer2_shift + other_shift; - #else - if ( !t ) - t = 1; - int const timer2_rate = 1 << timer2_shift; - int rate = (timer2_rate * tempo_unit + (t >> 1)) / t; - if ( rate < timer2_rate / 4 ) - rate = timer2_rate / 4; // max 4x tempo - m.timers [2].prescaler = rate; - m.timers [1].prescaler = rate << other_shift; - m.timers [0].prescaler = rate << other_shift; - #endif -} - -// Timer registers have been loaded. Applies these to the timers. Does not -// reset timer prescalers or dividers. -void SNES_SPC::timers_loaded() -{ - int i; - for ( i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->period = IF_0_THEN_256( REGS [r_t0target + i] ); - t->enabled = REGS [r_control] >> i & 1; - t->counter = REGS_IN [r_t0out + i] & 0x0F; - } - - set_tempo( m.tempo ); -} - -// Loads registers from unified 16-byte format -void SNES_SPC::load_regs( uint8_t const in [reg_count] ) -{ - memcpy( REGS, in, reg_count ); - //memcpy( REGS_IN, REGS, reg_count ); - - // These always read back as 0 - REGS_IN [r_test ] = 0; - REGS_IN [r_control ] = 0; - REGS_IN [r_t0target] = 0; - REGS_IN [r_t1target] = 0; - REGS_IN [r_t2target] = 0; -} - -// RAM was just loaded from SPC, with $F0-$FF containing SMP registers -// and timer counts. Copies these to proper registers. -void SNES_SPC::ram_loaded() -{ - m.rom_enabled = 0; - load_regs( &RAM [0xF0] ); - - // Put STOP instruction around memory to catch PC underflow/overflow - memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 ); - memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 ); -} - -// Registers were just loaded. Applies these new values. -void SNES_SPC::regs_loaded() -{ - enable_rom( REGS [r_control] & 0x80 ); - timers_loaded(); -} - -void SNES_SPC::reset_time_regs() -{ - m.cpu_error = 0; - m.echo_accessed = 0; - m.spc_time = 0; - m.dsp_time = 0; - #if SPC_LESS_ACCURATE - m.dsp_time = clocks_per_sample + 1; - #endif - - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->next_time = 1; - t->divider = 0; - } - - regs_loaded(); - - m.extra_clocks = 0; - reset_buf(); -} - -void SNES_SPC::reset_common( int timer_counter_init ) -{ - int i; - for ( i = 0; i < timer_count; i++ ) - REGS_IN [r_t0out + i] = timer_counter_init; - - // Run IPL ROM - memset( &m.cpu_regs, 0, sizeof m.cpu_regs ); - m.cpu_regs.pc = rom_addr; - - REGS [r_test ] = 0x0A; - REGS [r_control] = 0xB0; // ROM enabled, clear ports - for ( i = 0; i < port_count; i++ ) - REGS_IN [r_cpuio0 + i] = 0; - - reset_time_regs(); -} - -void SNES_SPC::soft_reset() -{ - reset_common( 0 ); - dsp.soft_reset(); -} - -void SNES_SPC::reset() -{ - memset( RAM, 0xFF, 0x10000 ); - ram_loaded(); - reset_common( 0x0F ); - dsp.reset(); -} - -char const SNES_SPC::signature [signature_size + 1] = - "SNES-SPC700 Sound File Data v0.30\x1A\x1A"; - -blargg_err_t SNES_SPC::load_spc( void const* data, long size ) -{ - spc_file_t const* const spc = (spc_file_t const*) data; - - // be sure compiler didn't insert any padding into fle_t - assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 ); - - // Check signature and file size - if ( size < signature_size || memcmp( spc, signature, 27 ) ) - return "Not an SPC file"; - - if ( size < spc_min_file_size ) - return "Corrupt SPC file"; - - // CPU registers - m.cpu_regs.pc = spc->pch * 0x100 + spc->pcl; - m.cpu_regs.a = spc->a; - m.cpu_regs.x = spc->x; - m.cpu_regs.y = spc->y; - m.cpu_regs.psw = spc->psw; - m.cpu_regs.sp = spc->sp; - - // RAM and registers - memcpy( RAM, spc->ram, 0x10000 ); - ram_loaded(); - - // DSP registers - dsp.load( spc->dsp ); - - reset_time_regs(); - - return 0; -} - -void SNES_SPC::clear_echo() -{ - if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) - { - int addr = 0x100 * dsp.read( SPC_DSP::r_esa ); - int end = addr + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); - if ( end > 0x10000 ) - end = 0x10000; - memset( &RAM [addr], 0xFF, end - addr ); - } -} - - -//// Sample output - -void SNES_SPC::reset_buf() -{ - // Start with half extra buffer of silence - sample_t* out = m.extra_buf; - while ( out < &m.extra_buf [extra_size / 2] ) - *out++ = 0; - - m.extra_pos = out; - m.buf_begin = 0; - - dsp.set_output( 0, 0 ); -} - -void SNES_SPC::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // size must be even - - m.extra_clocks &= clocks_per_sample - 1; - if ( out ) - { - sample_t const* out_end = out + size; - m.buf_begin = out; - m.buf_end = out_end; - - // Copy extra to output - sample_t const* in = m.extra_buf; - while ( in < m.extra_pos && out < out_end ) - *out++ = *in++; - - // Handle output being full already - if ( out >= out_end ) - { - // Have DSP write to remaining extra space - out = dsp.extra(); - out_end = &dsp.extra() [extra_size]; - - // Copy any remaining extra samples as if DSP wrote them - while ( in < m.extra_pos ) - *out++ = *in++; - assert( out <= out_end ); - } - - dsp.set_output( out, out_end - out ); - } - else - { - reset_buf(); - } -} - -void SNES_SPC::save_extra() -{ - // Get end pointers - sample_t const* main_end = m.buf_end; // end of data written to buf - sample_t const* dsp_end = dsp.out_pos(); // end of data written to dsp.extra() - if ( m.buf_begin <= dsp_end && dsp_end <= main_end ) - { - main_end = dsp_end; - dsp_end = dsp.extra(); // nothing in DSP's extra - } - - // Copy any extra samples at these ends into extra_buf - sample_t* out = m.extra_buf; - sample_t const* in; - for ( in = m.buf_begin + sample_count(); in < main_end; in++ ) - *out++ = *in; - for ( in = dsp.extra(); in < dsp_end ; in++ ) - *out++ = *in; - - m.extra_pos = out; - assert( out <= &m.extra_buf [extra_size] ); -} - -blargg_err_t SNES_SPC::play( int count, sample_t* out ) -{ - require( (count & 1) == 0 ); // must be even - if ( count ) - { - set_output( out, count ); - end_frame( count * (clocks_per_sample / 2) ); - } - - const char* err = m.cpu_error; - m.cpu_error = 0; - return err; -} - -blargg_err_t SNES_SPC::skip( int count ) -{ - #if SPC_LESS_ACCURATE - if ( count > 2 * sample_rate * 2 ) - { - set_output( 0, 0 ); - - // Skip a multiple of 4 samples - time_t end = count; - count = (count & 3) + 1 * sample_rate * 2; - end = (end - count) * (clocks_per_sample / 2); - - m.skipped_kon = 0; - m.skipped_koff = 0; - - // Preserve DSP and timer synchronization - // TODO: verify that this really preserves it - int old_dsp_time = m.dsp_time + m.spc_time; - m.dsp_time = end - m.spc_time + skipping_time; - end_frame( end ); - m.dsp_time = m.dsp_time - skipping_time + old_dsp_time; - - dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon ); - dsp.write( SPC_DSP::r_kon , m.skipped_kon ); - clear_echo(); - } - #endif - - return play( count, 0 ); -} - -//// Snes9x Accessor - -void SNES_SPC::dsp_set_spc_snapshot_callback( void (*callback) (void) ) -{ - dsp.set_spc_snapshot_callback( callback ); -} - -void SNES_SPC::dsp_dump_spc_snapshot( void ) -{ - dsp.dump_spc_snapshot(); -} - -void SNES_SPC::dsp_set_stereo_switch( int value ) -{ - dsp.set_stereo_switch( value ); -} - -uint8_t SNES_SPC::dsp_reg_value( int ch, int addr ) -{ - return dsp.reg_value( ch, addr ); -} - -int SNES_SPC::dsp_envx_value( int ch ) -{ - return dsp.envx_value( ch ); -} diff --git a/source/snes9x/apu/SNES_SPC_state.cpp b/source/snes9x/apu/SNES_SPC_state.cpp deleted file mode 100644 index 3d9d3f3..0000000 --- a/source/snes9x/apu/SNES_SPC_state.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// SPC emulation state save/load: copy_state(), save_spc() -// Separate file to avoid linking in unless needed - -// snes_spc 0.9.0. http://www.slack.net/‾ant/ - -#include "SNES_SPC.h" - -#if !SPC_NO_COPY_STATE_FUNCS - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -void SNES_SPC::save_regs( uint8_t out [reg_count] ) -{ - // Use current timer counter values - for ( int i = 0; i < timer_count; i++ ) - out [r_t0out + i] = m.timers [i].counter; - - // Last written values - memcpy( out, REGS, r_t0out ); -} - -void SNES_SPC::init_header( void* spc_out ) -{ - spc_file_t* const spc = (spc_file_t*) spc_out; - - spc->has_id666 = 26; // has none - spc->version = 30; - memcpy( spc, signature, sizeof spc->signature ); - memset( spc->text, 0, sizeof spc->text ); -} - -void SNES_SPC::save_spc( void* spc_out ) -{ - spc_file_t* const spc = (spc_file_t*) spc_out; - - // CPU - spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0); - spc->pch = (uint8_t) (m.cpu_regs.pc >> 8); - spc->a = m.cpu_regs.a; - spc->x = m.cpu_regs.x; - spc->y = m.cpu_regs.y; - spc->psw = m.cpu_regs.psw; - spc->sp = m.cpu_regs.sp; - - // RAM, ROM - memcpy( spc->ram, RAM, sizeof spc->ram ); - if ( m.rom_enabled ) - memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram ); - memset( spc->unused, 0, sizeof spc->unused ); - memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom ); - - // SMP registers - save_regs( &spc->ram [0xF0] ); - int i; - for ( i = 0; i < port_count; i++ ) - spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i]; - - // DSP registers - for ( i = 0; i < SPC_DSP::register_count; i++ ) - spc->dsp [i] = dsp.read( i ); -} - -#undef IF_0_THEN_256 -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) -void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // Make state data more readable by putting 64K RAM, 16 SMP registers, - // then DSP (with its 128 registers) first - - // RAM - enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below - copier.copy( RAM, 0x10000 ); - - { - // SMP registers - uint8_t regs [reg_count]; - uint8_t regs_in [reg_count]; - - memcpy( regs, REGS, reg_count ); - memcpy( regs_in, REGS_IN, reg_count ); - - copier.copy( regs, sizeof regs ); - copier.copy( regs_in, sizeof regs_in ); - - memcpy( REGS, regs, reg_count); - memcpy( REGS_IN, regs_in, reg_count ); - - enable_rom( REGS [r_control] & 0x80 ); - } - - // CPU registers - SPC_COPY( uint16_t, m.cpu_regs.pc ); - SPC_COPY( uint8_t, m.cpu_regs.a ); - SPC_COPY( uint8_t, m.cpu_regs.x ); - SPC_COPY( uint8_t, m.cpu_regs.y ); - SPC_COPY( uint8_t, m.cpu_regs.psw ); - SPC_COPY( uint8_t, m.cpu_regs.sp ); - copier.extra(); - - SPC_COPY( int16_t, m.spc_time ); - SPC_COPY( int16_t, m.dsp_time ); - - // DSP - dsp.copy_state( io, copy ); - - // Timers - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->period = IF_0_THEN_256( REGS [r_t0target + i] ); - t->enabled = REGS [r_control] >> i & 1; - SPC_COPY( int16_t, t->next_time ); - SPC_COPY( uint8_t, t->divider ); - SPC_COPY( uint8_t, t->counter ); - copier.extra(); - } - - set_tempo( m.tempo ); - - copier.extra(); -} -#endif diff --git a/source/snes9x/apu/SPC_CPU.h b/source/snes9x/apu/SPC_CPU.h deleted file mode 100644 index 664fc48..0000000 --- a/source/snes9x/apu/SPC_CPU.h +++ /dev/null @@ -1,1220 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -//// Memory access - -#if SPC_MORE_ACCURACY - #define SUSPICIOUS_OPCODE( name ) ((void) 0) -#else - #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) -#endif - -#define CPU_READ( time, offset, addr )\ - cpu_read( addr, time + offset ) - -#define CPU_WRITE( time, offset, addr, data )\ - cpu_write( data, addr, time + offset ) - -#if SPC_MORE_ACCURACY - #define CPU_READ_TIMER( time, offset, addr, out )\ - { out = CPU_READ( time, offset, addr ); } - -#else - // timers are by far the most common thing read from dp - #define CPU_READ_TIMER( time, offset, addr_, out )\ - {\ - rel_time_t adj_time = time + offset;\ - int dp_addr = addr_;\ - int ti = dp_addr - (r_t0out + 0xF0);\ - if ( (unsigned) ti < timer_count )\ - {\ - Timer* t = &m.timers [ti];\ - if ( adj_time >= t->next_time )\ - t = run_timer_( t, adj_time );\ - out = t->counter;\ - t->counter = 0;\ - }\ - else\ - {\ - out = ram [dp_addr];\ - int i = dp_addr - 0xF0;\ - if ( (unsigned) i < 0x10 )\ - out = cpu_read_smp_reg( i, adj_time );\ - }\ - } -#endif - -#define TIME_ADJ( n ) (n) - -#define READ_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out ) -#define READ( time, addr ) CPU_READ ( rel_time, TIME_ADJ(time), (addr) ) -#define WRITE( time, addr, data ) CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) ) - -#define DP_ADDR( addr ) (dp + (addr)) - -#define READ_DP_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out ) -#define READ_DP( time, addr ) READ ( time, DP_ADDR( addr ) ) -#define WRITE_DP( time, addr, data ) WRITE( time, DP_ADDR( addr ), data ) - -#define READ_PROG16( addr ) GET_LE16( ram + (addr) ) - -#define SET_PC( n ) (pc = ram + (n)) -#define GET_PC() (pc - ram) -#define READ_PC( pc ) (*(pc)) -#define READ_PC16( pc ) GET_LE16( pc ) - -// TODO: remove non-wrapping versions? -#define SPC_NO_SP_WRAPAROUND 0 - -#define SET_SP( v ) (sp = ram + 0x101 + (v)) -#define GET_SP() (sp - 0x101 - ram) - -#if SPC_NO_SP_WRAPAROUND -#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) -#define PUSH( v ) (void) (*--sp = (uint8_t) (v)) -#define POP( out ) (void) ((out) = *sp++) - -#else -#define PUSH16( data )\ -{\ - int addr = (sp -= 2) - ram;\ - if ( addr > 0x100 )\ - {\ - SET_LE16( sp, data );\ - }\ - else\ - {\ - ram [(uint8_t) addr + 0x100] = (uint8_t) data;\ - sp [1] = (uint8_t) (data >> 8);\ - sp += 0x100;\ - }\ -} - -#define PUSH( data )\ -{\ - *--sp = (uint8_t) (data);\ - if ( sp - ram == 0x100 )\ - sp += 0x100;\ -} - -#define POP( out )\ -{\ - out = *sp++;\ - if ( sp - ram == 0x201 )\ - {\ - out = sp [-0x101];\ - sp -= 0x100;\ - }\ -} - -#endif - -#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel ) - -unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time ) -{ - unsigned addr = READ_PC16( pc ); - unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13); - return t << 8 & 0x100; -} - -//// Status flag handling - -// Hex value in name to clarify code and bit shifting. -// Flag stored in indicated variable during emulation -int const n80 = 0x80; // nz -int const v40 = 0x40; // psw -int const p20 = 0x20; // dp -int const b10 = 0x10; // psw -int const h08 = 0x08; // psw -int const i04 = 0x04; // psw -int const z02 = 0x02; // nz -int const c01 = 0x01; // c - -int const nz_neg_mask = 0x880; // either bit set indicates N flag set - -#define GET_PSW( out )\ -{\ - out = psw & ~(n80 | p20 | z02 | c01);\ - out |= c >> 8 & c01;\ - out |= dp >> 3 & p20;\ - out |= ((nz >> 4) | nz) & n80;\ - if ( !(uint8_t) nz ) out |= z02;\ -} - -#define SET_PSW( in )\ -{\ - psw = in;\ - c = in << 8;\ - dp = in << 3 & 0x100;\ - nz = (in << 4 & 0x800) | (~in & z02);\ -} - -SPC_CPU_RUN_FUNC -{ - uint8_t* const ram = RAM; - int a = m.cpu_regs.a; - int x = m.cpu_regs.x; - int y = m.cpu_regs.y; - uint8_t const* pc; - uint8_t* sp; - int psw; - int c; - int nz; - int dp; - - SET_PC( m.cpu_regs.pc ); - SET_SP( m.cpu_regs.sp ); - SET_PSW( m.cpu_regs.psw ); - - goto loop; - - - // Main loop - -cbranch_taken_loop: - pc += *(BOOST::int8_t const*) pc; -inc_pc_loop: - pc++; -loop: -{ - unsigned opcode; - unsigned data; - - check( (unsigned) a < 0x100 ); - check( (unsigned) x < 0x100 ); - check( (unsigned) y < 0x100 ); - - opcode = *pc; - if ( (rel_time += m.cycle_table [opcode]) > 0 ) - goto out_of_time; - - #ifdef SPC_CPU_OPCODE_HOOK - SPC_CPU_OPCODE_HOOK( GET_PC(), opcode ); - #endif - /* - //SUB_CASE_COUNTER( 1 ); - #define PROFILE_TIMER_LOOP( op, addr, len )\ - if ( opcode == op )\ - {\ - int cond = (unsigned) ((addr) - 0xFD) < 3 &&\ - pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\ - SUB_CASE_COUNTER( op && cond );\ - } - - PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 ); - PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 ); - PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 ); - */ - - // TODO: if PC is at end of memory, this will get wrong operand (very obscure) - data = *++pc; - switch ( opcode ) - { - -// Common instructions - -#define BRANCH( cond )\ -{\ - pc++;\ - pc += (BOOST::int8_t) data;\ - if ( cond )\ - goto loop;\ - pc -= (BOOST::int8_t) data;\ - rel_time -= 2;\ - goto loop;\ -} - - case 0xF0: // BEQ - BRANCH( !(uint8_t) nz ) // 89% taken - - case 0xD0: // BNE - BRANCH( (uint8_t) nz ) - - case 0x3F:{// CALL - int old_addr = GET_PC() + 2; - SET_PC( READ_PC16( pc ) ); - PUSH16( old_addr ); - goto loop; - } - - case 0x6F:// RET - #if SPC_NO_SP_WRAPAROUND - { - SET_PC( GET_LE16( sp ) ); - sp += 2; - } - #else - { - int addr = sp - ram; - SET_PC( GET_LE16( sp ) ); - sp += 2; - if ( addr < 0x1FF ) - goto loop; - - SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] ); - sp -= 0x100; - } - #endif - goto loop; - - case 0xE4: // MOV a,dp - ++pc; - // 80% from timer - READ_DP_TIMER( 0, data, a = nz ); - goto loop; - - case 0xFA:{// MOV dp,dp - int temp; - READ_DP_TIMER( -2, data, temp ); - data = temp + no_read_before_write ; - } - // fall through - case 0x8F:{// MOV dp,#imm - int temp = READ_PC( pc + 1 ); - pc += 2; - - #if !SPC_MORE_ACCURACY - { - int i = dp + temp; - ram [i] = (uint8_t) data; - i -= 0xF0; - if ( (unsigned) i < 0x10 ) // 76% - { - REGS [i] = (uint8_t) data; - - // Registers other than $F2 and $F4-$F7 - //if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 ) - if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12% - cpu_write_smp_reg( data, rel_time, i ); - } - } - #else - WRITE_DP( 0, temp, data ); - #endif - goto loop; - } - - case 0xC4: // MOV dp,a - ++pc; - #if !SPC_MORE_ACCURACY - { - int i = dp + data; - ram [i] = (uint8_t) a; - i -= 0xF0; - if ( (unsigned) i < 0x10 ) // 39% - { - unsigned sel = i - 2; - REGS [i] = (uint8_t) a; - - if ( sel == 1 ) // 51% $F3 - dsp_write( a, rel_time ); - else if ( sel > 1 ) // 1% not $F2 or $F3 - cpu_write_smp_reg_( a, rel_time, i ); - } - } - #else - WRITE_DP( 0, data, a ); - #endif - goto loop; - -#define CASE( n ) case n: - -// Define common address modes based on opcode for immediate mode. Execution -// ends with data set to the address of the operand. -#define ADDR_MODES_( op )\ - CASE( op - 0x02 ) /* (X) */\ - data = x + dp;\ - pc--;\ - goto end_##op;\ - CASE( op + 0x0F ) /* (dp)+Y */\ - data = READ_PROG16( data + dp ) + y;\ - goto end_##op;\ - CASE( op - 0x01 ) /* (dp+X) */\ - data = READ_PROG16( ((uint8_t) (data + x)) + dp );\ - goto end_##op;\ - CASE( op + 0x0E ) /* abs+Y */\ - data += y;\ - goto abs_##op;\ - CASE( op + 0x0D ) /* abs+X */\ - data += x;\ - CASE( op - 0x03 ) /* abs */\ - abs_##op:\ - data += 0x100 * READ_PC( ++pc );\ - goto end_##op;\ - CASE( op + 0x0C ) /* dp+X */\ - data = (uint8_t) (data + x); - -#define ADDR_MODES_NO_DP( op )\ - ADDR_MODES_( op )\ - data += dp;\ - end_##op: - -#define ADDR_MODES( op )\ - ADDR_MODES_( op )\ - CASE( op - 0x04 ) /* dp */\ - data += dp;\ - end_##op: - -// 1. 8-bit Data Transmission Commands. Group I - - ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr - a = nz = READ( 0, data ); - goto inc_pc_loop; - - case 0xBF:{// MOV A,(X)+ - int temp = x + dp; - x = (uint8_t) (x + 1); - a = nz = READ( -1, temp ); - goto loop; - } - - case 0xE8: // MOV A,imm - a = data; - nz = data; - goto inc_pc_loop; - - case 0xF9: // MOV X,dp+Y - data = (uint8_t) (data + y); - case 0xF8: // MOV X,dp - READ_DP_TIMER( 0, data, x = nz ); - goto inc_pc_loop; - - case 0xE9: // MOV X,abs - data = READ_PC16( pc ); - ++pc; - data = READ( 0, data ); - case 0xCD: // MOV X,imm - x = data; - nz = data; - goto inc_pc_loop; - - case 0xFB: // MOV Y,dp+X - data = (uint8_t) (data + x); - case 0xEB: // MOV Y,dp - // 70% from timer - pc++; - READ_DP_TIMER( 0, data, y = nz ); - goto loop; - - case 0xEC:{// MOV Y,abs - int temp = READ_PC16( pc ); - pc += 2; - READ_TIMER( 0, temp, y = nz ); - //y = nz = READ( 0, temp ); - goto loop; - } - - case 0x8D: // MOV Y,imm - y = data; - nz = data; - goto inc_pc_loop; - -// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 - - ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A - WRITE( 0, data, a ); - goto inc_pc_loop; - - { - int temp; - case 0xCC: // MOV abs,Y - temp = y; - goto mov_abs_temp; - case 0xC9: // MOV abs,X - temp = x; - mov_abs_temp: - WRITE( 0, READ_PC16( pc ), temp ); - pc += 2; - goto loop; - } - - case 0xD9: // MOV dp+Y,X - data = (uint8_t) (data + y); - case 0xD8: // MOV dp,X - WRITE( 0, data + dp, x ); - goto inc_pc_loop; - - case 0xDB: // MOV dp+X,Y - data = (uint8_t) (data + x); - case 0xCB: // MOV dp,Y - WRITE( 0, data + dp, y ); - goto inc_pc_loop; - -// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. - - case 0x7D: // MOV A,X - a = x; - nz = x; - goto loop; - - case 0xDD: // MOV A,Y - a = y; - nz = y; - goto loop; - - case 0x5D: // MOV X,A - x = a; - nz = a; - goto loop; - - case 0xFD: // MOV Y,A - y = a; - nz = a; - goto loop; - - case 0x9D: // MOV X,SP - x = nz = GET_SP(); - goto loop; - - case 0xBD: // MOV SP,X - SET_SP( x ); - goto loop; - - //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2) - - case 0xAF: // MOV (X)+,A - WRITE_DP( 0, x, a + no_read_before_write ); - x++; - goto loop; - -// 5. 8-BIT LOGIC OPERATION COMMANDS - -#define LOGICAL_OP( op, func )\ - ADDR_MODES( op ) /* addr */\ - data = READ( 0, data );\ - case op: /* imm */\ - nz = a func##= data;\ - goto inc_pc_loop;\ - { unsigned addr;\ - case op + 0x11: /* X,Y */\ - data = READ_DP( -2, y );\ - addr = x + dp;\ - goto addr_##op;\ - case op + 0x01: /* dp,dp */\ - data = READ_DP( -3, data );\ - case op + 0x10:{/*dp,imm*/\ - uint8_t const* addr2 = pc + 1;\ - pc += 2;\ - addr = READ_PC( addr2 ) + dp;\ - }\ - addr_##op:\ - nz = data func READ( -1, addr );\ - WRITE( 0, addr, nz );\ - goto loop;\ - } - - LOGICAL_OP( 0x28, & ); // AND - - LOGICAL_OP( 0x08, | ); // OR - - LOGICAL_OP( 0x48, ^ ); // EOR - -// 4. 8-BIT ARITHMETIC OPERATION COMMANDS - - ADDR_MODES( 0x68 ) // CMP addr - data = READ( 0, data ); - case 0x68: // CMP imm - nz = a - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x79: // CMP (X),(Y) - data = READ_DP( -2, y ); - nz = READ_DP( -1, x ) - data; - c = ~nz; - nz &= 0xFF; - goto loop; - - case 0x69: // CMP dp,dp - data = READ_DP( -3, data ); - case 0x78: // CMP dp,imm - nz = READ_DP( -1, READ_PC( ++pc ) ) - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x3E: // CMP X,dp - data += dp; - goto cmp_x_addr; - case 0x1E: // CMP X,abs - data = READ_PC16( pc ); - pc++; - cmp_x_addr: - data = READ( 0, data ); - case 0xC8: // CMP X,imm - nz = x - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x7E: // CMP Y,dp - data += dp; - goto cmp_y_addr; - case 0x5E: // CMP Y,abs - data = READ_PC16( pc ); - pc++; - cmp_y_addr: - data = READ( 0, data ); - case 0xAD: // CMP Y,imm - nz = y - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - { - int addr; - case 0xB9: // SBC (x),(y) - case 0x99: // ADC (x),(y) - pc--; // compensate for inc later - data = READ_DP( -2, y ); - addr = x + dp; - goto adc_addr; - case 0xA9: // SBC dp,dp - case 0x89: // ADC dp,dp - data = READ_DP( -3, data ); - case 0xB8: // SBC dp,imm - case 0x98: // ADC dp,imm - addr = READ_PC( ++pc ) + dp; - adc_addr: - nz = READ( -1, addr ); - goto adc_data; - -// catch ADC and SBC together, then decode later based on operand -#undef CASE -#define CASE( n ) case n: case (n) + 0x20: - ADDR_MODES( 0x88 ) // ADC/SBC addr - data = READ( 0, data ); - case 0xA8: // SBC imm - case 0x88: // ADC imm - addr = -1; // A - nz = a; - adc_data: { - int flags; - if ( opcode >= 0xA0 ) // SBC - data ^= 0xFF; - - flags = data ^ nz; - nz += data + (c >> 8 & 1); - flags ^= nz; - - psw = (psw & ~(v40 | h08)) | - (flags >> 1 & h08) | - ((flags + 0x80) >> 2 & v40); - c = nz; - if ( addr < 0 ) - { - a = (uint8_t) nz; - goto inc_pc_loop; - } - WRITE( 0, addr, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - } - - } - -// 6. ADDITION & SUBTRACTION COMMANDS - -#define INC_DEC_REG( reg, op )\ - nz = reg op;\ - reg = (uint8_t) nz;\ - goto loop; - - case 0xBC: INC_DEC_REG( a, + 1 ) // INC A - case 0x3D: INC_DEC_REG( x, + 1 ) // INC X - case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y - - case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A - case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X - case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y - - case 0x9B: // DEC dp+X - case 0xBB: // INC dp+X - data = (uint8_t) (data + x); - case 0x8B: // DEC dp - case 0xAB: // INC dp - data += dp; - goto inc_abs; - case 0x8C: // DEC abs - case 0xAC: // INC abs - data = READ_PC16( pc ); - pc++; - inc_abs: - nz = (opcode >> 4 & 2) - 1; - nz += READ( -1, data ); - WRITE( 0, data, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - -// 7. SHIFT, ROTATION COMMANDS - - case 0x5C: // LSR A - c = 0; - case 0x7C:{// ROR A - nz = (c >> 1 & 0x80) | (a >> 1); - c = a << 8; - a = nz; - goto loop; - } - - case 0x1C: // ASL A - c = 0; - case 0x3C:{// ROL A - int temp = c >> 8 & 1; - c = a << 1; - nz = c | temp; - a = (uint8_t) nz; - goto loop; - } - - case 0x0B: // ASL dp - c = 0; - data += dp; - goto rol_mem; - case 0x1B: // ASL dp+X - c = 0; - case 0x3B: // ROL dp+X - data = (uint8_t) (data + x); - case 0x2B: // ROL dp - data += dp; - goto rol_mem; - case 0x0C: // ASL abs - c = 0; - case 0x2C: // ROL abs - data = READ_PC16( pc ); - pc++; - rol_mem: - nz = c >> 8 & 1; - nz |= (c = READ( -1, data ) << 1); - WRITE( 0, data, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - - case 0x4B: // LSR dp - c = 0; - data += dp; - goto ror_mem; - case 0x5B: // LSR dp+X - c = 0; - case 0x7B: // ROR dp+X - data = (uint8_t) (data + x); - case 0x6B: // ROR dp - data += dp; - goto ror_mem; - case 0x4C: // LSR abs - c = 0; - case 0x6C: // ROR abs - data = READ_PC16( pc ); - pc++; - ror_mem: { - int temp = READ( -1, data ); - nz = (c >> 1 & 0x80) | (temp >> 1); - c = temp << 8; - WRITE( 0, data, nz ); - goto inc_pc_loop; - } - - case 0x9F: // XCN - nz = a = (a >> 4) | (uint8_t) (a << 4); - goto loop; - -// 8. 16-BIT TRANSMISION COMMANDS - - case 0xBA: // MOVW YA,dp - a = READ_DP( -2, data ); - nz = (a & 0x7F) | (a >> 1); - y = READ_DP( 0, (uint8_t) (data + 1) ); - nz |= y; - goto inc_pc_loop; - - case 0xDA: // MOVW dp,YA - WRITE_DP( -1, data, a ); - WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write ); - goto inc_pc_loop; - -// 9. 16-BIT OPERATION COMMANDS - - case 0x3A: // INCW dp - case 0x1A:{// DECW dp - int temp; - // low byte - data += dp; - temp = READ( -3, data ); - temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW - nz = ((temp >> 1) | temp) & 0x7F; - WRITE( -2, data, /*(uint8_t)*/ temp ); - - // high byte - data = (uint8_t) (data + 1) + dp; - temp = (uint8_t) ((temp >> 8) + READ( -1, data )); - nz |= temp; - WRITE( 0, data, temp ); - - goto inc_pc_loop; - } - - case 0x7A: // ADDW YA,dp - case 0x9A:{// SUBW YA,dp - int lo = READ_DP( -2, data ); - int hi = READ_DP( 0, (uint8_t) (data + 1) ); - int result; - int flags; - - if ( opcode == 0x9A ) // SUBW - { - lo = (lo ^ 0xFF) + 1; - hi ^= 0xFF; - } - - lo += a; - result = y + hi + (lo >> 8); - flags = hi ^ y ^ result; - - psw = (psw & ~(v40 | h08)) | - (flags >> 1 & h08) | - ((flags + 0x80) >> 2 & v40); - c = result; - a = (uint8_t) lo; - result = (uint8_t) result; - y = result; - nz = (((lo >> 1) | lo) & 0x7F) | result; - - goto inc_pc_loop; - } - - case 0x5A: { // CMPW YA,dp - int temp = a - READ_DP( -1, data ); - nz = ((temp >> 1) | temp) & 0x7F; - temp = y + (temp >> 8); - temp -= READ_DP( 0, (uint8_t) (data + 1) ); - nz |= temp; - c = ~temp; - nz &= 0xFF; - goto inc_pc_loop; - } - -// 10. MULTIPLICATION & DIVISON COMMANDS - - case 0xCF: { // MUL YA - unsigned temp = y * a; - a = (uint8_t) temp; - nz = ((temp >> 1) | temp) & 0x7F; - y = temp >> 8; - nz |= y; - goto loop; - } - - case 0x9E: // DIV YA,X - { - unsigned ya = y * 0x100 + a; - - psw &= ~(h08 | v40); - - if ( y >= x ) - psw |= v40; - - if ( (y & 15) >= (x & 15) ) - psw |= h08; - - if ( y < x * 2 ) - { - a = ya / x; - y = ya - a * x; - } - else - { - a = 255 - (ya - x * 0x200) / (256 - x); - y = x + (ya - x * 0x200) % (256 - x); - } - - nz = (uint8_t) a; - a = (uint8_t) a; - - goto loop; - } - -// 11. DECIMAL COMPENSATION COMMANDS - - case 0xDF: // DAA - SUSPICIOUS_OPCODE( "DAA" ); - if ( a > 0x99 || c & 0x100 ) - { - a += 0x60; - c = 0x100; - } - - if ( (a & 0x0F) > 9 || psw & h08 ) - a += 0x06; - - nz = a; - a = (uint8_t) a; - goto loop; - - case 0xBE: // DAS - SUSPICIOUS_OPCODE( "DAS" ); - if ( a > 0x99 || !(c & 0x100) ) - { - a -= 0x60; - c = 0; - } - - if ( (a & 0x0F) > 9 || !(psw & h08) ) - a -= 0x06; - - nz = a; - a = (uint8_t) a; - goto loop; - -// 12. BRANCHING COMMANDS - - case 0x2F: // BRA rel - pc += (BOOST::int8_t) data; - goto inc_pc_loop; - - case 0x30: // BMI - BRANCH( (nz & nz_neg_mask) ) - - case 0x10: // BPL - BRANCH( !(nz & nz_neg_mask) ) - - case 0xB0: // BCS - BRANCH( c & 0x100 ) - - case 0x90: // BCC - BRANCH( !(c & 0x100) ) - - case 0x70: // BVS - BRANCH( psw & v40 ) - - case 0x50: // BVC - BRANCH( !(psw & v40) ) - - #define CBRANCH( cond )\ - {\ - pc++;\ - if ( cond )\ - goto cbranch_taken_loop;\ - rel_time -= 2;\ - goto inc_pc_loop;\ - } - - case 0x03: // BBS dp.bit,rel - case 0x23: - case 0x43: - case 0x63: - case 0x83: - case 0xA3: - case 0xC3: - case 0xE3: - CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 ) - - case 0x13: // BBC dp.bit,rel - case 0x33: - case 0x53: - case 0x73: - case 0x93: - case 0xB3: - case 0xD3: - case 0xF3: - CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) ) - - case 0xDE: // CBNE dp+X,rel - data = (uint8_t) (data + x); - // fall through - case 0x2E:{// CBNE dp,rel - int temp; - // 61% from timer - READ_DP_TIMER( -4, data, temp ); - CBRANCH( temp != a ) - } - - case 0x6E: { // DBNZ dp,rel - unsigned temp = READ_DP( -4, data ) - 1; - WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write ); - CBRANCH( temp ) - } - - case 0xFE: // DBNZ Y,rel - y = (uint8_t) (y - 1); - BRANCH( y ) - - case 0x1F: // JMP [abs+X] - SET_PC( READ_PC16( pc ) + x ); - // fall through - case 0x5F: // JMP abs - SET_PC( READ_PC16( pc ) ); - goto loop; - -// 13. SUB-ROUTINE CALL RETURN COMMANDS - - case 0x0F:{// BRK - int temp; - int ret_addr = GET_PC(); - SUSPICIOUS_OPCODE( "BRK" ); - SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified - PUSH16( ret_addr ); - GET_PSW( temp ); - psw = (psw | b10) & ~i04; - PUSH( temp ); - goto loop; - } - - case 0x4F:{// PCALL offset - int ret_addr = GET_PC() + 1; - SET_PC( 0xFF00 | data ); - PUSH16( ret_addr ); - goto loop; - } - - case 0x01: // TCALL n - case 0x11: - case 0x21: - case 0x31: - case 0x41: - case 0x51: - case 0x61: - case 0x71: - case 0x81: - case 0x91: - case 0xA1: - case 0xB1: - case 0xC1: - case 0xD1: - case 0xE1: - case 0xF1: { - int ret_addr = GET_PC(); - SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) ); - PUSH16( ret_addr ); - goto loop; - } - -// 14. STACK OPERATION COMMANDS - - { - int temp; - case 0x7F: // RET1 - temp = *sp; - SET_PC( GET_LE16( sp + 1 ) ); - sp += 3; - goto set_psw; - case 0x8E: // POP PSW - POP( temp ); - set_psw: - SET_PSW( temp ); - goto loop; - } - - case 0x0D: { // PUSH PSW - int temp; - GET_PSW( temp ); - PUSH( temp ); - goto loop; - } - - case 0x2D: // PUSH A - PUSH( a ); - goto loop; - - case 0x4D: // PUSH X - PUSH( x ); - goto loop; - - case 0x6D: // PUSH Y - PUSH( y ); - goto loop; - - case 0xAE: // POP A - POP( a ); - goto loop; - - case 0xCE: // POP X - POP( x ); - goto loop; - - case 0xEE: // POP Y - POP( y ); - goto loop; - -// 15. BIT OPERATION COMMANDS - - case 0x02: // SET1 - case 0x22: - case 0x42: - case 0x62: - case 0x82: - case 0xA2: - case 0xC2: - case 0xE2: - case 0x12: // CLR1 - case 0x32: - case 0x52: - case 0x72: - case 0x92: - case 0xB2: - case 0xD2: - case 0xF2: { - int bit = 1 << (opcode >> 5); - int mask = ~bit; - if ( opcode & 0x10 ) - bit = 0; - data += dp; - WRITE( 0, data, (READ( -1, data ) & mask) | bit ); - goto inc_pc_loop; - } - - case 0x0E: // TSET1 abs - case 0x4E: // TCLR1 abs - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -2, data ); - nz = (uint8_t) (a - temp); - temp &= ~a; - if ( opcode == 0x0E ) - temp |= a; - WRITE( 0, data, temp ); - } - goto loop; - - case 0x4A: // AND1 C,mem.bit - c &= MEM_BIT( 0 ); - pc += 2; - goto loop; - - case 0x6A: // AND1 C,/mem.bit - c &= ~MEM_BIT( 0 ); - pc += 2; - goto loop; - - case 0x0A: // OR1 C,mem.bit - c |= MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0x2A: // OR1 C,/mem.bit - c |= ~MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0x8A: // EOR1 C,mem.bit - c ^= MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0xEA: // NOT1 mem.bit - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -1, data & 0x1FFF ); - temp ^= 1 << (data >> 13); - WRITE( 0, data & 0x1FFF, temp ); - } - goto loop; - - case 0xCA: // MOV1 mem.bit,C - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -2, data & 0x1FFF ); - unsigned bit = data >> 13; - temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit); - WRITE( 0, data & 0x1FFF, temp + no_read_before_write ); - } - goto loop; - - case 0xAA: // MOV1 C,mem.bit - c = MEM_BIT( 0 ); - pc += 2; - goto loop; - -// 16. PROGRAM PSW FLAG OPERATION COMMANDS - - case 0x60: // CLRC - c = 0; - goto loop; - - case 0x80: // SETC - c = ~0; - goto loop; - - case 0xED: // NOTC - c ^= 0x100; - goto loop; - - case 0xE0: // CLRV - psw &= ~(v40 | h08); - goto loop; - - case 0x20: // CLRP - dp = 0; - goto loop; - - case 0x40: // SETP - dp = 0x100; - goto loop; - - case 0xA0: // EI - SUSPICIOUS_OPCODE( "EI" ); - psw |= i04; - goto loop; - - case 0xC0: // DI - SUSPICIOUS_OPCODE( "DI" ); - psw &= ~i04; - goto loop; - -// 17. OTHER COMMANDS - - case 0x00: // NOP - goto loop; - - case 0xFF:{// STOP - // handle PC wrap-around - unsigned addr = GET_PC() - 1; - if ( addr >= 0x10000 ) - { - addr &= 0xFFFF; - SET_PC( addr ); - dprintf( "SPC: PC wrapped around\n" ); - goto loop; - } - } - // fall through - case 0xEF: // SLEEP - SUSPICIOUS_OPCODE( "STOP/SLEEP" ); - --pc; - rel_time = 0; - m.cpu_error = "SPC emulation error"; - goto stop; - } // switch - - assert( 0 ); // catch any unhandled instructions -} -out_of_time: - rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode -stop: - - // Uncache registers - if ( GET_PC() >= 0x10000 ) - dprintf( "SPC: PC wrapped around\n" ); - m.cpu_regs.pc = (uint16_t) GET_PC(); - m.cpu_regs.sp = ( uint8_t) GET_SP(); - m.cpu_regs.a = ( uint8_t) a; - m.cpu_regs.x = ( uint8_t) x; - m.cpu_regs.y = ( uint8_t) y; - { - int temp; - GET_PSW( temp ); - m.cpu_regs.psw = (uint8_t) temp; - } -} -SPC_CPU_RUN_FUNC_END diff --git a/source/snes9x/apu/SPC_DSP.cpp b/source/snes9x/apu/SPC_DSP.cpp deleted file mode 100644 index 05eca32..0000000 --- a/source/snes9x/apu/SPC_DSP.cpp +++ /dev/null @@ -1,1062 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_DSP.h" - -#include "blargg_endian.h" -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -#if INT_MAX < 0x7FFFFFFF - #error "Requires that int type have at least 32 bits" -#endif - -// TODO: add to blargg_endian.h -#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) -#define GET_LE16A( addr ) GET_LE16( addr ) -#define SET_LE16A( addr, data ) SET_LE16( addr, data ) - -static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = -{ - 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, - 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, - 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, - 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, - 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, - 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF, - 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, - 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF -}; - -// if ( io < -32768 ) io = -32768; -// if ( io > 32767 ) io = 32767; -#define CLAMP16( io )\ -{\ - if ( (int16_t) io != io )\ - io = (io >> 31) ^ 0x7FFF;\ -} - -// Access global DSP register -#define REG(n) m.regs [r_##n] - -// Access voice DSP register -#define VREG(r,n) r [v_##n] - -#define WRITE_SAMPLES( l, r, out ) \ -{\ - out [0] = l;\ - out [1] = r;\ - out += 2;\ - if ( out >= m.out_end )\ - {\ - check( out == m.out_end );\ - check( m.out_end != &m.extra [extra_size] || \ - (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ - out = m.extra;\ - m.out_end = &m.extra [extra_size];\ - }\ -}\ - -void SPC_DSP::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // must be even - if ( !out ) - { - out = m.extra; - size = extra_size; - } - m.out_begin = out; - m.out = out; - m.out_end = out + size; -} - -// Volume registers and efb are signed! Easy to forget int8_t cast. -// Prefixes are to avoid accidental use of locals with same names. - -// Gaussian interpolation - -static short const gauss [512] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, - 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, - 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, - 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, - 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, - 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, - 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, - 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, - 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, - 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, - 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, - 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, - 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, - 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, - 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, - 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, - 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, - 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, - 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, - 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, -1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, -1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, -1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, -1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, -1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, -1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, -1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, -}; - -inline int SPC_DSP::interpolate( voice_t const* v ) -{ - // Make pointers into gaussian based on fractional position between samples - int offset = v->interp_pos >> 4 & 0xFF; - short const* fwd = gauss + 255 - offset; - short const* rev = gauss + offset; // mirror left half of gaussian - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = (fwd [ 0] * in [0]) >> 11; - out += (fwd [256] * in [1]) >> 11; - out += (rev [256] * in [2]) >> 11; - out = (int16_t) out; - out += (rev [ 0] * in [3]) >> 11; - - CLAMP16( out ); - out &= ~1; - return out; -} - - -//// Counters - -int const simple_counter_range = 2048 * 5 * 3; // 30720 - -static unsigned const counter_rates [32] = -{ - simple_counter_range + 1, // never fires - 2048, 1536, - 1280, 1024, 768, - 640, 512, 384, - 320, 256, 192, - 160, 128, 96, - 80, 64, 48, - 40, 32, 24, - 20, 16, 12, - 10, 8, 6, - 5, 4, 3, - 2, - 1 -}; - -static unsigned const counter_offsets [32] = -{ - 1, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 0, - 0 -}; - -inline void SPC_DSP::init_counter() -{ - m.counter = 0; -} - -inline void SPC_DSP::run_counters() -{ - if ( --m.counter < 0 ) - m.counter = simple_counter_range - 1; -} - -inline unsigned SPC_DSP::read_counter( int rate ) -{ - return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; -} - - -//// Envelope - -inline void SPC_DSP::run_envelope( voice_t* const v ) -{ - int env = v->env; - if ( v->env_mode == env_release ) // 60% - { - if ( (env -= 0x8) < 0 ) - env = 0; - v->env = env; - } - else - { - int rate; - int env_data = VREG(v->regs,adsr1); - if ( m.t_adsr0 & 0x80 ) // 99% ADSR - { - if ( v->env_mode >= env_decay ) // 99% - { - env--; - env -= env >> 8; - rate = env_data & 0x1F; - if ( v->env_mode == env_decay ) // 1% - rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; - } - else // env_attack - { - rate = (m.t_adsr0 & 0x0F) * 2 + 1; - env += rate < 31 ? 0x20 : 0x400; - } - } - else // GAIN - { - int mode; - env_data = VREG(v->regs,gain); - mode = env_data >> 5; - if ( mode < 4 ) // direct - { - env = env_data * 0x10; - rate = 31; - } - else - { - rate = env_data & 0x1F; - if ( mode == 4 ) // 4: linear decrease - { - env -= 0x20; - } - else if ( mode < 6 ) // 5: exponential decrease - { - env--; - env -= env >> 8; - } - else // 6,7: linear increase - { - env += 0x20; - if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) - env += 0x8 - 0x20; // 7: two-slope linear increase - } - } - } - - // Sustain level - if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) - v->env_mode = env_sustain; - - v->hidden_env = env; - - // unsigned cast because linear decrease going negative also triggers this - if ( (unsigned) env > 0x7FF ) - { - env = (env < 0 ? 0 : 0x7FF); - if ( v->env_mode == env_attack ) - v->env_mode = env_decay; - } - - if ( !read_counter( rate ) ) - v->env = env; // nothing else is controlled by the counter - } -} - - -//// BRR Decoding - -inline void SPC_DSP::decode_brr( voice_t* v ) -{ - // Arrange the four input nybbles in 0xABCD order for easy decoding - int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; - - int const header = m.t_brr_header; - - // Write to next four samples in circular buffer - int* pos = &v->buf [v->buf_pos]; - int* end; - if ( (v->buf_pos += 4) >= brr_buf_size ) - v->buf_pos = 0; - - // Decode four samples - for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) - { - // Extract nybble and sign-extend - int s = (int16_t) nybbles >> 12; - - // Shift sample based on header - int const shift = header >> 4; - s = (s << shift) >> 1; - if ( shift >= 0xD ) // handle invalid range - s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) - - // Apply IIR filter (8 is the most commonly used) - int const filter = header & 0x0C; - int const p1 = pos [brr_buf_size - 1]; - int const p2 = pos [brr_buf_size - 2] >> 1; - if ( filter >= 8 ) - { - s += p1; - s -= p2; - if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 - { - s += p2 >> 4; - s += (p1 * -3) >> 6; - } - else // s += p1 * 0.8984375 - p2 * 0.40625 - { - s += (p1 * -13) >> 7; - s += (p2 * 3) >> 4; - } - } - else if ( filter ) // s += p1 * 0.46875 - { - s += p1 >> 1; - s += (-p1) >> 5; - } - - // Adjust and write sample - CLAMP16( s ); - s = (int16_t) (s * 2); - pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around - } -} - - -//// Misc - -#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() - -MISC_CLOCK( 27 ) -{ - m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON -} -MISC_CLOCK( 28 ) -{ - m.t_non = REG(non); - m.t_eon = REG(eon); - m.t_dir = REG(dir); -} -MISC_CLOCK( 29 ) -{ - if ( (m.every_other_sample ^= 1) != 0 ) - m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read -} -MISC_CLOCK( 30 ) -{ - if ( m.every_other_sample ) - { - m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; - } - - run_counters(); - - // Noise - if ( !read_counter( REG(flg) & 0x1F ) ) - { - int feedback = (m.noise << 13) ^ (m.noise << 14); - m.noise = (feedback & 0x4000) ^ (m.noise >> 1); - } -} - - -//// Voices - -#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) - -inline VOICE_CLOCK( V1 ) -{ - m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; - m.t_srcn = VREG(v->regs,srcn); -} -inline VOICE_CLOCK( V2 ) -{ - // Read sample pointer (ignored if not needed) - uint8_t const* entry = &m.ram [m.t_dir_addr]; - if ( !v->kon_delay ) - entry += 2; - m.t_brr_next_addr = GET_LE16A( entry ); - - m.t_adsr0 = VREG(v->regs,adsr0); - - // Read pitch, spread over two clocks - m.t_pitch = VREG(v->regs,pitchl); -} -inline VOICE_CLOCK( V3a ) -{ - m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; -} -inline VOICE_CLOCK( V3b ) -{ - // Read BRR header and byte - m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; - m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking -} -VOICE_CLOCK( V3c ) -{ - // Pitch modulation using previous voice's output - if ( m.t_pmon & v->vbit ) - m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; - - if ( v->kon_delay ) - { - // Get ready to start BRR decoding on next sample - if ( v->kon_delay == 5 ) - { - v->brr_addr = m.t_brr_next_addr; - v->brr_offset = 1; - v->buf_pos = 0; - m.t_brr_header = 0; // header is ignored on this sample - m.kon_check = true; - - if (take_spc_snapshot) - { - take_spc_snapshot = 0; - if (spc_snapshot_callback) - spc_snapshot_callback(); - } - } - - // Envelope is never run during KON - v->env = 0; - v->hidden_env = 0; - - // Disable BRR decoding until last three samples - v->interp_pos = 0; - if ( --v->kon_delay & 3 ) - v->interp_pos = 0x4000; - - // Pitch is never added during KON - m.t_pitch = 0; - } - - // Gaussian interpolation - { - int output = interpolate( v ); - - // Noise - if ( m.t_non & v->vbit ) - output = (int16_t) (m.noise * 2); - - // Apply envelope - m.t_output = (output * v->env) >> 11 & ~1; - v->t_envx_out = (uint8_t) (v->env >> 4); - } - - // Immediate silence due to end of sample or soft reset - if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) - { - v->env_mode = env_release; - v->env = 0; - } - - if ( m.every_other_sample ) - { - // KOFF - if ( m.t_koff & v->vbit ) - v->env_mode = env_release; - - // KON - if ( m.kon & v->vbit ) - { - v->kon_delay = 5; - v->env_mode = env_attack; - } - } - - // Run envelope for next sample - if ( !v->kon_delay ) - run_envelope( v ); -} - -inline void SPC_DSP::voice_output( voice_t const* v, int ch ) -{ - // Apply left/right volume - int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; - amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); - - // Add to output total - m.t_main_out [ch] += amp; - CLAMP16( m.t_main_out [ch] ); - - // Optionally add to echo total - if ( m.t_eon & v->vbit ) - { - m.t_echo_out [ch] += amp; - CLAMP16( m.t_echo_out [ch] ); - } -} -VOICE_CLOCK( V4 ) -{ - // Decode BRR - m.t_looped = 0; - if ( v->interp_pos >= 0x4000 ) - { - decode_brr( v ); - - if ( (v->brr_offset += 2) >= brr_block_size ) - { - // Start decoding next BRR block - assert( v->brr_offset == brr_block_size ); - v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; - if ( m.t_brr_header & 1 ) - { - v->brr_addr = m.t_brr_next_addr; - m.t_looped = v->vbit; - } - v->brr_offset = 1; - } - } - - // Apply pitch - v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; - - // Keep from getting too far ahead (when using pitch modulation) - if ( v->interp_pos > 0x7FFF ) - v->interp_pos = 0x7FFF; - - // Output left - voice_output( v, 0 ); -} -inline VOICE_CLOCK( V5 ) -{ - // Output right - voice_output( v, 1 ); - - // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier - int endx_buf = REG(endx) | m.t_looped; - - // Clear bit in ENDX if KON just began - if ( v->kon_delay == 5 ) - endx_buf &= ~v->vbit; - m.endx_buf = (uint8_t) endx_buf; -} -inline VOICE_CLOCK( V6 ) -{ - (void) v; // avoid compiler warning about unused v - m.outx_buf = (uint8_t) (m.t_output >> 8); -} -inline VOICE_CLOCK( V7 ) -{ - // Update ENDX - REG(endx) = m.endx_buf; - - m.envx_buf = v->t_envx_out; -} -inline VOICE_CLOCK( V8 ) -{ - // Update OUTX - VREG(v->regs,outx) = m.outx_buf; -} -inline VOICE_CLOCK( V9 ) -{ - // Update ENVX - VREG(v->regs,envx) = m.envx_buf; -} - -// Most voices do all these in one clock, so make a handy composite -inline VOICE_CLOCK( V3 ) -{ - voice_V3a( v ); - voice_V3b( v ); - voice_V3c( v ); -} - -// Common combinations of voice steps on different voices. This greatly reduces -// code size and allows everything to be inlined in these functions. -VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } -VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } -VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } - - -//// Echo - -// Current echo buffer pointer for left/right channel -#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) - -// Sample in echo history buffer, where 0 is the oldest -#define ECHO_FIR( i ) (m.echo_hist_pos [i]) - -// Calculate FIR point for left/right channel -#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) - -#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() - -inline void SPC_DSP::echo_read( int ch ) -{ - int s = GET_LE16SA( ECHO_PTR( ch ) ); - // second copy simplifies wrap-around handling - ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; -} - -ECHO_CLOCK( 22 ) -{ - // History - if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) - m.echo_hist_pos = m.echo_hist; - - m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; - echo_read( 0 ); - - // FIR (using l and r temporaries below helps compiler optimize) - int l = CALC_FIR( 0, 0 ); - int r = CALC_FIR( 0, 1 ); - - m.t_echo_in [0] = l; - m.t_echo_in [1] = r; -} -ECHO_CLOCK( 23 ) -{ - int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); - int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; - - echo_read( 1 ); -} -ECHO_CLOCK( 24 ) -{ - int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); - int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; -} -ECHO_CLOCK( 25 ) -{ - int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); - int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); - - l = (int16_t) l; - r = (int16_t) r; - - l += (int16_t) CALC_FIR( 7, 0 ); - r += (int16_t) CALC_FIR( 7, 1 ); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_in [0] = l & ~1; - m.t_echo_in [1] = r & ~1; -} -inline int SPC_DSP::echo_output( int ch ) -{ - int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + - (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); - CLAMP16( out ); - return out; -} -ECHO_CLOCK( 26 ) -{ - // Left output volumes - // (save sample for next clock so we can output both together) - m.t_main_out [0] = echo_output( 0 ); - - // Echo feedback - int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); - int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_out [0] = l & ~1; - m.t_echo_out [1] = r & ~1; -} -ECHO_CLOCK( 27 ) -{ - // Output - int l = m.t_main_out [0]; - int r = echo_output( 1 ); - m.t_main_out [0] = 0; - m.t_main_out [1] = 0; - - // TODO: global muting isn't this simple (turns DAC on and off - // or something, causing small ~37-sample pulse when first muted) - if ( REG(flg) & 0x40 ) - { - l = 0; - r = 0; - } - - // Output sample to DAC - #ifdef SPC_DSP_OUT_HOOK - SPC_DSP_OUT_HOOK( l, r ); - #else - sample_t* out = m.out; - WRITE_SAMPLES( l, r, out ); - m.out = out; - #endif -} -ECHO_CLOCK( 28 ) -{ - m.t_echo_enabled = REG(flg); -} -inline void SPC_DSP::echo_write( int ch ) -{ - if ( !(m.t_echo_enabled & 0x20) ) - SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); - m.t_echo_out [ch] = 0; -} -ECHO_CLOCK( 29 ) -{ - m.t_esa = REG(esa); - - if ( !m.echo_offset ) - m.echo_length = (REG(edl) & 0x0F) * 0x800; - - m.echo_offset += 4; - if ( m.echo_offset >= m.echo_length ) - m.echo_offset = 0; - - // Write left echo - echo_write( 0 ); - - m.t_echo_enabled = REG(flg); -} -ECHO_CLOCK( 30 ) -{ - // Write right echo - echo_write( 1 ); -} - - -//// Timing - -// Execute clock for a particular voice -#define V( clock, voice ) voice_##clock( &m.voices [voice] ); - -/* The most common sequence of clocks uses composite operations -for efficiency. For example, the following are equivalent to the -individual steps on the right: - -V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) -V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) -V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ - -// Voice 0 1 2 3 4 5 6 7 -#define GEN_DSP_TIMING \ -PHASE( 0) V(V5,0)V(V2,1)\ -PHASE( 1) V(V6,0)V(V3,1)\ -PHASE( 2) V(V7_V4_V1,0)\ -PHASE( 3) V(V8_V5_V2,0)\ -PHASE( 4) V(V9_V6_V3,0)\ -PHASE( 5) V(V7_V4_V1,1)\ -PHASE( 6) V(V8_V5_V2,1)\ -PHASE( 7) V(V9_V6_V3,1)\ -PHASE( 8) V(V7_V4_V1,2)\ -PHASE( 9) V(V8_V5_V2,2)\ -PHASE(10) V(V9_V6_V3,2)\ -PHASE(11) V(V7_V4_V1,3)\ -PHASE(12) V(V8_V5_V2,3)\ -PHASE(13) V(V9_V6_V3,3)\ -PHASE(14) V(V7_V4_V1,4)\ -PHASE(15) V(V8_V5_V2,4)\ -PHASE(16) V(V9_V6_V3,4)\ -PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ -PHASE(18) V(V8_V5_V2,5)\ -PHASE(19) V(V9_V6_V3,5)\ -PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ -PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ -PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ -PHASE(23) V(V7,7) echo_23();\ -PHASE(24) V(V8,7) echo_24();\ -PHASE(25) V(V3b,0) V(V9,7) echo_25();\ -PHASE(26) echo_26();\ -PHASE(27) misc_27(); echo_27();\ -PHASE(28) misc_28(); echo_28();\ -PHASE(29) misc_29(); echo_29();\ -PHASE(30) misc_30();V(V3c,0) echo_30();\ -PHASE(31) V(V4,0) V(V1,2)\ - -#if !SPC_DSP_CUSTOM_RUN - -void SPC_DSP::run( int clocks_remain ) -{ - require( clocks_remain > 0 ); - - int const phase = m.phase; - m.phase = (phase + clocks_remain) & 31; - switch ( phase ) - { - loop: - - #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: - GEN_DSP_TIMING - #undef PHASE - - if ( --clocks_remain ) - goto loop; - } -} - -#endif - - -//// Setup - -void SPC_DSP::init( void* ram_64k ) -{ - m.ram = (uint8_t*) ram_64k; - mute_voices( 0 ); - disable_surround( false ); - set_output( 0, 0 ); - reset(); - - stereo_switch = 0xffff; - take_spc_snapshot = 0; - spc_snapshot_callback = 0; - - #ifndef NDEBUG - // be sure this sign-extends - assert( (int16_t) 0x8000 == -0x8000 ); - - // be sure right shift preserves sign - assert( (-1 >> 1) == -1 ); - - // check clamp macro - int i; - i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); - i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); - - blargg_verify_byte_order(); - #endif -} - -void SPC_DSP::soft_reset_common() -{ - require( m.ram ); // init() must have been called already - - m.noise = 0x4000; - m.echo_hist_pos = m.echo_hist; - m.every_other_sample = 1; - m.echo_offset = 0; - m.phase = 0; - - init_counter(); - - for (int i = 0; i < voice_count; i++) - m.voices[i].voice_number = i; -} - -void SPC_DSP::soft_reset() -{ - REG(flg) = 0xE0; - soft_reset_common(); -} - -void SPC_DSP::load( uint8_t const regs [register_count] ) -{ - memcpy( m.regs, regs, sizeof m.regs ); - memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); - - // Internal state - for ( int i = voice_count; --i >= 0; ) - { - voice_t* v = &m.voices [i]; - v->brr_offset = 1; - v->vbit = 1 << i; - v->regs = &m.regs [i * 0x10]; - } - m.new_kon = REG(kon); - m.t_dir = REG(dir); - m.t_esa = REG(esa); - - soft_reset_common(); -} - -void SPC_DSP::reset() { load( initial_regs ); } - - -//// State save/load - -#if !SPC_NO_COPY_STATE_FUNCS - -void SPC_State_Copier::copy( void* state, size_t size ) -{ - func( buf, state, size ); -} - -int SPC_State_Copier::copy_int( int state, int size ) -{ - BOOST::uint8_t s [2]; - SET_LE16( s, state ); - func( buf, &s, size ); - return GET_LE16( s ); -} - -void SPC_State_Copier::skip( int count ) -{ - if ( count > 0 ) - { - char temp [64]; - memset( temp, 0, sizeof temp ); - do - { - int n = sizeof temp; - if ( n > count ) - n = count; - count -= n; - func( buf, temp, n ); - } - while ( count ); - } -} - -void SPC_State_Copier::extra() -{ - int n = 0; - SPC_State_Copier& copier = *this; - SPC_COPY( uint8_t, n ); - skip( n ); -} - -void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // DSP registers - copier.copy( m.regs, register_count ); - - // Internal state - - // Voices - int i; - for ( i = 0; i < voice_count; i++ ) - { - voice_t* v = &m.voices [i]; - - // BRR buffer - int i; - for ( i = 0; i < brr_buf_size; i++ ) - { - int s = v->buf [i]; - SPC_COPY( int16_t, s ); - v->buf [i] = v->buf [i + brr_buf_size] = s; - } - - SPC_COPY( uint16_t, v->interp_pos ); - SPC_COPY( uint16_t, v->brr_addr ); - SPC_COPY( uint16_t, v->env ); - SPC_COPY( int16_t, v->hidden_env ); - SPC_COPY( uint8_t, v->buf_pos ); - SPC_COPY( uint8_t, v->brr_offset ); - SPC_COPY( uint8_t, v->kon_delay ); - { - int m = v->env_mode; - SPC_COPY( uint8_t, m ); - v->env_mode = (enum env_mode_t) m; - } - SPC_COPY( uint8_t, v->t_envx_out ); - - copier.extra(); - } - - // Echo history - for ( i = 0; i < echo_hist_size; i++ ) - { - int j; - for ( j = 0; j < 2; j++ ) - { - int s = m.echo_hist_pos [i] [j]; - SPC_COPY( int16_t, s ); - m.echo_hist [i] [j] = s; // write back at offset 0 - } - } - m.echo_hist_pos = m.echo_hist; - memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); - - // Misc - SPC_COPY( uint8_t, m.every_other_sample ); - SPC_COPY( uint8_t, m.kon ); - - SPC_COPY( uint16_t, m.noise ); - SPC_COPY( uint16_t, m.counter ); - SPC_COPY( uint16_t, m.echo_offset ); - SPC_COPY( uint16_t, m.echo_length ); - SPC_COPY( uint8_t, m.phase ); - - SPC_COPY( uint8_t, m.new_kon ); - SPC_COPY( uint8_t, m.endx_buf ); - SPC_COPY( uint8_t, m.envx_buf ); - SPC_COPY( uint8_t, m.outx_buf ); - - SPC_COPY( uint8_t, m.t_pmon ); - SPC_COPY( uint8_t, m.t_non ); - SPC_COPY( uint8_t, m.t_eon ); - SPC_COPY( uint8_t, m.t_dir ); - SPC_COPY( uint8_t, m.t_koff ); - - SPC_COPY( uint16_t, m.t_brr_next_addr ); - SPC_COPY( uint8_t, m.t_adsr0 ); - SPC_COPY( uint8_t, m.t_brr_header ); - SPC_COPY( uint8_t, m.t_brr_byte ); - SPC_COPY( uint8_t, m.t_srcn ); - SPC_COPY( uint8_t, m.t_esa ); - SPC_COPY( uint8_t, m.t_echo_enabled ); - - SPC_COPY( int16_t, m.t_main_out [0] ); - SPC_COPY( int16_t, m.t_main_out [1] ); - SPC_COPY( int16_t, m.t_echo_out [0] ); - SPC_COPY( int16_t, m.t_echo_out [1] ); - SPC_COPY( int16_t, m.t_echo_in [0] ); - SPC_COPY( int16_t, m.t_echo_in [1] ); - - SPC_COPY( uint16_t, m.t_dir_addr ); - SPC_COPY( uint16_t, m.t_pitch ); - SPC_COPY( int16_t, m.t_output ); - SPC_COPY( uint16_t, m.t_echo_ptr ); - SPC_COPY( uint8_t, m.t_looped ); - - copier.extra(); -} -#endif - - -//// Snes9x Accessor - -void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) -{ - spc_snapshot_callback = callback; -} - -void SPC_DSP::dump_spc_snapshot( void ) -{ - take_spc_snapshot = 1; -} - -void SPC_DSP::set_stereo_switch( int value ) -{ - stereo_switch = value; -} - -uint8_t SPC_DSP::reg_value( int ch, int addr ) -{ - return m.voices[ch].regs[addr]; -} - -int SPC_DSP::envx_value( int ch ) -{ - return m.voices[ch].env; -} diff --git a/source/snes9x/apu/SPC_DSP.h b/source/snes9x/apu/SPC_DSP.h deleted file mode 100644 index 6705a49..0000000 --- a/source/snes9x/apu/SPC_DSP.h +++ /dev/null @@ -1,317 +0,0 @@ -// Highly accurate SNES SPC-700 DSP emulator - -// snes_spc 0.9.0 -#ifndef SPC_DSP_H -#define SPC_DSP_H - -#include "blargg_common.h" - -extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } - -class SPC_DSP { -public: - typedef BOOST::uint8_t uint8_t; - -// Setup - - // Initializes DSP and has it use the 64K RAM provided - void init( void* ram_64k ); - - // Sets destination for output samples. If out is NULL or out_size is 0, - // doesn't generate any. - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since it was last set, always - // a multiple of 2. Undefined if more samples were generated than - // output buffer could hold. - int sample_count() const; - -// Emulation - - // Resets DSP to power-on state - void reset(); - - // Emulates pressing reset switch on SNES - void soft_reset(); - - // Reads/writes DSP registers. For accuracy, you must first call run() - // to catch the DSP up to present. - int read ( int addr ) const; - void write( int addr, int data ); - - // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks - // a pair of samples is be generated. - void run( int clock_count ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - -// State - - // Resets DSP and uses supplied values to initialize registers - enum { register_count = 128 }; - void load( uint8_t const regs [register_count] ); - - // Saves/loads exact emulator state - enum { state_size = 640 }; // maximum space needed when saving - typedef dsp_copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Returns non-zero if new key-on events occurred since last call - bool check_kon(); - -// Snes9x Accessor - - int stereo_switch; - int take_spc_snapshot; - void (*spc_snapshot_callback) (void); - - void set_spc_snapshot_callback( void (*callback) (void) ); - void dump_spc_snapshot( void ); - void set_stereo_switch( int ); - uint8_t reg_value( int, int ); - int envx_value( int ); - -// DSP register addresses - - // Global registers - enum { - r_mvoll = 0x0C, r_mvolr = 0x1C, - r_evoll = 0x2C, r_evolr = 0x3C, - r_kon = 0x4C, r_koff = 0x5C, - r_flg = 0x6C, r_endx = 0x7C, - r_efb = 0x0D, r_pmon = 0x2D, - r_non = 0x3D, r_eon = 0x4D, - r_dir = 0x5D, r_esa = 0x6D, - r_edl = 0x7D, - r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F - }; - - // Voice registers - enum { - v_voll = 0x00, v_volr = 0x01, - v_pitchl = 0x02, v_pitchh = 0x03, - v_srcn = 0x04, v_adsr0 = 0x05, - v_adsr1 = 0x06, v_gain = 0x07, - v_envx = 0x08, v_outx = 0x09 - }; - -public: - enum { extra_size = 16 }; - sample_t* extra() { return m.extra; } - sample_t const* out_pos() const { return m.out; } - void disable_surround( bool ) { } // not supported -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::int8_t int8_t; - typedef BOOST::int16_t int16_t; - - enum { echo_hist_size = 8 }; - - enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; - enum { brr_buf_size = 12 }; - struct voice_t - { - int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) - int buf_pos; // place in buffer where next samples will be decoded - int interp_pos; // relative fractional position in sample (0x1000 = 1.0) - int brr_addr; // address of current BRR block - int brr_offset; // current decoding offset in BRR block - uint8_t* regs; // pointer to voice's DSP registers - int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. - int kon_delay; // KON delay/current setup phase - env_mode_t env_mode; - int env; // current envelope level - int hidden_env; // used by GAIN mode 7, very obscure quirk - uint8_t t_envx_out; - int voice_number; - }; -private: - enum { brr_block_size = 9 }; - - struct state_t - { - uint8_t regs [register_count]; - - // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) - int echo_hist [echo_hist_size * 2] [2]; - int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] - - int every_other_sample; // toggles every sample - int kon; // KON value when last checked - int noise; - int counter; - int echo_offset; // offset from ESA in echo buffer - int echo_length; // number of bytes that echo_offset will stop at - int phase; // next clock cycle to run (0-31) - bool kon_check; // set when a new KON occurs - - // Hidden registers also written to when main register is written to - int new_kon; - uint8_t endx_buf; - uint8_t envx_buf; - uint8_t outx_buf; - - // Temporary state between clocks - - // read once per sample - int t_pmon; - int t_non; - int t_eon; - int t_dir; - int t_koff; - - // read a few clocks ahead then used - int t_brr_next_addr; - int t_adsr0; - int t_brr_header; - int t_brr_byte; - int t_srcn; - int t_esa; - int t_echo_enabled; - - // internal state that is recalculated every sample - int t_dir_addr; - int t_pitch; - int t_output; - int t_looped; - int t_echo_ptr; - - // left/right sums - int t_main_out [2]; - int t_echo_out [2]; - int t_echo_in [2]; - - voice_t voices [voice_count]; - - // non-emulation state - uint8_t* ram; // 64K shared RAM between DSP and SMP - int mute_mask; - sample_t* out; - sample_t* out_end; - sample_t* out_begin; - sample_t extra [extra_size]; - }; - state_t m; - - void init_counter(); - void run_counters(); - unsigned read_counter( int rate ); - - int interpolate( voice_t const* v ); - void run_envelope( voice_t* const v ); - void decode_brr( voice_t* v ); - - void misc_27(); - void misc_28(); - void misc_29(); - void misc_30(); - - void voice_output( voice_t const* v, int ch ); - void voice_V1( voice_t* const ); - void voice_V2( voice_t* const ); - void voice_V3( voice_t* const ); - void voice_V3a( voice_t* const ); - void voice_V3b( voice_t* const ); - void voice_V3c( voice_t* const ); - void voice_V4( voice_t* const ); - void voice_V5( voice_t* const ); - void voice_V6( voice_t* const ); - void voice_V7( voice_t* const ); - void voice_V8( voice_t* const ); - void voice_V9( voice_t* const ); - void voice_V7_V4_V1( voice_t* const ); - void voice_V8_V5_V2( voice_t* const ); - void voice_V9_V6_V3( voice_t* const ); - - void echo_read( int ch ); - int echo_output( int ch ); - void echo_write( int ch ); - void echo_22(); - void echo_23(); - void echo_24(); - void echo_25(); - void echo_26(); - void echo_27(); - void echo_28(); - void echo_29(); - void echo_30(); - - void soft_reset_common(); -}; - -#include - -inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } - -inline int SPC_DSP::read( int addr ) const -{ - assert( (unsigned) addr < register_count ); - return m.regs [addr]; -} - -inline void SPC_DSP::write( int addr, int data ) -{ - assert( (unsigned) addr < register_count ); - - m.regs [addr] = (uint8_t) data; - switch ( addr & 0x0F ) - { - case v_envx: - m.envx_buf = (uint8_t) data; - break; - - case v_outx: - m.outx_buf = (uint8_t) data; - break; - - case 0x0C: - if ( addr == r_kon ) - m.new_kon = (uint8_t) data; - - if ( addr == r_endx ) // always cleared, regardless of data written - { - m.endx_buf = 0; - m.regs [r_endx] = 0; - } - break; - } -} - -inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } - -inline bool SPC_DSP::check_kon() -{ - bool old = m.kon_check; - m.kon_check = 0; - return old; -} - -#if !SPC_NO_COPY_STATE_FUNCS - -class SPC_State_Copier { - SPC_DSP::copy_func_t func; - unsigned char** buf; -public: - SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } - void copy( void* state, size_t size ); - int copy_int( int state, int size ); - void skip( int count ); - void extra(); -}; - -#define SPC_COPY( type, state )\ -{\ - state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ - assert( (BOOST::type) state == state );\ -} - -#endif - -#endif diff --git a/source/snes9x/apu/SPC_Filter.cpp b/source/snes9x/apu/SPC_Filter.cpp deleted file mode 100644 index b3d5770..0000000 --- a/source/snes9x/apu/SPC_Filter.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_Filter.h" - -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } - -SPC_Filter::SPC_Filter() -{ - gain = gain_unit; - bass = bass_norm; - clear(); -} - -void SPC_Filter::run( short* io, int count ) -{ - require( (count & 1) == 0 ); // must be even - - int const gain = this->gain; - int const bass = this->bass; - chan_t* c = &ch [2]; - do - { - // cache in registers - int sum = (--c)->sum; - int pp1 = c->pp1; - int p1 = c->p1; - - for ( int i = 0; i < count; i += 2 ) - { - // Low-pass filter (two point FIR with coeffs 0.25, 0.75) - int f = io [i] + p1; - p1 = io [i] * 3; - - // High-pass filter ("leaky integrator") - int delta = f - pp1; - pp1 = f; - int s = sum >> (gain_bits + 2); - sum += (delta * gain) - (sum >> bass); - - // Clamp to 16 bits - if ( (short) s != s ) - s = (s >> 31) ^ 0x7FFF; - - io [i] = (short) s; - } - - c->p1 = p1; - c->pp1 = pp1; - c->sum = sum; - ++io; - } - while ( c != ch ); -} diff --git a/source/snes9x/apu/SPC_Filter.h b/source/snes9x/apu/SPC_Filter.h deleted file mode 100644 index d5c83cb..0000000 --- a/source/snes9x/apu/SPC_Filter.h +++ /dev/null @@ -1,47 +0,0 @@ -// Simple low-pass and high-pass filter to better match sound output of a SNES - -// snes_spc 0.9.0 -#ifndef SPC_FILTER_H -#define SPC_FILTER_H - -#include "blargg_common.h" - -struct SPC_Filter { -public: - - // Filters count samples of stereo sound in place. Count must be a multiple of 2. - typedef short sample_t; - void run( sample_t* io, int count ); - -// Optional features - - // Clears filter to silence - void clear(); - - // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit - // are fine, since output is clamped to 16-bit sample range. - enum { gain_unit = 0x100 }; - void set_gain( int gain ); - - // Sets amount of bass (logarithmic scale) - enum { bass_none = 0 }; - enum { bass_norm = 8 }; // normal amount - enum { bass_max = 31 }; - void set_bass( int bass ); - -public: - SPC_Filter(); - BLARGG_DISABLE_NOTHROW -private: - enum { gain_bits = 8 }; - int gain; - int bass; - struct chan_t { int p1, pp1, sum; }; - chan_t ch [2]; -}; - -inline void SPC_Filter::set_gain( int g ) { gain = g; } - -inline void SPC_Filter::set_bass( int b ) { bass = b; } - -#endif diff --git a/source/snes9x/apu/apu.cpp b/source/snes9x/apu/apu.cpp deleted file mode 100644 index 0529ff3..0000000 --- a/source/snes9x/apu/apu.cpp +++ /dev/null @@ -1,633 +0,0 @@ -/********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com) - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley, - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001-2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight, - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound DSP emulator code is derived from SNEeSe and OpenSPC: - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2007 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -**********************************************************************************/ - - -#include -#include "snes9x.h" -#include "apu.h" -#include "snapshot.h" -#include "display.h" -#include "resampler.h" - -#define APU_DEFAULT_INPUT_RATE 32000 -#define APU_MINIMUM_SAMPLE_COUNT 512 -#define APU_MINIMUM_SAMPLE_BLOCK 128 -#define APU_NUMERATOR_NTSC 5632 -#define APU_DENOMINATOR_NTSC 118125 -#define APU_NUMERATOR_PAL 102400 -#define APU_DENOMINATOR_PAL 2128137 - -SNES_SPC *spc_core = NULL; - -static uint8 APUROM[64] = -{ - 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, - 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78, - 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, - 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, - 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, - 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, - 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, - 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF -}; - -namespace spc -{ - static apu_callback sa_callback = NULL; - static void *extra_data = NULL; - - static bool8 sound_in_sync = TRUE; - static bool8 sound_enabled = FALSE; - - static int buffer_size; - static int lag_master = 0; - static int lag = 0; - - static uint8 *landing_buffer = NULL; - static uint8 *shrink_buffer = NULL; - - static Resampler *resampler = NULL; - - static int32 reference_time; - static uint32 remainder; - - static const int32 timing_hack_numerator = SNES_SPC::tempo_unit; - static int32 timing_hack_denominator = SNES_SPC::tempo_unit; -} - -static void EightBitize (uint8 *, int); -static void DeStereo (uint8 *, int); -static void ReverseStereo (uint8 *, int); -static void UpdatePlaybackRate (void); -static void from_apu_to_state (uint8 **, void *, size_t); -static void to_apu_from_state (uint8 **, void *, size_t); -static void SPCSnapshotCallback (void); -static inline int S9xAPUGetClock (int32); -static inline int S9xAPUGetClockRemainder (int32); - - -static void EightBitize (uint8 *buffer, int sample_count) -{ - uint8 *buf8 = (uint8 *) buffer; - int16 *buf16 = (int16 *) buffer; - - for (int i = 0; i < sample_count; i++) - buf8[i] = (uint8) ((buf16[i] / 256) + 128); -} - -static void DeStereo (uint8 *buffer, int sample_count) -{ - int16 *buf = (int16 *) buffer; - int32 s1, s2; - - for (int i = 0; i < sample_count >> 1; i++) - { - s1 = (int32) buf[2 * i]; - s2 = (int32) buf[2 * i + 1]; - buf[i] = (int16) ((s1 + s2) >> 1); - } -} - -static void ReverseStereo (uint8 *src_buffer, int sample_count) -{ - int16 *buffer = (int16 *) src_buffer; - - for (int i = 0; i < sample_count; i += 2) - { - buffer[i + 1] ^= buffer[i]; - buffer[i] ^= buffer[i + 1]; - buffer[i + 1] ^= buffer[i]; - } -} - -bool8 S9xMixSamples (uint8 *buffer, int sample_count) -{ - static int shrink_buffer_size = -1; - uint8 *dest; - - if (!Settings.SixteenBitSound || !Settings.Stereo) - { - /* We still need both stereo samples for generating the mono sample */ - if (!Settings.Stereo) - sample_count <<= 1; - - /* We still have to generate 16-bit samples for bit-dropping, too */ - if (shrink_buffer_size < (sample_count << 1)) - { - delete[] spc::shrink_buffer; - spc::shrink_buffer = new uint8[sample_count << 1]; - shrink_buffer_size = sample_count << 1; - } - - dest = spc::shrink_buffer; - } - else - dest = buffer; - - if (Settings.Mute) - { - memset(dest, 0, sample_count << 1); - spc::resampler->clear(); - - return (FALSE); - } - else - { - if (spc::resampler->avail() >= (sample_count + spc::lag)) - { - spc::resampler->read((short *) dest, sample_count); - if (spc::lag == spc::lag_master) - spc::lag = 0; - } - else - { - memset(buffer, (Settings.SixteenBitSound ? 0 : 128), (sample_count << (Settings.SixteenBitSound ? 1 : 0)) >> (Settings.Stereo ? 0 : 1)); - if (spc::lag == 0) - spc::lag = spc::lag_master; - - return (FALSE); - } - } - - if (Settings.ReverseStereo && Settings.Stereo) - ReverseStereo(dest, sample_count); - - if (!Settings.Stereo || !Settings.SixteenBitSound) - { - if (!Settings.Stereo) - { - DeStereo(dest, sample_count); - sample_count >>= 1; - } - - if (!Settings.SixteenBitSound) - EightBitize(dest, sample_count); - - memcpy(buffer, dest, (sample_count << (Settings.SixteenBitSound ? 1 : 0))); - } - - return (TRUE); -} - -int S9xGetSampleCount (void) -{ - return (spc::resampler->avail()); -} - -void S9xFinalizeSamples (void) -{ - if (!Settings.Mute) - { - if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count())) - { - /* We weren't able to process the entire buffer. Potential overrun. */ - spc::sound_in_sync = FALSE; - - if (Settings.SoundSync && !Settings.TurboMode) - return; - } - } - - if (!Settings.SoundSync || Settings.TurboMode || Settings.Mute) - spc::sound_in_sync = TRUE; - else - if (spc::resampler->space_empty() >= spc::resampler->space_filled()) - spc::sound_in_sync = TRUE; - else - spc::sound_in_sync = FALSE; - - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); -} - -void S9xLandSamples (void) -{ - if (spc::sa_callback != NULL) - spc::sa_callback(spc::extra_data); - else - S9xFinalizeSamples(); -} - -void S9xClearSamples (void) -{ - spc::resampler->clear(); - spc::lag = spc::lag_master; -} - -bool8 S9xSyncSound (void) -{ - if (!Settings.SoundSync || spc::sound_in_sync) - return (TRUE); - - S9xLandSamples(); - - return (spc::sound_in_sync); -} - -void S9xSetSamplesAvailableCallback (apu_callback callback, void *data) -{ - spc::sa_callback = callback; - spc::extra_data = data; -} - -static void UpdatePlaybackRate (void) -{ - if (Settings.SoundInputRate == 0) - Settings.SoundInputRate = APU_DEFAULT_INPUT_RATE; - - double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator); - spc::resampler->time_ratio(time_ratio); -} - -bool8 S9xInitSound (int sample_count, int lag_sample_count) -{ - // sample_count : buffer size given in samples in one channel - // lag_sample_count: allowable time-lag given in samples in one channel - - spc::lag_master = lag_sample_count; - if (Settings.Stereo) - spc::lag_master <<= 1; - spc::lag = spc::lag_master; - - if (sample_count < APU_MINIMUM_SAMPLE_COUNT) - sample_count = APU_MINIMUM_SAMPLE_COUNT; - - spc::buffer_size = sample_count; - if (Settings.Stereo) - spc::buffer_size <<= 1; - if (Settings.SixteenBitSound) - spc::buffer_size <<= 1; - - if (spc::landing_buffer) - delete[] spc::landing_buffer; - spc::landing_buffer = new uint8[spc::buffer_size * 2]; - if (!spc::landing_buffer) - return (FALSE); - - /* The resampler and spc unit use samples (16-bit short) as - arguments. Use 2x in the resampler for buffer leveling with SoundSync */ - if (!spc::resampler) - { - spc::resampler = new Resampler(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); - if (!spc::resampler) - { - delete[] spc::landing_buffer; - return (FALSE); - } - } - else - spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); - - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); - - UpdatePlaybackRate(); - - spc::sound_enabled = S9xOpenSoundDevice(spc::buffer_size); - - return (spc::sound_enabled); -} - -void S9xSetSoundControl (uint8 voice_switch) -{ - spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); -} - -void S9xSetSoundMute (bool8 mute) -{ - Settings.Mute = mute; - if (!spc::sound_enabled) - Settings.Mute = TRUE; -} - -void S9xDumpSPCSnapshot (void) -{ - spc_core->dsp_dump_spc_snapshot(); -} - -static void SPCSnapshotCallback (void) -{ - S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR)); - printf("Dumped key-on triggered spc snapshot.\n"); -} - -bool8 S9xInitAPU (void) -{ - spc_core = new SNES_SPC; - if (!spc_core) - return (FALSE); - - spc_core->init(); - spc_core->init_rom(APUROM); - - spc_core->dsp_set_spc_snapshot_callback(SPCSnapshotCallback); - - spc::landing_buffer = NULL; - spc::shrink_buffer = NULL; - spc::resampler = NULL; - - return (TRUE); -} - -void S9xDeinitAPU (void) -{ - if (spc_core) - { - delete spc_core; - spc_core = NULL; - } - - if (spc::resampler) - { - delete spc::resampler; - spc::resampler = NULL; - } - - if (spc::landing_buffer) - { - delete[] spc::landing_buffer; - spc::landing_buffer = NULL; - } - - if (spc::shrink_buffer) - { - delete[] spc::shrink_buffer; - spc::shrink_buffer = NULL; - } -} - -static inline int S9xAPUGetClock (int32 cpucycles) -{ - if (Settings.PAL) - return floor((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / - (APU_DENOMINATOR_PAL * spc::timing_hack_denominator); - else - return (APU_NUMERATOR_NTSC * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / - (APU_DENOMINATOR_NTSC * spc::timing_hack_denominator); -} - -static inline int S9xAPUGetClockRemainder (int32 cpucycles) -{ - if (Settings.PAL) - return fmod ((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder, - APU_DENOMINATOR_PAL * spc::timing_hack_denominator); - else - return (APU_NUMERATOR_NTSC * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) % - (APU_DENOMINATOR_NTSC * spc::timing_hack_denominator); -} - -uint8 S9xAPUReadPort (int port) -{ - return ((uint8) spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port)); -} - -void S9xAPUWritePort (int port, uint8 byte) -{ - spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte); -} - -void S9xAPUSetReferenceTime (int32 cpucycles) -{ - spc::reference_time = cpucycles; -} - -void S9xAPUExecute (void) -{ - /* Accumulate partial APU cycles */ - spc_core->end_frame(S9xAPUGetClock(CPU.Cycles)); - - spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles); - - S9xAPUSetReferenceTime(CPU.Cycles); -} - -void S9xAPUEndScanline (void) -{ - S9xAPUExecute(); - - if (spc_core->sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) - S9xLandSamples(); -} - -void S9xAPUTimingSetSpeedup (int ticks) -{ - if (ticks != 0) - printf("APU speedup hack: %d\n", ticks); - - spc_core->set_tempo(SNES_SPC::tempo_unit - ticks); - - spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks; - - UpdatePlaybackRate(); -} - -void S9xResetAPU (void) -{ - spc::reference_time = 0; - spc::remainder = 0; - spc_core->reset(); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); - - spc::resampler->clear(); -} - -void S9xSoftResetAPU (void) -{ - spc::reference_time = 0; - spc::remainder = 0; - spc_core->soft_reset(); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); - - spc::resampler->clear(); -} - -static void from_apu_to_state (uint8 **buf, void *var, size_t size) -{ - memcpy(*buf, var, size); - *buf += size; -} - -static void to_apu_from_state (uint8 **buf, void *var, size_t size) -{ - memcpy(var, *buf, size); - *buf += size; -} - -void S9xAPUSaveState (uint8 *block) -{ - uint8 *ptr = block; - - spc_core->copy_state(&ptr, from_apu_to_state); - - SET_LE32(ptr, spc::reference_time); - ptr += sizeof(int32); - SET_LE32(ptr, spc::remainder); -} - -void S9xAPULoadState (uint8 *block) -{ - uint8 *ptr = block; - - S9xResetAPU(); - - spc_core->copy_state(&ptr, to_apu_from_state); - - spc::reference_time = GET_LE32(ptr); - ptr += sizeof(int32); - spc::remainder = GET_LE32(ptr); -} diff --git a/source/snes9x/apu/blargg_common.h b/source/snes9x/apu/blargg_common.h deleted file mode 100644 index 8232803..0000000 --- a/source/snes9x/apu/blargg_common.h +++ /dev/null @@ -1,187 +0,0 @@ -// Sets up common environment for Shay Green's libraries. -// To change configuration options, modify blargg_config.h, not this file. - -// snes_spc 0.9.0 -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -#include -#include -#include -#include -#include - -#undef BLARGG_COMMON_H -// allow blargg_config.h to #include blargg_common.h -#include "blargg_config.h" -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -// BLARGG_RESTRICT: equivalent to restrict, where supported -#if defined (__GNUC__) || _MSC_VER >= 1100 - #define BLARGG_RESTRICT __restrict -#else - #define BLARGG_RESTRICT -#endif - -// STATIC_CAST(T,expr): Used in place of static_cast (expr) -#ifndef STATIC_CAST - #define STATIC_CAST(T,expr) ((T) (expr)) -#endif - -// blargg_err_t (0 on success, otherwise error string) -#ifndef blargg_err_t - typedef const char* blargg_err_t; -#endif - -// blargg_vector - very lightweight vector of POD types (no constructor/destructor) -template -class blargg_vector { - T* begin_; - size_t size_; -public: - blargg_vector() : begin_( 0 ), size_( 0 ) { } - ~blargg_vector() { free( begin_ ); } - size_t size() const { return size_; } - T* begin() const { return begin_; } - T* end() const { return begin_ + size_; } - blargg_err_t resize( size_t n ) - { - // TODO: blargg_common.cpp to hold this as an outline function, ugh - void* p = realloc( begin_, n * sizeof (T) ); - if ( p ) - begin_ = (T*) p; - else if ( n > size_ ) // realloc failure only a problem if expanding - return "Out of memory"; - size_ = n; - return 0; - } - void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } - T& operator [] ( size_t n ) const - { - assert( n <= size_ ); // <= to allow past-the-end value - return begin_ [n]; - } -}; - -#ifndef BLARGG_DISABLE_NOTHROW - // throw spec mandatory in ISO C++ if operator new can return NULL - #if __cplusplus >= 199711 || defined (__GNUC__) - #define BLARGG_THROWS( spec ) throw spec - #else - #define BLARGG_THROWS( spec ) - #endif - #define BLARGG_DISABLE_NOTHROW \ - void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ - void operator delete ( void* p ) { free( p ); } - #define BLARGG_NEW new -#else - #include - #define BLARGG_NEW new (std::nothrow) -#endif - -// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) -#define BLARGG_4CHAR( a, b, c, d ) \ - ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) - -// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. -#ifndef BOOST_STATIC_ASSERT - #ifdef _MSC_VER - // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) - #else - // Some other compilers fail when declaring same function multiple times in class, - // so differentiate them by line - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) - #endif -#endif - -// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, -// compiler is assumed to support bool. If undefined, availability is determined. -#ifndef BLARGG_COMPILER_HAS_BOOL - #if defined (__MWERKS__) - #if !__option(bool) - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (_MSC_VER) - #if _MSC_VER < 1100 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (__GNUC__) - // supports bool - #elif __cplusplus < 199711 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif -#endif -#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL - // If you get errors here, modify your blargg_config.h file - typedef int bool; - const bool true = 1; - const bool false = 0; -#endif - -// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough - -#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF - typedef long blargg_long; -#else - typedef int blargg_long; -#endif - -#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF - typedef unsigned long blargg_ulong; -#else - typedef unsigned blargg_ulong; -#endif - -// BOOST::int8_t etc. - -// HAVE_STDINT_H: If defined, use for int8_t etc. -#if defined (HAVE_STDINT_H) - #include - #define BOOST - -// HAVE_INTTYPES_H: If defined, use for int8_t etc. -#elif defined (HAVE_INTTYPES_H) - #include - #define BOOST - -#else - struct BOOST - { - #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F - typedef signed char int8_t; - typedef unsigned char uint8_t; - #else - // No suitable 8-bit type available - typedef struct see_blargg_common_h int8_t; - typedef struct see_blargg_common_h uint8_t; - #endif - - #if USHRT_MAX == 0xFFFF - typedef short int16_t; - typedef unsigned short uint16_t; - #else - // No suitable 16-bit type available - typedef struct see_blargg_common_h int16_t; - typedef struct see_blargg_common_h uint16_t; - #endif - - #if ULONG_MAX == 0xFFFFFFFF - typedef long int32_t; - typedef unsigned long uint32_t; - #elif UINT_MAX == 0xFFFFFFFF - typedef int int32_t; - typedef unsigned int uint32_t; - #else - // No suitable 32-bit type available - typedef struct see_blargg_common_h int32_t; - typedef struct see_blargg_common_h uint32_t; - #endif - }; -#endif - -#endif -#endif diff --git a/source/snes9x/apu/blargg_config.h b/source/snes9x/apu/blargg_config.h deleted file mode 100644 index 9dc69db..0000000 --- a/source/snes9x/apu/blargg_config.h +++ /dev/null @@ -1,24 +0,0 @@ -// snes_spc 0.9.0 user configuration file. Don't replace when updating library. - -// snes_spc 0.9.0 -#ifndef BLARGG_CONFIG_H -#define BLARGG_CONFIG_H - -// Uncomment to disable debugging checks -//#define NDEBUG 1 - -// Uncomment to enable platform-specific (and possibly non-portable) optimizations -//#define BLARGG_NONPORTABLE 1 - -// Uncomment if automatic byte-order determination doesn't work -//#define BLARGG_BIG_ENDIAN 1 - -// Uncomment if you get errors in the bool section of blargg_common.h -//#define BLARGG_COMPILER_HAS_BOOL 1 - -// Use standard config.h if present -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#endif diff --git a/source/snes9x/apu/blargg_endian.h b/source/snes9x/apu/blargg_endian.h deleted file mode 100644 index f2daca6..0000000 --- a/source/snes9x/apu/blargg_endian.h +++ /dev/null @@ -1,185 +0,0 @@ -// CPU Byte Order Utilities - -// snes_spc 0.9.0 -#ifndef BLARGG_ENDIAN -#define BLARGG_ENDIAN - -#include "blargg_common.h" - -// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - #define BLARGG_CPU_X86 1 - #define BLARGG_CPU_CISC 1 -#endif - -#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) - #define BLARGG_CPU_POWERPC 1 - #define BLARGG_CPU_RISC 1 -#endif - -// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only -// one may be #defined to 1. Only needed if something actually depends on byte order. -#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) -#ifdef __GLIBC__ - // GCC handles this for us - #include - #if __BYTE_ORDER == __LITTLE_ENDIAN - #define BLARGG_LITTLE_ENDIAN 1 - #elif __BYTE_ORDER == __BIG_ENDIAN - #define BLARGG_BIG_ENDIAN 1 - #endif -#else - -#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ - (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) - #define BLARGG_LITTLE_ENDIAN 1 -#endif - -#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ - defined (__sparc__) || BLARGG_CPU_POWERPC || \ - (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) - #define BLARGG_BIG_ENDIAN 1 -#elif !defined (__mips__) - // No endian specified; assume little-endian, since it's most common - #define BLARGG_LITTLE_ENDIAN 1 -#endif -#endif -#endif - -#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN - #undef BLARGG_LITTLE_ENDIAN - #undef BLARGG_BIG_ENDIAN -#endif - -inline void blargg_verify_byte_order() -{ - #ifndef NDEBUG - #if BLARGG_BIG_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i == 0 ); - #elif BLARGG_LITTLE_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i != 0 ); - #endif - #endif -} - -inline unsigned get_le16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} - -inline unsigned get_be16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [0] << 8 | - (unsigned) ((unsigned char const*) p) [1]; -} - -inline blargg_ulong get_le32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | - (blargg_ulong) ((unsigned char const*) p) [2] << 16 | - (blargg_ulong) ((unsigned char const*) p) [1] << 8 | - (blargg_ulong) ((unsigned char const*) p) [0]; -} - -inline blargg_ulong get_be32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | - (blargg_ulong) ((unsigned char const*) p) [1] << 16 | - (blargg_ulong) ((unsigned char const*) p) [2] << 8 | - (blargg_ulong) ((unsigned char const*) p) [3]; -} - -inline void set_le16( void* p, unsigned n ) -{ - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [0] = (unsigned char) n; -} - -inline void set_be16( void* p, unsigned n ) -{ - ((unsigned char*) p) [0] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) n; -} - -inline void set_le32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [0] = (unsigned char) n; - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16); - ((unsigned char*) p) [3] = (unsigned char) (n >> 24); -} - -inline void set_be32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [3] = (unsigned char) n; - ((unsigned char*) p) [2] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) (n >> 16); - ((unsigned char*) p) [0] = (unsigned char) (n >> 24); -} - -#if BLARGG_NONPORTABLE - // Optimized implementation if byte order is known - #if BLARGG_LITTLE_ENDIAN - #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - #elif BLARGG_BIG_ENDIAN - #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - - #if BLARGG_CPU_POWERPC - // PowerPC has special byte-reversed instructions - #if defined (__MWERKS__) - #define GET_LE16( addr ) (__lhbrx( addr, 0 )) - #define GET_LE32( addr ) (__lwbrx( addr, 0 )) - #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) - #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) - #elif defined (__GNUC__) - #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) - #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) - #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #endif - #endif - #endif -#endif - -#ifndef GET_LE16 - #define GET_LE16( addr ) get_le16( addr ) - #define SET_LE16( addr, data ) set_le16( addr, data ) -#endif - -#ifndef GET_LE32 - #define GET_LE32( addr ) get_le32( addr ) - #define SET_LE32( addr, data ) set_le32( addr, data ) -#endif - -#ifndef GET_BE16 - #define GET_BE16( addr ) get_be16( addr ) - #define SET_BE16( addr, data ) set_be16( addr, data ) -#endif - -#ifndef GET_BE32 - #define GET_BE32( addr ) get_be32( addr ) - #define SET_BE32( addr, data ) set_be32( addr, data ) -#endif - -// auto-selecting versions - -inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } -inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } -inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } -inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } -inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } -inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } -inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } -inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } - -#endif diff --git a/source/snes9x/apu/blargg_source.h b/source/snes9x/apu/blargg_source.h deleted file mode 100644 index 5e45c4f..0000000 --- a/source/snes9x/apu/blargg_source.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Included at the beginning of library source files, after all other #include lines. -Sets up helpful macros and services used in my source code. They don't need -module an annoying module prefix on their names since they are defined after -all other #include lines. */ - -// snes_spc 0.9.0 -#ifndef BLARGG_SOURCE_H -#define BLARGG_SOURCE_H - -// If debugging is enabled, abort program if expr is false. Meant for checking -// internal state and consistency. A failed assertion indicates a bug in the module. -// void assert( bool expr ); -#include - -// If debugging is enabled and expr is false, abort program. Meant for checking -// caller-supplied parameters and operations that are outside the control of the -// module. A failed requirement indicates a bug outside the module. -// void require( bool expr ); -#undef require -#define require( expr ) assert( expr ) - -// Like printf() except output goes to debug log file. Might be defined to do -// nothing (not even evaluate its arguments). -// void dprintf( const char* format, ... ); -static inline void blargg_dprintf_( const char*, ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ - -// If enabled, evaluate expr and if false, make debug log entry with source file -// and line. Meant for finding situations that should be examined further, but that -// don't indicate a problem. In all cases, execution continues normally. -#undef check -#define check( expr ) ((void) 0) - -// If expr yields error string, return it from current function, otherwise continue. -#undef RETURN_ERR -#define RETURN_ERR( expr ) do { \ - blargg_err_t blargg_return_err_ = (expr); \ - if ( blargg_return_err_ ) return blargg_return_err_; \ - } while ( 0 ) - -// If ptr is 0, return out of memory error string. -#undef CHECK_ALLOC -#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) - -// Avoid any macros which evaluate their arguments multiple times -#undef min -#undef max - -#define DEF_MIN_MAX( type ) \ - static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ - static inline type max( type x, type y ) { if ( y < x ) return x; return y; } - -DEF_MIN_MAX( int ) -DEF_MIN_MAX( unsigned ) -DEF_MIN_MAX( long ) -DEF_MIN_MAX( unsigned long ) -DEF_MIN_MAX( float ) -DEF_MIN_MAX( double ) - -#undef DEF_MIN_MAX - -/* -// using const references generates crappy code, and I am currenly only using these -// for built-in types, so they take arguments by value - -// TODO: remove -inline int min( int x, int y ) -template -inline T min( T x, T y ) -{ - if ( x < y ) - return x; - return y; -} - -template -inline T max( T x, T y ) -{ - if ( x < y ) - return y; - return x; -} -*/ - -// TODO: good idea? bad idea? -#undef byte -#define byte byte_ -typedef unsigned char byte; - -// deprecated -#define BLARGG_CHECK_ALLOC CHECK_ALLOC -#define BLARGG_RETURN_ERR RETURN_ERR - -// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check -#ifdef BLARGG_SOURCE_BEGIN - #include BLARGG_SOURCE_BEGIN -#endif - -#endif diff --git a/source/snes9x/apu/license.txt b/source/snes9x/apu/license.txt deleted file mode 100644 index 5faba9d..0000000 --- a/source/snes9x/apu/license.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/source/snes9x/apu/resampler.h b/source/snes9x/apu/resampler.h deleted file mode 100644 index c942bf3..0000000 --- a/source/snes9x/apu/resampler.h +++ /dev/null @@ -1,161 +0,0 @@ -/* Simple resampler based on bsnes's ruby audio library */ - -#ifndef __RESAMPLER_H -#define __RESAMPLER_H - -#include "ring_buffer.h" - -#undef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#undef CLAMP -#undef short_clamp -#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) -#define short_clamp(n) ((short) CLAMP((n), -32768, 32767)) - -class Resampler : public ring_buffer -{ - protected: - - double r_step; - double r_frac; - int r_left[4], r_right[4]; - - double - hermite (double mu1, double a, double b, double c, double d) - { - const double tension = 0.0; //-1 = low, 0 = normal, 1 = high - const double bias = 0.0; //-1 = left, 0 = even, 1 = right - - double mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1 + bias) * (1 - tension) / 2; - m0 += (c - b) * (1 - bias) * (1 - tension) / 2; - m1 = (c - b) * (1 + bias) * (1 - tension) / 2; - m1 += (d - c) * (1 - bias) * (1 - tension) / 2; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - } - - public: - Resampler (int num_samples) : ring_buffer (num_samples << 1) - { - r_frac = 0.0; - } - - ~Resampler () - { - } - - void - time_ratio (double ratio) - { - r_step = ratio; - clear (); - } - - void - clear (void) - { - ring_buffer::clear (); - r_frac = 0; - r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; - r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; - } - - void - read (short *data, int num_samples) - { - int i_position = start >> 1; - short *internal_buffer = (short *) buffer; - int o_position = 0; - int consumed = 0; - - while (o_position < num_samples && consumed < buffer_size) - { - int s_left = internal_buffer[i_position]; - int s_right = internal_buffer[i_position + 1]; - - if (r_step == 1.0) - { - data[o_position] = (short) s_left; - data[o_position + 1] = (short) s_right; - - o_position += 2; - i_position = (i_position + 2) % (buffer_size >> 1); - consumed += 2; - - continue; - } - - r_left [0] = r_left [1]; - r_left [1] = r_left [2]; - r_left [2] = r_left [3]; - r_left [3] = s_left; - - r_right[0] = r_right[1]; - r_right[1] = r_right[2]; - r_right[2] = r_right[3]; - r_right[3] = s_right; - - while (r_frac <= 1.0 && o_position < num_samples) - { - data[o_position] = short_clamp (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3])); - data[o_position + 1] = short_clamp (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3])); - - o_position += 2; - - r_frac += r_step; - } - - if (r_frac > 1.0) - { - r_frac -= 1.0; - i_position = (i_position + 2) % (buffer_size >> 1); - consumed += 2; - } - } - - size -= consumed << 1; - start = (start + (consumed << 1)) % buffer_size; - } - - bool - push (short *src, int num_samples) - { - if (max_write () < num_samples) - return false; - - ring_buffer::push ((unsigned char *) src, num_samples << 1); - - return true; - } - - int - max_write (void) - { - return space_empty () >> 1; - } - - void - resize (int num_samples) - { - ring_buffer::resize (num_samples << 1); - } - - int - avail (void) - { - return (int) floor (((size >> 2) - r_frac) / r_step) * 2; - } -}; - -#endif /* __RESAMPLER_H */ diff --git a/source/snes9x/apu/ring_buffer.h b/source/snes9x/apu/ring_buffer.h deleted file mode 100644 index b743c47..0000000 --- a/source/snes9x/apu/ring_buffer.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Simple byte-based ring buffer. Licensed under public domain (C) BearOso. */ - -#ifndef __RING_BUFFER_H -#define __RING_BUFFER_H - -#include - -#undef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -class ring_buffer -{ -protected: - int size; - int buffer_size; - int start; - unsigned char *buffer; - -public: - ring_buffer (int buffer_size) - { - this->buffer_size = buffer_size; - buffer = new unsigned char[this->buffer_size]; - memset (buffer, 0, this->buffer_size); - - size = 0; - start = 0; - } - - ~ring_buffer (void) - { - delete[] buffer; - } - - bool - push (unsigned char *src, int bytes) - { - if (space_empty () < bytes) - return false; - - int end = (start + size) % buffer_size; - int first_write_size = MIN (bytes, buffer_size - end); - - memcpy (buffer + end, src, first_write_size); - - if (bytes > first_write_size) - memcpy (buffer, src + first_write_size, bytes - first_write_size); - - size += bytes; - - return true; - } - - bool - pull (unsigned char *dst, int bytes) - { - if (space_filled () < bytes) - return false; - - memcpy (dst, buffer + start, MIN (bytes, buffer_size - start)); - - if (bytes > (buffer_size - start)) - memcpy (dst + (buffer_size - start), buffer, bytes - (buffer_size - start)); - - start = (start + bytes) % buffer_size; - size -= bytes; - - return true; - } - - inline int - space_empty (void) - { - return buffer_size - size; - } - - inline int - space_filled (void) - { - return size; - } - - void - clear (void) - { - start = 0; - size = 0; - memset (buffer, 0, buffer_size); - } - - void - resize (int size) - { - delete[] buffer; - buffer_size = size; - buffer = new unsigned char[buffer_size]; - memset (buffer, 0, this->buffer_size); - - size = 0; - start = 0; - } - - inline void - cache_silence (void) - { - clear (); - size = buffer_size; - } -}; - -#endif diff --git a/source/snes9x/apudebug.cpp b/source/snes9x/apudebug.cpp new file mode 100644 index 0000000..495979a --- /dev/null +++ b/source/snes9x/apudebug.cpp @@ -0,0 +1,509 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#include "snes9x.h" +#include "spc700.h" +#include "apu.h" +#include "soundux.h" +#include "cpuexec.h" + +#ifdef DEBUGGER +extern int32 env_counter_table[32]; + +FILE *apu_trace = NULL; + +static char *S9xMnemonics [256] = { + "NOP", "TCALL 0", "SET1 $%02X.0", "BBS $%02X.0,$%04X", + "OR A,$%02X", "OR A,!$%04X", "OR A,(X)", "OR A,[$%02X+X]", + "OR A,#$%02X", "OR $%02X,$%02X", "OR1 C,$%04X.%d", "ASL $%02X", + "MOV !$%04X,Y", "PUSH PSW", "TSET1 !$%04X", "BRK", + "BPL $%04X", "TCALL 1", "CLR1 $%02X.0", "BBC $%02X.0,$%04X", + "OR A,$%02X+X", "OR A,!$%04X+X", "OR A,!$%04X+Y", "OR A,[$%02X]+Y", + "OR $%02X,#$%02X", "OR (X),(Y)", "DECW $%02X", "ASL $%02X+X", + "ASL A", "DEC X", "CMP X,!$%04X", "JMP [!$%04X+X]", + "CLRP", "TCALL 2", "SET1 $%02X.1", "BBS $%02X.1,$%04X", + "AND A,$%02X", "AND A,!$%04X", "AND A,(X)", "AND A,[$%02X+X]", + "AND A,#$%02X", "AND $%02X,$%02X", "OR1 C,/$%04X.%d", "ROL $%02X", + "ROL !$%04X", "PUSH A", "CBNE $%02X,$%04X", "BRA $%04X", + "BMI $%04X", "TCALL 3", "CLR1 $%02X.1", "BBC $%02X.1,$%04X", + "AND A,$%02X+X", "AND A,!$%04X+X", "AND A,!$%04X+Y", "AND A,[$%02X]+Y", + "AND $%02X,#$%02X", "AND (X),(Y)", "INCW $%02X", "ROL $%02X+X", + "ROL A", "INC X", "CMP X,$%02X", "CALL !$%04X", + "SETP", "TCALL 4", "SET1 $%02X.2", "BBS $%02X.2,$%04X", + "EOR A,$%02X", "EOR A,!$%04X", "EOR A,(X)", "EOR A,[$%02X+X]", + "EOR A,#$%02X", "EOR $%02X,$%02X", "AND1 C,$%04X.%d", "LSR $%02X", + "LSR !$%04X", "PUSH X", "TCLR1 !$%04X", "PCALL $%02X", + "BVC $%04X", "TCALL 5", "CLR1 $%02X.2", "BBC $%02X.2,$%04X", + "EOR A,$%02X+X", "EOR A,!$%04X+X", "EOR A,!$%04X+Y", "EOR A,[$%02X]+Y", + "EOR $%02X,#$%02X", "EOR (X),(Y)", "CMPW YA,$%02X", "LSR $%02X+X", + "LSR A", "MOV X,A", "CMP Y,!$%04X", "JMP !$%04X", + "CLRC", "TCALL 6", "SET1 $%02X.3", "BBS $%02X.3,$%04X", + "CMP A,$%02X", "CMP A,!$%04X", "CMP A,(X)", "CMP A,[$%02X+X]", + "CMP A,#$%02X", "CMP $%02X,$%02X", "AND1 C,/$%04X.%d", "ROR $%02X", + "ROR !$%04X", "PUSH Y", "DBNZ $%02X,$%04X", "RET", + "BVS $%04X", "TCALL 7", "CLR1 $%02X.3", "BBC $%02X.3,$%04X", + "CMP A,$%02X+X", "CMP A,!$%04X+X", "CMP A,!$%04X+Y", "CMP A,[$%02X]+Y", + "CMP $%02X,#$%02X", "CMP (X),(Y)", "ADDW YA,$%02X", "ROR $%02X+X", + "ROR A", "MOV A,X", "CMP Y,$%02X", "RET1", + "SETC", "TCALL 8", "SET1 $%02X.4", "BBS $%02X.4,$%04X", + "ADC A,$%02X", "ADC A,!$%04X", "ADC A,(X)", "ADC A,[$%02X+X]", + "ADC A,#$%02X", "ADC $%02X,$%02X", "EOR1 C,$%04X.%d", "DEC $%02X", + "DEC !$%04X", "MOV Y,#$%02X", "POP PSW", "MOV $%02X,#$%02X", + "BCC $%04X", "TCALL 9", "CLR1 $%02X.4", "BBC $%02X.4,$%04X", + "ADC A,$%02X+X", "ADC A,!$%04X+X", "ADC A,!$%04X+Y", "ADC A,[$%02X]+Y", + "ADC $%02X,#$%02X", "ADC (X),(Y)", "SUBW YA,$%02X", "DEC $%02X+X", + "DEC A", "MOV X,SP", "DIV YA,X", "XCN A", + "EI", "TCALL 10", "SET1 $%02X.5", "BBS $%02X.5,$%04X", + "SBC A,$%02X", "SBC A,!$%04X", "SBC A,(X)", "SBC A,[$%02X+X]", + "SBC A,#$%02X", "SBC $%02X,$%02X", "MOV1 C,$%04X.%d", "INC $%02X", + "INC !$%04X", "CMP Y,#$%02X", "POP A", "MOV (X)+,A", + "BCS $%04X", "TCALL 11", "CLR1 $%02X.5", "BBC $%02X.5,$%04X", + "SBC A,$%02X+X", "SBC A,!$%04X+X", "SBC A,!$%04X+Y", "SBC A,[$%02X]+Y", + "SBC $%02X,#$%02X", "SBC (X),(Y)", "MOVW YA,$%02X", "INC $%02X+X", + "INC A", "MOV SP,X", "DAS A", "MOV A,(X)+", + "DI", "TCALL 12", "SET1 $%02X.6", "BBS $%02X.6,$%04X", + "MOV $%02X,A", "MOV !$%04X,A", "MOV (X),A", "MOV [$%02X+X],A", + "CMP X,#$%02X", "MOV !$%04X,X", "MOV1 $%04X.%d,C", "MOV $%02X,Y", + "ASL !$%04X", "MOV X,#$%02X", "POP X", "MUL YA", + "BNE $%04X", "TCALL 13", "CLR1 $%02X.6", "BBC $%02X.6,$%04X", + "MOV $%02X+X,A", "MOV !$%04X+X,A", "MOV !$%04X+Y,A", "MOV [$%02X]+Y,A", + "MOV $%02X,X", "MOV $%02X+Y,X", "MOVW $%02X,YA", "MOV $%02X+X,Y", + "DEC Y", "MOV A,Y", "CBNE $%02X+X,$%04X", "DAA A", + "CLRV", "TCALL 14", "SET1 $%02X.7", "BBS $%02X.7,$%04X", + "MOV A,$%02X", "MOV A,!$%04X", "MOV A,(X)", "MOV A,[$%02X+X]", + "MOV A,#$%02X", "MOV X,!$%04X", "NOT1 $%04X.%d", "MOV Y,$%02X", + "MOV Y,!$%04X", "NOTC", "POP Y", "SLEEP", + "BEQ $%04X", "TCALL 15", "CLR1 $%02X.7", "BBC $%02X.7,$%04X", + "MOV A,$%02X+X", "MOV A,!$%04X+X", "MOV A,!$%04X+Y", "MOV A,[$%02X]+Y", + "MOV X,$%02X", "MOV X,$%02X+Y", "MOV $%02X,$%02X", "MOV Y,$%02X+X", + "INC Y", "MOV Y,A", "DBNZ Y,$%04X", "STOP" +}; + +#undef ABS + +#define DP 0 +#define ABS 1 +#define IM 2 +#define DP2DP 3 +#define DPIM 4 +#define DPREL 5 +#define ABSBIT 6 +#define REL 7 + +static uint8 Modes [256] = { + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, DP2DP, ABSBIT, DP, + ABS, IM, ABS, IM, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DPIM, IM, DP, DP, + IM, IM, ABS, ABS, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, DP2DP, ABSBIT, DP, + ABS, IM, DPREL, REL, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DPIM, IM, DP, DP, + IM, IM, DP, ABS, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, DP2DP, ABSBIT, DP, + ABS, IM, ABS, DP, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DPIM, IM, DP, DP, + IM, IM, ABS, ABS, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, DP2DP, ABSBIT, DP, + ABS, IM, DPREL, IM, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DPIM, IM, DP, DP, + IM, IM, DP, IM, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, DP2DP, ABSBIT, DP, + ABS, DP, IM, DPIM, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DPIM, IM, DP, DP, + IM, IM, IM, IM, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, DP2DP, ABSBIT, DP, + ABS, DP, IM, IM, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DPIM, IM, DP, DP, + IM, IM, IM, IM, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, ABS, ABSBIT, DP, + ABS, DP, IM, IM, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DP, DP, DP, DP, + IM, IM, DPREL, IM, + IM, IM, DP, DPREL, + DP, ABS, IM, DP, + DP, ABS, ABSBIT, DP, + ABS, IM, IM, IM, + REL, IM, DP, DPREL, + DP, ABS, ABS, DP, + DP, DP, DP2DP, DP, + IM, IM, REL, IM +}; + +static uint8 ModesToBytes [] = { + 2, 3, 1, 3, 3, 3, 3, 2 +}; + +static FILE *SoundTracing = NULL; + +void S9xOpenCloseSoundTracingFile (bool8 open) +{ + if (open && !SoundTracing) + { + SoundTracing = fopen ("sound_trace.log", "w"); + } + else + if (!open && SoundTracing) + { + fclose (SoundTracing); + SoundTracing = NULL; + } +} + +void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0, + int i4 = 0, int i5 = 0, int i6 = 0, int i7 = 0) +{ + fprintf (SoundTracing, s, i1, i2, i3, i4, i5, i6, i7); +} + +int S9xTraceAPU () +{ + char buffer [200]; + + uint8 b = S9xAPUOPrint (buffer, IAPU.PC - IAPU.RAM); + if (apu_trace == NULL) + apu_trace = fopen ("apu_trace.log", "wb"); + + fprintf (apu_trace, "%s\n", buffer); + return (b); +} + +int S9xAPUOPrint (char *buffer, uint16 Address) +{ + char mnem [100]; + uint8 *p = IAPU.RAM + Address; + int mode = Modes [*p]; + int bytes = ModesToBytes [mode]; + + switch (bytes) + { + case 1: + sprintf (buffer, "%04X %02X ", p - IAPU.RAM, *p); + break; + case 2: + sprintf (buffer, "%04X %02X %02X ", p - IAPU.RAM, *p, + *(p + 1)); + break; + case 3: + sprintf (buffer, "%04X %02X %02X %02X ", p - IAPU.RAM, *p, + *(p + 1), *(p + 2)); + break; + } + + switch (mode) + { + case DP: + sprintf (mnem, S9xMnemonics [*p], *(p + 1)); + break; + case ABS: + sprintf (mnem, S9xMnemonics [*p], *(p + 1) + (*(p + 2) << 8)); + break; + case IM: + sprintf (mnem, S9xMnemonics [*p]); + break; + case DP2DP: + sprintf (mnem, S9xMnemonics [*p], *(p + 2), *(p + 1));; + break; + case DPIM: + sprintf (mnem, S9xMnemonics [*p], *(p + 2), *(p + 1));; + break; + case DPREL: + sprintf (mnem, S9xMnemonics [*p], *(p + 1), + (int) (p + 3 - IAPU.RAM) + (signed char) *(p + 2)); + break; + case ABSBIT: + sprintf (mnem, S9xMnemonics [*p], (*(p + 1) + (*(p + 2) << 8)) & 0x1fff, + *(p + 2) >> 5); + break; + case REL: + sprintf (mnem, S9xMnemonics [*p], + (int) (p + 2 - IAPU.RAM) + (signed char) *(p + 1)); + break; + } + + sprintf (buffer, "%s %-20s A:%02X X:%02X Y:%02X S:%02X P:%c%c%c%c%c%c%c%c %03ld %04ld %04d", + buffer, mnem, + APURegisters.YA.B.A, APURegisters.X, APURegisters.YA.B.Y, + APURegisters.S, + APUCheckNegative () ? 'N' : 'n', + APUCheckOverflow () ? 'V' : 'v', + APUCheckDirectPage () ? 'P' : 'p', + APUCheckBreak () ? 'B' : 'b', + APUCheckHalfCarry () ? 'H' : 'h', + APUCheckInterrupt () ? 'I' : 'i', + APUCheckZero () ? 'Z' : 'z', + APUCheckCarry () ? 'C' : 'c', + CPU.V_Counter, + CPU.Cycles, + APU.Cycles >> SNES_APU_ACCURACY); + + return (bytes); +} + +const char *as_binary (uint8 data) +{ + static char buf [9]; + + for (int i = 7; i >= 0; i--) + buf [7 - i] = ((data & (1 << i)) != 0) + '0'; + + buf [8] = 0; + return (buf); +} + +void S9xPrintAPUState () +{ + printf ("Master volume left: %d, right: %d\n", + SoundData.master_volume_left, SoundData.master_volume_right); + printf ("Echo: %s %s, Delay: %d Feedback: %d Left: %d Right: %d\n", + SoundData.echo_write_enabled ? "on" : "off", + as_binary (SoundData.echo_enable), + SoundData.echo_buffer_size >> 9, + SoundData.echo_feedback, SoundData.echo_volume_left, + SoundData.echo_volume_right); + + printf ("Noise: %s, Frequency: %d, Pitch mod: %s\n", as_binary (APU.DSP [APU_NON]), + env_counter_table [APU.DSP [APU_FLG] & 0x1f], + as_binary (SoundData.pitch_mod)); + extern int FilterTaps [8]; + + printf ("Filter: "); + for (int i = 0; i < 8; i++) + printf ("%03d, ", FilterTaps [i]); + printf ("\n"); + for (int J = 0; J < 8; J++) + { + register Channel *ch = &SoundData.channels[J]; + + printf ("%d: ", J); + if (ch->state == SOUND_SILENT) + { + printf ("off\n"); + } + else + if (!(so.sound_switch & (1 << J))) + printf ("muted by user using channel on/off toggle\n"); + else + { + int freq = ch->hertz; + if (APU.DSP [APU_NON] & (1 << J)) //ch->type == SOUND_NOISE) + { + freq = env_counter_table [APU.DSP [APU_FLG] & 0x1f]; + printf ("noise, "); + } + else + printf ("sample %d, ", APU.DSP [APU_SRCN + J * 0x10]); + + printf ("freq: %d", freq); + if (J > 0 && (SoundData.pitch_mod & (1 << J)) && + ch->type != SOUND_NOISE) + { + printf ("(mod), "); + } + else + printf (", "); + + printf ("left: %d, right: %d, ", + ch->volume_left, ch->volume_right); + + static char* envelope [] = + { + "silent", "attack", "decay", "sustain", "release", "gain", + "inc_lin", "inc_bent", "dec_lin", "dec_exp" + }; + printf ("%s envx: %d, target: %d, %ld", ch->state > 9 ? "???" : envelope [ch->state], + ch->envx, ch->envx_target, ch->erate); + printf ("\n"); + } + } +} +#endif + + diff --git a/source/snes9x/reader.cpp b/source/snes9x/apumem.h similarity index 66% rename from source/snes9x/reader.cpp rename to source/snes9x/apumem.h index d69b529..df9a3f1 100644 --- a/source/snes9x/reader.cpp +++ b/source/snes9x/apumem.h @@ -158,180 +158,153 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ -// Abstract the details of reading from zip files versus FILE *'s. -#include -#ifdef UNZIP_SUPPORT -#include "unzip.h" -#endif -#include "snes9x.h" -#include "reader.h" +#ifndef _apumemory_h_ +#define _apumemory_h_ +START_EXTERN_C +extern uint8 APUROM[64]; +END_EXTERN_C -// Generic constructor/destructor - -Reader::Reader (void) +static INLINE uint8 apu_get_reg (uint8 Address) { - return; -} - -Reader::~Reader (void) -{ - return; -} - -// Generic getline function, based on gets. Reimlpement if you can do better. - -char * Reader::getline (void) -{ - bool eof; - std::string ret; - - ret = getline(eof); - if (ret.size() == 0 && eof) - return (NULL); - - return (strdup(ret.c_str())); -} - -std::string Reader::getline (bool &eof) -{ - char buf[1024]; - std::string ret; - - eof = false; - ret.clear(); - - do + switch (Address) { - if (gets(buf, sizeof(buf)) == NULL) - { - eof = true; - break; - } + case 0xf0: // -w TEST + return 0; - ret.append(buf); - } - while (*ret.rbegin() != '\n'); + case 0xf1: // -w CONTROL + return 0; - return (ret); -} + case 0xf2: // rw DSPADDR + return (IAPU.RAM[Address]); -// snes9x.h STREAM reader + case 0xf3: // rw DSPDATA + return (S9xGetAPUDSP()); -fReader::fReader (STREAM f) -{ - fp = f; -} + case 0xf4: // r- CPUI0 + case 0xf5: // r- CPUI1 + case 0xf6: // r- CPUI2 + case 0xf7: // r- CPUI3 + #ifdef SPC700_SHUTDOWN + IAPU.WaitAddress2 = IAPU.WaitAddress1; + IAPU.WaitAddress1 = IAPU.PC; + #endif + return (IAPU.RAM[Address]); -fReader::~fReader (void) -{ - return; -} + case 0xf8: // rw - Normal RAM + case 0xf9: // rw - Normal RAM + return (IAPU.RAM[Address]); -int fReader::get_char (void) -{ - return (GETC_STREAM(fp)); -} + case 0xfa: // -w T0TARGET + case 0xfb: // -w T1TARGET + case 0xfc: // -w T2TARGET + return 0; -char * fReader::gets (char *buf, size_t len) -{ - return (GETS_STREAM(buf, len, fp)); -} - -size_t fReader::read (char *buf, size_t len) -{ - return (READ_STREAM(buf, len, fp)); -} - -// unzip reader - -#ifdef UNZIP_SUPPORT - -unzReader::unzReader (unzFile &v) -{ - file = v; - head = NULL; - numbytes = 0; -} - -unzReader::~unzReader (void) -{ - return; -} - -int unzReader::get_char (void) -{ - unsigned char c; - - if (numbytes <= 0) - { - numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ); - if (numbytes <= 0) - return (EOF); - head = buffer; + case 0xfd: // r- T0OUT + case 0xfe: // r- T1OUT + case 0xff: // r- T2OUT + #ifdef SPC700_SHUTDOWN + IAPU.WaitAddress2 = IAPU.WaitAddress1; + IAPU.WaitAddress1 = IAPU.PC; + #endif + uint8 t = IAPU.RAM[Address] & 0xF; + IAPU.RAM[Address] = 0; + return (t); } - c = *head; - head++; - numbytes--; - - return ((int) c); + return 0; } -char * unzReader::gets (char *buf, size_t len) +static INLINE void apu_set_reg (uint8 byte, uint8 Address) { - size_t i; - int c; - - for (i = 0; i < len - 1; i++) + switch (Address) { - c = get_char(); - if (c == EOF) - { - if (i == 0) - return (NULL); - break; - } + case 0xf0: // -w TEST + //printf("Write %02X to APU 0xF0!\n", byte); + return; - buf[i] = (char) c; - if (buf[i] == '\n') - break; + case 0xf1: // -w CONTROL + S9xSetAPUControl(byte); + return; + + case 0xf2: // rw DSPADDR + IAPU.RAM[Address] = byte; + return; + + case 0xf3: // rw DSPDATA + S9xSetAPUDSP(byte); + return; + + case 0xf4: // -w CPUO0 + case 0xf5: // -w CPUO1 + case 0xf6: // -w CPUO2 + case 0xf7: // -w CPUO3 + APU.OutPorts[Address - 0xf4] = byte; + return; + + case 0xf8: // rw - Normal RAM + case 0xf9: // rw - Normal RAM + IAPU.RAM[Address] = byte; + return; + + case 0xfa: // -w T0TARGET + case 0xfb: // -w T1TARGET + case 0xfc: // -w T2TARGET + IAPU.RAM[Address] = byte; + if (byte == 0) + APU.TimerTarget[Address - 0xfa] = 0x100; + else + APU.TimerTarget[Address - 0xfa] = byte; + return; + + case 0xfd: // r- T0OUT + case 0xfe: // r- T1OUT + case 0xff: // r- T2OUT + return; } - - buf[i] = '\0'; - - return (buf); } -size_t unzReader::read (char *buf, size_t len) +INLINE uint8 S9xAPUGetByteZ (uint8 Address) { - if (len == 0) - return (len); - - if (len <= numbytes) - { - memcpy(buf, head, len); - numbytes -= len; - head += len; - return (len); - } - - size_t numread = 0; - if (numbytes > 0) - { - memcpy(buf, head, numbytes); - numread += numbytes; - head = NULL; - numbytes = 0; - } - - int l = unzReadCurrentFile(file, buf + numread, len - numread); - if (l > 0) - numread += l; - - return (numread); + if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) + return (apu_get_reg(Address)); + else + return (IAPU.DirectPage[Address]); } -#endif +INLINE void S9xAPUSetByteZ (uint8 byte, uint8 Address) +{ + if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) + apu_set_reg(byte, Address); + else + IAPU.DirectPage[Address] = byte; +} + +INLINE uint8 S9xAPUGetByte (uint32 Address) +{ + Address &= 0xffff; + if (Address <= 0xff && Address >= 0xf0) + return (apu_get_reg(Address & 0xff)); + else + return (IAPU.RAM[Address]); +} + +INLINE void S9xAPUSetByte (uint8 byte, uint32 Address) +{ + Address &= 0xffff; + if (Address <= 0xff && Address >= 0xf0) + apu_set_reg(byte, Address & 0xff); + else + if (Address < 0xffc0) + IAPU.RAM[Address] = byte; + else + { + APU.ExtraRAM[Address - 0xffc0] = byte; + if (!APU.ShowROM) + IAPU.RAM[Address] = byte; + } +} + +#endif // _apumemory_h_ diff --git a/source/snes9x/bsx.cpp b/source/snes9x/bsx.cpp index 8b2d23a..e594ae3 100644 --- a/source/snes9x/bsx.cpp +++ b/source/snes9x/bsx.cpp @@ -158,47 +158,49 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ -// Dreamer Nom wrote: + + + +// Anonymous wrote: // Large thanks to John Weidman for all his initial research // Thanks to Seph3 for his modem notes +#include -#include "snes9x.h" #include "memmap.h" #include "display.h" +#include "bsx.h" -//#define BSX_DEBUG +//#define BSX_DEBUG -#define BIOS_SIZE 0x100000 -#define FLASH_SIZE 0x200000 -#define PSRAM_SIZE 0x80000 +#define BIOS_SIZE 0x100000 +#define FLASH_SIZE 0x200000 +#define PSRAM_SIZE 0x80000 -#define Map Memory.Map -#define BlockIsRAM Memory.BlockIsRAM -#define BlockIsROM Memory.BlockIsROM -#define RAM Memory.RAM -#define SRAM Memory.SRAM -#define PSRAM Memory.BSRAM -#define BIOSROM Memory.BIOSROM -#define MAP_BSX Memory.MAP_BSX -#define MAP_CPU Memory.MAP_CPU -#define MAP_PPU Memory.MAP_PPU -#define MAP_NONE Memory.MAP_NONE - -#define BSXPPUBASE 0x2180 +#define Map Memory.Map +#define BlockIsRAM Memory.BlockIsRAM +#define BlockIsROM Memory.BlockIsROM +#define RAM Memory.RAM +#define SRAM Memory.SRAM +#define PSRAM Memory.BSRAM +#define BIOSROM Memory.BIOSROM +#define MAP_BSX Memory.MAP_BSX +#define MAP_CPU Memory.MAP_CPU +#define MAP_PPU Memory.MAP_PPU +#define MAP_NONE Memory.MAP_NONE struct SBSX_RTC { - int hours; - int minutes; - int seconds; - int ticks; + int hours; + int minutes; + int seconds; + int ticks; }; -static struct SBSX_RTC BSX_RTC; +struct SBSX_RTC BSX_RTC; // flash card vendor information -static const uint8 flashcard[20] = +const uint8 flashcard[20] = { 0x4D, 0x00, 0x50, 0x00, // vendor id 0x00, 0x00, // ? @@ -207,7 +209,7 @@ static const uint8 flashcard[20] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const uint8 init2192[32] = // FIXME +const uint8 init2192[32] = // FIXME { 00, 00, 00, 00, 00, // unknown 01, 01, 00, 00, 00, @@ -219,29 +221,29 @@ static const uint8 init2192[32] = // FIXME 00, 00, 00, 00, 00, 00, 00, 00, 00 }; -static bool8 FlashMode; -static uint32 FlashSize; -static uint8 *MapROM, *FlashROM; +bool8 FlashMode; +uint32 FlashSize; +uint8 *MapROM, *FlashROM; -static void BSX_Map_SNES (void); -static void BSX_Map_LoROM (void); -static void BSX_Map_HiROM (void); -static void BSX_Map_MMC (void); -static void BSX_Map_FlashIO (void); -static void BSX_Map_SRAM (void); -static void BSX_Map_PSRAM (void); -static void BSX_Map_BIOS (void); -static void BSX_Map_RAM (void); -static void BSX_Map_Dirty (void); -static void BSX_Map (void); -static void BSX_Set_Bypass_FlashIO (uint16, uint8); -static uint8 BSX_Get_Bypass_FlashIO (uint16); -static bool8 BSX_LoadBIOS (void); -static void map_psram_mirror_sub (uint32); -static int is_bsx (unsigned char *); +static void BSX_Map_SNES(void); +static void BSX_Map_LoROM(void); +static void BSX_Map_HiROM(void); +static void BSX_Map_MMC(void); +static void BSX_Map_FlashIO(void); +static void BSX_Map_SRAM(void); +static void BSX_Map_PSRAM(void); +static void BSX_Map_BIOS(void); +static void BSX_Map_RAM(void); +static void BSX_Map_Dirty(void); +static void BSX_Map(void); +static void BSX_Set_Bypass_FlashIO(uint16, uint8); +static uint8 BSX_Get_Bypass_FlashIO(uint16); +static bool8 BSX_LoadBIOS(void); +static void map_psram_mirror_sub(uint32); +static int is_bsx(unsigned char *); -static void BSX_Map_SNES (void) +static void BSX_Map_SNES(void) { // These maps will be partially overwritten @@ -264,7 +266,7 @@ static void BSX_Map_SNES (void) } } -static void BSX_Map_LoROM (void) +static void BSX_Map_LoROM(void) { // These maps will be partially overwritten @@ -298,7 +300,7 @@ static void BSX_Map_LoROM (void) } } -static void BSX_Map_HiROM (void) +static void BSX_Map_HiROM(void) { // These maps will be partially overwritten @@ -327,7 +329,7 @@ static void BSX_Map_HiROM (void) } } -static void BSX_Map_MMC (void) +static void BSX_Map_MMC(void) { int c; @@ -339,7 +341,7 @@ static void BSX_Map_MMC (void) } } -static void BSX_Map_FlashIO (void) +static void BSX_Map_FlashIO(void) { int c; @@ -355,7 +357,7 @@ static void BSX_Map_FlashIO (void) } } -static void BSX_Map_SRAM (void) +static void BSX_Map_SRAM(void) { int c; @@ -368,7 +370,7 @@ static void BSX_Map_SRAM (void) } } -static void map_psram_mirror_sub (uint32 bank) +static void map_psram_mirror_sub(uint32 bank) { int i, c; @@ -405,7 +407,7 @@ static void map_psram_mirror_sub (uint32 bank) } } -static void BSX_Map_PSRAM (void) +static void BSX_Map_PSRAM(void) { int c; @@ -443,7 +445,7 @@ static void BSX_Map_PSRAM (void) map_psram_mirror_sub(0x60); } -static void BSX_Map_BIOS (void) +static void BSX_Map_BIOS(void) { int i,c; @@ -476,7 +478,7 @@ static void BSX_Map_BIOS (void) } } -static void BSX_Map_RAM (void) +static void BSX_Map_RAM(void) { int c; @@ -492,7 +494,7 @@ static void BSX_Map_RAM (void) } } -static void BSX_Map_Dirty (void) +static void BSX_Map_Dirty(void) { // for the quick bank change @@ -525,7 +527,7 @@ static void BSX_Map_Dirty (void) } } -static void BSX_Map (void) +static void BSX_Map(void) { #ifdef BSX_DEBUG printf("BS: Remapping\n"); @@ -580,20 +582,20 @@ static void BSX_Map (void) Memory.map_WriteProtectROM(); } -static uint8 BSX_Get_Bypass_FlashIO (uint16 offset) +static uint8 BSX_Get_Bypass_FlashIO(uint16 offset) { if (BSX.MMC[0x02]) - return (MapROM[offset]); + return MapROM[offset]; else { if (offset < 0x8000) - return (MapROM[offset]); + return MapROM[offset]; else - return (MapROM[offset - 0x8000]); + return MapROM[offset - 0x8000]; } } -static void BSX_Set_Bypass_FlashIO (uint16 offset, uint8 byte) +static void BSX_Set_Bypass_FlashIO(uint16 offset, uint8 byte) { if (BSX.MMC[0x02]) MapROM[offset] = byte; @@ -606,7 +608,7 @@ static void BSX_Set_Bypass_FlashIO (uint16 offset, uint8 byte) } } -uint8 S9xGetBSX (uint32 address) +uint8 S9xGetBSX(uint32 address) { uint8 bank = (address >> 16) & 0xFF; uint16 offset = address & 0xFFFF; @@ -614,7 +616,7 @@ uint8 S9xGetBSX (uint32 address) // MMC if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) - return (BSX.MMC[bank]); + return BSX.MMC[bank]; // Flash IO if (bank == 0xC0) @@ -652,10 +654,10 @@ uint8 S9xGetBSX (uint32 address) } } - return (t); + return t; } -void S9xSetBSX (uint8 byte, uint32 address) +void S9xSetBSX(uint8 byte, uint32 address) { uint8 bank = (address >> 16) & 0xFF; uint16 offset = address & 0xFFFF; @@ -774,207 +776,210 @@ void S9xSetBSX (uint8 byte, uint32 address) } } -uint8 S9xGetBSXPPU (uint16 address) +uint8 S9xGetBSXPPU(uint16 address) { - uint8 t; + uint8 t = 0; - // known read registers - switch (address) + if (address >= 0x2188 && address <= 0x219F) { - // Test register low? (r/w) - case 0x2188: - t = BSX.PPU[0x2188 - BSXPPUBASE]; - break; + // known read registers + switch(address) + { + // Test register low? (r/w) + case 0x2188: + t = BSX.PPU[0x2188]; + break; - // Test register high? (r/w) - case 0x2189: - t = BSX.PPU[0x2189 - BSXPPUBASE]; - break; + // Test register high? (r/w) + case 0x2189: + t = BSX.PPU[0x2189]; + break; - case 0x218A: - t = BSX.PPU[0x218A - BSXPPUBASE]; - break; + case 0x218A: + t = BSX.PPU[0x218A]; + break; - case 0x218C: - t = BSX.PPU[0x218C - BSXPPUBASE]; - break; + case 0x218C: + t = BSX.PPU[0x218C]; + break; - // Transmission number low? (r/w) - case 0x218E: - t = BSX.PPU[0x218E - BSXPPUBASE]; - break; + // Transmission number low? (r/w) + case 0x218E: + t = BSX.PPU[0x218E]; + break; - // Transmission number high? (r/w) - case 0x218F: - t = BSX.PPU[0x218F - BSXPPUBASE]; - break; + // Transmission number high? (r/w) + case 0x218F: + t = BSX.PPU[0x218F]; + break; - // Status register? (r) - case 0x2190: - t = BSX.PPU[0x2190 - BSXPPUBASE]; - break; + // Status register? (r) + case 0x2190: + t = BSX.PPU[0x2190]; + break; - // Data register? (r/w) - case 0x2192: - t = BSX.PPU[0x2192 - BSXPPUBASE]; + // Data register? (r/w) + case 0x2192: + t = BSX.PPU[0x2192]; - // test - t = BSX.test2192[BSX.out_index++]; - if (BSX.out_index == 32) + // test + t = BSX.test2192[BSX.out_index++]; + if (BSX.out_index == 32) + BSX.out_index = 0; + + BSX_RTC.ticks++; + if (BSX_RTC.ticks >= 1000) + { + BSX_RTC.ticks = 0; + BSX_RTC.seconds++; + } + if (BSX_RTC.seconds >= 60) + { + BSX_RTC.seconds = 0; + BSX_RTC.minutes++; + } + if (BSX_RTC.minutes >= 60) + { + BSX_RTC.minutes = 0; + BSX_RTC.hours++; + } + if (BSX_RTC.hours >= 24) + BSX_RTC.hours = 0; + + BSX.test2192[10] = BSX_RTC.seconds; + BSX.test2192[11] = BSX_RTC.minutes; + BSX.test2192[12] = BSX_RTC.hours; + + break; + + // Transmission status? (r/w) + case 0x2193: + // Data ready when bits 2/3 clear? + t = BSX.PPU[0x2193] & ~0x0C; + break; + + // Reset? (r/w) + case 0x2194: + t = BSX.PPU[0x2194]; + break; + + // Unknown (r) + case 0x2196: + t = BSX.PPU[0x2196]; + break; + + // Unknown (r/w) + case 0x2197: + t = BSX.PPU[0x2197]; + break; + + // Modem protocol? (r/w) + case 0x2199: + t = BSX.PPU[0x2199]; + break; + + default: + t = OpenBus; + break; + } + } + + return t; +} + +void S9xSetBSXPPU(uint8 byte, uint16 address) +{ + if (address >= 0x2188 && address <= 0x219F) + { + // known write registers + switch(address) + { + // Test register low? (r/w) + case 0x2188: + BSX.PPU[0x2188] = byte; + break; + + // Test register high? (r/w) + case 0x2189: + BSX.PPU[0x2189] = byte; + break; + + case 0x218A: + BSX.PPU[0x218A] = byte; + break; + + case 0x218B: + BSX.PPU[0x218B] = byte; + break; + + case 0x218C: + BSX.PPU[0x218C] = byte; + break; + + // Transmission number low? (r/w) + case 0x218E: + BSX.PPU[0x218E] = byte; + break; + + // Transmission number high? (r/w) + case 0x218F: + BSX.PPU[0x218F] = byte; + + // ? + BSX.PPU[0x218E] >>= 1; + BSX.PPU[0x218E] = BSX.PPU[0x218F] - BSX.PPU[0x218E]; + BSX.PPU[0x218F] >>= 1; + + BSX.PPU[0x2190] = 0x80; // ? + break; + + // Strobe assert? (w) + case 0x2191: + BSX.PPU[0x2191] = byte; BSX.out_index = 0; + break; - BSX_RTC.ticks++; - if (BSX_RTC.ticks >= 1000) - { - BSX_RTC.ticks = 0; - BSX_RTC.seconds++; - } - if (BSX_RTC.seconds >= 60) - { - BSX_RTC.seconds = 0; - BSX_RTC.minutes++; - } - if (BSX_RTC.minutes >= 60) - { - BSX_RTC.minutes = 0; - BSX_RTC.hours++; - } - if (BSX_RTC.hours >= 24) - BSX_RTC.hours = 0; + // Data register? (r/w) + case 0x2192: + BSX.PPU[0x2192] = 0x01; // ? + BSX.PPU[0x2190] = 0x80; // ? + break; - BSX.test2192[10] = BSX_RTC.seconds; - BSX.test2192[11] = BSX_RTC.minutes; - BSX.test2192[12] = BSX_RTC.hours; + // Transmission status? (r/w) + case 0x2193: + BSX.PPU[0x2193] = byte; + break; - break; + // Reset? (r/w) + case 0x2194: + BSX.PPU[0x2194] = byte; + break; - // Transmission status? (r/w) - case 0x2193: - // Data ready when bits 2/3 clear? - t = BSX.PPU[0x2193 - BSXPPUBASE] & ~0x0C; - break; + // Unknown (r/w) + case 0x2197: + BSX.PPU[0x2197] = byte; + break; - // Reset? (r/w) - case 0x2194: - t = BSX.PPU[0x2194 - BSXPPUBASE]; - break; - - // Unknown (r) - case 0x2196: - t = BSX.PPU[0x2196 - BSXPPUBASE]; - break; - - // Unknown (r/w) - case 0x2197: - t = BSX.PPU[0x2197 - BSXPPUBASE]; - break; - - // Modem protocol? (r/w) - case 0x2199: - t = BSX.PPU[0x2199 - BSXPPUBASE]; - break; - - default: - t = OpenBus; - break; - } - - return (t); -} - -void S9xSetBSXPPU (uint8 byte, uint16 address) -{ - // known write registers - switch (address) - { - // Test register low? (r/w) - case 0x2188: - BSX.PPU[0x2188 - BSXPPUBASE] = byte; - break; - - // Test register high? (r/w) - case 0x2189: - BSX.PPU[0x2189 - BSXPPUBASE] = byte; - break; - - case 0x218A: - BSX.PPU[0x218A - BSXPPUBASE] = byte; - break; - - case 0x218B: - BSX.PPU[0x218B - BSXPPUBASE] = byte; - break; - - case 0x218C: - BSX.PPU[0x218C - BSXPPUBASE] = byte; - break; - - // Transmission number low? (r/w) - case 0x218E: - BSX.PPU[0x218E - BSXPPUBASE] = byte; - break; - - // Transmission number high? (r/w) - case 0x218F: - BSX.PPU[0x218F - BSXPPUBASE] = byte; - - // ? - BSX.PPU[0x218E - BSXPPUBASE] >>= 1; - BSX.PPU[0x218E - BSXPPUBASE] = BSX.PPU[0x218F - BSXPPUBASE] - BSX.PPU[0x218E - BSXPPUBASE]; - BSX.PPU[0x218F - BSXPPUBASE] >>= 1; - - BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; // ? - break; - - // Strobe assert? (w) - case 0x2191: - BSX.PPU[0x2191 - BSXPPUBASE] = byte; - BSX.out_index = 0; - break; - - // Data register? (r/w) - case 0x2192: - BSX.PPU[0x2192 - BSXPPUBASE] = 0x01; // ? - BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; // ? - break; - - // Transmission status? (r/w) - case 0x2193: - BSX.PPU[0x2193 - BSXPPUBASE] = byte; - break; - - // Reset? (r/w) - case 0x2194: - BSX.PPU[0x2194 - BSXPPUBASE] = byte; - break; - - // Unknown (r/w) - case 0x2197: - BSX.PPU[0x2197 - BSXPPUBASE] = byte; - break; - - // Modem protocol? (r/w) - case 0x2199: - // Lots of modem strings written here when - // connection is lost or no uplink established - BSX.PPU[0x2199 - BSXPPUBASE] = byte; - break; + // Modem protocol? (r/w) + case 0x2199: + // Lots of modem strings written here when + // connection is lost or no uplink established + BSX.PPU[0x2199] = byte; + break; + } } } -uint8 * S9xGetBasePointerBSX (uint32 address) +uint8 * S9xGetBasePointerBSX(uint32 address) { - return (MapROM); + return MapROM; } -static bool8 BSX_LoadBIOS (void) +static bool8 BSX_LoadBIOS(void) { -#ifdef GEKKO return FALSE; // We're not loading the BIOS! -#endif - FILE *fp; - char path[PATH_MAX + 1], name[PATH_MAX + 1]; + char path[_MAX_PATH + 1], name[_MAX_PATH + 1]; bool8 r = FALSE; strcpy(path, S9xGetDirectory(BIOS_DIR)); @@ -1007,10 +1012,10 @@ static bool8 BSX_LoadBIOS (void) printf("BS: BIOS not found!\n"); #endif - return (r); + return r; } -void S9xInitBSX (void) +void S9xInitBSX(void) { Settings.BS = FALSE; @@ -1092,7 +1097,7 @@ void S9xInitBSX (void) } } -void S9xResetBSX (void) +void S9xResetBSX(void) { if (Settings.BSXItself) memset(Memory.ROM, 0, FLASH_SIZE); @@ -1144,7 +1149,7 @@ void S9xResetBSX (void) BSX_Map(); } -void S9xBSXPostLoadState (void) +void S9xFixBSXAfterSnapshotLoad(void) { uint8 temp[16]; bool8 pd1, pd2; @@ -1161,30 +1166,34 @@ void S9xBSXPostLoadState (void) BSX.dirty2 = pd2; } -static bool valid_normal_bank (unsigned char bankbyte) +static bool valid_normal_bank(unsigned char bankbyte) { - switch (bankbyte) - { - case 32: case 33: case 48: case 49: - return (true); - break; - } - - return (false); + switch (bankbyte) + { + case 32: case 33: case 48: case 49: + return(true); + break; + } + return(false); } -static int is_bsx (unsigned char *p) +static int is_bsx(unsigned char *p) { - if ((p[26] == 0x33 || p[26] == 0xFF) && (!p[21] || (p[21] & 131) == 128) && valid_normal_bank(p[24])) - { - unsigned char m = p[22]; - - if (!m && !p[23]) - return (2); - - if ((m == 0xFF && p[23] == 0xFF) || (!(m & 0xF) && ((m >> 4) - 1 < 12))) - return (1); - } - - return (0); + if ((p[26] == 0x33 || p[26] == 0xFF) && + (!p[21] || (p[21] & 131) == 128) && + valid_normal_bank(p[24])) + { + unsigned char m = p[22]; + if (!m && !p[23]) + { + return(2); + } + if ((m == 0xFF && p[23] == 0xFF) || + (!(m & 0xF) && ((m >> 4) - 1 < 12))) + { + return(1); + } + } + return(0); } + diff --git a/source/snes9x/bsx.h b/source/snes9x/bsx.h index 4b33b44..abf74ab 100644 --- a/source/snes9x/bsx.h +++ b/source/snes9x/bsx.h @@ -159,6 +159,8 @@ **********************************************************************************/ + + #ifndef _BSX_H_ #define _BSX_H_ @@ -181,15 +183,17 @@ struct SBSX uint8 test2192[32]; }; +START_EXTERN_C extern struct SBSX BSX; -uint8 S9xGetBSX (uint32); -void S9xSetBSX (uint8, uint32); -uint8 S9xGetBSXPPU (uint16); -void S9xSetBSXPPU (uint8, uint16); -uint8 * S9xGetBasePointerBSX (uint32); -void S9xInitBSX (void); -void S9xResetBSX (void); -void S9xBSXPostLoadState (void); +uint8 S9xGetBSX(uint32); +void S9xSetBSX(uint8, uint32); +uint8 S9xGetBSXPPU(uint16); +void S9xSetBSXPPU(uint8, uint16); +uint8 * S9xGetBasePointerBSX(uint32); +void S9xInitBSX(void); +void S9xResetBSX(void); +void S9xFixBSXAfterSnapshotLoad(void); +END_EXTERN_C #endif diff --git a/source/snes9x/c4.cpp b/source/snes9x/c4.cpp index 308a38d..978e535 100644 --- a/source/snes9x/c4.cpp +++ b/source/snes9x/c4.cpp @@ -159,146 +159,155 @@ **********************************************************************************/ + #include -#include "snes9x.h" +#include +#include "c4.h" #include "memmap.h" +extern "C" { -#define C4_PI 3.14159265 +short C4WFXVal; +short C4WFYVal; +short C4WFZVal; +short C4WFX2Val; +short C4WFY2Val; +short C4WFDist; +short C4WFScale; -int16 C4WFXVal; -int16 C4WFYVal; -int16 C4WFZVal; -int16 C4WFX2Val; -int16 C4WFY2Val; -int16 C4WFDist; -int16 C4WFScale; -int16 C41FXVal; -int16 C41FYVal; -int16 C41FAngleRes; -int16 C41FDist; -int16 C41FDistVal; +static double tanval; +static double c4x, c4y, c4z; +static double c4x2, c4y2, c4z2; -static double tanval; -static double c4x, c4y, c4z; -static double c4x2, c4y2, c4z2; - - -void C4TransfWireFrame (void) +void C4TransfWireFrame () { - c4x = (double) C4WFXVal; - c4y = (double) C4WFYVal; - c4z = (double) C4WFZVal - 0x95; + c4x = (double) C4WFXVal; + c4y = (double) C4WFYVal; + c4z = (double) C4WFZVal - 0x95; - // Rotate X - tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; - c4y2 = c4y * cos(tanval) - c4z * sin(tanval); - c4z2 = c4y * sin(tanval) + c4z * cos(tanval); + // Rotate X + tanval = -(double) C4WFX2Val * 3.14159265 * 2 / 128; + c4y2 = c4y * cos (tanval) - c4z * sin (tanval); + c4z2 = c4y * sin (tanval) + c4z * cos (tanval); - // Rotate Y - tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; - c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); - c4z = c4x * -sin(tanval) + c4z2 * cos(tanval); + // Rotate Y + tanval = -(double)C4WFY2Val*3.14159265*2/128; + c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); + c4z = c4x * - sin (tanval) + c4z2 * cos (tanval); - // Rotate Z - tanval = -(double) C4WFDist * C4_PI * 2 / 128; - c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); - c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); + // Rotate Z + tanval = -(double) C4WFDist * 3.14159265*2 / 128; + c4x = c4x2 * cos (tanval) - c4y2 * sin (tanval); + c4y = c4x2 * sin (tanval) + c4y2 * cos (tanval); - // Scale - C4WFXVal = (int16) (c4x * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); - C4WFYVal = (int16) (c4y * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); + // Scale + C4WFXVal = (short) (c4x*(double)C4WFScale/(0x90*(c4z+0x95))*0x95); + C4WFYVal = (short) (c4y*(double)C4WFScale/(0x90*(c4z+0x95))*0x95); } -void C4TransfWireFrame2 (void) +void C4TransfWireFrame2 () { - c4x = (double) C4WFXVal; - c4y = (double) C4WFYVal; - c4z = (double) C4WFZVal; + c4x = (double)C4WFXVal; + c4y = (double)C4WFYVal; + c4z = (double)C4WFZVal; - // Rotate X - tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; - c4y2 = c4y * cos(tanval) - c4z * sin(tanval); - c4z2 = c4y * sin(tanval) + c4z * cos(tanval); + // Rotate X + tanval = -(double) C4WFX2Val * 3.14159265 * 2 / 128; + c4y2 = c4y * cos (tanval) - c4z * sin (tanval); + c4z2 = c4y * sin (tanval) + c4z * cos (tanval); - // Rotate Y - tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; - c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); - c4z = c4x * -sin(tanval) + c4z2 * cos(tanval); + // Rotate Y + tanval = -(double) C4WFY2Val * 3.14159265 * 2 / 128; + c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); + c4z = c4x * -sin (tanval) + c4z2 * cos (tanval); - // Rotate Z - tanval = -(double) C4WFDist * C4_PI * 2 / 128; - c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); - c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); + // Rotate Z + tanval = -(double)C4WFDist * 3.14159265 * 2 / 128; + c4x = c4x2 * cos (tanval) - c4y2 * sin (tanval); + c4y = c4x2 * sin (tanval) + c4y2 * cos (tanval); - // Scale - C4WFXVal = (int16) (c4x * (double) C4WFScale / 0x100); - C4WFYVal = (int16) (c4y * (double) C4WFScale / 0x100); + // Scale + C4WFXVal =(short)(c4x * (double)C4WFScale / 0x100); + C4WFYVal =(short)(c4y * (double)C4WFScale / 0x100); } -void C4CalcWireFrame (void) +void C4CalcWireFrame () { - C4WFXVal = C4WFX2Val - C4WFXVal; - C4WFYVal = C4WFY2Val - C4WFYVal; - - if (abs(C4WFXVal) > abs(C4WFYVal)) - { - C4WFDist = abs(C4WFXVal) + 1; - C4WFYVal = (int16) (256 * (double) C4WFYVal / abs(C4WFXVal)); - if (C4WFXVal < 0) - C4WFXVal = -256; - else - C4WFXVal = 256; - } - else - { - if (C4WFYVal != 0) - { - C4WFDist = abs(C4WFYVal) + 1; - C4WFXVal = (int16) (256 * (double) C4WFXVal / abs(C4WFYVal)); - if (C4WFYVal < 0) - C4WFYVal = -256; - else - C4WFYVal = 256; - } - else - C4WFDist = 0; - } + C4WFXVal = C4WFX2Val - C4WFXVal; + C4WFYVal = C4WFY2Val - C4WFYVal; + if (abs (C4WFXVal) > abs (C4WFYVal)) + { + C4WFDist = abs (C4WFXVal) + 1; + C4WFYVal = (short) (256 * (double) C4WFYVal / abs (C4WFXVal)); + if (C4WFXVal < 0) + C4WFXVal = -256; + else + C4WFXVal = 256; + } + else + { + if (C4WFYVal != 0) + { + C4WFDist = abs(C4WFYVal)+1; + C4WFXVal = (short) (256 * (double)C4WFXVal / abs (C4WFYVal)); + if (C4WFYVal < 0) + C4WFYVal = -256; + else + C4WFYVal = 256; + } + else + C4WFDist = 0; + } } -void C4Op1F (void) +short C41FXVal; +short C41FYVal; +short C41FAngleRes; +short C41FDist; +short C41FDistVal; + +void C4Op1F () { - if (C41FXVal == 0) - { - if (C41FYVal > 0) - C41FAngleRes = 0x80; - else - C41FAngleRes = 0x180; - } - else - { - tanval = (double) C41FYVal / C41FXVal; - C41FAngleRes = (int16) (atan(tanval) / (C4_PI * 2) * 512); - C41FAngleRes = C41FAngleRes; - if (C41FXVal< 0) - C41FAngleRes += 0x100; - C41FAngleRes &= 0x1FF; - } + if (C41FXVal == 0) + { + if (C41FYVal > 0) + C41FAngleRes = 0x80; + else + C41FAngleRes = 0x180; + } + else + { + tanval = (double) C41FYVal / C41FXVal; + C41FAngleRes = (short) (atan (tanval) / (3.141592675 * 2) * 512); + C41FAngleRes = C41FAngleRes; + if (C41FXVal< 0) + C41FAngleRes += 0x100; + C41FAngleRes &= 0x1FF; + } } -void C4Op15 (void) +void C4Op15() { - tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - C41FDist = (int16) tanval; + tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + C41FDist = (short) tanval; } -void C4Op0D (void) +void C4Op0D() { - tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - tanval = C41FDistVal / tanval; - C41FYVal = (int16) (C41FYVal * tanval * 0.99); - C41FXVal = (int16) (C41FXVal * tanval * 0.98); + tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (short) (C41FYVal * tanval * 0.99); + C41FXVal = (short) (C41FXVal * tanval * 0.98); } +#ifdef ZSNES_C4 +EXTERN_C void C4LoaDMem(char *C4RAM) +{ + memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), + C4GetMemPointer(READ_3WORD(C4RAM+0x1f40)), + READ_WORD(C4RAM+0x1f43)); +} +#endif + uint8 * S9xGetBasePointerC4 (uint16 Address) { if (Address >= 0x7f40 && Address <= 0x7f5e) @@ -313,13 +322,4 @@ uint8 * S9xGetMemPointerC4 (uint16 Address) return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); } -#ifdef ZSNES_C4 -START_EXTERN_C - -void C4LoaDMem (char *C4RAM) -{ - memmove(C4RAM + (READ_WORD(C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(C4RAM + 0x1f40)), READ_WORD(C4RAM + 0x1f43)); -} - -END_EXTERN_C -#endif +}//end extern C diff --git a/source/snes9x/c4.h b/source/snes9x/c4.h index b72da27..9bc9d83 100644 --- a/source/snes9x/c4.h +++ b/source/snes9x/c4.h @@ -159,50 +159,45 @@ **********************************************************************************/ + #ifndef _C4_H_ #define _C4_H_ -extern int16 C4WFXVal; -extern int16 C4WFYVal; -extern int16 C4WFZVal; -extern int16 C4WFX2Val; -extern int16 C4WFY2Val; -extern int16 C4WFDist; -extern int16 C4WFScale; -extern int16 C41FXVal; -extern int16 C41FYVal; -extern int16 C41FAngleRes; -extern int16 C41FDist; -extern int16 C41FDistVal; +#include "port.h" +#include "memmap.h" -#ifdef ZSNES_C4 -extern uint8 *C4Ram; -#endif +extern "C" { -#ifdef ZSNES_C4 -START_EXTERN_C -#endif +extern int16 C4WFXVal; +extern int16 C4WFYVal; +extern int16 C4WFZVal; +extern int16 C4WFX2Val; +extern int16 C4WFY2Val; +extern int16 C4WFDist; +extern int16 C4WFScale; -void C4TransfWireFrame (void); -void C4TransfWireFrame2 (void); -void C4CalcWireFrame (void); -void C4Op0D (void); -void C4Op15 (void); -void C4Op1F (void); -void S9xInitC4 (void); -void S9xSetC4 (uint8, uint16); -uint8 S9xGetC4 (uint16); +void C4TransfWireFrame(); +void C4TransfWireFrame2(); +void C4CalcWireFrame(); -#ifdef ZSNES_C4 -END_EXTERN_C -#endif +extern int16 C41FXVal; +extern int16 C41FYVal; +extern int16 C41FAngleRes; +extern int16 C41FDist; +extern int16 C41FDistVal; -uint8 * S9xGetBasePointerC4 (uint16); -uint8 * S9xGetMemPointerC4 (uint16); +void C4Op1F(); +void C4Op15(); +void C4Op0D(); -static inline uint8 * C4GetMemPointer (uint32 Address) -{ - return (Memory.ROM + ((Address & 0xff0000) >> 1) + (Address & 0x7fff)); +extern int16 C4CosTable[]; +extern int16 C4SinTable[]; + +} + +static inline uint8 *C4GetMemPointer(uint32 Address){ + return (Memory.ROM + ((Address&0xff0000)>>1) + (Address&0x7fff)); } #endif + diff --git a/source/snes9x/c4emu.cpp b/source/snes9x/c4emu.cpp index ff35ff5..ea80989 100644 --- a/source/snes9x/c4emu.cpp +++ b/source/snes9x/c4emu.cpp @@ -159,1064 +159,930 @@ **********************************************************************************/ + +#ifndef ZSNES_C4 +#ifdef HAVE_CONFIG_H + #include +#endif #include #include "snes9x.h" -#include "memmap.h" #include "sar.h" +#include "memmap.h" +#include "ppu.h" +#include "c4.h" -static int16 C4SinTable[512] = +void S9xInitC4 () { - 0, 402, 804, 1206, 1607, 2009, 2410, 2811, - 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, - 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, - 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, - 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, - 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, - 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, - 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, - 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, - 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, - 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, - 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, - 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, - 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, - 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, - 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765, - 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, - 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, - 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, - 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, - 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, - 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, - 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, - 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, - 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, - 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, - 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, - 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, - 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, - 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, - 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, - 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, - 0, -402, -804, -1206, -1607, -2009, -2410, -2811, - -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, - -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, - -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, - -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, - -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, - -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, - -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, - -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, - -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, - -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, - -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, - -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, - -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, - -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, - -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, - -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, - -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, - -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, - -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, - -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, - -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, - -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, - -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, - -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, - -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, - -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, - -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, - -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, - -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, - -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, - -3211, -2811, -2410, -2009, -1607, -1206, -804, -402 -}; - -static int16 C4CosTable[512] = -{ - 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, - 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, - 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, - 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, - 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, - 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, - 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, - 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, - 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, - 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, - 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, - 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, - 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, - 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, - 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, - 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, - 0, -402, -804, -1206, -1607, -2009, -2410, -2811, - -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, - -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, - -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, - -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, - -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, - -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, - -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, - -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, - -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, - -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, - -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, - -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, - -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, - -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, - -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, - -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, - -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, - -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, - -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, - -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, - -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, - -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, - -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, - -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, - -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, - -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, - -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, - -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, - -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, - -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, - -3211, -2811, -2410, -2009, -1607, -1206, -804, -402, - 0, 402, 804, 1206, 1607, 2009, 2410, 2811, - 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, - 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, - 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, - 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, - 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, - 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, - 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, - 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, - 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, - 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, - 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, - 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, - 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, - 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, - 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765 -}; - -static uint8 C4TestPattern[12 * 4] = -{ - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x00, - 0x80, 0xff, 0xff, 0x7f, - 0x00, 0x80, 0x00, 0xff, - 0x7f, 0x00, 0xff, 0x7f, - 0xff, 0x7f, 0xff, 0xff, - 0x00, 0x00, 0x01, 0xff, - 0xff, 0xfe, 0x00, 0x01, - 0x00, 0xff, 0xfe, 0x00 -}; - -static void C4ConvOAM (void); -static void C4DoScaleRotate (int); -static void C4DrawLine (int32, int32, int16, int32, int32, int16, uint8); -static void C4DrawWireFrame (void); -static void C4TransformLines (void); -static void C4BitPlaneWave (void); -static void C4SprDisintegrate (void); -static void C4ProcessSprites (void); - - -static void C4ConvOAM (void) -{ - uint8 *OAMptr = Memory.C4RAM + (Memory.C4RAM[0x626] << 2); - for (uint8 *i = Memory.C4RAM + 0x1fd; i > OAMptr; i -= 4) - *i = 0xe0; // Clear OAM-to-be - - uint8 *OAMptr2; - uint16 globalX, globalY; - int16 SprX, SprY; - uint8 SprName, SprAttr; - uint8 SprCount; - - globalX = READ_WORD(Memory.C4RAM + 0x0621); - globalY = READ_WORD(Memory.C4RAM + 0x0623); - OAMptr2 = Memory.C4RAM + 0x200 + (Memory.C4RAM[0x626] >> 2); - -#ifdef DEBUGGER - if (Memory.C4RAM[0x625] != 0) - printf("$6625=%02x, expected 00\n", Memory.C4RAM[0x625]); - if ((Memory.C4RAM[0x626] >> 2) != Memory.C4RAM[0x629]) - printf("$6629=%02x, expected %02x\n", Memory.C4RAM[0x629], (Memory.C4RAM[0x626] >> 2)); - if (((uint16) Memory.C4RAM[0x626] << 2) != READ_WORD(Memory.C4RAM + 0x627)) - printf("$6627=%04x, expected %04x\n", READ_WORD(Memory.C4RAM + 0x627), ((uint16) Memory.C4RAM[0x626] << 2)); -#endif - - if (Memory.C4RAM[0x0620] != 0) - { - SprCount = 128 - Memory.C4RAM[0x626]; - - uint8 offset = (Memory.C4RAM[0x626] & 3) * 2; - uint8 *srcptr = Memory.C4RAM + 0x220; - - for (int i = Memory.C4RAM[0x0620]; i > 0 && SprCount > 0; i--, srcptr += 16) - { - SprX = READ_WORD(srcptr) - globalX; - SprY = READ_WORD(srcptr + 2) - globalY; - SprName = srcptr[5]; - SprAttr = srcptr[4] | srcptr[0x06]; // XXX: mask bits? - - uint8 *sprptr = C4GetMemPointer(READ_3WORD(srcptr + 7)); - if (*sprptr != 0) - { - int16 X, Y; - - for (int SprCnt = *sprptr++; SprCnt > 0 && SprCount > 0; SprCnt--, sprptr += 4) - { - X = (int8) sprptr[1]; - if (SprAttr & 0x40) - X = -X - ((sprptr[0] & 0x20) ? 16 : 8); // flip X - X += SprX; - - if (X >= -16 && X <= 272) - { - Y = (int8) sprptr[2]; - if (SprAttr & 0x80) - Y = -Y - ((sprptr[0] & 0x20) ? 16 : 8); - Y += SprY; - - if (Y >= -16 && Y <= 224) - { - OAMptr[0] = X & 0xff; - OAMptr[1] = (uint8) Y; - OAMptr[2] = SprName + sprptr[3]; - OAMptr[3] = SprAttr ^ (sprptr[0] & 0xc0); // XXX: Carry from SprName addition? - - *OAMptr2 &= ~(3 << offset); - if (X & 0x100) - *OAMptr2 |= 1 << offset; - if (sprptr[0] & 0x20) - *OAMptr2 |= 2 << offset; - - OAMptr += 4; - SprCount--; - - offset = (offset + 2) & 6; - if (offset == 0) - OAMptr2++; - } - } - } - } - else - if (SprCount > 0) - { - // XXX: Should we be testing -16<=SprX<=272 and -16<=SprY<=224? - OAMptr[0] = (uint8) SprX; - OAMptr[1] = (uint8) SprY; - OAMptr[2] = SprName; - OAMptr[3] = SprAttr; - - *OAMptr2 &= ~(3 << offset); - if (SprX & 0x100) - *OAMptr2 |= 3 << offset; - else - *OAMptr2 |= 2 << offset; - - OAMptr += 4; - SprCount--; - - offset = (offset + 2) & 6; - if (offset == 0) - OAMptr2++; - } - } - } -} - -static void C4DoScaleRotate (int row_padding) -{ - int16 A, B, C, D; - - // Calculate matrix - int32 XScale = READ_WORD(Memory.C4RAM + 0x1f8f); - if (XScale & 0x8000) - XScale = 0x7fff; - - int32 YScale = READ_WORD(Memory.C4RAM + 0x1f92); - if (YScale & 0x8000) - YScale = 0x7fff; - - if (READ_WORD(Memory.C4RAM + 0x1f80) == 0) // no rotation - { - // XXX: only do this for C and D? - // XXX: and then only when YScale is 0x1000? - A = (int16) XScale; - B = 0; - C = 0; - D = (int16) YScale; - } - else - if (READ_WORD(Memory.C4RAM + 0x1f80) == 128) // 90 degree rotation - { - // XXX: Really do this? - A = 0; - B = (int16) (-YScale); - C = (int16) XScale; - D = 0; - } - else - if (READ_WORD(Memory.C4RAM + 0x1f80) == 256) // 180 degree rotation - { - // XXX: Really do this? - A = (int16) (-XScale); - B = 0; - C = 0; - D = (int16) (-YScale); - } - else - if (READ_WORD(Memory.C4RAM + 0x1f80) == 384) // 270 degree rotation - { - // XXX: Really do this? - A = 0; - B = (int16) YScale; - C = (int16) (-XScale); - D = 0; - } - else - { - A = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15); - B = (int16) (-SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15)); - C = (int16) SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15); - D = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15); - } - - // Calculate Pixel Resolution - uint8 w = Memory.C4RAM[0x1f89] & ~7; - uint8 h = Memory.C4RAM[0x1f8c] & ~7; - - //printf("%dx%d XScale=%04x YScale=%04x angle=%03x\n", w, h, XScale, YScale, READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff); - //printf("Matrix: [%10g %10g] [%04x %04x]\n", A / 4096.0, B / 4096.0, A & 0xffff, B & 0xffff); - //printf(" [%10g %10g] [%04x %04x]\n", C / 4096.0, D / 4096.0, C & 0xffff, D & 0xffff); - - // Clear the output RAM - memset(Memory.C4RAM, 0, (w + row_padding / 4) * h / 2); - - int32 Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f83); - int32 Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f86); - -#ifdef DEBUGGER - if (Memory.C4RAM[0x1f97] != 0) - printf("$7f97=%02x, expected 00\n", Memory.C4RAM[0x1f97]); - if ((Cx & ~1) != w / 2 || (Cy & ~1) != h / 2) - printf("Center is not middle of image! (%d, %d) != (%d, %d)\n", Cx, Cy, w / 2, h / 2); -#endif - - // Calculate start position (i.e. (Ox, Oy) = (0, 0)) - // The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in the function. - // We do Cx*A etc normally because the matrix parameters already have the fractional parts. - int32 LineX = (Cx << 12) - Cx * A - Cx * B; - int32 LineY = (Cy << 12) - Cy * C - Cy * D; - - // Start loop - uint32 X, Y; - uint8 byte; - int outidx = 0; - uint8 bit = 0x80; - - for (int y = 0; y < h; y++) - { - X = LineX; - Y = LineY; - - for (int x = 0; x < w; x++) - { - if ((X >> 12) >= w || (Y >> 12) >= h) - byte = 0; - else - { - uint32 addr = (Y >> 12) * w + (X >> 12); - byte = Memory.C4RAM[0x600 + (addr >> 1)]; - if (addr & 1) - byte >>= 4; - } - - // De-bitplanify - if (byte & 1) - Memory.C4RAM[outidx] |= bit; - if (byte & 2) - Memory.C4RAM[outidx + 1] |= bit; - if (byte & 4) - Memory.C4RAM[outidx + 16] |= bit; - if (byte & 8) - Memory.C4RAM[outidx + 17] |= bit; - - bit >>= 1; - if (bit == 0) - { - bit = 0x80; - outidx += 32; - } - - X += A; // Add 1 to output x => add an A and a C - Y += C; - } - - outidx += 2 + row_padding; - if (outidx & 0x10) - outidx &= ~0x10; - else - outidx -= w * 4 + row_padding; - - LineX += B; // Add 1 to output y => add a B and a D - LineY += D; - } -} - -static void C4DrawLine (int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) -{ - // Transform coordinates - C4WFXVal = (int16) X1; - C4WFYVal = (int16) Y1; - C4WFZVal = Z1; - C4WFScale = Memory.C4RAM[0x1f90]; - C4WFX2Val = Memory.C4RAM[0x1f86]; - C4WFY2Val = Memory.C4RAM[0x1f87]; - C4WFDist = Memory.C4RAM[0x1f88]; - C4TransfWireFrame2(); - X1 = (C4WFXVal + 48) << 8; - Y1 = (C4WFYVal + 48) << 8; - - C4WFXVal = (int16) X2; - C4WFYVal = (int16) Y2; - C4WFZVal = Z2; - C4TransfWireFrame2(); - X2 = (C4WFXVal + 48) << 8; - Y2 = (C4WFYVal + 48) << 8; - - // Get line info - C4WFXVal = (int16) (X1 >> 8); - C4WFYVal = (int16) (Y1 >> 8); - C4WFX2Val = (int16) (X2 >> 8); - C4WFY2Val = (int16) (Y2 >> 8); - C4CalcWireFrame(); - X2 = (int16) C4WFXVal; - Y2 = (int16) C4WFYVal; - - // Render line - for (int i = C4WFDist ? C4WFDist : 1; i > 0; i--) - { - if (X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) - { - uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2; - uint8 bit = 0x80 >> ((X1 >> 8) & 7); - - Memory.C4RAM[addr + 0x300] &= ~bit; - Memory.C4RAM[addr + 0x301] &= ~bit; - if (Color & 1) - Memory.C4RAM[addr + 0x300] |= bit; - if (Color & 2) - Memory.C4RAM[addr + 0x301] |= bit; - } - - X1 += X2; - Y1 += Y2; - } -} - -static void C4DrawWireFrame (void) -{ - uint8 *line = C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f80)); - uint8 *point1, *point2; - int16 X1, Y1, Z1; - int16 X2, Y2, Z2; - uint8 Color; - -#ifdef DEBUGGER - if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff) - printf("wireframe: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f)); - if (READ_3WORD(Memory.C4RAM + 0x1fa4) != 0x001000) - printf("wireframe: Unexpected value in $7fa4: %06x\n", READ_3WORD(Memory.C4RAM + 0x1fa4)); -#endif - - for (int i = Memory.C4RAM[0x0295]; i > 0; i--, line += 5) - { - if (line[0] == 0xff && line[1] == 0xff) - { - uint8 *tmp = line - 5; - while (tmp[2] == 0xff && tmp[3] == 0xff) - tmp -= 5; - point1 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (tmp[2] << 8) | tmp[3]); - } - else - point1 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (line[0] << 8) | line[1]); - - point2 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (line[2] << 8) | line[3]); - - X1 = (point1[0] << 8) | point1[1]; - Y1 = (point1[2] << 8) | point1[3]; - Z1 = (point1[4] << 8) | point1[5]; - X2 = (point2[0] << 8) | point2[1]; - Y2 = (point2[2] << 8) | point2[3]; - Z2 = (point2[4] << 8) | point2[5]; - - Color = line[4]; - - C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color); - } -} - -static void C4TransformLines (void) -{ - C4WFX2Val = Memory.C4RAM[0x1f83]; - C4WFY2Val = Memory.C4RAM[0x1f86]; - C4WFDist = Memory.C4RAM[0x1f89]; - C4WFScale = Memory.C4RAM[0x1f8c]; - -#ifdef DEBUGGER - if (Memory.C4RAM[0x1f8a] != 0x90) - printf("lines: $7f8a = %02x, expected 90\n", READ_WORD(Memory.C4RAM + 0x1f8a)); -#endif - - // Transform vertices - uint8 *ptr = Memory.C4RAM; - - for (int i = READ_WORD(Memory.C4RAM + 0x1f80); i > 0; i--, ptr += 0x10) - { - C4WFXVal = READ_WORD(ptr + 1); - C4WFYVal = READ_WORD(ptr + 5); - C4WFZVal = READ_WORD(ptr + 9); - C4TransfWireFrame(); - - // Displace - WRITE_WORD(ptr + 1, C4WFXVal + 0x80); - WRITE_WORD(ptr + 5, C4WFYVal + 0x50); - } - - WRITE_WORD(Memory.C4RAM + 0x600, 23); - WRITE_WORD(Memory.C4RAM + 0x602, 0x60); - WRITE_WORD(Memory.C4RAM + 0x605, 0x40); - WRITE_WORD(Memory.C4RAM + 0x600 + 8, 23); - WRITE_WORD(Memory.C4RAM + 0x602 + 8, 0x60); - WRITE_WORD(Memory.C4RAM + 0x605 + 8, 0x40); - - ptr = Memory.C4RAM + 0xb02; - uint8 *ptr2 = Memory.C4RAM; - - for (int i = READ_WORD(Memory.C4RAM + 0xb00); i > 0; i--, ptr += 2, ptr2 += 8) - { - C4WFXVal = READ_WORD(Memory.C4RAM + (ptr[0] << 4) + 1); - C4WFYVal = READ_WORD(Memory.C4RAM + (ptr[0] << 4) + 5); - C4WFX2Val = READ_WORD(Memory.C4RAM + (ptr[1] << 4) + 1); - C4WFY2Val = READ_WORD(Memory.C4RAM + (ptr[1] << 4) + 5); - C4CalcWireFrame(); - - WRITE_WORD(ptr2 + 0x600, C4WFDist ? C4WFDist : 1); - WRITE_WORD(ptr2 + 0x602, C4WFXVal); - WRITE_WORD(ptr2 + 0x605, C4WFYVal); - } -} - -static void C4BitPlaneWave (void) -{ - static uint16 bmpdata[] = - { - 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E, - 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, - 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, - 0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E, - 0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E - }; - - uint8 *dst = Memory.C4RAM; - uint32 waveptr = Memory.C4RAM[0x1f83]; - uint16 mask1 = 0xc0c0; - uint16 mask2 = 0x3f3f; - -#ifdef DEBUGGER - if (READ_3WORD(Memory.C4RAM + 0x1f80) != Memory.C4RAM[waveptr + 0xb00]) - printf("$7f80=%06x, expected %02x\n", READ_3WORD(Memory.C4RAM + 0x1f80), Memory.C4RAM[waveptr + 0xb00]); -#endif - - for (int j = 0; j < 0x10; j++) - { - do - { - int16 height = -((int8) Memory.C4RAM[waveptr + 0xb00]) - 16; - - for (int i = 0; i < 40; i++) - { - uint16 tmp = READ_WORD(dst + bmpdata[i]) & mask2; - if (height >= 0) - { - if (height < 8) - tmp |= mask1 & READ_WORD(Memory.C4RAM + 0xa00 + height * 2); - else - tmp |= mask1 & 0xff00; - } - - WRITE_WORD(dst + bmpdata[i], tmp); - - height++; - } - - waveptr = (waveptr + 1) & 0x7f; - mask1 = (mask1 >> 2) | (mask1 << 6); - mask2 = (mask2 >> 2) | (mask2 << 6); - } - while (mask1 != 0xc0c0); - - dst += 16; - - do - { - int16 height = -((int8) Memory.C4RAM[waveptr + 0xb00]) - 16; - - for (int i = 0; i < 40; i++) - { - uint16 tmp = READ_WORD(dst + bmpdata[i]) & mask2; - if (height >= 0) - { - if (height < 8) - tmp |= mask1 & READ_WORD(Memory.C4RAM + 0xa10 + height * 2); - else - tmp |= mask1 & 0xff00; - } - - WRITE_WORD(dst + bmpdata[i], tmp); - - height++; - } - - waveptr = (waveptr + 1) & 0x7f; - mask1 = (mask1 >> 2) | (mask1 << 6); - mask2 = (mask2 >> 2) | (mask2 << 6); - } - while (mask1 != 0xc0c0); - - dst += 16; - } -} - -static void C4SprDisintegrate (void) -{ - uint8 *src; - uint8 width, height; - uint32 StartX, StartY; - int32 scaleX, scaleY; - int32 Cx, Cy; - - width = Memory.C4RAM[0x1f89]; - height = Memory.C4RAM[0x1f8c]; - Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f80); - Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f83); - -#ifdef DEBUGGER - if ((Cx & ~1) != width / 2 || (Cy & ~1) != height / 2) - printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width / 2, height / 2); -#endif - - scaleX = (int16) READ_WORD(Memory.C4RAM + 0x1f86); - scaleY = (int16) READ_WORD(Memory.C4RAM + 0x1f8f); - StartX = -Cx * scaleX + (Cx << 8); - StartY = -Cy * scaleY + (Cy << 8); - - src = Memory.C4RAM + 0x600; - - memset(Memory.C4RAM, 0, width * height / 2); - - for (uint32 y = StartY, i = 0; i < height; i++, y += scaleY) - { - for (uint32 x = StartX, j = 0; j < width; j++, x += scaleX) - { - if ((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) - { - uint8 pixel = (j & 1) ? (*src >> 4) : *src; - int idx = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2; - uint8 mask = 0x80 >> ((x >> 8) & 7); - - if (pixel & 1) - Memory.C4RAM[idx] |= mask; - if (pixel & 2) - Memory.C4RAM[idx + 1] |= mask; - if (pixel & 4) - Memory.C4RAM[idx + 16] |= mask; - if (pixel & 8) - Memory.C4RAM[idx + 17] |= mask; - } - - if (j & 1) - src++; - } - } -} - -static void C4ProcessSprites (void) -{ - switch (Memory.C4RAM[0x1f4d]) - { - case 0x00: // Build OAM - #ifdef DEBUGGER - //printf("00 00 Build OAM!\n"); - #endif - C4ConvOAM(); - break; - - case 0x03: // Scale/Rotate - #ifdef DEBUGGER - //printf("00 03 Scale/Rotate!\n"); - #endif - C4DoScaleRotate(0); - break; - - case 0x05: // Transform Lines - #ifdef DEBUGGER - //printf("00 05 Transform Lines!\n"); - #endif - C4TransformLines(); - break; - - case 0x07: // Scale/Rotate - #ifdef DEBUGGER - //printf("00 07 Scale/Rotate!\n"); - #endif - C4DoScaleRotate(64); - break; - - case 0x08: // Draw wireframe - #ifdef DEBUGGER - //printf("00 08 Draw wireframe!\n"); - #endif - C4DrawWireFrame(); - break; - - case 0x0b: // Disintegrate - #ifdef DEBUGGER - //printf("00 0b Disintegrate!\n"); - #endif - C4SprDisintegrate(); - break; - - case 0x0c: // Wave - #ifdef DEBUGGER - //printf("00 0b Wave!\n"); - #endif - C4BitPlaneWave(); - break; - - default: - #ifdef DEBUGGER - printf("Unknown C4 sprite command (%02x)\n", Memory.C4RAM[0x1f4d]); - #endif - break; - } -} - -void S9xInitC4 (void) -{ - // Stupid zsnes code, we can't do the logical thing without breaking savestates - // Memory.C4RAM = &Memory.FillRAM [0x6000]; - memset(Memory.C4RAM, 0, 0x2000); + // Stupid zsnes code, we can't do the logical thing without breaking + // savestates +// Memory.C4RAM = &Memory.FillRAM [0x6000]; + memset(Memory.C4RAM, 0, 0x2000); } uint8 S9xGetC4 (uint16 Address) { - if (Address == 0x7f5e) - return (0); + if(Address==0x7f5e) return 0; + return (Memory.C4RAM [Address-0x6000]); +} - return (Memory.C4RAM[Address - 0x6000]); +static uint8 C4TestPattern [12 * 4] = +{ + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, + 0x80, 0xff, 0xff, 0x7f, + 0x00, 0x80, 0x00, 0xff, + 0x7f, 0x00, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0xff, + 0x00, 0x00, 0x01, 0xff, + 0xff, 0xfe, 0x00, 0x01, + 0x00, 0xff, 0xfe, 0x00 +}; + + +static void C4ConvOAM(void){ + uint8 *OAMptr=Memory.C4RAM+(Memory.C4RAM[0x626]<<2); + for(uint8 *i=Memory.C4RAM+0x1fd; i>OAMptr; i-=4){ + // Clear OAM-to-be + *i=0xe0; + } + + uint16 globalX, globalY; + uint8 *OAMptr2; + int16 SprX, SprY; + uint8 SprName, SprAttr; + uint8 SprCount; + + globalX=READ_WORD(Memory.C4RAM+0x0621); + globalY=READ_WORD(Memory.C4RAM+0x0623); + OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2); + +#ifdef DEBUGGER + if(Memory.C4RAM[0x625]!=0) printf("$6625=%02x, expected 00\n", Memory.C4RAM[0x625]); + if((Memory.C4RAM[0x626]>>2)!=Memory.C4RAM[0x629]) printf("$6629=%02x, expected %02x\n", Memory.C4RAM[0x629], (Memory.C4RAM[0x626]>>2)); + if(((uint16)Memory.C4RAM[0x626]<<2)!=READ_WORD(Memory.C4RAM+0x627)) printf("$6627=%04x, expected %04x\n", READ_WORD(Memory.C4RAM+0x627), ((uint16)Memory.C4RAM[0x626]<<2)); +#endif + + if(Memory.C4RAM[0x0620]!=0){ + SprCount=128-Memory.C4RAM[0x626]; + uint8 offset=(Memory.C4RAM[0x626]&3)*2; + uint8 *srcptr=Memory.C4RAM+0x220; + for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ + SprX=READ_WORD(srcptr)-globalX; + SprY=READ_WORD(srcptr+2)-globalY; + SprName=srcptr[5]; + SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? + + uint8 *sprptr=C4GetMemPointer(READ_3WORD(srcptr+7)); + if(*sprptr!=0){ + int16 X, Y; + for(int SprCnt=*sprptr++; SprCnt>0 && SprCount>0; SprCnt--, sprptr+=4){ + X=(int8)sprptr[1]; + if(SprAttr&0x40){ // flip X + X=-X-((sprptr[0]&0x20)?16:8); + } + X+=SprX; + if(X>=-16 && X<=272){ + Y=(int8)sprptr[2]; + if(SprAttr&0x80){ + Y=-Y-((sprptr[0]&0x20)?16:8); + } + Y+=SprY; + if(Y>=-16 && Y<=224){ + OAMptr[0]=X&0xff; + OAMptr[1]=(uint8)Y; + OAMptr[2]=SprName+sprptr[3]; + OAMptr[3]=SprAttr^(sprptr[0]&0xc0); // XXX: Carry from SprName addition? + *OAMptr2 &= ~(3<0){ + // XXX: Should we be testing -16<=SprX<=272 and -16<=SprY<=224? + OAMptr[0]=(uint8)SprX; + OAMptr[1]=(uint8)SprY; + OAMptr[2]=SprName; + OAMptr[3]=SprAttr; + *OAMptr2 &= ~(3<>12)>=w || (Y>>12)>=h){ + byte=0; + } else { + uint32 addr=(Y>>12)*w+(X>>12); + byte=Memory.C4RAM[0x600+(addr>>1)]; + if(addr&1) byte>>=4; + } + + // De-bitplanify + if(byte&1) Memory.C4RAM[outidx]|=bit; + if(byte&2) Memory.C4RAM[outidx+1]|=bit; + if(byte&4) Memory.C4RAM[outidx+16]|=bit; + if(byte&8) Memory.C4RAM[outidx+17]|=bit; + + bit>>=1; + if(bit==0){ + bit=0x80; + outidx+=32; + } + + X+=A; // Add 1 to output x => add an A and a C + Y+=C; + } + outidx+=2+row_padding; + if(outidx&0x10){ + outidx&=~0x10; + } else { + outidx-=w*4+row_padding; + } + LineX+=B; // Add 1 to output y => add a B and a D + LineY+=D; + } +} + +static void C4DrawLine(int32 X1, int32 Y1, int16 Z1, + int32 X2, int32 Y2, int16 Z2, uint8 Color){ + // Transform coordinates + C4WFXVal=(short)X1; + C4WFYVal=(short)Y1; + C4WFZVal=Z1; + C4WFScale=Memory.C4RAM[0x1f90]; + C4WFX2Val=Memory.C4RAM[0x1f86]; + C4WFY2Val=Memory.C4RAM[0x1f87]; + C4WFDist=Memory.C4RAM[0x1f88]; + C4TransfWireFrame2(); + X1=(C4WFXVal+48)<<8; + Y1=(C4WFYVal+48)<<8; + + C4WFXVal=(short)X2; + C4WFYVal=(short)Y2; + C4WFZVal=Z2; + C4TransfWireFrame2(); + X2=(C4WFXVal+48)<<8; + Y2=(C4WFYVal+48)<<8; + + // get line info + C4WFXVal=(short)(X1>>8); + C4WFYVal=(short)(Y1>>8); + C4WFX2Val=(short)(X2>>8); + C4WFY2Val=(short)(Y2>>8); + C4CalcWireFrame(); + X2=(int16)C4WFXVal; + Y2=(int16)C4WFYVal; + + // render line + for(int i=C4WFDist?C4WFDist:1; i>0; i--) + { //.loop + if(X1>0xff && Y1>0xff && X1<0x6000 && Y1<0x6000) + { + uint16 addr=((X1&~0x7ff) + (Y1&~0x7ff)*12 + (Y1&0x700))>>7; + addr=(((Y1>>8)>>3)<<8)-(((Y1>>8)>>3)<<6)+(((X1>>8)>>3)<<4)+((Y1>>8)&7)*2; + uint8 bit=0x80>>((X1>>8)&7); + Memory.C4RAM[addr+0x300]&=~bit; + Memory.C4RAM[addr+0x301]&=~bit; + if(Color&1) Memory.C4RAM[addr+0x300]|=bit; + if(Color&2) Memory.C4RAM[addr+0x301]|=bit; + } + X1+=X2; + Y1+=Y2; + } +} + +static void C4DrawWireFrame(void) +{ + uint8 *line=C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f80)); + uint8 *point1, *point2; + int16 X1, Y1, Z1; + int16 X2, Y2, Z2; + uint8 Color; + +#ifdef DEBUGGER + if(READ_3WORD(Memory.C4RAM+0x1f8f)&0xff00ff) printf("wireframe: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM+0x1f8f)); + if(READ_3WORD(Memory.C4RAM+0x1fa4)!=0x001000) printf("wireframe: Unexpected value in $7fa4: %06x\n", READ_3WORD(Memory.C4RAM+0x1fa4)); +#endif + + for(int i=Memory.C4RAM[0x0295]; i>0; i--, line+=5){ + if(line[0]==0xff && line[1]==0xff){ + uint8 *tmp=line-5; + while(tmp[2]==0xff && tmp[3]==0xff) tmp-=5; + point1=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (tmp[2]<<8) | tmp[3]); + } else { + point1=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[0]<<8) | line[1]); + } + point2=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[2]<<8) | line[3]); + + X1=(point1[0]<<8) | point1[1]; + Y1=(point1[2]<<8) | point1[3]; + Z1=(point1[4]<<8) | point1[5]; + X2=(point2[0]<<8) | point2[1]; + Y2=(point2[2]<<8) | point2[3]; + Z2=(point2[4]<<8) | point2[5]; + Color=line[4]; + C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color); + } +} + +static void C4TransformLines(void){ + C4WFX2Val=Memory.C4RAM[0x1f83]; + C4WFY2Val=Memory.C4RAM[0x1f86]; + C4WFDist=Memory.C4RAM[0x1f89]; + C4WFScale=Memory.C4RAM[0x1f8c]; + +#ifdef DEBUGGER + if(Memory.C4RAM[0x1f8a]!=0x90) printf("lines: $7f8a = %02x, expected 90\n", READ_WORD(Memory.C4RAM+0x1f8a)); +#endif + + // transform vertices + uint8 *ptr=Memory.C4RAM; + { + for(int i=READ_WORD(Memory.C4RAM+0x1f80); i>0; i--, ptr+=0x10) + { + C4WFXVal=READ_WORD(ptr+1); + C4WFYVal=READ_WORD(ptr+5); + C4WFZVal=READ_WORD(ptr+9); + C4TransfWireFrame(); + + // displace + WRITE_WORD(ptr+1, C4WFXVal+0x80); + WRITE_WORD(ptr+5, C4WFYVal+0x50); + } + } + WRITE_WORD(Memory.C4RAM+0x600, 23); + WRITE_WORD(Memory.C4RAM+0x602, 0x60); + WRITE_WORD(Memory.C4RAM+0x605, 0x40); + WRITE_WORD(Memory.C4RAM+0x600+8, 23); + WRITE_WORD(Memory.C4RAM+0x602+8, 0x60); + WRITE_WORD(Memory.C4RAM+0x605+8, 0x40); + + ptr=Memory.C4RAM+0xb02; + uint8 *ptr2=Memory.C4RAM; + { + for(int i=READ_WORD(Memory.C4RAM+0xb00); i>0; i--, ptr+=2, ptr2+=8) + { + C4WFXVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+1); + C4WFYVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+5); + C4WFX2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+1); + C4WFY2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+5); + C4CalcWireFrame(); + WRITE_WORD(ptr2+0x600, C4WFDist?C4WFDist:1); + WRITE_WORD(ptr2+0x602, C4WFXVal); + WRITE_WORD(ptr2+0x605, C4WFYVal); + } + } +} +static void C4BitPlaneWave(){ + static uint16 bmpdata[]={ + 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E, + 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, + 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, + 0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E, + 0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E + }; + + uint8 *dst=Memory.C4RAM; + uint32 waveptr=Memory.C4RAM[0x1f83]; + uint16 mask1=0xc0c0; + uint16 mask2=0x3f3f; + +#ifdef DEBUGGER + if(READ_3WORD(Memory.C4RAM+0x1f80) != Memory.C4RAM[waveptr+0xb00]) printf("$7f80=%06x, expected %02x\n", READ_3WORD(Memory.C4RAM+0x1f80), Memory.C4RAM[waveptr+0xb00]); +#endif + + for(int j=0; j<0x10; j++){ + do { + int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16; + for(int i=0; i<40; i++){ + uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2; + if(height>=0){ + if(height<8){ + tmp|=mask1&READ_WORD(Memory.C4RAM+0xa00+height*2); + } else { + tmp|=mask1&0xff00; + } + } + WRITE_WORD(dst+bmpdata[i], tmp); + height++; + } + waveptr=(waveptr+1)&0x7f; + mask1=(mask1>>2)|(mask1<<6); + mask2=(mask2>>2)|(mask2<<6); + } while(mask1!=0xc0c0); + dst+=16; + + do { + int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16; + for(int i=0; i<40; i++){ + uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2; + if(height>=0){ + if(height<8){ + tmp|=mask1&READ_WORD(Memory.C4RAM+0xa10+height*2); + } else { + tmp|=mask1&0xff00; + } + } + WRITE_WORD(dst+bmpdata[i], tmp); + height++; + } + waveptr=(waveptr+1)&0x7f; + mask1=(mask1>>2)|(mask1<<6); + mask2=(mask2>>2)|(mask2<<6); + } while(mask1!=0xc0c0); + dst+=16; + } +} + +static void C4SprDisintegrate() +{ + uint8 width, height; + uint32 StartX, StartY; + uint8 *src; + int32 scaleX, scaleY; + int32 Cx, Cy; + + width=Memory.C4RAM[0x1f89]; + height=Memory.C4RAM[0x1f8c]; + Cx=(int16)READ_WORD(Memory.C4RAM+0x1f80); + Cy=(int16)READ_WORD(Memory.C4RAM+0x1f83); + +#ifdef DEBUGGER + if((Cx&~1)!=width/2 || (Cy&~1)!=height/2) printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width/2, height/2); +#endif + + scaleX=(int16)READ_WORD(Memory.C4RAM+0x1f86); + scaleY=(int16)READ_WORD(Memory.C4RAM+0x1f8f); + StartX=-Cx*scaleX+(Cx<<8); + StartY=-Cy*scaleY+(Cy<<8); + src=Memory.C4RAM+0x600; + + memset(Memory.C4RAM, 0, width*height/2); + + for(uint32 y=StartY, i=0; i>8)>8)>8)*width+(x>>8)<0x2000) + { + uint8 pixel=(j&1)?(*src>>4):*src; + int idx=(y>>11)*width*4+(x>>11)*32+((y>>8)&7)*2; + uint8 mask=0x80>>((x>>8)&7); + if(pixel&1) Memory.C4RAM[idx]|=mask; + if(pixel&2) Memory.C4RAM[idx+1]|=mask; + if(pixel&4) Memory.C4RAM[idx+16]|=mask; + if(pixel&8) Memory.C4RAM[idx+17]|=mask; + } + if(j&1) src++; + } + } +} + +static void S9xC4ProcessSprites() +{ + switch(Memory.C4RAM[0x1f4d]) + { + case 0x00: // Build OAM +#ifdef DEBUGGER +// printf("00 00 Build OAM!\n"); +#endif + C4ConvOAM(); + break; + + case 0x03: // Scale/Rotate +#ifdef DEBUGGER +// printf("00 03 Scale/Rotate!\n"); +#endif + C4DoScaleRotate(0); + break; + + case 0x05: // Transform Lines +#ifdef DEBUGGER +// printf("00 05 Transform Lines!\n"); +#endif + C4TransformLines(); + break; + + case 0x07: // Scale/Rotate +#ifdef DEBUGGER +// printf("00 07 Scale/Rotate!\n"); +#endif + C4DoScaleRotate(64); + break; + + case 0x08: // Draw wireframe +#ifdef DEBUGGER +// printf("00 08 Draw wireframe!\n"); +#endif + C4DrawWireFrame(); + break; + + case 0x0b: // Disintegrate +#ifdef DEBUGGER + printf("00 0b Disintegrate!\n"); +#endif + C4SprDisintegrate(); + break; + + case 0x0c: // Wave +#ifdef DEBUGGER +// printf("00 0b Wave!\n"); +#endif + C4BitPlaneWave(); + break; + + default: +#ifdef DEBUGGER + printf ("Unknown C4 sprite command (%02x)\n", Memory.C4RAM [0x1f4d]); +#endif + break; + } } void S9xSetC4 (uint8 byte, uint16 Address) { - Memory.C4RAM[Address - 0x6000] = byte; + int i; - if (Address == 0x7f4f) + Memory.C4RAM [Address-0x6000] = byte; + if (Address == 0x7f4f) { - if (Memory.C4RAM[0x1f4d] == 0x0e && byte < 0x40 && (byte & 3) == 0) + if(Memory.C4RAM[0x1f4d]==0x0e && byte<0x40 && (byte&3)==0) { - #ifdef DEBUGGER - printf("Test command %02x 0e used!\n", byte); - #endif - Memory.C4RAM[0x1f80] = byte >> 2; - } +#ifdef DEBUGGER + printf("Test command %02x 0e used!\n", byte); +#endif + Memory.C4RAM[0x1f80]=byte>>2; + } else { - switch (byte) + switch (byte) { - case 0x00: // Sprite - #ifdef DEBUGGER - //printf("00 Sprite!\n"); - #endif - C4ProcessSprites(); - break; + case 0x00: // Sprite + S9xC4ProcessSprites(); + break; - case 0x01: // Draw wireframe - #ifdef DEBUGGER - //printf("01 Draw wireframe!\n"); - if (Memory.C4RAM[0x1f4d] != 8) - printf("$7f4d=%02x, expected 08 for command 01 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - memset(Memory.C4RAM + 0x300, 0, 16 * 12 * 3 * 4); - C4DrawWireFrame(); - break; + case 0x01: // Draw wireframe +#ifdef DEBUGGER + //printf("01 Draw wireframe used!\n"); + if(Memory.C4RAM[0x1f4d]!=8) printf("$7f4d=%02x, expected 08 for command 01 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + memset(Memory.C4RAM+0x300, 0, 16*12*3*4); + C4DrawWireFrame(); + break; - case 0x05: // Propulsion (?) - { - #ifdef DEBUGGER - //printf("05 Propulsion (?)!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 05 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - int32 tmp = 0x10000; - if (READ_WORD(Memory.C4RAM + 0x1f83)) - tmp = SAR((tmp / READ_WORD(Memory.C4RAM + 0x1f83)) * READ_WORD(Memory.C4RAM + 0x1f81), 8); + case 0x05: // Propulsion (?) +#ifdef DEBUGGER + printf("05 Propulsion (?)!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 05 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + { + int32 tmp=0x10000; + if(READ_WORD(Memory.C4RAM+0x1f83)){ + tmp=SAR((tmp/READ_WORD(Memory.C4RAM+0x1f83))*READ_WORD(Memory.C4RAM+0x1f81), 8); + } + WRITE_WORD(Memory.C4RAM+0x1f80, (uint16)tmp); + } + break; - WRITE_WORD(Memory.C4RAM + 0x1f80, (uint16) tmp); - break; - } + case 0x0d: // Set vector length +#ifdef DEBUGGER + printf("0d Set vector length!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 0d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C41FDistVal=READ_WORD(Memory.C4RAM+0x1f86); + C4Op0D(); + WRITE_WORD(Memory.C4RAM+0x1f89, C41FXVal); + WRITE_WORD(Memory.C4RAM+0x1f8c, C41FYVal); + break; - case 0x0d: // Set vector length - #ifdef DEBUGGER - //printf("0d Set vector length!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 0d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); - C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); - C41FDistVal = READ_WORD(Memory.C4RAM + 0x1f86); - C4Op0D(); - WRITE_WORD(Memory.C4RAM + 0x1f89, C41FXVal); - WRITE_WORD(Memory.C4RAM + 0x1f8c, C41FYVal); - break; + case 0x10: // Polar to rectangluar +#ifdef DEBUGGER +// printf("10 Polar->Rect!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 10 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + { + int32 tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16); + WRITE_3WORD(Memory.C4RAM+0x1f86, tmp); + tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16); + WRITE_3WORD(Memory.C4RAM+0x1f89, (tmp-SAR(tmp, 6))); + } + break; - case 0x10: // Polar to rectangluar - { - #ifdef DEBUGGER - //printf("10 Polar->Rect!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 10 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - int32 tmp; - tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 16); - WRITE_3WORD(Memory.C4RAM + 0x1f86, tmp); - tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 16); - WRITE_3WORD(Memory.C4RAM + 0x1f89, (tmp - SAR(tmp, 6))); - break; - } + case 0x13: // Polar to rectangluar +#ifdef DEBUGGER +// printf("13 Polar->Rect!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 13 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + { + int32 tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8); + WRITE_3WORD(Memory.C4RAM+0x1f86, tmp); + tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8); + WRITE_3WORD(Memory.C4RAM+0x1f89, tmp); + } + break; - case 0x13: // Polar to rectangluar - { - #ifdef DEBUGGER - //printf("13 Polar->Rect!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 13 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - int32 tmp; - tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 8); - WRITE_3WORD(Memory.C4RAM + 0x1f86, tmp); - tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 8); - WRITE_3WORD(Memory.C4RAM + 0x1f89, tmp); - break; - } + case 0x15: // Pythagorean +#ifdef DEBUGGER + printf("15 Pythagorean!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 15 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + //C4Op15(); // optimized to: + C41FDist=(int16)sqrt((double)C41FXVal*C41FXVal + (double)C41FYVal*C41FYVal); + WRITE_WORD(Memory.C4RAM+0x1f80, C41FDist); + break; - case 0x15: // Pythagorean - #ifdef DEBUGGER - //printf("15 Pythagorean!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 15 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); - C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); - //C4Op15(); // optimized to: - C41FDist = (int16) sqrt((double) C41FXVal * C41FXVal + (double) C41FYVal * C41FYVal); - WRITE_WORD(Memory.C4RAM + 0x1f80, C41FDist); - break; + case 0x1f: // atan +#ifdef DEBUGGER +// printf("1f atan!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 1f %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C4Op1F(); + WRITE_WORD(Memory.C4RAM+0x1f86, C41FAngleRes); + break; - case 0x1f: // atan - #ifdef DEBUGGER - //printf("1f atan!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 1f %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); - C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); - C4Op1F(); - WRITE_WORD(Memory.C4RAM + 0x1f86, C41FAngleRes); - break; + case 0x22: // Trapezoid + { +#ifdef DEBUGGER +// printf("22 Trapezoid!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 22 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + int16 angle1=READ_WORD(Memory.C4RAM+0x1f8c)&0x1ff; + int16 angle2=READ_WORD(Memory.C4RAM+0x1f8f)&0x1ff; +#ifdef DEBUGGER + if(C4CosTable[angle1]==0) fprintf(stderr, "22 Trapezoid: Invalid tangent! angle1=%d\n", angle1); + if(C4CosTable[angle2]==0) fprintf(stderr, "22 Trapezoid: Invalid tangent! angle2=%d\n", angle2); +#endif + int32 tan1=(C4CosTable[angle1]!=0)?((((int32)C4SinTable[angle1])<<16)/C4CosTable[angle1]):0x80000000; + int32 tan2=(C4CosTable[angle2]!=0)?((((int32)C4SinTable[angle2])<<16)/C4CosTable[angle2]):0x80000000; + int16 y = READ_WORD(Memory.C4RAM+0x1f83) - READ_WORD(Memory.C4RAM+0x1f89); + int16 left, right; + for(int j=0; j<225; j++) + { + if(y>=0) + { + left = SAR((int32)tan1*y, 16) - + READ_WORD(Memory.C4RAM+0x1f80) + + READ_WORD(Memory.C4RAM+0x1f86); + right = SAR((int32)tan2*y, 16) - + READ_WORD(Memory.C4RAM+0x1f80) + + READ_WORD(Memory.C4RAM+0x1f86) + + READ_WORD(Memory.C4RAM+0x1f93); - case 0x22: // Trapezoid - { - #ifdef DEBUGGER - //printf("22 Trapezoid!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 22 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - int16 angle1 = READ_WORD(Memory.C4RAM + 0x1f8c) & 0x1ff; - int16 angle2 = READ_WORD(Memory.C4RAM + 0x1f8f) & 0x1ff; + if(left<0 && right<0){ + left=1; + right=0; + } else if(left<0){ + left=0; + } else if(right<0){ + right=0; + } + if(left>255 && right>255){ + left=255; + right=254; + } else if(left>255){ + left=255; + } else if(right>255){ + right=255; + } + } + else + { + left=1; + right=0; + } + Memory.C4RAM[j+0x800] = (uint8)left; + Memory.C4RAM[j+0x900] = (uint8)right; + y++; + } + } + break; - #ifdef DEBUGGER - if (C4CosTable[angle1] == 0) - fprintf(stderr, "22 Trapezoid: Invalid tangent! angle1=%d\n", angle1); - if (C4CosTable[angle2] == 0) - fprintf(stderr, "22 Trapezoid: Invalid tangent! angle2=%d\n", angle2); - #endif + case 0x25: // Multiply +#ifdef DEBUGGER + printf("25 Multiply!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + { + int32 foo=READ_3WORD(Memory.C4RAM+0x1f80); + int32 bar=READ_3WORD(Memory.C4RAM+0x1f83); + foo*=bar; + WRITE_3WORD(Memory.C4RAM+0x1f80, foo); + } + break; - int32 tan1 = (C4CosTable[angle1] != 0) ? ((((int32) C4SinTable[angle1]) << 16) / C4CosTable[angle1]) : 0x80000000; - int32 tan2 = (C4CosTable[angle2] != 0) ? ((((int32) C4SinTable[angle2]) << 16) / C4CosTable[angle2]) : 0x80000000; + case 0x2d: // Transform Coords +#ifdef DEBUGGER +// printf("2d Transform Coords!\n"); + if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 2d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + if(READ_3WORD(Memory.C4RAM+0x1f8f)&0xff00ff) printf("2d transform coords: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM+0x1f8f)); + if(READ_3WORD(Memory.C4RAM+0x1f8c)!=0x001000) printf("0d transform coords: Unexpected value in $7f8c: %06x\n", READ_3WORD(Memory.C4RAM+0x1f8c)); +#endif + C4WFXVal=READ_WORD(Memory.C4RAM+0x1f81); + C4WFYVal=READ_WORD(Memory.C4RAM+0x1f84); + C4WFZVal=READ_WORD(Memory.C4RAM+0x1f87); + C4WFX2Val=Memory.C4RAM[0x1f89]; + C4WFY2Val=Memory.C4RAM[0x1f8a]; + C4WFDist=Memory.C4RAM[0x1f8b]; + C4WFScale=READ_WORD(Memory.C4RAM+0x1f90); + C4TransfWireFrame2(); + WRITE_WORD(Memory.C4RAM+0x1f80, C4WFXVal); + WRITE_WORD(Memory.C4RAM+0x1f83, C4WFYVal); + break; - int16 y = READ_WORD(Memory.C4RAM + 0x1f83) - READ_WORD(Memory.C4RAM + 0x1f89); - int16 left, right; + case 0x40: // Sum +#ifdef DEBUGGER + printf("40 Sum!\n"); + if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 40 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + { + uint16 sum=0; + for(int i=0; i<0x800; sum+=Memory.C4RAM[i++]); + WRITE_WORD(Memory.C4RAM+0x1f80, sum); + } + break; - for (int j = 0; j < 225; j++) - { - if (y >= 0) - { - left = SAR((int32) tan1 * y, 16) - READ_WORD(Memory.C4RAM + 0x1f80) + READ_WORD(Memory.C4RAM + 0x1f86); - right = SAR((int32) tan2 * y, 16) - READ_WORD(Memory.C4RAM + 0x1f80) + READ_WORD(Memory.C4RAM + 0x1f86) + READ_WORD(Memory.C4RAM + 0x1f93); + case 0x54: // Square +#ifdef DEBUGGER + printf("54 Square!\n"); + if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 54 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + { + int64 a=SAR((int64)READ_3WORD(Memory.C4RAM+0x1f80)<<40, 40); + // printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF)); + a*=a; + // printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF)); + WRITE_3WORD(Memory.C4RAM+0x1f83, a); + WRITE_3WORD(Memory.C4RAM+0x1f86, (a>>24)); + } + break; - if (left < 0 && right < 0) - { - left = 1; - right = 0; - } - else - if (left < 0) - left = 0; - else - if (right < 0) - right = 0; + case 0x5c: // Immediate Reg +#ifdef DEBUGGER + printf("5c Immediate Reg!\n"); + if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 5c %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + for (i = 0; i < 12 * 4; i++) + Memory.C4RAM [i] = C4TestPattern [i]; + break; - if (left > 255 && right > 255) - { - left = 255; - right = 254; - } - else - if (left > 255) - left = 255; - else - if (right > 255) - right = 255; - } - else - { - left = 1; - right = 0; - } + case 0x89: // Immediate ROM +#ifdef DEBUGGER + printf("89 Immediate ROM!\n"); + if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 89 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); +#endif + Memory.C4RAM [0x1f80] = 0x36; + Memory.C4RAM [0x1f81] = 0x43; + Memory.C4RAM [0x1f82] = 0x05; + break; - Memory.C4RAM[j + 0x800] = (uint8) left; - Memory.C4RAM[j + 0x900] = (uint8) right; - - y++; - } - - break; - } - - case 0x25: // Multiply - { - #ifdef DEBUGGER - //printf("25 Multiply!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - int32 foo = READ_3WORD(Memory.C4RAM + 0x1f80); - int32 bar = READ_3WORD(Memory.C4RAM + 0x1f83); - foo *= bar; - WRITE_3WORD(Memory.C4RAM + 0x1f80, foo); - break; - } - - case 0x2d: // Transform Coords - #ifdef DEBUGGER - //printf("2d Transform Coords!\n"); - if (Memory.C4RAM[0x1f4d] != 2) - printf("$7f4d=%02x, expected 02 for command 2d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff) - printf("2d transform coords: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f)); - if (READ_3WORD(Memory.C4RAM + 0x1f8c) != 0x001000) - printf("0d transform coords: Unexpected value in $7f8c: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8c)); - #endif - C4WFXVal = READ_WORD(Memory.C4RAM + 0x1f81); - C4WFYVal = READ_WORD(Memory.C4RAM + 0x1f84); - C4WFZVal = READ_WORD(Memory.C4RAM + 0x1f87); - C4WFX2Val = Memory.C4RAM[0x1f89]; - C4WFY2Val = Memory.C4RAM[0x1f8a]; - C4WFDist = Memory.C4RAM[0x1f8b]; - C4WFScale = READ_WORD(Memory.C4RAM + 0x1f90); - C4TransfWireFrame2(); - WRITE_WORD(Memory.C4RAM + 0x1f80, C4WFXVal); - WRITE_WORD(Memory.C4RAM + 0x1f83, C4WFYVal); - break; - - case 0x40: // Sum - { - #ifdef DEBUGGER - //printf("40 Sum!\n"); - if (Memory.C4RAM[0x1f4d] != 0x0e) - printf("$7f4d=%02x, expected 0e for command 40 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - uint16 sum = 0; - for (int i = 0; i < 0x800; sum += Memory.C4RAM[i++]) ; - WRITE_WORD(Memory.C4RAM + 0x1f80, sum); - break; - } - - case 0x54: // Square - { - #ifdef DEBUGGER - //printf("54 Square!\n"); - if (Memory.C4RAM[0x1f4d] != 0x0e) - printf("$7f4d=%02x, expected 0e for command 54 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - int64 a = SAR((int64) READ_3WORD(Memory.C4RAM + 0x1f80) << 40, 40); - //printf("%08X%08X\n", (uint32) (a>>32), (uint32) (a&0xFFFFFFFF)); - a *= a; - //printf("%08X%08X\n", (uint32) (a>>32), (uint32) (a&0xFFFFFFFF)); - WRITE_3WORD(Memory.C4RAM + 0x1f83, a); - WRITE_3WORD(Memory.C4RAM + 0x1f86, (a >> 24)); - break; - } - - case 0x5c: // Immediate Reg - #ifdef DEBUGGER - //printf("5c Immediate Reg!\n"); - if (Memory.C4RAM[0x1f4d] != 0x0e) - printf("$7f4d=%02x, expected 0e for command 5c %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - for (int i = 0; i < 12 * 4; i++) - Memory.C4RAM[i] = C4TestPattern[i]; - break; - - case 0x89: // Immediate ROM - #ifdef DEBUGGER - //printf("89 Immediate ROM!\n"); - if (Memory.C4RAM[0x1f4d] != 0x0e) - printf("$7f4d=%02x, expected 0e for command 89 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); - #endif - Memory.C4RAM[0x1f80] = 0x36; - Memory.C4RAM[0x1f81] = 0x43; - Memory.C4RAM[0x1f82] = 0x05; - break; - - default: - #ifdef DEBUGGER - printf("Unknown C4 command (%02x)\n", byte); - #endif - break; - } - } - } - else - if (Address == 0x7f47) - { - #ifdef DEBUGGER - //printf("C4 load memory %06x => %04x, %04x bytes\n", READ_3WORD(Memory.C4RAM + 0x1f40), READ_WORD(Memory.C4RAM + 0x1f45), READ_WORD(Memory.C4RAM + 0x1f43)); - if (byte != 0) - printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte); - if (READ_WORD(Memory.C4RAM + 0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM + 0x1f45) + READ_WORD(Memory.C4RAM + 0x1f43)) > 0x6c00) - printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM + 0x1f45)); - #endif - memmove(Memory.C4RAM + (READ_WORD(Memory.C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f40)), READ_WORD(Memory.C4RAM + 0x1f43)); - } + default: +#ifdef DEBUGGER + printf ("Unknown C4 command (%02x)\n", byte); +#endif + break; + } + } + } else if (Address == 0x7f47) { +#ifdef DEBUGGER +// printf("C4 load memory %06x => %04x, %04x bytes\n", READ_3WORD(Memory.C4RAM+0x1f40), READ_WORD(Memory.C4RAM+0x1f45), READ_WORD(Memory.C4RAM+0x1f43)); + if(byte != 0) printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte); + if(READ_WORD(Memory.C4RAM+0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM+0x1f45) + READ_WORD(Memory.C4RAM+0x1f43)) > 0x6c00) printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM+0x1f45)); +#endif + memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), + C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)), + READ_WORD(Memory.C4RAM+0x1f43)); + } } + +int16 C4SinTable[512] = { + 0, 402, 804, 1206, 1607, 2009, 2410, 2811, + 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, + 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, + 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, + 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, + 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, + 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, + 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, + 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, + 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, + 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, + 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, + 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, + 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, + 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, + 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765, + 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, + 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, + 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, + 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, + 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, + 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, + 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, + 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, + 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, + 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, + 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, + 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, + 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, + 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, + 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, + 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, + 0, -402, -804, -1206, -1607, -2009, -2410, -2811, + -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, + -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, + -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, + -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, + -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, + -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, + -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, + -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, + -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, + -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, + -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, + -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, + -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, + -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, + -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, + -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, + -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, + -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, + -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, + -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, + -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, + -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, + -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, + -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, + -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, + -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, + -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, + -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, + -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, + -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, + -3211, -2811, -2410, -2009, -1607, -1206, -804, -402 +}; + +int16 C4CosTable[512] = { + 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, + 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, + 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, + 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, + 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, + 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, + 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, + 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, + 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, + 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, + 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, + 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, + 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, + 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, + 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, + 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, + 0, -402, -804, -1206, -1607, -2009, -2410, -2811, + -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, + -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, + -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, + -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, + -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, + -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, + -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, + -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, + -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, + -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, + -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, + -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, + -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, + -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, + -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, + -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, + -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, + -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, + -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, + -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, + -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, + -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, + -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, + -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, + -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, + -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, + -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, + -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, + -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, + -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, + -3211, -2811, -2410, -2009, -1607, -1206, -804, -402, + 0, 402, 804, 1206, 1607, 2009, 2410, 2811, + 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, + 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, + 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, + 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, + 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, + 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, + 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, + 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, + 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, + 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, + 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, + 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, + 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, + 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, + 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765 +}; +#endif diff --git a/source/snes9x/cheats.cpp b/source/snes9x/cheats.cpp index fc5d076..0a94e39 100644 --- a/source/snes9x/cheats.cpp +++ b/source/snes9x/cheats.cpp @@ -159,404 +159,426 @@ **********************************************************************************/ + +#include #include +#include #include "snes9x.h" -#include "memmap.h" #include "cheats.h" - -#define WRAM_BITS ALL_BITS -#define SRAM_BITS ALL_BITS + (0x20000 >> 5) -#define IRAM_BITS ALL_BITS + (0x30000 >> 5) - -#define BIT_CLEAR(a, v) (a)[(v) >> 5] &= ~(1 << ((v) & 31)) - -#define TEST_BIT(a, v) ((a)[(v) >> 5] & (1 << ((v) & 31))) - -#define _S9XCHTC(c, a, b) \ - ((c) == S9X_LESS_THAN ? (a) < (b) : \ - (c) == S9X_GREATER_THAN ? (a) > (b) : \ - (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ - (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ - (c) == S9X_EQUAL ? (a) == (b) : \ - (a) != (b)) - -#define _S9XCHTD(s, m, o) \ - ((s) == S9X_8_BITS ? ((uint8) (*((m) + (o)))) : \ - (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ - ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -#define _S9XCHTDS(s, m, o) \ - ((s) == S9X_8_BITS ? ((int8) (*((m) + (o)))) : \ - (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ - ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -static bool8 S9xAllHex (const char *, int); - +#include "memmap.h" static bool8 S9xAllHex (const char *code, int len) { - for (int i = 0; i < len; i++) - if ((code[i] < '0' || code[i] > '9') && (code[i] < 'a' || code[i] > 'f') && (code[i] < 'A' || code[i] > 'F')) - return (FALSE); + for (int i = 0; i < len; i++) + if ((code [i] < '0' || code [i] > '9') && + (code [i] < 'a' || code [i] > 'f') && + (code [i] < 'A' || code [i] > 'F')) + return (FALSE); - return (TRUE); + return (TRUE); } -const char * S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) +const char *S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) { - uint32 data = 0; + uint32 data = 0; + if (strlen (code) != 8 || !S9xAllHex (code, 8) || + sscanf (code, "%x", &data) != 1) + return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); - if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x", &data) != 1) - return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); - - address = data >> 8; - byte = (uint8) data; - - return (NULL); + address = data >> 8; + byte = (uint8) data; + return (NULL); } -const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3]) +const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, + uint8 &num_bytes, uint8 bytes[3]) { - char tmp[15]; - int i; + char tmp [15]; + if (strlen (code) != 14) + return ("Invalid Gold Finger code should be 14 hex digits in length."); - if (strlen(code) != 14) - return ("Invalid Gold Finger code - should be 14 hex digits in length."); + strncpy (tmp, code, 5); + tmp [5] = 0; + if (sscanf (tmp, "%x", &address) != 1) + return ("Invalid Gold Finger code."); - strncpy(tmp, code, 5); - tmp[5] = 0; - if (sscanf(tmp, "%x", &address) != 1) - return ("Invalid Gold Finger code."); + int i; + for (i = 0; i < 3; i++) + { + strncpy (tmp, code + 5 + i * 2, 2); + tmp [2] = 0; + unsigned int byte; + if (sscanf (tmp, "%x", &byte) != 1) + break; + bytes [i] = (uint8) byte; + } + num_bytes = i; + sram = code [13] == '1'; + return (NULL); +} - for (i = 0; i < 3; i++) +const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) +{ + char new_code [12]; + + if (strlen (code) != 9 || *(code + 4) != '-' || !S9xAllHex (code, 4) || + !S9xAllHex (code + 5, 4)) + return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); + + strcpy (new_code, "0x"); + strncpy (new_code + 2, code, 4); + strcpy (new_code + 6, code + 5); + + static char *real_hex = "0123456789ABCDEF"; + static char *genie_hex = "DF4709156BC8A23E"; + + for (int i = 2; i < 10; i++) + { + if (islower (new_code [i])) + new_code [i] = toupper (new_code [i]); + int j; + for (j = 0; j < 16; j++) { - unsigned int byte; - - strncpy(tmp, code + 5 + i * 2, 2); - tmp[2] = 0; - if (sscanf(tmp, "%x", &byte) != 1) - break; - bytes[i] = (uint8) byte; + if (new_code [i] == genie_hex [j]) + { + new_code [i] = real_hex [j]; + break; + } } + if (j == 16) + return ("Invalid hex-character in Game Genie(tm) code"); + } + uint32 data = 0; + sscanf (new_code, "%x", &data); + byte = (uint8)(data >> 24); + address = data & 0xffffff; + address = ((address & 0x003c00) << 10) + + ((address & 0x00003c) << 14) + + ((address & 0xf00000) >> 8) + + ((address & 0x000003) << 10) + + ((address & 0x00c000) >> 6) + + ((address & 0x0f0000) >> 12) + + ((address & 0x0003c0) >> 6); - num_bytes = i; - sram = code[13] == '1'; - - return (NULL); -} - -const char * S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) -{ - char new_code[12]; - - if (strlen(code) != 9 || *(code + 4) != '-' || !S9xAllHex(code, 4) || !S9xAllHex(code + 5, 4)) - return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); - - strcpy(new_code, "0x"); - strncpy(new_code + 2, code, 4); - strcpy(new_code + 6, code + 5); - - static const char *real_hex = "0123456789ABCDEF"; - static const char *genie_hex = "DF4709156BC8A23E"; - - for (int i = 2; i < 10; i++) - { - if (islower(new_code[i])) - new_code[i] = toupper(new_code[i]); - - int j; - for (j = 0; j < 16; j++) - { - if (new_code[i] == genie_hex[j]) - { - new_code[i] = real_hex[j]; - break; - } - } - - if (j == 16) - return ("Invalid hex-character in Game Genie(tm) code."); - } - - uint32 data = 0; - sscanf(new_code, "%x", &data); - byte = (uint8) (data >> 24); - address = data & 0xffffff; - address = ((address & 0x003c00) << 10) + - ((address & 0x00003c) << 14) + - ((address & 0xf00000) >> 8) + - ((address & 0x000003) << 10) + - ((address & 0x00c000) >> 6) + - ((address & 0x0f0000) >> 12) + - ((address & 0x0003c0) >> 6); - - return (NULL); + return (NULL); } void S9xStartCheatSearch (SCheatData *d) { - memmove(d->CWRAM, d->RAM, 0x20000); - memmove(d->CSRAM, d->SRAM, 0x10000); - memmove(d->CIRAM, &d->FillRAM[0x3000], 0x2000); - memset((char *) d->ALL_BITS, 0xff, 0x32000 >> 3); + memmove (d->CWRAM, d->RAM, 0x20000); + memmove (d->CSRAM, d->SRAM, 0x10000); + memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); + memset ((char *) d->ALL_BITS, 0xff, 0x32000 >> 3); } -void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool8 is_signed, bool8 update) +#define BIT_CLEAR(a,v) \ +(a)[(v) >> 5] &= ~(1 << ((v) & 31)) + +#define BIT_SET(a,v) \ +(a)[(v) >> 5] |= 1 << ((v) & 31) + +#define TEST_BIT(a,v) \ +((a)[(v) >> 5] & (1 << ((v) & 31))) + +#ifdef NGC +#undef _C /*** Stops powerpc-gekko-g++ complaining -;) ***/ +#endif + +#define _C(c,a,b) \ +((c) == S9X_LESS_THAN ? (a) < (b) : \ + (c) == S9X_GREATER_THAN ? (a) > (b) : \ + (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ + (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ + (c) == S9X_EQUAL ? (a) == (b) : \ + (a) != (b)) + +#define _D(s,m,o) \ +((s) == S9X_8_BITS ? (uint8) (*((m) + (o))) : \ + (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ +((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +#define _DS(s,m,o) \ +((s) == S9X_8_BITS ? ((int8) *((m) + (o))) : \ + (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ + ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, bool8 is_signed, bool8 update) { - int l, i; + int l; - switch (size) - { - case S9X_8_BITS: l = 0; break; - case S9X_16_BITS: l = 1; break; - case S9X_24_BITS: l = 2; break; - default: - case S9X_32_BITS: l = 3; break; - } + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } - if (is_signed) - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), _S9XCHTDS(size, d->CWRAM, i))) - { - if (update) - d->CWRAM[i] = d->RAM[i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } + int i; + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _DS(size, d->RAM, i), _DS(size, d->CWRAM, i))) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), _S9XCHTDS(size, d->CSRAM, i))) - { - if (update) - d->CSRAM[i] = d->SRAM[i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i))) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), _S9XCHTDS(size, d->CIRAM, i))) - { - if (update) - d->CIRAM[i] = d->FillRAM[i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), _S9XCHTD(size, d->CWRAM, i))) - { - if (update) - d->CWRAM[i] = d->RAM[i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i))) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i))) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), _S9XCHTD(size, d->CSRAM, i))) - { - if (update) - d->CSRAM[i] = d->SRAM[i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i))) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), _S9XCHTD(size, d->CIRAM, i))) - { - if (update) - d->CIRAM[i] = d->FillRAM[i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } - - for (i = 0x20000 - l; i < 0x20000; i++) - BIT_CLEAR(d->WRAM_BITS, i); - - for (i = 0x10000 - l; i < 0x10000; i++) - BIT_CLEAR(d->SRAM_BITS, i); + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _D(size, d->FillRAM + 0x3000, i), _D(size, d->CIRAM, i))) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR (d->WRAM_BITS, i); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR (d->SRAM_BITS, i); } -void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 is_signed, bool8 update) +void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, + bool8 is_signed, bool8 update) { - int l, i; + int l; - switch (size) - { - case S9X_8_BITS: l = 0; break; - case S9X_16_BITS: l = 1; break; - case S9X_24_BITS: l = 2; break; - default: - case S9X_32_BITS: l = 3; break; - } + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } - if (is_signed) - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), (int32) value)) - { - if (update) - d->CWRAM[i] = d->RAM[i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } + int i; - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), (int32) value)) - { - if (update) - d->CSRAM[i] = d->SRAM[i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _DS(size, d->RAM, i), (int32) value)) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), (int32) value)) - { - if (update) - d->CIRAM[i] = d->FillRAM[i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), value)) - { - if (update) - d->CWRAM[i] = d->RAM[i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _DS(size, d->SRAM, i), (int32) value)) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), value)) - { - if (update) - d->CSRAM[i] = d->SRAM[i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _DS(size, d->FillRAM + 0x3000, i), (int32) value)) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _D(size, d->RAM, i), value)) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), value)) - { - if (update) - d->CIRAM[i] = d->FillRAM[i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _D(size, d->SRAM, i), value)) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } - for (i = 0x20000 - l; i < 0x20000; i++) - BIT_CLEAR(d->WRAM_BITS, i); - - for (i = 0x10000 - l; i < 0x10000; i++) - BIT_CLEAR(d->SRAM_BITS, i); + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _D(size, d->FillRAM + 0x3000, i), value)) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR (d->WRAM_BITS, i); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR (d->SRAM_BITS, i); } -void S9xSearchForAddress (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 update) +void S9xSearchForAddress (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, bool8 update) { - int l, i; + int l; - switch (size) - { - case S9X_8_BITS: l = 0; break; - case S9X_16_BITS: l = 1; break; - case S9X_24_BITS: l = 2; break; - default: - case S9X_32_BITS: l = 3; break; - } + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, i, (int32) value)) - { - if (update) - d->CWRAM[i] = d->RAM[i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } + int i; - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, i + 0x20000, (int32) value)) - { - if (update) - d->CSRAM[i] = d->SRAM[i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } + { - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, i + 0x30000, (int32) value)) - { - if (update) - d->CIRAM[i] = d->FillRAM[i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, i, (int)value)) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } - for (i = 0x20000 - l; i < 0x20000; i++) - BIT_CLEAR(d->WRAM_BITS, i); + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, i+0x20000, (int)value)) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } - for (i = 0x10000 - l; i < 0x10000; i++) - BIT_CLEAR(d->SRAM_BITS, i); + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, i+0x30000, (int)value)) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR (d->WRAM_BITS, i); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR (d->SRAM_BITS, i); } void S9xOutputCheatSearchResults (SCheatData *d) { - int i; + int i; + for (i = 0; i < 0x20000; i++) + { + if (TEST_BIT (d->WRAM_BITS, i)) + printf ("WRAM: %05x: %02x\n", i, d->RAM [i]); + } - for (i = 0; i < 0x20000; i++) - { - if (TEST_BIT(d->WRAM_BITS, i)) - printf("WRAM: %05x: %02x\n", i, d->RAM[i]); - } + for (i = 0; i < 0x10000; i++) + { + if (TEST_BIT (d->SRAM_BITS, i)) + printf ("SRAM: %04x: %02x\n", i, d->SRAM [i]); + } - for (i = 0; i < 0x10000; i++) - { - if (TEST_BIT(d->SRAM_BITS, i)) - printf("SRAM: %04x: %02x\n", i, d->SRAM[i]); - } - - for (i = 0; i < 0x2000; i++) - { - if (TEST_BIT(d->IRAM_BITS, i)) - printf("IRAM: %05x: %02x\n", i, d->FillRAM[i + 0x3000]); - } + for (i = 0; i < 0x2000; i++) + { + if (TEST_BIT (d->IRAM_BITS, i)) + printf ("IRAM: %05x: %02x\n", i, d->FillRAM [i + 0x3000]); + } } + diff --git a/source/snes9x/cheats.h b/source/snes9x/cheats.h index 53411b8..199189f 100644 --- a/source/snes9x/cheats.h +++ b/source/snes9x/cheats.h @@ -159,88 +159,89 @@ **********************************************************************************/ + #ifndef _CHEATS_H_ #define _CHEATS_H_ -#define MAX_CHEATS 150 - struct SCheat { - uint32 address; - uint8 byte; - uint8 saved_byte; - bool8 enabled; - bool8 saved; - char name[22]; + uint32 address; + uint8 byte; + uint8 saved_byte; + bool8 enabled; + bool8 saved; + char name [22]; }; +#define MAX_CHEATS 150 + struct SCheatData { - struct SCheat c[MAX_CHEATS]; - uint32 num_cheats; - uint8 CWRAM[0x20000]; - uint8 CSRAM[0x10000]; - uint8 CIRAM[0x2000]; - uint8 *RAM; - uint8 *FillRAM; - uint8 *SRAM; - uint32 ALL_BITS[0x32000 >> 5]; - uint8 CWatchRAM[0x32000]; + struct SCheat c [MAX_CHEATS]; + uint32 num_cheats; + uint8 CWRAM [0x20000]; + uint8 CSRAM [0x10000]; + uint8 CIRAM [0x2000]; + uint8 *RAM; + uint8 *FillRAM; + uint8 *SRAM; + uint32 ALL_BITS [(0x32000 >> 5)]; +#define WRAM_BITS ALL_BITS +#define SRAM_BITS ALL_BITS + (0x20000 >> 5) +#define IRAM_BITS ALL_BITS + (0x30000 >> 5) + uint8 CWatchRAM [0x32000]; }; -struct Watch -{ - bool on; - int size; - int format; - uint32 address; - char buf[12]; - char desc[32]; + +struct Watch { + bool on; + int size; + int format; + uint32 address; + char buf[12]; + char desc[32]; }; +extern Watch watches [16]; typedef enum { - S9X_LESS_THAN, - S9X_GREATER_THAN, - S9X_LESS_THAN_OR_EQUAL, - S9X_GREATER_THAN_OR_EQUAL, - S9X_EQUAL, - S9X_NOT_EQUAL -} S9xCheatComparisonType; + S9X_LESS_THAN, S9X_GREATER_THAN, S9X_LESS_THAN_OR_EQUAL, + S9X_GREATER_THAN_OR_EQUAL, S9X_EQUAL, S9X_NOT_EQUAL +} S9xCheatComparisonType; typedef enum { - S9X_8_BITS, - S9X_16_BITS, - S9X_24_BITS, - S9X_32_BITS -} S9xCheatDataSize; + S9X_8_BITS, S9X_16_BITS, S9X_24_BITS, S9X_32_BITS +} S9xCheatDataSize; -extern SCheatData Cheat; -extern Watch watches[16]; +void S9xInitCheatData (); -void S9xApplyCheat (uint32); -void S9xApplyCheats (void); -void S9xRemoveCheat (uint32); -void S9xRemoveCheats (void); -void S9xDeleteCheat (uint32); -void S9xDeleteCheats (void); -void S9xEnableCheat (uint32); -void S9xDisableCheat (uint32); -void S9xAddCheat (bool8, bool8, uint32, uint8); -void S9xInitCheatData (void); -void S9xInitWatchedAddress (void); -bool8 S9xLoadCheatFile (const char *); -bool8 S9xSaveCheatFile (const char *); +const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte); +const char *S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte); +const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, + uint8 &num_bytes, uint8 bytes[3]); +void S9xApplyCheats (); +void S9xApplyCheat (uint32 which1); +void S9xRemoveCheats (); +void S9xRemoveCheat (uint32 which1); +void S9xEnableCheat (uint32 which1); +void S9xDisableCheat (uint32 which1); +void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, + uint8 byte); +void S9xDeleteCheats (); +void S9xDeleteCheat (uint32 which1); +bool8 S9xLoadCheatFile (const char *filename); +bool8 S9xSaveCheatFile (const char *filename); void S9xStartCheatSearch (SCheatData *); -void S9xSearchForChange (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, bool8, bool8); -void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8, bool8); -void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8); +void S9xSearchForChange (SCheatData *, S9xCheatComparisonType cmp, + S9xCheatDataSize size, bool8 is_signed, bool8 update); +void S9xSearchForValue (SCheatData *, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, + bool8 is_signed, bool8 update); +void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 address, bool8 update); void S9xOutputCheatSearchResults (SCheatData *); -const char * S9xGameGenieToRaw (const char *, uint32 &, uint8 &); -const char * S9xProActionReplayToRaw (const char *, uint32 &, uint8 &); -const char * S9xGoldFingerToRaw (const char *, uint32 &, bool8 &, uint8 &, uint8 bytes[3]); - #endif + diff --git a/source/snes9x/cheats2.cpp b/source/snes9x/cheats2.cpp index 0804e77..55fb2dd 100644 --- a/source/snes9x/cheats2.cpp +++ b/source/snes9x/cheats2.cpp @@ -159,232 +159,223 @@ **********************************************************************************/ + +#include +#include +#include #include "snes9x.h" -#include "memmap.h" #include "cheats.h" +#include "memmap.h" -static uint8 S9xGetByteFree (uint32); -static void S9xSetByteFree (uint8, uint32); +#ifndef INLINE +#define INLINE inline +#endif +extern SCheatData Cheat; +Watch watches [16]; -static uint8 S9xGetByteFree (uint32 address) +// read a byte without altering CPU +INLINE uint8 S9xGetByteFree (uint32 Address) { - uint32 Cycles = CPU.Cycles; - uint32 WaitAddress = CPU.WaitAddress; - uint8 byte; - - byte = S9xGetByte(address); - + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + uint8 rv = S9xGetByte (Address); CPU.WaitAddress = WaitAddress; CPU.Cycles = Cycles; - - return (byte); + return rv; } - -static void S9xSetByteFree (uint8 byte, uint32 address) +INLINE void S9xSetByteFree (uint8 Byte, uint32 Address) { - uint32 Cycles = CPU.Cycles; - uint32 WaitAddress = CPU.WaitAddress; - - S9xSetByte(byte, address); - + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + S9xSetByte (Byte, Address); CPU.WaitAddress = WaitAddress; CPU.Cycles = Cycles; } -void S9xInitWatchedAddress (void) +void S9xInitCheatData () { - for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) - watches[i].on = false; - + Cheat.RAM = Memory.RAM; + Cheat.SRAM = Memory.SRAM; + Cheat.FillRAM = Memory.FillRAM; } -void S9xInitCheatData (void) +void S9xAddCheat (bool8 enable, bool8 save_current_value, + uint32 address, uint8 byte) { - Cheat.RAM = Memory.RAM; - Cheat.SRAM = Memory.SRAM; - Cheat.FillRAM = Memory.FillRAM; -} - -void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte) -{ - if (Cheat.num_cheats < sizeof(Cheat.c) / sizeof(Cheat.c[0])) + if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0])) + { + Cheat.c [Cheat.num_cheats].address = address; + Cheat.c [Cheat.num_cheats].byte = byte; +#ifdef __MACOSX__ + Cheat.c [Cheat.num_cheats].enabled = enable; +#else + Cheat.c [Cheat.num_cheats].enabled = TRUE; +#endif + if (save_current_value) { - Cheat.c[Cheat.num_cheats].address = address; - Cheat.c[Cheat.num_cheats].byte = byte; - Cheat.c[Cheat.num_cheats].enabled = enable; - - if (save_current_value) - { - Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(address); - Cheat.c[Cheat.num_cheats].saved = TRUE; - } - - Cheat.num_cheats++; + Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByteFree (address); + Cheat.c [Cheat.num_cheats].saved = TRUE; } + Cheat.num_cheats++; + } } void S9xDeleteCheat (uint32 which1) { - if (which1 < Cheat.num_cheats) - { - if (Cheat.c[which1].enabled) - S9xRemoveCheat(which1); + if (which1 < Cheat.num_cheats) + { + if (Cheat.c [which1].enabled) + S9xRemoveCheat (which1); - memmove(&Cheat.c[which1], &Cheat.c[which1 + 1], sizeof(Cheat.c[0]) * (Cheat.num_cheats - which1 - 1)); - - Cheat.num_cheats--; - } + memmove (&Cheat.c [which1], &Cheat.c [which1 + 1], + sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1)); + Cheat.num_cheats--; //MK: This used to set it to 0?? + } } -void S9xDeleteCheats (void) +void S9xDeleteCheats () { - S9xRemoveCheats(); - Cheat.num_cheats = 0; -} - -void S9xRemoveCheat (uint32 which1) -{ - if (Cheat.c[which1].saved) - { - uint32 address = Cheat.c[which1].address; - - int block = (address & 0xffffff) >> MEMMAP_SHIFT; - uint8 *ptr = Memory.Map[block]; - - if (ptr >= (uint8 *) CMemory::MAP_LAST) - *(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte; - else - S9xSetByteFree(Cheat.c[which1].saved_byte, address); - } -} - -void S9xRemoveCheats (void) -{ - for (uint32 i = 0; i < Cheat.num_cheats; i++) - if (Cheat.c[i].enabled) - S9xRemoveCheat(i); + S9xRemoveCheats (); + Cheat.num_cheats = 0; } void S9xEnableCheat (uint32 which1) { - if (which1 < Cheat.num_cheats && !Cheat.c[which1].enabled) - { - Cheat.c[which1].enabled = TRUE; - S9xApplyCheat(which1); - } + if (which1 < Cheat.num_cheats && !Cheat.c [which1].enabled) + { + Cheat.c [which1].enabled = TRUE; + S9xApplyCheat (which1); + } } void S9xDisableCheat (uint32 which1) { - if (which1 < Cheat.num_cheats && Cheat.c[which1].enabled) - { - S9xRemoveCheat(which1); - Cheat.c[which1].enabled = FALSE; - } + if (which1 < Cheat.num_cheats && Cheat.c [which1].enabled) + { + S9xRemoveCheat (which1); + Cheat.c [which1].enabled = FALSE; + } +} + +void S9xRemoveCheat (uint32 which1) +{ + if (Cheat.c [which1].saved) + { + uint32 address = Cheat.c [which1].address; + + int block = ((address&0xffffff) >> MEMMAP_SHIFT); + uint8 *ptr = Memory.Map [block]; + + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c [which1].saved_byte; + else + S9xSetByte (Cheat.c [which1].saved_byte, address); + } } void S9xApplyCheat (uint32 which1) { - uint32 address = Cheat.c[which1].address; + uint32 address = Cheat.c [which1].address; - if (!Cheat.c[which1].saved) - { - Cheat.c[which1].saved_byte = S9xGetByteFree(address); - Cheat.c[which1].saved = TRUE; - } + if (!Cheat.c [which1].saved) + Cheat.c [which1].saved_byte = S9xGetByteFree (address); - int block = (address & 0xffffff) >> MEMMAP_SHIFT; - uint8 *ptr = Memory.Map[block]; + int block = ((address&0xffffff) >> MEMMAP_SHIFT); + uint8 *ptr = Memory.Map [block]; - if (ptr >= (uint8 *) CMemory::MAP_LAST) - *(ptr + (address & 0xffff)) = Cheat.c[which1].byte; - else - S9xSetByteFree(Cheat.c[which1].byte, address); + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c [which1].byte; + else + S9xSetByte (Cheat.c [which1].byte, address); + Cheat.c [which1].saved = TRUE; } -void S9xApplyCheats (void) +void S9xApplyCheats () { - if (Settings.ApplyCheats) - { - for (uint32 i = 0; i < Cheat.num_cheats; i++) - if (Cheat.c[i].enabled) - S9xApplyCheat(i); - } + if (Settings.ApplyCheats) + { + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c [i].enabled) + S9xApplyCheat (i); + } +} + +void S9xRemoveCheats () +{ + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c [i].enabled) + S9xRemoveCheat (i); } bool8 S9xLoadCheatFile (const char *filename) { - FILE *fs; - uint8 data[28]; + Cheat.num_cheats = 0; - Cheat.num_cheats = 0; + FILE *fs = fopen (filename, "rb"); + uint8 data [28]; - fs = fopen(filename, "rb"); - if (!fs) - return (FALSE); + if (!fs) + return (FALSE); - while (fread((void *) data, 1, 28, fs) == 28) - { - Cheat.c[Cheat.num_cheats].enabled = (data[0] & 4) == 0; - Cheat.c[Cheat.num_cheats].byte = data[1]; - Cheat.c[Cheat.num_cheats].address = data[2] | (data[3] << 8) | (data[4] << 16); - Cheat.c[Cheat.num_cheats].saved_byte = data[5]; - Cheat.c[Cheat.num_cheats].saved = (data[0] & 8) != 0; - memmove(Cheat.c[Cheat.num_cheats].name, &data[8], 20); - Cheat.c[Cheat.num_cheats++].name[20] = 0; - } + while (fread ((void *) data, 1, 28, fs) == 28) + { + Cheat.c [Cheat.num_cheats].enabled = (data [0] & 4) == 0; + Cheat.c [Cheat.num_cheats].byte = data [1]; + Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16); + Cheat.c [Cheat.num_cheats].saved_byte = data [5]; + Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0; + memmove (Cheat.c [Cheat.num_cheats].name, &data [8], 20); + Cheat.c [Cheat.num_cheats++].name [20] = 0; + } + fclose (fs); - fclose(fs); - - return (TRUE); + return (TRUE); } bool8 S9xSaveCheatFile (const char *filename) { - if (Cheat.num_cheats == 0) + if (Cheat.num_cheats == 0) + { + (void) remove (filename); + return (TRUE); + } + + FILE *fs = fopen (filename, "wb"); + uint8 data [28]; + + if (!fs) + return (FALSE); + + uint32 i; + for (i = 0; i < Cheat.num_cheats; i++) + { + memset (data, 0, 28); + if (i == 0) { - remove(filename); - return (TRUE); + data [6] = 254; + data [7] = 252; } + if (!Cheat.c [i].enabled) + data [0] |= 4; - FILE *fs; - uint8 data[28]; + if (Cheat.c [i].saved) + data [0] |= 8; - fs = fopen(filename, "wb"); - if (!fs) - return (FALSE); + data [1] = Cheat.c [i].byte; + data [2] = (uint8) Cheat.c [i].address; + data [3] = (uint8) (Cheat.c [i].address >> 8); + data [4] = (uint8) (Cheat.c [i].address >> 16); + data [5] = Cheat.c [i].saved_byte; - for (uint32 i = 0; i < Cheat.num_cheats; i++) + memmove (&data [8], Cheat.c [i].name, 19); + if (fwrite (data, 28, 1, fs) != 1) { - ZeroMemory(data, 28); - - if (i == 0) - { - data[6] = 254; - data[7] = 252; - } - - if (!Cheat.c[i].enabled) - data[0] |= 4; - - if (Cheat.c[i].saved) - data[0] |= 8; - - data[1] = Cheat.c[i].byte; - data[2] = (uint8) (Cheat.c[i].address >> 0); - data[3] = (uint8) (Cheat.c[i].address >> 8); - data[4] = (uint8) (Cheat.c[i].address >> 16); - data[5] = Cheat.c[i].saved_byte; - - memmove(&data[8], Cheat.c[i].name, 19); - - if (fwrite(data, 28, 1, fs) != 1) - { - fclose(fs); - return (FALSE); - } + fclose (fs); + return (FALSE); } - - return (fclose(fs) == 0); + } + return (fclose (fs) == 0); } + + diff --git a/source/snes9x/clip.cpp b/source/snes9x/clip.cpp index e64cfee..13947d3 100644 --- a/source/snes9x/clip.cpp +++ b/source/snes9x/clip.cpp @@ -159,231 +159,189 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" +#include "ppu.h" -static uint8 region_map[6][6] = -{ - { 0, 0x01, 0x03, 0x07, 0x0f, 0x1f }, - { 0, 0, 0x02, 0x06, 0x0e, 0x1e }, - { 0, 0, 0, 0x04, 0x0c, 0x1c }, - { 0, 0, 0, 0, 0x08, 0x18 }, - { 0, 0, 0, 0, 0, 0x10 } +static uint8 region_map[6][6]={ + {0, 0x01, 0x03, 0x07, 0x0f, 0x1f }, + {0, 0, 0x02, 0x06, 0x0e, 0x1e }, + {0, 0, 0, 0x04, 0x0c, 0x1c }, + {0, 0, 0, 0, 0x08, 0x18 }, + {0, 0, 0, 0, 0, 0x10 } }; -static inline uint8 CalcWindowMask (int, uint8, uint8); -static inline void StoreWindowRegions (uint8, struct ClipData *, int, int16 *, uint8 *, bool8, bool8 s = FALSE); +static inline uint8 CalcWindowMask(int i, uint8 W1, uint8 W2){ + if(!PPU.ClipWindow1Enable[i]){ + if(!PPU.ClipWindow2Enable[i]){ + return 0; + } else { + if(!PPU.ClipWindow2Inside[i]) return ~W2; + return W2; + } + } else { + if(!PPU.ClipWindow2Enable[i]){ + if(!PPU.ClipWindow1Inside[i]) return ~W1; + return W1; + } else { + if(!PPU.ClipWindow1Inside[i]) W1=~W1; + if(!PPU.ClipWindow2Inside[i]) W2=~W2; + switch(PPU.ClipWindowOverlapLogic[i]){ + case 0: // OR + return W1|W2; + case 1: // AND + return W1&W2; + case 2: // XOR + return W1^W2; + case 3: // XNOR + return ~(W1^W2); + } + } + } - -static inline uint8 CalcWindowMask (int i, uint8 W1, uint8 W2) -{ - if (!PPU.ClipWindow1Enable[i]) - { - if (!PPU.ClipWindow2Enable[i]) - return (0); - else - { - if (!PPU.ClipWindow2Inside[i]) - return (~W2); - return (W2); - } - } - else - { - if (!PPU.ClipWindow2Enable[i]) - { - if (!PPU.ClipWindow1Inside[i]) - return (~W1); - return (W1); - } - else - { - if (!PPU.ClipWindow1Inside[i]) - W1 = ~W1; - if (!PPU.ClipWindow2Inside[i]) - W2 = ~W2; - - switch (PPU.ClipWindowOverlapLogic[i]) - { - case 0: // OR - return (W1 | W2); - - case 1: // AND - return (W1 & W2); - - case 2: // XOR - return (W1 ^ W2); - - case 3: // XNOR - return (~(W1 ^ W2)); - } - } - } - - // Never get here - return (0); + // Never get here + return 0; } -static inline void StoreWindowRegions (uint8 Mask, struct ClipData *Clip, int n_regions, int16 *windows, uint8 *drawing_modes, bool8 sub, bool8 StoreMode0) -{ - int ct = 0; - - for (int j = 0; j < n_regions; j++) - { - int DrawMode = drawing_modes[j]; - if (sub) - DrawMode |= 1; - if (Mask & (1 << j)) - DrawMode = 0; - - if (!StoreMode0 && !DrawMode) - continue; - - if (ct > 0 && Clip->Right[ct - 1] == windows[j] && Clip->DrawMode[ct - 1] == DrawMode) - Clip->Right[ct - 1] = windows[j + 1]; // This region borders with and has the same drawing mode as the previous region: merge them. - else - { - // Add a new region to the BG - Clip->Left[ct] = windows[j]; - Clip->Right[ct] = windows[j + 1]; - Clip->DrawMode[ct] = DrawMode; - ct++; - } - } - - Clip->Count = ct; +static inline void StoreWindowRegions(uint8 Mask, struct ClipData *Clip, int n_regions, int16 *windows, uint8 *drawing_modes, bool8 sub, bool8 StoreMode0=FALSE){ + int ct=0; + for(int j=0; j0 && Clip->Right[ct-1]==windows[j] && Clip->DrawMode[ct-1]==DrawMode){ + // This region borders with and has the same drawing mode as the + // previous region: merge them. + Clip->Right[ct-1]=windows[j+1]; + } else { + // Add a new region to the BG + Clip->Left[ct]=windows[j]; + Clip->Right[ct]=windows[j+1]; + Clip->DrawMode[ct]=DrawMode; + ct++; + } + } + Clip->Count=ct; } -void S9xComputeClipWindows (void) -{ - int16 windows[6] = { 0, 256, 256, 256, 256, 256 }; - uint8 drawing_modes[5] = { 0, 0, 0, 0, 0 }; - int n_regions = 1; - int i, j; +void ComputeClipWindows () { + int16 windows[6]={0,256,256,256,256,256}; + uint8 drawing_modes[5]={0,0,0,0,0}; + int n_regions=1; + int i, j; - // Calculate window regions. We have at most 5 regions, because we have 6 control points - // (screen edges, window 1 left & right, and window 2 left & right). + // Calculate window regions. We have at most 5 regions, because we have 6 + // control points (screen edges, window 1 left & right, and window 2 left & + // right). + if(PPU.Window1Left<=PPU.Window1Right){ + if(PPU.Window1Left>0){ + windows[2]=256; + windows[1]=PPU.Window1Left; + n_regions=2; + } + if(PPU.Window1Right<255){ + windows[n_regions+1]=256; + windows[n_regions]=PPU.Window1Right+1; + n_regions++; + } + } + if(PPU.Window2Left<=PPU.Window2Right){ + for(i=0; i<=n_regions; i++){ + if(PPU.Window2Left==windows[i]) break; + if(PPU.Window2Left=i; j--){ + windows[j+1]=windows[j]; + } + windows[i]=PPU.Window2Left; + n_regions++; + break; + } + } + for(; i<=n_regions; i++){ + if(PPU.Window2Right+1==windows[i]) break; + if(PPU.Window2Right+1=i; j--){ + windows[j+1]=windows[j]; + } + windows[i]=PPU.Window2Right+1; + n_regions++; + break; + } + } + } - if (PPU.Window1Left <= PPU.Window1Right) - { - if (PPU.Window1Left > 0) - { - windows[2] = 256; - windows[1] = PPU.Window1Left; - n_regions = 2; - } + // Get a bitmap of which regions correspond to each window. + uint8 W1, W2; - if (PPU.Window1Right < 255) - { - windows[n_regions + 1] = 256; - windows[n_regions] = PPU.Window1Right + 1; - n_regions++; - } - } + if(PPU.Window1Left<=PPU.Window1Right){ + for(i=0; windows[i]!=PPU.Window1Left; i++); + for(j=i; windows[j]!=PPU.Window1Right+1; j++); + W1=region_map[i][j]; + } else { + W1=0; + } + if(PPU.Window2Left<=PPU.Window2Right){ + for(i=0; windows[i]!=PPU.Window2Left; i++); + for(j=i; windows[j]!=PPU.Window2Right+1; j++); + W2=region_map[i][j]; + } else { + W2=0; + } - if (PPU.Window2Left <= PPU.Window2Right) - { - for (i = 0; i <= n_regions; i++) - { - if (PPU.Window2Left == windows[i]) - break; + // Color Window affects the drawing mode for each region. Modes are: 3=Draw + // as normal, 2=clip color (math only), 1=no math (draw only), 0=nothing. + uint8 CW_color=0, CW_math=0; + uint8 CW=CalcWindowMask(5,W1,W2); - if (PPU.Window2Left < windows[i]) - { - for (j = n_regions; j >= i; j--) - windows[j + 1] = windows[j]; + switch(Memory.FillRAM[0x2130]&0xc0){ + case 0x00: + CW_color=0; + break; + case 0x40: + CW_color=~CW; + break; + case 0x80: + CW_color=CW; + break; + case 0xc0: + CW_color=0xff; + break; + } + switch(Memory.FillRAM[0x2130]&0x30){ + case 0x00: + CW_math=0; + break; + case 0x10: + CW_math=~CW; + break; + case 0x20: + CW_math=CW; + break; + case 0x30: + CW_math=0xff; + break; + } + for(i=0; i= i; j--) - windows[j + 1] = windows[j]; - - windows[i] = PPU.Window2Right + 1; - n_regions++; - break; - } - } - } - - // Get a bitmap of which regions correspond to each window. - - uint8 W1, W2; - - if (PPU.Window1Left <= PPU.Window1Right) - { - for (i = 0; windows[i] != PPU.Window1Left; i++) ; - for (j = i; windows[j] != PPU.Window1Right + 1; j++) ; - W1 = region_map[i][j]; - } - else - W1 = 0; - - if (PPU.Window2Left <= PPU.Window2Right) - { - for (i = 0; windows[i] != PPU.Window2Left; i++) ; - for (j = i; windows[j] != PPU.Window2Right + 1; j++) ; - W2 = region_map[i][j]; - } - else - W2 = 0; - - // Color Window affects the drawing mode for each region. - // Modes are: 3=Draw as normal, 2=clip color (math only), 1=no math (draw only), 0=nothing. - - uint8 CW_color = 0, CW_math = 0; - uint8 CW = CalcWindowMask(5, W1, W2); - - switch (Memory.FillRAM[0x2130] & 0xc0) - { - case 0x00: CW_color = 0; break; - case 0x40: CW_color = ~CW; break; - case 0x80: CW_color = CW; break; - case 0xc0: CW_color = 0xff; break; - } - - switch (Memory.FillRAM[0x2130] & 0x30) - { - case 0x00: CW_math = 0; break; - case 0x10: CW_math = ~CW; break; - case 0x20: CW_math = CW; break; - case 0x30: CW_math = 0xff; break; - } - - for (i = 0; i < n_regions; i++) - { - if (!(CW_color & (1 << i))) - drawing_modes[i] |= 1; - if (!(CW_math & (1 << i))) - drawing_modes[i] |= 2; - } - - // Store backdrop clip window (draw everywhere color window allows) - - StoreWindowRegions(0, &IPPU.Clip[0][5], n_regions, windows, drawing_modes, FALSE, TRUE); - StoreWindowRegions(0, &IPPU.Clip[1][5], n_regions, windows, drawing_modes, TRUE, TRUE); - - // Store per-BG and OBJ clip windows - - for (j = 0; j < 5; j++) - { - uint8 W = Settings.DisableGraphicWindows ? 0 : CalcWindowMask(j, W1, W2); - for (int sub = 0; sub < 2; sub++) - { - if (Memory.FillRAM[sub + 0x212e] & (1 << j)) - StoreWindowRegions(W, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); - else - StoreWindowRegions(0, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); - } - } + // Store per-BG and OBJ clip windows + for(j=0; j<5; j++){ + uint8 W=Settings.DisableGraphicWindows?0:CalcWindowMask(j,W1,W2); + for(int sub=0; sub<2; sub++){ + if(Memory.FillRAM[sub+0x212e]&(1< +#include +#include +#include +#include +#include #include #include #include #include #include -#include #include "snes9x.h" #include "memmap.h" -#include "apu/apu.h" -#include "snapshot.h" #include "controls.h" #include "crosshairs.h" -#include "movie.h" +#include "ppu.h" #include "display.h" +#include "cpuexec.h" +#include "snapshot.h" +#include "spc7110.h" +//#include "movie.h" #ifdef NETPLAY_SUPPORT #include "netplay.h" #endif -using namespace std; +#ifdef __WIN32__ +#define snprintf _snprintf // needs ANSI compliant name +#endif -#define NONE (-2) -#define MP5 (-1) -#define JOYPAD0 0 -#define JOYPAD1 1 -#define JOYPAD2 2 -#define JOYPAD3 3 -#define JOYPAD4 4 -#define JOYPAD5 5 -#define JOYPAD6 6 -#define JOYPAD7 7 -#define MOUSE0 8 -#define MOUSE1 9 -#define SUPERSCOPE 10 -#define ONE_JUSTIFIER 11 -#define TWO_JUSTIFIERS 12 -#define NUMCTLS 13 // This must be LAST +using namespace std; -#define POLL_ALL NUMCTLS +#define NONE -2 +#define MP5 -1 +#define JOYPAD0 0 +#define JOYPAD1 1 +#define JOYPAD2 2 +#define JOYPAD3 3 +#define JOYPAD4 4 +#define JOYPAD5 5 +#define JOYPAD6 6 +#define JOYPAD7 7 +#define MOUSE0 8 +#define MOUSE1 9 +#define SUPERSCOPE 10 +#define ONE_JUSTIFIER 11 +#define TWO_JUSTIFIERS 12 +#define NUMCTLS 13 // This must be LAST -#define SUPERSCOPE_FIRE 0x80 -#define SUPERSCOPE_CURSOR 0x40 -#define SUPERSCOPE_TURBO 0x20 -#define SUPERSCOPE_PAUSE 0x10 -#define SUPERSCOPE_OFFSCREEN 0x02 +#define POLL_ALL NUMCTLS -#define JUSTIFIER_TRIGGER 0x80 -#define JUSTIFIER_START 0x20 -#define JUSTIFIER_SELECT 0x08 +static map keymap; +static set pollmap[NUMCTLS+1]; +static vector multis; +struct exemulti { + int32 pos; + bool8 data1; + s9xcommand_t *script; +}; +static set exemultis; -#define MAP_UNKNOWN (-1) -#define MAP_NONE 0 -#define MAP_BUTTON 1 -#define MAP_AXIS 2 -#define MAP_POINTER 3 +static struct { + int16 x, y; + int16 V_adj; bool8 V_var; + int16 H_adj; bool8 H_var; + bool8 mapped; +} pseudopointer[8]; +static uint8 pseudobuttons[256]; -#define FLAG_IOBIT0 (Memory.FillRAM[0x4213] & 0x40) -#define FLAG_IOBIT1 (Memory.FillRAM[0x4213] & 0x80) -#define FLAG_IOBIT(n) ((n) ? (FLAG_IOBIT1) : (FLAG_IOBIT0)) - -bool8 pad_read = 0, pad_read_last = 0; -uint8 read_idx[2 /* ports */][2 /* per port */]; - -struct exemulti -{ - int32 pos; - bool8 data1; - s9xcommand_t *script; +struct crosshair { + uint8 set; + uint8 img; + uint8 fg; + uint8 bg; }; -struct crosshair -{ - uint8 set; - uint8 img; - uint8 fg, bg; -}; +static uint8 turbo_time; +static struct { + uint16 buttons; + uint16 turbos; + uint16 toggleturbo; + uint16 togglestick; + uint8 turbo_ct; +} joypad[8]; +static struct { + uint8 delta_x, delta_y; + int16 old_x, old_y; + int16 cur_x, cur_y; + uint8 buttons; + uint32 ID; + struct crosshair crosshair; +} mouse[2]; -static struct -{ - int16 x, y; - int16 V_adj; - bool8 V_var; - int16 H_adj; - bool8 H_var; - bool8 mapped; -} pseudopointer[8]; +#define SUPERSCOPE_FIRE 0x80 +#define SUPERSCOPE_CURSOR 0x40 +#define SUPERSCOPE_TURBO 0x20 +#define SUPERSCOPE_PAUSE 0x10 +#define SUPERSCOPE_OFFSCREEN 0x02 +static struct { + int16 x, y; + uint8 phys_buttons; + uint8 next_buttons; + uint8 read_buttons; + uint32 ID; + struct crosshair crosshair; +} superscope; -static struct -{ - uint16 buttons; - uint16 turbos; - uint16 toggleturbo; - uint16 togglestick; - uint8 turbo_ct; -} joypad[8]; +#define JUSTIFIER_TRIGGER 0x80 +#define JUSTIFIER_START 0x20 +#define JUSTIFIER_SELECT 0x08 +static struct { + int16 x[2], y[2]; + uint8 buttons; + bool8 offscreen[2]; + uint32 ID[2]; + struct crosshair crosshair[2]; +} justifier; +static struct { + int8 pads[4]; +} mp5[2]; -static struct -{ - uint8 delta_x, delta_y; - int16 old_x, old_y; - int16 cur_x, cur_y; - uint8 buttons; - uint32 ID; - struct crosshair crosshair; -} mouse[2]; +uint8 read_idx[2 /* ports */][2 /* per port */]; -static struct -{ - int16 x, y; - uint8 phys_buttons; - uint8 next_buttons; - uint8 read_buttons; - uint32 ID; - struct crosshair crosshair; -} superscope; +bool8 pad_read = 0, pad_read_last = 0; -static struct -{ - int16 x[2], y[2]; - uint8 buttons; - bool8 offscreen[2]; - uint32 ID[2]; - struct crosshair crosshair[2]; -} justifier; +#define FLAG_IOBIT0 (Memory.FillRAM[0x4213]&0x40) +#define FLAG_IOBIT1 (Memory.FillRAM[0x4213]&0x80) +#define FLAG_IOBIT(n) ((n)?(FLAG_IOBIT1):(FLAG_IOBIT0)) +static bool8 FLAG_LATCH=false; +static int32 curcontrollers[2]={ NONE, NONE }; +static int32 newcontrollers[2]={ JOYPAD0, NONE }; -static struct -{ - int8 pads[4]; -} mp5[2]; - -static set exemultis; -static set pollmap[NUMCTLS + 1]; -static map keymap; -static vector multis; -static uint8 turbo_time; -static uint8 pseudobuttons[256]; -static bool8 FLAG_LATCH = FALSE; -static int32 curcontrollers[2] = { NONE, NONE }; -static int32 newcontrollers[2] = { JOYPAD0, NONE }; -static char buf[256]; - -static const char *color_names[32] = -{ - "Trans", - "Black", - "25Grey", - "50Grey", - "75Grey", - "White", - "Red", - "Orange", - "Yellow", - "Green", - "Cyan", - "Sky", - "Blue", - "Violet", - "MagicPink", - "Purple", - NULL, - "tBlack", - "t25Grey", - "t50Grey", - "t75Grey", - "tWhite", - "tRed", - "tOrange", - "tYellow", - "tGreen", - "tCyan", - "tSky", - "tBlue", - "tViolet", - "tMagicPink", - "tPurple" -}; - -static const char *speed_names[4] = -{ - "Var", - "Slow", - "Med", - "Fast" -}; - -static const int ptrspeeds[4] = { 1, 1, 4, 8 }; +/*******************/ // Note: these should be in asciibetical order! #define THE_COMMANDS \ - S(BeginRecordingMovie), \ - S(ClipWindows), \ - S(Debugger), \ - S(DecEmuTurbo), \ - S(DecFrameRate), \ - S(DecFrameTime), \ - S(DecTurboSpeed), \ - S(EmuTurbo), \ - S(EndRecordingMovie), \ - S(ExitEmu), \ - S(IncEmuTurbo), \ - S(IncFrameRate), \ - S(IncFrameTime), \ - S(IncTurboSpeed), \ - S(LoadFreezeFile), \ - S(LoadMovie), \ - S(LoadOopsFile), \ - S(Pause), \ - S(QuickLoad000), \ - S(QuickLoad001), \ - S(QuickLoad002), \ - S(QuickLoad003), \ - S(QuickLoad004), \ - S(QuickLoad005), \ - S(QuickLoad006), \ - S(QuickLoad007), \ - S(QuickLoad008), \ - S(QuickLoad009), \ - S(QuickLoad010), \ - S(QuickSave000), \ - S(QuickSave001), \ - S(QuickSave002), \ - S(QuickSave003), \ - S(QuickSave004), \ - S(QuickSave005), \ - S(QuickSave006), \ - S(QuickSave007), \ - S(QuickSave008), \ - S(QuickSave009), \ - S(QuickSave010), \ - S(Reset), \ - S(SaveFreezeFile), \ - S(SaveSPC), \ - S(Screenshot), \ - S(SeekToFrame), \ - S(SoftReset), \ - S(SoundChannel0), \ - S(SoundChannel1), \ - S(SoundChannel2), \ - S(SoundChannel3), \ - S(SoundChannel4), \ - S(SoundChannel5), \ - S(SoundChannel6), \ - S(SoundChannel7), \ - S(SoundChannelsOn), \ - S(SwapJoypads), \ - S(ToggleBG0), \ - S(ToggleBG1), \ - S(ToggleBG2), \ - S(ToggleBG3), \ - S(ToggleEmuTurbo), \ - S(ToggleHDMA), \ - S(ToggleSprites), \ - S(ToggleTransparency) \ + S(BGLayeringHack), \ + S(BeginRecordingMovie), \ + S(ClipWindows), \ + S(Debugger), \ + S(DecEmuTurbo), \ + S(DecFrameRate), \ + S(DecFrameTime), \ + S(DecTurboSpeed), \ + S(DumpSPC7110Log), \ + S(EmuTurbo), \ + S(EndRecordingMovie), \ + S(ExitEmu), \ + S(IncEmuTurbo), \ + S(IncFrameRate), \ + S(IncFrameTime), \ + S(IncTurboSpeed), \ + S(InterpolateSound), \ + S(LoadFreezeFile), \ + S(LoadMovie), \ + S(LoadOopsFile), \ +/* S(Mode7Interpolate),*/ \ + S(Pause), \ + S(QuickLoad000), S(QuickLoad001), S(QuickLoad002), S(QuickLoad003), S(QuickLoad004), S(QuickLoad005), S(QuickLoad006), S(QuickLoad007), S(QuickLoad008), S(QuickLoad009), S(QuickLoad010), \ + S(QuickSave000), S(QuickSave001), S(QuickSave002), S(QuickSave003), S(QuickSave004), S(QuickSave005), S(QuickSave006), S(QuickSave007), S(QuickSave008), S(QuickSave009), S(QuickSave010), \ + S(Reset), \ + S(SaveFreezeFile), \ + S(SaveSPC), \ + S(Screenshot), \ + S(SeekToFrame), \ + S(SoftReset), \ + S(SoundChannel0), S(SoundChannel1), S(SoundChannel2), S(SoundChannel3), S(SoundChannel4), S(SoundChannel5), S(SoundChannel6), S(SoundChannel7), \ + S(SoundChannelsOn), \ + S(SwapJoypads), \ + S(SynchronizeSound), \ + S(ToggleBG0), S(ToggleBG1), S(ToggleBG2), S(ToggleBG3), \ + S(ToggleEmuTurbo), \ + S(ToggleHDMA), \ + S(ToggleSprites), \ + S(ToggleTransparency), \ + // end -#define S(x) x +#define S(x) x -enum command_numbers -{ - THE_COMMANDS, - LAST_COMMAND +enum command_numbers { + THE_COMMANDS + LAST_COMMAND // must be last! }; #undef S -#define S(x) #x +#define S(x) #x -static const char *command_names[LAST_COMMAND + 1] = -{ - THE_COMMANDS, - NULL +static const char *command_names[LAST_COMMAND+1]={ + THE_COMMANDS + NULL // This MUST be last! }; #undef S #undef THE_COMMANDS -static void DisplayStateChange (const char *, bool8); -static void DoGunLatch (int, int); -static int maptype (int); -static bool strless (const char *, const char *); -static int findstr (const char *, const char **, int); -static int get_threshold (const char **); -static const char * maptypename (int); -static int32 ApplyMulti (s9xcommand_t *, int32, int16); -static void do_polling (int); -static void UpdatePolledMouse (int); +static const char *color_names[32]={ + "Trans", "Black", "25Grey", "50Grey", "75Grey", "White", "Red", "Orange", "Yellow", "Green", "Cyan", "Sky", "Blue", "Violet", "MagicPink", "Purple", + NULL, "tBlack", "t25Grey", "t50Grey", "t75Grey", "tWhite", "tRed", "tOrange", "tYellow", "tGreen", "tCyan", "tSky", "tBlue", "tViolet", "tMagicPink", "tPurple" +}; +static const char *speed_names[4]={ "Var", "Slow", "Med", "Fast" }; -static string& operator += (string &s, int i) -{ - snprintf(buf, sizeof(buf), "%d", i); - s.append(buf); - return (s); +static const int ptrspeeds[4]={ 1, 1, 4, 8 }; + +/*******************/ + +static char buf[256]; +static string& operator+=(string &s, int i){ + snprintf(buf, sizeof(buf), "%d", i); + s.append(buf); + return s; } -static string& operator += (string &s, double d) -{ - snprintf(buf, sizeof(buf), "%g", d); - s.append(buf); - return (s); +static string& operator+=(string &s, double d){ + snprintf(buf, sizeof(buf), "%g", d); + s.append(buf); + return s; } -static void DisplayStateChange (const char *str, bool8 on) -{ - snprintf(buf, sizeof(buf), "%s: %s", str, on ? "on":"off"); - S9xSetInfoString(buf); +static void S9xDisplayStateChange(const char *str, bool8 on){ + snprintf(buf, sizeof(buf), "%s %s", str, on?"on":"off"); + S9xSetInfoString(buf); } -static void DoGunLatch (int x, int y) -{ - x += 40; +static void DoGunLatch(int x, int y){ + x+=40; + if(x>295) x=295; + if(x<40) x=40; + if(y>PPU.ScreenHeight-1) y=PPU.ScreenHeight-1; + if(y<0) y=0; - if (x > 295) - x = 295; - else - if (x < 40) - x = 40; - - if (y > PPU.ScreenHeight - 1) - y = PPU.ScreenHeight - 1; - else - if (y < 0) - y = 0; - - PPU.GunVLatch = (uint16) (y + 1); - PPU.GunHLatch = (uint16) x; + PPU.GunVLatch = (uint16) (y + 1); + PPU.GunHLatch = (uint16) x; } -static int maptype (int t) -{ - switch (t) - { - case S9xNoMapping: - return (MAP_NONE); +#define MAP_UNKNOWN -1 +#define MAP_NONE 0 +#define MAP_BUTTON 1 +#define MAP_AXIS 2 +#define MAP_POINTER 3 +static int maptype(int t){ + switch(t){ + case S9xNoMapping: + return MAP_NONE; - case S9xButtonJoypad: - case S9xButtonMouse: - case S9xButtonSuperscope: - case S9xButtonJustifier: - case S9xButtonCommand: - case S9xButtonPseudopointer: - case S9xButtonPort: - case S9xButtonMulti: - return (MAP_BUTTON); + case S9xButtonJoypad: + case S9xButtonMouse: + case S9xButtonSuperscope: + case S9xButtonJustifier: + case S9xButtonCommand: + case S9xButtonPseudopointer: + case S9xButtonPort: + case S9xButtonMulti: + return MAP_BUTTON; - case S9xAxisJoypad: - case S9xAxisPseudopointer: - case S9xAxisPseudobuttons: - case S9xAxisPort: - return (MAP_AXIS); + case S9xAxisJoypad: + case S9xAxisPseudopointer: + case S9xAxisPseudobuttons: + case S9xAxisPort: + return MAP_AXIS; - case S9xPointer: - case S9xPointerPort: - return (MAP_POINTER); + case S9xPointer: + case S9xPointerPort: + return MAP_POINTER; - default: - return (MAP_UNKNOWN); - } + default: + return MAP_UNKNOWN; + } } -void S9xControlsReset (void) -{ - S9xControlsSoftReset(); - mouse[0].buttons &= ~0x30; - mouse[1].buttons &= ~0x30; - justifier.buttons &= ~JUSTIFIER_SELECT; +void S9xControlsReset(void){ + S9xControlsSoftReset(); + mouse[0].buttons&=~0x30; + mouse[1].buttons&=~0x30; + justifier.buttons&=~JUSTIFIER_SELECT; } -void S9xControlsSoftReset (void) -{ - for (set::iterator it = exemultis.begin(); it != exemultis.end(); it++) - delete *it; - exemultis.clear(); +void S9xControlsSoftReset(void){ + int i, j; - for (int i = 0; i < 2; i++) - for (int j = 0; j < 2; j++) - read_idx[i][j]=0; - - FLAG_LATCH = FALSE; + for(set::iterator it=exemultis.begin(); it!=exemultis.end(); it++){ + delete *it; + } + exemultis.clear(); + for(i=0; i<2; i++){ + for(j=0; j<2; j++){ + read_idx[i][j]=0; + } + } + FLAG_LATCH=false; } -void S9xUnmapAllControls (void) -{ - S9xControlsReset(); +void S9xUnmapAllControls(void){ + int i; - keymap.clear(); - - for (int i = 0; i < (int) multis.size(); i++) - free(multis[i]); - multis.clear(); - - for (int i = 0; i < NUMCTLS + 1; i++) - pollmap[i].clear(); - - for (int i = 0; i < 8; i++) - { - pseudopointer[i].x = 0; - pseudopointer[i].y = 0; - pseudopointer[i].H_adj = 0; - pseudopointer[i].V_adj = 0; - pseudopointer[i].H_var = 0; - pseudopointer[i].V_var = 0; - pseudopointer[i].mapped = false; - - joypad[i].buttons = 0; - joypad[i].turbos = 0; - joypad[i].turbo_ct = 0; - } - - for (int i = 0; i < 2; i++) - { - mouse[i].old_x = mouse[i].old_y = 0; - mouse[i].cur_x = mouse[i].cur_y = 0; - mouse[i].buttons = 1; - mouse[i].ID = InvalidControlID; - - if (!(mouse[i].crosshair.set & 1)) - mouse[i].crosshair.img = 0; // no image for mouse because its only logical position is game-specific, not known by the emulator - if (!(mouse[i].crosshair.set & 2)) - mouse[i].crosshair.fg = 5; - if (!(mouse[i].crosshair.set & 4)) - mouse[i].crosshair.bg = 1; - - justifier.x[i] = justifier.y[i] = 0; - justifier.offscreen[i] = 0; - justifier.ID[i] = InvalidControlID; - - if (!(justifier.crosshair[i].set & 1)) - justifier.crosshair[i].img = 4; - if (!(justifier.crosshair[i].set & 2)) - justifier.crosshair[i].fg = i ? 14 : 12; - if (!(justifier.crosshair[i].set & 4)) - justifier.crosshair[i].bg = 1; - } - - justifier.buttons = 0; - - superscope.x = superscope.y = 0; - superscope.phys_buttons = 0; - superscope.next_buttons = 0; - superscope.read_buttons = 0; - superscope.ID = InvalidControlID; - - if (!(superscope.crosshair.set & 1)) - superscope.crosshair.img = 2; - if (!(superscope.crosshair.set & 2)) - superscope.crosshair.fg = 5; - if (!(superscope.crosshair.set & 4)) - superscope.crosshair.bg = 1; - - ZeroMemory(pseudobuttons, sizeof(pseudobuttons)); - - turbo_time = 1; + S9xControlsReset(); + keymap.clear(); + for(i=0; i<(int)multis.size(); i++){ + free(multis[i]); + } + multis.clear(); + for(i=0; i 1) - return; +void S9xSetController(int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4){ + if(port<0 || port>1) return; + switch(controller){ + case CTL_NONE: + break; + case CTL_JOYPAD: + if(id1<0 || id1>7) break; + newcontrollers[port]=JOYPAD0+id1; + return; + case CTL_MOUSE: + if(id1<0 || id1>1) break; + if(!Settings.MouseMaster){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); + break; + } + newcontrollers[port]=MOUSE0+id1; + return; + case CTL_SUPERSCOPE: + if(!Settings.SuperScopeMaster){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + break; + } + newcontrollers[port]=SUPERSCOPE; + return; + case CTL_JUSTIFIER: + if(id1<0 || id1>1) break; + if(!Settings.JustifierMaster){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); + break; + } + newcontrollers[port]=ONE_JUSTIFIER+id1; + return; + case CTL_MP5: + if(id1<-1 || id1>7) break; + if(id2<-1 || id2>7) break; + if(id3<-1 || id3>7) break; + if(id4<-1 || id4>7) break; + if(!Settings.MultiPlayer5Master){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + break; + } + newcontrollers[port]=MP5; + mp5[port].pads[0]=(id1<0)?NONE:JOYPAD0+id1; + mp5[port].pads[1]=(id2<0)?NONE:JOYPAD0+id2; + mp5[port].pads[2]=(id3<0)?NONE:JOYPAD0+id3; + mp5[port].pads[3]=(id4<0)?NONE:JOYPAD0+id4; + return; + default: + fprintf(stderr, "Unknown controller type %d\n", controller); + break; + } + newcontrollers[port]=NONE; + return; - switch (controller) - { - case CTL_NONE: - break; - - case CTL_JOYPAD: - if (id1 < 0 || id1 > 7) - break; - - newcontrollers[port] = JOYPAD0 + id1; - return; - - case CTL_MOUSE: - if (id1 < 0 || id1 > 1) - break; - if (!Settings.MouseMaster) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); - break; - } - - newcontrollers[port] = MOUSE0 + id1; - return; - - case CTL_SUPERSCOPE: - if (!Settings.SuperScopeMaster) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); - break; - } - - newcontrollers[port] = SUPERSCOPE; - return; - - case CTL_JUSTIFIER: - if (id1 < 0 || id1 > 1) - break; - if (!Settings.JustifierMaster) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); - break; - } - - newcontrollers[port] = ONE_JUSTIFIER + id1; - return; - - case CTL_MP5: - if (id1 < -1 || id1 > 7) - break; - if (id2 < -1 || id2 > 7) - break; - if (id3 < -1 || id3 > 7) - break; - if (id4 < -1 || id4 > 7) - break; - if (!Settings.MultiPlayer5Master) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); - break; - } - - newcontrollers[port] = MP5; - mp5[port].pads[0] = (id1 < 0) ? NONE : JOYPAD0 + id1; - mp5[port].pads[1] = (id2 < 0) ? NONE : JOYPAD0 + id2; - mp5[port].pads[2] = (id3 < 0) ? NONE : JOYPAD0 + id3; - mp5[port].pads[3] = (id4 < 0) ? NONE : JOYPAD0 + id4; - return; - - default: - fprintf(stderr, "Unknown controller type %d\n", controller); - break; - } - - newcontrollers[port] = NONE; } -bool S9xVerifyControllers (void) -{ - bool ret = false; - int port, i, used[NUMCTLS]; +bool S9xVerifyControllers(void){ + bool ret=false; + int port; + int i, used[NUMCTLS]; - for (i = 0; i < NUMCTLS; used[i++] = 0) ; + for(i=0; i0){ + snprintf(buf, sizeof(buf), "Mouse%d used more than once! Disabling extra instances", i-MOUSE0+1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port]=NONE; + ret=true; + break; + } + break; + case SUPERSCOPE: + if(!Settings.SuperScopeMaster){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + newcontrollers[port]=NONE; + ret=true; + break; + } + if(used[i]++>0){ + snprintf(buf, sizeof(buf), "Superscope used more than once! Disabling extra instances"); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port]=NONE; + ret=true; + break; + } + break; + case ONE_JUSTIFIER: case TWO_JUSTIFIERS: + if(!Settings.JustifierMaster){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); + newcontrollers[port]=NONE; + ret=true; + break; + } + if(used[ONE_JUSTIFIER]++>0){ + snprintf(buf, sizeof(buf), "Justifier used more than once! Disabling extra instances"); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port]=NONE; + ret=true; + break; + } + break; + case MP5: + if(!Settings.MultiPlayer5Master){ + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + newcontrollers[port]=NONE; + ret=true; + break; + } + for(i=0; i<4; i++){ + if(mp5[port].pads[i]!=NONE){ + if(used[mp5[port].pads[i]-JOYPAD0]++>0){ + snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", mp5[port].pads[i]-JOYPAD0+1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + mp5[port].pads[i]=NONE; + ret=true; + break; + } + } + } + break; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + if(used[i-JOYPAD0]++>0){ + snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", i-JOYPAD0+1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port]=NONE; + ret=true; + break; + } + break; + default: + break; + } + } - if (used[i]++ > 0) - { - snprintf(buf, sizeof(buf), "Mouse%d used more than once! Disabling extra instances", i - MOUSE0 + 1); - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); - newcontrollers[port] = NONE; - ret = true; - break; - } - - break; - - case SUPERSCOPE: - if (!Settings.SuperScopeMaster) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); - newcontrollers[port] = NONE; - ret = true; - break; - } - - if (used[i]++ > 0) - { - snprintf(buf, sizeof(buf), "Superscope used more than once! Disabling extra instances"); - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); - newcontrollers[port] = NONE; - ret = true; - break; - } - - break; - - case ONE_JUSTIFIER: - case TWO_JUSTIFIERS: - if (!Settings.JustifierMaster) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); - newcontrollers[port] = NONE; - ret = true; - break; - } - - if (used[ONE_JUSTIFIER]++ > 0) - { - snprintf(buf, sizeof(buf), "Justifier used more than once! Disabling extra instances"); - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); - newcontrollers[port] = NONE; - ret = true; - break; - } - - break; - - case MP5: - if (!Settings.MultiPlayer5Master) - { - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); - newcontrollers[port] = NONE; - ret = true; - break; - } - - for (i = 0; i < 4; i++) - { - if (mp5[port].pads[i] != NONE) - { - if (used[mp5[port].pads[i] - JOYPAD0]++ > 0) - { - snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", mp5[port].pads[i] - JOYPAD0 + 1); - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); - mp5[port].pads[i] = NONE; - ret = true; - break; - } - } - } - - break; - - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - if (used[i - JOYPAD0]++ > 0) - { - snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", i - JOYPAD0 + 1); - S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); - newcontrollers[port] = NONE; - ret = true; - break; - } - - break; - - default: - break; - } - } - - return (ret); + return ret; } -void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4) -{ - int i; +void S9xGetController(int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4){ + int i; - *controller = CTL_NONE; - *id1 = *id2 = *id3 = *id4 = -1; + *controller=CTL_NONE; + *id1=*id2=*id3=*id4=-1; + if(port<0 || port>1) return; + switch(i=newcontrollers[port]){ + case MP5: + *controller=CTL_MP5; + *id1=(mp5[port].pads[0]==NONE)?-1:mp5[port].pads[0]-JOYPAD0; + *id2=(mp5[port].pads[1]==NONE)?-1:mp5[port].pads[1]-JOYPAD0; + *id3=(mp5[port].pads[2]==NONE)?-1:mp5[port].pads[2]-JOYPAD0; + *id4=(mp5[port].pads[3]==NONE)?-1:mp5[port].pads[3]-JOYPAD0; + return; - if (port < 0 || port > 1) - return; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + *controller=CTL_JOYPAD; + *id1=i-JOYPAD0; + return; - switch (i = newcontrollers[port]) - { - case MP5: - *controller = CTL_MP5; - *id1 = (mp5[port].pads[0] == NONE) ? -1 : mp5[port].pads[0] - JOYPAD0; - *id2 = (mp5[port].pads[1] == NONE) ? -1 : mp5[port].pads[1] - JOYPAD0; - *id3 = (mp5[port].pads[2] == NONE) ? -1 : mp5[port].pads[2] - JOYPAD0; - *id4 = (mp5[port].pads[3] == NONE) ? -1 : mp5[port].pads[3] - JOYPAD0; - return; + case MOUSE0: case MOUSE1: + *controller=CTL_MOUSE; + *id1=i-MOUSE0; + return; - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - *controller = CTL_JOYPAD; - *id1 = i - JOYPAD0; - return; + case SUPERSCOPE: + *controller=CTL_SUPERSCOPE; + *id1=1; + return; - case MOUSE0: - case MOUSE1: - *controller = CTL_MOUSE; - *id1 = i - MOUSE0; - return; - - case SUPERSCOPE: - *controller = CTL_SUPERSCOPE; - *id1 = 1; - return; - - case ONE_JUSTIFIER: - case TWO_JUSTIFIERS: - *controller = CTL_JUSTIFIER; - *id1 = i - ONE_JUSTIFIER; - return; - } + case ONE_JUSTIFIER: case TWO_JUSTIFIERS: + *controller=CTL_JUSTIFIER; + *id1=i-ONE_JUSTIFIER; + return; + } } -void S9xReportControllers (void) -{ - static char mes[128]; - char *c = mes; +void S9xReportControllers(void){ + int port, i; + static char buf[128]; // static because S9xMessage keeps our pointer instead of copying + char *c=buf; - S9xVerifyControllers(); + S9xVerifyControllers(); + for(port=0; port<2; port++){ + c+=sprintf(c, "Port %d: ", port+1); + switch(newcontrollers[port]){ + case NONE: + c+=sprintf(c, ". "); + break; - for (int port = 0; port < 2; port++) - { - c += sprintf(c, "Port %d: ", port + 1); + case MP5: + c+=sprintf(c, "MP5 with pads"); + for(i=0; i<4; i++){ + if(mp5[port].pads[i]==NONE){ + c+=sprintf(c, " . "); + } else { + c+=sprintf(c, " #%d. ", mp5[port].pads[i]+1-JOYPAD0); + } + } + break; - switch (newcontrollers[port]) - { - case NONE: - c += sprintf(c, ". "); - break; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + c+=sprintf(c, "Pad #%d. ", (int)(newcontrollers[port]-JOYPAD0+1)); + break; - case MP5: - c += sprintf(c, "MP5 with pads"); - for (int i = 0; i < 4; i++) - { - if (mp5[port].pads[i] == NONE) - c += sprintf(c, " . "); - else - c += sprintf(c, " #%d. ", mp5[port].pads[i] + 1 - JOYPAD0); - } + case MOUSE0: case MOUSE1: + c+=sprintf(c, "Mouse #%d. ", (int)(newcontrollers[port]-MOUSE0+1)); + break; - break; + case SUPERSCOPE: + if(port==0) c+=sprintf(c, "Superscope (cannot fire). "); + else c+=sprintf(c, "Superscope. "); + break; - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - c += sprintf(c, "Pad #%d. ", (int) (newcontrollers[port] - JOYPAD0 + 1)); - break; + case ONE_JUSTIFIER: + if(port==0) c+=sprintf(c, "Blue Justifier (cannot fire). "); + else c+=sprintf(c, "Blue Justifier. "); + break; - case MOUSE0: - case MOUSE1: - c += sprintf(c, "Mouse #%d. ", (int) (newcontrollers[port] - MOUSE0 + 1)); - break; - - case SUPERSCOPE: - if (port == 0) - c += sprintf(c, "Superscope (cannot fire). "); - else - c += sprintf(c, "Superscope. "); - break; - - case ONE_JUSTIFIER: - if (port == 0) - c += sprintf(c, "Blue Justifier (cannot fire). "); - else - c += sprintf(c, "Blue Justifier. "); - break; - - case TWO_JUSTIFIERS: - if (port == 0) - c += sprintf(c, "Blue and Pink Justifiers (cannot fire). "); - else - c += sprintf(c, "Blue and Pink Justifiers. "); - break; - } - } - - S9xMessage(S9X_INFO, S9X_CONFIG_INFO, mes); + case TWO_JUSTIFIERS: + if(port==0) c+=sprintf(c, "Blue and Pink Justifiers (cannot fire). "); + else c+=sprintf(c, "Blue and Pink Justifiers. "); + break; + } + } + S9xMessage(S9X_INFO, S9X_CONFIG_INFO, buf); } -char * S9xGetCommandName (s9xcommand_t command) -{ - string s; - char c; - switch (command.type) - { - case S9xButtonJoypad: - if (command.button.joypad.buttons == 0) - return (strdup("None")); - if (command.button.joypad.buttons & 0x000f) - return (strdup("None")); +char *S9xGetCommandName(s9xcommand_t command){ + string s; + char c; - s = "Joypad"; - s += command.button.joypad.idx + 1; + switch(command.type){ + case S9xButtonJoypad: + if(command.button.joypad.buttons==0) return strdup("None"); + if(command.button.joypad.buttons&0x000f) return strdup("None"); + s="Joypad"; + s+=command.button.joypad.idx+1; + c=' '; + if(command.button.joypad.toggle){ if(c) s+=c; s+="Toggle"; c=0; } + if(command.button.joypad.sticky){ if(c) s+=c; s+="Sticky"; c=0; } + if(command.button.joypad.turbo){ if(c) s+=c; s+="Turbo"; c=0; } - c = ' '; - if (command.button.joypad.toggle) { if (c) s += c; s += "Toggle"; c = 0; } - if (command.button.joypad.sticky) { if (c) s += c; s += "Sticky"; c = 0; } - if (command.button.joypad.turbo ) { if (c) s += c; s += "Turbo"; c = 0; } + c=' '; + if(command.button.joypad.buttons&SNES_UP_MASK){ s+=c; s+="Up"; c='+'; } + if(command.button.joypad.buttons&SNES_DOWN_MASK){ s+=c; s+="Down"; c='+'; } + if(command.button.joypad.buttons&SNES_LEFT_MASK){ s+=c; s+="Left"; c='+'; } + if(command.button.joypad.buttons&SNES_RIGHT_MASK){ s+=c; s+="Right"; c='+'; } + if(command.button.joypad.buttons&SNES_A_MASK){ s+=c; s+="A"; c='+'; } + if(command.button.joypad.buttons&SNES_B_MASK){ s+=c; s+="B"; c='+'; } + if(command.button.joypad.buttons&SNES_X_MASK){ s+=c; s+="X"; c='+'; } + if(command.button.joypad.buttons&SNES_Y_MASK){ s+=c; s+="Y"; c='+'; } + if(command.button.joypad.buttons&SNES_TL_MASK){ s+=c; s+="L"; c='+'; } + if(command.button.joypad.buttons&SNES_TR_MASK){ s+=c; s+="R"; c='+'; } + if(command.button.joypad.buttons&SNES_START_MASK){ s+=c; s+="Start"; c='+'; } + if(command.button.joypad.buttons&SNES_SELECT_MASK){ s+=c; s+="Select"; c='+'; } + break; - c = ' '; - if (command.button.joypad.buttons & SNES_UP_MASK ) { s += c; s += "Up"; c = '+'; } - if (command.button.joypad.buttons & SNES_DOWN_MASK ) { s += c; s += "Down"; c = '+'; } - if (command.button.joypad.buttons & SNES_LEFT_MASK ) { s += c; s += "Left"; c = '+'; } - if (command.button.joypad.buttons & SNES_RIGHT_MASK ) { s += c; s += "Right"; c = '+'; } - if (command.button.joypad.buttons & SNES_A_MASK ) { s += c; s += "A"; c = '+'; } - if (command.button.joypad.buttons & SNES_B_MASK ) { s += c; s += "B"; c = '+'; } - if (command.button.joypad.buttons & SNES_X_MASK ) { s += c; s += "X"; c = '+'; } - if (command.button.joypad.buttons & SNES_Y_MASK ) { s += c; s += "Y"; c = '+'; } - if (command.button.joypad.buttons & SNES_TL_MASK ) { s += c; s += "L"; c = '+'; } - if (command.button.joypad.buttons & SNES_TR_MASK ) { s += c; s += "R"; c = '+'; } - if (command.button.joypad.buttons & SNES_START_MASK ) { s += c; s += "Start"; c = '+'; } - if (command.button.joypad.buttons & SNES_SELECT_MASK) { s += c; s += "Select"; c = '+'; } + case S9xButtonMouse: + if(!command.button.mouse.left && !command.button.mouse.right) return strdup("None"); + s="Mouse"; + s+=command.button.mouse.idx+1; + s+=" "; + if(command.button.mouse.left) s+="L"; + if(command.button.mouse.right) s+="R"; + break; - break; + case S9xButtonSuperscope: + if(!command.button.scope.fire && !command.button.scope.cursor && !command.button.scope.turbo && !command.button.scope.pause && !command.button.scope.aim_offscreen) return strdup("None"); + s="Superscope"; + if(command.button.scope.aim_offscreen) s+=" AimOffscreen"; + c=' '; + if(command.button.scope.fire){ s+=c; s+="Fire"; c='+'; } + if(command.button.scope.cursor){ s+=c; s+="Cursor"; c='+'; } + if(command.button.scope.turbo){ s+=c; s+="ToggleTurbo"; c='+'; } + if(command.button.scope.pause){ s+=c; s+="Pause"; c='+'; } + break; - case S9xButtonMouse: - if (!command.button.mouse.left && !command.button.mouse.right) - return (strdup("None")); + case S9xButtonJustifier: + if(!command.button.justifier.trigger && !command.button.justifier.start && !command.button.justifier.aim_offscreen) return strdup("None"); + s="Justifier"; + s+=command.button.justifier.idx+1; + if(command.button.justifier.aim_offscreen) s+=" AimOffscreen"; + c=' '; + if(command.button.justifier.trigger){ s+=c; s+="Trigger"; c='+'; } + if(command.button.justifier.start){ s+=c; s+="Start"; c='+'; } + break; - s = "Mouse"; - s += command.button.mouse.idx + 1; - s += " "; + case S9xButtonCommand: + if(command.button.command>=LAST_COMMAND) return strdup("None"); + return strdup(command_names[command.button.command]); - if (command.button.mouse.left ) s += "L"; - if (command.button.mouse.right) s += "R"; + case S9xPointer: + if(!command.pointer.aim_mouse0 && !command.pointer.aim_mouse1 && !command.pointer.aim_scope && !command.pointer.aim_justifier0 && !command.pointer.aim_justifier1) return strdup("None"); + s="Pointer"; + c=' '; + if(command.pointer.aim_mouse0){ s+=c; s+="Mouse1"; c='+'; } + if(command.pointer.aim_mouse1){ s+=c; s+="Mouse2"; c='+'; } + if(command.pointer.aim_scope){ s+=c; s+="Superscope"; c='+'; } + if(command.pointer.aim_justifier0){ s+=c; s+="Justifier1"; c='+'; } + if(command.pointer.aim_justifier1){ s+=c; s+="Justifier2"; c='+'; } + break; - break; + case S9xButtonPseudopointer: + if(!command.button.pointer.UD && !command.button.pointer.LR) return strdup("None"); + if(command.button.pointer.UD==-2 || command.button.pointer.LR==-2) return strdup("None"); + s="ButtonToPointer "; + s+=command.button.pointer.idx+1; + if(command.button.pointer.UD) s+=(command.button.pointer.UD==1)?'d':'u'; + if(command.button.pointer.LR) s+=(command.button.pointer.LR==1)?'r':'l'; + s+=" "; + s+=speed_names[command.button.pointer.speed_type]; + break; - case S9xButtonSuperscope: - if (!command.button.scope.fire && !command.button.scope.cursor && !command.button.scope.turbo && !command.button.scope.pause && !command.button.scope.aim_offscreen) - return (strdup("None")); + case S9xAxisJoypad: + s="Joypad"; + s+=command.axis.joypad.idx+1; + s+=" Axis "; + switch(command.axis.joypad.axis){ + case 0: + s+=(command.axis.joypad.invert?"Right/Left":"Left/Right"); + break; + case 1: + s+=(command.axis.joypad.invert?"Down/Up":"Up/Down"); + break; + case 2: + s+=(command.axis.joypad.invert?"A/Y":"Y/A"); + break; + case 3: + s+=(command.axis.joypad.invert?"B/X":"X/B"); + break; + case 4: + s+=(command.axis.joypad.invert?"R/L":"L/R"); + break; + default: + return strdup("None"); + } + s+=" T="; + s+=int((command.axis.joypad.threshold+1)*1000/256)/10.0; + s+="%"; + break; - s = "Superscope"; + case S9xAxisPseudopointer: + s="AxisToPointer "; + s+=command.axis.pointer.idx+1; + s+=command.axis.pointer.HV?'v':'h'; + s+=" "; + if(command.axis.pointer.invert) s+="-"; + s+=speed_names[command.axis.pointer.speed_type]; + break; - if (command.button.scope.aim_offscreen) s += " AimOffscreen"; + case S9xAxisPseudobuttons: + s="AxisToButtons "; + s+=command.axis.button.negbutton; + s+="/"; + s+=command.axis.button.posbutton; + s+=" T="; + s+=int((command.axis.button.threshold+1)*1000/256)/10.0; + s+="%"; + break; - c = ' '; - if (command.button.scope.fire ) { s += c; s += "Fire"; c = '+'; } - if (command.button.scope.cursor) { s += c; s += "Cursor"; c = '+'; } - if (command.button.scope.turbo ) { s += c; s += "ToggleTurbo"; c = '+'; } - if (command.button.scope.pause ) { s += c; s += "Pause"; c = '+'; } + case S9xButtonPort: + case S9xAxisPort: + case S9xPointerPort: + return strdup("BUG: Port should have handled this instead of calling S9xGetCommandName()"); - break; + case S9xNoMapping: + return strdup("None"); - case S9xButtonJustifier: - if (!command.button.justifier.trigger && !command.button.justifier.start && !command.button.justifier.aim_offscreen) - return (strdup("None")); + case S9xButtonMulti: + { + if(command.button.multi_idx>=(int)multis.size()) return strdup("None"); + s="{"; + if(multis[command.button.multi_idx]->multi_press) s="+{"; + bool sep=false; + for(s9xcommand_t *c=multis[command.button.multi_idx]; c->multi_press!=3; c++){ + if(c->type==S9xNoMapping){ + s+=";"; + sep=false; + } else { + if(sep) s+=","; + if(c->multi_press==1) s+="+"; + if(c->multi_press==2) s+="-"; + s+=S9xGetCommandName(*c); + sep=true; + } + } + s+="}"; + } + break; - s = "Justifier"; - s += command.button.justifier.idx + 1; + default: + return strdup("BUG: Unknown command type"); + } - if (command.button.justifier.aim_offscreen) s += " AimOffscreen"; - - c = ' '; - if (command.button.justifier.trigger) { s += c; s += "Trigger"; c = '+'; } - if (command.button.justifier.start ) { s += c; s += "Start"; c = '+'; } - - break; - - case S9xButtonCommand: - if (command.button.command >= LAST_COMMAND) - return (strdup("None")); - - return (strdup(command_names[command.button.command])); - - case S9xPointer: - if (!command.pointer.aim_mouse0 && !command.pointer.aim_mouse1 && !command.pointer.aim_scope && !command.pointer.aim_justifier0 && !command.pointer.aim_justifier1) - return (strdup("None")); - - s = "Pointer"; - - c = ' '; - if (command.pointer.aim_mouse0 ) { s += c; s += "Mouse1"; c = '+'; } - if (command.pointer.aim_mouse1 ) { s += c; s += "Mouse2"; c = '+'; } - if (command.pointer.aim_scope ) { s += c; s += "Superscope"; c = '+'; } - if (command.pointer.aim_justifier0) { s += c; s += "Justifier1"; c = '+'; } - if (command.pointer.aim_justifier1) { s += c; s += "Justifier2"; c = '+'; } - - break; - - case S9xButtonPseudopointer: - if (!command.button.pointer.UD && !command.button.pointer.LR) - return (strdup("None")); - if (command.button.pointer.UD == -2 || command.button.pointer.LR == -2) - return (strdup("None")); - - s = "ButtonToPointer "; - s += command.button.pointer.idx + 1; - - if (command.button.pointer.UD) s += (command.button.pointer.UD == 1) ? 'd' : 'u'; - if (command.button.pointer.LR) s += (command.button.pointer.LR == 1) ? 'r' : 'l'; - - s += " "; - s += speed_names[command.button.pointer.speed_type]; - - break; - - case S9xAxisJoypad: - s = "Joypad"; - s += command.axis.joypad.idx + 1; - s += " Axis "; - - switch (command.axis.joypad.axis) - { - case 0: s += (command.axis.joypad.invert ? "Right/Left" : "Left/Right"); break; - case 1: s += (command.axis.joypad.invert ? "Down/Up" : "Up/Down" ); break; - case 2: s += (command.axis.joypad.invert ? "A/Y" : "Y/A" ); break; - case 3: s += (command.axis.joypad.invert ? "B/X" : "X/B" ); break; - case 4: s += (command.axis.joypad.invert ? "R/L" : "L/R" ); break; - default: return (strdup("None")); - } - - s += " T="; - s += int((command.axis.joypad.threshold + 1) * 1000 / 256) / 10.0; - s += "%"; - - break; - - case S9xAxisPseudopointer: - s = "AxisToPointer "; - s += command.axis.pointer.idx + 1; - s += command.axis.pointer.HV ? 'v' : 'h'; - s += " "; - - if (command.axis.pointer.invert) s += "-"; - - s += speed_names[command.axis.pointer.speed_type]; - - break; - - case S9xAxisPseudobuttons: - s = "AxisToButtons "; - s += command.axis.button.negbutton; - s += "/"; - s += command.axis.button.posbutton; - s += " T="; - s += int((command.axis.button.threshold + 1) * 1000 / 256) / 10.0; - s += "%"; - - break; - - case S9xButtonPort: - case S9xAxisPort: - case S9xPointerPort: - return (strdup("BUG: Port should have handled this instead of calling S9xGetCommandName()")); - - case S9xNoMapping: - return (strdup("None")); - - case S9xButtonMulti: - { - if (command.button.multi_idx >= (int) multis.size()) - return (strdup("None")); - - s = "{"; - if (multis[command.button.multi_idx]->multi_press) s = "+{"; - - bool sep = false; - - for (s9xcommand_t *m = multis[command.button.multi_idx]; m->multi_press != 3; m++) - { - if (m->type == S9xNoMapping) - { - s += ";"; - sep = false; - } - else - { - if (sep) s += ","; - if (m->multi_press == 1) s += "+"; - if (m->multi_press == 2) s += "-"; - - s += S9xGetCommandName(*m); - sep = true; - } - } - - s += "}"; - - break; - } - - default: - return (strdup("BUG: Unknown command type")); - } - - return (strdup(s.c_str())); + return strdup(s.c_str()); } -static bool strless (const char *a, const char *b) -{ - return (strcmp(a, b) < 0); +static bool strless(const char *a, const char *b){ + return strcmp(a, b)<0; } -static int findstr (const char *needle, const char **haystack, int numstr) -{ - const char **r; - - r = lower_bound(haystack, haystack + numstr, needle, strless); - if (r >= haystack + numstr || strcmp(needle, *r)) - return (-1); - - return (r - haystack); +static int findstr(const char *needle, const char **haystack, int numstr){ + const char **r; + r=lower_bound(haystack, haystack+numstr, needle, strless); + if(r>=haystack+numstr || strcmp(needle,*r)) return -1; + return r-haystack; } -static int get_threshold (const char **ss) -{ - const char *s = *ss; - int i; +static int get_threshold(const char **ss){ + int i; + const char *s=*ss; - if (s[0] != 'T' || s[1] != '=') - return (-1); - - s += 2; - i = 0; - - if (s[0] == '0') - { - if (s[1] != '.') - return (-1); - - s++; - } - else - { - do - { - if (*s < '0' || *s > '9') - return (-1); - - i = i * 10 + 10 * (*s - '0'); - if (i > 1000) - return (-1); - - s++; - } - while (*s != '.' && *s != '%'); - } - - if (*s == '.') - { - if (s[1] < '0' || s[1] > '9' || s[2] != '%') - return (-1); - - i += s[1] - '0'; - } - - if (i > 1000) - return (-1); - - *ss = s; - - return (i); + if(s[0]!='T' || s[1]!='=') return -1; + s+=2; + i=0; + if(s[0]=='0'){ + if(s[1]!='.') return -1; + s++; + } else { + do { + if(*s<'0' || *s>'9') return -1; + i=i*10+10*(*s-'0'); + if(i>1000) return -1; + s++; + } while(*s!='.' && *s!='%'); + } + if(*s=='.'){ + if(s[1]<'0' || s[1]>'9' || s[2]!='%') return -1; + i+=s[1]-'0'; + } + if(i>1000) return -1; + *ss=s; + return i; } -s9xcommand_t S9xGetCommandT (const char *name) -{ - s9xcommand_t cmd; - int i, j; - const char *s; - - ZeroMemory(&cmd, sizeof(cmd)); - cmd.type = S9xBadMapping; - cmd.multi_press = 0; - cmd.button_norpt = 0; - - if (!strcmp(name, "None")) - cmd.type = S9xNoMapping; - else - if (!strncmp(name, "Joypad", 6)) - { - if (name[6] < '1' || name[6] > '8' || name[7] != ' ') - return (cmd); - - if (!strncmp(name + 8, "Axis ", 5)) - { - cmd.axis.joypad.idx = name[6] - '1'; - s = name + 13; - - if (!strncmp(s, "Left/Right ", 11)) { j = 0; i = 0; s += 11; } - else - if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; } - else - if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; } - else - if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; } - else - if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; } - else - if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; } - else - if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; } - else - if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; } - else - if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; } - else - if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; } - else - return (cmd); - - cmd.axis.joypad.axis = j; - cmd.axis.joypad.invert = i; - i = get_threshold(&s); - if (i < 0) - return (cmd); - cmd.axis.joypad.threshold = (i - 1) * 256 / 1000; - - cmd.type = S9xAxisJoypad; - } - else - { - cmd.button.joypad.idx = name[6] - '1'; - s = name + 8; - i = 0; - - if ((cmd.button.joypad.toggle = strncmp(s, "Toggle", 6) ? 0 : 1)) s += i = 6; - if ((cmd.button.joypad.sticky = strncmp(s, "Sticky", 6) ? 0 : 1)) s += i = 6; - if ((cmd.button.joypad.turbo = strncmp(s, "Turbo", 5) ? 0 : 1)) s += i = 5; - - if (cmd.button.joypad.toggle && !(cmd.button.joypad.sticky || cmd.button.joypad.turbo)) - return (cmd); - - if (i) - { - if (*s != ' ') - return (cmd); - s++; - } - - i = 0; - - if (!strncmp(s, "Up", 2)) { i |= SNES_UP_MASK; s += 2; if (*s == '+') s++; } - if (!strncmp(s, "Down", 4)) { i |= SNES_DOWN_MASK; s += 4; if (*s == '+') s++; } - if (!strncmp(s, "Left", 4)) { i |= SNES_LEFT_MASK; s += 4; if (*s == '+') s++; } - if (!strncmp(s, "Right", 5)) { i |= SNES_RIGHT_MASK; s += 5; if (*s == '+') s++; } - - if (*s == 'A') { i |= SNES_A_MASK; s++; if (*s == '+') s++; } - if (*s == 'B') { i |= SNES_B_MASK; s++; if (*s == '+') s++; } - if (*s == 'X') { i |= SNES_X_MASK; s++; if (*s == '+') s++; } - if (*s == 'Y') { i |= SNES_Y_MASK; s++; if (*s == '+') s++; } - if (*s == 'L') { i |= SNES_TL_MASK; s++; if (*s == '+') s++; } - if (*s == 'R') { i |= SNES_TR_MASK; s++; if (*s == '+') s++; } - - if (!strncmp(s, "Start", 5)) { i |= SNES_START_MASK; s += 5; if (*s == '+') s++; } - if (!strncmp(s, "Select", 6)) { i |= SNES_SELECT_MASK; s += 6; } - - if (i == 0 || *s != 0 || *(s - 1) == '+') - return (cmd); - - cmd.button.joypad.buttons = i; - - cmd.type = S9xButtonJoypad; - } - } - else - if (!strncmp(name, "Mouse", 5)) - { - if (name[5] < '1' || name[5] > '2' || name[6] != ' ') - return (cmd); - - cmd.button.mouse.idx = name[5] - '1'; - s = name + 7; - i = 0; - - if ((cmd.button.mouse.left = (*s == 'L'))) s += i = 1; - if ((cmd.button.mouse.right = (*s == 'R'))) s += i = 1; - - if (i == 0 || *s != 0) - return (cmd); - - cmd.type = S9xButtonMouse; - } - else - if (!strncmp(name, "Superscope ", 11)) - { - s = name + 11; - i = 0; - - if ((cmd.button.scope.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1)) { s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); } - if ((cmd.button.scope.fire = strncmp(s, "Fire", 4) ? 0 : 1)) { s += i = 4; if (*s == '+') s++; } - if ((cmd.button.scope.cursor = strncmp(s, "Cursor", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } - if ((cmd.button.scope.turbo = strncmp(s, "ToggleTurbo", 11) ? 0 : 1)) { s += i = 11; if (*s == '+') s++; } - if ((cmd.button.scope.pause = strncmp(s, "Pause", 5) ? 0 : 1)) { s += i = 5; } - - if (i == 0 || *s != 0 || *(s - 1) == '+') - return (cmd); - - cmd.type = S9xButtonSuperscope; - } - else - if (!strncmp(name, "Justifier", 9)) - { - if (name[9] < '1' || name[9] > '2' || name[10] != ' ') - return (cmd); - - cmd.button.justifier.idx = name[9] - '1'; - s = name + 11; - i = 0; - - if ((cmd.button.justifier.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1)) { s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); } - if ((cmd.button.justifier.trigger = strncmp(s, "Trigger", 7) ? 0 : 1)) { s += i = 7; if (*s == '+') s++; } - if ((cmd.button.justifier.start = strncmp(s, "Start", 5) ? 0 : 1)) { s += i = 5; } - - if (i == 0 || *s != 0 || *(s - 1) == '+') - return (cmd); - - cmd.type = S9xButtonJustifier; - } - else - if (!strncmp(name, "Pointer ", 8)) - { - s = name + 8; - i = 0; - - if ((cmd.pointer.aim_mouse0 = strncmp(s, "Mouse1", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } - if ((cmd.pointer.aim_mouse1 = strncmp(s, "Mouse2", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } - if ((cmd.pointer.aim_scope = strncmp(s, "Superscope", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; } - if ((cmd.pointer.aim_justifier0 = strncmp(s, "Justifier1", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; } - if ((cmd.pointer.aim_justifier1 = strncmp(s, "Justifier2", 10) ? 0 : 1)) { s += i = 10; } - - if (i == 0 || *s != 0 || *(s - 1) == '+') - return (cmd); - - cmd.type = S9xPointer; - } - else - if (!strncmp(name, "ButtonToPointer ", 16)) - { - if (name[16] < '1' || name[16] > '8') - return (cmd); - - cmd.button.pointer.idx = name[16] - '1'; - s = name + 17; - i = 0; - - if ((cmd.button.pointer.UD = (*s == 'u' ? -1 : (*s == 'd' ? 1 : 0)))) s += i = 1; - if ((cmd.button.pointer.LR = (*s == 'l' ? -1 : (*s == 'r' ? 1 : 0)))) s += i = 1; - - if (i == 0 || *(s++) != ' ') - return (cmd); - - for (i = 0; i < 4; i++) - if (!strcmp(s, speed_names[i])) - break; - if (i > 3) - return (cmd); - - cmd.button.pointer.speed_type = i; - - cmd.type = S9xButtonPseudopointer; - } - else - if (!strncmp(name, "AxisToPointer ", 14)) - { - if (name[14] < '1' || name[14] > '8') - return (cmd); - - cmd.axis.pointer.idx = name[14] - '1'; - s= name + 15; - i = 0; - - if (*s == 'h') - cmd.axis.pointer.HV = 0; - else - if (*s == 'v') - cmd.axis.pointer.HV = 1; - else - return (cmd); - - if (s[1] != ' ') - return (cmd); - - s += 2; - if ((cmd.axis.pointer.invert = *s == '-')) - s++; - - for (i = 0; i < 4; i++) - if (!strcmp(s, speed_names[i])) - break; - if (i > 3) - return (cmd); - - cmd.axis.pointer.speed_type = i; - - cmd.type = S9xAxisPseudopointer; - } - else - if (!strncmp(name, "AxisToButtons ", 14)) - { - s = name + 14; - - if (s[0] == '0') - { - if (s[1] != '/') - return (cmd); - - cmd.axis.button.negbutton = 0; - s += 2; - } - else - { - i = 0; - do - { - if (*s < '0' || *s > '9') - return (cmd); - - i = i * 10 + *s - '0'; - if (i > 255) - return (cmd); - } - while (*++s != '/'); - - cmd.axis.button.negbutton = i; - s++; - } - - if (s[0] == '0') - { - if (s[1] != ' ') - return (cmd); - - cmd.axis.button.posbutton = 0; - s += 2; - } - else - { - i = 0; - do - { - if (*s < '0' || *s > '9') - return (cmd); - - i = i * 10 + *s - '0'; - if (i > 255) - return (cmd); - } - while (*++s != ' '); - - cmd.axis.button.posbutton = i; - s++; - } - - i = get_threshold(&s); - if (i < 0) - return (cmd); - cmd.axis.button.threshold = (i - 1) * 256 / 1000; - - cmd.type = S9xAxisPseudobuttons; - } - else - if (!strncmp(name, "MULTI#", 6)) - { - i = strtol(name + 6, (char **) &s, 10); - if (s != NULL && *s != '\0') - return (cmd); - if (i >= (int) multis.size()) - return (cmd); - - cmd.button.multi_idx = i; - cmd.type = S9xButtonMulti; - } - else - if (((name[0] == '+' && name[1] == '{') || name[0] == '{') && name[strlen(name) - 1] == '}') - { - if (multis.size() > 2147483640) - { - fprintf(stderr, "Too many multis!"); - return (cmd); - } - - string x; - int n; - - j = 2; - for (i = (name[0] == '+') ? 2 : 1; name[i] != '\0'; i++) - { - if (name[i] == ',' || name[i] == ';') - { - if (name[i] == ';') - j++; - if (++j > 2147483640) - { - fprintf(stderr, "Multi too long!"); - return (cmd); - } - } - - if (name[i] == '{') - return (cmd); - } - - s9xcommand_t *c = (s9xcommand_t *) calloc(j, sizeof(s9xcommand_t)); - if (c == NULL) - { - perror("malloc error while parsing multi"); - return (cmd); - } - - n = 0; - i = (name[0] == '+') ? 2 : 1; - - do - { - if (name[i] == ';') - { - c[n].type = S9xNoMapping; - c[n].multi_press = 0; - c[n].button_norpt = 0; - - j = i; - } - else - if (name[i] == ',') - { - free(c); - return (cmd); - } - else - { - uint8 press = 0; - - if (name[0] == '+') - { - if (name[i] == '+') - press = 1; - else - if (name[i] == '-') - press = 2; - else - { - free(c); - return (cmd); - } - - i++; - } - - for (j = i; name[j] != ';' && name[j] != ',' && name[j] != '}'; j++) ; - - x.assign(name + i, j - i); - c[n] = S9xGetCommandT(x.c_str()); - c[n].multi_press = press; - - if (maptype(c[n].type) != MAP_BUTTON) - { - free(c); - return (cmd); - } - - if (name[j] == ';') - j--; - } - - i = j + 1; - n++; - } - while (name[i] != '\0'); - - c[n].type = S9xNoMapping; - c[n].multi_press = 3; - - multis.push_back(c); - - cmd.button.multi_idx = multis.size() - 1; - cmd.type = S9xButtonMulti; - } - else - { - i = findstr(name, command_names, LAST_COMMAND); - if (i < 0) - return (cmd); - - cmd.type = S9xButtonCommand; - cmd.button.command = i; - } - - return (cmd); +s9xcommand_t S9xGetCommandT(const char *name){ + s9xcommand_t cmd; + int i, j; + const char *s; + ZeroMemory(&cmd, sizeof(cmd)); + cmd.type=S9xBadMapping; + cmd.multi_press=0; + cmd.button_norpt=0; + + if(!strcmp(name,"None")){ + cmd.type=S9xNoMapping; + } else if(!strncmp(name,"Joypad",6)){ + if(name[6]<'1' || name[6]>'8' || name[7]!=' ') return cmd; + if(!strncmp(name+8,"Axis ",5)){ + cmd.axis.joypad.idx = name[6]-'1'; + s=name+13; + if(!strncmp(s,"Left/Right ",11)){ j=0; i=0; s+=11; } + else if(!strncmp(s,"Right/Left ",11)){ j=0; i=1; s+=11; } + else if(!strncmp(s,"Up/Down ",8)){ j=1; i=0; s+=8; } + else if(!strncmp(s,"Down/Up ",8)){ j=1; i=1; s+=8; } + else if(!strncmp(s,"Y/A ",4)){ j=2; i=0; s+=4; } + else if(!strncmp(s,"A/Y ",4)){ j=2; i=1; s+=4; } + else if(!strncmp(s,"X/B ",4)){ j=3; i=0; s+=4; } + else if(!strncmp(s,"B/X ",4)){ j=3; i=1; s+=4; } + else if(!strncmp(s,"L/R ",4)){ j=4; i=0; s+=4; } + else if(!strncmp(s,"R/L ",4)){ j=4; i=1; s+=4; } + else { return cmd; } + cmd.axis.joypad.axis=j; + cmd.axis.joypad.invert=i; + i=get_threshold(&s); + if(i<0) return cmd; + cmd.axis.joypad.threshold=(i-1)*256/1000; + cmd.type=S9xAxisJoypad; + } else { + cmd.button.joypad.idx = name[6]-'1'; + s=name+8; + i=0; + if((cmd.button.joypad.toggle=strncmp(s,"Toggle",6)?0:1)) s+=i=6; + if((cmd.button.joypad.sticky=strncmp(s,"Sticky",6)?0:1)) s+=i=6; + if((cmd.button.joypad.turbo=strncmp(s,"Turbo",5)?0:1)) s+=i=5; + if(cmd.button.joypad.toggle && !(cmd.button.joypad.sticky || cmd.button.joypad.turbo)) return cmd; + if(i){ + if(*s!=' ') return cmd; + s++; + } + + i=0; + if(!strncmp(s,"Up",2)){ i|=SNES_UP_MASK; s+=2; if(*s=='+') s++; } + if(!strncmp(s,"Down",4)){ i|=SNES_DOWN_MASK; s+=4; if(*s=='+') s++; } + if(!strncmp(s,"Left",4)){ i|=SNES_LEFT_MASK; s+=4; if(*s=='+') s++; } + if(!strncmp(s,"Right",5)){ i|=SNES_RIGHT_MASK; s+=5; if(*s=='+') s++; } + if(*s=='A'){ i|=SNES_A_MASK; s++; if(*s=='+') s++; } + if(*s=='B'){ i|=SNES_B_MASK; s++; if(*s=='+') s++; } + if(*s=='X'){ i|=SNES_X_MASK; s++; if(*s=='+') s++; } + if(*s=='Y'){ i|=SNES_Y_MASK; s++; if(*s=='+') s++; } + if(*s=='L'){ i|=SNES_TL_MASK; s++; if(*s=='+') s++; } + if(*s=='R'){ i|=SNES_TR_MASK; s++; if(*s=='+') s++; } + if(!strncmp(s,"Start",5)){ i|=SNES_START_MASK; s+=5; if(*s=='+') s++; } + if(!strncmp(s,"Select",6)){ i|=SNES_SELECT_MASK; s+=6; } + if(i==0 || *s!=0 || *(s-1)=='+') return cmd; + cmd.button.joypad.buttons=i; + cmd.type=S9xButtonJoypad; + } + } else if(!strncmp(name,"Mouse",5)){ + if(name[5]<'1' || name[5]>'2' || name[6]!=' ') return cmd; + cmd.button.mouse.idx = name[5]-'1'; + s=name+7; + i=0; + if((cmd.button.mouse.left=(*s=='L'))) s+=i=1; + if((cmd.button.mouse.right=(*s=='R'))) s+=i=1; + if(i==0 || *s!=0) return cmd; + cmd.type=S9xButtonMouse; + } else if(!strncmp(name,"Superscope ",11)){ + s=name+11; + i=0; + if((cmd.button.scope.aim_offscreen=strncmp(s,"AimOffscreen",12)?0:1)){ s+=i=12; if(*s==' '){ s++; } else if(*s!=0){ return cmd; }} + if((cmd.button.scope.fire=strncmp(s,"Fire",4)?0:1)){ s+=i=4; if(*s=='+') s++; } + if((cmd.button.scope.cursor=strncmp(s,"Cursor",6)?0:1)){ s+=i=6; if(*s=='+') s++; } + if((cmd.button.scope.turbo=strncmp(s,"ToggleTurbo",11)?0:1)){ s+=i=11; if(*s=='+') s++; } + if((cmd.button.scope.pause=strncmp(s,"Pause",5)?0:1)){ s+=i=5; } + if(i==0 || *s!=0 || *(s-1)=='+') return cmd; + cmd.type=S9xButtonSuperscope; + } else if(!strncmp(name,"Justifier",9)){ + if(name[9]<'1' || name[9]>'2' || name[10]!=' ') return cmd; + cmd.button.justifier.idx = name[9]-'1'; + s=name+11; + i=0; + if((cmd.button.justifier.aim_offscreen=strncmp(s,"AimOffscreen",12)?0:1)){ s+=i=12; if(*s==' '){ s++; } else if(*s!=0){ return cmd; }} + if((cmd.button.justifier.trigger=strncmp(s,"Trigger",7)?0:1)){ s+=i=7; if(*s=='+') s++; } + if((cmd.button.justifier.start=strncmp(s,"Start",5)?0:1)){ s+=i=5; } + if(i==0 || *s!=0 || *(s-1)=='+') return cmd; + cmd.type=S9xButtonJustifier; + } else if(!strncmp(name,"Pointer ",8)){ + s=name+8; + i=0; + if((cmd.pointer.aim_mouse0=strncmp(s,"Mouse1",6)?0:1)){ s+=i=6; if(*s=='+') s++; } + if((cmd.pointer.aim_mouse1=strncmp(s,"Mouse2",6)?0:1)){ s+=i=6; if(*s=='+') s++; } + if((cmd.pointer.aim_scope=strncmp(s,"Superscope",10)?0:1)){ s+=i=10; if(*s=='+') s++; } + if((cmd.pointer.aim_justifier0=strncmp(s,"Justifier1",10)?0:1)){ s+=i=10; if(*s=='+') s++; } + if((cmd.pointer.aim_justifier1=strncmp(s,"Justifier2",10)?0:1)){ s+=i=10; } + if(i==0 || *s!=0 || *(s-1)=='+') return cmd; + cmd.type=S9xPointer; + } else if(!strncmp(name,"ButtonToPointer ",16)){ + if(name[16]<'1' || name[16]>'8') return cmd; + cmd.button.pointer.idx = name[16]-'1'; + s=name+17; + i=0; + if((cmd.button.pointer.UD=(*s=='u'?-1:(*s=='d'?1:0)))) s+=i=1; + if((cmd.button.pointer.LR=(*s=='l'?-1:(*s=='r'?1:0)))) s+=i=1; + if(i==0 || *(s++)!=' ') return cmd; + for(i=0; i<4; i++){ + if(!strcmp(s,speed_names[i])) break; + } + if(i>3) return cmd; + cmd.button.pointer.speed_type=i; + cmd.type=S9xButtonPseudopointer; + } else if(!strncmp(name,"AxisToPointer ",14)){ + if(name[14]<'1' || name[14]>'8') return cmd; + cmd.axis.pointer.idx = name[14]-'1'; + s=name+15; + i=0; + if(*s=='h') cmd.axis.pointer.HV=0; + else if(*s=='v') cmd.axis.pointer.HV=1; + else return cmd; + if(s[1]!=' ') return cmd; + s+=2; + if((cmd.axis.pointer.invert=*s=='-')) s++; + for(i=0; i<4; i++){ + if(!strcmp(s,speed_names[i])) break; + } + if(i>3) return cmd; + cmd.axis.pointer.speed_type=i; + cmd.type=S9xAxisPseudopointer; + } else if(!strncmp(name,"AxisToButtons ",14)){ + s=name+14; + if(s[0]=='0'){ + if(s[1]!='/') return cmd; + cmd.axis.button.negbutton=0; + s+=2; + } else { + i=0; + do { + if(*s<'0' || *s>'9') return cmd; + i=i*10+*s-'0'; + if(i>255) return cmd; + } while(*++s!='/'); + cmd.axis.button.negbutton=i; + s++; + } + if(s[0]=='0'){ + if(s[1]!=' ') return cmd; + cmd.axis.button.posbutton=0; + s+=2; + } else { + i=0; + do { + if(*s<'0' || *s>'9') return cmd; + i=i*10+*s-'0'; + if(i>255) return cmd; + } while(*++s!=' '); + cmd.axis.button.posbutton=i; + s++; + } + i=get_threshold(&s); + if(i<0) return cmd; + cmd.axis.button.threshold=(i-1)*256/1000; + cmd.type=S9xAxisPseudobuttons; + } else if(!strncmp(name, "MULTI#",6)){ + i=strtol(name+6,(char **)&s,10); + if(s!=NULL && *s!='\0') return cmd; + if(i>=(int)multis.size()) return cmd; + cmd.button.multi_idx=i; + cmd.type=S9xButtonMulti; + } else if(((name[0]=='+' && name[1]=='{') || name[0]=='{') && + name[strlen(name)-1]=='}'){ + if(multis.size()>2147483640){ + fprintf(stderr, "Too many multis!"); + return cmd; + } + string x; + int n; + j=2; + for(i=(name[0]=='+')?2:1; name[i]!='\0'; i++){ + if(name[i]==',' || name[i]==';'){ + if(name[i]==';') j++; + if(++j>2147483640){ + fprintf(stderr, "Multi too long!"); + return cmd; + } + } + if(name[i]=='{') return cmd; + } + s9xcommand_t *c=(s9xcommand_t *)calloc(j,sizeof(s9xcommand_t)); + if(c==NULL){ + perror("malloc error while parsing multi"); + return cmd; + } + n=0; i=(name[0]=='+')?2:1; + do { + if(name[i]==';'){ + c[n].type=S9xNoMapping; + c[n].multi_press=0; + c[n].button_norpt=0; + j=i; + } else if(name[i]==','){ + free(c); + return cmd; + } else { + uint8 press=0; + if(name[0]=='+'){ + if(name[i]=='+'){ + press=1; + } else if(name[i]=='-'){ + press=2; + } else { + free(c); + return cmd; + } + i++; + } + for(j=i; name[j]!=';' && name[j]!=',' && name[j]!='}'; j++); + x.assign(name+i,j-i); + c[n]=S9xGetCommandT(x.c_str()); + c[n].multi_press=press; + if(maptype(c[n].type)!=MAP_BUTTON){ + free(c); + return cmd; + } + if(name[j]==';') j--; + } + i=j+1; n++; + } while(name[i]!='\0'); + c[n].type=S9xNoMapping; c[n].multi_press=3; + + multis.push_back(c); + cmd.button.multi_idx=multis.size()-1; + cmd.type=S9xButtonMulti; + } else { + i=findstr(name, command_names, LAST_COMMAND); + if(i<0) return cmd; + cmd.type = S9xButtonCommand; + cmd.button.command = i; + } + + return cmd; } -const char ** S9xGetAllSnes9xCommands (void) -{ - return (command_names); +const char **S9xGetAllSnes9xCommands(void){ + return command_names; } -s9xcommand_t S9xGetMapping (uint32 id) -{ - if (keymap.count(id) == 0) - { - s9xcommand_t cmd; - cmd.type = S9xNoMapping; - return (cmd); - } - else - return (keymap[id]); +s9xcommand_t S9xGetMapping(uint32 id){ + if(keymap.count(id)==0){ + s9xcommand_t cmd; + cmd.type=S9xNoMapping; + return cmd; + } else { + return keymap[id]; + } } -static const char * maptypename (int t) -{ - switch (t) - { - case MAP_NONE: return ("unmapped"); - case MAP_BUTTON: return ("button"); - case MAP_AXIS: return ("axis"); - case MAP_POINTER: return ("pointer"); - default: return ("unknown"); - } +static const char *maptypename(int t){ + switch(t){ + case MAP_NONE: return "unmapped"; + case MAP_BUTTON: return "button"; + case MAP_AXIS: return "axis"; + case MAP_POINTER: return "pointer"; + default: return "unknown"; + } } -void S9xUnmapID (uint32 id) -{ - for (int i = 0; i < NUMCTLS + 1; i++) - pollmap[i].erase(id); - - if (mouse[0].ID == id) mouse[0].ID = InvalidControlID; - if (mouse[1].ID == id) mouse[1].ID = InvalidControlID; - if (superscope.ID == id) superscope.ID = InvalidControlID; - if (justifier.ID[0] == id) justifier.ID[0] = InvalidControlID; - if (justifier.ID[1] == id) justifier.ID[1] = InvalidControlID; - - if (id >= PseudoPointerBase) - pseudopointer[id - PseudoPointerBase].mapped = false; - - keymap.erase(id); +void S9xUnmapID(uint32 id){ + int i; + for(i=0; i=PseudoPointerBase) pseudopointer[id-PseudoPointerBase].mapped=false; + keymap.erase(id); } -bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll) -{ - int t; +bool S9xMapButton(uint32 id, s9xcommand_t mapping, bool poll){ + int t; - if (id == InvalidControlID) - { - fprintf(stderr, "Cannot map InvalidControlID\n"); - return (false); - } + if(id==InvalidControlID){ + fprintf(stderr, "Cannot map InvalidControlID\n"); + return false; + } + t=maptype(mapping.type); + if(t==MAP_NONE){ S9xUnmapID(id); return true; } + if(t!=MAP_BUTTON) return false; + t=maptype(S9xGetMapping(id).type); + if(t!=MAP_NONE && t!=MAP_BUTTON) fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to button\n", id, maptypename(t)); + if(id>=PseudoPointerBase){ + fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as a button\n", id-PseudoPointerBase); + return false; + } - t = maptype(mapping.type); + t=-1; + if(poll){ + if(id>=PseudoButtonBase){ + fprintf(stderr, "INFO: Ignoring attempt to set pseudo-button #%d to polling\n", id-PseudoButtonBase); + } else switch(mapping.type){ + case S9xButtonJoypad: + t=JOYPAD0+mapping.button.joypad.idx; + break; + case S9xButtonMouse: + t=MOUSE0+mapping.button.mouse.idx; + break; + case S9xButtonSuperscope: + t=SUPERSCOPE; + break; + case S9xButtonJustifier: + t=ONE_JUSTIFIER+mapping.button.justifier.idx; + break; + case S9xButtonCommand: + case S9xButtonPseudopointer: + case S9xButtonPort: + case S9xButtonMulti: + t=POLL_ALL; + break; + } + } - if (t == MAP_NONE) - { - S9xUnmapID(id); - return (true); - } - - if (t != MAP_BUTTON) - return (false); - - t = maptype(S9xGetMapping(id).type); - - if (t != MAP_NONE && t != MAP_BUTTON) - fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to button\n", id, maptypename(t)); - - if (id >= PseudoPointerBase) - { - fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as a button\n", id - PseudoPointerBase); - return (false); - } - - t = -1; - - if (poll) - { - if (id >= PseudoButtonBase) - fprintf(stderr, "INFO: Ignoring attempt to set pseudo-button #%d to polling\n", id - PseudoButtonBase); - else - { - switch (mapping.type) - { - case S9xButtonJoypad: - t = JOYPAD0 + mapping.button.joypad.idx; - break; - - case S9xButtonMouse: - t = MOUSE0 + mapping.button.mouse.idx; - break; - - case S9xButtonSuperscope: - t = SUPERSCOPE; - break; - - case S9xButtonJustifier: - t = ONE_JUSTIFIER + mapping.button.justifier.idx; - break; - - case S9xButtonCommand: - case S9xButtonPseudopointer: - case S9xButtonPort: - case S9xButtonMulti: - t = POLL_ALL; - break; - } - } - } - - S9xUnmapID(id); - - keymap[id] = mapping; - - if (t >= 0) - pollmap[t].insert(id); - - return (true); + S9xUnmapID(id); + keymap[id]=mapping; + if(t>=0) pollmap[t].insert(id); + return true; } -void S9xReportButton (uint32 id, bool pressed) -{ - if (keymap.count(id) == 0) - return; +void S9xReportButton(uint32 id, bool pressed){ + if(keymap.count(id)==0) return; + if(keymap[id].type==S9xNoMapping) return; + if(maptype(keymap[id].type)!=MAP_BUTTON){ + fprintf(stderr, "ERROR: S9xReportButton called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } - if (keymap[id].type == S9xNoMapping) - return; - - if (maptype(keymap[id].type) != MAP_BUTTON) - { - fprintf(stderr, "ERROR: S9xReportButton called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); - return; - } - - if (keymap[id].type == S9xButtonCommand) // skips the "already-pressed check" unless it's a command, as a hack to work around the following problem: - if (keymap[id].button_norpt == pressed) // FIXME: this makes the controls "stick" after loading a savestate while recording a movie and holding any button - return; - - keymap[id].button_norpt = pressed; - - S9xApplyCommand(keymap[id], pressed, 0); + if(keymap[id].type==S9xButtonCommand) // skips the "already-pressed check" unless it's a command, as a hack to work around the following problem: + if(keymap[id].button_norpt==pressed) return; // FIXME: this makes the controls "stick" after loading a savestate while recording a movie and holding any button + keymap[id].button_norpt=pressed; + S9xApplyCommand(keymap[id], pressed, 0); } -bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll) -{ - int t; - if (id == InvalidControlID) - { - fprintf(stderr, "Cannot map InvalidControlID\n"); - return (false); - } +bool S9xMapPointer(uint32 id, s9xcommand_t mapping, bool poll){ + int t; - t = maptype(mapping.type); + if(id==InvalidControlID){ + fprintf(stderr, "Cannot map InvalidControlID\n"); + return false; + } + t=maptype(mapping.type); + if(t==MAP_NONE){ S9xUnmapID(id); return true; } + if(t!=MAP_POINTER) return false; + t=maptype(S9xGetMapping(id).type); + if(t!=MAP_NONE && t!=MAP_POINTER) fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to pointer\n", id, maptypename(t)); + if(id=PseudoButtonBase){ + fprintf(stderr, "ERROR: Refusing to map pseudo-button #%d as a pointer\n", id-PseudoButtonBase); + return false; + } - if (t == MAP_NONE) - { - S9xUnmapID(id); - return (true); - } + if(mapping.type==S9xPointer){ + if(mapping.pointer.aim_mouse0 && mouse[0].ID!=InvalidControlID && mouse[0].ID!=id){ fprintf(stderr, "ERROR: Rejecting attempt to control Mouse1 with two pointers\n"); return false; } + if(mapping.pointer.aim_mouse1 && mouse[1].ID!=InvalidControlID && mouse[1].ID!=id){ fprintf(stderr, "ERROR: Rejecting attempt to control Mouse2 with two pointers\n"); return false; } + if(mapping.pointer.aim_scope && superscope.ID!=InvalidControlID && superscope.ID!=id){ fprintf(stderr, "ERROR: Rejecting attempt to control SuperScope with two pointers\n"); return false; } + if(mapping.pointer.aim_justifier0 && justifier.ID[0]!=InvalidControlID && justifier.ID[0]!=id){ fprintf(stderr, "ERROR: Rejecting attempt to control Justifier1 with two pointers\n"); return false; } + if(mapping.pointer.aim_justifier1 && justifier.ID[1]!=InvalidControlID && justifier.ID[1]!=id){ fprintf(stderr, "ERROR: Rejecting attempt to control Justifier2 with two pointers\n"); return false; } + } - if (t != MAP_POINTER) - return (false); + S9xUnmapID(id); + if(poll){ + if(id>=PseudoPointerBase){ + fprintf(stderr, "INFO: Ignoring attempt to set pseudo-pointer #%d to polling\n", id-PseudoPointerBase); + } else switch(mapping.type){ + case S9xPointer: + if(mapping.pointer.aim_mouse0) pollmap[MOUSE0].insert(id); + if(mapping.pointer.aim_mouse1) pollmap[MOUSE1].insert(id); + if(mapping.pointer.aim_scope) pollmap[SUPERSCOPE].insert(id); + if(mapping.pointer.aim_justifier0) pollmap[ONE_JUSTIFIER].insert(id); + if(mapping.pointer.aim_justifier1) pollmap[TWO_JUSTIFIERS].insert(id); + break; + case S9xPointerPort: + pollmap[POLL_ALL].insert(id); + break; + } + } - t = maptype(S9xGetMapping(id).type); - - if (t != MAP_NONE && t != MAP_POINTER) - fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to pointer\n", id, maptypename(t)); - - if (id < PseudoPointerBase && id >= PseudoButtonBase) - { - fprintf(stderr, "ERROR: Refusing to map pseudo-button #%d as a pointer\n", id - PseudoButtonBase); - return (false); - } - - if (mapping.type == S9xPointer) - { - if (mapping.pointer.aim_mouse0 && mouse[0].ID != InvalidControlID && mouse[0].ID != id) - { - fprintf(stderr, "ERROR: Rejecting attempt to control Mouse1 with two pointers\n"); - return (false); - } - - if (mapping.pointer.aim_mouse1 && mouse[1].ID != InvalidControlID && mouse[1].ID != id) - { - fprintf(stderr, "ERROR: Rejecting attempt to control Mouse2 with two pointers\n"); - return (false); - } - - if (mapping.pointer.aim_scope && superscope.ID != InvalidControlID && superscope.ID != id) - { - fprintf(stderr, "ERROR: Rejecting attempt to control SuperScope with two pointers\n"); - return (false); - } - - if (mapping.pointer.aim_justifier0 && justifier.ID[0] != InvalidControlID && justifier.ID[0] != id) - { - fprintf(stderr, "ERROR: Rejecting attempt to control Justifier1 with two pointers\n"); - return (false); - } - - if (mapping.pointer.aim_justifier1 && justifier.ID[1] != InvalidControlID && justifier.ID[1] != id) - { - fprintf(stderr, "ERROR: Rejecting attempt to control Justifier2 with two pointers\n"); - return (false); - } - } - - S9xUnmapID(id); - - if (poll) - { - if (id >= PseudoPointerBase) - fprintf(stderr, "INFO: Ignoring attempt to set pseudo-pointer #%d to polling\n", id - PseudoPointerBase); - else - { - switch (mapping.type) - { - case S9xPointer: - if (mapping.pointer.aim_mouse0 ) pollmap[MOUSE0 ].insert(id); - if (mapping.pointer.aim_mouse1 ) pollmap[MOUSE1 ].insert(id); - if (mapping.pointer.aim_scope ) pollmap[SUPERSCOPE ].insert(id); - if (mapping.pointer.aim_justifier0) pollmap[ONE_JUSTIFIER ].insert(id); - if (mapping.pointer.aim_justifier1) pollmap[TWO_JUSTIFIERS].insert(id); - break; - - case S9xPointerPort: - pollmap[POLL_ALL].insert(id); - break; - } - } - } - - if (id >= PseudoPointerBase) - pseudopointer[id - PseudoPointerBase].mapped = true; - - keymap[id] = mapping; - - if (mapping.pointer.aim_mouse0 ) mouse[0].ID = id; - if (mapping.pointer.aim_mouse1 ) mouse[1].ID = id; - if (mapping.pointer.aim_scope ) superscope.ID = id; - if (mapping.pointer.aim_justifier0) justifier.ID[0] = id; - if (mapping.pointer.aim_justifier1) justifier.ID[1] = id; - - return (true); + if(id>=PseudoPointerBase) pseudopointer[id-PseudoPointerBase].mapped=true; + keymap[id]=mapping; + if(mapping.pointer.aim_mouse0) mouse[0].ID=id; + if(mapping.pointer.aim_mouse1) mouse[1].ID=id; + if(mapping.pointer.aim_scope) superscope.ID=id; + if(mapping.pointer.aim_justifier0) justifier.ID[0]=id; + if(mapping.pointer.aim_justifier1) justifier.ID[1]=id; + return true; } -void S9xReportPointer (uint32 id, int16 x, int16 y) -{ - if (keymap.count(id) == 0) - return; +void S9xReportPointer(uint32 id, int16 x, int16 y){ + if(keymap.count(id)==0) return; + if(keymap[id].type==S9xNoMapping) return; + if(maptype(keymap[id].type)!=MAP_POINTER){ + fprintf(stderr, "ERROR: S9xReportPointer called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } - if (keymap[id].type == S9xNoMapping) - return; - - if (maptype(keymap[id].type) != MAP_POINTER) - { - fprintf(stderr, "ERROR: S9xReportPointer called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); - return; - } - - S9xApplyCommand(keymap[id], x, y); + S9xApplyCommand(keymap[id], x, y); } -bool S9xMapAxis (uint32 id, s9xcommand_t mapping, bool poll) -{ - int t; - if (id == InvalidControlID) - { - fprintf(stderr, "Cannot map InvalidControlID\n"); - return (false); - } +bool S9xMapAxis(uint32 id, s9xcommand_t mapping, bool poll){ + int t; - t = maptype(mapping.type); + if(id==InvalidControlID){ + fprintf(stderr, "Cannot map InvalidControlID\n"); + return false; + } + t=maptype(mapping.type); + if(t==MAP_NONE){ S9xUnmapID(id); return true; } + if(t!=MAP_AXIS) return false; + t=maptype(S9xGetMapping(id).type); + if(t!=MAP_NONE && t!=MAP_AXIS) fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to axis\n", id, maptypename(t)); + if(id>=PseudoPointerBase){ + fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as an axis\n", id-PseudoPointerBase); + return false; + } + if(id>=PseudoButtonBase){ + fprintf(stderr, "ERROR: Refusing to map pseudo-button #%d as an axis\n", id-PseudoButtonBase); + return false; + } - if (t == MAP_NONE) - { - S9xUnmapID(id); - return (true); - } + t=-1; + if(poll){ + switch(mapping.type){ + case S9xAxisJoypad: + t=JOYPAD0+mapping.axis.joypad.idx; + break; + case S9xAxisPseudopointer: + case S9xAxisPseudobuttons: + case S9xAxisPort: + t=POLL_ALL; + break; + } + } - if (t != MAP_AXIS) - return (false); - - t = maptype(S9xGetMapping(id).type); - - if (t != MAP_NONE && t != MAP_AXIS) - fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to axis\n", id, maptypename(t)); - - if (id >= PseudoPointerBase) - { - fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as an axis\n", id - PseudoPointerBase); - return (false); - } - - t = -1; - - if (poll) - { - switch (mapping.type) - { - case S9xAxisJoypad: - t = JOYPAD0 + mapping.axis.joypad.idx; - break; - - case S9xAxisPseudopointer: - case S9xAxisPseudobuttons: - case S9xAxisPort: - t=POLL_ALL; - break; - } - } - - S9xUnmapID(id); - - keymap[id] = mapping; - - if (t >= 0) - pollmap[t].insert(id); - - return (true); + S9xUnmapID(id); + keymap[id]=mapping; + if(t>=0) pollmap[t].insert(id); + return true; } -void S9xReportAxis (uint32 id, int16 value) -{ - if (keymap.count(id) == 0) - return; +void S9xReportAxis(uint32 id, int16 value){ + if(keymap.count(id)==0) return; + if(keymap[id].type==S9xNoMapping) return; + if(maptype(keymap[id].type)!=MAP_AXIS){ + fprintf(stderr, "ERROR: S9xReportAxis called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } - if (keymap[id].type == S9xNoMapping) - return; - - if (maptype(keymap[id].type) != MAP_AXIS) - { - fprintf(stderr, "ERROR: S9xReportAxis called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); - return; - } - - S9xApplyCommand(keymap[id], value, 0); + S9xApplyCommand(keymap[id], value, 0); } -static int32 ApplyMulti (s9xcommand_t *multi, int32 pos, int16 data1) -{ - while (1) - { - if (multi[pos].multi_press == 3) - return (-1); - if (multi[pos].type == S9xNoMapping) - break; - - if (multi[pos].multi_press) - S9xApplyCommand(multi[pos], multi[pos].multi_press == 1, 0); - else - S9xApplyCommand(multi[pos], data1, 0); - - pos++; - } - - return (pos + 1); +static int32 ApplyMulti(s9xcommand_t *multi, int32 pos, int16 data1){ + while(1){ + if(multi[pos].multi_press==3) return -1; + if(multi[pos].type==S9xNoMapping) break; + if(multi[pos].multi_press){ + S9xApplyCommand(multi[pos], multi[pos].multi_press==1, 0); + } else { + S9xApplyCommand(multi[pos], data1, 0); + } + pos++; + } + return pos+1; } -void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2) -{ - int i; +void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ + int i; - switch (cmd.type) - { - case S9xNoMapping: - return; + switch(cmd.type){ + case S9xNoMapping: + return; - case S9xButtonJoypad: - if (cmd.button.joypad.toggle) - { - if (!data1) - return; - - uint16 r = cmd.button.joypad.buttons; - - if (cmd.button.joypad.turbo) joypad[cmd.button.joypad.idx].toggleturbo ^= r; - if (cmd.button.joypad.sticky) joypad[cmd.button.joypad.idx].togglestick ^= r; - } - else - { - uint16 r, s, t, st; - - s = t = st = 0; - r = cmd.button.joypad.buttons; - st = r & joypad[cmd.button.joypad.idx].togglestick & joypad[cmd.button.joypad.idx].toggleturbo; - r ^= st; - t = r & joypad[cmd.button.joypad.idx].toggleturbo; - r ^= t; - s = r & joypad[cmd.button.joypad.idx].togglestick; - r ^= s; - - if (cmd.button.joypad.turbo && cmd.button.joypad.sticky) + case S9xButtonJoypad: + if(cmd.button.joypad.toggle){ + if(!data1) return; + uint16 r=cmd.button.joypad.buttons; + if(cmd.button.joypad.turbo) joypad[cmd.button.joypad.idx].toggleturbo^=r; + if(cmd.button.joypad.sticky) joypad[cmd.button.joypad.idx].togglestick^=r; + } else { + uint16 r,s,t,st; + s=t=st=0; + r=cmd.button.joypad.buttons; + st=r & joypad[cmd.button.joypad.idx].togglestick & joypad[cmd.button.joypad.idx].toggleturbo; + r ^= st; + t=r & joypad[cmd.button.joypad.idx].toggleturbo; + r ^= t; + s=r & joypad[cmd.button.joypad.idx].togglestick; + r ^= s; + if(cmd.button.joypad.turbo && cmd.button.joypad.sticky){ + uint16 x=r; r=st; st=x; + x=s; s=t; t=x; + } else if(cmd.button.joypad.turbo){ + uint16 x=r; r=t; t=x; + x=s; s=st; st=x; + } else if(cmd.button.joypad.sticky){ + uint16 x=r; r=s; s=x; + x=t; t=st; st=x; + } + if(data1){ + if(!Settings.UpAndDown) // if up+down isn't allowed AND we are NOT playing a movie, { - uint16 x = r; r = st; st = x; - x = s; s = t; t = x; - } - else - if (cmd.button.joypad.turbo) + if(cmd.button.joypad.buttons&(SNES_LEFT_MASK|SNES_RIGHT_MASK)){ + // if we're pressing left or right, then unpress and unturbo + // them both first so we don't end up hittnig left AND right + // accidentally. Note though that the user can still do it on + // purpose, if Settings.UpAndDown = true. + // This is a feature, look up glitches in tLoZ:aLttP to find + // out why. + joypad[cmd.button.joypad.idx].buttons &= ~(SNES_LEFT_MASK|SNES_RIGHT_MASK); + joypad[cmd.button.joypad.idx].turbos &= ~(SNES_LEFT_MASK|SNES_RIGHT_MASK); + } + if(cmd.button.joypad.buttons&(SNES_UP_MASK|SNES_DOWN_MASK)){ + // and ditto for up/down + joypad[cmd.button.joypad.idx].buttons &= ~(SNES_UP_MASK|SNES_DOWN_MASK); + joypad[cmd.button.joypad.idx].turbos &= ~(SNES_UP_MASK|SNES_DOWN_MASK); + } + }//end up+down protection + joypad[cmd.button.joypad.idx].buttons |= r; + joypad[cmd.button.joypad.idx].turbos |= t; + joypad[cmd.button.joypad.idx].buttons ^= s; + joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & st); + joypad[cmd.button.joypad.idx].turbos ^= st; + } else { + joypad[cmd.button.joypad.idx].buttons &= ~r; + joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & t); + joypad[cmd.button.joypad.idx].turbos &= ~t; + } + } + return; + + case S9xButtonMouse: + i=0; + if(cmd.button.mouse.left) i|=0x40; + if(cmd.button.mouse.right) i|=0x80; + if(data1){ + mouse[cmd.button.mouse.idx].buttons |= i; + } else { + mouse[cmd.button.mouse.idx].buttons &= ~i; + } + return; + + case S9xButtonSuperscope: + i=0; + if(cmd.button.scope.fire) i|=SUPERSCOPE_FIRE; + if(cmd.button.scope.cursor) i|=SUPERSCOPE_CURSOR; + if(cmd.button.scope.pause) i|=SUPERSCOPE_PAUSE; + if(cmd.button.scope.aim_offscreen) i|=SUPERSCOPE_OFFSCREEN; + if(data1){ + superscope.phys_buttons |= i; + if(cmd.button.scope.turbo){ + superscope.phys_buttons^=SUPERSCOPE_TURBO; + if(superscope.phys_buttons&SUPERSCOPE_TURBO){ + superscope.next_buttons |= superscope.phys_buttons&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR); + } else { + superscope.next_buttons &= ~(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR); + } + } + superscope.next_buttons |= i&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR|SUPERSCOPE_PAUSE); +#ifndef NGC + if(!S9xMovieActive()) // PPU modification during non-recordable command screws up movie synchronization +#endif + if((superscope.next_buttons&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR)) && + curcontrollers[1]==SUPERSCOPE && + !(superscope.phys_buttons&SUPERSCOPE_OFFSCREEN)){ + DoGunLatch(superscope.x, superscope.y); + } + } else { + superscope.phys_buttons &= ~i; + superscope.next_buttons &= SUPERSCOPE_OFFSCREEN|~i; + } + return; + + case S9xButtonJustifier: + i=0; + if(cmd.button.justifier.trigger) i|=JUSTIFIER_TRIGGER; + if(cmd.button.justifier.start) i|=JUSTIFIER_START; + if(cmd.button.justifier.aim_offscreen) justifier.offscreen[cmd.button.justifier.idx]=data1?1:0; + i>>=cmd.button.justifier.idx; + if(data1){ + justifier.buttons |= i; + } else { + justifier.buttons &= ~i; + } + return; + + case S9xButtonCommand: + if(((enum command_numbers)cmd.button.command)>=LAST_COMMAND){ + fprintf(stderr, "Unknown command %04x\n", cmd.button.command); + return; + } + if(!data1){ + switch(i=cmd.button.command){ + case EmuTurbo: + Settings.TurboMode = FALSE; + break; + } + } else { + switch((enum command_numbers)(i=cmd.button.command)){ + case ExitEmu: + S9xExit(); + break; + case Reset: + S9xReset(); + break; + case SoftReset: +#ifndef NGC + S9xMovieUpdateOnReset (); + if(S9xMoviePlaying()) + S9xMovieStop (TRUE); +#endif + S9xSoftReset(); + break; + case EmuTurbo: + Settings.TurboMode = TRUE; + break; + case ToggleEmuTurbo: + Settings.TurboMode = !Settings.TurboMode; + S9xDisplayStateChange("Turbo Mode", Settings.TurboMode); + break; + case BGLayeringHack: + Settings.BGLayering = !Settings.BGLayering; + S9xDisplayStateChange("Background layering hack", Settings.BGLayering); + break; + case ClipWindows: + Settings.DisableGraphicWindows = !Settings.DisableGraphicWindows; + S9xDisplayStateChange("Graphic clip windows", + !Settings.DisableGraphicWindows); + break; + case Debugger: +#ifdef DEBUGGER + CPU.Flags |= DEBUG_MODE_FLAG; +#endif + break; + case IncFrameRate: + if (Settings.SkipFrames == AUTO_FRAMERATE) + Settings.SkipFrames = 1; + else + if (Settings.SkipFrames < 10) + Settings.SkipFrames++; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString ("Auto frame skip"); + else { + sprintf (buf, "Frame skip: %d", + Settings.SkipFrames - 1); + S9xSetInfoString (buf); + } + break; + case DecFrameRate: + if (Settings.SkipFrames <= 1) + Settings.SkipFrames = AUTO_FRAMERATE; + else + if (Settings.SkipFrames != AUTO_FRAMERATE) + Settings.SkipFrames--; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString ("Auto frame skip"); + else { + sprintf (buf, "Frame skip: %d", + Settings.SkipFrames - 1); + S9xSetInfoString (buf); + } + break; + case IncEmuTurbo: + if(Settings.TurboSkipFrames<20) Settings.TurboSkipFrames += 1; + else if(Settings.TurboSkipFrames<200) Settings.TurboSkipFrames += 5; + sprintf (buf, "Turbo Frame Skip: %d", + Settings.TurboSkipFrames); + S9xSetInfoString (buf); + break; + case DecEmuTurbo: + if(Settings.TurboSkipFrames>20) Settings.TurboSkipFrames -= 5; + else if(Settings.TurboSkipFrames>0) Settings.TurboSkipFrames -= 1; + sprintf (buf, "Turbo Frame Skip: %d", + Settings.TurboSkipFrames); + S9xSetInfoString (buf); + break; + case IncFrameTime: + // Increase emulated frame time by 1ms + Settings.FrameTime += 1000; + sprintf (buf, "Emulated frame time: %dms", + Settings.FrameTime / 1000); + S9xSetInfoString (buf); + break; + case DecFrameTime: + // Decrease emulated frame time by 1ms + if (Settings.FrameTime >= 1000) + Settings.FrameTime -= 1000; + sprintf (buf, "Emulated frame time: %dms", + Settings.FrameTime / 1000); + S9xSetInfoString (buf); + break; + case IncTurboSpeed: + if(turbo_time>=120) break; + turbo_time++; + sprintf (buf, "Turbo speed: %d", + turbo_time); + S9xSetInfoString (buf); + break; + case DecTurboSpeed: + if(turbo_time<=1) break; + turbo_time--; + sprintf (buf, "Turbo speed: %d", + turbo_time); + S9xSetInfoString (buf); + break; + case InterpolateSound: + Settings.InterpolatedSound ^= 1; + S9xDisplayStateChange("Interpolated sound", Settings.InterpolatedSound); + break; + case LoadFreezeFile: +#ifndef NGC + S9xUnfreezeGame(S9xChooseFilename(TRUE)); +#endif + break; + case SaveFreezeFile: +#ifndef NGC + S9xFreezeGame(S9xChooseFilename(FALSE)); +#endif + break; + case LoadOopsFile: + { + char def [PATH_MAX]; + char filename [PATH_MAX]; + char drive [_MAX_DRIVE]; + char dir [_MAX_DIR]; + char ext [_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + sprintf (filename, "%s%s%s.%.*s", + S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, + _MAX_EXT-1, "oops"); + +#ifndef NGC + if (S9xLoadSnapshot (filename)) + { + sprintf (buf, "%s.%.*s loaded", def, _MAX_EXT-1, "oops"); + S9xSetInfoString (buf); + } + else + { + S9xMessage (S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, + "Oops file not found"); + } +#endif + } + break; +/* case Mode7Interpolate: + Settings.Mode7Interpolate ^= TRUE; + S9xDisplayStateChange ("Mode 7 Interpolation", + Settings.Mode7Interpolate); + break;*/ + case Pause: + Settings.Paused ^= 1; + S9xDisplayStateChange ("Pause", Settings.Paused); +#if defined(NETPLAY_SUPPORT) && !defined(__WIN32__) + S9xNPSendPause(Settings.Paused); +#endif + break; + case QuickLoad000: case QuickLoad001: case QuickLoad002: case QuickLoad003: case QuickLoad004: case QuickLoad005: case QuickLoad006: case QuickLoad007: case QuickLoad008: case QuickLoad009: case QuickLoad010: + { + char def [PATH_MAX]; + char filename [PATH_MAX]; + char drive [_MAX_DRIVE]; + char dir [_MAX_DIR]; + char ext [_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + sprintf (filename, "%s%s%s.%03d", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, + i - QuickLoad000); + +#ifndef NGC + if (S9xLoadSnapshot (filename)) + { + sprintf (buf, "%s.%03d loaded", def, i - QuickLoad000); + S9xSetInfoString (buf); + } + else + { + static char *digits = "t123456789"; + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + sprintf (filename, "%s%s%s.zs%c", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, + def, digits [i - QuickLoad000]); + if (S9xLoadSnapshot (filename)) + { + sprintf (buf, + "Loaded ZSNES freeze file %s.zs%c", + def, digits [i - QuickLoad000]); + S9xSetInfoString (buf); + } + else + S9xMessage (S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, + "Freeze file not found"); + } +#endif + } + break; + case QuickSave000: case QuickSave001: case QuickSave002: case QuickSave003: case QuickSave004: case QuickSave005: case QuickSave006: case QuickSave007: case QuickSave008: case QuickSave009: case QuickSave010: + { + char def [PATH_MAX]; + char filename [PATH_MAX]; + char drive [_MAX_DRIVE]; + char dir [_MAX_DIR]; + char ext [_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + sprintf (filename, "%s%s%s.%03d", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, + i - QuickSave000); + sprintf (buf, "%s.%03d saved", def, i - QuickSave000); + S9xSetInfoString (buf); +#ifndef NGC + Snapshot(filename); +#endif + + } + break; + case SaveSPC: + { + char def [PATH_MAX]; + char filename [PATH_MAX]; + char drive [_MAX_DRIVE]; + char dir [_MAX_DIR]; + char ext [_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + strcpy (ext, "spc"); + _makepath (filename, drive, S9xGetDirectory (SPC_DIR), + def, ext); + +#ifndef NGC + if (S9xSPCDump (filename)) + sprintf (buf, "%s.%s saved", def, ext); + else + sprintf (buf, "%s.%s not saved (%s)", + def, ext, strerror (errno)); +#endif + S9xSetInfoString (buf); + } + break; + case Screenshot: + Settings.TakeScreenshot=TRUE; + break; + case SoundChannel0: case SoundChannel1: case SoundChannel2: case SoundChannel3: case SoundChannel4: case SoundChannel5: case SoundChannel6: case SoundChannel7: + S9xToggleSoundChannel(i-SoundChannel0); + sprintf (buf, "Sound channel %d toggled", i-SoundChannel0); + S9xSetInfoString (buf); + break; + case SoundChannelsOn: + S9xToggleSoundChannel(8); + S9xSetInfoString ("All sound channels on"); + break; + case SynchronizeSound: + Settings.SoundSync ^= 1; + S9xDisplayStateChange ("Synchronised sound", + Settings.SoundSync); + break; + case ToggleBG0: + Settings.BG_Forced ^= 1; + S9xDisplayStateChange ("BG#0", !(Settings.BG_Forced & 1)); + break; + case ToggleBG1: + Settings.BG_Forced ^= 2; + S9xDisplayStateChange ("BG#1", !(Settings.BG_Forced & 2)); + break; + case ToggleBG2: + Settings.BG_Forced ^= 4; + S9xDisplayStateChange ("BG#2", !(Settings.BG_Forced & 4)); + break; + case ToggleBG3: + Settings.BG_Forced ^= 8; + S9xDisplayStateChange ("BG#3", !(Settings.BG_Forced & 8)); + break; + case ToggleSprites: + Settings.BG_Forced ^= 16; + S9xDisplayStateChange ("Sprites", !(Settings.BG_Forced & 16)); + break; + case ToggleHDMA: + Settings.DisableHDMA = !Settings.DisableHDMA; + S9xDisplayStateChange ("HDMA emulation", !Settings.DisableHDMA); + break; + case ToggleTransparency: + Settings.Transparency = !Settings.Transparency; + S9xDisplayStateChange ("Transparency effects", + Settings.Transparency); + break; + + case DumpSPC7110Log: + if(Settings.SPC7110) Do7110Logging(); + break; + + case BeginRecordingMovie: +#ifndef NGC + if(S9xMovieActive()) S9xMovieStop(FALSE); + + S9xMovieCreate(S9xChooseMovieFilename(FALSE), + 0xFF, + //MOVIE_OPT_FROM_SNAPSHOT + MOVIE_OPT_FROM_RESET, + NULL, 0); +#endif + break; + + case LoadMovie: +#ifndef NGC + if(S9xMovieActive()) S9xMovieStop(FALSE); + S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE); +#endif + break; + + case EndRecordingMovie: +#ifndef NGC + if(S9xMovieActive()) S9xMovieStop(FALSE); +#endif + break; + + case SwapJoypads: + if((curcontrollers[0]!=NONE && !(curcontrollers[0]>=JOYPAD0 && curcontrollers[0]<=JOYPAD7))){ + S9xSetInfoString("Cannot swap pads: port 1 is not a joypad"); + break; + } + if((curcontrollers[1]!=NONE && !(curcontrollers[1]>=JOYPAD0 && curcontrollers[1]<=JOYPAD7))){ + S9xSetInfoString("Cannot swap pads: port 2 is not a joypad"); + break; + } + newcontrollers[1]=curcontrollers[0]; + newcontrollers[0]=curcontrollers[1]; + strcpy(buf, "Swap pads: P1="); + i=14; + if(newcontrollers[0]==NONE){ + strcpy(buf+i, ""); + i+=6; + } else { + sprintf(buf+i, "Joypad%d", newcontrollers[0]-JOYPAD0+1); + i+=7; + } + strcpy(buf+i, " P2="); + i+=4; + if(newcontrollers[1]==NONE){ + strcpy(buf+i, ""); + i+=6; + } else { + sprintf(buf+i, "Joypad%d", newcontrollers[1]-JOYPAD0+1); + i+=7; + } + S9xSetInfoString(buf); + break; + + case SeekToFrame: { +#ifndef NGC + if (!S9xMovieActive()) + { - uint16 x = r; r = t; t = x; - x = s; s = st; st = x; - } - else - if (cmd.button.joypad.sticky) - { - uint16 x = r; r = s; s = x; - x = t; t = st; st = x; - } - - if (data1) - { - if (!Settings.UpAndDown && !S9xMoviePlaying()) // if up+down isn't allowed AND we are NOT playing a movie, - { - if (cmd.button.joypad.buttons & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) - { - // if we're pressing left or right, then unpress and unturbo them both first - // so we don't end up hittnig left AND right accidentally. - // Note though that the user can still do it on purpose, if Settings.UpAndDown = true. - // This is a feature, look up glitches in tLoZ:aLttP to find out why. - joypad[cmd.button.joypad.idx].buttons &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK); - joypad[cmd.button.joypad.idx].turbos &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK); - } - - if (cmd.button.joypad.buttons & (SNES_UP_MASK | SNES_DOWN_MASK)) - { - // and ditto for up/down - joypad[cmd.button.joypad.idx].buttons &= ~(SNES_UP_MASK | SNES_DOWN_MASK); - joypad[cmd.button.joypad.idx].turbos &= ~(SNES_UP_MASK | SNES_DOWN_MASK); - } - } - - joypad[cmd.button.joypad.idx].buttons |= r; - joypad[cmd.button.joypad.idx].turbos |= t; - joypad[cmd.button.joypad.idx].buttons ^= s; - joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & st); - joypad[cmd.button.joypad.idx].turbos ^= st; - } - else - { - joypad[cmd.button.joypad.idx].buttons &= ~r; - joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & t); - joypad[cmd.button.joypad.idx].turbos &= ~t; - } - } - - return; - - case S9xButtonMouse: - i = 0; - if (cmd.button.mouse.left ) i |= 0x40; - if (cmd.button.mouse.right) i |= 0x80; - - if (data1) - mouse[cmd.button.mouse.idx].buttons |= i; - else - mouse[cmd.button.mouse.idx].buttons &= ~i; - - return; - - case S9xButtonSuperscope: - i = 0; - if (cmd.button.scope.fire ) i |= SUPERSCOPE_FIRE; - if (cmd.button.scope.cursor ) i |= SUPERSCOPE_CURSOR; - if (cmd.button.scope.pause ) i |= SUPERSCOPE_PAUSE; - if (cmd.button.scope.aim_offscreen) i |= SUPERSCOPE_OFFSCREEN; - - if (data1) - { - superscope.phys_buttons |= i; - - if (cmd.button.scope.turbo) - { - superscope.phys_buttons ^= SUPERSCOPE_TURBO; - - if (superscope.phys_buttons & SUPERSCOPE_TURBO) - superscope.next_buttons |= superscope.phys_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR); - else - superscope.next_buttons &= ~(SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR); - } - - superscope.next_buttons |= i & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR | SUPERSCOPE_PAUSE); - - if (!S9xMovieActive()) // PPU modification during non-recordable command screws up movie synchronization - if ((superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) && curcontrollers[1] == SUPERSCOPE && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN)) - DoGunLatch(superscope.x, superscope.y); - } - else - { - superscope.phys_buttons &= ~i; - superscope.next_buttons &= SUPERSCOPE_OFFSCREEN | ~i; - } - - return; - - case S9xButtonJustifier: - i = 0; - if (cmd.button.justifier.trigger) i |= JUSTIFIER_TRIGGER; - if (cmd.button.justifier.start ) i |= JUSTIFIER_START; - if (cmd.button.justifier.aim_offscreen) justifier.offscreen[cmd.button.justifier.idx] = data1 ? 1 : 0; - i >>= cmd.button.justifier.idx; - - if (data1) - justifier.buttons |= i; - else - justifier.buttons &= ~i; - - return; - - case S9xButtonCommand: - if (((enum command_numbers) cmd.button.command) >= LAST_COMMAND) - { - fprintf(stderr, "Unknown command %04x\n", cmd.button.command); - return; - } - - if (!data1) - { - switch (i = cmd.button.command) - { - case EmuTurbo: - Settings.TurboMode = FALSE; - break; - } - } - else - { - switch ((enum command_numbers) (i = cmd.button.command)) - { - case ExitEmu: - S9xExit(); - break; - - case Reset: - S9xReset(); - break; - - case SoftReset: - S9xMovieUpdateOnReset(); - if (S9xMoviePlaying()) - S9xMovieStop(TRUE); - S9xSoftReset(); - break; - - case EmuTurbo: - Settings.TurboMode = TRUE; - break; - - case ToggleEmuTurbo: - Settings.TurboMode = !Settings.TurboMode; - DisplayStateChange("Turbo mode", Settings.TurboMode); - break; - - case ClipWindows: - Settings.DisableGraphicWindows = !Settings.DisableGraphicWindows; - DisplayStateChange("Graphic clip windows", !Settings.DisableGraphicWindows); - break; - - case Debugger: - #ifdef DEBUGGER - CPU.Flags |= DEBUG_MODE_FLAG; - #endif - break; - - case IncFrameRate: - if (Settings.SkipFrames == AUTO_FRAMERATE) - Settings.SkipFrames = 1; - else - if (Settings.SkipFrames < 10) - Settings.SkipFrames++; - - if (Settings.SkipFrames == AUTO_FRAMERATE) - S9xSetInfoString("Auto frame skip"); - else - { - sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1); - S9xSetInfoString(buf); - } - - break; - - case DecFrameRate: - if (Settings.SkipFrames <= 1) - Settings.SkipFrames = AUTO_FRAMERATE; - else - if (Settings.SkipFrames != AUTO_FRAMERATE) - Settings.SkipFrames--; - - if (Settings.SkipFrames == AUTO_FRAMERATE) - S9xSetInfoString("Auto frame skip"); - else - { - sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1); - S9xSetInfoString(buf); - } - - break; - - case IncEmuTurbo: - if (Settings.TurboSkipFrames < 20) - Settings.TurboSkipFrames += 1; - else - if (Settings.TurboSkipFrames < 200) - Settings.TurboSkipFrames += 5; - sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames); - S9xSetInfoString(buf); - break; - - case DecEmuTurbo: - if (Settings.TurboSkipFrames > 20) - Settings.TurboSkipFrames -= 5; - else - if (Settings.TurboSkipFrames > 0) - Settings.TurboSkipFrames -= 1; - sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames); - S9xSetInfoString(buf); - break; - - case IncFrameTime: // Increase emulated frame time by 1ms - Settings.FrameTime += 1000; - sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000); - S9xSetInfoString(buf); - break; - - case DecFrameTime: // Decrease emulated frame time by 1ms - if (Settings.FrameTime >= 1000) - Settings.FrameTime -= 1000; - sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000); - S9xSetInfoString(buf); - break; - - case IncTurboSpeed: - if (turbo_time >= 120) - break; - turbo_time++; - sprintf(buf, "Turbo speed: %d", turbo_time); - S9xSetInfoString(buf); - break; - - case DecTurboSpeed: - if (turbo_time <= 1) - break; - turbo_time--; - sprintf(buf, "Turbo speed: %d", turbo_time); - S9xSetInfoString(buf); - break; - - case LoadFreezeFile: - S9xUnfreezeGame(S9xChooseFilename(TRUE)); - break; - - case SaveFreezeFile: - S9xFreezeGame(S9xChooseFilename(FALSE)); - break; - - case LoadOopsFile: - { - char filename[PATH_MAX + 1]; - char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; - - _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops"); - - if (S9xUnfreezeGame(filename)) - { - sprintf(buf, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops"); - S9xSetInfoString (buf); - } - else - S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Oops file not found"); - - break; - } - - case Pause: - Settings.Paused = !Settings.Paused; - DisplayStateChange("Pause", Settings.Paused); - #if defined(NETPLAY_SUPPORT) && !defined(__WIN32__) - S9xNPSendPause(Settings.Paused); - #endif - break; - - case QuickLoad000: - case QuickLoad001: - case QuickLoad002: - case QuickLoad003: - case QuickLoad004: - case QuickLoad005: - case QuickLoad006: - case QuickLoad007: - case QuickLoad008: - case QuickLoad009: - case QuickLoad010: - { - char filename[PATH_MAX + 1]; - char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; - - _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000); - - if (S9xUnfreezeGame(filename)) - { - sprintf(buf, "%s.%03d loaded", def, i - QuickLoad000); - S9xSetInfoString(buf); - } - else - S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Freeze file not found"); - - break; - } - - case QuickSave000: - case QuickSave001: - case QuickSave002: - case QuickSave003: - case QuickSave004: - case QuickSave005: - case QuickSave006: - case QuickSave007: - case QuickSave008: - case QuickSave009: - case QuickSave010: - { - char filename[PATH_MAX + 1]; - char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; - - _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000); - - sprintf(buf, "%s.%03d saved", def, i - QuickSave000); - S9xSetInfoString(buf); - - S9xFreezeGame(filename); - break; - } - - case SaveSPC: - S9xDumpSPCSnapshot(); - break; - - case Screenshot: - Settings.TakeScreenshot = TRUE; - break; - - case SoundChannel0: - case SoundChannel1: - case SoundChannel2: - case SoundChannel3: - case SoundChannel4: - case SoundChannel5: - case SoundChannel6: - case SoundChannel7: - S9xToggleSoundChannel(i - SoundChannel0); - sprintf(buf, "Sound channel %d toggled", i - SoundChannel0); - S9xSetInfoString(buf); - break; - - case SoundChannelsOn: - S9xToggleSoundChannel(8); - S9xSetInfoString("All sound channels on"); - break; - - case ToggleBG0: - Settings.BG_Forced ^= 1; - DisplayStateChange("BG#0", !(Settings.BG_Forced & 1)); - break; - - case ToggleBG1: - Settings.BG_Forced ^= 2; - DisplayStateChange("BG#1", !(Settings.BG_Forced & 2)); - break; - - case ToggleBG2: - Settings.BG_Forced ^= 4; - DisplayStateChange("BG#2", !(Settings.BG_Forced & 4)); - break; - - case ToggleBG3: - Settings.BG_Forced ^= 8; - DisplayStateChange("BG#3", !(Settings.BG_Forced & 8)); - break; - - case ToggleSprites: - Settings.BG_Forced ^= 16; - DisplayStateChange("Sprites", !(Settings.BG_Forced & 16)); - break; - - case ToggleHDMA: - Settings.DisableHDMA = !Settings.DisableHDMA; - DisplayStateChange("HDMA emulation", !Settings.DisableHDMA); - break; - - case ToggleTransparency: - Settings.Transparency = !Settings.Transparency; - DisplayStateChange("Transparency effects", Settings.Transparency); - break; - - case BeginRecordingMovie: - if (S9xMovieActive()) - S9xMovieStop(FALSE); - S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0); - break; - - case LoadMovie: - if (S9xMovieActive()) - S9xMovieStop(FALSE); - S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE); - break; - - case EndRecordingMovie: - if (S9xMovieActive()) - S9xMovieStop(FALSE); - break; - - case SwapJoypads: - if ((curcontrollers[0] != NONE && !(curcontrollers[0] >= JOYPAD0 && curcontrollers[0] <= JOYPAD7))) - { - S9xSetInfoString("Cannot swap pads: port 1 is not a joypad"); - break; - } - - if ((curcontrollers[1] != NONE && !(curcontrollers[1] >= JOYPAD0 && curcontrollers[1] <= JOYPAD7))) - { - S9xSetInfoString("Cannot swap pads: port 2 is not a joypad"); - break; - } - - newcontrollers[1] = curcontrollers[0]; - newcontrollers[0] = curcontrollers[1]; - - strcpy(buf, "Swap pads: P1="); - i = 14; - if (newcontrollers[0] == NONE) - { - strcpy(buf + i, ""); - i += 6; - } - else - { - sprintf(buf + i, "Joypad%d", newcontrollers[0] - JOYPAD0 + 1); - i += 7; - } - - strcpy(buf + i, " P2="); - i += 4; - if (newcontrollers[1] == NONE) - strcpy(buf + i, ""); - else - sprintf(buf + i, "Joypad%d", newcontrollers[1] - JOYPAD0 + 1); - - S9xSetInfoString(buf); - break; - - case SeekToFrame: - if (S9xMovieActive()) - { - sprintf(buf, "Select frame number (current: %d)", S9xMovieGetFrameCounter()); - const char *frameno = S9xStringInput(buf); - if (!frameno) - return; - - int frameDest = atoi(frameno); - if (frameDest > 0 && frameDest > (int) S9xMovieGetFrameCounter()) - { - int distance = frameDest - S9xMovieGetFrameCounter(); - Settings.HighSpeedSeek = distance; - } - } - - break; - - case LAST_COMMAND: - break; - } - } - - return; - - case S9xPointer: - if (cmd.pointer.aim_mouse0) - { - mouse[0].cur_x = data1; - mouse[0].cur_y = data2; - } - - if (cmd.pointer.aim_mouse1) - { - mouse[1].cur_x = data1; - mouse[1].cur_y = data2; - } - - if (cmd.pointer.aim_scope) - { - superscope.x = data1; - superscope.y = data2; - } - - if (cmd.pointer.aim_justifier0) - { - justifier.x[0] = data1; - justifier.y[0] = data2; - } - - if (cmd.pointer.aim_justifier1) - { - justifier.x[1] = data1; - justifier.y[1] = data2; - } - - return; - - case S9xButtonPseudopointer: - if (data1) - { - if (cmd.button.pointer.UD) - { - if (!pseudopointer[cmd.button.pointer.idx].V_adj) - pseudopointer[cmd.button.pointer.idx].V_adj = cmd.button.pointer.UD * ptrspeeds[cmd.button.pointer.speed_type]; - pseudopointer[cmd.button.pointer.idx].V_var = (cmd.button.pointer.speed_type == 0); - } - - if (cmd.button.pointer.LR) - { - if (!pseudopointer[cmd.button.pointer.idx].H_adj) - pseudopointer[cmd.button.pointer.idx].H_adj = cmd.button.pointer.LR * ptrspeeds[cmd.button.pointer.speed_type]; - pseudopointer[cmd.button.pointer.idx].H_var = (cmd.button.pointer.speed_type == 0); - } - } - else - { - if (cmd.button.pointer.UD) - { - pseudopointer[cmd.button.pointer.idx].V_adj = 0; - pseudopointer[cmd.button.pointer.idx].V_var = false; - } - - if (cmd.button.pointer.LR) - { - pseudopointer[cmd.button.pointer.idx].H_adj = 0; - pseudopointer[cmd.button.pointer.idx].H_var = false; - } - } - - return; - - case S9xAxisJoypad: - { - uint16 pos, neg; - - switch (cmd.axis.joypad.axis) - { - case 0: neg = SNES_LEFT_MASK; pos = SNES_RIGHT_MASK; break; - case 1: neg = SNES_UP_MASK; pos = SNES_DOWN_MASK; break; - case 2: neg = SNES_Y_MASK; pos = SNES_A_MASK; break; - case 3: neg = SNES_X_MASK; pos = SNES_B_MASK; break; - case 4: neg = SNES_TL_MASK; pos = SNES_TR_MASK; break; - default: return; - } - - if (cmd.axis.joypad.invert) - data1 = -data1; - - uint16 p, r; - - p = r = 0; - if (data1 > ((cmd.axis.joypad.threshold + 1) * 127)) - p |= pos; - else - r |= pos; - - if (data1 <= ((cmd.axis.joypad.threshold + 1) * -127)) - p |= neg; - else - r |= neg; - - joypad[cmd.axis.joypad.idx].buttons |= p; - joypad[cmd.axis.joypad.idx].buttons &= ~r; - joypad[cmd.axis.joypad.idx].turbos &= ~(p | r); - - return; - } - - case S9xAxisPseudopointer: - if (data1 == 0) - { - if (cmd.axis.pointer.HV) - { - pseudopointer[cmd.axis.pointer.idx].V_adj = 0; - pseudopointer[cmd.axis.pointer.idx].V_var = false; - } - else - { - pseudopointer[cmd.axis.pointer.idx].H_adj = 0; - pseudopointer[cmd.axis.pointer.idx].H_var = false; - } - } - else - { - if (cmd.axis.pointer.invert) - data1 = -data1; - - if (cmd.axis.pointer.HV) - { - if (!pseudopointer[cmd.axis.pointer.idx].V_adj) - pseudopointer[cmd.axis.pointer.idx].V_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767); - pseudopointer[cmd.axis.pointer.idx].V_var = (cmd.axis.pointer.speed_type == 0); - } - else - { - if (!pseudopointer[cmd.axis.pointer.idx].H_adj) - pseudopointer[cmd.axis.pointer.idx].H_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767); - pseudopointer[cmd.axis.pointer.idx].H_var = (cmd.axis.pointer.speed_type == 0); - } - } - - return; - - case S9xAxisPseudobuttons: - if (data1 > ((cmd.axis.button.threshold + 1) * 127)) - { - if (!pseudobuttons[cmd.axis.button.posbutton]) - { - pseudobuttons[cmd.axis.button.posbutton] = 1; - S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, true); - } - } - else - { - if (pseudobuttons[cmd.axis.button.posbutton]) - { - pseudobuttons[cmd.axis.button.posbutton] = 0; - S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, false); - } - } - - if (data1 <= ((cmd.axis.button.threshold + 1) * -127)) - { - if (!pseudobuttons[cmd.axis.button.negbutton]) - { - pseudobuttons[cmd.axis.button.negbutton] = 1; - S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, true); - } - } - else - { - if (pseudobuttons[cmd.axis.button.negbutton]) - { - pseudobuttons[cmd.axis.button.negbutton] = 0; - S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, false); - } - } - - return; - - case S9xButtonPort: - case S9xAxisPort: - case S9xPointerPort: - S9xHandlePortCommand(cmd, data1, data2); - return; - - case S9xButtonMulti: - if (cmd.button.multi_idx >= (int) multis.size()) - return; - - if (multis[cmd.button.multi_idx]->multi_press && !data1) - return; - - i = ApplyMulti(multis[cmd.button.multi_idx], 0, data1); - if (i >= 0) - { - struct exemulti *e = new struct exemulti; - e->pos = i; - e->data1 = data1 != 0; - e->script = multis[cmd.button.multi_idx]; - exemultis.insert(e); - } - - return; - - default: - fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type); - return; - } + S9xSetInfoString("No movie in progress."); + return; + } + + char msg[128]; + sprintf(msg, "Select frame number (current: %d)", S9xMovieGetFrameCounter()); + + const char *frameno = S9xStringInput(msg); + if (!frameno) + return; + int frameDest = atoi(frameno); + if (frameDest > 0 && frameDest > (int)S9xMovieGetFrameCounter()) + { + int distance = frameDest - S9xMovieGetFrameCounter(); + Settings.HighSpeedSeek = distance; + } +#endif + } // braces for vlocalitylocality + break; + + case LAST_COMMAND: break; + /* no default, so we get compiler warnings */ + } + } + return; + + case S9xPointer: + if(cmd.pointer.aim_mouse0){ + mouse[0].cur_x=data1; + mouse[0].cur_y=data2; + } + if(cmd.pointer.aim_mouse1){ + mouse[1].cur_x=data1; + mouse[1].cur_y=data2; + } + if(cmd.pointer.aim_scope){ + superscope.x=data1; + superscope.y=data2; + } + if(cmd.pointer.aim_justifier0){ + justifier.x[0]=data1; + justifier.y[0]=data2; + } + if(cmd.pointer.aim_justifier1){ + justifier.x[1]=data1; + justifier.y[1]=data2; + } + return; + + case S9xButtonPseudopointer: + if(data1){ + if(cmd.button.pointer.UD){ + if(!pseudopointer[cmd.button.pointer.idx].V_adj) pseudopointer[cmd.button.pointer.idx].V_adj=cmd.button.pointer.UD*ptrspeeds[cmd.button.pointer.speed_type]; + pseudopointer[cmd.button.pointer.idx].V_var=(cmd.button.pointer.speed_type==0); + } + if(cmd.button.pointer.LR){ + if(!pseudopointer[cmd.button.pointer.idx].H_adj) pseudopointer[cmd.button.pointer.idx].H_adj=cmd.button.pointer.LR*ptrspeeds[cmd.button.pointer.speed_type]; + pseudopointer[cmd.button.pointer.idx].H_var=(cmd.button.pointer.speed_type==0); + } + } else { + if(cmd.button.pointer.UD){ + pseudopointer[cmd.button.pointer.idx].V_adj=0; + pseudopointer[cmd.button.pointer.idx].V_var=false; + } + if(cmd.button.pointer.LR){ + pseudopointer[cmd.button.pointer.idx].H_adj=0; + pseudopointer[cmd.button.pointer.idx].H_var=false; + } + } + return; + + case S9xAxisJoypad: + { + uint16 pos, neg; + switch(cmd.axis.joypad.axis){ + case 0: neg=SNES_LEFT_MASK; pos=SNES_RIGHT_MASK; break; + case 1: neg=SNES_UP_MASK; pos=SNES_DOWN_MASK; break; + case 2: neg=SNES_Y_MASK; pos=SNES_A_MASK; break; + case 3: neg=SNES_X_MASK; pos=SNES_B_MASK; break; + case 4: neg=SNES_TL_MASK; pos=SNES_TR_MASK; break; + default: return; + } + if(cmd.axis.joypad.invert) data1=-data1; + uint16 p, r; + p=r=0; + if(data1>((cmd.axis.joypad.threshold+1)*127)){ + p|=pos; + } else { + r|=pos; + } + if(data1<=((cmd.axis.joypad.threshold+1)*-127)){ + p|=neg; + } else { + r|=neg; + } + joypad[cmd.axis.joypad.idx].buttons |= p; + joypad[cmd.axis.joypad.idx].buttons &= ~r; + joypad[cmd.axis.joypad.idx].turbos &= ~(p|r); + } + return; + + case S9xAxisPseudopointer: + if(data1==0){ + if(cmd.axis.pointer.HV){ + pseudopointer[cmd.axis.pointer.idx].V_adj=0; + pseudopointer[cmd.axis.pointer.idx].V_var=false; + } else { + pseudopointer[cmd.axis.pointer.idx].H_adj=0; + pseudopointer[cmd.axis.pointer.idx].H_var=false; + } + } else { + if(cmd.axis.pointer.invert) data1=-data1; + if(cmd.axis.pointer.HV){ + if(!pseudopointer[cmd.axis.pointer.idx].V_adj) pseudopointer[cmd.axis.pointer.idx].V_adj=(int16)((int32)data1*ptrspeeds[cmd.axis.pointer.speed_type]/32767); + pseudopointer[cmd.axis.pointer.idx].V_var=(cmd.axis.pointer.speed_type==0); + } else { + if(!pseudopointer[cmd.axis.pointer.idx].H_adj) pseudopointer[cmd.axis.pointer.idx].H_adj=(int16)((int32)data1*ptrspeeds[cmd.axis.pointer.speed_type]/32767); + pseudopointer[cmd.axis.pointer.idx].H_var=(cmd.axis.pointer.speed_type==0); + } + } + return; + + case S9xAxisPseudobuttons: + if(data1>((cmd.axis.button.threshold+1)*127)){ + if(!pseudobuttons[cmd.axis.button.posbutton]){ + pseudobuttons[cmd.axis.button.posbutton]=1; + S9xReportButton(PseudoButtonBase+cmd.axis.button.posbutton, true); + } + } else { + if(pseudobuttons[cmd.axis.button.posbutton]){ + pseudobuttons[cmd.axis.button.posbutton]=0; + S9xReportButton(PseudoButtonBase+cmd.axis.button.posbutton, false); + } + } + if(data1<=((cmd.axis.button.threshold+1)*-127)){ + if(!pseudobuttons[cmd.axis.button.negbutton]){ + pseudobuttons[cmd.axis.button.negbutton]=1; + S9xReportButton(PseudoButtonBase+cmd.axis.button.negbutton, true); + } + } else { + if(pseudobuttons[cmd.axis.button.negbutton]){ + pseudobuttons[cmd.axis.button.negbutton]=0; + S9xReportButton(PseudoButtonBase+cmd.axis.button.negbutton, false); + } + } + return; + + case S9xButtonPort: + case S9xAxisPort: + case S9xPointerPort: + S9xHandlePortCommand(cmd, data1, data2); + return; + + case S9xButtonMulti: + if(cmd.button.multi_idx>=(int)multis.size()) return; + if(multis[cmd.button.multi_idx]->multi_press && !data1) return; + i=ApplyMulti(multis[cmd.button.multi_idx], 0, data1); + if(i>=0){ + struct exemulti *e=new struct exemulti; + e->pos=i; + e->data1=data1!=0; + e->script=multis[cmd.button.multi_idx]; + exemultis.insert(e); + } + return; + + + + default: + fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type); + return; + } } -static void do_polling (int mp) -{ - set::iterator itr; - if (S9xMoviePlaying()) - return; +static void do_polling(int mp){ + set::iterator itr; - if (pollmap[mp].empty()) - return; + if(pollmap[mp].empty()) return; +#ifndef NGC + if(S9xMoviePlaying()) return; +#endif + for(itr=pollmap[mp].begin(); itr!=pollmap[mp].end(); itr++){ + switch(maptype(keymap[*itr].type)){ + case MAP_BUTTON: + bool pressed; + if(S9xPollButton(*itr, &pressed)) S9xReportButton(*itr, pressed); + break; - for (itr = pollmap[mp].begin(); itr != pollmap[mp].end(); itr++) - { - switch (maptype(keymap[*itr].type)) - { - case MAP_BUTTON: - { - bool pressed; - if (S9xPollButton(*itr, &pressed)) - S9xReportButton(*itr, pressed); - break; - } + case MAP_AXIS: + int16 value; + if(S9xPollAxis(*itr, &value)) S9xReportAxis(*itr, value); + break; - case MAP_AXIS: - { - int16 value; - if (S9xPollAxis(*itr, &value)) - S9xReportAxis(*itr, value); - break; - } + case MAP_POINTER: + int16 x, y; + if(S9xPollPointer(*itr, &x, &y)) S9xReportPointer(*itr, x, y); + break; - case MAP_POINTER: - { - int16 x, y; - if (S9xPollPointer(*itr, &x, &y)) - S9xReportPointer(*itr, x, y); - break; - } - - default: - break; - } - } + default: + break; + } + } } -static void UpdatePolledMouse (int i) -{ - int16 j; - - j = mouse[i - MOUSE0].cur_x - mouse[i - MOUSE0].old_x; - - if (j < -127) - { - mouse[i - MOUSE0].delta_x = 0xff; - mouse[i - MOUSE0].old_x -= 127; - } - else - if (j < 0) - { - mouse[i - MOUSE0].delta_x = 0x80 | -j; - mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x; - } - else - if (j > 127) - { - mouse[i - MOUSE0].delta_x = 0x7f; - mouse[i - MOUSE0].old_x += 127; - } - else - { - mouse[i - MOUSE0].delta_x = (uint8) j; - mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x; - } - - j = mouse[i - MOUSE0].cur_y - mouse[i - MOUSE0].old_y; - - if (j < -127) - { - mouse[i - MOUSE0].delta_y = 0xff; - mouse[i - MOUSE0].old_y -= 127; - } - else - if (j < 0) - { - mouse[i - MOUSE0].delta_y = 0x80 | -j; - mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y; - } - else - if (j > 127) - { - mouse[i - MOUSE0].delta_y = 0x7f; - mouse[i - MOUSE0].old_y += 127; - } - else - { - mouse[i - MOUSE0].delta_y = (uint8) j; - mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y; - } +static void UpdatePolledMouse(int i) { + int16 j; + j=mouse[i-MOUSE0].cur_x-mouse[i-MOUSE0].old_x; + if(j<-127){ + mouse[i-MOUSE0].delta_x=0xff; + mouse[i-MOUSE0].old_x-=127; + } else if(j<0){ + mouse[i-MOUSE0].delta_x=0x80 | -j; + mouse[i-MOUSE0].old_x=mouse[i-MOUSE0].cur_x; + } else if(j>127){ + mouse[i-MOUSE0].delta_x=0x7f; + mouse[i-MOUSE0].old_x+=127; + } else { + mouse[i-MOUSE0].delta_x=(uint8)j; + mouse[i-MOUSE0].old_x=mouse[i-MOUSE0].cur_x; + } + j=mouse[i-MOUSE0].cur_y-mouse[i-MOUSE0].old_y; + if(j<-127){ + mouse[i-MOUSE0].delta_y=0xff; + mouse[i-MOUSE0].old_y-=127; + } else if(j<0){ + mouse[i-MOUSE0].delta_y=0x80 | -j; + mouse[i-MOUSE0].old_y=mouse[i-MOUSE0].cur_y; + } else if(j>127){ + mouse[i-MOUSE0].delta_y=0x7f; + mouse[i-MOUSE0].old_y+=127; + } else { + mouse[i-MOUSE0].delta_y=(uint8)j; + mouse[i-MOUSE0].old_y=mouse[i-MOUSE0].cur_y; + } } -void S9xSetJoypadLatch (bool latch) -{ - if (!latch && FLAG_LATCH) - { - // 1 written, 'plug in' new controllers now - curcontrollers[0] = newcontrollers[0]; - curcontrollers[1] = newcontrollers[1]; - } +void S9xSetJoypadLatch(bool latch){ + if(!latch && FLAG_LATCH){ + // 1 written, 'plug in' new controllers now + curcontrollers[0]=newcontrollers[0]; + curcontrollers[1]=newcontrollers[1]; + } + if(latch && !FLAG_LATCH){ + int i, j, n; - if (latch && !FLAG_LATCH) - { - int i; + for(n=0; n<2; n++){ + for(j=0; j<2; j++){ + read_idx[n][j]=0; + } + switch(i=curcontrollers[n]){ + case MP5: + for(j=0, i=mp5[n].pads[j]; j<4; i=mp5[n].pads[++j]){ + if(i==NONE) continue; + do_polling(i); + } + break; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + do_polling(i); + break; - for (int n = 0; n < 2; n++) - { - for (int j = 0; j < 2; j++) - read_idx[n][j] = 0; - - switch (i = curcontrollers[n]) - { - case MP5: - for (int j = 0, k = mp5[n].pads[j]; j < 4; k = mp5[n].pads[++j]) - { - if (k == NONE) - continue; - do_polling(k); - } - - break; - - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - do_polling(i); - break; - - case MOUSE0: - case MOUSE1: - do_polling(i); - if (!S9xMoviePlaying()) - UpdatePolledMouse(i); - break; - - case SUPERSCOPE: - if (superscope.next_buttons & SUPERSCOPE_FIRE) - { - superscope.next_buttons &= ~SUPERSCOPE_TURBO; - superscope.next_buttons |= superscope.phys_buttons & SUPERSCOPE_TURBO; - } - - if (superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) - { - superscope.next_buttons &= ~SUPERSCOPE_OFFSCREEN; - superscope.next_buttons |= superscope.phys_buttons & SUPERSCOPE_OFFSCREEN; - } - - superscope.read_buttons = superscope.next_buttons; - - superscope.next_buttons &= ~SUPERSCOPE_PAUSE; - if (!(superscope.phys_buttons & SUPERSCOPE_TURBO)) - superscope.next_buttons &= ~(SUPERSCOPE_CURSOR | SUPERSCOPE_FIRE); - - do_polling(i); - break; - - case TWO_JUSTIFIERS: - do_polling(TWO_JUSTIFIERS); - // fall through - - case ONE_JUSTIFIER: - justifier.buttons ^= JUSTIFIER_SELECT; - do_polling(ONE_JUSTIFIER); - break; - - default: - break; - } - } - } - - FLAG_LATCH = latch; + case MOUSE0: case MOUSE1: + do_polling(i); +#ifndef NGC + if(!S9xMoviePlaying()) +#endif + UpdatePolledMouse(i); + break; + case SUPERSCOPE: + if(superscope.next_buttons&SUPERSCOPE_FIRE){ + superscope.next_buttons&=~SUPERSCOPE_TURBO; + superscope.next_buttons|=superscope.phys_buttons&SUPERSCOPE_TURBO; + } + if(superscope.next_buttons&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR)){ + superscope.next_buttons&=~SUPERSCOPE_OFFSCREEN; + superscope.next_buttons|=superscope.phys_buttons&SUPERSCOPE_OFFSCREEN; + } + superscope.read_buttons=superscope.next_buttons; + superscope.next_buttons&=~SUPERSCOPE_PAUSE; + if(!(superscope.phys_buttons&SUPERSCOPE_TURBO)) superscope.next_buttons&=~(SUPERSCOPE_CURSOR|SUPERSCOPE_FIRE); + do_polling(i); + break; + case TWO_JUSTIFIERS: + do_polling(TWO_JUSTIFIERS); + /* fall through */ + case ONE_JUSTIFIER: + justifier.buttons^=JUSTIFIER_SELECT; + do_polling(ONE_JUSTIFIER); + break; + default: + break; + } + } + } + FLAG_LATCH=latch; } -uint8 S9xReadJOYSERn (int n) -{ - int i, j, r; +uint8 S9xReadJOYSERn(int n){ + int i, j, r; - if (n > 1) - n -= 0x4016; - assert(n == 0 || n == 1); + if(n>1) n-=0x4016; + assert(n==0 || n==1); - uint8 bits = (OpenBus & ~3) | ((n == 1) ? 0x1c : 0); + uint8 bits=(OpenBus&~3)|((n==1)?0x1c:0); - if (FLAG_LATCH) - { - switch (i = curcontrollers[n]) - { - case MP5: - return (bits | 2); - - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - return (bits | ((joypad[i - JOYPAD0].buttons & 0x8000) ? 1 : 0)); - - case MOUSE0: - case MOUSE1: - mouse[i - MOUSE0].buttons += 0x10; - if ((mouse[i - MOUSE0].buttons & 0x30) == 0x30) - mouse[i - MOUSE0].buttons &= 0xcf; - return (bits); - - case SUPERSCOPE: - return (bits | ((superscope.read_buttons & 0x80) ? 1 : 0)); - - case ONE_JUSTIFIER: - case TWO_JUSTIFIERS: - return (bits); - - default: - return (bits); - } - } - else - { - switch (i = curcontrollers[n]) - { - case MP5: - r = read_idx[n][FLAG_IOBIT(n) ? 0 : 1]++; - j = FLAG_IOBIT(n) ? 0 : 2; - - for (i = 0; i < 2; i++, j++) - { - if (mp5[n].pads[j] == NONE) - continue; - if (r >= 16) - bits |= 1 << i; - else - bits |= ((joypad[mp5[n].pads[j] - JOYPAD0].buttons & (0x8000 >> r)) ? 1 : 0) << i; - } - - return (bits); - - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - if (read_idx[n][0] >= 16) - { - read_idx[n][0]++; - return (bits | 1); - } - else - return (bits | ((joypad[i - JOYPAD0].buttons & (0x8000 >> read_idx[n][0]++)) ? 1 : 0)); - - case MOUSE0: - case MOUSE1: - if (read_idx[n][0] < 8) - { - read_idx[n][0]++; - return (bits); - } - else - if (read_idx[n][0] < 16) - return (bits | ((mouse[i - MOUSE0].buttons & (0x8000 >> read_idx[n][0]++)) ? 1 : 0)); - else - if (read_idx[n][0] < 24) - return (bits | ((mouse[i - MOUSE0].delta_y & (0x800000 >> read_idx[n][0]++)) ? 1 : 0)); - else - if (read_idx[n][0] < 32) - return (bits | ((mouse[i - MOUSE0].delta_x & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); - else - { - read_idx[n][0]++; - return (bits | 1); - } - - case SUPERSCOPE: - if (read_idx[n][0] < 8) - return (bits | ((superscope.read_buttons & (0x80 >> read_idx[n][0]++)) ? 1 : 0)); - else - { - read_idx[n][0]++; - return (bits | 1); - } - - case ONE_JUSTIFIER: - if (read_idx[n][0] < 24) - return (bits | ((0xaa7000 >> read_idx[n][0]++) & 1)); - else - if (read_idx[n][0] < 32) - return (bits | ((justifier.buttons & (JUSTIFIER_TRIGGER | JUSTIFIER_START | JUSTIFIER_SELECT) & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); - else - { - read_idx[n][0]++; - return (bits | 1); - } - - case TWO_JUSTIFIERS: - if (read_idx[n][0] < 24) - return (bits | ((0xaa7000 >> read_idx[n][0]++) & 1)); - else - if (read_idx[n][0] < 32) - return (bits | ((justifier.buttons & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); - else - { - read_idx[n][0]++; - return (bits | 1); - } - - default: - read_idx[n][0]++; - return (bits); - } - } + if(FLAG_LATCH){ + switch(i=curcontrollers[n]){ + case MP5: + return bits|2; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + return bits|((joypad[i-JOYPAD0].buttons&0x8000)?1:0); + case MOUSE0: case MOUSE1: + mouse[i-MOUSE0].buttons+=0x10; + if((mouse[i-MOUSE0].buttons&0x30)==0x30) + mouse[i-MOUSE0].buttons&=0xcf; + return bits; + case SUPERSCOPE: + return bits|((superscope.read_buttons&0x80)?1:0); + case ONE_JUSTIFIER: case TWO_JUSTIFIERS: + return bits; + default: + return bits; + } + } else { + switch(i=curcontrollers[n]){ + case MP5: + r=read_idx[n][FLAG_IOBIT(n)?0:1]++; + j=FLAG_IOBIT(n)?0:2; + for(i=0; i<2; i++, j++){ + if(mp5[n].pads[j]==NONE) continue; + if(r>=16){ + bits|=1<>r))?1:0)<=16){ + read_idx[n][0]++; + return bits|1; + } else { + return bits|((joypad[i-JOYPAD0].buttons&(0x8000>>read_idx[n][0]++))?1:0); + } + case MOUSE0: case MOUSE1: + if(read_idx[n][0]<8){ + read_idx[n][0]++; + return bits; + } else if(read_idx[n][0]<16){ + return bits|((mouse[i-MOUSE0].buttons&(0x8000>>read_idx[n][0]++))?1:0); + } else if(read_idx[n][0]<24){ + return bits|((mouse[i-MOUSE0].delta_y&(0x800000>>read_idx[n][0]++))?1:0); + } else if(read_idx[n][0]<32){ + return bits|((mouse[i-MOUSE0].delta_x&(0x80000000>>read_idx[n][0]++))?1:0); + } else { + read_idx[n][0]++; + return bits|1; + } + case SUPERSCOPE: + if(read_idx[n][0]<8){ + return bits|((superscope.read_buttons&(0x80>>read_idx[n][0]++))?1:0); + } else { + read_idx[n][0]++; + return bits|1; + } + case ONE_JUSTIFIER: + if(read_idx[n][0]<24){ + return bits|((0xaa7000>>read_idx[n][0]++)&1); + } else if(read_idx[n][0]<32){ + bits|=((justifier.buttons & + (JUSTIFIER_TRIGGER|JUSTIFIER_START|JUSTIFIER_SELECT) & + (0x80000000>>read_idx[n][0]++))?1:0); + return bits; + } else { + read_idx[n][0]++; + return bits|1; + } + case TWO_JUSTIFIERS: + if(read_idx[n][0]<24){ + return bits|((0xaa7000>>read_idx[n][0]++)&1); + } else if(read_idx[n][0]<32){ + return bits|((justifier.buttons&(0x80000000>>read_idx[n][0]++))?1:0); + } else { + read_idx[n][0]++; + return bits|1; + } + default: + read_idx[n][0]++; + return bits; + } + } } -void S9xDoAutoJoypad (void) -{ - int i, j; - - S9xSetJoypadLatch(1); - S9xSetJoypadLatch(0); +void S9xDoAutoJoypad(void){ + int n, i, j; + S9xSetJoypadLatch(1); + S9xSetJoypadLatch(0); +#ifndef NGC S9xMovieUpdate(false); - - for (int n = 0; n < 2; n++) - { - switch (i = curcontrollers[n]) - { - case MP5: - j = FLAG_IOBIT(n) ? 0 : 2; - for (i = 0; i < 2; i++, j++) - { - if (mp5[n].pads[j] == NONE) - WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2 + i * 4, 0); - else - WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2 + i * 4, joypad[mp5[n].pads[j] - JOYPAD0].buttons); - } - - read_idx[n][FLAG_IOBIT(n) ? 0 : 1] = 16; - break; - - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - read_idx[n][0] = 16; - WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, joypad[i - JOYPAD0].buttons); - WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); - break; - - case MOUSE0: - case MOUSE1: - read_idx[n][0] = 16; - WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, mouse[i - MOUSE0].buttons); - WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); - break; - - case SUPERSCOPE: - read_idx[n][0] = 16; - Memory.FillRAM[0x4218 + n * 2] = 0xff; - Memory.FillRAM[0x4219 + n * 2] = superscope.read_buttons; - WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); - break; - - case ONE_JUSTIFIER: - case TWO_JUSTIFIERS: - read_idx[n][0] = 16; - WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0x000e); - WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); - break; - - default: - WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0); - WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); - break; - } - } +#endif + for(n=0; n<2; n++){ + switch(i=curcontrollers[n]){ + case MP5: + j=FLAG_IOBIT(n)?0:2; + for(i=0; i<2; i++, j++){ + if(mp5[n].pads[j]==NONE){ + WRITE_WORD(Memory.FillRAM+0x4218+n*2+i*4, 0); + } else { + WRITE_WORD(Memory.FillRAM+0x4218+n*2+i*4, joypad[mp5[n].pads[j]-JOYPAD0].buttons); + } + } + read_idx[n][FLAG_IOBIT(n)?0:1]=16; + break; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + read_idx[n][0]=16; + WRITE_WORD(Memory.FillRAM+0x4218+n*2, joypad[i-JOYPAD0].buttons); + WRITE_WORD(Memory.FillRAM+0x421c+n*2, 0); + break; + case MOUSE0: case MOUSE1: + read_idx[n][0]=16; + WRITE_WORD(Memory.FillRAM+0x4218+n*2, mouse[i-MOUSE0].buttons); + WRITE_WORD(Memory.FillRAM+0x421c+n*2, 0); + break; + case SUPERSCOPE: + read_idx[n][0]=16; + Memory.FillRAM[0x4218+n*2]=0xff; + Memory.FillRAM[0x4219+n*2]=superscope.read_buttons; + WRITE_WORD(Memory.FillRAM+0x421c+n*2, 0); + break; + case ONE_JUSTIFIER: case TWO_JUSTIFIERS: + read_idx[n][0]=16; + WRITE_WORD(Memory.FillRAM+0x4218+n*2, 0x000e); + WRITE_WORD(Memory.FillRAM+0x421c+n*2, 0); + break; + default: + WRITE_WORD(Memory.FillRAM+0x4218+n*2, 0); + WRITE_WORD(Memory.FillRAM+0x421c+n*2, 0); + break; + } + } } -void S9xControlEOF (void) -{ - struct crosshair *c; - int i, j; +void S9xControlEOF(void){ + int i, j, n; + struct crosshair *c; - PPU.GunVLatch = 1000; // i.e., never latch - PPU.GunHLatch = 0; + PPU.GunVLatch=1000; /* i.e., never latch */ + PPU.GunHLatch=0; - for (int n = 0; n < 2; n++) - { - switch (i = curcontrollers[n]) - { - case MP5: - for (j = 0, i = mp5[n].pads[j]; j < 4; i = mp5[n].pads[++j]) - { - if (i == NONE) - continue; + for(n=0; n<2; n++){ + switch(i=curcontrollers[n]){ + case MP5: + for(j=0, i=mp5[n].pads[j]; j<4; i=mp5[n].pads[++j]){ + if(i==NONE) continue; + if(++joypad[i-JOYPAD0].turbo_ct>=turbo_time){ + joypad[i-JOYPAD0].turbo_ct=0; + joypad[i-JOYPAD0].buttons ^= joypad[i-JOYPAD0].turbos; + } + } + break; + case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: + case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: + if(++joypad[i-JOYPAD0].turbo_ct>=turbo_time){ + joypad[i-JOYPAD0].turbo_ct=0; + joypad[i-JOYPAD0].buttons ^= joypad[i-JOYPAD0].turbos; + } + break; + case MOUSE0: case MOUSE1: + c=&mouse[i-MOUSE0].crosshair; + if(IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, + mouse[i-MOUSE0].cur_x, mouse[i-MOUSE0].cur_y); + break; + case SUPERSCOPE: + if(n==1 && !(superscope.phys_buttons&SUPERSCOPE_OFFSCREEN)){ + if(superscope.next_buttons&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR)) + DoGunLatch(superscope.x, superscope.y); - if (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) - { - joypad[i - JOYPAD0].turbo_ct = 0; - joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; - } - } + c=&superscope.crosshair; + if(IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, + superscope.x, superscope.y); + } + break; + case TWO_JUSTIFIERS: + if(n==1 && !justifier.offscreen[1]){ + c=&justifier.crosshair[1]; + if(IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, + justifier.x[1], justifier.y[1]); + } + i=(justifier.buttons&JUSTIFIER_SELECT)?1:0; + goto do_justifier; + case ONE_JUSTIFIER: + i=(justifier.buttons&JUSTIFIER_SELECT)?-1:0; +do_justifier: + if(n==1){ + if(i>=0 && !justifier.offscreen[i]) + DoGunLatch(justifier.x[i], justifier.y[i]); - break; + if(!justifier.offscreen[0]){ + c=&justifier.crosshair[0]; + if(IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, + justifier.x[0], justifier.y[0]); + } + } + break; + default: + break; + } + } - case JOYPAD0: - case JOYPAD1: - case JOYPAD2: - case JOYPAD3: - case JOYPAD4: - case JOYPAD5: - case JOYPAD6: - case JOYPAD7: - if (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) - { - joypad[i - JOYPAD0].turbo_ct = 0; - joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; - } + for(n=0; n<8; n++){ + if(!pseudopointer[n].mapped) continue; + if(pseudopointer[n].H_adj){ + pseudopointer[n].x+=pseudopointer[n].H_adj; + if(pseudopointer[n].x<0) pseudopointer[n].x=0; + if(pseudopointer[n].x>255) pseudopointer[n].x=255; + if(pseudopointer[n].H_var){ + if(pseudopointer[n].H_adj<0){ + if(pseudopointer[n].H_adj>-ptrspeeds[3]) pseudopointer[n].H_adj--; + } else { + if(pseudopointer[n].H_adjPPU.ScreenHeight-1) pseudopointer[n].y=PPU.ScreenHeight-1; + if(pseudopointer[n].V_var){ + if(pseudopointer[n].V_adj<0){ + if(pseudopointer[n].V_adj>-ptrspeeds[3]) pseudopointer[n].V_adj--; + } else { + if(pseudopointer[n].V_adjimg), c->fg, c->bg, mouse[i - MOUSE0].cur_x, mouse[i - MOUSE0].cur_y); - break; - - case SUPERSCOPE: - if (n == 1 && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN)) - { - if (superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) - DoGunLatch(superscope.x, superscope.y); - - c = &superscope.crosshair; - if (IPPU.RenderThisFrame) - S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, superscope.x, superscope.y); - } - - break; - - case TWO_JUSTIFIERS: - if (n == 1 && !justifier.offscreen[1]) - { - c = &justifier.crosshair[1]; - if (IPPU.RenderThisFrame) - S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[1], justifier.y[1]); - } - - i = (justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0; - goto do_justifier; - - case ONE_JUSTIFIER: - i = (justifier.buttons & JUSTIFIER_SELECT) ? -1 : 0; - - do_justifier: - if (n == 1) - { - if (i >= 0 && !justifier.offscreen[i]) - DoGunLatch(justifier.x[i], justifier.y[i]); - - if (!justifier.offscreen[0]) - { - c = &justifier.crosshair[0]; - if (IPPU.RenderThisFrame) - S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[0], justifier.y[0]); - } - } - - break; - - default: - break; - } - } - - for (int n = 0; n < 8; n++) - { - if (!pseudopointer[n].mapped) - continue; - - if (pseudopointer[n].H_adj) - { - pseudopointer[n].x += pseudopointer[n].H_adj; - if (pseudopointer[n].x < 0) - pseudopointer[n].x = 0; - else - if (pseudopointer[n].x > 255) - pseudopointer[n].x = 255; - - if (pseudopointer[n].H_var) - { - if (pseudopointer[n].H_adj < 0) - { - if (pseudopointer[n].H_adj > -ptrspeeds[3]) - pseudopointer[n].H_adj--; - } - else - { - if (pseudopointer[n].H_adj < ptrspeeds[3]) - pseudopointer[n].H_adj++; - } - } - } - - if (pseudopointer[n].V_adj) - { - pseudopointer[n].y += pseudopointer[n].V_adj; - if (pseudopointer[n].y < 0) - pseudopointer[n].y = 0; - else - if (pseudopointer[n].y > PPU.ScreenHeight - 1) - pseudopointer[n].y = PPU.ScreenHeight - 1; - - if (pseudopointer[n].V_var) - { - if (pseudopointer[n].V_adj < 0) - { - if (pseudopointer[n].V_adj > -ptrspeeds[3]) - pseudopointer[n].V_adj--; - } - else - { - if (pseudopointer[n].V_adj < ptrspeeds[3]) - pseudopointer[n].V_adj++; - } - } - } - - S9xReportPointer(PseudoPointerBase + n, pseudopointer[n].x, pseudopointer[n].y); - } - - set::iterator it, jt; - - for (it = exemultis.begin(); it != exemultis.end(); it++) - { - i = ApplyMulti((*it)->script, (*it)->pos, (*it)->data1); - - if (i >= 0) - (*it)->pos = i; - else - { - jt = it; - it--; - delete *jt; - exemultis.erase(jt); - } - } - - do_polling(POLL_ALL); - - S9xMovieUpdate(); + set::iterator it, jt; + for(it=exemultis.begin(); it!=exemultis.end(); it++){ + i=ApplyMulti((*it)->script, (*it)->pos, (*it)->data1); + if(i>=0){ + (*it)->pos=i; + } else { + jt=it; + it--; + delete *jt; + exemultis.erase(jt); + } + } + do_polling(POLL_ALL); +#ifndef NGC + S9xMovieUpdate(); +#endif pad_read_last = pad_read; - pad_read = false; + pad_read = false; } -void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg) -{ - struct crosshair *c; - int8 fgcolor = -1, bgcolor = -1; - int i, j; +void S9xSetControllerCrosshair(enum crosscontrols ctl, int8 idx, const char *fg, const char *bg){ + struct crosshair *c; + int8 fgcolor=-1, bgcolor=-1; + int i, j; - if (idx < -1 || idx > 31) - { - fprintf(stderr, "S9xSetControllerCrosshair() called with invalid index\n"); - return; - } + if(idx<-1 || idx>31){ + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid index\n"); + return; + } - switch (ctl) - { - case X_MOUSE1: c = &mouse[0].crosshair; break; - case X_MOUSE2: c = &mouse[1].crosshair; break; - case X_SUPERSCOPE: c = &superscope.crosshair; break; - case X_JUSTIFIER1: c = &justifier.crosshair[0]; break; - case X_JUSTIFIER2: c = &justifier.crosshair[1]; break; - default: - fprintf(stderr, "S9xSetControllerCrosshair() called with an invalid controller ID %d\n", ctl); - return; - } + switch(ctl){ + case X_MOUSE1: c=&mouse[0].crosshair; break; + case X_MOUSE2: c=&mouse[1].crosshair; break; + case X_SUPERSCOPE: c=&superscope.crosshair; break; + case X_JUSTIFIER1: c=&justifier.crosshair[0]; break; + case X_JUSTIFIER2: c=&justifier.crosshair[1]; break; + default: + fprintf(stderr, "S9xSetControllerCrosshair() called with an invalid controller ID %d\n", ctl); + return; + } - if (fg) - { - fgcolor = 0; - if (*fg == 't') - { - fg++; - fgcolor = 16; - } + if(fg!=NULL){ + fgcolor=0; + if(*fg=='t'){ fg++; fgcolor=16; } + for(i=0; i<16; i++){ + for(j=0; color_names[i][j] && fg[j]==color_names[i][j]; j++); + if(isalnum(fg[j])) continue; + if(!color_names[i][j]) break; + } + fgcolor|=i; + if(i>15 || fgcolor==16){ + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid fgcolor\n"); + return; + } + } - for (i = 0; i < 16; i++) - { - for (j = 0; color_names[i][j] && fg[j] == color_names[i][j]; j++) ; - if (isalnum(fg[j])) - continue; + if(bg!=NULL){ + bgcolor=0; + if(*bg=='t'){ bg++; bgcolor=16; } + for(i=0; i<16; i++){ + for(j=0; color_names[i][j] && bg[j]==color_names[i][j]; j++); + if(isalnum(bg[j])) continue; + if(!color_names[i][j]) break; + } + bgcolor|=i; + if(i>15 || bgcolor==16){ + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid bgcolor\n"); + return; + } + } - if (!color_names[i][j]) - break; - } - - fgcolor |= i; - if (i > 15 || fgcolor == 16) - { - fprintf(stderr, "S9xSetControllerCrosshair() called with invalid fgcolor\n"); - return; - } - } - - if (bg) - { - bgcolor = 0; - if (*bg == 't') - { - bg++; - bgcolor = 16; - } - - for (i = 0; i < 16; i++) - { - for (j = 0; color_names[i][j] && bg[j] == color_names[i][j]; j++) ; - if (isalnum(bg[j])) - continue; - - if (!color_names[i][j]) - break; - } - - bgcolor |= i; - if (i > 15 || bgcolor == 16) - { - fprintf(stderr, "S9xSetControllerCrosshair() called with invalid bgcolor\n"); - return; - } - } - - if (idx != -1) - { - c->set |= 1; - c->img = idx; - } - - if (fgcolor != -1) - { - c->set |= 2; - c->fg = fgcolor; - } - - if (bgcolor != -1) - { - c->set |= 4; - c->bg = bgcolor; - } + if(idx!=-1){ c->set|=1; c->img=idx; } + if(fgcolor!=-1){ c->set|=2; c->fg=fgcolor; } + if(bgcolor!=-1){c->set|=4; c->bg=bgcolor; } } -void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg) -{ - struct crosshair *c; +void S9xGetControllerCrosshair(enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg){ + struct crosshair *c; - switch (ctl) - { - case X_MOUSE1: c = &mouse[0].crosshair; break; - case X_MOUSE2: c = &mouse[1].crosshair; break; - case X_SUPERSCOPE: c = &superscope.crosshair; break; - case X_JUSTIFIER1: c = &justifier.crosshair[0]; break; - case X_JUSTIFIER2: c = &justifier.crosshair[1]; break; - default: - fprintf(stderr, "S9xGetControllerCrosshair() called with an invalid controller ID %d\n", ctl); - return; - } + switch(ctl){ + case X_MOUSE1: c=&mouse[0].crosshair; break; + case X_MOUSE2: c=&mouse[1].crosshair; break; + case X_SUPERSCOPE: c=&superscope.crosshair; break; + case X_JUSTIFIER1: c=&justifier.crosshair[0]; break; + case X_JUSTIFIER2: c=&justifier.crosshair[1]; break; + default: + fprintf(stderr, "S9xGetControllerCrosshair() called with an invalid controller ID %d\n", ctl); + return; + } - if (idx) - *idx = c->img; - - if (fg) - *fg = color_names[c->fg]; - - if (bg) - *bg = color_names[c->bg]; + if(idx!=NULL) *idx=c->img; + if(fg!=NULL) *fg=color_names[c->fg]; + if(bg!=NULL) *bg=color_names[c->bg]; } -void S9xControlPreSaveState (struct SControlSnapshot *s) -{ - ZeroMemory(s, sizeof(*s)); - s->ver = 3; +uint16 MovieGetJoypad(int i){ + if(i<0 || i>7) return 0; + return joypad[i].buttons; +} - for (int j = 0; j < 2; j++) - { - s->port1_read_idx[j] = read_idx[0][j]; - s->port2_read_idx[j] = read_idx[1][j]; - } +void MovieSetJoypad(int i, uint16 buttons){ + if(i<0 || i>7) return; + joypad[i].buttons=buttons; +} - for (int j = 0; j < 2; j++) - s->mouse_speed[j] = (mouse[j].buttons & 0x30) >> 4; +// from movie.cpp, used for MovieGetX functions to avoid platform-dependent byte order in the file +#ifndef NGC +extern void Write16(uint16 v, uint8*& ptr); +extern uint16 Read16(const uint8*& ptr); +#endif +#ifndef NGC +bool MovieGetMouse(int i, uint8 out [5]){ + if(i<0 || i>1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) return false; + const int n = curcontrollers[i]-MOUSE0; + uint8* ptr = out; + Write16(mouse[n].cur_x, ptr); + Write16(mouse[n].cur_y, ptr); + *ptr++ = mouse[n].buttons; + return true; +} - s->justifier_select = ((justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0); +void MovieSetMouse(int i, const uint8 in [5], bool inPolling){ + if(i<0 || i>1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) return; + const int n = curcontrollers[i]-MOUSE0; + const uint8* ptr = in; + mouse[n].cur_x = Read16(ptr); + mouse[n].cur_y = Read16(ptr); + mouse[n].buttons = *ptr++; + if(inPolling) + UpdatePolledMouse(curcontrollers[i]); +} -#define COPY(x) { memcpy((char *) s->internal + i, &(x), sizeof(x)); i += sizeof(x); } +bool MovieGetScope(int i, uint8 out [6]){ + if(i<0 || i>1 || (curcontrollers[i] != SUPERSCOPE)) return false; + uint8* ptr = out; + Write16(superscope.x, ptr); + Write16(superscope.y, ptr); + *ptr++ = superscope.phys_buttons; + *ptr++ = superscope.next_buttons; + return true; +} - int i = 0; +void MovieSetScope(int i, const uint8 in [6]){ + if(i<0 || i>1 || (curcontrollers[i] != SUPERSCOPE)) return; + const uint8* ptr = in; + superscope.x = Read16(ptr); + superscope.y = Read16(ptr); + superscope.phys_buttons = *ptr++; + superscope.next_buttons = *ptr++; +} - for (int j = 0; j < 8; j++) +bool MovieGetJustifier(int i, uint8 out [11]){ + if(i<0 || i>1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) return false; + uint8* ptr = out; + Write16(justifier.x[0], ptr); + Write16(justifier.x[1], ptr); + Write16(justifier.y[0], ptr); + Write16(justifier.y[1], ptr); + *ptr++ = justifier.buttons; + *ptr++ = justifier.offscreen[0]; + *ptr++ = justifier.offscreen[1]; + return true; +} + +void MovieSetJustifier(int i, const uint8 in [11]){ + if(i<0 || i>1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) return; + const uint8* ptr = in; + justifier.x[0] = Read16(ptr); + justifier.x[1] = Read16(ptr); + justifier.y[0] = Read16(ptr); + justifier.y[1] = Read16(ptr); + justifier.buttons = *ptr++; + justifier.offscreen[0] = *ptr++; + justifier.offscreen[1] = *ptr++; +} +#endif + +void S9xControlPreSave(struct SControlSnapshot *s){ + int i, j; + + ZeroMemory(s, sizeof(*s)); + s->ver=3; + for(i=0; i<2; i++){ + s->port1_read_idx[i]=read_idx[0][i]; + s->port2_read_idx[i]=read_idx[1][i]; + } + for(i=0; i<2; i++){ + s->mouse_speed[i]=(mouse[i].buttons&0x30)>>4; + } + s->justifier_select=((justifier.buttons&JUSTIFIER_SELECT)?1:0); + +#define COPY(x) {memcpy((char*)s->internal+i, &(x), sizeof(x)); i+=sizeof(x);} + i=0; + for(j=0; j<8; j++) COPY(joypad[j].buttons); - - for (int j = 0; j < 2; j++) - { + for(j=0; j<2; j++) { COPY(mouse[j].delta_x); COPY(mouse[j].delta_y); COPY(mouse[j].old_x); @@ -3469,70 +2673,54 @@ void S9xControlPreSaveState (struct SControlSnapshot *s) COPY(mouse[j].cur_y); COPY(mouse[j].buttons); } - COPY(superscope.x); COPY(superscope.y); COPY(superscope.phys_buttons); COPY(superscope.next_buttons); COPY(superscope.read_buttons); - - for (int j = 0; j < 2; j++) - COPY(justifier.x[j]); - for (int j = 0; j < 2; j++) - COPY(justifier.y[j]); + for(j=0; j<2; j++) COPY(justifier.x[j]); + for(j=0; j<2; j++) COPY(justifier.y[j]); COPY(justifier.buttons); - for (int j = 0; j < 2; j++) - COPY(justifier.offscreen[j]); - - for (int j = 0; j < 2; j++) - for (int k = 0; k < 2; k++) + for(j=0; j<2; j++) COPY(justifier.offscreen[j]); + for(j=0; j<2; j++) + for(int k=0; k<2; k++) COPY(mp5[j].pads[k]); - - assert(i == sizeof(s->internal)); - + assert(i==sizeof(s->internal)); #undef COPY - - s->pad_read = pad_read; - s->pad_read_last = pad_read_last; + s->pad_read=pad_read; + s->pad_read_last=pad_read_last; } -void S9xControlPostLoadState (struct SControlSnapshot *s) -{ - if (curcontrollers[0] == MP5 && s->ver < 1) +void S9xControlPostLoad(struct SControlSnapshot *s){ + int i, j; + + if(curcontrollers[0]==MP5 && s->ver<1){ + // Crap. Old snes9x didn't support this. + S9xMessage(S9X_WARNING, S9X_FREEZE_FILE_INFO, "Old savestate has no support for MP5 in port 1."); + newcontrollers[0]=curcontrollers[0]; + curcontrollers[0]=mp5[0].pads[0]; + } + for(i=0; i<2; i++){ + read_idx[0][i]=s->port1_read_idx[i]; + read_idx[1][i]=s->port2_read_idx[i]; + } + + mouse[0].buttons|=(s->mouse_speed[0]&3)<<4; + mouse[1].buttons|=(s->mouse_speed[1]&3)<<4; + if(s->justifier_select&1){ + justifier.buttons|=JUSTIFIER_SELECT; + } else { + justifier.buttons&=~JUSTIFIER_SELECT; + } + FLAG_LATCH=(Memory.FillRAM[0x4016]&1)==1; + + if(s->ver>1) { - // Crap. Old snes9x didn't support this. - S9xMessage(S9X_WARNING, S9X_FREEZE_FILE_INFO, "Old savestate has no support for MP5 in port 1."); - newcontrollers[0] = curcontrollers[0]; - curcontrollers[0] = mp5[0].pads[0]; - } - - for (int j = 0; j < 2; j++) - { - read_idx[0][j] = s->port1_read_idx[j]; - read_idx[1][j] = s->port2_read_idx[j]; - } - - for (int j = 0; j < 2; j++) - mouse[j].buttons |= (s->mouse_speed[j] & 3) << 4; - - if (s->justifier_select & 1) - justifier.buttons |= JUSTIFIER_SELECT; - else - justifier.buttons &= ~JUSTIFIER_SELECT; - - FLAG_LATCH = (Memory.FillRAM[0x4016] & 1) == 1; - - if (s->ver > 1) - { - #define COPY(x) { memcpy(&(x), (char *) s->internal + i, sizeof(x)); i += sizeof(x); } - - int i = 0; - - for (int j = 0; j < 8; j++) +#define COPY(x) {memcpy(&(x), (char*)s->internal+i, sizeof(x)); i+=sizeof(x);} + i=0; + for(j=0; j<8; j++) COPY(joypad[j].buttons); - - for (int j = 0; j < 2; j++) - { + for(j=0; j<2; j++) { COPY(mouse[j].delta_x); COPY(mouse[j].delta_y); COPY(mouse[j].old_x); @@ -3541,141 +2729,24 @@ void S9xControlPostLoadState (struct SControlSnapshot *s) COPY(mouse[j].cur_y); COPY(mouse[j].buttons); } - COPY(superscope.x); COPY(superscope.y); COPY(superscope.phys_buttons); COPY(superscope.next_buttons); COPY(superscope.read_buttons); - - for (int j = 0; j < 2; j++) - COPY(justifier.x[j]); - for (int j = 0; j < 2; j++) - COPY(justifier.y[j]); + for(j=0; j<2; j++) COPY(justifier.x[j]); + for(j=0; j<2; j++) COPY(justifier.y[j]); COPY(justifier.buttons); - for (int j = 0; j < 2; j++) - COPY(justifier.offscreen[j]); - for (int j = 0; j < 2; j++) - for (int k = 0; k < 2; k++) + for(j=0; j<2; j++) COPY(justifier.offscreen[j]); + for(j=0; j<2; j++) + for(int k=0; k<2; k++) COPY(mp5[j].pads[k]); - - assert(i == sizeof(s->internal)); - - #undef COPY + assert(i==sizeof(s->internal)); +#undef COPY } - - if (s->ver > 2) + if(s->ver>2) { - pad_read = s->pad_read; - pad_read_last = s->pad_read_last; + pad_read=s->pad_read; + pad_read_last=s->pad_read_last; } } - -uint16 MovieGetJoypad (int i) -{ - if (i < 0 || i > 7) - return (0); - - return (joypad[i].buttons); -} - -void MovieSetJoypad (int i, uint16 buttons) -{ - if (i < 0 || i > 7) - return; - - joypad[i].buttons = buttons; -} - -bool MovieGetMouse (int i, uint8 out[5]) -{ - if (i < 0 || i > 1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) - return (false); - - int n = curcontrollers[i] - MOUSE0; - uint8 *ptr = out; - - WRITE_WORD(ptr, mouse[n].cur_x); ptr += 2; - WRITE_WORD(ptr, mouse[n].cur_y); ptr += 2; - *ptr = mouse[n].buttons; - - return (true); -} - -void MovieSetMouse (int i, uint8 in[5], bool inPolling) -{ - if (i < 0 || i > 1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) - return; - - int n = curcontrollers[i] - MOUSE0; - uint8 *ptr = in; - - mouse[n].cur_x = READ_WORD(ptr); ptr += 2; - mouse[n].cur_y = READ_WORD(ptr); ptr += 2; - mouse[n].buttons = *ptr; - - if (inPolling) - UpdatePolledMouse(curcontrollers[i]); -} - -bool MovieGetScope (int i, uint8 out[6]) -{ - if (i < 0 || i > 1 || curcontrollers[i] != SUPERSCOPE) - return (false); - - uint8 *ptr = out; - - WRITE_WORD(ptr, superscope.x); ptr += 2; - WRITE_WORD(ptr, superscope.y); ptr += 2; - *ptr++ = superscope.phys_buttons; - *ptr = superscope.next_buttons; - - return (true); -} - -void MovieSetScope (int i, uint8 in[6]) -{ - if (i < 0 || i > 1 || curcontrollers[i] != SUPERSCOPE) - return; - - uint8 *ptr = in; - - superscope.x = READ_WORD(ptr); ptr += 2; - superscope.y = READ_WORD(ptr); ptr += 2; - superscope.phys_buttons = *ptr++; - superscope.next_buttons = *ptr; -} - -bool MovieGetJustifier (int i, uint8 out[11]) -{ - if (i < 0 || i > 1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) - return (false); - - uint8 *ptr = out; - - WRITE_WORD(ptr, justifier.x[0]); ptr += 2; - WRITE_WORD(ptr, justifier.x[1]); ptr += 2; - WRITE_WORD(ptr, justifier.y[0]); ptr += 2; - WRITE_WORD(ptr, justifier.y[1]); ptr += 2; - *ptr++ = justifier.buttons; - *ptr++ = justifier.offscreen[0]; - *ptr = justifier.offscreen[1]; - - return (true); -} - -void MovieSetJustifier (int i, uint8 in[11]) -{ - if (i < 0 || i > 1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) - return; - - uint8 *ptr = in; - - justifier.x[0] = READ_WORD(ptr); ptr += 2; - justifier.x[1] = READ_WORD(ptr); ptr += 2; - justifier.y[0] = READ_WORD(ptr); ptr += 2; - justifier.y[1] = READ_WORD(ptr); ptr += 2; - justifier.buttons = *ptr++; - justifier.offscreen[0] = *ptr++; - justifier.offscreen[1] = *ptr; -} diff --git a/source/snes9x/controls.h b/source/snes9x/controls.h index db434c6..a81d695 100644 --- a/source/snes9x/controls.h +++ b/source/snes9x/controls.h @@ -159,279 +159,292 @@ **********************************************************************************/ -#ifndef _CONTROLS_H_ -#define _CONTROLS_H_ -#define S9xNoMapping 0 -#define S9xButtonJoypad 1 -#define S9xButtonMouse 2 -#define S9xButtonSuperscope 3 -#define S9xButtonJustifier 4 -#define S9xButtonCommand 5 -#define S9xButtonMulti 6 -#define S9xAxisJoypad 7 -#define S9xPointer 8 +#ifndef FOO_H +#define FOO_H -#define S9xButtonPseudopointer 254 -#define S9xAxisPseudopointer 253 -#define S9xAxisPseudobuttons 252 +#include "port.h" -// These are automatically kicked out to the S9xHandlePortCommand function. -// If your port wants to define port-specific commands or whatever, use these values for the s9xcommand_t type field. +#define S9xNoMapping 0 +#define S9xButtonJoypad 1 +#define S9xButtonMouse 2 +#define S9xButtonSuperscope 3 +#define S9xButtonJustifier 4 +#define S9xButtonCommand 5 +#define S9xButtonMulti 6 +#define S9xAxisJoypad 7 +#define S9xPointer 8 -#define S9xButtonPort 251 -#define S9xAxisPort 250 -#define S9xPointerPort 249 +#define S9xButtonPseudopointer 254 +#define S9xAxisPseudopointer 253 +#define S9xAxisPseudobuttons 252 -#define S9xBadMapping 255 -#define InvalidControlID ((uint32) -1) +// These are automatically kicked out to the S9xHandlePortCommand function. If +// your port wants to define port-specific commands or whatever, use these +// values for the s9xcommand_t type field. +#define S9xButtonPort 251 +#define S9xAxisPort 250 +#define S9xPointerPort 249 -// S9xButtonPseudopointer and S9xAxisPseudopointer will report pointer motion using IDs PseudoPointerBase through PseudoPointerBase+7. -// S9xAxisPseudopointer command types. S9xAxisPseudobuttons will report buttons with IDs PseudoButtonBase to PseudoButtonBase+255. +#define S9xBadMapping 255 +#define InvalidControlID ((uint32)-1) -#define PseudoPointerBase (InvalidControlID - 8) -#define PseudoButtonBase (PseudoPointerBase - 256) +// S9xButtonPseudopointer and S9xAxisPseudopointer will report pointer motion +// using IDs PseudoPointerBase through PseudoPointerBase+7. +// S9xAxisPseudopointer command types. S9xAxisPseudobuttons will report buttons +// with IDs PseudoButtonBase to PseudoButtonBase+255. +#define PseudoPointerBase (InvalidControlID-8) +#define PseudoButtonBase (PseudoPointerBase-256) -typedef struct -{ - uint8 type; - uint8 multi_press:2; - uint8 button_norpt:1; +// Yes, this struct looks huge. But gcc makes it 6 bytes (the minimum), so it's +// not that bad. +typedef struct { + uint8 type; + uint8 multi_press:2; + uint8 button_norpt:1; - union - { - union - { - struct - { - uint8 idx:3; // Pad number 0-7 - uint8 toggle:1; // If set, toggle turbo/sticky for the button - uint8 turbo:1; // If set, be a 'turbo' button - uint8 sticky:1; // If set, toggle button state (on/turbo or off) when pressed and do nothing on release - uint16 buttons; // Which buttons to actuate. Use SNES_*_MASK constants from snes9x.h - } joypad; + union { + union { + struct { + uint8 idx:3; // Pad number 0-7 + uint8 toggle:1; // If set, toggle turbo/sticky for the button + uint8 turbo:1; // If set, be a 'turbo' button + uint8 sticky:1; // If set, toggle button state (on/turbo or off) + // when pressed and do nothing on release + uint16 buttons; // Which buttons to actuate. + // Use SNES_*_MASK constants from snes9x.h + } joypad; - struct - { - uint8 idx:1; // Mouse number 0-1 - uint8 left:1; // buttons - uint8 right:1; - } mouse; + struct { + uint8 idx:1; // Mouse number 0-1 + uint8 left:1; // buttons + uint8 right:1; + } mouse; - struct - { - uint8 fire:1; - uint8 cursor:1; - uint8 turbo:1; - uint8 pause:1; - uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer) - } scope; + struct { + uint8 fire:1; + uint8 cursor:1; + uint8 turbo:1; + uint8 pause:1; + uint8 aim_offscreen:1; // Pretend we're pointing the gun + // offscreen (ignore the pointer) + } scope; - struct - { - uint8 idx:3; // Pseudo-pointer number 0-7 - uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast - int8 UD:2; // -1=up, 1=down, 0=no vertical motion - int8 LR:2; // -1=left, 1=right, 0=no horizontal motion - } pointer; + struct { + uint8 idx:3; // Pseudo-pointer number 0-7 + uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast + int8 UD:2; // -1=up, 1=down, 0=no vertical motion + int8 LR:2; // -1=left, 1=right, 0=no horizontal motion + } pointer; - struct - { - uint8 idx:1; // Justifier number 0-1 - uint8 trigger:1; // buttons - uint8 start:1; - uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer) - } justifier; + struct { + uint8 idx:1; // Justifier number 0-1 + uint8 trigger:1; // buttons + uint8 start:1; + uint8 aim_offscreen:1; // Pretend we're pointing the gun + // offscreen (ignore the pointer) + } justifier; - int32 multi_idx; - uint16 command; - } button; + int32 multi_idx; + uint16 command; + } button; - union - { - struct - { - uint8 idx:3; // Pad number 0-7 - uint8 invert:1; // 1 = positive is Left/Up/Y/X/L - uint8 axis:3; // 0=Left/Right, 1=Up/Down, 2=Y/A, 3=X/B, 4=L/R - uint8 threshold; // (threshold+1)/256% deflection is a button press - } joypad; + union { + struct { + uint8 idx:3; // Pad number 0-7 + uint8 invert:1; // 1 = positive is Left/Up/Y/X/L + uint8 axis:3; // 0=Left/Right, 1=Up/Down, + // 2=Y/A, 3=X/B, 4=L/R + uint8 threshold; // (threshold+1)/256% deflection is a + // button press + } joypad; - struct - { - uint8 idx:3; // Pseudo-pointer number 0-7 - uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast - uint8 invert:1; // 1 = invert axis, so positive is up/left - uint8 HV:1; // 0=horizontal, 1=vertical - } pointer; + struct { + uint8 idx:3; // Pseudo-pointer number 0-7 + uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast + uint8 invert:1; // 1 = invert axis, so positive is up/left + uint8 HV:1; // 0=horizontal, 1=vertical + } pointer; - struct - { - uint8 threshold; // (threshold+1)/256% deflection is a button press - uint8 negbutton; // Button ID for negative deflection - uint8 posbutton; // Button ID for positive deflection - } button; - } axis; + struct { + uint8 threshold; // (threshold+1)/256% deflection is a + // button press + uint8 negbutton; // Button ID for negative deflection + uint8 posbutton; // Button ID for positive deflection + } button; + } axis; - struct // Which SNES-pointers to control with this pointer - { - uint16 aim_mouse0:1; - uint16 aim_mouse1:1; - uint16 aim_scope:1; - uint16 aim_justifier0:1; - uint16 aim_justifier1:1; - } pointer; + struct { + // Which SNES-pointers to control with this pointer + uint16 aim_mouse0:1; + uint16 aim_mouse1:1; + uint16 aim_scope:1; + uint16 aim_justifier0:1; + uint16 aim_justifier1:1; + } pointer; - uint8 port[4]; - }; -} s9xcommand_t; + uint8 port[4]; + }; +} s9xcommand_t; -// Starting out... -void S9xUnmapAllControls (void); +/* Starting out... */ +void S9xUnmapAllControls(void); -// Setting which controllers are plugged in. - -enum controllers -{ - CTL_NONE, // all ids ignored - CTL_JOYPAD, // use id1 to specify 0-7 - CTL_MOUSE, // use id1 to specify 0-1 - CTL_SUPERSCOPE, - CTL_JUSTIFIER, // use id1: 0=one justifier, 1=two justifiers - CTL_MP5 // use id1-id4 to specify pad 0-7 (or -1) +/* Setting which controllers are plugged in */ +enum controllers { + CTL_NONE, /* all ids ignored */ + CTL_JOYPAD, /* use id1 to specify 0-7 */ + CTL_MOUSE, /* use id1 to specify 0-1 */ + CTL_SUPERSCOPE, + CTL_JUSTIFIER, /* use id1: 0=one justifier, 1=two justifiers */ + CTL_MP5 /* use id1-id4 to specify pad 0-7 (or -1) */ }; +void S9xSetController(int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4); /* port=0-1 */ +void S9xGetController(int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4); +void S9xReportControllers(void); -void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4); // port=0-1 -void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4); -void S9xReportControllers (void); +/* Call this when you're done with S9xSetController, or if you change any of + * the controller Settings.*Master flags. Returns true if something was + * disabled */ +bool S9xVerifyControllers(void); -// Call this when you're done with S9xSetController, or if you change any of the controller Settings.*Master flags. -// Returns true if something was disabled. +/* + * Functions for translation s9xcommand_t's into strings, and vice versa. + * free() the returned string after you're done with it. + */ +char *S9xGetCommandName(s9xcommand_t command); +s9xcommand_t S9xGetCommandT(const char *name); -bool S9xVerifyControllers (void); +/* + * Returns an array of strings naming all the snes9x commands. Note that this + * is only the strings for S9xButtonCommand! The idea is that this would be + * used for a pull-down list in a config GUI. DO NOT free() the returned value. + */ +const char **S9xGetAllSnes9xCommands(void); -// Functions for translation s9xcommand_t's into strings, and vice versa. -// free() the returned string after you're done with it. +/* + * Generic mapping functions + */ +s9xcommand_t S9xGetMapping(uint32 id); +void S9xUnmapID(uint32 id); -char * S9xGetCommandName (s9xcommand_t command); -s9xcommand_t S9xGetCommandT (const char *name); +/* + * Button mapping functions. If a button is mapped with poll=TRUE, then + * S9xPollButton will be called whenever snes9x feels a need for that mapping. + * Otherwise, snes9x will assume you will call S9xReportButton() whenever the + * button state changes. S9xMapButton() will fail and return FALSE if + * mapping.type isn't a S9xButton* type. + */ +bool S9xMapButton(uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportButton(uint32 id, bool pressed); -// Returns an array of strings naming all the snes9x commands. -// Note that this is only the strings for S9xButtonCommand! -// The idea is that this would be used for a pull-down list in a config GUI. DO NOT free() the returned value. +/* + * Pointer mapping functions. If a button is mapped with poll=TRUE, then + * S9xPollPointer will be called whenever snes9x feels a need for that mapping. + * Otherwise, snes9x will assume you will call S9xReportPointer() whenever the + * pointer position changes. S9xMapPointer() will fail and return FALSE if + * mapping.type isn't S9xPointer. + * + * Note that position [0,0] is considered the upper-left corner of the + * 'screen', and either [255,223] or [255,239] is the lower-right. Note that + * the SNES mouse doesn't aim at a particular point, so the SNES's idea of + * where the mouse pointer is will probably differ from your OS's idea. + */ +bool S9xMapPointer(uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportPointer(uint32 id, int16 x, int16 y); -const char ** S9xGetAllSnes9xCommands (void); +/* + * Axis mapping functions. If a button is mapped with poll=TRUE, then + * S9xPollAxis will be called whenever snes9x feels a need for that mapping. + * Otherwise, snes9x will assume you will call S9xReportAxis() whenever the + * axis deflection changes. S9xMapAxis() will fail and return FALSE if + * mapping.type isn't a S9xAxis* type. + * + * Note that value is linear -32767 through 32767 with 0 being no + * deflection. If your axis reports differently you should transform the + * value before passing it to S9xReportAxis(). + */ +bool S9xMapAxis(uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportAxis(uint32 id, int16 value); -// Generic mapping functions +/* + * Do whatever the s9xcommand_t says to do. If cmd.type is a button type, data1 + * should be TRUE (non-0) or FALSE (0) to indicate whether the 'button' is + * pressed or released. If cmd.type is an axis, data1 holds the deflection + * value. If cmd.type is a pointer, data1 and data2 are the positions of the + * pointer. + */ +void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2); -s9xcommand_t S9xGetMapping (uint32 id); -void S9xUnmapID (uint32 id); +/******* + * These functions are called by snes9x into your port, so each port should + * implement them. + */ -// Button mapping functions. -// If a button is mapped with poll=TRUE, then S9xPollButton will be called whenever snes9x feels a need for that mapping. -// Otherwise, snes9x will assume you will call S9xReportButton() whenever the button state changes. -// S9xMapButton() will fail and return FALSE if mapping.type isn't an S9xButton* type. +/* + * If something was mapped with poll=TRUE, these functions will be called when + * snes9x needs the button/axis/pointer state. Fill in the reference options as + * appropriate. + */ +bool S9xPollButton(uint32 id, bool *pressed); +bool S9xPollPointer(uint32 id, int16 *x, int16 *y); +bool S9xPollAxis(uint32 id, int16 *value); -bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll); -void S9xReportButton (uint32 id, bool pressed); - -// Pointer mapping functions. -// If a pointer is mapped with poll=TRUE, then S9xPollPointer will be called whenever snes9x feels a need for that mapping. -// Otherwise, snes9x will assume you will call S9xReportPointer() whenever the pointer position changes. -// S9xMapPointer() will fail and return FALSE if mapping.type isn't an S9xPointer* type. - -// Note that position [0,0] is considered the upper-left corner of the 'screen', -// and either [255,223] or [255,239] is the lower-right. -// Note that the SNES mouse doesn't aim at a particular point, -// so the SNES's idea of where the mouse pointer is will probably differ from your OS's idea. - -bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll); -void S9xReportPointer (uint32 id, int16 x, int16 y); - -// Axis mapping functions. -// If an axis is mapped with poll=TRUE, then S9xPollAxis will be called whenever snes9x feels a need for that mapping. -// Otherwise, snes9x will assume you will call S9xReportAxis() whenever the axis deflection changes. -// S9xMapAxis() will fail and return FALSE if mapping.type isn't an S9xAxis* type. - -// Note that value is linear -32767 through 32767 with 0 being no deflection. -// If your axis reports differently you should transform the value before passing it to S9xReportAxis(). - -bool S9xMapAxis (uint32 id, s9xcommand_t mapping, bool poll); -void S9xReportAxis (uint32 id, int16 value); - -// Do whatever the s9xcommand_t says to do. -// If cmd.type is a button type, data1 should be TRUE (non-0) or FALSE (0) to indicate whether the 'button' is pressed or released. -// If cmd.type is an axis, data1 holds the deflection value. -// If cmd.type is a pointer, data1 and data2 are the positions of the pointer. - -void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2); - -////////// -// These functions are called by snes9x into your port, so each port should implement them. - -// If something was mapped with poll=TRUE, these functions will be called when snes9x needs the button/axis/pointer state. -// Fill in the reference options as appropriate. - -bool S9xPollButton (uint32 id, bool *pressed); -bool S9xPollPointer (uint32 id, int16 *x, int16 *y); -bool S9xPollAxis (uint32 id, int16 *value); - -// These are called when snes9x tries to apply a command with a S9x*Port type. -// data1 and data2 are filled in like S9xApplyCommand. - -void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2); - -// Called before already-read SNES joypad data is being used by the game if your port defines SNES_JOY_READ_CALLBACKS. +/* + * These are called when snes9x tries to apply a command with a S9x*Port type. + * data1 and data2 are filled in like S9xApplyCommand. + */ +void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2); +/* + * Called before already-read SNES joypad data is being used by the game + * if your port defines SNES_JOY_READ_CALLBACKS + */ #ifdef SNES_JOY_READ_CALLBACKS -void S9xOnSNESPadRead (void); +void S9xOnSNESPadRead(); #endif -// These are for your use. +/* These are for your use */ +s9xcommand_t S9xGetPortCommandT(const char *name); +char *S9xGetPortCommandName(s9xcommand_t command); +void S9xSetupDefaultKeymap(void); +bool8 S9xMapInput(const char *name, s9xcommand_t *cmd); -s9xcommand_t S9xGetPortCommandT (const char *name); -char * S9xGetPortCommandName (s9xcommand_t command); -void S9xSetupDefaultKeymap (void); -bool8 S9xMapInput (const char *name, s9xcommand_t *cmd); -////////// -// These functions are called from snes9x into this subsystem. No need to use them from a port. +/******* + * These functions are called from snes9x into this subsystem. No need to use + * them from a port. + */ -// Use when resetting snes9x. +/* Use when resetting snes9x */ +void S9xControlsReset(void); +void S9xControlsSoftReset(void); -void S9xControlsReset (void); -void S9xControlsSoftReset (void); +/* Use when writing to $4016 */ +void S9xSetJoypadLatch(bool latch); -// Use when writing to $4016. +/* Use when reading $4016/7 (JOYSER0 and JOYSER1) */ +uint8 S9xReadJOYSERn(int n); -void S9xSetJoypadLatch (bool latch); +/* End-Of-Frame processing. Sets gun latch variables and tries to draw + * crosshairs */ +void S9xControlEOF(void); -// Use when reading $4016/7 (JOYSER0 and JOYSER1). - -uint8 S9xReadJOYSERn (int n); - -// End-Of-Frame processing. Sets gun latch variables and tries to draw crosshairs - -void S9xControlEOF (void); - -// Functions and a structure for snapshot. - -struct SControlSnapshot -{ - uint8 ver; - uint8 port1_read_idx[2]; - uint8 dummy1[4]; // for future expansion - uint8 port2_read_idx[2]; - uint8 dummy2[4]; - uint8 mouse_speed[2]; - uint8 justifier_select; - uint8 dummy3[8]; - bool8 pad_read, pad_read_last; - uint8 internal[60]; // yes, we need to save this! +struct SControlSnapshot { + uint8 ver; + uint8 port1_read_idx[2]; + uint8 dummy1[4]; // for future expansion + uint8 port2_read_idx[2]; + uint8 dummy2[4]; + uint8 mouse_speed[2]; + uint8 justifier_select; + uint8 dummy3[8]; + bool8 pad_read, pad_read_last; + uint8 internal[60]; // yes, we need to save this! }; -void S9xControlPreSaveState (struct SControlSnapshot *s); -void S9xControlPostLoadState (struct SControlSnapshot *s); +void S9xControlPreSave(struct SControlSnapshot *s); +void S9xControlPostLoad(struct SControlSnapshot *s); #endif diff --git a/source/snes9x/copyright.h b/source/snes9x/copyright.h new file mode 100644 index 0000000..e90dd1a --- /dev/null +++ b/source/snes9x/copyright.h @@ -0,0 +1,233 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996, 1997, 1998, 1999 Gary Henderson (gary@daniver.demon.co.uk) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code (c) Copyright 1997, 1998 Ivar and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + diff --git a/source/snes9x/cpu.cpp b/source/snes9x/cpu.cpp index 0e03079..da2c234 100644 --- a/source/snes9x/cpu.cpp +++ b/source/snes9x/cpu.cpp @@ -159,165 +159,283 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" +#include "ppu.h" +#include "dsp1.h" +#include "cpuexec.h" +#include "s9xdebug.h" +#include "apu.h" #include "dma.h" -#include "apu/apu.h" -#include "fxemu.h" -#include "sdd1.h" -#include "srtc.h" -#include "snapshot.h" +#include "sa1.h" #include "cheats.h" +#include "srtc.h" +#include "sdd1.h" +#include "spc7110.h" +#include "obc1.h" +#include "bsx.h" +#include "snapshot.h" +#ifndef NGC #include "logger.h" -#ifdef DEBUGGER -#include "debug.h" #endif -static void S9xResetCPU (void); -static void S9xSoftResetCPU (void); +#ifndef ZSNES_FX +#include "fxemu.h" -static void S9xResetCPU (void) +extern struct FxInit_s SuperFX; + +void S9xResetSuperFX () { - S9xSoftResetCPU(); - Registers.SL = 0xff; - Registers.P.W = 0; - Registers.A.W = 0; - Registers.X.W = 0; - Registers.Y.W = 0; - SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); - ClearFlags(Decimal); + SuperFX.vFlags = 0; //FX_FLAG_ROM_BUFFER;// | FX_FLAG_ADDRESS_CHECKING; + // FIXME: Snes9x can't execute CPU and SuperFX at a time. Don't ask me what is 0.417 :P + SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max)))); + //printf("SFX:%d\n", SuperFX.speedPerLine); + SuperFX.oneLineDone = FALSE; + FxReset (&SuperFX); } +#endif -static void S9xSoftResetCPU (void) +void S9xSoftResetCPU () { - Registers.PBPC = 0; - Registers.PB = 0; - Registers.PCw = S9xGetWord(0xfffc); - OpenBus = Registers.PCh; - Registers.D.W = 0; - Registers.DB = 0; - Registers.SH = 1; - Registers.SL -= 3; - Registers.XH = 0; - Registers.YH = 0; + Registers.PBPC = 0; + Registers.PB = 0; + Registers.PCw = S9xGetWord (0xFFFC); + OpenBus = Registers.PCh; + Registers.D.W = 0; + Registers.DB = 0; + Registers.SH = 1; + Registers.SL -= 3; + Registers.XH = 0; + Registers.YH = 0; - ICPU.ShiftedPB = 0; - ICPU.ShiftedDB = 0; - SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); - ClearFlags(Decimal); + ICPU.ShiftedPB = 0; + ICPU.ShiftedDB = 0; + SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags (Decimal); - CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. - CPU.PrevCycles = -1; - CPU.V_Counter = 0; - CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); - CPU.PCBase = NULL; - CPU.IRQActive = FALSE; - CPU.IRQPending = 0; - CPU.MemSpeed = SLOW_ONE_CYCLE; - CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; - CPU.FastROMSpeed = SLOW_ONE_CYCLE; + CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + CPU.BranchSkip = FALSE; + CPU.NMIActive = FALSE; + CPU.IRQActive = FALSE; + CPU.WaitingForInterrupt = FALSE; CPU.InDMA = FALSE; CPU.InHDMA = FALSE; - CPU.InDMAorHDMA = FALSE; + CPU.InDMAorHDMA = FALSE; CPU.InWRAMDMAorHDMA = FALSE; CPU.HDMARanInDMA = 0; - CPU.CurrentDMAorHDMAChannel = -1; - CPU.WhichEvent = HC_RENDER_EVENT; - CPU.NextEvent = Timings.RenderPos; - CPU.WaitingForInterrupt = FALSE; - CPU.WaitAddress = 0xffffffff; - CPU.WaitCounter = 0; - CPU.PBPCAtOpcodeStart = 0xffffffff; - CPU.AutoSaveTimer = 0; - CPU.SRAMModified = FALSE; + CPU.PCBase = NULL; + CPU.PBPCAtOpcodeStart = 0xffffffff; + CPU.WaitAddress = 0xffffffff; + CPU.WaitCounter = 0; + CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. + CPU.PrevCycles = -1; + CPU.V_Counter = 0; + CPU.MemSpeed = SLOW_ONE_CYCLE; + CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + CPU.AutoSaveTimer = 0; + CPU.SRAMModified = FALSE; + CPU.BRKTriggered = FALSE; + CPU.IRQPending = 0; Timings.InterlaceField = FALSE; Timings.H_Max = Timings.H_Max_Master; Timings.V_Max = Timings.V_Max_Master; - Timings.NMITriggerPos = 0xffff; + Timings.NMITriggerPos = 0xffff; if (Model->_5A22 == 2) Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; else Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; - S9xSetPCBase(Registers.PBPC); + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; - ICPU.S9xOpcodes = S9xOpcodesE1; - ICPU.S9xOpLengths = S9xOpLengthsM1X1; - ICPU.CPUExecuting = TRUE; + S9xSetPCBase (Registers.PBPC); - S9xUnpackStatus(); + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + ICPU.CPUExecuting = TRUE; + + S9xUnpackStatus(); } +void S9xResetCPU () +{ + S9xSoftResetCPU (); + Registers.SL = 0xFF; + Registers.P.W = 0; + Registers.A.W = 0; + Registers.X.W = 0; + Registers.Y.W = 0; + SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags (Decimal); +} + +#ifdef ZSNES_FX +START_EXTERN_C +void S9xResetSuperFX (); +bool8 WinterGold = 0; +extern uint8 *C4Ram; +END_EXTERN_C +#endif + void S9xReset (void) { - S9xResetSaveTimer(FALSE); - S9xResetLogger(); +#ifndef NGC + ResetLogger(); + S9xResetSaveTimer (FALSE); +#endif - memset(Memory.RAM, 0x55, 0x20000); - memset(Memory.VRAM, 0x00, 0x10000); - ZeroMemory(Memory.FillRAM, 0x8000); + ZeroMemory (Memory.FillRAM, 0x8000); + memset (Memory.VRAM, 0x00, 0x10000); + memset (Memory.RAM, 0x55, 0x20000); if (Settings.BS) S9xResetBSX(); + if(Settings.SPC7110) + S9xSpc7110Reset(); + S9xResetCPU (); + S9xResetPPU (); + S9xResetSRTC (); + if (Settings.SDD1) + S9xResetSDD1 (); - S9xResetCPU(); - S9xResetPPU(); - S9xResetDMA(); - S9xResetAPU(); + S9xResetDMA (); + S9xResetAPU (); + S9xResetDSP1 (); + S9xSA1Init (); + if (Settings.C4) + S9xInitC4 (); + + S9xInitCheatData (); - if (Settings.DSP) - S9xResetDSP(); - if (Settings.SuperFX) - S9xResetSuperFX(); - if (Settings.SA1) - S9xSA1Init(); - if (Settings.SDD1) - S9xResetSDD1(); - if (Settings.SPC7110) - S9xResetSPC7110(); - if (Settings.C4) - S9xInitC4(); if (Settings.OBC1) - S9xResetOBC1(); - if (Settings.SRTC) - S9xResetSRTC(); - - S9xInitCheatData(); + ResetOBC1(); + if (Settings.SuperFX) + S9xResetSuperFX (); +#ifdef ZSNES_FX + WinterGold = Settings.WinterGold; +#endif +// Settings.Paused = FALSE; } void S9xSoftReset (void) { - S9xResetSaveTimer(FALSE); - - memset(Memory.VRAM, 0x00, 0x10000); - ZeroMemory(Memory.FillRAM, 0x8000); - +#ifndef NGC + S9xResetSaveTimer (FALSE); +#endif if (Settings.BS) S9xResetBSX(); + if (Settings.SuperFX) + S9xResetSuperFX (); +#ifdef ZSNES_FX + WinterGold = Settings.WinterGold; +#endif + ZeroMemory (Memory.FillRAM, 0x8000); + memset (Memory.VRAM, 0x00, 0x10000); + // memset (Memory.RAM, 0x55, 0x20000); - S9xSoftResetCPU(); - S9xSoftResetPPU(); - S9xResetDMA(); - S9xSoftResetAPU(); + if(Settings.SPC7110) + S9xSpc7110Reset(); + S9xSoftResetCPU (); + S9xSoftResetPPU (); + S9xResetSRTC (); + if (Settings.SDD1) + S9xResetSDD1 (); - if (Settings.DSP) - S9xResetDSP(); - if (Settings.SuperFX) - S9xResetSuperFX(); - if (Settings.SA1) - S9xSA1Init(); - if (Settings.SDD1) - S9xResetSDD1(); - if (Settings.SPC7110) - S9xResetSPC7110(); - if (Settings.C4) - S9xInitC4(); - if (Settings.OBC1) - S9xResetOBC1(); - if (Settings.SRTC) - S9xResetSRTC(); + S9xResetDMA (); + S9xResetAPU (); + S9xResetDSP1 (); + if(Settings.OBC1) + ResetOBC1(); + S9xSA1Init (); + if (Settings.C4) + S9xInitC4 (); - S9xInitCheatData(); + S9xInitCheatData (); + +// Settings.Paused = FALSE; } + +uint8 S9xOpLengthsM0X0[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 3, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM0X1[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM1X0[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM1X1[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; diff --git a/source/snes9x/cpuaddr.h b/source/snes9x/cpuaddr.h index df2446b..bc66a73 100644 --- a/source/snes9x/cpuaddr.h +++ b/source/snes9x/cpuaddr.h @@ -159,516 +159,395 @@ **********************************************************************************/ + + #ifndef _CPUADDR_H_ #define _CPUADDR_H_ -typedef enum -{ - NONE = 0, - READ = 1, - WRITE = 2, - MODIFY = 3, - JUMP = 5, - JSR = 8 -} AccessMode; +typedef enum { + NONE = 0, + READ = 1, + WRITE = 2, + MODIFY = 3, + JUMP = 5, + JSR = 8 +} AccessMode; -static inline uint8 Immediate8Slow (AccessMode a) -{ - uint8 val = S9xGetByte(Registers.PBPC); - if (a & READ) - OpenBus = val; - Registers.PCw++; - - return (val); +STATIC inline uint8 Immediate8 (AccessMode a) { + uint8 val = CPU.PCBase[Registers.PCw]; + if(a&READ) OpenBus = val; + AddCycles(CPU.MemSpeed); + Registers.PCw++; + return val; } -static inline uint8 Immediate8 (AccessMode a) -{ - uint8 val = CPU.PCBase[Registers.PCw]; - if (a & READ) - OpenBus = val; - AddCycles(CPU.MemSpeed); - Registers.PCw++; - - return (val); +STATIC inline uint8 Immediate8Slow (AccessMode a) { + uint8 val = S9xGetByte(Registers.PBPC); + if(a&READ) OpenBus = val; + Registers.PCw++; + return val; } -static inline uint16 Immediate16Slow (AccessMode a) -{ - uint16 val = S9xGetWord(Registers.PBPC, WRAP_BANK); - if (a & READ) - OpenBus = (uint8) (val >> 8); - Registers.PCw += 2; - - return (val); +STATIC inline uint16 Immediate16 (AccessMode a) { + uint16 val = READ_WORD(CPU.PCBase+Registers.PCw); + if(a&READ) OpenBus = (uint8)(val>>8); + AddCycles(CPU.MemSpeedx2); + Registers.PCw+=2; + return val; } -static inline uint16 Immediate16 (AccessMode a) -{ - uint16 val = READ_WORD(CPU.PCBase + Registers.PCw); - if (a & READ) - OpenBus = (uint8) (val >> 8); - AddCycles(CPU.MemSpeedx2); - Registers.PCw += 2; - - return (val); +STATIC inline uint16 Immediate16Slow (AccessMode a) { + uint16 val = S9xGetWord(Registers.PBPC, WRAP_BANK); + if(a&READ) OpenBus = (uint8)(val>>8); + Registers.PCw+=2; + return val; } -static inline uint32 RelativeSlow (AccessMode a) // branch $xx -{ - int8 offset = Immediate8Slow(a); - return ((int16) Registers.PCw + offset) & 0xffff; +STATIC inline uint32 RelativeSlow (AccessMode a) { // branch $xx + int8 offset = Immediate8Slow(a); + return ((int16)Registers.PCw + offset) & 0xffff; } -static inline uint32 Relative (AccessMode a) // branch $xx -{ - int8 offset = Immediate8(a); - - return ((int16) Registers.PCw + offset) & 0xffff; +STATIC inline uint32 Relative (AccessMode a) { // branch $xx + int8 offset = Immediate8(a); + return ((int16)Registers.PCw + offset) & 0xffff; } -static inline uint32 RelativeLongSlow (AccessMode a) // BRL $xxxx -{ - int16 offset = Immediate16Slow(a); - - return ((int32) Registers.PCw + offset) & 0xffff; +STATIC inline uint32 RelativeLongSlow (AccessMode a) { // BRL $xxxx + int16 offset = Immediate16Slow(a); + return ((int32)Registers.PCw + offset) & 0xffff; } -static inline uint32 RelativeLong (AccessMode a) // BRL $xxxx -{ - int16 offset = Immediate16(a); - - return ((int32) Registers.PCw + offset) & 0xffff; +STATIC inline uint32 RelativeLong (AccessMode a) { // BRL $xxxx + int16 offset = Immediate16(a); + return ((int32)Registers.PCw + offset) & 0xffff; } -static inline uint32 AbsoluteIndexedIndirectSlow (AccessMode a) // (a,X) -{ - uint16 addr; +STATIC inline uint32 AbsoluteIndexedIndirectSlow (AccessMode a) { // (a,X) + uint16 addr; + if(a&JSR){ + // JSR (a,X) pushes the old address in the middle of loading the new. + // OpenBus needs to be set to account for this. + addr = Immediate8Slow(READ); + if(a==JSR) OpenBus = Registers.PCl; + addr |= Immediate8Slow(READ)<<8; + } else { + addr = Immediate16Slow(READ); + } + AddCycles(ONE_CYCLE); + addr+=Registers.X.W; - if (a & JSR) - { - // JSR (a,X) pushes the old address in the middle of loading the new. - // OpenBus needs to be set to account for this. - addr = Immediate8Slow(READ); - if (a == JSR) - OpenBus = Registers.PCl; - addr |= Immediate8Slow(READ) << 8; - } - else - addr = Immediate16Slow(READ); - - AddCycles(ONE_CYCLE); - addr += Registers.X.W; - - // Address load wraps within the bank - uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); - OpenBus = addr2 >> 8; - - return (addr2); + // Address load wraps within the bank + uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); + OpenBus = addr2>>8; + return addr2; } -static inline uint32 AbsoluteIndexedIndirect (AccessMode a) // (a,X) -{ - uint16 addr = Immediate16Slow(READ); - addr += Registers.X.W; +STATIC inline uint32 AbsoluteIndexedIndirect (AccessMode a) { // (a,X) + uint16 addr = Immediate16Slow(READ); + addr+=Registers.X.W; - // Address load wraps within the bank - uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); - OpenBus = addr2 >> 8; - - return (addr2); + // Address load wraps within the bank + uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); + OpenBus = addr2>>8; + return addr2; } -static inline uint32 AbsoluteIndirectLongSlow (AccessMode a) // [a] -{ - uint16 addr = Immediate16Slow(READ); +STATIC inline uint32 AbsoluteIndirectLongSlow (AccessMode a) { // [a] + uint16 addr = Immediate16Slow(READ); - // No info on wrapping, but it doesn't matter anyway due to mirroring - uint32 addr2 = S9xGetWord(addr); - OpenBus = addr2 >> 8; - addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; - - return (addr2); + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint32 addr2 = S9xGetWord(addr); + OpenBus=addr2>>8; + addr2 |= (OpenBus = S9xGetByte(addr+2))<<16; + return addr2; } -static inline uint32 AbsoluteIndirectLong (AccessMode a) // [a] -{ - uint16 addr = Immediate16(READ); +STATIC inline uint32 AbsoluteIndirectLong (AccessMode a) { // [a] + uint16 addr = Immediate16(READ); - // No info on wrapping, but it doesn't matter anyway due to mirroring - uint32 addr2 = S9xGetWord(addr); - OpenBus = addr2 >> 8; - addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; - - return (addr2); + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint32 addr2 = S9xGetWord(addr); + OpenBus=addr2>>8; + addr2 |= (OpenBus = S9xGetByte(addr+2))<<16; + return addr2; } -static inline uint32 AbsoluteIndirectSlow (AccessMode a) // (a) -{ - // No info on wrapping, but it doesn't matter anyway due to mirroring - uint16 addr2 = S9xGetWord(Immediate16Slow(READ)); - OpenBus = addr2 >> 8; - - return (addr2); +STATIC inline uint32 AbsoluteIndirectSlow (AccessMode a) { // (a) + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint16 addr2 = S9xGetWord(Immediate16Slow(READ)); + OpenBus=addr2>>8; + return addr2; } -static inline uint32 AbsoluteIndirect (AccessMode a) // (a) -{ - // No info on wrapping, but it doesn't matter anyway due to mirroring - uint16 addr2 = S9xGetWord(Immediate16(READ)); - OpenBus = addr2 >> 8; - - return (addr2); +STATIC inline uint32 AbsoluteIndirect (AccessMode a) { // (a) + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint16 addr2 = S9xGetWord(Immediate16(READ)); + OpenBus=addr2>>8; + return addr2; } -static inline uint32 AbsoluteSlow (AccessMode a) // a -{ - return (ICPU.ShiftedDB | Immediate16Slow(a)); +STATIC inline uint32 AbsoluteSlow (AccessMode a) { // a + return ICPU.ShiftedDB|Immediate16Slow(a); } -static inline uint32 Absolute (AccessMode a) // a -{ - return (ICPU.ShiftedDB | Immediate16(a)); +STATIC inline uint32 Absolute (AccessMode a) { // a + return ICPU.ShiftedDB|Immediate16(a); } -static inline uint32 AbsoluteLongSlow (AccessMode a) // l -{ - uint32 addr = Immediate16Slow(READ); +STATIC inline uint32 AbsoluteLongSlow (AccessMode a) { // l + uint32 addr = Immediate16Slow(READ); - // JSR l pushes the old bank in the middle of loading the new. - // OpenBus needs to be set to account for this. - if (a == JSR) - OpenBus = Registers.PB; + // JSR l pushes the old bank in the middle of loading the new. + // OpenBus needs to be set to account for this. + if(a==JSR) OpenBus = Registers.PB; - addr |= Immediate8Slow(a) << 16; - - return (addr); + addr |= Immediate8Slow(a)<<16; + return addr; } -static inline uint32 AbsoluteLong (AccessMode a) // l -{ - uint32 addr = READ_3WORD(CPU.PCBase + Registers.PCw); - AddCycles(CPU.MemSpeedx2 + CPU.MemSpeed); - if (a & READ) - OpenBus = addr >> 16; - Registers.PCw += 3; - - return (addr); +STATIC inline uint32 AbsoluteLong (AccessMode a) { // l + uint32 addr = READ_3WORD(CPU.PCBase+Registers.PCw); + AddCycles(CPU.MemSpeedx2+CPU.MemSpeed); + if(a&READ) OpenBus = addr>>16; + Registers.PCw+=3; + return addr; } -static inline uint32 DirectSlow (AccessMode a) // d -{ - uint16 addr = Immediate8Slow(a) + Registers.D.W; - if (Registers.DL != 0) - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 DirectSlow (AccessMode a) { // d + uint16 addr = Immediate8Slow(a) + Registers.D.W; + if(Registers.DL!=0) AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 Direct (AccessMode a) // d -{ - uint16 addr = Immediate8(a) + Registers.D.W; - if (Registers.DL != 0) - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 Direct (AccessMode a) { // d + uint16 addr = Immediate8(a) + Registers.D.W; + if(Registers.DL!=0) AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 DirectIndirectSlow (AccessMode a) // (d) -{ - uint32 addr = S9xGetWord(DirectSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - addr |= ICPU.ShiftedDB; - - return (addr); +STATIC inline uint32 DirectIndirectSlow (AccessMode a) { // (d) + uint32 addr = S9xGetWord(DirectSlow(READ), + (!CheckEmulation() || Registers.DL)?WRAP_BANK:WRAP_PAGE); + if(a&READ) OpenBus=(uint8)(addr>>8); + addr |= ICPU.ShiftedDB; + return addr; } -static inline uint32 DirectIndirectE0 (AccessMode a) // (d) -{ - uint32 addr = S9xGetWord(Direct(READ)); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - addr |= ICPU.ShiftedDB; - - return (addr); +STATIC inline uint32 DirectIndirectE0 (AccessMode a) { // (d) + uint32 addr = S9xGetWord(Direct(READ)); + if(a&READ) OpenBus = (uint8)(addr>>8); + addr |= ICPU.ShiftedDB; + return addr; } -static inline uint32 DirectIndirectE1 (AccessMode a) // (d) -{ - uint32 addr = S9xGetWord(DirectSlow(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - addr |= ICPU.ShiftedDB; - - return (addr); +STATIC inline uint32 DirectIndirectE1 (AccessMode a) { // (d) + uint32 addr = S9xGetWord(DirectSlow(READ), + Registers.DL?WRAP_BANK:WRAP_PAGE); + if(a&READ) OpenBus=(uint8)(addr>>8); + addr |= ICPU.ShiftedDB; + return addr; } -static inline uint32 DirectIndirectIndexedSlow (AccessMode a) // (d),Y -{ - uint32 addr = DirectIndirectSlow(a); - if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 DirectIndirectIndexedSlow (AccessMode a) { // (d),Y + uint32 addr = DirectIndirectSlow(a); + if(a&WRITE || !CheckIndex() || (addr&0xff)+Registers.YL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 DirectIndirectIndexedE0X0 (AccessMode a) // (d),Y -{ - uint32 addr = DirectIndirectE0(a); - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 DirectIndirectIndexedE0X0 (AccessMode a) { // (d),Y + uint32 addr = DirectIndirectE0(a); + AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 DirectIndirectIndexedE0X1 (AccessMode a) // (d),Y -{ - uint32 addr = DirectIndirectE0(a); - if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 DirectIndirectIndexedE0X1 (AccessMode a) { // (d),Y + uint32 addr = DirectIndirectE0(a); + if(a&WRITE || (addr&0xff)+Registers.YL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 DirectIndirectIndexedE1 (AccessMode a) // (d),Y -{ - uint32 addr = DirectIndirectE1(a); - if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 DirectIndirectIndexedE1 (AccessMode a) { // (d),Y + uint32 addr = DirectIndirectE1(a); + if(a&WRITE || (addr&0xff)+Registers.YL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 DirectIndirectLongSlow (AccessMode a) // [d] -{ - uint16 addr = DirectSlow(READ); - uint32 addr2 = S9xGetWord(addr); - OpenBus = addr2 >> 8; - addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; - - return (addr2); +STATIC inline uint32 DirectIndirectLongSlow (AccessMode a) { // [d] + uint16 addr = DirectSlow(READ); + uint32 addr2 = S9xGetWord(addr); + OpenBus=addr2>>8; + addr2 |= (OpenBus = S9xGetByte(addr+2))<<16; + return addr2; } -static inline uint32 DirectIndirectLong (AccessMode a) // [d] -{ - uint16 addr = Direct(READ); - uint32 addr2 = S9xGetWord(addr); - OpenBus = addr2 >> 8; - addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; - - return (addr2); +STATIC inline uint32 DirectIndirectLong (AccessMode a) { // [d] + uint16 addr = Direct(READ); + uint32 addr2 = S9xGetWord(addr); + OpenBus=addr2>>8; + addr2 |= (OpenBus = S9xGetByte(addr+2))<<16; + return addr2; } -static inline uint32 DirectIndirectIndexedLongSlow (AccessMode a) // [d],Y -{ - return (DirectIndirectLongSlow(a) + Registers.Y.W); +STATIC inline uint32 DirectIndirectIndexedLongSlow (AccessMode a) { // [d],Y + return DirectIndirectLongSlow(a) + Registers.Y.W; } -static inline uint32 DirectIndirectIndexedLong (AccessMode a) // [d],Y -{ - return (DirectIndirectLong(a) + Registers.Y.W); +STATIC inline uint32 DirectIndirectIndexedLong (AccessMode a) { // [d],Y + return DirectIndirectLong(a) + Registers.Y.W; } -static inline uint32 DirectIndexedXSlow (AccessMode a) // d,X -{ - pair addr; - addr.W = DirectSlow(a); - if (!CheckEmulation() || Registers.DL) - addr.W += Registers.X.W; - else - addr.B.l += Registers.XL; - - AddCycles(ONE_CYCLE); - - return (addr.W); +STATIC inline uint32 DirectIndexedXSlow (AccessMode a) { // d,X + pair addr; + addr.W = DirectSlow(a); + if(!CheckEmulation() || Registers.DL){ + addr.W+=Registers.X.W; + } else { + addr.B.l+=Registers.XL; + } + AddCycles(ONE_CYCLE); + return addr.W; } -static inline uint32 DirectIndexedXE0 (AccessMode a) // d,X -{ - uint16 addr = Direct(a) + Registers.X.W; - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 DirectIndexedXE0 (AccessMode a) { // d,X + uint16 addr = Direct(a) + Registers.X.W; + AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 DirectIndexedXE1 (AccessMode a) // d,X -{ - if (Registers.DL) - return (DirectIndexedXE0(a)); - else - { - pair addr; - addr.W = Direct(a); - addr.B.l += Registers.XL; - AddCycles(ONE_CYCLE); - - return (addr.W); - } +STATIC inline uint32 DirectIndexedXE1 (AccessMode a) { // d,X + if(Registers.DL){ + return DirectIndexedXE0(a); + } else { + pair addr; + addr.W = Direct(a); + addr.B.l+=Registers.XL; + AddCycles(ONE_CYCLE); + return addr.W; + } } -static inline uint32 DirectIndexedYSlow (AccessMode a) // d,Y -{ - pair addr; - addr.W = DirectSlow(a); - if (!CheckEmulation() || Registers.DL) - addr.W += Registers.Y.W; - else - addr.B.l += Registers.YL; - - AddCycles(ONE_CYCLE); - - return (addr.W); +STATIC inline uint32 DirectIndexedYSlow (AccessMode a) { // d,Y + pair addr; + addr.W = DirectSlow(a); + if(!CheckEmulation() || Registers.DL){ + addr.W+=Registers.Y.W; + } else { + addr.B.l+=Registers.YL; + } + AddCycles(ONE_CYCLE); + return addr.W; } -static inline uint32 DirectIndexedYE0 (AccessMode a) // d,Y -{ - uint16 addr = Direct(a) + Registers.Y.W; - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 DirectIndexedYE0 (AccessMode a) { // d,Y + uint16 addr = Direct(a) + Registers.Y.W; + AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 DirectIndexedYE1 (AccessMode a) // d,Y -{ - if (Registers.DL) - return (DirectIndexedYE0(a)); - else - { - pair addr; - addr.W = Direct(a); - addr.B.l += Registers.YL; - AddCycles(ONE_CYCLE); - - return (addr.W); - } +STATIC inline uint32 DirectIndexedYE1 (AccessMode a) { // d,Y + if(Registers.DL){ + return DirectIndexedYE0(a); + } else { + pair addr; + addr.W = Direct(a); + addr.B.l+=Registers.YL; + AddCycles(ONE_CYCLE); + return addr.W; + } } -static inline uint32 DirectIndexedIndirectSlow (AccessMode a) // (d,X) -{ - uint32 addr = S9xGetWord(DirectIndexedXSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - - return (ICPU.ShiftedDB | addr); +STATIC inline uint32 DirectIndexedIndirectSlow (AccessMode a) { // (d,X) + uint32 addr = S9xGetWord(DirectIndexedXSlow(READ), + (!CheckEmulation() || Registers.DL)?WRAP_BANK:WRAP_PAGE); + if(a&READ) OpenBus=(uint8)(addr>>8); + return ICPU.ShiftedDB|addr; } -static inline uint32 DirectIndexedIndirectE0 (AccessMode a) // (d,X) -{ - uint32 addr = S9xGetWord(DirectIndexedXE0(READ)); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - - return (ICPU.ShiftedDB | addr); +STATIC inline uint32 DirectIndexedIndirectE0 (AccessMode a) { // (d,X) + uint32 addr = S9xGetWord(DirectIndexedXE0(READ)); + if(a&READ) OpenBus = (uint8)(addr>>8); + return ICPU.ShiftedDB|addr; } -static inline uint32 DirectIndexedIndirectE1 (AccessMode a) // (d,X) -{ - uint32 addr = S9xGetWord(DirectIndexedXE1(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - - return (ICPU.ShiftedDB | addr); +STATIC inline uint32 DirectIndexedIndirectE1 (AccessMode a) { // (d,X) + uint32 addr = S9xGetWord(DirectIndexedXE1(READ), + Registers.DL?WRAP_BANK:WRAP_PAGE); + if(a&READ) OpenBus=(uint8)(addr>>8); + return ICPU.ShiftedDB|addr; } -static inline uint32 AbsoluteIndexedXSlow (AccessMode a) // a,X -{ - uint32 addr = AbsoluteSlow(a); - if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.XL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.X.W); +STATIC inline uint32 AbsoluteIndexedXSlow (AccessMode a) { // a,X + uint32 addr = AbsoluteSlow(a); + if(a&WRITE || !CheckIndex() || (addr&0xff)+Registers.XL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.X.W); } -static inline uint32 AbsoluteIndexedXX0 (AccessMode a) // a,X -{ - uint32 addr = Absolute(a); - AddCycles(ONE_CYCLE); - - return (addr + Registers.X.W); +STATIC inline uint32 AbsoluteIndexedXX0 (AccessMode a) { // a,X + uint32 addr = Absolute(a); + AddCycles(ONE_CYCLE); + return (addr + Registers.X.W); } -static inline uint32 AbsoluteIndexedXX1 (AccessMode a) // a,X -{ - uint32 addr = Absolute(a); - if (a & WRITE || (addr & 0xff) + Registers.XL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.X.W); +STATIC inline uint32 AbsoluteIndexedXX1 (AccessMode a) { // a,X + uint32 addr = Absolute(a); + if(a&WRITE || (addr&0xff)+Registers.XL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.X.W); } -static inline uint32 AbsoluteIndexedYSlow (AccessMode a) // a,Y -{ - uint32 addr = AbsoluteSlow(a); - if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 AbsoluteIndexedYSlow (AccessMode a) { // a,Y + uint32 addr = AbsoluteSlow(a); + if(a&WRITE || !CheckIndex() || (addr&0xff)+Registers.YL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 AbsoluteIndexedYX0 (AccessMode a) // a,Y -{ - uint32 addr = Absolute(a); - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 AbsoluteIndexedYX0 (AccessMode a) { // a,Y + uint32 addr = Absolute(a); + AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 AbsoluteIndexedYX1 (AccessMode a) // a,Y -{ - uint32 addr = Absolute(a); - if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) - AddCycles(ONE_CYCLE); - - return (addr + Registers.Y.W); +STATIC inline uint32 AbsoluteIndexedYX1 (AccessMode a) { // a,Y + uint32 addr = Absolute(a); + if(a&WRITE || (addr&0xff)+Registers.YL>=0x100) AddCycles(ONE_CYCLE); + return (addr + Registers.Y.W); } -static inline uint32 AbsoluteLongIndexedXSlow (AccessMode a) // l,X -{ - return (AbsoluteLongSlow(a) + Registers.X.W); +STATIC inline uint32 AbsoluteLongIndexedXSlow (AccessMode a) { // l,X + return (AbsoluteLongSlow(a) + Registers.X.W); } -static inline uint32 AbsoluteLongIndexedX (AccessMode a) // l,X -{ - return (AbsoluteLong(a) + Registers.X.W); +STATIC inline uint32 AbsoluteLongIndexedX (AccessMode a) { // l,X + return (AbsoluteLong(a) + Registers.X.W); } -static inline uint32 StackRelativeSlow (AccessMode a) // d,S -{ - uint16 addr = Immediate8Slow(a) + Registers.S.W; - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 StackRelativeSlow (AccessMode a) { // d,S + uint16 addr = Immediate8Slow(a) + Registers.S.W; + AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 StackRelative (AccessMode a) // d,S -{ - uint16 addr = Immediate8(a) + Registers.S.W; - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 StackRelative (AccessMode a) { // d,S + uint16 addr = Immediate8(a) + Registers.S.W; + AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 StackRelativeIndirectIndexedSlow (AccessMode a) // (d,S),Y -{ - uint32 addr = S9xGetWord(StackRelativeSlow(READ)); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff; - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 StackRelativeIndirectIndexedSlow (AccessMode a) { // (d,S),Y + uint32 addr=S9xGetWord(StackRelativeSlow(READ)); + if(a&READ) OpenBus = (uint8)(addr>>8); + addr = (addr+Registers.Y.W+ICPU.ShiftedDB)&0xffffff; + AddCycles(ONE_CYCLE); + return addr; } -static inline uint32 StackRelativeIndirectIndexed (AccessMode a) // (d,S),Y -{ - uint32 addr = S9xGetWord(StackRelative(READ)); - if (a & READ) - OpenBus = (uint8) (addr >> 8); - addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff; - AddCycles(ONE_CYCLE); - - return (addr); +STATIC inline uint32 StackRelativeIndirectIndexed (AccessMode a) { // (d,S),Y + uint32 addr=S9xGetWord(StackRelative(READ)); + if(a&READ) OpenBus = (uint8)(addr>>8); + addr = (addr+Registers.Y.W+ICPU.ShiftedDB)&0xffffff; + AddCycles(ONE_CYCLE); + return addr; } - #endif + diff --git a/source/snes9x/cpuexec.cpp b/source/snes9x/cpuexec.cpp index 649df5d..6c17356 100644 --- a/source/snes9x/cpuexec.cpp +++ b/source/snes9x/cpuexec.cpp @@ -159,21 +159,38 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "cpuops.h" -#include "dma.h" -#include "apu/apu.h" -#include "fxemu.h" +#include "ppu.h" +#include "cpuexec.h" +#include "s9xdebug.h" #include "snapshot.h" -#ifdef DEBUGGER -#include "debug.h" +#include "gfx.h" #include "missing.h" -#endif +#include "apu.h" +#include "dma.h" +#include "sa1.h" +#include "spc7110.h" +#ifndef ZSNES_FX +#include "fxemu.h" +extern struct FxInit_s SuperFX; +#endif void S9xMainLoop (void) { + if(ICPU.SavedAtOp) + { + ICPU.SavedAtOp = FALSE; + Registers.PCw = CPU.PBPCAtOpcodeStart; + if(CPU.PCBase) + CPU.Cycles -= CPU.MemSpeed; + goto doOp; + } + for (;;) { if (CPU.Flags) @@ -194,7 +211,7 @@ void S9xMainLoop (void) } } - #ifdef DEBUGGER +#ifdef DEBUGGER if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) { for (int Break = 0; Break != 6; Break++) @@ -210,7 +227,7 @@ void S9xMainLoop (void) } } } - #endif +#endif CHECK_SOUND(); @@ -218,7 +235,7 @@ void S9xMainLoop (void) { if (CPU.IRQPending) // FIXME: In case of IRQ during WRAM refresh - CPU.IRQPending--; + CPU.IRQPending = 0; else { if (CPU.WaitingForInterrupt) @@ -241,7 +258,7 @@ void S9xMainLoop (void) if (CPU.Flags & SCAN_KEYS_FLAG) break; - #ifdef DEBUGGER +#ifdef DEBUGGER if (CPU.Flags & DEBUG_MODE_FLAG) break; @@ -253,13 +270,13 @@ void S9xMainLoop (void) CPU.Flags &= ~SINGLE_STEP_FLAG; CPU.Flags |= DEBUG_MODE_FLAG; } - #endif +#endif } - #ifdef CPU_SHUTDOWN +#ifdef CPU_SHUTDOWN CPU.PBPCAtOpcodeStart = Registers.PBPC; - #endif - +#endif + doOp: register uint8 Op; register struct SOpcodes *Opcodes; @@ -278,41 +295,50 @@ void S9xMainLoop (void) Opcodes = S9xOpcodesSlow; } - if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + if ((Registers.PCw&MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) { uint8 *oldPCBase = CPU.PCBase; - CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); - if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) + CPU.PCBase = GetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); + if (oldPCBase!=CPU.PCBase || (Registers.PCw&~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) Opcodes = S9xOpcodesSlow; } Registers.PCw++; (*Opcodes[Op].S9xOpcode)(); + if(ICPU.SavedAtOp) + { + ICPU.SavedAtOp = false; + continue; + } + + S9xAPUExecute(); + if (SA1.Executing) S9xSA1MainLoop(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); - } + } - S9xPackStatus(); + S9xPackStatus(); + APURegisters.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus(); - if (CPU.Flags & SCAN_KEYS_FLAG) - { - #ifdef DEBUGGER + if (CPU.Flags & SCAN_KEYS_FLAG) + { +#ifdef DEBUGGER if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) - #endif +#endif S9xSyncSpeed(); CPU.Flags &= ~SCAN_KEYS_FLAG; - } + } } void S9xSetIRQ (uint32 source) { CPU.IRQActive |= source; - CPU.IRQPending = Timings.IRQPendCount; CPU.Flags |= IRQ_FLAG; if (CPU.WaitingForInterrupt) @@ -322,35 +348,22 @@ void S9xSetIRQ (uint32 source) CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } - -#ifdef DEBUGGER - S9xTraceMessage("--- /IRQ low"); -#endif } void S9xClearIRQ (uint32 source) { - CPU.IRQActive &= ~source; - if (!CPU.IRQActive) - CPU.Flags &= ~IRQ_FLAG; - -#ifdef DEBUGGER - S9xTraceMessage("--- /IRQ high"); -#endif + CLEAR_IRQ_SOURCE(source); } void S9xDoHEventProcessing (void) { #ifdef DEBUGGER - if (Settings.TraceHCEvent) - S9xTraceFormattedMessage("--- HC event processing (%02d) expected HC:%04d executed HC:%04d", - CPU.WhichEvent, CPU.NextEvent, CPU.Cycles); + char mes[256]; #endif #ifdef CPU_SHUTDOWN CPU.WaitCounter++; #endif - switch (CPU.WhichEvent) { case HC_HBLANK_START_EVENT: @@ -362,7 +375,8 @@ void S9xDoHEventProcessing (void) if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) { #ifdef DEBUGGER - S9xTraceFormattedMessage("*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + sprintf(mes, "*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + S9xTraceMessage(mes); #endif PPU.HDMA = S9xDoHDMA(PPU.HDMA); } @@ -383,13 +397,20 @@ void S9xDoHEventProcessing (void) S9xSuperFXExec(); #endif - S9xAPUEndScanline(); + #ifndef STORM + if (Settings.SoundSync) + S9xGenerateSound(); + #endif + CPU.Cycles -= Timings.H_Max; - S9xAPUSetReferenceTime(CPU.Cycles); + APU.NextAPUTimerPos -= (Timings.H_Max << SNES_APU_ACCURACY); + APU.Cycles -= (Timings.H_Max << SNES_APU_ACCURACY); if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max)) Timings.NMITriggerPos -= Timings.H_Max; + ICPU.Scanline++; + CPU.V_Counter++; if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1 { @@ -466,7 +487,7 @@ void S9xDoHEventProcessing (void) if (PPU.OAMPriorityRotation) tmp = (PPU.OAMAddr & 0xFE) >> 1; - if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) + if ((PPU.OAMFlip & 1) || PPU.FirstSprite!=tmp) { PPU.FirstSprite = tmp; IPPU.OBJChanged = TRUE; @@ -510,7 +531,7 @@ void S9xDoHEventProcessing (void) case HC_RENDER_EVENT: if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight) - RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); + RenderLine((uint8)(CPU.V_Counter - FIRST_VISIBLE_LINE)); S9xCheckMissingHTimerPosition(Timings.RenderPos); @@ -518,10 +539,12 @@ void S9xDoHEventProcessing (void) case HC_WRAM_REFRESH_EVENT: #ifdef DEBUGGER - S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); + sprintf(mes, "*** WRAM Refresh HC:%04d", CPU.Cycles); + S9xTraceMessage(mes); #endif S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; + S9xAPUExecute(); S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); @@ -534,18 +557,13 @@ void S9xDoHEventProcessing (void) case HC_IRQ_9_A_EVENT: case HC_IRQ_A_1_EVENT: if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_IRQ_SOURCE); + S9xSetIRQ(PPU_H_BEAM_IRQ_SOURCE); else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_IRQ_SOURCE); + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); break; } S9xReschedule(); - -#ifdef DEBUGGER - if (Settings.TraceHCEvent) - S9xTraceFormattedMessage("--- HC event rescheduled (%02d) expected HC:%04d", CPU.WhichEvent, CPU.NextEvent); -#endif } diff --git a/source/snes9x/cpuexec.h b/source/snes9x/cpuexec.h index 542b73c..101c354 100644 --- a/source/snes9x/cpuexec.h +++ b/source/snes9x/cpuexec.h @@ -159,102 +159,126 @@ **********************************************************************************/ + + #ifndef _CPUEXEC_H_ #define _CPUEXEC_H_ -#include "ppu.h" +#include "snes9x.h" -struct SOpcodes -{ - void (*S9xOpcode) (void); +struct SOpcodes { +#ifdef __WIN32__ + void (__cdecl *S9xOpcode)( void); +#else + void (*S9xOpcode)( void); +#endif }; struct SICPU { - struct SOpcodes *S9xOpcodes; - uint8 *S9xOpLengths; - uint8 _Carry; - uint8 _Zero; - uint8 _Negative; - uint8 _Overflow; - bool8 CPUExecuting; - uint32 ShiftedPB; - uint32 ShiftedDB; - uint32 Frame; - uint32 FrameAdvanceCount; + uint8 *Speed; // unused + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + uint32 Frame; + uint32 Scanline; + uint32 FrameAdvanceCount; + bool8 SavedAtOp; }; -extern struct SICPU ICPU; +START_EXTERN_C +extern struct SICPU ICPU; +END_EXTERN_C -extern struct SOpcodes S9xOpcodesE1[256]; -extern struct SOpcodes S9xOpcodesM1X1[256]; -extern struct SOpcodes S9xOpcodesM1X0[256]; -extern struct SOpcodes S9xOpcodesM0X1[256]; -extern struct SOpcodes S9xOpcodesM0X0[256]; -extern struct SOpcodes S9xOpcodesSlow[256]; -extern uint8 S9xOpLengthsM1X1[256]; -extern uint8 S9xOpLengthsM1X0[256]; -extern uint8 S9xOpLengthsM0X1[256]; -extern uint8 S9xOpLengthsM0X0[256]; +#include "ppu.h" +#include "memmap.h" +#include "65c816.h" +START_EXTERN_C void S9xMainLoop (void); void S9xReset (void); void S9xSoftReset (void); -void S9xDoHEventProcessing (void); +void S9xDoHEventProcessing (); void S9xClearIRQ (uint32); void S9xSetIRQ (uint32); -static inline void S9xUnpackStatus (void) +extern struct SOpcodes S9xOpcodesE1 [256]; +extern struct SOpcodes S9xOpcodesM1X1 [256]; +extern struct SOpcodes S9xOpcodesM1X0 [256]; +extern struct SOpcodes S9xOpcodesM0X1 [256]; +extern struct SOpcodes S9xOpcodesM0X0 [256]; +extern struct SOpcodes S9xOpcodesSlow [256]; +extern uint8 S9xOpLengthsM1X1 [256]; +extern uint8 S9xOpLengthsM1X0 [256]; +extern uint8 S9xOpLengthsM0X1 [256]; +extern uint8 S9xOpLengthsM0X0 [256]; +END_EXTERN_C + +STATIC inline void S9xUnpackStatus() { - ICPU._Zero = (Registers.PL & Zero) == 0; - ICPU._Negative = (Registers.PL & Negative); - ICPU._Carry = (Registers.PL & Carry); - ICPU._Overflow = (Registers.PL & Overflow) >> 6; + ICPU._Zero = (Registers.PL & Zero) == 0; + ICPU._Negative = (Registers.PL & Negative); + ICPU._Carry = (Registers.PL & Carry); + ICPU._Overflow = (Registers.PL & Overflow) >> 6; } -static inline void S9xPackStatus (void) +STATIC inline void S9xPackStatus() { - Registers.PL &= ~(Zero | Negative | Carry | Overflow); - Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) | (ICPU._Negative & 0x80) | (ICPU._Overflow << 6); + Registers.PL &= ~(Zero | Negative | Carry | Overflow); + Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) | + (ICPU._Negative & 0x80) | (ICPU._Overflow << 6); } -static inline void S9xFixCycles (void) +STATIC inline void CLEAR_IRQ_SOURCE (uint32 M) { - if (CheckEmulation()) + CPU.IRQActive &= ~M; + if (!CPU.IRQActive) + CPU.Flags &= ~IRQ_FLAG; +} + +STATIC inline void S9xFixCycles () +{ + if (CheckEmulation ()) + { + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + if (CheckMemory ()) + { + if (CheckIndex ()) { - ICPU.S9xOpcodes = S9xOpcodesE1; - ICPU.S9xOpLengths = S9xOpLengthsM1X1; - } - else - if (CheckMemory()) - { - if (CheckIndex()) - { - ICPU.S9xOpcodes = S9xOpcodesM1X1; - ICPU.S9xOpLengths = S9xOpLengthsM1X1; - } - else - { - ICPU.S9xOpcodes = S9xOpcodesM1X0; - ICPU.S9xOpLengths = S9xOpLengthsM1X0; - } + ICPU.S9xOpcodes = S9xOpcodesM1X1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; } else { - if (CheckIndex()) - { - ICPU.S9xOpcodes = S9xOpcodesM0X1; - ICPU.S9xOpLengths = S9xOpLengthsM0X1; - } - else - { - ICPU.S9xOpcodes = S9xOpcodesM0X0; - ICPU.S9xOpLengths = S9xOpLengthsM0X0; - } + ICPU.S9xOpcodes = S9xOpcodesM1X0; + ICPU.S9xOpLengths = S9xOpLengthsM1X0; } + } + else + { + if (CheckIndex ()) + { + ICPU.S9xOpcodes = S9xOpcodesM0X1; + ICPU.S9xOpLengths = S9xOpLengthsM0X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM0X0; + ICPU.S9xOpLengths = S9xOpLengthsM0X0; + } + } } -static inline void S9xReschedule (void) +STATIC inline void S9xReschedule (void) { uint8 next = 0; int32 hpos = 0; diff --git a/source/snes9x/cpumacro.h b/source/snes9x/cpumacro.h index d8bcb72..f0cd870 100644 --- a/source/snes9x/cpumacro.h +++ b/source/snes9x/cpumacro.h @@ -159,730 +159,642 @@ **********************************************************************************/ + + #ifndef _CPUMACRO_H_ #define _CPUMACRO_H_ #define rOP8(OP, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ - FUNC(val); \ -} + static void Op##OP (void) { \ + uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ + FUNC(val); \ + } #define rOP16(OP, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - uint16 val = S9xGetWord(ADDR(READ), WRAP); \ - OpenBus = (uint8) (val >> 8); \ - FUNC(val); \ -} + static void Op##OP (void) { \ + uint16 val = S9xGetWord(ADDR(READ), WRAP); \ + OpenBus = (uint8)(val>>8); \ + FUNC(val); \ + } #define rOPC(OP, COND, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - if (Check##COND()) \ - { \ - uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ - FUNC(val); \ - } \ - else \ - { \ - uint16 val = S9xGetWord(ADDR(READ), WRAP); \ - OpenBus = (uint8) (val >> 8); \ - FUNC(val); \ - } \ -} + static void Op##OP (void) { \ + if(Check##COND()){ \ + uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ + FUNC(val); \ + } else { \ + uint16 val = S9xGetWord(ADDR(READ), WRAP); \ + OpenBus = (uint8)(val>>8); \ + FUNC(val); \ + } \ + } #define rOPM(OP, ADDR, WRAP, FUNC) \ -rOPC(OP, Memory, ADDR, WRAP, FUNC) + rOPC(OP, Memory, ADDR, WRAP, FUNC) #define rOPX(OP, ADDR, WRAP, FUNC) \ -rOPC(OP, Index, ADDR, WRAP, FUNC) + rOPC(OP, Index, ADDR, WRAP, FUNC) + #define wOP8(OP, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - FUNC##8(ADDR(WRITE)); \ -} + static void Op##OP (void) { \ + FUNC##8 (ADDR(WRITE)); \ + } #define wOP16(OP, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - FUNC##16(ADDR(WRITE), WRAP); \ -} + static void Op##OP (void) { \ + FUNC##16 (ADDR(WRITE), WRAP); \ + } #define wOPC(OP, COND, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - if (Check##COND()) \ - FUNC##8(ADDR(WRITE)); \ - else \ - FUNC##16(ADDR(WRITE), WRAP); \ -} + static void Op##OP (void) { \ + if(Check##COND()){ \ + FUNC##8 (ADDR(WRITE)); \ + } else { \ + FUNC##16 (ADDR(WRITE), WRAP); \ + } \ + } #define wOPM(OP, ADDR, WRAP, FUNC) \ -wOPC(OP, Memory, ADDR, WRAP, FUNC) + wOPC(OP, Memory, ADDR, WRAP, FUNC) #define wOPX(OP, ADDR, WRAP, FUNC) \ -wOPC(OP, Index, ADDR, WRAP, FUNC) + wOPC(OP, Index, ADDR, WRAP, FUNC) + #define mOP8(OP, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - FUNC##8(ADDR(MODIFY)); \ -} + static void Op##OP (void) { \ + FUNC##8 (ADDR(MODIFY)); \ + } #define mOP16(OP, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - FUNC##16(ADDR(MODIFY), WRAP); \ -} + static void Op##OP (void) { \ + FUNC##16 (ADDR(MODIFY), WRAP); \ + } #define mOPC(OP, COND, ADDR, WRAP, FUNC) \ -static void Op##OP (void) \ -{ \ - if (Check##COND()) \ - FUNC##8(ADDR(MODIFY)); \ - else \ - FUNC##16(ADDR(MODIFY), WRAP); \ -} + static void Op##OP (void) { \ + if(Check##COND()){ \ + FUNC##8 (ADDR(MODIFY)); \ + } else { \ + FUNC##16 (ADDR(MODIFY), WRAP); \ + } \ + } #define mOPM(OP, ADDR, WRAP, FUNC) \ -mOPC(OP, Memory, ADDR, WRAP, FUNC) + mOPC(OP, Memory, ADDR, WRAP, FUNC) + #define bOP(OP, REL, COND, CHK, E) \ -static void Op##OP (void) \ -{ \ - pair newPC; \ - newPC.W = REL(JUMP); \ - if (COND) \ - { \ - AddCycles(ONE_CYCLE); \ - if (E && Registers.PCh != newPC.B.h) \ - AddCycles(ONE_CYCLE); \ - if ((Registers.PCw & ~MEMMAP_MASK) != (newPC.W & ~MEMMAP_MASK)) \ - S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \ - else \ - Registers.PCw = newPC.W; \ - CPUShutdown(); \ - } \ + static void Op##OP (void) { \ + pair newPC; \ + newPC.W = REL(JUMP); \ + BranchCheck##CHK (); \ + if(COND){ \ + AddCycles(ONE_CYCLE); \ + if(E && Registers.PCh!=newPC.B.h){AddCycles(ONE_CYCLE);} \ + if((Registers.PCw&~MEMMAP_MASK)!=(newPC.W&~MEMMAP_MASK)){ \ + S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \ + } else { \ + Registers.PCw = newPC.W; \ + } \ + CPUShutdown (); \ + } \ + } + + +STATIC inline void SetZN (uint16 Work) { + ICPU._Zero = Work != 0; + ICPU._Negative = (uint8) (Work >> 8); } - -static inline void SetZN (uint16 Work16) -{ - ICPU._Zero = Work16 != 0; - ICPU._Negative = (uint8) (Work16 >> 8); +STATIC inline void SetZN (uint8 Work) { + ICPU._Zero = Work; + ICPU._Negative = Work; } -static inline void SetZN (uint8 Work8) -{ - ICPU._Zero = Work8; - ICPU._Negative = Work8; -} +STATIC inline void ADC (uint8 Work8) { + if(CheckDecimal()) { + uint8 A1 = Registers.A.W & 0x0F; + uint16 A2 = Registers.A.W & 0xF0; + uint8 W1 = Work8 & 0x0F; + uint8 W2 = Work8 & 0xF0; -static inline void ADC (uint16 Work16) -{ - if (CheckDecimal()) - { - uint16 A1 = Registers.A.W & 0x000F; - uint16 A2 = Registers.A.W & 0x00F0; - uint16 A3 = Registers.A.W & 0x0F00; - uint32 A4 = Registers.A.W & 0xF000; - uint16 W1 = Work16 & 0x000F; - uint16 W2 = Work16 & 0x00F0; - uint16 W3 = Work16 & 0x0F00; - uint16 W4 = Work16 & 0xF000; - - A1 += W1 + CheckCarry(); - if (A1 > 0x0009) - { - A1 -= 0x000A; - A1 &= 0x000F; - A2 += 0x0010; - } - - A2 += W2; - if (A2 > 0x0090) - { - A2 -= 0x00A0; - A2 &= 0x00F0; - A3 += 0x0100; - } - - A3 += W3; - if (A3 > 0x0900) - { - A3 -= 0x0A00; - A3 &= 0x0F00; - A4 += 0x1000; - } - - A4 += W4; - if (A4 > 0x9000) - { - A4 -= 0xA000; - A4 &= 0xF000; - SetCarry(); - } - else - ClearCarry(); - - uint16 Ans16 = A4 | A3 | A2 | A1; - - if (~(Registers.A.W ^ Work16) & (Work16 ^ Ans16) & 0x8000) - SetOverflow(); - else - ClearOverflow(); - - Registers.A.W = Ans16; - SetZN(Registers.A.W); + A1 += W1+CheckCarry(); + if(A1>0x09){ + A1-=0x0A; + A1&=0x0F; + A2+=0x10; } + + A2 += W2; + if(A2>0x90){ + A2-=0xA0; + A2&=0xF0; + SetCarry(); + } else { + ClearCarry(); + } + + uint8 Ans8 = A2|A1; + if (~(Registers.AL ^ Work8) & + (Work8 ^ Ans8) & 0x80) + SetOverflow(); else - { - uint32 Ans32 = Registers.A.W + Work16 + CheckCarry(); + ClearOverflow(); + Registers.AL = Ans8; + SetZN (Registers.AL); + } else { + uint16 Ans16 = Registers.AL + Work8 + CheckCarry(); - ICPU._Carry = Ans32 >= 0x10000; + ICPU._Carry = Ans16 >= 0x100; - if (~(Registers.A.W ^ Work16) & (Work16 ^ (uint16) Ans32) & 0x8000) - SetOverflow(); - else - ClearOverflow(); - - Registers.A.W = (uint16) Ans32; - SetZN(Registers.A.W); - } -} - -static inline void ADC (uint8 Work8) -{ - if (CheckDecimal()) - { - uint8 A1 = Registers.A.W & 0x0F; - uint16 A2 = Registers.A.W & 0xF0; - uint8 W1 = Work8 & 0x0F; - uint8 W2 = Work8 & 0xF0; - - A1 += W1 + CheckCarry(); - if (A1 > 0x09) - { - A1 -= 0x0A; - A1 &= 0x0F; - A2 += 0x10; - } - - A2 += W2; - if (A2 > 0x90) - { - A2 -= 0xA0; - A2 &= 0xF0; - SetCarry(); - } - else - ClearCarry(); - - uint8 Ans8 = A2 | A1; - - if (~(Registers.AL ^ Work8) & (Work8 ^ Ans8) & 0x80) - SetOverflow(); - else - ClearOverflow(); - - Registers.AL = Ans8; - SetZN(Registers.AL); - } + if (~(Registers.AL ^ Work8) & + (Work8 ^ (uint8) Ans16) & 0x80) + SetOverflow(); else - { - uint16 Ans16 = Registers.AL + Work8 + CheckCarry(); + ClearOverflow(); + Registers.AL = (uint8) Ans16; + SetZN (Registers.AL); + } +} - ICPU._Carry = Ans16 >= 0x100; +STATIC inline void ADC (uint16 Work16) { + if (CheckDecimal ()) { + uint16 A1 = Registers.A.W & 0x000F; + uint16 A2 = Registers.A.W & 0x00F0; + uint16 A3 = Registers.A.W & 0x0F00; + uint32 A4 = Registers.A.W & 0xF000; + uint16 W1 = Work16 & 0x000F; + uint16 W2 = Work16 & 0x00F0; + uint16 W3 = Work16 & 0x0F00; + uint16 W4 = Work16 & 0xF000; - if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8) Ans16) & 0x80) - SetOverflow(); - else - ClearOverflow(); - - Registers.AL = (uint8) Ans16; - SetZN(Registers.AL); + A1 += W1 + CheckCarry (); + if(A1>0x0009) { + A1 -= 0x000A; + A1 &= 0x000F; + A2 += 0x0010; } + + A2 += W2; + if(A2>0x0090){ + A2 -= 0x00A0; + A2 &= 0x00F0; + A3 += 0x0100; + } + + A3 += W3; + if(A3>0x0900){ + A3 -= 0x0A00; + A3 &= 0x0F00; + A4 += 0x1000; + } + + A4 += W4; + if(A4>0x9000){ + A4 -= 0xA000; + A4 &= 0xF000; + SetCarry (); + } else { + ClearCarry (); + } + + uint16 Ans16 = A4|A3|A2|A1; + if (~(Registers.A.W ^ Work16) & + (Work16 ^ Ans16) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + Registers.A.W = Ans16; + SetZN (Registers.A.W); + } else { + uint32 Ans32 = Registers.A.W + Work16 + CheckCarry(); + + ICPU._Carry = Ans32 >= 0x10000; + + if (~(Registers.A.W ^ Work16) & + (Work16 ^ (uint16) Ans32) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + Registers.A.W = (uint16) Ans32; + SetZN (Registers.A.W); + } } -static inline void AND (uint16 Work16) -{ - Registers.A.W &= Work16; - SetZN(Registers.A.W); +STATIC inline void AND (uint16 Work16) { + Registers.A.W &= Work16; + SetZN (Registers.A.W); } -static inline void AND (uint8 Work8) -{ - Registers.AL &= Work8; - SetZN(Registers.AL); +STATIC inline void AND (uint8 Work8) { + Registers.AL &= Work8; + SetZN (Registers.AL); } -static inline void ASL16 (uint32 OpAddress, s9xwrap_t w) -{ - uint16 Work16 = S9xGetWord(OpAddress, w); - ICPU._Carry = (Work16 & 0x8000) != 0; - Work16 <<= 1; - AddCycles(ONE_CYCLE); - S9xSetWord(Work16, OpAddress, w, WRITE_10); - OpenBus = Work16 & 0xff; - SetZN(Work16); +STATIC inline void ASL16 (uint32 OpAddress, s9xwrap_t w) { + uint16 Work16 = S9xGetWord (OpAddress, w); + ICPU._Carry = (Work16 & 0x8000) != 0; + Work16 <<= 1; + AddCycles(ONE_CYCLE); + S9xSetWord (Work16, OpAddress, w, WRITE_10); + OpenBus = (Work16&0xff); + SetZN (Work16); } -static inline void ASL8 (uint32 OpAddress) -{ - uint8 Work8 = S9xGetByte(OpAddress); - ICPU._Carry = (Work8 & 0x80) != 0; - Work8 <<= 1; - AddCycles(ONE_CYCLE); - S9xSetByte(Work8, OpAddress); - OpenBus = Work8; - SetZN(Work8); +STATIC inline void ASL8 (uint32 OpAddress) { + uint8 Work8 = S9xGetByte (OpAddress); + ICPU._Carry = (Work8 & 0x80) != 0; + Work8 <<= 1; + AddCycles(ONE_CYCLE); + S9xSetByte (Work8, OpAddress); + OpenBus = Work8; + SetZN (Work8); } -static inline void BIT (uint16 Work16) -{ - ICPU._Overflow = (Work16 & 0x4000) != 0; - ICPU._Negative = (uint8) (Work16 >> 8); - ICPU._Zero = (Work16 & Registers.A.W) != 0; +STATIC inline void BIT (uint16 Work16) { + ICPU._Overflow = (Work16 & 0x4000) != 0; + ICPU._Negative = (uint8) (Work16 >> 8); + ICPU._Zero = (Work16 & Registers.A.W) != 0; } -static inline void BIT (uint8 Work8) -{ - ICPU._Overflow = (Work8 & 0x40) != 0; - ICPU._Negative = Work8; - ICPU._Zero = Work8 & Registers.AL; +STATIC inline void BIT (uint8 Work8) { + ICPU._Overflow = (Work8 & 0x40) != 0; + ICPU._Negative = Work8; + ICPU._Zero = Work8 & Registers.AL; } -static inline void CMP (uint16 val) -{ - int32 Int32 = (int32) Registers.A.W - (int32) val; +STATIC inline void CMP (uint16 val) { + int32 Int32 = (int32) Registers.A.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); +} + +STATIC inline void CMP (uint8 val) { + int16 Int16 = (int16) Registers.AL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN ((uint8) Int16); +} + +STATIC inline void CPX (uint16 val) { + int32 Int32 = (int32) Registers.X.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); +} + +STATIC inline void CPX (uint8 val) { + int16 Int16 = (int16) Registers.XL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN ((uint8) Int16); +} + +STATIC inline void CPY (uint16 val) { + int32 Int32 = (int32) Registers.Y.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); +} + +STATIC inline void CPY (uint8 val) { + int16 Int16 = (int16) Registers.YL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN ((uint8) Int16); +} + +STATIC inline void DEC16 (uint32 OpAddress, s9xwrap_t w) { +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + uint16 Work16 = S9xGetWord(OpAddress, w) - 1; + AddCycles(ONE_CYCLE); + S9xSetWord (Work16, OpAddress, w, WRITE_10); + OpenBus = Work16&0xff; + SetZN (Work16); +} + +STATIC inline void DEC8 (uint32 OpAddress) { +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + uint8 Work8 = S9xGetByte (OpAddress) - 1; + AddCycles(ONE_CYCLE); + S9xSetByte (Work8, OpAddress); + OpenBus = Work8; + SetZN (Work8); +} + +STATIC inline void EOR (uint16 val) { + Registers.A.W ^= val; + SetZN (Registers.A.W); +} + +STATIC inline void EOR (uint8 val) { + Registers.AL ^= val; + SetZN (Registers.AL); +} + +STATIC inline void INC16 (uint32 OpAddress, s9xwrap_t w) { +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + uint16 Work16 = S9xGetWord(OpAddress, w) + 1; + AddCycles(ONE_CYCLE); + S9xSetWord (Work16, OpAddress, w, WRITE_10); + OpenBus = Work16&0xff; + SetZN (Work16); +} + +STATIC inline void INC8 (uint32 OpAddress) { +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + uint8 Work8 = S9xGetByte (OpAddress) + 1; + AddCycles(ONE_CYCLE); + S9xSetByte (Work8, OpAddress); + OpenBus = Work8; + SetZN (Work8); +} + +STATIC inline void LDA (uint16 val) { + Registers.A.W = val; + SetZN (Registers.A.W); +} + +STATIC inline void LDA (uint8 val) { + Registers.AL = val; + SetZN (Registers.AL); +} + +STATIC inline void LDX (uint16 val) { + Registers.X.W = val; + SetZN (Registers.X.W); +} + +STATIC inline void LDX (uint8 val) { + Registers.XL = val; + SetZN (Registers.XL); +} + +STATIC inline void LDY (uint16 val) { + Registers.Y.W = val; + SetZN (Registers.Y.W); +} + +STATIC inline void LDY (uint8 val) { + Registers.YL = val; + SetZN (Registers.YL); +} + +STATIC inline void LSR16 (uint32 OpAddress, s9xwrap_t w) { + uint16 Work16 = S9xGetWord (OpAddress, w); + ICPU._Carry = Work16 & 1; + Work16 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetWord (Work16, OpAddress, w, WRITE_10); + OpenBus = (Work16&0xff); + SetZN (Work16); +} + +STATIC inline void LSR8 (uint32 OpAddress) { + uint8 Work8 = S9xGetByte (OpAddress); + ICPU._Carry = Work8 & 1; + Work8 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetByte (Work8, OpAddress); + OpenBus = Work8; + SetZN (Work8); +} + +STATIC inline void ORA (uint16 val) { + Registers.A.W |= val; + SetZN (Registers.A.W); +} + +STATIC inline void ORA (uint8 val) { + Registers.AL |= val; + SetZN (Registers.AL); +} + +STATIC inline void ROL16 (uint32 OpAddress, s9xwrap_t w) { + uint32 Work32 = (((uint32)S9xGetWord(OpAddress, w))<<1) | CheckCarry(); + ICPU._Carry = Work32>=0x10000; + AddCycles(ONE_CYCLE); + S9xSetWord ((uint16)Work32, OpAddress, w, WRITE_10); + OpenBus = (Work32&0xff); + SetZN ((uint16)Work32); +} + +STATIC inline void ROL8 (uint32 OpAddress) { + uint16 Work16 = (((uint16)S9xGetByte(OpAddress))<<1) | CheckCarry(); + ICPU._Carry = Work16>=0x100; + AddCycles(ONE_CYCLE); + S9xSetByte ((uint8)Work16, OpAddress); + OpenBus = Work16&0xff; + SetZN ((uint8)Work16); +} + +STATIC inline void ROR16 (uint32 OpAddress, s9xwrap_t w) { + uint32 Work32 = ((uint32)S9xGetWord(OpAddress, w)) | (((uint32)CheckCarry())<<16); + ICPU._Carry = Work32&1; + Work32 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetWord ((uint16)Work32, OpAddress, w, WRITE_10); + OpenBus = (Work32&0xff); + SetZN ((uint16)Work32); +} + +STATIC inline void ROR8 (uint32 OpAddress) { + uint16 Work16 = ((uint16)S9xGetByte(OpAddress)) | (((uint16)CheckCarry())<<8); + ICPU._Carry = Work16&1; + Work16 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetByte ((uint8)Work16, OpAddress); + OpenBus = Work16&0xff; + SetZN ((uint8)Work16); +} + +STATIC inline void SBC (uint16 Work16) { + if (CheckDecimal ()) { + uint16 A1 = Registers.A.W & 0x000F; + uint16 A2 = Registers.A.W & 0x00F0; + uint16 A3 = Registers.A.W & 0x0F00; + uint32 A4 = Registers.A.W & 0xF000; + uint16 W1 = Work16 & 0x000F; + uint16 W2 = Work16 & 0x00F0; + uint16 W3 = Work16 & 0x0F00; + uint16 W4 = Work16 & 0xF000; + + A1 -= W1 + !CheckCarry (); + A2 -= W2; + A3 -= W3; + A4 -= W4; + if (A1 > 0x000F) { + A1 += 0x000A; + A1 &= 0x000F; + A2 -= 0x0010; + } + if (A2 > 0x00F0) { + A2 += 0x00A0; + A2 &= 0x00F0; + A3 -= 0x0100; + } + if (A3 > 0x0F00) { + A3 += 0x0A00; + A3 &= 0x0F00; + A4 -= 0x1000; + } + if (A4 > 0xF000) { + A4 += 0xA000; + A4 &= 0xF000; + ClearCarry (); + } else { + SetCarry (); + } + + uint16 Ans16 = A4|A3|A2|A1; + if ((Registers.A.W ^ Work16) & + (Registers.A.W ^ Ans16) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + Registers.A.W = Ans16; + SetZN (Registers.A.W); + } else { + int32 Int32 = (int32) Registers.A.W - (int32) Work16 + (int32) CheckCarry() - 1; + ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); -} -static inline void CMP (uint8 val) -{ - int16 Int16 = (int16) Registers.AL - (int16) val; - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); -} - -static inline void CPX (uint16 val) -{ - int32 Int32 = (int32) Registers.X.W - (int32) val; - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); -} - -static inline void CPX (uint8 val) -{ - int16 Int16 = (int16) Registers.XL - (int16) val; - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); -} - -static inline void CPY (uint16 val) -{ - int32 Int32 = (int32) Registers.Y.W - (int32) val; - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); -} - -static inline void CPY (uint8 val) -{ - int16 Int16 = (int16) Registers.YL - (int16) val; - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); -} - -static inline void DEC16 (uint32 OpAddress, s9xwrap_t w) -{ -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - uint16 Work16 = S9xGetWord(OpAddress, w) - 1; - AddCycles(ONE_CYCLE); - S9xSetWord(Work16, OpAddress, w, WRITE_10); - OpenBus = Work16 & 0xff; - SetZN(Work16); -} - -static inline void DEC8 (uint32 OpAddress) -{ -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - uint8 Work8 = S9xGetByte(OpAddress) - 1; - AddCycles(ONE_CYCLE); - S9xSetByte(Work8, OpAddress); - OpenBus = Work8; - SetZN(Work8); -} - -static inline void EOR (uint16 val) -{ - Registers.A.W ^= val; - SetZN(Registers.A.W); -} - -static inline void EOR (uint8 val) -{ - Registers.AL ^= val; - SetZN(Registers.AL); -} - -static inline void INC16 (uint32 OpAddress, s9xwrap_t w) -{ -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - uint16 Work16 = S9xGetWord(OpAddress, w) + 1; - AddCycles(ONE_CYCLE); - S9xSetWord(Work16, OpAddress, w, WRITE_10); - OpenBus = Work16 & 0xff; - SetZN(Work16); -} - -static inline void INC8 (uint32 OpAddress) -{ -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - uint8 Work8 = S9xGetByte(OpAddress) + 1; - AddCycles(ONE_CYCLE); - S9xSetByte(Work8, OpAddress); - OpenBus = Work8; - SetZN(Work8); -} - -static inline void LDA (uint16 val) -{ - Registers.A.W = val; - SetZN(Registers.A.W); -} - -static inline void LDA (uint8 val) -{ - Registers.AL = val; - SetZN(Registers.AL); -} - -static inline void LDX (uint16 val) -{ - Registers.X.W = val; - SetZN(Registers.X.W); -} - -static inline void LDX (uint8 val) -{ - Registers.XL = val; - SetZN(Registers.XL); -} - -static inline void LDY (uint16 val) -{ - Registers.Y.W = val; - SetZN(Registers.Y.W); -} - -static inline void LDY (uint8 val) -{ - Registers.YL = val; - SetZN(Registers.YL); -} - -static inline void LSR16 (uint32 OpAddress, s9xwrap_t w) -{ - uint16 Work16 = S9xGetWord(OpAddress, w); - ICPU._Carry = Work16 & 1; - Work16 >>= 1; - AddCycles(ONE_CYCLE); - S9xSetWord(Work16, OpAddress, w, WRITE_10); - OpenBus = Work16 & 0xff; - SetZN(Work16); -} - -static inline void LSR8 (uint32 OpAddress) -{ - uint8 Work8 = S9xGetByte(OpAddress); - ICPU._Carry = Work8 & 1; - Work8 >>= 1; - AddCycles(ONE_CYCLE); - S9xSetByte(Work8, OpAddress); - OpenBus = Work8; - SetZN(Work8); -} - -static inline void ORA (uint16 val) -{ - Registers.A.W |= val; - SetZN(Registers.A.W); -} - -static inline void ORA (uint8 val) -{ - Registers.AL |= val; - SetZN(Registers.AL); -} - -static inline void ROL16 (uint32 OpAddress, s9xwrap_t w) -{ - uint32 Work32 = (((uint32) S9xGetWord(OpAddress, w)) << 1) | CheckCarry(); - ICPU._Carry = Work32 >= 0x10000; - AddCycles(ONE_CYCLE); - S9xSetWord((uint16) Work32, OpAddress, w, WRITE_10); - OpenBus = Work32 & 0xff; - SetZN((uint16) Work32); -} - -static inline void ROL8 (uint32 OpAddress) -{ - uint16 Work16 = (((uint16) S9xGetByte(OpAddress)) << 1) | CheckCarry(); - ICPU._Carry = Work16 >= 0x100; - AddCycles(ONE_CYCLE); - S9xSetByte((uint8) Work16, OpAddress); - OpenBus = Work16 & 0xff; - SetZN((uint8) Work16); -} - -static inline void ROR16 (uint32 OpAddress, s9xwrap_t w) -{ - uint32 Work32 = ((uint32) S9xGetWord(OpAddress, w)) | (((uint32) CheckCarry()) << 16); - ICPU._Carry = Work32 & 1; - Work32 >>= 1; - AddCycles(ONE_CYCLE); - S9xSetWord((uint16) Work32, OpAddress, w, WRITE_10); - OpenBus = Work32 & 0xff; - SetZN((uint16) Work32); -} - -static inline void ROR8 (uint32 OpAddress) -{ - uint16 Work16 = ((uint16) S9xGetByte(OpAddress)) | (((uint16) CheckCarry()) << 8); - ICPU._Carry = Work16 & 1; - Work16 >>= 1; - AddCycles(ONE_CYCLE); - S9xSetByte((uint8) Work16, OpAddress); - OpenBus = Work16 & 0xff; - SetZN((uint8) Work16); -} - -static inline void SBC (uint16 Work16) -{ - if (CheckDecimal()) - { - uint16 A1 = Registers.A.W & 0x000F; - uint16 A2 = Registers.A.W & 0x00F0; - uint16 A3 = Registers.A.W & 0x0F00; - uint32 A4 = Registers.A.W & 0xF000; - uint16 W1 = Work16 & 0x000F; - uint16 W2 = Work16 & 0x00F0; - uint16 W3 = Work16 & 0x0F00; - uint16 W4 = Work16 & 0xF000; - - A1 -= W1 + !CheckCarry(); - A2 -= W2; - A3 -= W3; - A4 -= W4; - - if (A1 > 0x000F) - { - A1 += 0x000A; - A1 &= 0x000F; - A2 -= 0x0010; - } - - if (A2 > 0x00F0) - { - A2 += 0x00A0; - A2 &= 0x00F0; - A3 -= 0x0100; - } - - if (A3 > 0x0F00) - { - A3 += 0x0A00; - A3 &= 0x0F00; - A4 -= 0x1000; - } - - if (A4 > 0xF000) - { - A4 += 0xA000; - A4 &= 0xF000; - ClearCarry(); - } - else - SetCarry(); - - uint16 Ans16 = A4 | A3 | A2 | A1; - - if ((Registers.A.W ^ Work16) & (Registers.A.W ^ Ans16) & 0x8000) - SetOverflow(); - else - ClearOverflow(); - - Registers.A.W = Ans16; - SetZN(Registers.A.W); - } + if ((Registers.A.W ^ Work16) & + (Registers.A.W ^ (uint16) Int32) & 0x8000) + SetOverflow(); else - { - int32 Int32 = (int32) Registers.A.W - (int32) Work16 + (int32) CheckCarry() - 1; - - ICPU._Carry = Int32 >= 0; - - if ((Registers.A.W ^ Work16) & (Registers.A.W ^ (uint16) Int32) & 0x8000) - SetOverflow(); - else - ClearOverflow(); - - Registers.A.W = (uint16) Int32; - SetZN(Registers.A.W); - } + ClearOverflow (); + Registers.A.W = (uint16) Int32; + SetZN (Registers.A.W); + } } -static inline void SBC (uint8 Work8) -{ - if (CheckDecimal()) - { - uint8 A1 = Registers.A.W & 0x0F; - uint16 A2 = Registers.A.W & 0xF0; - uint8 W1 = Work8 & 0x0F; - uint8 W2 = Work8 & 0xF0; +STATIC inline void SBC (uint8 Work8) { + if (CheckDecimal ()) { + uint8 A1 = Registers.A.W & 0x0F; + uint16 A2 = Registers.A.W & 0xF0; + uint8 W1 = Work8 & 0x0F; + uint8 W2 = Work8 & 0xF0; - A1 -= W1 + !CheckCarry(); - A2 -= W2; - - if (A1 > 0x0F) - { - A1 += 0x0A; - A1 &= 0x0F; - A2 -= 0x10; - } - - if (A2 > 0xF0) - { - A2 += 0xA0; - A2 &= 0xF0; - ClearCarry(); - } - else - SetCarry(); - - uint8 Ans8 = A2 | A1; - - if ((Registers.AL ^ Work8) & (Registers.AL ^ Ans8) & 0x80) - SetOverflow(); - else - ClearOverflow(); - - Registers.AL = Ans8; - SetZN(Registers.AL); + A1 -= W1 + !CheckCarry (); + A2 -= W2; + if (A1 > 0x0F) { + A1 += 0x0A; + A1 &= 0x0F; + A2 -= 0x10; } + if (A2 > 0xF0) { + A2 += 0xA0; + A2 &= 0xF0; + ClearCarry (); + } else { + SetCarry (); + } + + uint8 Ans8 = A2|A1; + if ((Registers.AL ^ Work8) & + (Registers.AL ^ Ans8) & 0x80) + SetOverflow (); else - { - int16 Int16 = (int16) Registers.AL - (int16) Work8 + (int16) CheckCarry() - 1; + ClearOverflow (); + Registers.AL = Ans8; + SetZN (Registers.AL); + } else { + int16 Int16 = (int16) Registers.AL - (int16) Work8 + (int16) CheckCarry() - 1; - ICPU._Carry = Int16 >= 0; - - if ((Registers.AL ^ Work8) & (Registers.AL ^ (uint8) Int16) & 0x80) - SetOverflow(); - else - ClearOverflow(); - - Registers.AL = (uint8) Int16; - SetZN(Registers.AL); - } + ICPU._Carry = Int16 >= 0; + if ((Registers.AL ^ Work8) & + (Registers.AL ^ (uint8) Int16) & 0x80) + SetOverflow (); + else + ClearOverflow (); + Registers.AL = (uint8) Int16; + SetZN (Registers.AL); + } } -static inline void STA16 (uint32 OpAddress, enum s9xwrap_t w) -{ - S9xSetWord(Registers.A.W, OpAddress, w); - OpenBus = Registers.AH; +STATIC inline void STA16 (uint32 OpAddress, enum s9xwrap_t w) { + S9xSetWord (Registers.A.W, OpAddress, w); + OpenBus = Registers.AH; } -static inline void STA8 (uint32 OpAddress) -{ - S9xSetByte(Registers.AL, OpAddress); - OpenBus = Registers.AL; +STATIC inline void STA8 (uint32 OpAddress) { + S9xSetByte (Registers.AL, OpAddress); + OpenBus = Registers.AL; } -static inline void STX16 (uint32 OpAddress, enum s9xwrap_t w) -{ - S9xSetWord(Registers.X.W, OpAddress, w); - OpenBus = Registers.XH; +STATIC inline void STX16 (uint32 OpAddress, enum s9xwrap_t w) { + S9xSetWord (Registers.X.W, OpAddress, w); + OpenBus = Registers.XH; } -static inline void STX8 (uint32 OpAddress) -{ - S9xSetByte(Registers.XL, OpAddress); - OpenBus = Registers.XL; +STATIC inline void STX8 (uint32 OpAddress) { + S9xSetByte (Registers.XL, OpAddress); + OpenBus = Registers.XL; } -static inline void STY16 (uint32 OpAddress, enum s9xwrap_t w) -{ - S9xSetWord(Registers.Y.W, OpAddress, w); - OpenBus = Registers.YH; +STATIC inline void STY16 (uint32 OpAddress, enum s9xwrap_t w) { + S9xSetWord (Registers.Y.W, OpAddress, w); + OpenBus = Registers.YH; } -static inline void STY8 (uint32 OpAddress) -{ - S9xSetByte(Registers.YL, OpAddress); - OpenBus = Registers.YL; +STATIC inline void STY8 (uint32 OpAddress) { + S9xSetByte (Registers.YL, OpAddress); + OpenBus = Registers.YL; } -static inline void STZ16 (uint32 OpAddress, enum s9xwrap_t w) -{ - S9xSetWord(0, OpAddress, w); - OpenBus = 0; +STATIC inline void STZ16 (uint32 OpAddress, enum s9xwrap_t w) { + S9xSetWord (0, OpAddress, w); + OpenBus = 0; } -static inline void STZ8 (uint32 OpAddress) -{ - S9xSetByte(0, OpAddress); - OpenBus = 0; +STATIC inline void STZ8 (uint32 OpAddress) { + S9xSetByte (0, OpAddress); + OpenBus = 0; } -static inline void TSB16 (uint32 OpAddress, enum s9xwrap_t w) -{ - uint16 Work16 = S9xGetWord(OpAddress, w); - ICPU._Zero = (Work16 & Registers.A.W) != 0; - Work16 |= Registers.A.W; - AddCycles(ONE_CYCLE); - S9xSetWord(Work16, OpAddress, w, WRITE_10); - OpenBus = Work16 & 0xff; +STATIC inline void TSB16 (uint32 OpAddress, enum s9xwrap_t w) { + uint16 Work16 = S9xGetWord (OpAddress, w); + ICPU._Zero = (Work16 & Registers.A.W) != 0; + Work16 |= Registers.A.W; + AddCycles(ONE_CYCLE); + S9xSetWord (Work16, OpAddress, w, WRITE_10); + OpenBus = Work16&0xff; } -static inline void TSB8 (uint32 OpAddress) -{ - uint8 Work8 = S9xGetByte(OpAddress); - ICPU._Zero = Work8 & Registers.AL; - Work8 |= Registers.AL; - AddCycles(ONE_CYCLE); - S9xSetByte(Work8, OpAddress); - OpenBus = Work8; +STATIC inline void TSB8 (uint32 OpAddress) { + uint8 Work8 = S9xGetByte (OpAddress); + ICPU._Zero = Work8 & Registers.AL; + Work8 |= Registers.AL; + AddCycles(ONE_CYCLE); + S9xSetByte (Work8, OpAddress); + OpenBus = Work8; } -static inline void TRB16 (uint32 OpAddress, enum s9xwrap_t w) -{ - uint16 Work16 = S9xGetWord(OpAddress, w); - ICPU._Zero = (Work16 & Registers.A.W) != 0; - Work16 &= ~Registers.A.W; - AddCycles(ONE_CYCLE); - S9xSetWord(Work16, OpAddress, w, WRITE_10); - OpenBus = Work16 & 0xff; +STATIC inline void TRB16 (uint32 OpAddress, enum s9xwrap_t w) { + uint16 Work16 = S9xGetWord (OpAddress, w); + ICPU._Zero = (Work16 & Registers.A.W) != 0; + Work16 &= ~Registers.A.W; + AddCycles(ONE_CYCLE); + S9xSetWord (Work16, OpAddress, w, WRITE_10); + OpenBus = Work16&0xff; } -static inline void TRB8 (uint32 OpAddress) -{ - uint8 Work8 = S9xGetByte(OpAddress); - ICPU._Zero = Work8 & Registers.AL; - Work8 &= ~Registers.AL; - AddCycles(ONE_CYCLE); - S9xSetByte(Work8, OpAddress); - OpenBus = Work8; +STATIC inline void TRB8 (uint32 OpAddress) { + uint8 Work8 = S9xGetByte (OpAddress); + ICPU._Zero = Work8 & Registers.AL; + Work8 &= ~Registers.AL; + AddCycles(ONE_CYCLE); + S9xSetByte (Work8, OpAddress); + OpenBus = Work8; } - #endif diff --git a/source/snes9x/cpuops.cpp b/source/snes9x/cpuops.cpp index e50b78f..d55e321 100644 --- a/source/snes9x/cpuops.cpp +++ b/source/snes9x/cpuops.cpp @@ -159,1382 +159,1369 @@ **********************************************************************************/ + + +/*****************************************************************************/ +/* CPU-S9xOpcodes.CPP */ +/* This file contains all the opcodes */ +/*****************************************************************************/ + #include "snes9x.h" #include "memmap.h" -#include "apu/apu.h" - -// for "Magic WDM" features -#ifdef DEBUGGER -#include "snapshot.h" -#include "display.h" -#include "debug.h" +#include "s9xdebug.h" #include "missing.h" +#ifdef DEBUGGER +// for "Magic WDM" features +#include "display.h" +#include "snapshot.h" #endif +#include "apu.h" +#include "sa1.h" +#include "spc7110.h" +#include "dsp1.h" #ifdef SA1_OPCODES -#define AddCycles(n) { } +#define AddCycles(n) {} #else -#define AddCycles(n) CPU.Cycles += n +#define AddCycles(n) CPU.Cycles+=n #endif +#include "cpuexec.h" #include "cpuaddr.h" #include "cpuops.h" #include "cpumacro.h" - /* ADC ********************************************************************* */ - -static void Op69M1 (void) -{ - ADC(Immediate8(READ)); +static void Op69M1 (void) { + ADC(Immediate8(READ)); } -static void Op69M0 (void) -{ - ADC(Immediate16(READ)); +static void Op69M0 (void) { + ADC(Immediate16(READ)); } -static void Op69Slow (void) -{ - if (CheckMemory()) - ADC(Immediate8Slow(READ)); - else - ADC(Immediate16Slow(READ)); +static void Op69Slow (void) { + if(CheckMemory()) { + ADC(Immediate8Slow(READ)); + } else { + ADC(Immediate16Slow(READ)); + } } -rOP8 (65M1, Direct, WRAP_BANK, ADC) -rOP16(65M0, Direct, WRAP_BANK, ADC) -rOPM (65Slow, DirectSlow, WRAP_BANK, ADC) +rOP8 (65M1, Direct, WRAP_BANK, ADC) +rOP16(65M0, Direct, WRAP_BANK, ADC) +rOPM (65Slow, DirectSlow, WRAP_BANK, ADC) -rOP8 (75E1, DirectIndexedXE1, WRAP_BANK, ADC) -rOP8 (75E0M1, DirectIndexedXE0, WRAP_BANK, ADC) -rOP16(75E0M0, DirectIndexedXE0, WRAP_BANK, ADC) -rOPM (75Slow, DirectIndexedXSlow, WRAP_BANK, ADC) +rOP8 (75E1, DirectIndexedXE1, WRAP_BANK, ADC) +rOP8 (75E0M1, DirectIndexedXE0, WRAP_BANK, ADC) +rOP16(75E0M0, DirectIndexedXE0, WRAP_BANK, ADC) +rOPM (75Slow, DirectIndexedXSlow, WRAP_BANK, ADC) -rOP8 (72E1, DirectIndirectE1, WRAP_NONE, ADC) -rOP8 (72E0M1, DirectIndirectE0, WRAP_NONE, ADC) -rOP16(72E0M0, DirectIndirectE0, WRAP_NONE, ADC) -rOPM (72Slow, DirectIndirectSlow, WRAP_NONE, ADC) +rOP8 (72E1, DirectIndirectE1, WRAP_NONE, ADC) +rOP8 (72E0M1, DirectIndirectE0, WRAP_NONE, ADC) +rOP16(72E0M0, DirectIndirectE0, WRAP_NONE, ADC) +rOPM (72Slow, DirectIndirectSlow, WRAP_NONE, ADC) -rOP8 (61E1, DirectIndexedIndirectE1, WRAP_NONE, ADC) -rOP8 (61E0M1, DirectIndexedIndirectE0, WRAP_NONE, ADC) -rOP16(61E0M0, DirectIndexedIndirectE0, WRAP_NONE, ADC) -rOPM (61Slow, DirectIndexedIndirectSlow, WRAP_NONE, ADC) +rOP8 (61E1, DirectIndexedIndirectE1, WRAP_NONE, ADC) +rOP8 (61E0M1, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOP16(61E0M0, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOPM (61Slow, DirectIndexedIndirectSlow, WRAP_NONE, ADC) -rOP8 (71E1, DirectIndirectIndexedE1, WRAP_NONE, ADC) -rOP8 (71E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) -rOP16(71E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) -rOP8 (71E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) -rOP16(71E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) -rOPM (71Slow, DirectIndirectIndexedSlow, WRAP_NONE, ADC) +rOP8 (71E1, DirectIndirectIndexedE1, WRAP_NONE, ADC) +rOP8 (71E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP16(71E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP8 (71E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOP16(71E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOPM (71Slow, DirectIndirectIndexedSlow, WRAP_NONE, ADC) -rOP8 (67M1, DirectIndirectLong, WRAP_NONE, ADC) -rOP16(67M0, DirectIndirectLong, WRAP_NONE, ADC) -rOPM (67Slow, DirectIndirectLongSlow, WRAP_NONE, ADC) +rOP8 (67M1, DirectIndirectLong, WRAP_NONE, ADC) +rOP16(67M0, DirectIndirectLong, WRAP_NONE, ADC) +rOPM (67Slow, DirectIndirectLongSlow, WRAP_NONE, ADC) -rOP8 (77M1, DirectIndirectIndexedLong, WRAP_NONE, ADC) -rOP16(77M0, DirectIndirectIndexedLong, WRAP_NONE, ADC) -rOPM (77Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ADC) +rOP8 (77M1, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOP16(77M0, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOPM (77Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ADC) -rOP8 (6DM1, Absolute, WRAP_NONE, ADC) -rOP16(6DM0, Absolute, WRAP_NONE, ADC) -rOPM (6DSlow, AbsoluteSlow, WRAP_NONE, ADC) +rOP8 (6DM1, Absolute, WRAP_NONE, ADC) +rOP16(6DM0, Absolute, WRAP_NONE, ADC) +rOPM (6DSlow, AbsoluteSlow, WRAP_NONE, ADC) -rOP8 (7DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) -rOP16(7DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) -rOP8 (7DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) -rOP16(7DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) -rOPM (7DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ADC) +rOP8 (7DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP16(7DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP8 (7DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOP16(7DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOPM (7DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ADC) -rOP8 (79M1X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) -rOP16(79M0X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) -rOP8 (79M1X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) -rOP16(79M0X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) -rOPM (79Slow, AbsoluteIndexedYSlow, WRAP_NONE, ADC) +rOP8 (79M1X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP16(79M0X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP8 (79M1X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOP16(79M0X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOPM (79Slow, AbsoluteIndexedYSlow, WRAP_NONE, ADC) -rOP8 (6FM1, AbsoluteLong, WRAP_NONE, ADC) -rOP16(6FM0, AbsoluteLong, WRAP_NONE, ADC) -rOPM (6FSlow, AbsoluteLongSlow, WRAP_NONE, ADC) +rOP8 (6FM1, AbsoluteLong, WRAP_NONE, ADC) +rOP16(6FM0, AbsoluteLong, WRAP_NONE, ADC) +rOPM (6FSlow, AbsoluteLongSlow, WRAP_NONE, ADC) -rOP8 (7FM1, AbsoluteLongIndexedX, WRAP_NONE, ADC) -rOP16(7FM0, AbsoluteLongIndexedX, WRAP_NONE, ADC) -rOPM (7FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ADC) +rOP8 (7FM1, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOP16(7FM0, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOPM (7FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ADC) -rOP8 (63M1, StackRelative, WRAP_NONE, ADC) -rOP16(63M0, StackRelative, WRAP_NONE, ADC) -rOPM (63Slow, StackRelativeSlow, WRAP_NONE, ADC) +rOP8 (63M1, StackRelative, WRAP_NONE, ADC) +rOP16(63M0, StackRelative, WRAP_NONE, ADC) +rOPM (63Slow, StackRelativeSlow, WRAP_NONE, ADC) -rOP8 (73M1, StackRelativeIndirectIndexed, WRAP_NONE, ADC) -rOP16(73M0, StackRelativeIndirectIndexed, WRAP_NONE, ADC) -rOPM (73Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC) +rOP8 (73M1, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOP16(73M0, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOPM (73Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC) + +/*****************************************************************************/ /* AND ********************************************************************* */ - -static void Op29M1 (void) -{ - Registers.AL &= Immediate8(READ); - SetZN(Registers.AL); +static void Op29M1 (void) { + Registers.AL &= Immediate8(READ); + SetZN (Registers.AL); } -static void Op29M0 (void) -{ - Registers.A.W &= Immediate16(READ); - SetZN(Registers.A.W); +static void Op29M0 (void) { + Registers.A.W &= Immediate16(READ); + SetZN (Registers.A.W); } -static void Op29Slow (void) -{ - if (CheckMemory()) - { - Registers.AL &= Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W &= Immediate16Slow(READ); - SetZN(Registers.A.W); - } +static void Op29Slow (void) { + if(CheckMemory()){ + Registers.AL &= Immediate8Slow(READ); + SetZN (Registers.AL); + } else { + Registers.A.W &= Immediate16Slow(READ); + SetZN (Registers.A.W); + } } -rOP8 (25M1, Direct, WRAP_BANK, AND) -rOP16(25M0, Direct, WRAP_BANK, AND) -rOPM (25Slow, DirectSlow, WRAP_BANK, AND) +rOP8 (25M1, Direct, WRAP_BANK, AND) +rOP16(25M0, Direct, WRAP_BANK, AND) +rOPM (25Slow, DirectSlow, WRAP_BANK, AND) -rOP8 (35E1, DirectIndexedXE1, WRAP_BANK, AND) -rOP8 (35E0M1, DirectIndexedXE0, WRAP_BANK, AND) -rOP16(35E0M0, DirectIndexedXE0, WRAP_BANK, AND) -rOPM (35Slow, DirectIndexedXSlow, WRAP_BANK, AND) +rOP8 (35E1, DirectIndexedXE1, WRAP_BANK, AND) +rOP8 (35E0M1, DirectIndexedXE0, WRAP_BANK, AND) +rOP16(35E0M0, DirectIndexedXE0, WRAP_BANK, AND) +rOPM (35Slow, DirectIndexedXSlow, WRAP_BANK, AND) -rOP8 (32E1, DirectIndirectE1, WRAP_NONE, AND) -rOP8 (32E0M1, DirectIndirectE0, WRAP_NONE, AND) -rOP16(32E0M0, DirectIndirectE0, WRAP_NONE, AND) -rOPM (32Slow, DirectIndirectSlow, WRAP_NONE, AND) +rOP8 (32E1, DirectIndirectE1, WRAP_NONE, AND) +rOP8 (32E0M1, DirectIndirectE0, WRAP_NONE, AND) +rOP16(32E0M0, DirectIndirectE0, WRAP_NONE, AND) +rOPM (32Slow, DirectIndirectSlow, WRAP_NONE, AND) -rOP8 (21E1, DirectIndexedIndirectE1, WRAP_NONE, AND) -rOP8 (21E0M1, DirectIndexedIndirectE0, WRAP_NONE, AND) -rOP16(21E0M0, DirectIndexedIndirectE0, WRAP_NONE, AND) -rOPM (21Slow, DirectIndexedIndirectSlow, WRAP_NONE, AND) +rOP8 (21E1, DirectIndexedIndirectE1, WRAP_NONE, AND) +rOP8 (21E0M1, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOP16(21E0M0, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOPM (21Slow, DirectIndexedIndirectSlow, WRAP_NONE, AND) -rOP8 (31E1, DirectIndirectIndexedE1, WRAP_NONE, AND) -rOP8 (31E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) -rOP16(31E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) -rOP8 (31E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) -rOP16(31E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) -rOPM (31Slow, DirectIndirectIndexedSlow, WRAP_NONE, AND) +rOP8 (31E1, DirectIndirectIndexedE1, WRAP_NONE, AND) +rOP8 (31E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP16(31E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP8 (31E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOP16(31E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOPM (31Slow, DirectIndirectIndexedSlow, WRAP_NONE, AND) -rOP8 (27M1, DirectIndirectLong, WRAP_NONE, AND) -rOP16(27M0, DirectIndirectLong, WRAP_NONE, AND) -rOPM (27Slow, DirectIndirectLongSlow, WRAP_NONE, AND) +rOP8 (27M1, DirectIndirectLong, WRAP_NONE, AND) +rOP16(27M0, DirectIndirectLong, WRAP_NONE, AND) +rOPM (27Slow, DirectIndirectLongSlow, WRAP_NONE, AND) -rOP8 (37M1, DirectIndirectIndexedLong, WRAP_NONE, AND) -rOP16(37M0, DirectIndirectIndexedLong, WRAP_NONE, AND) -rOPM (37Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, AND) +rOP8 (37M1, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOP16(37M0, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOPM (37Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, AND) -rOP8 (2DM1, Absolute, WRAP_NONE, AND) -rOP16(2DM0, Absolute, WRAP_NONE, AND) -rOPM (2DSlow, AbsoluteSlow, WRAP_NONE, AND) +rOP8 (2DM1, Absolute, WRAP_NONE, AND) +rOP16(2DM0, Absolute, WRAP_NONE, AND) +rOPM (2DSlow, AbsoluteSlow, WRAP_NONE, AND) -rOP8 (3DM1X1, AbsoluteIndexedXX1, WRAP_NONE, AND) -rOP16(3DM0X1, AbsoluteIndexedXX1, WRAP_NONE, AND) -rOP8 (3DM1X0, AbsoluteIndexedXX0, WRAP_NONE, AND) -rOP16(3DM0X0, AbsoluteIndexedXX0, WRAP_NONE, AND) -rOPM (3DSlow, AbsoluteIndexedXSlow, WRAP_NONE, AND) +rOP8 (3DM1X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP16(3DM0X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP8 (3DM1X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOP16(3DM0X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOPM (3DSlow, AbsoluteIndexedXSlow, WRAP_NONE, AND) -rOP8 (39M1X1, AbsoluteIndexedYX1, WRAP_NONE, AND) -rOP16(39M0X1, AbsoluteIndexedYX1, WRAP_NONE, AND) -rOP8 (39M1X0, AbsoluteIndexedYX0, WRAP_NONE, AND) -rOP16(39M0X0, AbsoluteIndexedYX0, WRAP_NONE, AND) -rOPM (39Slow, AbsoluteIndexedYSlow, WRAP_NONE, AND) +rOP8 (39M1X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP16(39M0X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP8 (39M1X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOP16(39M0X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOPM (39Slow, AbsoluteIndexedYSlow, WRAP_NONE, AND) -rOP8 (2FM1, AbsoluteLong, WRAP_NONE, AND) -rOP16(2FM0, AbsoluteLong, WRAP_NONE, AND) -rOPM (2FSlow, AbsoluteLongSlow, WRAP_NONE, AND) +rOP8 (2FM1, AbsoluteLong, WRAP_NONE, AND) +rOP16(2FM0, AbsoluteLong, WRAP_NONE, AND) +rOPM (2FSlow, AbsoluteLongSlow, WRAP_NONE, AND) -rOP8 (3FM1, AbsoluteLongIndexedX, WRAP_NONE, AND) -rOP16(3FM0, AbsoluteLongIndexedX, WRAP_NONE, AND) -rOPM (3FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, AND) +rOP8 (3FM1, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOP16(3FM0, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOPM (3FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, AND) -rOP8 (23M1, StackRelative, WRAP_NONE, AND) -rOP16(23M0, StackRelative, WRAP_NONE, AND) -rOPM (23Slow, StackRelativeSlow, WRAP_NONE, AND) +rOP8 (23M1, StackRelative, WRAP_NONE, AND) +rOP16(23M0, StackRelative, WRAP_NONE, AND) +rOPM (23Slow, StackRelativeSlow, WRAP_NONE, AND) -rOP8 (33M1, StackRelativeIndirectIndexed, WRAP_NONE, AND) -rOP16(33M0, StackRelativeIndirectIndexed, WRAP_NONE, AND) -rOPM (33Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, AND) +rOP8 (33M1, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOP16(33M0, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOPM (33Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, AND) + +/*****************************************************************************/ /* ASL ********************************************************************* */ - -static void Op0AM1 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = (Registers.AL & 0x80) != 0; - Registers.AL <<= 1; - SetZN(Registers.AL); +static void Op0AM1 (void) { + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN (Registers.AL); } -static void Op0AM0 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = (Registers.AH & 0x80) != 0; - Registers.A.W <<= 1; - SetZN(Registers.A.W); +static void Op0AM0 (void) { + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN (Registers.A.W); } -static void Op0ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - ICPU._Carry = (Registers.AL & 0x80) != 0; - Registers.AL <<= 1; - SetZN(Registers.AL); - } - else - { - ICPU._Carry = (Registers.AH & 0x80) != 0; - Registers.A.W <<= 1; - SetZN(Registers.A.W); - } +static void Op0ASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckMemory()){ + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN (Registers.AL); + } else { + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN (Registers.A.W); + } } -mOP8 (06M1, Direct, WRAP_BANK, ASL) -mOP16(06M0, Direct, WRAP_BANK, ASL) -mOPM (06Slow, DirectSlow, WRAP_BANK, ASL) +mOP8 (06M1, Direct, WRAP_BANK, ASL) +mOP16(06M0, Direct, WRAP_BANK, ASL) +mOPM (06Slow, DirectSlow, WRAP_BANK, ASL) -mOP8 (16E1, DirectIndexedXE1, WRAP_BANK, ASL) -mOP8 (16E0M1, DirectIndexedXE0, WRAP_BANK, ASL) -mOP16(16E0M0, DirectIndexedXE0, WRAP_BANK, ASL) -mOPM (16Slow, DirectIndexedXSlow, WRAP_BANK, ASL) +mOP8 (16E1, DirectIndexedXE1, WRAP_BANK, ASL) +mOP8 (16E0M1, DirectIndexedXE0, WRAP_BANK, ASL) +mOP16(16E0M0, DirectIndexedXE0, WRAP_BANK, ASL) +mOPM (16Slow, DirectIndexedXSlow, WRAP_BANK, ASL) -mOP8 (0EM1, Absolute, WRAP_NONE, ASL) -mOP16(0EM0, Absolute, WRAP_NONE, ASL) -mOPM (0ESlow, AbsoluteSlow, WRAP_NONE, ASL) +mOP8 (0EM1, Absolute, WRAP_NONE, ASL) +mOP16(0EM0, Absolute, WRAP_NONE, ASL) +mOPM (0ESlow, AbsoluteSlow, WRAP_NONE, ASL) -mOP8 (1EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) -mOP16(1EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) -mOP8 (1EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) -mOP16(1EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) -mOPM (1ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ASL) +mOP8 (1EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP16(1EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP8 (1EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOP16(1EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOPM (1ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ASL) + +/*****************************************************************************/ /* BIT ********************************************************************* */ -static void Op89M1 (void) -{ - ICPU._Zero = Registers.AL & Immediate8(READ); +static void Op89M1 (void) { + ICPU._Zero = Registers.AL & Immediate8(READ); } -static void Op89M0 (void) -{ - ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0; +static void Op89M0 (void) { + ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0; } -static void Op89Slow (void) -{ - if (CheckMemory()) - ICPU._Zero = Registers.AL & Immediate8Slow(READ); - else - ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0; +static void Op89Slow (void) { + if(CheckMemory()){ + ICPU._Zero = Registers.AL & Immediate8Slow(READ); + } else { + ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0; + } } -rOP8 (24M1, Direct, WRAP_BANK, BIT) -rOP16(24M0, Direct, WRAP_BANK, BIT) -rOPM (24Slow, DirectSlow, WRAP_BANK, BIT) +rOP8 (24M1, Direct, WRAP_BANK, BIT) +rOP16(24M0, Direct, WRAP_BANK, BIT) +rOPM (24Slow, DirectSlow, WRAP_BANK, BIT) -rOP8 (34E1, DirectIndexedXE1, WRAP_BANK, BIT) -rOP8 (34E0M1, DirectIndexedXE0, WRAP_BANK, BIT) -rOP16(34E0M0, DirectIndexedXE0, WRAP_BANK, BIT) -rOPM (34Slow, DirectIndexedXSlow, WRAP_BANK, BIT) +rOP8 (34E1, DirectIndexedXE1, WRAP_BANK, BIT) +rOP8 (34E0M1, DirectIndexedXE0, WRAP_BANK, BIT) +rOP16(34E0M0, DirectIndexedXE0, WRAP_BANK, BIT) +rOPM (34Slow, DirectIndexedXSlow, WRAP_BANK, BIT) -rOP8 (2CM1, Absolute, WRAP_NONE, BIT) -rOP16(2CM0, Absolute, WRAP_NONE, BIT) -rOPM (2CSlow, AbsoluteSlow, WRAP_NONE, BIT) +rOP8 (2CM1, Absolute, WRAP_NONE, BIT) +rOP16(2CM0, Absolute, WRAP_NONE, BIT) +rOPM (2CSlow, AbsoluteSlow, WRAP_NONE, BIT) -rOP8 (3CM1X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) -rOP16(3CM0X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) -rOP8 (3CM1X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) -rOP16(3CM0X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) -rOPM (3CSlow, AbsoluteIndexedXSlow, WRAP_NONE, BIT) +rOP8 (3CM1X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP16(3CM0X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP8 (3CM1X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOP16(3CM0X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOPM (3CSlow, AbsoluteIndexedXSlow, WRAP_NONE, BIT) + +/*****************************************************************************/ /* CMP ********************************************************************* */ -static void OpC9M1 (void) -{ - int16 Int16 = (int16) Registers.AL - (int16) Immediate8(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); +static void OpC9M1 (void) { + int16 Int16 = (int16)Registers.AL - (int16)Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN ((uint8)Int16); } -static void OpC9M0 (void) -{ - int32 Int32 = (int32) Registers.A.W - (int32) Immediate16(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); +static void OpC9M0 (void) { + int32 Int32 = (int32)Registers.A.W - (int32)Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); } -static void OpC9Slow (void) -{ - if (CheckMemory()) - { - int16 Int16 = (int16) Registers.AL - (int16) Immediate8Slow(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); - } - else - { - int32 Int32 = (int32) Registers.A.W - (int32) Immediate16Slow(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); - } +static void OpC9Slow (void) { + if(CheckMemory()){ + int16 Int16 = (int16)Registers.AL - (int16)Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN ((uint8)Int16); + } else { + int32 Int32 = (int32)Registers.A.W - (int32)Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN ((uint16)Int32); + } } -rOP8 (C5M1, Direct, WRAP_BANK, CMP) -rOP16(C5M0, Direct, WRAP_BANK, CMP) -rOPM (C5Slow, DirectSlow, WRAP_BANK, CMP) +rOP8 (C5M1, Direct, WRAP_BANK, CMP) +rOP16(C5M0, Direct, WRAP_BANK, CMP) +rOPM (C5Slow, DirectSlow, WRAP_BANK, CMP) -rOP8 (D5E1, DirectIndexedXE1, WRAP_BANK, CMP) -rOP8 (D5E0M1, DirectIndexedXE0, WRAP_BANK, CMP) -rOP16(D5E0M0, DirectIndexedXE0, WRAP_BANK, CMP) -rOPM (D5Slow, DirectIndexedXSlow, WRAP_BANK, CMP) +rOP8 (D5E1, DirectIndexedXE1, WRAP_BANK, CMP) +rOP8 (D5E0M1, DirectIndexedXE0, WRAP_BANK, CMP) +rOP16(D5E0M0, DirectIndexedXE0, WRAP_BANK, CMP) +rOPM (D5Slow, DirectIndexedXSlow, WRAP_BANK, CMP) -rOP8 (D2E1, DirectIndirectE1, WRAP_NONE, CMP) -rOP8 (D2E0M1, DirectIndirectE0, WRAP_NONE, CMP) -rOP16(D2E0M0, DirectIndirectE0, WRAP_NONE, CMP) -rOPM (D2Slow, DirectIndirectSlow, WRAP_NONE, CMP) +rOP8 (D2E1, DirectIndirectE1, WRAP_NONE, CMP) +rOP8 (D2E0M1, DirectIndirectE0, WRAP_NONE, CMP) +rOP16(D2E0M0, DirectIndirectE0, WRAP_NONE, CMP) +rOPM (D2Slow, DirectIndirectSlow, WRAP_NONE, CMP) -rOP8 (C1E1, DirectIndexedIndirectE1, WRAP_NONE, CMP) -rOP8 (C1E0M1, DirectIndexedIndirectE0, WRAP_NONE, CMP) -rOP16(C1E0M0, DirectIndexedIndirectE0, WRAP_NONE, CMP) -rOPM (C1Slow, DirectIndexedIndirectSlow, WRAP_NONE, CMP) +rOP8 (C1E1, DirectIndexedIndirectE1, WRAP_NONE, CMP) +rOP8 (C1E0M1, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOP16(C1E0M0, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOPM (C1Slow, DirectIndexedIndirectSlow, WRAP_NONE, CMP) -rOP8 (D1E1, DirectIndirectIndexedE1, WRAP_NONE, CMP) -rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) -rOP16(D1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) -rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) -rOP16(D1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) -rOPM (D1Slow, DirectIndirectIndexedSlow, WRAP_NONE, CMP) +rOP8 (D1E1, DirectIndirectIndexedE1, WRAP_NONE, CMP) +rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP16(D1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOP16(D1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOPM (D1Slow, DirectIndirectIndexedSlow, WRAP_NONE, CMP) -rOP8 (C7M1, DirectIndirectLong, WRAP_NONE, CMP) -rOP16(C7M0, DirectIndirectLong, WRAP_NONE, CMP) -rOPM (C7Slow, DirectIndirectLongSlow, WRAP_NONE, CMP) +rOP8 (C7M1, DirectIndirectLong, WRAP_NONE, CMP) +rOP16(C7M0, DirectIndirectLong, WRAP_NONE, CMP) +rOPM (C7Slow, DirectIndirectLongSlow, WRAP_NONE, CMP) -rOP8 (D7M1, DirectIndirectIndexedLong, WRAP_NONE, CMP) -rOP16(D7M0, DirectIndirectIndexedLong, WRAP_NONE, CMP) -rOPM (D7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, CMP) +rOP8 (D7M1, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOP16(D7M0, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOPM (D7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, CMP) -rOP8 (CDM1, Absolute, WRAP_NONE, CMP) -rOP16(CDM0, Absolute, WRAP_NONE, CMP) -rOPM (CDSlow, AbsoluteSlow, WRAP_NONE, CMP) +rOP8 (CDM1, Absolute, WRAP_NONE, CMP) +rOP16(CDM0, Absolute, WRAP_NONE, CMP) +rOPM (CDSlow, AbsoluteSlow, WRAP_NONE, CMP) -rOP8 (DDM1X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) -rOP16(DDM0X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) -rOP8 (DDM1X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) -rOP16(DDM0X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) -rOPM (DDSlow, AbsoluteIndexedXSlow, WRAP_NONE, CMP) +rOP8 (DDM1X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP16(DDM0X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP8 (DDM1X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOP16(DDM0X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOPM (DDSlow, AbsoluteIndexedXSlow, WRAP_NONE, CMP) -rOP8 (D9M1X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) -rOP16(D9M0X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) -rOP8 (D9M1X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) -rOP16(D9M0X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) -rOPM (D9Slow, AbsoluteIndexedYSlow, WRAP_NONE, CMP) +rOP8 (D9M1X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP16(D9M0X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP8 (D9M1X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOP16(D9M0X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOPM (D9Slow, AbsoluteIndexedYSlow, WRAP_NONE, CMP) -rOP8 (CFM1, AbsoluteLong, WRAP_NONE, CMP) -rOP16(CFM0, AbsoluteLong, WRAP_NONE, CMP) -rOPM (CFSlow, AbsoluteLongSlow, WRAP_NONE, CMP) +rOP8 (CFM1, AbsoluteLong, WRAP_NONE, CMP) +rOP16(CFM0, AbsoluteLong, WRAP_NONE, CMP) +rOPM (CFSlow, AbsoluteLongSlow, WRAP_NONE, CMP) -rOP8 (DFM1, AbsoluteLongIndexedX, WRAP_NONE, CMP) -rOP16(DFM0, AbsoluteLongIndexedX, WRAP_NONE, CMP) -rOPM (DFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, CMP) +rOP8 (DFM1, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOP16(DFM0, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOPM (DFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, CMP) -rOP8 (C3M1, StackRelative, WRAP_NONE, CMP) -rOP16(C3M0, StackRelative, WRAP_NONE, CMP) -rOPM (C3Slow, StackRelativeSlow, WRAP_NONE, CMP) +rOP8 (C3M1, StackRelative, WRAP_NONE, CMP) +rOP16(C3M0, StackRelative, WRAP_NONE, CMP) +rOPM (C3Slow, StackRelativeSlow, WRAP_NONE, CMP) -rOP8 (D3M1, StackRelativeIndirectIndexed, WRAP_NONE, CMP) -rOP16(D3M0, StackRelativeIndirectIndexed, WRAP_NONE, CMP) -rOPM (D3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP) +rOP8 (D3M1, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOP16(D3M0, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOPM (D3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP) + +/*****************************************************************************/ /* CPX ********************************************************************* */ -static void OpE0X1 (void) -{ - int16 Int16 = (int16) Registers.XL - (int16) Immediate8(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); +static void OpE0X1 (void) { + int16 Int16 = (int16)Registers.XL - (int16)Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN ((uint8)Int16); } -static void OpE0X0 (void) -{ - int32 Int32 = (int32) Registers.X.W - (int32) Immediate16(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); +static void OpE0X0 (void) { + int32 Int32 = (int32)Registers.X.W - (int32)Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); } -static void OpE0Slow (void) -{ - if (CheckIndex()) - { - int16 Int16 = (int16) Registers.XL - (int16) Immediate8Slow(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); - } - else - { - int32 Int32 = (int32) Registers.X.W - (int32) Immediate16Slow(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); - } +static void OpE0Slow (void) { + if(CheckIndex()){ + int16 Int16 = (int16)Registers.XL - (int16)Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN ((uint8)Int16); + } else { + int32 Int32 = (int32)Registers.X.W - (int32)Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); + } } -rOP8 (E4X1, Direct, WRAP_BANK, CPX) -rOP16(E4X0, Direct, WRAP_BANK, CPX) -rOPX (E4Slow, DirectSlow, WRAP_BANK, CPX) +rOP8 (E4X1, Direct, WRAP_BANK, CPX) +rOP16(E4X0, Direct, WRAP_BANK, CPX) +rOPX (E4Slow, DirectSlow, WRAP_BANK, CPX) -rOP8 (ECX1, Absolute, WRAP_NONE, CPX) -rOP16(ECX0, Absolute, WRAP_NONE, CPX) -rOPX (ECSlow, AbsoluteSlow, WRAP_NONE, CPX) +rOP8 (ECX1, Absolute, WRAP_NONE, CPX) +rOP16(ECX0, Absolute, WRAP_NONE, CPX) +rOPX (ECSlow, AbsoluteSlow, WRAP_NONE, CPX) + +/*****************************************************************************/ /* CPY ********************************************************************* */ -static void OpC0X1 (void) -{ - int16 Int16 = (int16) Registers.YL - (int16) Immediate8(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); +static void OpC0X1 (void) { + int16 Int16 = (int16)Registers.YL - (int16)Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN ((uint8)Int16); } -static void OpC0X0 (void) -{ - int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); +static void OpC0X0 (void) { + int32 Int32 = (int32)Registers.Y.W - (int32)Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); } -static void OpC0Slow (void) -{ - if (CheckIndex()) - { - int16 Int16 = (int16) Registers.YL - (int16) Immediate8Slow(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); - } - else - { - int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16Slow(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); - } +static void OpC0Slow (void) { + if(CheckIndex()){ + int16 Int16 = (int16)Registers.YL - (int16)Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN ((uint8)Int16); + } else { + int32 Int32 = (int32)Registers.Y.W - (int32)Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN ((uint16) Int32); + } } -rOP8 (C4X1, Direct, WRAP_BANK, CPY) -rOP16(C4X0, Direct, WRAP_BANK, CPY) -rOPX (C4Slow, DirectSlow, WRAP_BANK, CPY) +rOP8 (C4X1, Direct, WRAP_BANK, CPY) +rOP16(C4X0, Direct, WRAP_BANK, CPY) +rOPX (C4Slow, DirectSlow, WRAP_BANK, CPY) -rOP8 (CCX1, Absolute, WRAP_NONE, CPY) -rOP16(CCX0, Absolute, WRAP_NONE, CPY) -rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY) +rOP8 (CCX1, Absolute, WRAP_NONE, CPY) +rOP16(CCX0, Absolute, WRAP_NONE, CPY) +rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY) + +/*****************************************************************************/ /* DEC ********************************************************************* */ -static void Op3AM1 (void) -{ - AddCycles(ONE_CYCLE); +static void Op3AM1 (void){ + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.AL--; - SetZN(Registers.AL); + Registers.AL--; + SetZN (Registers.AL); } -static void Op3AM0 (void) -{ - AddCycles(ONE_CYCLE); +static void Op3AM0 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.A.W--; - SetZN(Registers.A.W); + Registers.A.W--; + SetZN (Registers.A.W); } -static void Op3ASlow (void) -{ - AddCycles(ONE_CYCLE); +static void Op3ASlow (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - - if (CheckMemory()) - { - Registers.AL--; - SetZN(Registers.AL); - } - else - { - Registers.A.W--; - SetZN(Registers.A.W); - } + if(CheckMemory()){ + Registers.AL--; + SetZN (Registers.AL); + } else { + Registers.A.W--; + SetZN (Registers.A.W); + } } -mOP8 (C6M1, Direct, WRAP_BANK, DEC) -mOP16(C6M0, Direct, WRAP_BANK, DEC) -mOPM (C6Slow, DirectSlow, WRAP_BANK, DEC) +mOP8 (C6M1, Direct, WRAP_BANK, DEC) +mOP16(C6M0, Direct, WRAP_BANK, DEC) +mOPM (C6Slow, DirectSlow, WRAP_BANK, DEC) -mOP8 (D6E1, DirectIndexedXE1, WRAP_BANK, DEC) -mOP8 (D6E0M1, DirectIndexedXE0, WRAP_BANK, DEC) -mOP16(D6E0M0, DirectIndexedXE0, WRAP_BANK, DEC) -mOPM (D6Slow, DirectIndexedXSlow, WRAP_BANK, DEC) +mOP8 (D6E1, DirectIndexedXE1, WRAP_BANK, DEC) +mOP8 (D6E0M1, DirectIndexedXE0, WRAP_BANK, DEC) +mOP16(D6E0M0, DirectIndexedXE0, WRAP_BANK, DEC) +mOPM (D6Slow, DirectIndexedXSlow, WRAP_BANK, DEC) -mOP8 (CEM1, Absolute, WRAP_NONE, DEC) -mOP16(CEM0, Absolute, WRAP_NONE, DEC) -mOPM (CESlow, AbsoluteSlow, WRAP_NONE, DEC) +mOP8 (CEM1, Absolute, WRAP_NONE, DEC) +mOP16(CEM0, Absolute, WRAP_NONE, DEC) +mOPM (CESlow, AbsoluteSlow, WRAP_NONE, DEC) -mOP8 (DEM1X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) -mOP16(DEM0X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) -mOP8 (DEM1X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) -mOP16(DEM0X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) -mOPM (DESlow, AbsoluteIndexedXSlow, WRAP_NONE, DEC) +mOP8 (DEM1X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP16(DEM0X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP8 (DEM1X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOP16(DEM0X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOPM (DESlow, AbsoluteIndexedXSlow, WRAP_NONE, DEC) + +/*****************************************************************************/ /* EOR ********************************************************************* */ - -static void Op49M1 (void) -{ - Registers.AL ^= Immediate8(READ); - SetZN(Registers.AL); +static void Op49M1 (void) { + Registers.AL ^= Immediate8(READ); + SetZN (Registers.AL); } -static void Op49M0 (void) -{ - Registers.A.W ^= Immediate16(READ); - SetZN(Registers.A.W); +static void Op49M0 (void) { + Registers.A.W ^= Immediate16(READ); + SetZN (Registers.A.W); } -static void Op49Slow (void) -{ - if (CheckMemory()) - { - Registers.AL ^= Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W ^= Immediate16Slow(READ); - SetZN(Registers.A.W); - } +static void Op49Slow (void) { + if(CheckMemory()) { + Registers.AL ^= Immediate8Slow(READ); + SetZN (Registers.AL); + } else { + Registers.A.W ^= Immediate16Slow(READ); + SetZN (Registers.A.W); + } } -rOP8 (45M1, Direct, WRAP_BANK, EOR) -rOP16(45M0, Direct, WRAP_BANK, EOR) -rOPM (45Slow, DirectSlow, WRAP_BANK, EOR) +rOP8 (45M1, Direct, WRAP_BANK, EOR) +rOP16(45M0, Direct, WRAP_BANK, EOR) +rOPM (45Slow, DirectSlow, WRAP_BANK, EOR) -rOP8 (55E1, DirectIndexedXE1, WRAP_BANK, EOR) -rOP8 (55E0M1, DirectIndexedXE0, WRAP_BANK, EOR) -rOP16(55E0M0, DirectIndexedXE0, WRAP_BANK, EOR) -rOPM (55Slow, DirectIndexedXSlow, WRAP_BANK, EOR) +rOP8 (55E1, DirectIndexedXE1, WRAP_BANK, EOR) +rOP8 (55E0M1, DirectIndexedXE0, WRAP_BANK, EOR) +rOP16(55E0M0, DirectIndexedXE0, WRAP_BANK, EOR) +rOPM (55Slow, DirectIndexedXSlow, WRAP_BANK, EOR) -rOP8 (52E1, DirectIndirectE1, WRAP_NONE, EOR) -rOP8 (52E0M1, DirectIndirectE0, WRAP_NONE, EOR) -rOP16(52E0M0, DirectIndirectE0, WRAP_NONE, EOR) -rOPM (52Slow, DirectIndirectSlow, WRAP_NONE, EOR) +rOP8 (52E1, DirectIndirectE1, WRAP_NONE, EOR) +rOP8 (52E0M1, DirectIndirectE0, WRAP_NONE, EOR) +rOP16(52E0M0, DirectIndirectE0, WRAP_NONE, EOR) +rOPM (52Slow, DirectIndirectSlow, WRAP_NONE, EOR) -rOP8 (41E1, DirectIndexedIndirectE1, WRAP_NONE, EOR) -rOP8 (41E0M1, DirectIndexedIndirectE0, WRAP_NONE, EOR) -rOP16(41E0M0, DirectIndexedIndirectE0, WRAP_NONE, EOR) -rOPM (41Slow, DirectIndexedIndirectSlow, WRAP_NONE, EOR) +rOP8 (41E1, DirectIndexedIndirectE1, WRAP_NONE, EOR) +rOP8 (41E0M1, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOP16(41E0M0, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOPM (41Slow, DirectIndexedIndirectSlow, WRAP_NONE, EOR) -rOP8 (51E1, DirectIndirectIndexedE1, WRAP_NONE, EOR) -rOP8 (51E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) -rOP16(51E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) -rOP8 (51E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) -rOP16(51E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) -rOPM (51Slow, DirectIndirectIndexedSlow, WRAP_NONE, EOR) +rOP8 (51E1, DirectIndirectIndexedE1, WRAP_NONE, EOR) +rOP8 (51E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP16(51E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP8 (51E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOP16(51E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOPM (51Slow, DirectIndirectIndexedSlow, WRAP_NONE, EOR) -rOP8 (47M1, DirectIndirectLong, WRAP_NONE, EOR) -rOP16(47M0, DirectIndirectLong, WRAP_NONE, EOR) -rOPM (47Slow, DirectIndirectLongSlow, WRAP_NONE, EOR) +rOP8 (47M1, DirectIndirectLong, WRAP_NONE, EOR) +rOP16(47M0, DirectIndirectLong, WRAP_NONE, EOR) +rOPM (47Slow, DirectIndirectLongSlow, WRAP_NONE, EOR) -rOP8 (57M1, DirectIndirectIndexedLong, WRAP_NONE, EOR) -rOP16(57M0, DirectIndirectIndexedLong, WRAP_NONE, EOR) -rOPM (57Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, EOR) +rOP8 (57M1, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOP16(57M0, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOPM (57Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, EOR) -rOP8 (4DM1, Absolute, WRAP_NONE, EOR) -rOP16(4DM0, Absolute, WRAP_NONE, EOR) -rOPM (4DSlow, AbsoluteSlow, WRAP_NONE, EOR) +rOP8 (4DM1, Absolute, WRAP_NONE, EOR) +rOP16(4DM0, Absolute, WRAP_NONE, EOR) +rOPM (4DSlow, AbsoluteSlow, WRAP_NONE, EOR) -rOP8 (5DM1X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) -rOP16(5DM0X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) -rOP8 (5DM1X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) -rOP16(5DM0X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) -rOPM (5DSlow, AbsoluteIndexedXSlow, WRAP_NONE, EOR) +rOP8 (5DM1X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP16(5DM0X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP8 (5DM1X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOP16(5DM0X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOPM (5DSlow, AbsoluteIndexedXSlow, WRAP_NONE, EOR) -rOP8 (59M1X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) -rOP16(59M0X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) -rOP8 (59M1X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) -rOP16(59M0X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) -rOPM (59Slow, AbsoluteIndexedYSlow, WRAP_NONE, EOR) +rOP8 (59M1X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP16(59M0X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP8 (59M1X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOP16(59M0X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOPM (59Slow, AbsoluteIndexedYSlow, WRAP_NONE, EOR) -rOP8 (4FM1, AbsoluteLong, WRAP_NONE, EOR) -rOP16(4FM0, AbsoluteLong, WRAP_NONE, EOR) -rOPM (4FSlow, AbsoluteLongSlow, WRAP_NONE, EOR) +rOP8 (4FM1, AbsoluteLong, WRAP_NONE, EOR) +rOP16(4FM0, AbsoluteLong, WRAP_NONE, EOR) +rOPM (4FSlow, AbsoluteLongSlow, WRAP_NONE, EOR) -rOP8 (5FM1, AbsoluteLongIndexedX, WRAP_NONE, EOR) -rOP16(5FM0, AbsoluteLongIndexedX, WRAP_NONE, EOR) -rOPM (5FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, EOR) +rOP8 (5FM1, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOP16(5FM0, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOPM (5FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, EOR) -rOP8 (43M1, StackRelative, WRAP_NONE, EOR) -rOP16(43M0, StackRelative, WRAP_NONE, EOR) -rOPM (43Slow, StackRelativeSlow, WRAP_NONE, EOR) +rOP8 (43M1, StackRelative, WRAP_NONE, EOR) +rOP16(43M0, StackRelative, WRAP_NONE, EOR) +rOPM (43Slow, StackRelativeSlow, WRAP_NONE, EOR) -rOP8 (53M1, StackRelativeIndirectIndexed, WRAP_NONE, EOR) -rOP16(53M0, StackRelativeIndirectIndexed, WRAP_NONE, EOR) -rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR) +rOP8 (53M1, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOP16(53M0, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR) + +/*****************************************************************************/ /* INC ********************************************************************* */ -static void Op1AM1 (void) -{ - AddCycles(ONE_CYCLE); +static void Op1AM1 (void){ + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.AL++; - SetZN(Registers.AL); + Registers.AL++; + SetZN (Registers.AL); } -static void Op1AM0 (void) -{ - AddCycles(ONE_CYCLE); +static void Op1AM0 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.A.W++; - SetZN(Registers.A.W); + Registers.A.W++; + SetZN (Registers.A.W); } -static void Op1ASlow (void) -{ - AddCycles(ONE_CYCLE); +static void Op1ASlow (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - - if (CheckMemory()) - { - Registers.AL++; - SetZN(Registers.AL); - } - else - { - Registers.A.W++; - SetZN(Registers.A.W); - } + if(CheckMemory()){ + Registers.AL++; + SetZN (Registers.AL); + } else { + Registers.A.W++; + SetZN (Registers.A.W); + } } -mOP8 (E6M1, Direct, WRAP_BANK, INC) -mOP16(E6M0, Direct, WRAP_BANK, INC) -mOPM (E6Slow, DirectSlow, WRAP_BANK, INC) +mOP8 (E6M1, Direct, WRAP_BANK, INC) +mOP16(E6M0, Direct, WRAP_BANK, INC) +mOPM (E6Slow, DirectSlow, WRAP_BANK, INC) -mOP8 (F6E1, DirectIndexedXE1, WRAP_BANK, INC) -mOP8 (F6E0M1, DirectIndexedXE0, WRAP_BANK, INC) -mOP16(F6E0M0, DirectIndexedXE0, WRAP_BANK, INC) -mOPM (F6Slow, DirectIndexedXSlow, WRAP_BANK, INC) +mOP8 (F6E1, DirectIndexedXE1, WRAP_BANK, INC) +mOP8 (F6E0M1, DirectIndexedXE0, WRAP_BANK, INC) +mOP16(F6E0M0, DirectIndexedXE0, WRAP_BANK, INC) +mOPM (F6Slow, DirectIndexedXSlow, WRAP_BANK, INC) -mOP8 (EEM1, Absolute, WRAP_NONE, INC) -mOP16(EEM0, Absolute, WRAP_NONE, INC) -mOPM (EESlow, AbsoluteSlow, WRAP_NONE, INC) +mOP8 (EEM1, Absolute, WRAP_NONE, INC) +mOP16(EEM0, Absolute, WRAP_NONE, INC) +mOPM (EESlow, AbsoluteSlow, WRAP_NONE, INC) -mOP8 (FEM1X1, AbsoluteIndexedXX1, WRAP_NONE, INC) -mOP16(FEM0X1, AbsoluteIndexedXX1, WRAP_NONE, INC) -mOP8 (FEM1X0, AbsoluteIndexedXX0, WRAP_NONE, INC) -mOP16(FEM0X0, AbsoluteIndexedXX0, WRAP_NONE, INC) -mOPM (FESlow, AbsoluteIndexedXSlow, WRAP_NONE, INC) +mOP8 (FEM1X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP16(FEM0X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP8 (FEM1X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOP16(FEM0X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOPM (FESlow, AbsoluteIndexedXSlow, WRAP_NONE, INC) +/*****************************************************************************/ /* LDA ********************************************************************* */ - -static void OpA9M1 (void) -{ - Registers.AL = Immediate8(READ); - SetZN(Registers.AL); +static void OpA9M1 (void) { + Registers.AL = Immediate8(READ); + SetZN(Registers.AL); } -static void OpA9M0 (void) -{ - Registers.A.W = Immediate16(READ); - SetZN(Registers.A.W); +static void OpA9M0 (void) { + Registers.A.W = Immediate16(READ); + SetZN(Registers.A.W); } -static void OpA9Slow (void) -{ - if (CheckMemory()) - { - Registers.AL = Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W = Immediate16Slow(READ); - SetZN(Registers.A.W); - } +static void OpA9Slow (void) { + if(CheckMemory()) { + Registers.AL = Immediate8Slow(READ); + SetZN(Registers.AL); + } else { + Registers.A.W = Immediate16Slow(READ); + SetZN(Registers.A.W); + } } -rOP8 (A5M1, Direct, WRAP_BANK, LDA) -rOP16(A5M0, Direct, WRAP_BANK, LDA) -rOPM (A5Slow, DirectSlow, WRAP_BANK, LDA) +rOP8 (A5M1, Direct, WRAP_BANK, LDA) +rOP16(A5M0, Direct, WRAP_BANK, LDA) +rOPM (A5Slow, DirectSlow, WRAP_BANK, LDA) -rOP8 (B5E1, DirectIndexedXE1, WRAP_BANK, LDA) -rOP8 (B5E0M1, DirectIndexedXE0, WRAP_BANK, LDA) -rOP16(B5E0M0, DirectIndexedXE0, WRAP_BANK, LDA) -rOPM (B5Slow, DirectIndexedXSlow, WRAP_BANK, LDA) +rOP8 (B5E1, DirectIndexedXE1, WRAP_BANK, LDA) +rOP8 (B5E0M1, DirectIndexedXE0, WRAP_BANK, LDA) +rOP16(B5E0M0, DirectIndexedXE0, WRAP_BANK, LDA) +rOPM (B5Slow, DirectIndexedXSlow, WRAP_BANK, LDA) -rOP8 (B2E1, DirectIndirectE1, WRAP_NONE, LDA) -rOP8 (B2E0M1, DirectIndirectE0, WRAP_NONE, LDA) -rOP16(B2E0M0, DirectIndirectE0, WRAP_NONE, LDA) -rOPM (B2Slow, DirectIndirectSlow, WRAP_NONE, LDA) +rOP8 (B2E1, DirectIndirectE1, WRAP_NONE, LDA) +rOP8 (B2E0M1, DirectIndirectE0, WRAP_NONE, LDA) +rOP16(B2E0M0, DirectIndirectE0, WRAP_NONE, LDA) +rOPM (B2Slow, DirectIndirectSlow, WRAP_NONE, LDA) -rOP8 (A1E1, DirectIndexedIndirectE1, WRAP_NONE, LDA) -rOP8 (A1E0M1, DirectIndexedIndirectE0, WRAP_NONE, LDA) -rOP16(A1E0M0, DirectIndexedIndirectE0, WRAP_NONE, LDA) -rOPM (A1Slow, DirectIndexedIndirectSlow, WRAP_NONE, LDA) +rOP8 (A1E1, DirectIndexedIndirectE1, WRAP_NONE, LDA) +rOP8 (A1E0M1, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOP16(A1E0M0, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOPM (A1Slow, DirectIndexedIndirectSlow, WRAP_NONE, LDA) -rOP8 (B1E1, DirectIndirectIndexedE1, WRAP_NONE, LDA) -rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) -rOP16(B1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) -rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) -rOP16(B1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) -rOPM (B1Slow, DirectIndirectIndexedSlow, WRAP_NONE, LDA) +rOP8 (B1E1, DirectIndirectIndexedE1, WRAP_NONE, LDA) +rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP16(B1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOP16(B1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOPM (B1Slow, DirectIndirectIndexedSlow, WRAP_NONE, LDA) -rOP8 (A7M1, DirectIndirectLong, WRAP_NONE, LDA) -rOP16(A7M0, DirectIndirectLong, WRAP_NONE, LDA) -rOPM (A7Slow, DirectIndirectLongSlow, WRAP_NONE, LDA) +rOP8 (A7M1, DirectIndirectLong, WRAP_NONE, LDA) +rOP16(A7M0, DirectIndirectLong, WRAP_NONE, LDA) +rOPM (A7Slow, DirectIndirectLongSlow, WRAP_NONE, LDA) -rOP8 (B7M1, DirectIndirectIndexedLong, WRAP_NONE, LDA) -rOP16(B7M0, DirectIndirectIndexedLong, WRAP_NONE, LDA) -rOPM (B7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, LDA) +rOP8 (B7M1, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOP16(B7M0, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOPM (B7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, LDA) -rOP8 (ADM1, Absolute, WRAP_NONE, LDA) -rOP16(ADM0, Absolute, WRAP_NONE, LDA) -rOPM (ADSlow, AbsoluteSlow, WRAP_NONE, LDA) +rOP8 (ADM1, Absolute, WRAP_NONE, LDA) +rOP16(ADM0, Absolute, WRAP_NONE, LDA) +rOPM (ADSlow, AbsoluteSlow, WRAP_NONE, LDA) -rOP8 (BDM1X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) -rOP16(BDM0X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) -rOP8 (BDM1X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) -rOP16(BDM0X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) -rOPM (BDSlow, AbsoluteIndexedXSlow, WRAP_NONE, LDA) +rOP8 (BDM1X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP16(BDM0X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP8 (BDM1X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOP16(BDM0X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOPM (BDSlow, AbsoluteIndexedXSlow, WRAP_NONE, LDA) -rOP8 (B9M1X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) -rOP16(B9M0X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) -rOP8 (B9M1X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) -rOP16(B9M0X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) -rOPM (B9Slow, AbsoluteIndexedYSlow, WRAP_NONE, LDA) +rOP8 (B9M1X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP16(B9M0X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP8 (B9M1X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOP16(B9M0X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOPM (B9Slow, AbsoluteIndexedYSlow, WRAP_NONE, LDA) -rOP8 (AFM1, AbsoluteLong, WRAP_NONE, LDA) -rOP16(AFM0, AbsoluteLong, WRAP_NONE, LDA) -rOPM (AFSlow, AbsoluteLongSlow, WRAP_NONE, LDA) +rOP8 (AFM1, AbsoluteLong, WRAP_NONE, LDA) +rOP16(AFM0, AbsoluteLong, WRAP_NONE, LDA) +rOPM (AFSlow, AbsoluteLongSlow, WRAP_NONE, LDA) -rOP8 (BFM1, AbsoluteLongIndexedX, WRAP_NONE, LDA) -rOP16(BFM0, AbsoluteLongIndexedX, WRAP_NONE, LDA) -rOPM (BFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, LDA) +rOP8 (BFM1, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOP16(BFM0, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOPM (BFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, LDA) -rOP8 (A3M1, StackRelative, WRAP_NONE, LDA) -rOP16(A3M0, StackRelative, WRAP_NONE, LDA) -rOPM (A3Slow, StackRelativeSlow, WRAP_NONE, LDA) +rOP8 (A3M1, StackRelative, WRAP_NONE, LDA) +rOP16(A3M0, StackRelative, WRAP_NONE, LDA) +rOPM (A3Slow, StackRelativeSlow, WRAP_NONE, LDA) -rOP8 (B3M1, StackRelativeIndirectIndexed, WRAP_NONE, LDA) -rOP16(B3M0, StackRelativeIndirectIndexed, WRAP_NONE, LDA) -rOPM (B3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA) +rOP8 (B3M1, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOP16(B3M0, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOPM (B3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA) + +/*****************************************************************************/ /* LDX ********************************************************************* */ - -static void OpA2X1 (void) -{ - Registers.XL = Immediate8(READ); - SetZN(Registers.XL); +static void OpA2X1 (void) { + Registers.XL = Immediate8(READ); + SetZN(Registers.XL); } -static void OpA2X0 (void) -{ - Registers.X.W = Immediate16(READ); - SetZN(Registers.X.W); +static void OpA2X0 (void) { + Registers.X.W = Immediate16(READ); + SetZN(Registers.X.W); } -static void OpA2Slow (void) -{ - if (CheckIndex()) - { - Registers.XL = Immediate8Slow(READ); - SetZN(Registers.XL); - } - else - { - Registers.X.W = Immediate16Slow(READ); - SetZN(Registers.X.W); - } +static void OpA2Slow (void) { + if(CheckIndex()) { + Registers.XL = Immediate8Slow(READ); + SetZN(Registers.XL); + } else { + Registers.X.W = Immediate16Slow(READ); + SetZN(Registers.X.W); + } } -rOP8 (A6X1, Direct, WRAP_BANK, LDX) -rOP16(A6X0, Direct, WRAP_BANK, LDX) -rOPX (A6Slow, DirectSlow, WRAP_BANK, LDX) +rOP8 (A6X1, Direct, WRAP_BANK, LDX) +rOP16(A6X0, Direct, WRAP_BANK, LDX) +rOPX (A6Slow, DirectSlow, WRAP_BANK, LDX) -rOP8 (B6E1, DirectIndexedYE1, WRAP_BANK, LDX) -rOP8 (B6E0X1, DirectIndexedYE0, WRAP_BANK, LDX) -rOP16(B6E0X0, DirectIndexedYE0, WRAP_BANK, LDX) -rOPX (B6Slow, DirectIndexedYSlow, WRAP_BANK, LDX) +rOP8 (B6E1, DirectIndexedYE1, WRAP_BANK, LDX) +rOP8 (B6E0X1, DirectIndexedYE0, WRAP_BANK, LDX) +rOP16(B6E0X0, DirectIndexedYE0, WRAP_BANK, LDX) +rOPX (B6Slow, DirectIndexedYSlow, WRAP_BANK, LDX) -rOP8 (AEX1, Absolute, WRAP_BANK, LDX) -rOP16(AEX0, Absolute, WRAP_BANK, LDX) -rOPX (AESlow, AbsoluteSlow, WRAP_BANK, LDX) +rOP8 (AEX1, Absolute, WRAP_BANK, LDX) +rOP16(AEX0, Absolute, WRAP_BANK, LDX) +rOPX (AESlow, AbsoluteSlow, WRAP_BANK, LDX) -rOP8 (BEX1, AbsoluteIndexedYX1, WRAP_BANK, LDX) -rOP16(BEX0, AbsoluteIndexedYX0, WRAP_BANK, LDX) -rOPX (BESlow, AbsoluteIndexedYSlow, WRAP_BANK, LDX) +rOP8 (BEX1, AbsoluteIndexedYX1, WRAP_BANK, LDX) +rOP16(BEX0, AbsoluteIndexedYX0, WRAP_BANK, LDX) +rOPX (BESlow, AbsoluteIndexedYSlow, WRAP_BANK, LDX) + +/*****************************************************************************/ /* LDY ********************************************************************* */ - -static void OpA0X1 (void) -{ - Registers.YL = Immediate8(READ); - SetZN(Registers.YL); +static void OpA0X1 (void) { + Registers.YL = Immediate8(READ); + SetZN(Registers.YL); } -static void OpA0X0 (void) -{ - Registers.Y.W = Immediate16(READ); - SetZN(Registers.Y.W); +static void OpA0X0 (void) { + Registers.Y.W = Immediate16(READ); + SetZN(Registers.Y.W); } -static void OpA0Slow (void) -{ - if (CheckIndex()) - { - Registers.YL = Immediate8Slow(READ); - SetZN(Registers.YL); - } - else - { - Registers.Y.W = Immediate16Slow(READ); - SetZN(Registers.Y.W); - } +static void OpA0Slow (void) { + if(CheckIndex()) { + Registers.YL = Immediate8Slow(READ); + SetZN(Registers.YL); + } else { + Registers.Y.W = Immediate16Slow(READ); + SetZN(Registers.Y.W); + } } -rOP8 (A4X1, Direct, WRAP_BANK, LDY) -rOP16(A4X0, Direct, WRAP_BANK, LDY) -rOPX (A4Slow, DirectSlow, WRAP_BANK, LDY) +rOP8 (A4X1, Direct, WRAP_BANK, LDY) +rOP16(A4X0, Direct, WRAP_BANK, LDY) +rOPX (A4Slow, DirectSlow, WRAP_BANK, LDY) -rOP8 (B4E1, DirectIndexedXE1, WRAP_BANK, LDY) -rOP8 (B4E0X1, DirectIndexedXE0, WRAP_BANK, LDY) -rOP16(B4E0X0, DirectIndexedXE0, WRAP_BANK, LDY) -rOPX (B4Slow, DirectIndexedXSlow, WRAP_BANK, LDY) +rOP8 (B4E1, DirectIndexedXE1, WRAP_BANK, LDY) +rOP8 (B4E0X1, DirectIndexedXE0, WRAP_BANK, LDY) +rOP16(B4E0X0, DirectIndexedXE0, WRAP_BANK, LDY) +rOPX (B4Slow, DirectIndexedXSlow, WRAP_BANK, LDY) -rOP8 (ACX1, Absolute, WRAP_BANK, LDY) -rOP16(ACX0, Absolute, WRAP_BANK, LDY) -rOPX (ACSlow, AbsoluteSlow, WRAP_BANK, LDY) +rOP8 (ACX1, Absolute, WRAP_BANK, LDY) +rOP16(ACX0, Absolute, WRAP_BANK, LDY) +rOPX (ACSlow, AbsoluteSlow, WRAP_BANK, LDY) -rOP8 (BCX1, AbsoluteIndexedXX1, WRAP_BANK, LDY) -rOP16(BCX0, AbsoluteIndexedXX0, WRAP_BANK, LDY) -rOPX (BCSlow, AbsoluteIndexedXSlow, WRAP_BANK, LDY) +rOP8 (BCX1, AbsoluteIndexedXX1, WRAP_BANK, LDY) +rOP16(BCX0, AbsoluteIndexedXX0, WRAP_BANK, LDY) +rOPX (BCSlow, AbsoluteIndexedXSlow, WRAP_BANK, LDY) + +/*****************************************************************************/ /* LSR ********************************************************************* */ - -static void Op4AM1 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = Registers.AL & 1; - Registers.AL >>= 1; - SetZN(Registers.AL); +static void Op4AM1 (void) { + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN (Registers.AL); } -static void Op4AM0 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = Registers.A.W & 1; - Registers.A.W >>= 1; - SetZN(Registers.A.W); +static void Op4AM0 (void) { + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN (Registers.A.W); } -static void Op4ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - ICPU._Carry = Registers.AL & 1; - Registers.AL >>= 1; - SetZN(Registers.AL); - } - else - { - ICPU._Carry = Registers.A.W & 1; - Registers.A.W >>= 1; - SetZN(Registers.A.W); - } +static void Op4ASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckMemory()){ + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN (Registers.AL); + } else { + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN (Registers.A.W); + } } -mOP8 (46M1, Direct, WRAP_BANK, LSR) -mOP16(46M0, Direct, WRAP_BANK, LSR) -mOPM (46Slow, DirectSlow, WRAP_BANK, LSR) +mOP8 (46M1, Direct, WRAP_BANK, LSR) +mOP16(46M0, Direct, WRAP_BANK, LSR) +mOPM (46Slow, DirectSlow, WRAP_BANK, LSR) -mOP8 (56E1, DirectIndexedXE1, WRAP_BANK, LSR) -mOP8 (56E0M1, DirectIndexedXE0, WRAP_BANK, LSR) -mOP16(56E0M0, DirectIndexedXE0, WRAP_BANK, LSR) -mOPM (56Slow, DirectIndexedXSlow, WRAP_BANK, LSR) +mOP8 (56E1, DirectIndexedXE1, WRAP_BANK, LSR) +mOP8 (56E0M1, DirectIndexedXE0, WRAP_BANK, LSR) +mOP16(56E0M0, DirectIndexedXE0, WRAP_BANK, LSR) +mOPM (56Slow, DirectIndexedXSlow, WRAP_BANK, LSR) -mOP8 (4EM1, Absolute, WRAP_NONE, LSR) -mOP16(4EM0, Absolute, WRAP_NONE, LSR) -mOPM (4ESlow, AbsoluteSlow, WRAP_NONE, LSR) +mOP8 (4EM1, Absolute, WRAP_NONE, LSR) +mOP16(4EM0, Absolute, WRAP_NONE, LSR) +mOPM (4ESlow, AbsoluteSlow, WRAP_NONE, LSR) -mOP8 (5EM1X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) -mOP16(5EM0X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) -mOP8 (5EM1X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) -mOP16(5EM0X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) -mOPM (5ESlow, AbsoluteIndexedXSlow, WRAP_NONE, LSR) +mOP8 (5EM1X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP16(5EM0X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP8 (5EM1X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOP16(5EM0X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOPM (5ESlow, AbsoluteIndexedXSlow, WRAP_NONE, LSR) + +/*****************************************************************************/ /* ORA ********************************************************************* */ - -static void Op09M1 (void) -{ - Registers.AL |= Immediate8(READ); - SetZN(Registers.AL); +static void Op09M1 (void) { + Registers.AL |= Immediate8(READ); + SetZN (Registers.AL); } -static void Op09M0 (void) -{ - Registers.A.W |= Immediate16(READ); - SetZN(Registers.A.W); +static void Op09M0 (void) { + Registers.A.W |= Immediate16(READ); + SetZN (Registers.A.W); } -static void Op09Slow (void) -{ - if (CheckMemory()) - { - Registers.AL |= Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W |= Immediate16Slow(READ); - SetZN(Registers.A.W); - } +static void Op09Slow (void) { + if(CheckMemory()){ + Registers.AL |= Immediate8Slow(READ); + SetZN (Registers.AL); + } else { + Registers.A.W |= Immediate16Slow(READ); + SetZN (Registers.A.W); + } } -rOP8 (05M1, Direct, WRAP_BANK, ORA) -rOP16(05M0, Direct, WRAP_BANK, ORA) -rOPM (05Slow, DirectSlow, WRAP_BANK, ORA) +rOP8 (05M1, Direct, WRAP_BANK, ORA) +rOP16(05M0, Direct, WRAP_BANK, ORA) +rOPM (05Slow, DirectSlow, WRAP_BANK, ORA) -rOP8 (15E1, DirectIndexedXE1, WRAP_BANK, ORA) -rOP8 (15E0M1, DirectIndexedXE0, WRAP_BANK, ORA) -rOP16(15E0M0, DirectIndexedXE0, WRAP_BANK, ORA) -rOPM (15Slow, DirectIndexedXSlow, WRAP_BANK, ORA) +rOP8 (15E1, DirectIndexedXE1, WRAP_BANK, ORA) +rOP8 (15E0M1, DirectIndexedXE0, WRAP_BANK, ORA) +rOP16(15E0M0, DirectIndexedXE0, WRAP_BANK, ORA) +rOPM (15Slow, DirectIndexedXSlow, WRAP_BANK, ORA) -rOP8 (12E1, DirectIndirectE1, WRAP_NONE, ORA) -rOP8 (12E0M1, DirectIndirectE0, WRAP_NONE, ORA) -rOP16(12E0M0, DirectIndirectE0, WRAP_NONE, ORA) -rOPM (12Slow, DirectIndirectSlow, WRAP_NONE, ORA) +rOP8 (12E1, DirectIndirectE1, WRAP_NONE, ORA) +rOP8 (12E0M1, DirectIndirectE0, WRAP_NONE, ORA) +rOP16(12E0M0, DirectIndirectE0, WRAP_NONE, ORA) +rOPM (12Slow, DirectIndirectSlow, WRAP_NONE, ORA) -rOP8 (01E1, DirectIndexedIndirectE1, WRAP_NONE, ORA) -rOP8 (01E0M1, DirectIndexedIndirectE0, WRAP_NONE, ORA) -rOP16(01E0M0, DirectIndexedIndirectE0, WRAP_NONE, ORA) -rOPM (01Slow, DirectIndexedIndirectSlow, WRAP_NONE, ORA) +rOP8 (01E1, DirectIndexedIndirectE1, WRAP_NONE, ORA) +rOP8 (01E0M1, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOP16(01E0M0, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOPM (01Slow, DirectIndexedIndirectSlow, WRAP_NONE, ORA) -rOP8 (11E1, DirectIndirectIndexedE1, WRAP_NONE, ORA) -rOP8 (11E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) -rOP16(11E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) -rOP8 (11E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) -rOP16(11E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) -rOPM (11Slow, DirectIndirectIndexedSlow, WRAP_NONE, ORA) +rOP8 (11E1, DirectIndirectIndexedE1, WRAP_NONE, ORA) +rOP8 (11E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP16(11E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP8 (11E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOP16(11E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOPM (11Slow, DirectIndirectIndexedSlow, WRAP_NONE, ORA) -rOP8 (07M1, DirectIndirectLong, WRAP_NONE, ORA) -rOP16(07M0, DirectIndirectLong, WRAP_NONE, ORA) -rOPM (07Slow, DirectIndirectLongSlow, WRAP_NONE, ORA) +rOP8 (07M1, DirectIndirectLong, WRAP_NONE, ORA) +rOP16(07M0, DirectIndirectLong, WRAP_NONE, ORA) +rOPM (07Slow, DirectIndirectLongSlow, WRAP_NONE, ORA) -rOP8 (17M1, DirectIndirectIndexedLong, WRAP_NONE, ORA) -rOP16(17M0, DirectIndirectIndexedLong, WRAP_NONE, ORA) -rOPM (17Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ORA) +rOP8 (17M1, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOP16(17M0, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOPM (17Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ORA) -rOP8 (0DM1, Absolute, WRAP_NONE, ORA) -rOP16(0DM0, Absolute, WRAP_NONE, ORA) -rOPM (0DSlow, AbsoluteSlow, WRAP_NONE, ORA) +rOP8 (0DM1, Absolute, WRAP_NONE, ORA) +rOP16(0DM0, Absolute, WRAP_NONE, ORA) +rOPM (0DSlow, AbsoluteSlow, WRAP_NONE, ORA) -rOP8 (1DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) -rOP16(1DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) -rOP8 (1DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) -rOP16(1DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) -rOPM (1DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ORA) +rOP8 (1DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP16(1DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP8 (1DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOP16(1DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOPM (1DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ORA) -rOP8 (19M1X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) -rOP16(19M0X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) -rOP8 (19M1X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) -rOP16(19M0X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) -rOPM (19Slow, AbsoluteIndexedYSlow, WRAP_NONE, ORA) +rOP8 (19M1X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP16(19M0X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP8 (19M1X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOP16(19M0X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOPM (19Slow, AbsoluteIndexedYSlow, WRAP_NONE, ORA) -rOP8 (0FM1, AbsoluteLong, WRAP_NONE, ORA) -rOP16(0FM0, AbsoluteLong, WRAP_NONE, ORA) -rOPM (0FSlow, AbsoluteLongSlow, WRAP_NONE, ORA) +rOP8 (0FM1, AbsoluteLong, WRAP_NONE, ORA) +rOP16(0FM0, AbsoluteLong, WRAP_NONE, ORA) +rOPM (0FSlow, AbsoluteLongSlow, WRAP_NONE, ORA) -rOP8 (1FM1, AbsoluteLongIndexedX, WRAP_NONE, ORA) -rOP16(1FM0, AbsoluteLongIndexedX, WRAP_NONE, ORA) -rOPM (1FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ORA) +rOP8 (1FM1, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOP16(1FM0, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOPM (1FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ORA) -rOP8 (03M1, StackRelative, WRAP_NONE, ORA) -rOP16(03M0, StackRelative, WRAP_NONE, ORA) -rOPM (03Slow, StackRelativeSlow, WRAP_NONE, ORA) +rOP8 (03M1, StackRelative, WRAP_NONE, ORA) +rOP16(03M0, StackRelative, WRAP_NONE, ORA) +rOPM (03Slow, StackRelativeSlow, WRAP_NONE, ORA) -rOP8 (13M1, StackRelativeIndirectIndexed, WRAP_NONE, ORA) -rOP16(13M0, StackRelativeIndirectIndexed, WRAP_NONE, ORA) -rOPM (13Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA) +rOP8 (13M1, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOP16(13M0, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOPM (13Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA) + +/*****************************************************************************/ /* ROL ********************************************************************* */ - -static void Op2AM1 (void) -{ - AddCycles(ONE_CYCLE); - uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x100; - Registers.AL = (uint8) w; - SetZN(Registers.AL); +static void Op2AM1 (void) { + AddCycles(ONE_CYCLE); + uint16 w = (((uint16)Registers.AL)<<1) | CheckCarry(); + ICPU._Carry = w>=0x100; + Registers.AL = (uint8)w; + SetZN (Registers.AL); } -static void Op2AM0 (void) -{ - AddCycles(ONE_CYCLE); - uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x10000; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); +static void Op2AM0 (void) { + AddCycles(ONE_CYCLE); + uint32 w = (((uint32)Registers.A.W)<<1) | CheckCarry(); + ICPU._Carry = w>=0x10000; + Registers.A.W = (uint16)w; + SetZN (Registers.A.W); } -static void Op2ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x100; - Registers.AL = (uint8) w; - SetZN(Registers.AL); - } - else - { - uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x10000; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); - } +static void Op2ASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckMemory()){ + uint16 w = (((uint16)Registers.AL)<<1) | CheckCarry(); + ICPU._Carry = w>=0x100; + Registers.AL = (uint8)w; + SetZN (Registers.AL); + } else { + uint32 w = (((uint32)Registers.A.W)<<1) | CheckCarry(); + ICPU._Carry = w>=0x10000; + Registers.A.W = (uint16)w; + SetZN (Registers.A.W); + } } -mOP8 (26M1, Direct, WRAP_BANK, ROL) -mOP16(26M0, Direct, WRAP_BANK, ROL) -mOPM (26Slow, DirectSlow, WRAP_BANK, ROL) +mOP8 (26M1, Direct, WRAP_BANK, ROL) +mOP16(26M0, Direct, WRAP_BANK, ROL) +mOPM (26Slow, DirectSlow, WRAP_BANK, ROL) -mOP8 (36E1, DirectIndexedXE1, WRAP_BANK, ROL) -mOP8 (36E0M1, DirectIndexedXE0, WRAP_BANK, ROL) -mOP16(36E0M0, DirectIndexedXE0, WRAP_BANK, ROL) -mOPM (36Slow, DirectIndexedXSlow, WRAP_BANK, ROL) +mOP8 (36E1, DirectIndexedXE1, WRAP_BANK, ROL) +mOP8 (36E0M1, DirectIndexedXE0, WRAP_BANK, ROL) +mOP16(36E0M0, DirectIndexedXE0, WRAP_BANK, ROL) +mOPM (36Slow, DirectIndexedXSlow, WRAP_BANK, ROL) -mOP8 (2EM1, Absolute, WRAP_NONE, ROL) -mOP16(2EM0, Absolute, WRAP_NONE, ROL) -mOPM (2ESlow, AbsoluteSlow, WRAP_NONE, ROL) +mOP8 (2EM1, Absolute, WRAP_NONE, ROL) +mOP16(2EM0, Absolute, WRAP_NONE, ROL) +mOPM (2ESlow, AbsoluteSlow, WRAP_NONE, ROL) -mOP8 (3EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) -mOP16(3EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) -mOP8 (3EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) -mOP16(3EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) -mOPM (3ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROL) +mOP8 (3EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP16(3EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP8 (3EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOP16(3EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOPM (3ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROL) + +/*****************************************************************************/ /* ROR ********************************************************************* */ - -static void Op6AM1 (void) -{ - AddCycles(ONE_CYCLE); - uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); - ICPU._Carry = w & 1; - w >>= 1; - Registers.AL = (uint8) w; - SetZN(Registers.AL); +static void Op6AM1 (void) { + AddCycles(ONE_CYCLE); + uint16 w = ((uint16)Registers.AL) | (((uint16)CheckCarry())<<8); + ICPU._Carry = w&1; + w>>=1; + Registers.AL = (uint8)w; + SetZN (Registers.AL); } -static void Op6AM0 (void) -{ - AddCycles(ONE_CYCLE); - uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); - ICPU._Carry = w & 1; - w >>= 1; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); +static void Op6AM0 (void) { + AddCycles(ONE_CYCLE); + uint32 w = ((uint32)Registers.A.W) | (((uint32)CheckCarry())<<16); + ICPU._Carry = w&1; + w>>=1; + Registers.A.W = (uint16)w; + SetZN (Registers.A.W); } -static void Op6ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); - ICPU._Carry = w & 1; - w >>= 1; - Registers.AL = (uint8) w; - SetZN(Registers.AL); - } - else - { - uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); - ICPU._Carry = w & 1; - w >>= 1; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); - } +static void Op6ASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckMemory()){ + uint16 w = ((uint16)Registers.AL) | (((uint16)CheckCarry())<<8); + ICPU._Carry = w&1; + w>>=1; + Registers.AL = (uint8)w; + SetZN (Registers.AL); + } else { + uint32 w = ((uint32)Registers.A.W) | (((uint32)CheckCarry())<<16); + ICPU._Carry = w&1; + w>>=1; + Registers.A.W = (uint16)w; + SetZN (Registers.A.W); + } } -mOP8 (66M1, Direct, WRAP_BANK, ROR) -mOP16(66M0, Direct, WRAP_BANK, ROR) -mOPM (66Slow, DirectSlow, WRAP_BANK, ROR) +mOP8 (66M1, Direct, WRAP_BANK, ROR) +mOP16(66M0, Direct, WRAP_BANK, ROR) +mOPM (66Slow, DirectSlow, WRAP_BANK, ROR) -mOP8 (76E1, DirectIndexedXE1, WRAP_BANK, ROR) -mOP8 (76E0M1, DirectIndexedXE0, WRAP_BANK, ROR) -mOP16(76E0M0, DirectIndexedXE0, WRAP_BANK, ROR) -mOPM (76Slow, DirectIndexedXSlow, WRAP_BANK, ROR) +mOP8 (76E1, DirectIndexedXE1, WRAP_BANK, ROR) +mOP8 (76E0M1, DirectIndexedXE0, WRAP_BANK, ROR) +mOP16(76E0M0, DirectIndexedXE0, WRAP_BANK, ROR) +mOPM (76Slow, DirectIndexedXSlow, WRAP_BANK, ROR) -mOP8 (6EM1, Absolute, WRAP_NONE, ROR) -mOP16(6EM0, Absolute, WRAP_NONE, ROR) -mOPM (6ESlow, AbsoluteSlow, WRAP_NONE, ROR) +mOP8 (6EM1, Absolute, WRAP_NONE, ROR) +mOP16(6EM0, Absolute, WRAP_NONE, ROR) +mOPM (6ESlow, AbsoluteSlow, WRAP_NONE, ROR) -mOP8 (7EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) -mOP16(7EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) -mOP8 (7EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) -mOP16(7EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) -mOPM (7ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROR) +mOP8 (7EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP16(7EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP8 (7EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOP16(7EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOPM (7ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROR) + +/*****************************************************************************/ /* SBC ********************************************************************* */ - -static void OpE9M1 (void) -{ - SBC(Immediate8(READ)); +static void OpE9M1 (void) { + SBC(Immediate8(READ)); } -static void OpE9M0 (void) -{ - SBC(Immediate16(READ)); +static void OpE9M0 (void) { + SBC(Immediate16(READ)); } -static void OpE9Slow (void) -{ - if (CheckMemory()) - SBC(Immediate8Slow(READ)); - else - SBC(Immediate16Slow(READ)); +static void OpE9Slow (void) { + if(CheckMemory()) { + SBC(Immediate8Slow(READ)); + } else { + SBC(Immediate16Slow(READ)); + } } -rOP8 (E5M1, Direct, WRAP_BANK, SBC) -rOP16(E5M0, Direct, WRAP_BANK, SBC) -rOPM (E5Slow, DirectSlow, WRAP_BANK, SBC) +rOP8 (E5M1, Direct, WRAP_BANK, SBC) +rOP16(E5M0, Direct, WRAP_BANK, SBC) +rOPM (E5Slow, DirectSlow, WRAP_BANK, SBC) -rOP8 (F5E1, DirectIndexedXE1, WRAP_BANK, SBC) -rOP8 (F5E0M1, DirectIndexedXE0, WRAP_BANK, SBC) -rOP16(F5E0M0, DirectIndexedXE0, WRAP_BANK, SBC) -rOPM (F5Slow, DirectIndexedXSlow, WRAP_BANK, SBC) +rOP8 (F5E1, DirectIndexedXE1, WRAP_BANK, SBC) +rOP8 (F5E0M1, DirectIndexedXE0, WRAP_BANK, SBC) +rOP16(F5E0M0, DirectIndexedXE0, WRAP_BANK, SBC) +rOPM (F5Slow, DirectIndexedXSlow, WRAP_BANK, SBC) -rOP8 (F2E1, DirectIndirectE1, WRAP_NONE, SBC) -rOP8 (F2E0M1, DirectIndirectE0, WRAP_NONE, SBC) -rOP16(F2E0M0, DirectIndirectE0, WRAP_NONE, SBC) -rOPM (F2Slow, DirectIndirectSlow, WRAP_NONE, SBC) +rOP8 (F2E1, DirectIndirectE1, WRAP_NONE, SBC) +rOP8 (F2E0M1, DirectIndirectE0, WRAP_NONE, SBC) +rOP16(F2E0M0, DirectIndirectE0, WRAP_NONE, SBC) +rOPM (F2Slow, DirectIndirectSlow, WRAP_NONE, SBC) -rOP8 (E1E1, DirectIndexedIndirectE1, WRAP_NONE, SBC) -rOP8 (E1E0M1, DirectIndexedIndirectE0, WRAP_NONE, SBC) -rOP16(E1E0M0, DirectIndexedIndirectE0, WRAP_NONE, SBC) -rOPM (E1Slow, DirectIndexedIndirectSlow, WRAP_NONE, SBC) +rOP8 (E1E1, DirectIndexedIndirectE1, WRAP_NONE, SBC) +rOP8 (E1E0M1, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOP16(E1E0M0, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOPM (E1Slow, DirectIndexedIndirectSlow, WRAP_NONE, SBC) -rOP8 (F1E1, DirectIndirectIndexedE1, WRAP_NONE, SBC) -rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) -rOP16(F1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) -rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) -rOP16(F1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) -rOPM (F1Slow, DirectIndirectIndexedSlow, WRAP_NONE, SBC) +rOP8 (F1E1, DirectIndirectIndexedE1, WRAP_NONE, SBC) +rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP16(F1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOP16(F1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOPM (F1Slow, DirectIndirectIndexedSlow, WRAP_NONE, SBC) -rOP8 (E7M1, DirectIndirectLong, WRAP_NONE, SBC) -rOP16(E7M0, DirectIndirectLong, WRAP_NONE, SBC) -rOPM (E7Slow, DirectIndirectLongSlow, WRAP_NONE, SBC) +rOP8 (E7M1, DirectIndirectLong, WRAP_NONE, SBC) +rOP16(E7M0, DirectIndirectLong, WRAP_NONE, SBC) +rOPM (E7Slow, DirectIndirectLongSlow, WRAP_NONE, SBC) -rOP8 (F7M1, DirectIndirectIndexedLong, WRAP_NONE, SBC) -rOP16(F7M0, DirectIndirectIndexedLong, WRAP_NONE, SBC) -rOPM (F7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, SBC) +rOP8 (F7M1, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOP16(F7M0, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOPM (F7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, SBC) -rOP8 (EDM1, Absolute, WRAP_NONE, SBC) -rOP16(EDM0, Absolute, WRAP_NONE, SBC) -rOPM (EDSlow, AbsoluteSlow, WRAP_NONE, SBC) +rOP8 (EDM1, Absolute, WRAP_NONE, SBC) +rOP16(EDM0, Absolute, WRAP_NONE, SBC) +rOPM (EDSlow, AbsoluteSlow, WRAP_NONE, SBC) -rOP8 (FDM1X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) -rOP16(FDM0X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) -rOP8 (FDM1X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) -rOP16(FDM0X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) -rOPM (FDSlow, AbsoluteIndexedXSlow, WRAP_NONE, SBC) +rOP8 (FDM1X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP16(FDM0X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP8 (FDM1X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOP16(FDM0X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOPM (FDSlow, AbsoluteIndexedXSlow, WRAP_NONE, SBC) -rOP8 (F9M1X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) -rOP16(F9M0X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) -rOP8 (F9M1X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) -rOP16(F9M0X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) -rOPM (F9Slow, AbsoluteIndexedYSlow, WRAP_NONE, SBC) +rOP8 (F9M1X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP16(F9M0X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP8 (F9M1X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOP16(F9M0X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOPM (F9Slow, AbsoluteIndexedYSlow, WRAP_NONE, SBC) -rOP8 (EFM1, AbsoluteLong, WRAP_NONE, SBC) -rOP16(EFM0, AbsoluteLong, WRAP_NONE, SBC) -rOPM (EFSlow, AbsoluteLongSlow, WRAP_NONE, SBC) +rOP8 (EFM1, AbsoluteLong, WRAP_NONE, SBC) +rOP16(EFM0, AbsoluteLong, WRAP_NONE, SBC) +rOPM (EFSlow, AbsoluteLongSlow, WRAP_NONE, SBC) -rOP8 (FFM1, AbsoluteLongIndexedX, WRAP_NONE, SBC) -rOP16(FFM0, AbsoluteLongIndexedX, WRAP_NONE, SBC) -rOPM (FFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, SBC) +rOP8 (FFM1, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOP16(FFM0, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOPM (FFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, SBC) -rOP8 (E3M1, StackRelative, WRAP_NONE, SBC) -rOP16(E3M0, StackRelative, WRAP_NONE, SBC) -rOPM (E3Slow, StackRelativeSlow, WRAP_NONE, SBC) +rOP8 (E3M1, StackRelative, WRAP_NONE, SBC) +rOP16(E3M0, StackRelative, WRAP_NONE, SBC) +rOPM (E3Slow, StackRelativeSlow, WRAP_NONE, SBC) -rOP8 (F3M1, StackRelativeIndirectIndexed, WRAP_NONE, SBC) -rOP16(F3M0, StackRelativeIndirectIndexed, WRAP_NONE, SBC) -rOPM (F3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC) +rOP8 (F3M1, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOP16(F3M0, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOPM (F3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC) + +/*****************************************************************************/ /* STA ********************************************************************* */ +wOP8 (85M1, Direct, WRAP_BANK, STA) +wOP16(85M0, Direct, WRAP_BANK, STA) +wOPM (85Slow, DirectSlow, WRAP_BANK, STA) -wOP8 (85M1, Direct, WRAP_BANK, STA) -wOP16(85M0, Direct, WRAP_BANK, STA) -wOPM (85Slow, DirectSlow, WRAP_BANK, STA) +wOP8 (95E1, DirectIndexedXE1, WRAP_BANK, STA) +wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) +wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) +wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) -wOP8 (95E1, DirectIndexedXE1, WRAP_BANK, STA) -wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) -wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) -wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) +wOP8 (92E1, DirectIndirectE1, WRAP_NONE, STA) +wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) +wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) +wOPM (92Slow, DirectIndirectSlow, WRAP_NONE, STA) -wOP8 (92E1, DirectIndirectE1, WRAP_NONE, STA) -wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) -wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) -wOPM (92Slow, DirectIndirectSlow, WRAP_NONE, STA) +wOP8 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) +wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) -wOP8 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) -wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) -wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) -wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) +wOP8 (91E1, DirectIndirectIndexedE1, WRAP_NONE, STA) +wOP8 (91E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP16(91E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP8 (91E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOP16(91E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOPM (91Slow, DirectIndirectIndexedSlow, WRAP_NONE, STA) -wOP8 (91E1, DirectIndirectIndexedE1, WRAP_NONE, STA) -wOP8 (91E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) -wOP16(91E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) -wOP8 (91E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) -wOP16(91E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) -wOPM (91Slow, DirectIndirectIndexedSlow, WRAP_NONE, STA) +wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) +wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) +wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) -wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) -wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) -wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) +wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) -wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) -wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) -wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) +wOP8 (8DM1, Absolute, WRAP_NONE, STA) +wOP16(8DM0, Absolute, WRAP_NONE, STA) +wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) -wOP8 (8DM1, Absolute, WRAP_NONE, STA) -wOP16(8DM0, Absolute, WRAP_NONE, STA) -wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) +wOP8 (9DM1X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP16(9DM0X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP8 (9DM1X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOP16(9DM0X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOPM (9DSlow, AbsoluteIndexedXSlow, WRAP_NONE, STA) -wOP8 (9DM1X1, AbsoluteIndexedXX1, WRAP_NONE, STA) -wOP16(9DM0X1, AbsoluteIndexedXX1, WRAP_NONE, STA) -wOP8 (9DM1X0, AbsoluteIndexedXX0, WRAP_NONE, STA) -wOP16(9DM0X0, AbsoluteIndexedXX0, WRAP_NONE, STA) -wOPM (9DSlow, AbsoluteIndexedXSlow, WRAP_NONE, STA) +wOP8 (99M1X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP16(99M0X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP8 (99M1X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOP16(99M0X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOPM (99Slow, AbsoluteIndexedYSlow, WRAP_NONE, STA) -wOP8 (99M1X1, AbsoluteIndexedYX1, WRAP_NONE, STA) -wOP16(99M0X1, AbsoluteIndexedYX1, WRAP_NONE, STA) -wOP8 (99M1X0, AbsoluteIndexedYX0, WRAP_NONE, STA) -wOP16(99M0X0, AbsoluteIndexedYX0, WRAP_NONE, STA) -wOPM (99Slow, AbsoluteIndexedYSlow, WRAP_NONE, STA) +wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) +wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) +wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) -wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) -wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) -wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) +wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) -wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) -wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) -wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) +wOP8 (83M1, StackRelative, WRAP_NONE, STA) +wOP16(83M0, StackRelative, WRAP_NONE, STA) +wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) -wOP8 (83M1, StackRelative, WRAP_NONE, STA) -wOP16(83M0, StackRelative, WRAP_NONE, STA) -wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) +wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOPM (93Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, STA) -wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) -wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) -wOPM (93Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, STA) +/*****************************************************************************/ /* STX ********************************************************************* */ -wOP8 (86X1, Direct, WRAP_BANK, STX) -wOP16(86X0, Direct, WRAP_BANK, STX) -wOPX (86Slow, DirectSlow, WRAP_BANK, STX) +wOP8 (86X1, Direct, WRAP_BANK, STX) +wOP16(86X0, Direct, WRAP_BANK, STX) +wOPX (86Slow, DirectSlow, WRAP_BANK, STX) -wOP8 (96E1, DirectIndexedYE1, WRAP_BANK, STX) -wOP8 (96E0X1, DirectIndexedYE0, WRAP_BANK, STX) -wOP16(96E0X0, DirectIndexedYE0, WRAP_BANK, STX) -wOPX (96Slow, DirectIndexedYSlow, WRAP_BANK, STX) +wOP8 (96E1, DirectIndexedYE1, WRAP_BANK, STX) +wOP8 (96E0X1, DirectIndexedYE0, WRAP_BANK, STX) +wOP16(96E0X0, DirectIndexedYE0, WRAP_BANK, STX) +wOPX (96Slow, DirectIndexedYSlow, WRAP_BANK, STX) -wOP8 (8EX1, Absolute, WRAP_BANK, STX) -wOP16(8EX0, Absolute, WRAP_BANK, STX) -wOPX (8ESlow, AbsoluteSlow, WRAP_BANK, STX) +wOP8 (8EX1, Absolute, WRAP_BANK, STX) +wOP16(8EX0, Absolute, WRAP_BANK, STX) +wOPX (8ESlow, AbsoluteSlow, WRAP_BANK, STX) + +/*****************************************************************************/ /* STY ********************************************************************* */ -wOP8 (84X1, Direct, WRAP_BANK, STY) -wOP16(84X0, Direct, WRAP_BANK, STY) -wOPX (84Slow, DirectSlow, WRAP_BANK, STY) +wOP8 (84X1, Direct, WRAP_BANK, STY) +wOP16(84X0, Direct, WRAP_BANK, STY) +wOPX (84Slow, DirectSlow, WRAP_BANK, STY) -wOP8 (94E1, DirectIndexedXE1, WRAP_BANK, STY) -wOP8 (94E0X1, DirectIndexedXE0, WRAP_BANK, STY) -wOP16(94E0X0, DirectIndexedXE0, WRAP_BANK, STY) -wOPX (94Slow, DirectIndexedXSlow, WRAP_BANK, STY) +wOP8 (94E1, DirectIndexedXE1, WRAP_BANK, STY) +wOP8 (94E0X1, DirectIndexedXE0, WRAP_BANK, STY) +wOP16(94E0X0, DirectIndexedXE0, WRAP_BANK, STY) +wOPX (94Slow, DirectIndexedXSlow, WRAP_BANK, STY) -wOP8 (8CX1, Absolute, WRAP_BANK, STY) -wOP16(8CX0, Absolute, WRAP_BANK, STY) -wOPX (8CSlow, AbsoluteSlow, WRAP_BANK, STY) +wOP8 (8CX1, Absolute, WRAP_BANK, STY) +wOP16(8CX0, Absolute, WRAP_BANK, STY) +wOPX (8CSlow, AbsoluteSlow, WRAP_BANK, STY) + +/*****************************************************************************/ /* STZ ********************************************************************* */ -wOP8 (64M1, Direct, WRAP_BANK, STZ) -wOP16(64M0, Direct, WRAP_BANK, STZ) -wOPM (64Slow, DirectSlow, WRAP_BANK, STZ) +wOP8 (64M1, Direct, WRAP_BANK, STZ) +wOP16(64M0, Direct, WRAP_BANK, STZ) +wOPM (64Slow, DirectSlow, WRAP_BANK, STZ) -wOP8 (74E1, DirectIndexedXE1, WRAP_BANK, STZ) -wOP8 (74E0M1, DirectIndexedXE0, WRAP_BANK, STZ) -wOP16(74E0M0, DirectIndexedXE0, WRAP_BANK, STZ) -wOPM (74Slow, DirectIndexedXSlow, WRAP_BANK, STZ) +wOP8 (74E1, DirectIndexedXE1, WRAP_BANK, STZ) +wOP8 (74E0M1, DirectIndexedXE0, WRAP_BANK, STZ) +wOP16(74E0M0, DirectIndexedXE0, WRAP_BANK, STZ) +wOPM (74Slow, DirectIndexedXSlow, WRAP_BANK, STZ) -wOP8 (9CM1, Absolute, WRAP_NONE, STZ) -wOP16(9CM0, Absolute, WRAP_NONE, STZ) -wOPM (9CSlow, AbsoluteSlow, WRAP_NONE, STZ) +wOP8 (9CM1, Absolute, WRAP_NONE, STZ) +wOP16(9CM0, Absolute, WRAP_NONE, STZ) +wOPM (9CSlow, AbsoluteSlow, WRAP_NONE, STZ) -wOP8 (9EM1X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) -wOP16(9EM0X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) -wOP8 (9EM1X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) -wOP16(9EM0X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) -wOPM (9ESlow, AbsoluteIndexedXSlow, WRAP_NONE, STZ) +wOP8 (9EM1X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP16(9EM0X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP8 (9EM1X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOP16(9EM0X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOPM (9ESlow, AbsoluteIndexedXSlow, WRAP_NONE, STZ) + +/*****************************************************************************/ /* TRB ********************************************************************* */ -mOP8 (14M1, Direct, WRAP_BANK, TRB) -mOP16(14M0, Direct, WRAP_BANK, TRB) -mOPM (14Slow, DirectSlow, WRAP_BANK, TRB) +mOP8 (14M1, Direct, WRAP_BANK, TRB) +mOP16(14M0, Direct, WRAP_BANK, TRB) +mOPM (14Slow, DirectSlow, WRAP_BANK, TRB) -mOP8 (1CM1, Absolute, WRAP_BANK, TRB) -mOP16(1CM0, Absolute, WRAP_BANK, TRB) -mOPM (1CSlow, AbsoluteSlow, WRAP_BANK, TRB) +mOP8 (1CM1, Absolute, WRAP_BANK, TRB) +mOP16(1CM0, Absolute, WRAP_BANK, TRB) +mOPM (1CSlow, AbsoluteSlow, WRAP_BANK, TRB) + +/*****************************************************************************/ /* TSB ********************************************************************* */ -mOP8 (04M1, Direct, WRAP_BANK, TSB) -mOP16(04M0, Direct, WRAP_BANK, TSB) -mOPM (04Slow, DirectSlow, WRAP_BANK, TSB) +mOP8 (04M1, Direct, WRAP_BANK, TSB) +mOP16(04M0, Direct, WRAP_BANK, TSB) +mOPM (04Slow, DirectSlow, WRAP_BANK, TSB) -mOP8 (0CM1, Absolute, WRAP_BANK, TSB) -mOP16(0CM0, Absolute, WRAP_BANK, TSB) -mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) +mOP8 (0CM1, Absolute, WRAP_BANK, TSB) +mOP16(0CM0, Absolute, WRAP_BANK, TSB) +mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) + +/*****************************************************************************/ /* Branch Instructions ***************************************************** */ +#ifndef SA1_OPCODES +#define BranchCheck0()\ + if( CPU.BranchSkip) {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) \ + if( Registers.PCw > newPC.W) \ + return; \ + } + +#define BranchCheck1()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) {\ + if( Registers.PCw > newPC.W)\ + return;\ + } else \ + if (Settings.SoundSkipMethod == 1)\ + return;\ + if (Settings.SoundSkipMethod == 3)\ + if( Registers.PCw > newPC.W)\ + return;\ + else\ + Registers.PCw = newPC.W;\ + } + +#define BranchCheck2()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) {\ + if( Registers.PCw > newPC.W)\ + return;\ + } else \ + if (Settings.SoundSkipMethod == 1)\ + Registers.PCw = newPC.W;\ + if (Settings.SoundSkipMethod == 3)\ + if (Registers.PCw > newPC.W)\ + return;\ + else\ + Registers.PCw = newPC.W;\ + } +#else +#define BranchCheck0() +#define BranchCheck1() +#define BranchCheck2() +#endif +#define BranchCheckX() #ifdef CPU_SHUTDOWN - #ifndef SA1_OPCODES - -inline void CPUShutdown (void) +inline void CPUShutdown() { if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) { @@ -1556,665 +1543,554 @@ inline void CPUShutdown (void) CPU.WaitCounter--; } } - #else - -inline void CPUShutdown (void) +inline void CPUShutdown() { if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) { if (CPU.WaitCounter >= 1) + { SA1.Executing = FALSE; + SA1.CPUExecuting = FALSE; + } else CPU.WaitCounter++; } } - #endif - #else - #define CPUShutdown() - #endif -// BCC -bOP(90E0, Relative, !CheckCarry(), 0, 0) -bOP(90E1, Relative, !CheckCarry(), 0, 1) -bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) +/* BCC */ +bOP(90E0, Relative, !CheckCarry(), 0, 0) +bOP(90E1, Relative, !CheckCarry(), 0, 1) +bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) -// BCS -bOP(B0E0, Relative, CheckCarry(), 0, 0) -bOP(B0E1, Relative, CheckCarry(), 0, 1) -bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) +/* BCS */ +bOP(B0E0, Relative, CheckCarry(), 0, 0) +bOP(B0E1, Relative, CheckCarry(), 0, 1) +bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) -// BEQ -bOP(F0E0, Relative, CheckZero(), 2, 0) -bOP(F0E1, Relative, CheckZero(), 2, 1) -bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) +/* BEQ */ +bOP(F0E0, Relative, CheckZero(), 2, 0) +bOP(F0E1, Relative, CheckZero(), 2, 1) +bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) -// BMI -bOP(30E0, Relative, CheckNegative(), 1, 0) -bOP(30E1, Relative, CheckNegative(), 1, 1) -bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) +/* BMI */ +bOP(30E0, Relative, CheckNegative(), 1, 0) +bOP(30E1, Relative, CheckNegative(), 1, 1) +bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) -// BNE -bOP(D0E0, Relative, !CheckZero(), 1, 0) -bOP(D0E1, Relative, !CheckZero(), 1, 1) -bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) +/* BNE */ +bOP(D0E0, Relative, !CheckZero(), 1, 0) +bOP(D0E1, Relative, !CheckZero(), 1, 1) +bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) -// BPL +/* BPL */ bOP(10E0, Relative, !CheckNegative(), 1, 0) bOP(10E1, Relative, !CheckNegative(), 1, 1) bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation()) -// BRA -bOP(80E0, Relative, 1, X, 0) -bOP(80E1, Relative, 1, X, 1) -bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) +/* BRA */ +bOP(80E0, Relative, 1, X, 0) +bOP(80E1, Relative, 1, X, 1) +bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) -// BVC +/* BVC */ bOP(50E0, Relative, !CheckOverflow(), 0, 0) bOP(50E1, Relative, !CheckOverflow(), 0, 1) bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation()) -// BVS -bOP(70E0, Relative, CheckOverflow(), 0, 0) -bOP(70E1, Relative, CheckOverflow(), 0, 1) -bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) +/* BVS */ +bOP(70E0, Relative, CheckOverflow(), 0, 0) +bOP(70E1, Relative, CheckOverflow(), 0, 1) +bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) -// BRL -static void Op82 (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); +/* BRL */ +static void Op82 (void) { + S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); } -static void Op82Slow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); +static void Op82Slow (void) { + S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); } +/*****************************************************************************/ + /* Flag Instructions ******************************************************* */ -// CLC -static void Op18 (void) -{ - ClearCarry(); - AddCycles(ONE_CYCLE); +/* CLC */ +static void Op18 (void) { + ClearCarry (); + AddCycles(ONE_CYCLE); } -// SEC -static void Op38 (void) -{ - SetCarry(); - AddCycles(ONE_CYCLE); +/* SEC */ +static void Op38 (void) { + SetCarry (); + AddCycles(ONE_CYCLE); } -// CLD -static void OpD8 (void) -{ - ClearDecimal(); - AddCycles(ONE_CYCLE); +/* CLD */ +static void OpD8 (void) { + ClearDecimal (); + AddCycles(ONE_CYCLE); } -// SED -static void OpF8 (void) -{ - SetDecimal(); - AddCycles(ONE_CYCLE); -#ifdef DEBUGGER - missing.decimal_mode = 1; -#endif +/* SED */ +static void OpF8 (void) { + SetDecimal (); + AddCycles(ONE_CYCLE); + missing.decimal_mode = 1; } -// CLI -static void Op58 (void) -{ - ClearIRQ(); - AddCycles(ONE_CYCLE); - //CHECK_FOR_IRQ(); +/* CLI */ +static void Op58 (void) { + ClearIRQ (); + AddCycles(ONE_CYCLE); +/* CHECK_FOR_IRQ(); */ } -// SEI -static void Op78 (void) -{ - SetIRQ(); - AddCycles(ONE_CYCLE); +/* SEI */ +static void Op78 (void) { + SetIRQ (); + AddCycles(ONE_CYCLE); } -// CLV -static void OpB8 (void) -{ - ClearOverflow(); - AddCycles(ONE_CYCLE); +/* CLV */ +static void OpB8 (void) { + ClearOverflow (); + AddCycles(ONE_CYCLE); } +/*****************************************************************************/ + /* DEX/DEY ***************************************************************** */ -static void OpCAX1 (void) -{ - AddCycles(ONE_CYCLE); +static void OpCAX1 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.XL--; - SetZN(Registers.XL); + Registers.XL--; + SetZN (Registers.XL); } -static void OpCAX0 (void) -{ - AddCycles(ONE_CYCLE); +static void OpCAX0 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.X.W--; - SetZN(Registers.X.W); + Registers.X.W--; + SetZN (Registers.X.W); } -static void OpCASlow (void) -{ - AddCycles(ONE_CYCLE); +static void OpCASlow (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - - if (CheckIndex()) - { - Registers.XL--; - SetZN(Registers.XL); - } - else - { - Registers.X.W--; - SetZN(Registers.X.W); - } + if(CheckIndex()){ + Registers.XL--; + SetZN (Registers.XL); + } else { + Registers.X.W--; + SetZN (Registers.X.W); + } } -static void Op88X1 (void) -{ - AddCycles(ONE_CYCLE); +static void Op88X1 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.YL--; - SetZN(Registers.YL); + Registers.YL--; + SetZN (Registers.YL); } -static void Op88X0 (void) -{ - AddCycles(ONE_CYCLE); +static void Op88X0 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.Y.W--; - SetZN(Registers.Y.W); + Registers.Y.W--; + SetZN (Registers.Y.W); } -static void Op88Slow (void) -{ - AddCycles(ONE_CYCLE); +static void Op88Slow (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - - if (CheckIndex()) - { - Registers.YL--; - SetZN(Registers.YL); - } - else - { - Registers.Y.W--; - SetZN(Registers.Y.W); - } + if(CheckIndex()){ + Registers.YL--; + SetZN (Registers.YL); + } else { + Registers.Y.W--; + SetZN (Registers.Y.W); + } } +/*****************************************************************************/ + /* INX/INY ***************************************************************** */ - -static void OpE8X1 (void) -{ - AddCycles(ONE_CYCLE); +static void OpE8X1 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.XL++; - SetZN(Registers.XL); + Registers.XL++; + SetZN (Registers.XL); } -static void OpE8X0 (void) -{ - AddCycles(ONE_CYCLE); +static void OpE8X0 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.X.W++; - SetZN(Registers.X.W); + Registers.X.W++; + SetZN (Registers.X.W); } -static void OpE8Slow (void) -{ - AddCycles(ONE_CYCLE); +static void OpE8Slow (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - - if (CheckIndex()) - { - Registers.XL++; - SetZN(Registers.XL); - } - else - { - Registers.X.W++; - SetZN(Registers.X.W); - } + if(CheckIndex()){ + Registers.XL++; + SetZN (Registers.XL); + } else { + Registers.X.W++; + SetZN (Registers.X.W); + } } -static void OpC8X1 (void) -{ - AddCycles(ONE_CYCLE); +static void OpC8X1 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.YL++; - SetZN(Registers.YL); + Registers.YL++; + SetZN (Registers.YL); } -static void OpC8X0 (void) -{ - AddCycles(ONE_CYCLE); +static void OpC8X0 (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - Registers.Y.W++; - SetZN(Registers.Y.W); + Registers.Y.W++; + SetZN (Registers.Y.W); } -static void OpC8Slow (void) -{ - AddCycles(ONE_CYCLE); +static void OpC8Slow (void) { + AddCycles(ONE_CYCLE); #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + CPU.WaitAddress = 0xffffffff; #endif - - if (CheckIndex()) - { - Registers.YL--; - SetZN(Registers.YL); - } - else - { - Registers.Y.W--; - SetZN(Registers.Y.W); - } + if(CheckIndex()){ + Registers.YL--; + SetZN (Registers.YL); + } else { + Registers.Y.W--; + SetZN (Registers.Y.W); + } } +/*****************************************************************************/ + /* NOP ********************************************************************* */ - -static void OpEA (void) -{ - AddCycles(ONE_CYCLE); +static void OpEA (void) { + AddCycles(ONE_CYCLE); } +/*****************************************************************************/ + /* PUSH Instructions ******************************************************* */ - #define PushW(w) \ - S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \ - Registers.S.W -= 2; + S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \ + Registers.S.W -= 2; #define PushWE(w) \ - Registers.SL--; \ - S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \ - Registers.SL--; + Registers.SL--; \ + S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \ + Registers.SL--; #define PushB(b) \ - S9xSetByte(b, Registers.S.W--); + S9xSetByte(b, Registers.S.W--); #define PushBE(b) \ - S9xSetByte(b, Registers.S.W); \ - Registers.SL--; + S9xSetByte (b, Registers.S.W); \ + Registers.SL--; -// PEA -static void OpF4E0 (void) -{ - uint16 val = (uint16) Absolute(NONE); - PushW(val); - OpenBus = val & 0xff; +/* PEA */ +static void OpF4E0 (void) { + uint16 val=(uint16)Absolute(NONE); + PushW(val); + OpenBus = val&0xff; } -static void OpF4E1 (void) -{ - // Note: PEA is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 val = (uint16) Absolute(NONE); - PushW(val); - OpenBus = val & 0xff; - Registers.SH = 1; +static void OpF4E1 (void) { + /* Note: PEA is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + uint16 val=(uint16)Absolute(NONE); + PushW(val); + OpenBus = val&0xff; + Registers.SH=1; } -static void OpF4Slow (void) -{ - uint16 val = (uint16) AbsoluteSlow(NONE); - PushW(val); - OpenBus = val & 0xff; - if (CheckEmulation()) - Registers.SH = 1; +static void OpF4Slow (void) { + uint16 val=(uint16)AbsoluteSlow(NONE); + PushW(val); + OpenBus = val&0xff; + if(CheckEmulation()) Registers.SH=1; } -// PEI -static void OpD4E0 (void) -{ - uint16 val = (uint16) DirectIndirectE0(NONE); - PushW(val); - OpenBus = val & 0xff; +/* PEI */ +static void OpD4E0 (void) { + uint16 val=(uint16)DirectIndirectE0(NONE); + PushW(val); + OpenBus = val&0xff; } -static void OpD4E1 (void) -{ - // Note: PEI is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 val = (uint16) DirectIndirectE1(NONE); - PushW(val); - OpenBus = val & 0xff; - Registers.SH = 1; +static void OpD4E1 (void) { + /* Note: PEI is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + uint16 val=(uint16)DirectIndirectE1(NONE); + PushW(val); + OpenBus = val&0xff; + Registers.SH=1; } -static void OpD4Slow (void) -{ - uint16 val = (uint16) DirectIndirectSlow(NONE); - PushW(val); - OpenBus = val & 0xff; - if (CheckEmulation()) - Registers.SH = 1; +static void OpD4Slow (void) { + uint16 val=(uint16)DirectIndirectSlow(NONE); + PushW(val); + OpenBus = val&0xff; + if(CheckEmulation()) Registers.SH=1; } -// PER -static void Op62E0 (void) -{ - uint16 val = (uint16) RelativeLong(NONE); - PushW(val); - OpenBus = val & 0xff; +/* PER */ +static void Op62E0 (void) { + uint16 val=(uint16)RelativeLong(NONE); + PushW(val); + OpenBus = val&0xff; } -static void Op62E1 (void) -{ - // Note: PER is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 val = (uint16) RelativeLong(NONE); - PushW(val); - OpenBus = val & 0xff; - Registers.SH = 1; +static void Op62E1 (void) { + /* Note: PER is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + uint16 val=(uint16)RelativeLong(NONE); + PushW(val); + OpenBus = val&0xff; + Registers.SH=1; } -static void Op62Slow (void) -{ - uint16 val = (uint16) RelativeLongSlow(NONE); - PushW(val); - OpenBus = val & 0xff; - if (CheckEmulation()) - Registers.SH = 1; +static void Op62Slow (void) { + uint16 val=(uint16)RelativeLongSlow(NONE); + PushW(val); + OpenBus = val&0xff; + if(CheckEmulation()) Registers.SH=1; } -// PHA -static void Op48E1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.AL); - OpenBus = Registers.AL; +/* PHA */ +static void Op48E1 (void) { + AddCycles(ONE_CYCLE); + PushBE(Registers.AL); + OpenBus = Registers.AL; } -static void Op48E0M1 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.AL); - OpenBus = Registers.AL; +static void Op48E0M1 (void) { + AddCycles(ONE_CYCLE); + PushB(Registers.AL); + OpenBus = Registers.AL; } -static void Op48E0M0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.A.W); - OpenBus = Registers.AL; +static void Op48E0M0 (void) { + AddCycles(ONE_CYCLE); + PushW(Registers.A.W); + OpenBus = Registers.AL; } -static void Op48Slow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.AL); - } - else - if (CheckMemory()) - { - PushB(Registers.AL); - } - else - { - PushW(Registers.A.W); - } - - OpenBus = Registers.AL; +static void Op48Slow (void) { + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushBE(Registers.AL); + } else if(CheckMemory()){ + PushB(Registers.AL); + } else { + PushW(Registers.A.W); + } + OpenBus = Registers.AL; } -// PHB -static void Op8BE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.DB); - OpenBus = Registers.DB; +/* PHB */ +static void Op8BE1 (void) { + AddCycles(ONE_CYCLE); + PushBE (Registers.DB); + OpenBus = Registers.DB; } -static void Op8BE0 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.DB); - OpenBus = Registers.DB; +static void Op8BE0 (void) { + AddCycles(ONE_CYCLE); + PushB (Registers.DB); + OpenBus = Registers.DB; } -static void Op8BSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.DB); - } - else - { - PushB(Registers.DB); - } - - OpenBus = Registers.DB; +static void Op8BSlow (void) { + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushBE (Registers.DB); + } else { + PushB (Registers.DB); + } + OpenBus = Registers.DB; } -// PHD -static void Op0BE0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.D.W); - OpenBus = Registers.DL; +/* PHD */ +static void Op0BE0 (void) { + AddCycles(ONE_CYCLE); + PushW (Registers.D.W); + OpenBus = Registers.DL; } -static void Op0BE1 (void) -{ - // Note: PHD is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - AddCycles(ONE_CYCLE); - PushW(Registers.D.W); - OpenBus = Registers.DL; - Registers.SH = 1; +static void Op0BE1 (void) { + /* Note: PHD is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + AddCycles(ONE_CYCLE); + PushW (Registers.D.W); + OpenBus = Registers.DL; + Registers.SH=1; } -static void Op0BSlow (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.D.W); - OpenBus = Registers.DL; - if (CheckEmulation()) - Registers.SH = 1; +static void Op0BSlow (void) { + AddCycles(ONE_CYCLE); + PushW (Registers.D.W); + OpenBus = Registers.DL; + if(CheckEmulation()) Registers.SH=1; } -// PHK -static void Op4BE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.PB); - OpenBus = Registers.PB; +/* PHK */ +static void Op4BE1 (void) { + AddCycles(ONE_CYCLE); + PushBE (Registers.PB); + OpenBus = Registers.PB; } -static void Op4BE0 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.PB); - OpenBus = Registers.PB; +static void Op4BE0 (void) { + AddCycles(ONE_CYCLE); + PushB (Registers.PB); + OpenBus = Registers.PB; } -static void Op4BSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.PB); - } - else - { - PushB(Registers.PB); - } - - OpenBus = Registers.PB; +static void Op4BSlow (void) { + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushBE (Registers.PB); + } else { + PushB (Registers.PB); + } + OpenBus = Registers.PB; } -// PHP -static void Op08E0 (void) -{ - S9xPackStatus(); - AddCycles(ONE_CYCLE); - PushB(Registers.PL); - OpenBus = Registers.PL; +/* PHP */ +static void Op08E0 (void) { + S9xPackStatus (); + AddCycles(ONE_CYCLE); + PushB (Registers.PL); + OpenBus = Registers.PL; } -static void Op08E1 (void) -{ - S9xPackStatus(); - AddCycles(ONE_CYCLE); - PushBE(Registers.PL); - OpenBus = Registers.PL; +static void Op08E1 (void) { + S9xPackStatus (); + AddCycles(ONE_CYCLE); + PushBE (Registers.PL); + OpenBus = Registers.PL; } -static void Op08Slow (void) -{ - S9xPackStatus(); - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.PL); - } - else - { - PushB(Registers.PL); - } - - OpenBus = Registers.PL; +static void Op08Slow (void) { + S9xPackStatus (); + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushBE (Registers.PL); + } else { + PushB (Registers.PL); + } + OpenBus = Registers.PL; } -// PHX -static void OpDAE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.XL); - OpenBus = Registers.XL; +/* PHX */ +static void OpDAE1 (void) { + AddCycles(ONE_CYCLE); + PushBE (Registers.XL); + OpenBus = Registers.XL; } -static void OpDAE0X1 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.XL); - OpenBus = Registers.XL; +static void OpDAE0X1 (void) { + AddCycles(ONE_CYCLE); + PushB(Registers.XL); + OpenBus = Registers.XL; } -static void OpDAE0X0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.X.W); - OpenBus = Registers.XL; +static void OpDAE0X0 (void) { + AddCycles(ONE_CYCLE); + PushW(Registers.X.W); + OpenBus = Registers.XL; } -static void OpDASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.XL); - } - else - if (CheckIndex()) - { - PushB(Registers.XL); - } - else - { - PushW(Registers.X.W); - } - - OpenBus = Registers.XL; +static void OpDASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushBE(Registers.XL); + } else if(CheckIndex()){ + PushB(Registers.XL); + } else { + PushW(Registers.X.W); + } + OpenBus = Registers.XL; } -// PHY -static void Op5AE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.YL); - OpenBus = Registers.YL; +/* PHY */ +static void Op5AE1 (void) { + AddCycles(ONE_CYCLE); + PushBE (Registers.YL); + OpenBus = Registers.YL; } -static void Op5AE0X1 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.YL); - OpenBus = Registers.YL; +static void Op5AE0X1 (void) { + AddCycles(ONE_CYCLE); + PushB(Registers.YL); + OpenBus = Registers.YL; } -static void Op5AE0X0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.Y.W); - OpenBus = Registers.YL; +static void Op5AE0X0 (void) { + AddCycles(ONE_CYCLE); + PushW(Registers.Y.W); + OpenBus = Registers.YL; } -static void Op5ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.YL); - } - else - if (CheckIndex()) - { - PushB(Registers.YL); - } - else - { - PushW(Registers.Y.W); - } - - OpenBus = Registers.YL; +static void Op5ASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushBE(Registers.YL); + } else if(CheckIndex()){ + PushB(Registers.YL); + } else { + PushW(Registers.Y.W); + } + OpenBus = Registers.YL; } +/*****************************************************************************/ + /* PULL Instructions ******************************************************* */ - #define PullW(w) \ w = S9xGetWord(Registers.S.W + 1, WRAP_BANK); \ Registers.S.W += 2; #define PullWE(w) \ - Registers.SL++; \ + Registers.SL++; \ w = S9xGetWord(Registers.S.W, WRAP_PAGE); \ Registers.SL++; @@ -2225,1774 +2101,1540 @@ static void Op5ASlow (void) Registers.SL++; \ b = S9xGetByte(Registers.S.W); -// PLA -static void Op68E1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; +/* PLA */ +static void Op68E1 (void) { + AddCycles(TWO_CYCLES); + PullBE (Registers.AL); + SetZN (Registers.AL); + OpenBus = Registers.AL; } -static void Op68E0M1 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; +static void Op68E0M1 (void) { + AddCycles(TWO_CYCLES); + PullB (Registers.AL); + SetZN (Registers.AL); + OpenBus = Registers.AL; } -static void Op68E0M0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.A.W); - SetZN(Registers.A.W); - OpenBus = Registers.AH; +static void Op68E0M0 (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.A.W); + SetZN (Registers.A.W); + OpenBus = Registers.AH; } -static void Op68Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; - } - else - if (CheckMemory()) - { - PullB(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; - } - else - { - PullW(Registers.A.W); - SetZN(Registers.A.W); - OpenBus = Registers.AH; - } +static void Op68Slow (void) { + AddCycles(TWO_CYCLES); + if(CheckEmulation()){ + PullBE (Registers.AL); + SetZN (Registers.AL); + OpenBus = Registers.AL; + } else if(CheckMemory()){ + PullB (Registers.AL); + SetZN (Registers.AL); + OpenBus = Registers.AL; + } else { + PullW (Registers.A.W); + SetZN (Registers.A.W); + OpenBus = Registers.AH; + } } -// PLB -static void OpABE1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.DB); - SetZN(Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = Registers.DB; +/* PLB */ +static void OpABE1 (void) { + AddCycles(TWO_CYCLES); + PullBE (Registers.DB); + SetZN (Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; } -static void OpABE0 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.DB); - SetZN(Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = Registers.DB; +static void OpABE0 (void) { + AddCycles(TWO_CYCLES); + PullB (Registers.DB); + SetZN (Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; } -static void OpABSlow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.DB); - } - else - { - PullB(Registers.DB); - } - - SetZN(Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = Registers.DB; +static void OpABSlow (void) { + AddCycles(TWO_CYCLES); + if(CheckEmulation()){ + PullBE (Registers.DB); + } else { + PullB (Registers.DB); + } + SetZN (Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; } -// PLD -static void Op2BE0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.D.W); - SetZN(Registers.D.W); - OpenBus = Registers.DH; +/* PLD */ +static void Op2BE0 (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.D.W); + SetZN (Registers.D.W); + OpenBus = Registers.DH; } -static void Op2BE1 (void) -{ - // Note: PLD is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - AddCycles(TWO_CYCLES); - PullW(Registers.D.W); - SetZN(Registers.D.W); - OpenBus = Registers.DH; - Registers.SH = 1; +static void Op2BE1 (void) { + /* Note: PHD is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + AddCycles(TWO_CYCLES); + PullW (Registers.D.W); + SetZN (Registers.D.W); + OpenBus = Registers.DH; + Registers.SH=1; } -static void Op2BSlow (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.D.W); - SetZN(Registers.D.W); - OpenBus = Registers.DH; - if (CheckEmulation()) - Registers.SH = 1; +static void Op2BSlow (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.D.W); + SetZN (Registers.D.W); + OpenBus = Registers.DH; + if(CheckEmulation()) Registers.SH=1; } -// PLP -static void Op28E1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.PL); - OpenBus = Registers.PL; - SetFlags(MemoryFlag | IndexFlag); - S9xUnpackStatus(); - S9xFixCycles(); - //CHECK_FOR_IRQ(); +/* PLP */ +static void Op28E1 (void) { + AddCycles(TWO_CYCLES); + PullBE (Registers.PL); + OpenBus = Registers.PL; + SetFlags (MemoryFlag | IndexFlag); + S9xUnpackStatus (); + S9xFixCycles(); +/* CHECK_FOR_IRQ();*/ } -static void Op28E0 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.PL); - OpenBus = Registers.PL; - S9xUnpackStatus(); - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); +static void Op28E0 (void) { + AddCycles(TWO_CYCLES); + PullB (Registers.PL); + OpenBus = Registers.PL; + S9xUnpackStatus (); + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ();*/ } -static void Op28Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.PL); - OpenBus = Registers.PL; - SetFlags(MemoryFlag | IndexFlag); - } - else - { - PullB(Registers.PL); - OpenBus = Registers.PL; - } - - S9xUnpackStatus(); - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); +static void Op28Slow (void) { + AddCycles(TWO_CYCLES); + if(CheckEmulation()){ + PullBE (Registers.PL); + OpenBus = Registers.PL; + SetFlags (MemoryFlag | IndexFlag); + } else { + PullB (Registers.PL); + OpenBus = Registers.PL; + } + S9xUnpackStatus (); + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ();*/ } -// PLX -static void OpFAE1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; +/* PLX */ +static void OpFAE1 (void) { + AddCycles(TWO_CYCLES); + PullBE (Registers.XL); + SetZN (Registers.XL); + OpenBus = Registers.XL; } -static void OpFAE0X1 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; +static void OpFAE0X1 (void) { + AddCycles(TWO_CYCLES); + PullB (Registers.XL); + SetZN (Registers.XL); + OpenBus = Registers.XL; } -static void OpFAE0X0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.X.W); - SetZN(Registers.X.W); - OpenBus = Registers.XH; +static void OpFAE0X0 (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.X.W); + SetZN (Registers.X.W); + OpenBus = Registers.XH; } -static void OpFASlow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; - } - else - if (CheckIndex()) - { - PullB(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; - } - else - { - PullW(Registers.X.W); - SetZN(Registers.X.W); - OpenBus = Registers.XH; - } +static void OpFASlow (void) { + AddCycles(TWO_CYCLES); + if(CheckEmulation()){ + PullBE (Registers.XL); + SetZN (Registers.XL); + OpenBus = Registers.XL; + } else if(CheckIndex()){ + PullB (Registers.XL); + SetZN (Registers.XL); + OpenBus = Registers.XL; + } else { + PullW (Registers.X.W); + SetZN (Registers.X.W); + OpenBus = Registers.XH; + } } -// PLY -static void Op7AE1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; +/* PLY */ +static void Op7AE1 (void) { + AddCycles(TWO_CYCLES); + PullBE (Registers.YL); + SetZN (Registers.YL); + OpenBus = Registers.YL; } -static void Op7AE0X1 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; +static void Op7AE0X1 (void) { + AddCycles(TWO_CYCLES); + PullB (Registers.YL); + SetZN (Registers.YL); + OpenBus = Registers.YL; } -static void Op7AE0X0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.Y.W); - SetZN(Registers.Y.W); - OpenBus = Registers.YH; +static void Op7AE0X0 (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.Y.W); + SetZN (Registers.Y.W); + OpenBus = Registers.YH; } -static void Op7ASlow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; - } - else - if (CheckIndex()) - { - PullB(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; - } - else - { - PullW(Registers.Y.W); - SetZN(Registers.Y.W); - OpenBus = Registers.YH; - } +static void Op7ASlow (void) { + AddCycles(TWO_CYCLES); + if(CheckEmulation()){ + PullBE (Registers.YL); + SetZN (Registers.YL); + OpenBus = Registers.YL; + } else if(CheckIndex()){ + PullB (Registers.YL); + SetZN (Registers.YL); + OpenBus = Registers.YL; + } else { + PullW (Registers.Y.W); + SetZN (Registers.Y.W); + OpenBus = Registers.YH; + } } +/*****************************************************************************/ + /* Transfer Instructions *************************************************** */ - -// TAX -static void OpAAX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.XL = Registers.AL; - SetZN(Registers.XL); +/* TAX */ +static void OpAAX1 (void) { + AddCycles(ONE_CYCLE); + Registers.XL = Registers.AL; + SetZN (Registers.XL); } -static void OpAAX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.X.W = Registers.A.W; - SetZN(Registers.X.W); +static void OpAAX0 (void) { + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.A.W; + SetZN (Registers.X.W); } -static void OpAASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.XL = Registers.AL; - SetZN(Registers.XL); - } - else - { - Registers.X.W = Registers.A.W; - SetZN(Registers.X.W); - } +static void OpAASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckIndex()){ + Registers.XL = Registers.AL; + SetZN (Registers.XL); + } else { + Registers.X.W = Registers.A.W; + SetZN (Registers.X.W); + } } -// TAY -static void OpA8X1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.YL = Registers.AL; - SetZN(Registers.YL); +/* TAY */ +static void OpA8X1 (void) { + AddCycles(ONE_CYCLE); + Registers.YL = Registers.AL; + SetZN (Registers.YL); } -static void OpA8X0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.Y.W = Registers.A.W; - SetZN(Registers.Y.W); +static void OpA8X0 (void) { + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.A.W; + SetZN (Registers.Y.W); } -static void OpA8Slow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.YL = Registers.AL; - SetZN(Registers.YL); - } - else - { - Registers.Y.W = Registers.A.W; - SetZN(Registers.Y.W); - } +static void OpA8Slow (void) { + AddCycles(ONE_CYCLE); + if(CheckIndex()){ + Registers.YL = Registers.AL; + SetZN (Registers.YL); + } else { + Registers.Y.W = Registers.A.W; + SetZN (Registers.Y.W); + } } -// TCD -static void Op5B (void) -{ - AddCycles(ONE_CYCLE); - Registers.D.W = Registers.A.W; - SetZN(Registers.D.W); +/* TCD */ +static void Op5B (void) { + AddCycles(ONE_CYCLE); + Registers.D.W = Registers.A.W; + SetZN (Registers.D.W); } -// TCS -static void Op1B (void) -{ - AddCycles(ONE_CYCLE); - Registers.S.W = Registers.A.W; - if (CheckEmulation()) - Registers.SH = 1; +/* TCS */ +static void Op1B (void) { + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.A.W; + if(CheckEmulation()) Registers.SH = 1; } -// TDC -static void Op7B (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.D.W; - SetZN(Registers.A.W); +/* TDC */ +static void Op7B (void) { + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.D.W; + SetZN (Registers.A.W); } -// TSC -static void Op3B (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.S.W; - SetZN(Registers.A.W); +/* TSC */ +static void Op3B (void) { + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.S.W; + SetZN (Registers.A.W); } -// TSX -static void OpBAX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.XL = Registers.SL; - SetZN(Registers.XL); +/* TSX */ +static void OpBAX1 (void) { + AddCycles(ONE_CYCLE); + Registers.XL = Registers.SL; + SetZN (Registers.XL); } -static void OpBAX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.X.W = Registers.S.W; - SetZN(Registers.X.W); +static void OpBAX0 (void) { + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.S.W; + SetZN (Registers.X.W); } -static void OpBASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.XL = Registers.SL; - SetZN(Registers.XL); - } - else - { - Registers.X.W = Registers.S.W; - SetZN(Registers.X.W); - } +static void OpBASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckIndex()){ + Registers.XL = Registers.SL; + SetZN (Registers.XL); + } else { + Registers.X.W = Registers.S.W; + SetZN (Registers.X.W); + } } -// TXA -static void Op8AM1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.AL = Registers.XL; - SetZN(Registers.AL); +/* TXA */ +static void Op8AM1 (void) { + AddCycles(ONE_CYCLE); + Registers.AL = Registers.XL; + SetZN (Registers.AL); } -static void Op8AM0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.X.W; - SetZN(Registers.A.W); +static void Op8AM0 (void) { + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.X.W; + SetZN (Registers.A.W); } -static void Op8ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - Registers.AL = Registers.XL; - SetZN(Registers.AL); - } - else - { - Registers.A.W = Registers.X.W; - SetZN(Registers.A.W); - } +static void Op8ASlow (void) { + AddCycles(ONE_CYCLE); + if(CheckMemory()){ + Registers.AL = Registers.XL; + SetZN (Registers.AL); + } else { + Registers.A.W = Registers.X.W; + SetZN (Registers.A.W); + } } -// TXS -static void Op9A (void) -{ - AddCycles(ONE_CYCLE); - Registers.S.W = Registers.X.W; - if (CheckEmulation()) - Registers.SH = 1; +/* TXS */ +static void Op9A (void) { + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.X.W; + if(CheckEmulation()) Registers.SH = 1; } -// TXY -static void Op9BX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.YL = Registers.XL; - SetZN(Registers.YL); +/* TXY */ +static void Op9BX1 (void) { + AddCycles(ONE_CYCLE); + Registers.YL = Registers.XL; + SetZN (Registers.YL); } -static void Op9BX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.Y.W = Registers.X.W; - SetZN(Registers.Y.W); +static void Op9BX0 (void) { + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.X.W; + SetZN (Registers.Y.W); } -static void Op9BSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.YL = Registers.XL; - SetZN(Registers.YL); - } - else - { - Registers.Y.W = Registers.X.W; - SetZN(Registers.Y.W); - } +static void Op9BSlow (void) { + AddCycles(ONE_CYCLE); + if(CheckIndex()){ + Registers.YL = Registers.XL; + SetZN (Registers.YL); + } else { + Registers.Y.W = Registers.X.W; + SetZN (Registers.Y.W); + } } -// TYA -static void Op98M1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.AL = Registers.YL; - SetZN(Registers.AL); +/* TYA */ +static void Op98M1 (void) { + AddCycles(ONE_CYCLE); + Registers.AL = Registers.YL; + SetZN (Registers.AL); } -static void Op98M0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.Y.W; - SetZN(Registers.A.W); +static void Op98M0 (void) { + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.Y.W; + SetZN (Registers.A.W); } -static void Op98Slow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - Registers.AL = Registers.YL; - SetZN(Registers.AL); - } - else - { - Registers.A.W = Registers.Y.W; - SetZN(Registers.A.W); - } +static void Op98Slow (void) { + AddCycles(ONE_CYCLE); + if(CheckMemory()){ + Registers.AL = Registers.YL; + SetZN (Registers.AL); + } else { + Registers.A.W = Registers.Y.W; + SetZN (Registers.A.W); + } } -// TYX -static void OpBBX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.XL = Registers.YL; - SetZN(Registers.XL); +/* TYX */ +static void OpBBX1 (void) { + AddCycles(ONE_CYCLE); + Registers.XL = Registers.YL; + SetZN (Registers.XL); } -static void OpBBX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.X.W = Registers.Y.W; - SetZN(Registers.X.W); +static void OpBBX0 (void) { + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.Y.W; + SetZN (Registers.X.W); } -static void OpBBSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.XL = Registers.YL; - SetZN(Registers.XL); - } - else - { - Registers.X.W = Registers.Y.W; - SetZN(Registers.X.W); - } +static void OpBBSlow (void) { + AddCycles(ONE_CYCLE); + if(CheckIndex()){ + Registers.XL = Registers.YL; + SetZN (Registers.XL); + } else { + Registers.X.W = Registers.Y.W; + SetZN (Registers.X.W); + } } +/*****************************************************************************/ + /* XCE ********************************************************************* */ +static void OpFB (void) { + AddCycles(ONE_CYCLE); -static void OpFB (void) -{ - AddCycles(ONE_CYCLE); + uint8 A1 = ICPU._Carry; + uint8 A2 = Registers.PH; + ICPU._Carry = A2 & 1; + Registers.PH = A1; - uint8 A1 = ICPU._Carry; - uint8 A2 = Registers.PH; - - ICPU._Carry = A2 & 1; - Registers.PH = A1; - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - Registers.SH = 1; - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); + if (CheckEmulation()) { + SetFlags (MemoryFlag | IndexFlag); + Registers.SH = 1; + missing.emulate6502 = 1; + } + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); } +/*****************************************************************************/ + /* BRK ********************************************************************* */ - -static void Op00 (void) -{ +static void Op00 (void) { #ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - S9xTraceMessage("*** BRK"); + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage ("*** BRK"); #endif - AddCycles(CPU.MemSpeed); +#ifndef SA1_OPCODES + CPU.BRKTriggered = TRUE; +#endif - uint16 addr; + AddCycles(CPU.MemSpeed); - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw + 1); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); + uint16 addr; + if (!CheckEmulation()) { + PushB (Registers.PB); + PushW (Registers.PCw + 1); + S9xPackStatus (); + PushB (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - addr = S9xGetWord(0xFFE6); - } - else - { - PushWE(Registers.PCw + 1); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); + addr = S9xGetWord (0xFFE6); + } else { + PushWE (Registers.PCw + 1); + S9xPackStatus (); + PushBE (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - addr = S9xGetWord(0xFFFE); - } - - S9xSetPCBase(addr); - OpenBus = addr >> 8; + addr = S9xGetWord (0xFFFE); + } + S9xSetPCBase(addr); + OpenBus = addr>>8; } +/*****************************************************************************/ + /* IRQ ********************************************************************* */ - -void S9xOpcode_IRQ (void) -{ +void S9xOpcode_IRQ (void) { #ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - S9xTraceMessage("*** IRQ"); + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage ("*** IRQ"); #endif - // IRQ and NMI do an opcode fetch as their first "IO" cycle. - AddCycles(CPU.MemSpeed + ONE_CYCLE); + /* IRQ and NMI do an opcode fetch as their first "IO" cycle */ + AddCycles(CPU.MemSpeed + ONE_CYCLE); - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); + if (!CheckEmulation()) { + PushB (Registers.PB); + PushW (Registers.PCw); + S9xPackStatus (); + PushB (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2208]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) - { - OpenBus = Memory.FillRAM[0x220f]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFEE); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } - else - { - PushWE(Registers.PCw); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); +#ifdef SA1_OPCODES + OpenBus = Memory.FillRAM [0x2208]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSA1SetPCBase (Memory.FillRAM [0x2207] | + (Memory.FillRAM [0x2208] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) { + OpenBus = Memory.FillRAM [0x220f]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + } else { + uint16 addr = S9xGetWord (0xFFEE); + OpenBus = addr>>8; + S9xSetPCBase (addr); + } +#endif + } else { + PushWE (Registers.PCw); + S9xPackStatus (); + PushBE (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2208]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) - { - OpenBus = Memory.FillRAM[0x220f]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFFE); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } +#ifdef SA1_OPCODES + OpenBus = Memory.FillRAM [0x2208]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSA1SetPCBase (Memory.FillRAM [0x2207] | + (Memory.FillRAM [0x2208] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) { + OpenBus = Memory.FillRAM [0x220f]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + } else { + uint16 addr = S9xGetWord (0xFFFE); + OpenBus = addr>>8; + S9xSetPCBase (addr); + } +#endif + } } +/*****************************************************************************/ + /* NMI ********************************************************************* */ - -void S9xOpcode_NMI (void) -{ +void S9xOpcode_NMI (void) { #ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - S9xTraceMessage("*** NMI"); + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage ("*** NMI"); #endif - // IRQ and NMI do an opcode fetch as their first "IO" cycle. - AddCycles(CPU.MemSpeed + ONE_CYCLE); + /* IRQ and NMI do an opcode fetch as their first "IO" cycle */ + AddCycles(CPU.MemSpeed + ONE_CYCLE); - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); + if (!CheckEmulation()) { + PushB (Registers.PB); + PushW (Registers.PCw); + S9xPackStatus (); + PushB (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2206]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) - { - OpenBus = Memory.FillRAM[0x220d]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFEA); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } - else - { - PushWE(Registers.PCw); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); +#ifdef SA1_OPCODES + OpenBus = Memory.FillRAM [0x2206]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSA1SetPCBase (Memory.FillRAM [0x2205] | + (Memory.FillRAM [0x2206] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) { + OpenBus = Memory.FillRAM [0x220d]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + } else { + uint16 addr = S9xGetWord (0xFFEA); + OpenBus = addr>>8; + S9xSetPCBase (addr); + } +#endif + } else { + PushWE (Registers.PCw); + S9xPackStatus (); + PushBE (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2206]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) - { - OpenBus = Memory.FillRAM[0x220d]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFFA); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } +#ifdef SA1_OPCODES + OpenBus = Memory.FillRAM [0x2206]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSA1SetPCBase (Memory.FillRAM [0x2205] | + (Memory.FillRAM [0x2206] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) { + OpenBus = Memory.FillRAM [0x220d]; + AddCycles(2*SLOW_ONE_CYCLE); + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + } else { + uint16 addr = S9xGetWord (0xFFFA); + OpenBus = addr>>8; + S9xSetPCBase (addr); + } +#endif + } } +/*****************************************************************************/ + /* COP ********************************************************************* */ - -static void Op02 (void) -{ +static void Op02 (void) { #ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - S9xTraceMessage("*** COP"); + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage ("*** COP"); #endif - AddCycles(CPU.MemSpeed); + AddCycles(CPU.MemSpeed); - uint16 addr; + uint16 addr; + if (!CheckEmulation()) { + PushB (Registers.PB); + PushW (Registers.PCw + 1); + S9xPackStatus (); + PushB (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw + 1); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); + addr = S9xGetWord (0xFFE4); + } else { + PushWE (Registers.PCw + 1); + S9xPackStatus (); + PushBE (Registers.PL); + OpenBus = Registers.PL; + ClearDecimal (); + SetIRQ (); - addr = S9xGetWord(0xFFE4); - } - else - { - PushWE(Registers.PCw + 1); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - addr = S9xGetWord(0xFFF4); - } - - S9xSetPCBase(addr); - OpenBus = addr >> 8; + addr = S9xGetWord (0xFFF4); + } + S9xSetPCBase(addr); + OpenBus = addr>>8; } +/*****************************************************************************/ + /* JML ********************************************************************* */ - -static void OpDC (void) -{ - S9xSetPCBase(AbsoluteIndirectLong(JUMP)); +static void OpDC (void) { + S9xSetPCBase (AbsoluteIndirectLong (JUMP)); } -static void OpDCSlow (void) -{ - S9xSetPCBase(AbsoluteIndirectLongSlow(JUMP)); +static void OpDCSlow (void) { + S9xSetPCBase (AbsoluteIndirectLongSlow (JUMP)); } -static void Op5C (void) -{ - S9xSetPCBase(AbsoluteLong(JUMP)); +static void Op5C (void) { + S9xSetPCBase(AbsoluteLong (JUMP)); } -static void Op5CSlow (void) -{ - S9xSetPCBase(AbsoluteLongSlow(JUMP)); +static void Op5CSlow (void) { + S9xSetPCBase(AbsoluteLongSlow (JUMP)); } +/*****************************************************************************/ + /* JMP ********************************************************************* */ - -static void Op4C (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP))); +static void Op4C (void) { + S9xSetPCBase (ICPU.ShiftedPB + ((uint16)Absolute(JUMP))); #if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) - CPUShutdown(); + CPUShutdown (); #endif } -static void Op4CSlow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP))); +static void Op4CSlow (void) { + S9xSetPCBase (ICPU.ShiftedPB + ((uint16)AbsoluteSlow(JUMP))); #if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) - CPUShutdown(); + CPUShutdown (); #endif } -static void Op6C (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirect(JUMP))); +static void Op6C (void) { + S9xSetPCBase (ICPU.ShiftedPB + ((uint16)AbsoluteIndirect(JUMP))); } -static void Op6CSlow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirectSlow(JUMP))); +static void Op6CSlow (void) { + S9xSetPCBase (ICPU.ShiftedPB + ((uint16)AbsoluteIndirectSlow(JUMP))); } -static void Op7C (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirect(JUMP))); +static void Op7C (void) { + S9xSetPCBase (ICPU.ShiftedPB + ((uint16)AbsoluteIndexedIndirect(JUMP))); } -static void Op7CSlow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirectSlow(JUMP))); +static void Op7CSlow (void) { + S9xSetPCBase (ICPU.ShiftedPB + ((uint16)AbsoluteIndexedIndirectSlow(JUMP))); } +/*****************************************************************************/ + /* JSL/RTL ***************************************************************** */ - -static void Op22E1 (void) -{ - // Note: JSL is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint32 addr = AbsoluteLong(JSR); - PushB(Registers.PB); - PushW(Registers.PCw - 1); - Registers.SH = 1; - S9xSetPCBase(addr); +static void Op22E1 (void) { + /* Note: JSL is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + uint32 addr = AbsoluteLong (JSR); + PushB (Registers.PB); + PushW (Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase (addr); } -static void Op22E0 (void) -{ - uint32 addr = AbsoluteLong(JSR); - PushB(Registers.PB); - PushW(Registers.PCw - 1); - S9xSetPCBase(addr); +static void Op22E0 (void) { + uint32 addr = AbsoluteLong (JSR); + PushB (Registers.PB); + PushW (Registers.PCw - 1); + S9xSetPCBase (addr); } -static void Op22Slow (void) -{ - uint32 addr = AbsoluteLongSlow(JSR); - PushB(Registers.PB); - PushW(Registers.PCw - 1); - if (CheckEmulation()) - Registers.SH = 1; - S9xSetPCBase(addr); +static void Op22Slow (void) { + uint32 addr = AbsoluteLongSlow (JSR); + PushB (Registers.PB); + PushW (Registers.PCw - 1); + if(CheckEmulation()) Registers.SH = 1; + S9xSetPCBase (addr); } -static void Op6BE1 (void) -{ - // Note: RTL is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - PullB(Registers.PB); - Registers.SH = 1; - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); +static void Op6BE1 (void) { + /* Note: RTL is a new instruction, and so doesn't respect the emu-mode + * stack bounds */ + AddCycles(TWO_CYCLES); + PullW (Registers.PCw); + PullB (Registers.PB); + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); } -static void Op6BE0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - PullB(Registers.PB); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); +static void Op6BE0 (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.PCw); + PullB (Registers.PB); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); } -static void Op6BSlow (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - PullB(Registers.PB); - if (CheckEmulation()) - Registers.SH = 1; - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); +static void Op6BSlow (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.PCw); + PullB (Registers.PB); + if(CheckEmulation()) Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); } +/*****************************************************************************/ + /* JSR/RTS ***************************************************************** */ - -static void Op20E1 (void) -{ - uint16 addr = Absolute(JSR); - AddCycles(ONE_CYCLE); - PushWE(Registers.PCw - 1); - S9xSetPCBase(ICPU.ShiftedPB + addr); +static void Op20E1 (void) { + uint16 addr = Absolute (JSR); + AddCycles(ONE_CYCLE); + PushWE (Registers.PCw - 1); + S9xSetPCBase (ICPU.ShiftedPB + addr); } -static void Op20E0 (void) -{ - uint16 addr = Absolute(JSR); - AddCycles(ONE_CYCLE); - PushW(Registers.PCw - 1); - S9xSetPCBase(ICPU.ShiftedPB + addr); +static void Op20E0 (void) { + uint16 addr = Absolute (JSR); + AddCycles(ONE_CYCLE); + PushW (Registers.PCw - 1); + S9xSetPCBase (ICPU.ShiftedPB + addr); } -static void Op20Slow (void) -{ - uint16 addr = AbsoluteSlow(JSR); - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushWE(Registers.PCw - 1); - } - else - { - PushW(Registers.PCw - 1); - } - - S9xSetPCBase(ICPU.ShiftedPB + addr); +static void Op20Slow (void) { + uint16 addr = AbsoluteSlow (JSR); + AddCycles(ONE_CYCLE); + if(CheckEmulation()){ + PushWE (Registers.PCw - 1); + } else { + PushW (Registers.PCw - 1); + } + S9xSetPCBase (ICPU.ShiftedPB + addr); } -static void OpFCE1 (void) -{ - // Note: JSR (a,X) is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 addr = AbsoluteIndexedIndirect(JSR); - PushW(Registers.PCw - 1); - Registers.SH = 1; - S9xSetPCBase(ICPU.ShiftedPB + addr); +static void OpFCE1 (void) { + /* Note: JSR (a,X) is a new instruction, and so doesn't respect the + * emu-mode stack bounds */ + uint16 addr = AbsoluteIndexedIndirect (JSR); + PushW (Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase (ICPU.ShiftedPB + addr); } -static void OpFCE0 (void) -{ - uint16 addr = AbsoluteIndexedIndirect(JSR); - PushW(Registers.PCw - 1); - S9xSetPCBase(ICPU.ShiftedPB + addr); +static void OpFCE0 (void) { + uint16 addr = AbsoluteIndexedIndirect (JSR); + PushW (Registers.PCw - 1); + S9xSetPCBase (ICPU.ShiftedPB + addr); } -static void OpFCSlow (void) -{ - uint16 addr = AbsoluteIndexedIndirectSlow(JSR); - PushW(Registers.PCw - 1); - if (CheckEmulation()) - Registers.SH = 1; - S9xSetPCBase(ICPU.ShiftedPB + addr); +static void OpFCSlow (void) { + uint16 addr = AbsoluteIndexedIndirectSlow (JSR); + PushW (Registers.PCw - 1); + if(CheckEmulation()) Registers.SH = 1; + S9xSetPCBase (ICPU.ShiftedPB + addr); } -static void Op60E1 (void) -{ - AddCycles(TWO_CYCLES); - PullWE(Registers.PCw); - AddCycles(ONE_CYCLE); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); +static void Op60E1 (void) { + AddCycles(TWO_CYCLES); + PullWE (Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase (Registers.PBPC); } -static void Op60E0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - AddCycles(ONE_CYCLE); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); +static void Op60E0 (void) { + AddCycles(TWO_CYCLES); + PullW (Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase (Registers.PBPC); } -static void Op60Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullWE(Registers.PCw); - } - else - { - PullW(Registers.PCw); - } - - AddCycles(ONE_CYCLE); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); +static void Op60Slow (void) { + AddCycles(TWO_CYCLES); + if(CheckEmulation()){ + PullWE (Registers.PCw); + } else { + PullW (Registers.PCw); + } + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase (Registers.PBPC); } +/*****************************************************************************/ + /* MVN/MVP ***************************************************************** */ +static void Op54X1 (void) { + uint32 SrcBank; -static void Op54X1 (void) -{ - uint32 SrcBank; + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); + S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + Registers.XL++; + Registers.YL++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; - Registers.XL++; - Registers.YL++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); + AddCycles(TWO_CYCLES); } -static void Op54X0 (void) -{ - uint32 SrcBank; +static void Op54X0 (void) { + uint32 SrcBank; - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); - Registers.X.W++; - Registers.Y.W++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; + Registers.X.W++; + Registers.Y.W++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; - AddCycles(TWO_CYCLES); + AddCycles(TWO_CYCLES); } -static void Op54Slow (void) -{ - uint32 SrcBank; +static void Op54Slow (void) { + uint32 SrcBank; - OpenBus = Registers.DB = Immediate8Slow(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8Slow(NONE); + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); - if (CheckIndex()) - { - Registers.XL++; - Registers.YL++; - } - else - { - Registers.X.W++; - Registers.Y.W++; - } + if(CheckIndex()){ + Registers.XL++; + Registers.YL++; + } else { + Registers.X.W++; + Registers.Y.W++; + } + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); + AddCycles(TWO_CYCLES); } -static void Op44X1 (void) -{ - uint32 SrcBank; +static void Op44X1 (void) { + uint32 SrcBank; - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); - Registers.XL--; - Registers.YL--; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; + Registers.XL--; + Registers.YL--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; - AddCycles(TWO_CYCLES); + AddCycles(TWO_CYCLES); } -static void Op44X0 (void) -{ - uint32 SrcBank; +static void Op44X0 (void) { + uint32 SrcBank; - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); - Registers.X.W--; - Registers.Y.W--; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; + Registers.X.W--; + Registers.Y.W--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; - AddCycles(TWO_CYCLES); + AddCycles(TWO_CYCLES); } -static void Op44Slow (void) -{ - uint32 SrcBank; +static void Op44Slow (void) { + uint32 SrcBank; - OpenBus = Registers.DB = Immediate8Slow(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8Slow(NONE); + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); - if (CheckIndex()) - { - Registers.XL--; - Registers.YL--; - } - else - { - Registers.X.W--; - Registers.Y.W--; - } + if(CheckIndex()){ + Registers.XL--; + Registers.YL--; + } else { + Registers.X.W--; + Registers.Y.W--; + } + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); + AddCycles(TWO_CYCLES); } +/*****************************************************************************/ + /* REP/SEP ***************************************************************** */ +static void OpC2 (void) { + uint8 Work8 = ~Immediate8(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; -static void OpC2 (void) -{ - uint8 Work8 = ~Immediate8(READ); - Registers.PL &= Work8; - ICPU._Carry &= Work8; - ICPU._Overflow &= (Work8 >> 6); - ICPU._Negative &= Work8; - ICPU._Zero |= ~Work8 & Zero; - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); + AddCycles(ONE_CYCLE); + if (CheckEmulation()) { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ } -static void OpC2Slow (void) -{ - uint8 Work8 = ~Immediate8Slow(READ); - Registers.PL &= Work8; - ICPU._Carry &= Work8; - ICPU._Overflow &= (Work8 >> 6); - ICPU._Negative &= Work8; - ICPU._Zero |= ~Work8 & Zero; +static void OpC2Slow (void) { + uint8 Work8 = ~Immediate8Slow(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); + AddCycles(ONE_CYCLE); + if (CheckEmulation()) { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ } -static void OpE2 (void) -{ - uint8 Work8 = Immediate8(READ); - Registers.PL |= Work8; - ICPU._Carry |= Work8 & 1; - ICPU._Overflow |= (Work8 >> 6) & 1; - ICPU._Negative |= Work8; - if (Work8 & Zero) - ICPU._Zero = 0; +static void OpE2 (void) { + uint8 Work8 = Immediate8(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) ICPU._Zero = 0; - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); + AddCycles(ONE_CYCLE); + if (CheckEmulation()) { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); } -static void OpE2Slow (void) -{ - uint8 Work8 = Immediate8Slow(READ); - Registers.PL |= Work8; - ICPU._Carry |= Work8 & 1; - ICPU._Overflow |= (Work8 >> 6) & 1; - ICPU._Negative |= Work8; - if (Work8 & Zero) - ICPU._Zero = 0; +static void OpE2Slow (void) { + uint8 Work8 = Immediate8Slow(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) ICPU._Zero = 0; - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); + AddCycles(ONE_CYCLE); + if (CheckEmulation()) { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); } +/*****************************************************************************/ + /* XBA ********************************************************************* */ - -static void OpEB (void) -{ - uint8 Work8 = Registers.AL; - Registers.AL = Registers.AH; - Registers.AH = Work8; - SetZN(Registers.AL); - AddCycles(TWO_CYCLES); +static void OpEB (void) { + uint8 Work8 = Registers.AL; + Registers.AL = Registers.AH; + Registers.AH = Work8; + SetZN (Registers.AL); + AddCycles(TWO_CYCLES); } +/*****************************************************************************/ + /* RTI ********************************************************************* */ +static void Op40Slow (void) { + AddCycles(TWO_CYCLES); + if (!CheckEmulation()) { + PullB (Registers.PL); + S9xUnpackStatus (); + PullW (Registers.PCw); + PullB (Registers.PB); + OpenBus = Registers.PB; + ICPU.ShiftedPB = Registers.PB << 16; + } else { + PullBE (Registers.PL); + S9xUnpackStatus (); + PullWE (Registers.PCw); + OpenBus = Registers.PCh; + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + S9xSetPCBase (Registers.PBPC); -static void Op40Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (!CheckEmulation()) - { - PullB(Registers.PL); - S9xUnpackStatus(); - PullW(Registers.PCw); - PullB(Registers.PB); - OpenBus = Registers.PB; - ICPU.ShiftedPB = Registers.PB << 16; - } - else - { - PullBE(Registers.PL); - S9xUnpackStatus(); - PullWE(Registers.PCw); - OpenBus = Registers.PCh; - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - S9xSetPCBase(Registers.PBPC); - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); + if (CheckIndex ()) { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ } -/* STP/WAI ***************************************************************** */ +/*****************************************************************************/ +/* STP/WAI/WDM ************************************************************* */ // WAI -static void OpCB (void) -{ - // Ok, let's just C-ify the ASM versions separately. +static void OpCB (void) { + // Ok, let's just C-ify the ASM versions separately. #ifdef SA1_OPCODES - SA1.WaitingForInterrupt = TRUE; - Registers.PCw--; + SA1.WaitingForInterrupt = TRUE; + Registers.PCw--; #if 0 - // XXX: FIXME - if (Settings.Shutdown) - { - SA1.Cycles = SA1.NextEvent; + // XXX: FIXME + if(Settings.Shutdown){ + SA1.Cycles = SA1.NextEvent; SA1.Executing = FALSE; //S9xAPUExecute(); // FIXME SA1.Executing = TRUE; - } + } #endif -#else // SA1_OPCODES +#else // SA1_OPCODES #if 0 - if (CPU.IRQActive) - AddCycles(TWO_CYCLES); - else + if (CPU.IRQActive) { + AddCycles(TWO_CYCLES); + } else #endif - { - CPU.WaitingForInterrupt = TRUE; - Registers.PCw--; - #ifdef CPU_SHUTDOWN - if (Settings.Shutdown) - { - CPU.Cycles = CPU.NextEvent; + { + CPU.WaitingForInterrupt = TRUE; + Registers.PCw--; +#ifdef CPU_SHUTDOWN + if (Settings.Shutdown) + { + CPU.Cycles = CPU.NextEvent; ICPU.CPUExecuting = FALSE; S9xAPUExecute(); ICPU.CPUExecuting = TRUE; - } + } else - AddCycles(TWO_CYCLES); - #else + AddCycles(TWO_CYCLES); +#else AddCycles(TWO_CYCLES); #endif - } -#endif // SA1_OPCODES + } +#endif // SA1_OPCODES } // STP -static void OpDB (void) -{ - Registers.PCw--; - CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG; +static void OpDB (void) { + Registers.PCw--; + CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG; } -/* WDM (Reserved S9xOpcode) ************************************************ */ - +// WDM (Reserved S9xOpcode) #ifdef DEBUGGER -extern FILE *trace, *trace2; +extern FILE *trace; +extern FILE *trace2; #endif - -static void Op42 (void) -{ +static void Op42 (void) { #ifdef DEBUGGER - uint8 byte = (uint8) S9xGetWord(Registers.PBPC); -#else - S9xGetWord(Registers.PBPC); + uint8 byte = (uint8) #endif - Registers.PCw++; - + S9xGetWord(Registers.PBPC); + Registers.PCw++; #ifdef DEBUGGER - // Hey, let's use this to trigger debug modes. - switch (byte) - { - case 0xdb: // "STP" = Enter debug mode - CPU.Flags |= DEBUG_MODE_FLAG; - break; + // Hey, let's use this to trigger debug modes + switch(byte){ + case 0xdb: // "STP" = Enter debug mode + CPU.Flags |= DEBUG_MODE_FLAG; + break; +#ifndef SA1_OPCODES + case 0xe2: // "SEP" = Trace on + if(!(CPU.Flags & TRACE_FLAG)) {{ + char buf[25]; + CPU.Flags |= TRACE_FLAG; + snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if(trace != NULL) fclose(trace); + trace = fopen ("WDMtrace.log", "ab"); + }} + break; + case 0xc2: // "REP" = Trace off + if(CPU.Flags & TRACE_FLAG) {{ + char buf[26]; + CPU.Flags &= ~TRACE_FLAG; + snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if(trace != NULL) fclose(trace); + trace = NULL; + }} + break; +#endif + case 0x42: // "WDM" = Snapshot + { + char def [PATH_MAX]; + char filename [PATH_MAX]; + char drive [_MAX_DRIVE]; + char dir [_MAX_DIR]; + char ext [_MAX_EXT]; - #ifndef SA1_OPCODES - case 0xe2: // "SEP" = Trace on - if (!(CPU.Flags & TRACE_FLAG)) - { - char buf[25]; - CPU.Flags |= TRACE_FLAG; - snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw); - S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); - if (trace != NULL) - fclose(trace); - trace = fopen("WDMtrace.log", "ab"); - } + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + snprintf (filename, PATH_MAX, "%s%s%s-%06X.wdm", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC&0xffffff); + sprintf (def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename); + S9xMessage (S9X_DEBUG, S9X_DEBUG_OUTPUT, def); + Snapshot(filename); + } + break; - break; - - case 0xc2: // "REP" = Trace off - if (CPU.Flags & TRACE_FLAG) - { - char buf[26]; - CPU.Flags &= ~TRACE_FLAG; - snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw); - S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); - if (trace != NULL) - fclose(trace); - trace = NULL; - } - - break; - #endif - - case 0x42: // "WDM" = Snapshot - char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1]; - - _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff); - sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename); - S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def); - S9xFreezeGame(filename); - - break; - - default: - break; - } + default: + break; + } #endif } -/* CPU-S9xOpcodes Definitions ************************************************/ +/*****************************************************************************/ -struct SOpcodes S9xOpcodesM1X1[256] = -{ - { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, - { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, - { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, - { Op0FM1 }, { Op10E0 }, { Op11E0M1X1 }, { Op12E0M1 }, { Op13M1 }, - { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, - { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, - { Op1EM1X1 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, - { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, - { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, - { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X1 }, - { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, - { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, - { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, - { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, - { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, - { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, - { Op50E0 }, { Op51E0M1X1 }, { Op52E0M1 }, { Op53M1 }, { Op54X1 }, - { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, - { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, - { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, - { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, - { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, - { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X1 }, { Op72E0M1 }, - { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, - { Op78 }, { Op79M1X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, - { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, - { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, - { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, - { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E0 }, - { Op91E0M1X1 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X1 }, { Op95E0M1 }, - { Op96E0X1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, - { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, - { OpA0X1 }, { OpA1E0M1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, - { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, - { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, - { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X1 }, { OpB2E0M1 }, { OpB3M1 }, - { OpB4E0X1 }, { OpB5E0M1 }, { OpB6E0X1 }, { OpB7M1 }, { OpB8 }, - { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, - { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E0M1 }, { OpC2 }, - { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, - { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, - { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X1 }, - { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, - { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE0X1 }, { OpDB }, - { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, - { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, - { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, - { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, - { OpF0E0 }, { OpF1E0M1X1 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, - { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, - { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM1X1 }, { OpFEM1X1 }, - { OpFFM1 } +/*****************************************************************************/ +/* CPU-S9xOpcodes Definitions */ +/*****************************************************************************/ +struct SOpcodes S9xOpcodesM1X1[256] = { + {Op00}, {Op01E0M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08E0}, {Op09M1}, + {Op0AM1}, {Op0BE0}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10E0}, {Op11E0M1X1}, {Op12E0M1}, {Op13M1}, + {Op14M1}, {Op15E0M1}, {Op16E0M1}, {Op17M1}, {Op18}, + {Op19M1X1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1X1}, + {Op1EM1X1}, {Op1FM1}, {Op20E0}, {Op21E0M1}, {Op22E0}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28E0}, {Op29M1}, {Op2AM1}, {Op2BE0}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30E0}, {Op31E0M1X1}, + {Op32E0M1}, {Op33M1}, {Op34E0M1}, {Op35E0M1}, {Op36E0M1}, + {Op37M1}, {Op38}, {Op39M1X1}, {Op3AM1}, {Op3B}, + {Op3CM1X1}, {Op3DM1X1}, {Op3EM1X1}, {Op3FM1}, {Op40Slow}, + {Op41E0M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48E0M1}, {Op49M1}, {Op4AM1}, + {Op4BE0}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50E0}, {Op51E0M1X1}, {Op52E0M1}, {Op53M1}, {Op54X1}, + {Op55E0M1}, {Op56E0M1}, {Op57M1}, {Op58}, {Op59M1X1}, + {Op5AE0X1}, {Op5B}, {Op5C}, {Op5DM1X1}, {Op5EM1X1}, + {Op5FM1}, {Op60E0}, {Op61E0M1}, {Op62E0}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68E0M1}, + {Op69M1}, {Op6AM1}, {Op6BE0}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70E0}, {Op71E0M1X1}, {Op72E0M1}, + {Op73M1}, {Op74E0M1}, {Op75E0M1}, {Op76E0M1}, {Op77M1}, + {Op78}, {Op79M1X1}, {Op7AE0X1}, {Op7B}, {Op7C}, + {Op7DM1X1}, {Op7EM1X1}, {Op7FM1}, {Op80E0}, {Op81E0M1}, + {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, + {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8BE0}, + {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90E0}, + {Op91E0M1X1}, {Op92E0M1}, {Op93M1}, {Op94E0X1}, {Op95E0M1}, + {Op96E0X1}, {Op97M1}, {Op98M1}, {Op99M1X1}, {Op9A}, + {Op9BX1}, {Op9CM1}, {Op9DM1X1}, {Op9EM1X1}, {Op9FM1}, + {OpA0X1}, {OpA1E0M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, + {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, + {OpAAX1}, {OpABE0}, {OpACX1}, {OpADM1}, {OpAEX1}, + {OpAFM1}, {OpB0E0}, {OpB1E0M1X1}, {OpB2E0M1}, {OpB3M1}, + {OpB4E0X1}, {OpB5E0M1}, {OpB6E0X1}, {OpB7M1}, {OpB8}, + {OpB9M1X1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1X1}, + {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1E0M1}, {OpC2}, + {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0E0}, {OpD1E0M1X1}, + {OpD2E0M1}, {OpD3M1}, {OpD4E0}, {OpD5E0M1}, {OpD6E0M1}, + {OpD7M1}, {OpD8}, {OpD9M1X1}, {OpDAE0X1}, {OpDB}, + {OpDC}, {OpDDM1X1}, {OpDEM1X1}, {OpDFM1}, {OpE0X1}, + {OpE1E0M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0E0}, {OpF1E0M1X1}, {OpF2E0M1}, {OpF3M1}, {OpF4E0}, + {OpF5E0M1}, {OpF6E0M1}, {OpF7M1}, {OpF8}, {OpF9M1X1}, + {OpFAE0X1}, {OpFB}, {OpFCE0}, {OpFDM1X1}, {OpFEM1X1}, + {OpFFM1} }; -struct SOpcodes S9xOpcodesE1[256] = -{ - { Op00 }, { Op01E1 }, { Op02 }, { Op03M1 }, { Op04M1 }, - { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E1 }, { Op09M1 }, - { Op0AM1 }, { Op0BE1 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, - { Op0FM1 }, { Op10E1 }, { Op11E1 }, { Op12E1 }, { Op13M1 }, - { Op14M1 }, { Op15E1 }, { Op16E1 }, { Op17M1 }, { Op18 }, - { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, - { Op1EM1X1 }, { Op1FM1 }, { Op20E1 }, { Op21E1 }, { Op22E1 }, - { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, - { Op28E1 }, { Op29M1 }, { Op2AM1 }, { Op2BE1 }, { Op2CM1 }, - { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E1 }, { Op31E1 }, - { Op32E1 }, { Op33M1 }, { Op34E1 }, { Op35E1 }, { Op36E1 }, - { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, - { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, - { Op41E1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, - { Op46M1 }, { Op47M1 }, { Op48E1 }, { Op49M1 }, { Op4AM1 }, - { Op4BE1 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, - { Op50E1 }, { Op51E1 }, { Op52E1 }, { Op53M1 }, { Op54X1 }, - { Op55E1 }, { Op56E1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, - { Op5AE1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, - { Op5FM1 }, { Op60E1 }, { Op61E1 }, { Op62E1 }, { Op63M1 }, - { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E1 }, - { Op69M1 }, { Op6AM1 }, { Op6BE1 }, { Op6C }, { Op6DM1 }, - { Op6EM1 }, { Op6FM1 }, { Op70E1 }, { Op71E1 }, { Op72E1 }, - { Op73M1 }, { Op74E1 }, { Op75E1 }, { Op76E1 }, { Op77M1 }, - { Op78 }, { Op79M1X1 }, { Op7AE1 }, { Op7B }, { Op7C }, - { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E1 }, { Op81E1 }, - { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, - { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE1 }, - { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E1 }, - { Op91E1 }, { Op92E1 }, { Op93M1 }, { Op94E1 }, { Op95E1 }, - { Op96E1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, - { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, - { OpA0X1 }, { OpA1E1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, - { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, - { OpAAX1 }, { OpABE1 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, - { OpAFM1 }, { OpB0E1 }, { OpB1E1 }, { OpB2E1 }, { OpB3M1 }, - { OpB4E1 }, { OpB5E1 }, { OpB6E1 }, { OpB7M1 }, { OpB8 }, - { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, - { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E1 }, { OpC2 }, - { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, - { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, - { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E1 }, { OpD1E1 }, - { OpD2E1 }, { OpD3M1 }, { OpD4E1 }, { OpD5E1 }, { OpD6E1 }, - { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE1 }, { OpDB }, - { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, - { OpE1E1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, - { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, - { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, - { OpF0E1 }, { OpF1E1 }, { OpF2E1 }, { OpF3M1 }, { OpF4E1 }, - { OpF5E1 }, { OpF6E1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, - { OpFAE1 }, { OpFB }, { OpFCE1 }, { OpFDM1X1 }, { OpFEM1X1 }, - { OpFFM1 } +struct SOpcodes S9xOpcodesE1[256] = { + {Op00}, {Op01E1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08E1}, {Op09M1}, + {Op0AM1}, {Op0BE1}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10E1}, {Op11E1}, {Op12E1}, {Op13M1}, + {Op14M1}, {Op15E1}, {Op16E1}, {Op17M1}, {Op18}, + {Op19M1X1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1X1}, + {Op1EM1X1}, {Op1FM1}, {Op20E1}, {Op21E1}, {Op22E1}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28E1}, {Op29M1}, {Op2AM1}, {Op2BE1}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30E1}, {Op31E1}, + {Op32E1}, {Op33M1}, {Op34E1}, {Op35E1}, {Op36E1}, + {Op37M1}, {Op38}, {Op39M1X1}, {Op3AM1}, {Op3B}, + {Op3CM1X1}, {Op3DM1X1}, {Op3EM1X1}, {Op3FM1}, {Op40Slow}, + {Op41E1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48E1}, {Op49M1}, {Op4AM1}, + {Op4BE1}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50E1}, {Op51E1}, {Op52E1}, {Op53M1}, {Op54X1}, + {Op55E1}, {Op56E1}, {Op57M1}, {Op58}, {Op59M1X1}, + {Op5AE1}, {Op5B}, {Op5C}, {Op5DM1X1}, {Op5EM1X1}, + {Op5FM1}, {Op60E1}, {Op61E1}, {Op62E1}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68E1}, + {Op69M1}, {Op6AM1}, {Op6BE1}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70E1}, {Op71E1}, {Op72E1}, + {Op73M1}, {Op74E1}, {Op75E1}, {Op76E1}, {Op77M1}, + {Op78}, {Op79M1X1}, {Op7AE1}, {Op7B}, {Op7C}, + {Op7DM1X1}, {Op7EM1X1}, {Op7FM1}, {Op80E1}, {Op81E1}, + {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, + {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8BE1}, + {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90E1}, + {Op91E1}, {Op92E1}, {Op93M1}, {Op94E1}, {Op95E1}, + {Op96E1}, {Op97M1}, {Op98M1}, {Op99M1X1}, {Op9A}, + {Op9BX1}, {Op9CM1}, {Op9DM1X1}, {Op9EM1X1}, {Op9FM1}, + {OpA0X1}, {OpA1E1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, + {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, + {OpAAX1}, {OpABE1}, {OpACX1}, {OpADM1}, {OpAEX1}, + {OpAFM1}, {OpB0E1}, {OpB1E1}, {OpB2E1}, {OpB3M1}, + {OpB4E1}, {OpB5E1}, {OpB6E1}, {OpB7M1}, {OpB8}, + {OpB9M1X1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1X1}, + {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1E1}, {OpC2}, + {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0E1}, {OpD1E1}, + {OpD2E1}, {OpD3M1}, {OpD4E1}, {OpD5E1}, {OpD6E1}, + {OpD7M1}, {OpD8}, {OpD9M1X1}, {OpDAE1}, {OpDB}, + {OpDC}, {OpDDM1X1}, {OpDEM1X1}, {OpDFM1}, {OpE0X1}, + {OpE1E1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0E1}, {OpF1E1}, {OpF2E1}, {OpF3M1}, {OpF4E1}, + {OpF5E1}, {OpF6E1}, {OpF7M1}, {OpF8}, {OpF9M1X1}, + {OpFAE1}, {OpFB}, {OpFCE1}, {OpFDM1X1}, {OpFEM1X1}, + {OpFFM1} }; -struct SOpcodes S9xOpcodesM1X0[256] = -{ - { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, - { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, - { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, - { Op0FM1 }, { Op10E0 }, { Op11E0M1X0 }, { Op12E0M1 }, { Op13M1 }, - { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, - { Op19M1X0 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X0 }, - { Op1EM1X0 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, - { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, - { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, - { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X0 }, - { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, - { Op37M1 }, { Op38 }, { Op39M1X0 }, { Op3AM1 }, { Op3B }, - { Op3CM1X0 }, { Op3DM1X0 }, { Op3EM1X0 }, { Op3FM1 }, { Op40Slow }, - { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X0 }, { Op45M1 }, - { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, - { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, - { Op50E0 }, { Op51E0M1X0 }, { Op52E0M1 }, { Op53M1 }, { Op54X0 }, - { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X0 }, - { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM1X0 }, { Op5EM1X0 }, - { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, - { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, - { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, - { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X0 }, { Op72E0M1 }, - { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, - { Op78 }, { Op79M1X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, - { Op7DM1X0 }, { Op7EM1X0 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, - { Op82 }, { Op83M1 }, { Op84X0 }, { Op85M1 }, { Op86X0 }, - { Op87M1 }, { Op88X0 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, - { Op8CX0 }, { Op8DM1 }, { Op8EX0 }, { Op8FM1 }, { Op90E0 }, - { Op91E0M1X0 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X0 }, { Op95E0M1 }, - { Op96E0X0 }, { Op97M1 }, { Op98M1 }, { Op99M1X0 }, { Op9A }, - { Op9BX0 }, { Op9CM1 }, { Op9DM1X0 }, { Op9EM1X0 }, { Op9FM1 }, - { OpA0X0 }, { OpA1E0M1 }, { OpA2X0 }, { OpA3M1 }, { OpA4X0 }, - { OpA5M1 }, { OpA6X0 }, { OpA7M1 }, { OpA8X0 }, { OpA9M1 }, - { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM1 }, { OpAEX0 }, - { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X0 }, { OpB2E0M1 }, { OpB3M1 }, - { OpB4E0X0 }, { OpB5E0M1 }, { OpB6E0X0 }, { OpB7M1 }, { OpB8 }, - { OpB9M1X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM1X0 }, - { OpBEX0 }, { OpBFM1 }, { OpC0X0 }, { OpC1E0M1 }, { OpC2 }, - { OpC3M1 }, { OpC4X0 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, - { OpC8X0 }, { OpC9M1 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, - { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X0 }, - { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, - { OpD7M1 }, { OpD8 }, { OpD9M1X0 }, { OpDAE0X0 }, { OpDB }, - { OpDC }, { OpDDM1X0 }, { OpDEM1X0 }, { OpDFM1 }, { OpE0X0 }, - { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X0 }, { OpE5M1 }, - { OpE6M1 }, { OpE7M1 }, { OpE8X0 }, { OpE9M1 }, { OpEA }, - { OpEB }, { OpECX0 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, - { OpF0E0 }, { OpF1E0M1X0 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, - { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X0 }, - { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM1X0 }, { OpFEM1X0 }, - { OpFFM1 } +struct SOpcodes S9xOpcodesM1X0[256] = { + {Op00}, {Op01E0M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08E0}, {Op09M1}, + {Op0AM1}, {Op0BE0}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10E0}, {Op11E0M1X0}, {Op12E0M1}, {Op13M1}, + {Op14M1}, {Op15E0M1}, {Op16E0M1}, {Op17M1}, {Op18}, + {Op19M1X0}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1X0}, + {Op1EM1X0}, {Op1FM1}, {Op20E0}, {Op21E0M1}, {Op22E0}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28E0}, {Op29M1}, {Op2AM1}, {Op2BE0}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30E0}, {Op31E0M1X0}, + {Op32E0M1}, {Op33M1}, {Op34E0M1}, {Op35E0M1}, {Op36E0M1}, + {Op37M1}, {Op38}, {Op39M1X0}, {Op3AM1}, {Op3B}, + {Op3CM1X0}, {Op3DM1X0}, {Op3EM1X0}, {Op3FM1}, {Op40Slow}, + {Op41E0M1}, {Op42}, {Op43M1}, {Op44X0}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48E0M1}, {Op49M1}, {Op4AM1}, + {Op4BE0}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50E0}, {Op51E0M1X0}, {Op52E0M1}, {Op53M1}, {Op54X0}, + {Op55E0M1}, {Op56E0M1}, {Op57M1}, {Op58}, {Op59M1X0}, + {Op5AE0X0}, {Op5B}, {Op5C}, {Op5DM1X0}, {Op5EM1X0}, + {Op5FM1}, {Op60E0}, {Op61E0M1}, {Op62E0}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68E0M1}, + {Op69M1}, {Op6AM1}, {Op6BE0}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70E0}, {Op71E0M1X0}, {Op72E0M1}, + {Op73M1}, {Op74E0M1}, {Op75E0M1}, {Op76E0M1}, {Op77M1}, + {Op78}, {Op79M1X0}, {Op7AE0X0}, {Op7B}, {Op7C}, + {Op7DM1X0}, {Op7EM1X0}, {Op7FM1}, {Op80E0}, {Op81E0M1}, + {Op82}, {Op83M1}, {Op84X0}, {Op85M1}, {Op86X0}, + {Op87M1}, {Op88X0}, {Op89M1}, {Op8AM1}, {Op8BE0}, + {Op8CX0}, {Op8DM1}, {Op8EX0}, {Op8FM1}, {Op90E0}, + {Op91E0M1X0}, {Op92E0M1}, {Op93M1}, {Op94E0X0}, {Op95E0M1}, + {Op96E0X0}, {Op97M1}, {Op98M1}, {Op99M1X0}, {Op9A}, + {Op9BX0}, {Op9CM1}, {Op9DM1X0}, {Op9EM1X0}, {Op9FM1}, + {OpA0X0}, {OpA1E0M1}, {OpA2X0}, {OpA3M1}, {OpA4X0}, + {OpA5M1}, {OpA6X0}, {OpA7M1}, {OpA8X0}, {OpA9M1}, + {OpAAX0}, {OpABE0}, {OpACX0}, {OpADM1}, {OpAEX0}, + {OpAFM1}, {OpB0E0}, {OpB1E0M1X0}, {OpB2E0M1}, {OpB3M1}, + {OpB4E0X0}, {OpB5E0M1}, {OpB6E0X0}, {OpB7M1}, {OpB8}, + {OpB9M1X0}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM1X0}, + {OpBEX0}, {OpBFM1}, {OpC0X0}, {OpC1E0M1}, {OpC2}, + {OpC3M1}, {OpC4X0}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X0}, {OpC9M1}, {OpCAX0}, {OpCB}, {OpCCX0}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0E0}, {OpD1E0M1X0}, + {OpD2E0M1}, {OpD3M1}, {OpD4E0}, {OpD5E0M1}, {OpD6E0M1}, + {OpD7M1}, {OpD8}, {OpD9M1X0}, {OpDAE0X0}, {OpDB}, + {OpDC}, {OpDDM1X0}, {OpDEM1X0}, {OpDFM1}, {OpE0X0}, + {OpE1E0M1}, {OpE2}, {OpE3M1}, {OpE4X0}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X0}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX0}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0E0}, {OpF1E0M1X0}, {OpF2E0M1}, {OpF3M1}, {OpF4E0}, + {OpF5E0M1}, {OpF6E0M1}, {OpF7M1}, {OpF8}, {OpF9M1X0}, + {OpFAE0X0}, {OpFB}, {OpFCE0}, {OpFDM1X0}, {OpFEM1X0}, + {OpFFM1} }; -struct SOpcodes S9xOpcodesM0X0[256] = -{ - { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, - { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, - { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, - { Op0FM0 }, { Op10E0 }, { Op11E0M0X0 }, { Op12E0M0 }, { Op13M0 }, - { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, - { Op19M0X0 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X0 }, - { Op1EM0X0 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, - { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, - { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, - { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X0 }, - { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, - { Op37M0 }, { Op38 }, { Op39M0X0 }, { Op3AM0 }, { Op3B }, - { Op3CM0X0 }, { Op3DM0X0 }, { Op3EM0X0 }, { Op3FM0 }, { Op40Slow }, - { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X0 }, { Op45M0 }, - { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, - { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, - { Op50E0 }, { Op51E0M0X0 }, { Op52E0M0 }, { Op53M0 }, { Op54X0 }, - { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X0 }, - { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM0X0 }, { Op5EM0X0 }, - { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, - { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, - { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, - { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X0 }, { Op72E0M0 }, - { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, - { Op78 }, { Op79M0X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, - { Op7DM0X0 }, { Op7EM0X0 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, - { Op82 }, { Op83M0 }, { Op84X0 }, { Op85M0 }, { Op86X0 }, - { Op87M0 }, { Op88X0 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, - { Op8CX0 }, { Op8DM0 }, { Op8EX0 }, { Op8FM0 }, { Op90E0 }, - { Op91E0M0X0 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X0 }, { Op95E0M0 }, - { Op96E0X0 }, { Op97M0 }, { Op98M0 }, { Op99M0X0 }, { Op9A }, - { Op9BX0 }, { Op9CM0 }, { Op9DM0X0 }, { Op9EM0X0 }, { Op9FM0 }, - { OpA0X0 }, { OpA1E0M0 }, { OpA2X0 }, { OpA3M0 }, { OpA4X0 }, - { OpA5M0 }, { OpA6X0 }, { OpA7M0 }, { OpA8X0 }, { OpA9M0 }, - { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM0 }, { OpAEX0 }, - { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X0 }, { OpB2E0M0 }, { OpB3M0 }, - { OpB4E0X0 }, { OpB5E0M0 }, { OpB6E0X0 }, { OpB7M0 }, { OpB8 }, - { OpB9M0X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM0X0 }, - { OpBEX0 }, { OpBFM0 }, { OpC0X0 }, { OpC1E0M0 }, { OpC2 }, - { OpC3M0 }, { OpC4X0 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, - { OpC8X0 }, { OpC9M0 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, - { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X0 }, - { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, - { OpD7M0 }, { OpD8 }, { OpD9M0X0 }, { OpDAE0X0 }, { OpDB }, - { OpDC }, { OpDDM0X0 }, { OpDEM0X0 }, { OpDFM0 }, { OpE0X0 }, - { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X0 }, { OpE5M0 }, - { OpE6M0 }, { OpE7M0 }, { OpE8X0 }, { OpE9M0 }, { OpEA }, - { OpEB }, { OpECX0 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, - { OpF0E0 }, { OpF1E0M0X0 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, - { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X0 }, - { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM0X0 }, { OpFEM0X0 }, - { OpFFM0 } +struct SOpcodes S9xOpcodesM0X0[256] = { + {Op00}, {Op01E0M0}, {Op02}, {Op03M0}, {Op04M0}, + {Op05M0}, {Op06M0}, {Op07M0}, {Op08E0}, {Op09M0}, + {Op0AM0}, {Op0BE0}, {Op0CM0}, {Op0DM0}, {Op0EM0}, + {Op0FM0}, {Op10E0}, {Op11E0M0X0}, {Op12E0M0}, {Op13M0}, + {Op14M0}, {Op15E0M0}, {Op16E0M0}, {Op17M0}, {Op18}, + {Op19M0X0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0X0}, + {Op1EM0X0}, {Op1FM0}, {Op20E0}, {Op21E0M0}, {Op22E0}, + {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, + {Op28E0}, {Op29M0}, {Op2AM0}, {Op2BE0}, {Op2CM0}, + {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30E0}, {Op31E0M0X0}, + {Op32E0M0}, {Op33M0}, {Op34E0M0}, {Op35E0M0}, {Op36E0M0}, + {Op37M0}, {Op38}, {Op39M0X0}, {Op3AM0}, {Op3B}, + {Op3CM0X0}, {Op3DM0X0}, {Op3EM0X0}, {Op3FM0}, {Op40Slow}, + {Op41E0M0}, {Op42}, {Op43M0}, {Op44X0}, {Op45M0}, + {Op46M0}, {Op47M0}, {Op48E0M0}, {Op49M0}, {Op4AM0}, + {Op4BE0}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, + {Op50E0}, {Op51E0M0X0}, {Op52E0M0}, {Op53M0}, {Op54X0}, + {Op55E0M0}, {Op56E0M0}, {Op57M0}, {Op58}, {Op59M0X0}, + {Op5AE0X0}, {Op5B}, {Op5C}, {Op5DM0X0}, {Op5EM0X0}, + {Op5FM0}, {Op60E0}, {Op61E0M0}, {Op62E0}, {Op63M0}, + {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68E0M0}, + {Op69M0}, {Op6AM0}, {Op6BE0}, {Op6C}, {Op6DM0}, + {Op6EM0}, {Op6FM0}, {Op70E0}, {Op71E0M0X0}, {Op72E0M0}, + {Op73M0}, {Op74E0M0}, {Op75E0M0}, {Op76E0M0}, {Op77M0}, + {Op78}, {Op79M0X0}, {Op7AE0X0}, {Op7B}, {Op7C}, + {Op7DM0X0}, {Op7EM0X0}, {Op7FM0}, {Op80E0}, {Op81E0M0}, + {Op82}, {Op83M0}, {Op84X0}, {Op85M0}, {Op86X0}, + {Op87M0}, {Op88X0}, {Op89M0}, {Op8AM0}, {Op8BE0}, + {Op8CX0}, {Op8DM0}, {Op8EX0}, {Op8FM0}, {Op90E0}, + {Op91E0M0X0}, {Op92E0M0}, {Op93M0}, {Op94E0X0}, {Op95E0M0}, + {Op96E0X0}, {Op97M0}, {Op98M0}, {Op99M0X0}, {Op9A}, + {Op9BX0}, {Op9CM0}, {Op9DM0X0}, {Op9EM0X0}, {Op9FM0}, + {OpA0X0}, {OpA1E0M0}, {OpA2X0}, {OpA3M0}, {OpA4X0}, + {OpA5M0}, {OpA6X0}, {OpA7M0}, {OpA8X0}, {OpA9M0}, + {OpAAX0}, {OpABE0}, {OpACX0}, {OpADM0}, {OpAEX0}, + {OpAFM0}, {OpB0E0}, {OpB1E0M0X0}, {OpB2E0M0}, {OpB3M0}, + {OpB4E0X0}, {OpB5E0M0}, {OpB6E0X0}, {OpB7M0}, {OpB8}, + {OpB9M0X0}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM0X0}, + {OpBEX0}, {OpBFM0}, {OpC0X0}, {OpC1E0M0}, {OpC2}, + {OpC3M0}, {OpC4X0}, {OpC5M0}, {OpC6M0}, {OpC7M0}, + {OpC8X0}, {OpC9M0}, {OpCAX0}, {OpCB}, {OpCCX0}, + {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0E0}, {OpD1E0M0X0}, + {OpD2E0M0}, {OpD3M0}, {OpD4E0}, {OpD5E0M0}, {OpD6E0M0}, + {OpD7M0}, {OpD8}, {OpD9M0X0}, {OpDAE0X0}, {OpDB}, + {OpDC}, {OpDDM0X0}, {OpDEM0X0}, {OpDFM0}, {OpE0X0}, + {OpE1E0M0}, {OpE2}, {OpE3M0}, {OpE4X0}, {OpE5M0}, + {OpE6M0}, {OpE7M0}, {OpE8X0}, {OpE9M0}, {OpEA}, + {OpEB}, {OpECX0}, {OpEDM0}, {OpEEM0}, {OpEFM0}, + {OpF0E0}, {OpF1E0M0X0}, {OpF2E0M0}, {OpF3M0}, {OpF4E0}, + {OpF5E0M0}, {OpF6E0M0}, {OpF7M0}, {OpF8}, {OpF9M0X0}, + {OpFAE0X0}, {OpFB}, {OpFCE0}, {OpFDM0X0}, {OpFEM0X0}, + {OpFFM0} }; -struct SOpcodes S9xOpcodesM0X1[256] = -{ - { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, - { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, - { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, - { Op0FM0 }, { Op10E0 }, { Op11E0M0X1 }, { Op12E0M0 }, { Op13M0 }, - { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, - { Op19M0X1 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X1 }, - { Op1EM0X1 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, - { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, - { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, - { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X1 }, - { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, - { Op37M0 }, { Op38 }, { Op39M0X1 }, { Op3AM0 }, { Op3B }, - { Op3CM0X1 }, { Op3DM0X1 }, { Op3EM0X1 }, { Op3FM0 }, { Op40Slow }, - { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X1 }, { Op45M0 }, - { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, - { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, - { Op50E0 }, { Op51E0M0X1 }, { Op52E0M0 }, { Op53M0 }, { Op54X1 }, - { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X1 }, - { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM0X1 }, { Op5EM0X1 }, - { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, - { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, - { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, - { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X1 }, { Op72E0M0 }, - { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, - { Op78 }, { Op79M0X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, - { Op7DM0X1 }, { Op7EM0X1 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, - { Op82 }, { Op83M0 }, { Op84X1 }, { Op85M0 }, { Op86X1 }, - { Op87M0 }, { Op88X1 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, - { Op8CX1 }, { Op8DM0 }, { Op8EX1 }, { Op8FM0 }, { Op90E0 }, - { Op91E0M0X1 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X1 }, { Op95E0M0 }, - { Op96E0X1 }, { Op97M0 }, { Op98M0 }, { Op99M0X1 }, { Op9A }, - { Op9BX1 }, { Op9CM0 }, { Op9DM0X1 }, { Op9EM0X1 }, { Op9FM0 }, - { OpA0X1 }, { OpA1E0M0 }, { OpA2X1 }, { OpA3M0 }, { OpA4X1 }, - { OpA5M0 }, { OpA6X1 }, { OpA7M0 }, { OpA8X1 }, { OpA9M0 }, - { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM0 }, { OpAEX1 }, - { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X1 }, { OpB2E0M0 }, { OpB3M0 }, - { OpB4E0X1 }, { OpB5E0M0 }, { OpB6E0X1 }, { OpB7M0 }, { OpB8 }, - { OpB9M0X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM0X1 }, - { OpBEX1 }, { OpBFM0 }, { OpC0X1 }, { OpC1E0M0 }, { OpC2 }, - { OpC3M0 }, { OpC4X1 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, - { OpC8X1 }, { OpC9M0 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, - { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X1 }, - { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, - { OpD7M0 }, { OpD8 }, { OpD9M0X1 }, { OpDAE0X1 }, { OpDB }, - { OpDC }, { OpDDM0X1 }, { OpDEM0X1 }, { OpDFM0 }, { OpE0X1 }, - { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X1 }, { OpE5M0 }, - { OpE6M0 }, { OpE7M0 }, { OpE8X1 }, { OpE9M0 }, { OpEA }, - { OpEB }, { OpECX1 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, - { OpF0E0 }, { OpF1E0M0X1 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, - { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X1 }, - { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM0X1 }, { OpFEM0X1 }, - { OpFFM0 } +struct SOpcodes S9xOpcodesM0X1[256] = { + {Op00}, {Op01E0M0}, {Op02}, {Op03M0}, {Op04M0}, + {Op05M0}, {Op06M0}, {Op07M0}, {Op08E0}, {Op09M0}, + {Op0AM0}, {Op0BE0}, {Op0CM0}, {Op0DM0}, {Op0EM0}, + {Op0FM0}, {Op10E0}, {Op11E0M0X1}, {Op12E0M0}, {Op13M0}, + {Op14M0}, {Op15E0M0}, {Op16E0M0}, {Op17M0}, {Op18}, + {Op19M0X1}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0X1}, + {Op1EM0X1}, {Op1FM0}, {Op20E0}, {Op21E0M0}, {Op22E0}, + {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, + {Op28E0}, {Op29M0}, {Op2AM0}, {Op2BE0}, {Op2CM0}, + {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30E0}, {Op31E0M0X1}, + {Op32E0M0}, {Op33M0}, {Op34E0M0}, {Op35E0M0}, {Op36E0M0}, + {Op37M0}, {Op38}, {Op39M0X1}, {Op3AM0}, {Op3B}, + {Op3CM0X1}, {Op3DM0X1}, {Op3EM0X1}, {Op3FM0}, {Op40Slow}, + {Op41E0M0}, {Op42}, {Op43M0}, {Op44X1}, {Op45M0}, + {Op46M0}, {Op47M0}, {Op48E0M0}, {Op49M0}, {Op4AM0}, + {Op4BE0}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, + {Op50E0}, {Op51E0M0X1}, {Op52E0M0}, {Op53M0}, {Op54X1}, + {Op55E0M0}, {Op56E0M0}, {Op57M0}, {Op58}, {Op59M0X1}, + {Op5AE0X1}, {Op5B}, {Op5C}, {Op5DM0X1}, {Op5EM0X1}, + {Op5FM0}, {Op60E0}, {Op61E0M0}, {Op62E0}, {Op63M0}, + {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68E0M0}, + {Op69M0}, {Op6AM0}, {Op6BE0}, {Op6C}, {Op6DM0}, + {Op6EM0}, {Op6FM0}, {Op70E0}, {Op71E0M0X1}, {Op72E0M0}, + {Op73M0}, {Op74E0M0}, {Op75E0M0}, {Op76E0M0}, {Op77M0}, + {Op78}, {Op79M0X1}, {Op7AE0X1}, {Op7B}, {Op7C}, + {Op7DM0X1}, {Op7EM0X1}, {Op7FM0}, {Op80E0}, {Op81E0M0}, + {Op82}, {Op83M0}, {Op84X1}, {Op85M0}, {Op86X1}, + {Op87M0}, {Op88X1}, {Op89M0}, {Op8AM0}, {Op8BE0}, + {Op8CX1}, {Op8DM0}, {Op8EX1}, {Op8FM0}, {Op90E0}, + {Op91E0M0X1}, {Op92E0M0}, {Op93M0}, {Op94E0X1}, {Op95E0M0}, + {Op96E0X1}, {Op97M0}, {Op98M0}, {Op99M0X1}, {Op9A}, + {Op9BX1}, {Op9CM0}, {Op9DM0X1}, {Op9EM0X1}, {Op9FM0}, + {OpA0X1}, {OpA1E0M0}, {OpA2X1}, {OpA3M0}, {OpA4X1}, + {OpA5M0}, {OpA6X1}, {OpA7M0}, {OpA8X1}, {OpA9M0}, + {OpAAX1}, {OpABE0}, {OpACX1}, {OpADM0}, {OpAEX1}, + {OpAFM0}, {OpB0E0}, {OpB1E0M0X1}, {OpB2E0M0}, {OpB3M0}, + {OpB4E0X1}, {OpB5E0M0}, {OpB6E0X1}, {OpB7M0}, {OpB8}, + {OpB9M0X1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM0X1}, + {OpBEX1}, {OpBFM0}, {OpC0X1}, {OpC1E0M0}, {OpC2}, + {OpC3M0}, {OpC4X1}, {OpC5M0}, {OpC6M0}, {OpC7M0}, + {OpC8X1}, {OpC9M0}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0E0}, {OpD1E0M0X1}, + {OpD2E0M0}, {OpD3M0}, {OpD4E0}, {OpD5E0M0}, {OpD6E0M0}, + {OpD7M0}, {OpD8}, {OpD9M0X1}, {OpDAE0X1}, {OpDB}, + {OpDC}, {OpDDM0X1}, {OpDEM0X1}, {OpDFM0}, {OpE0X1}, + {OpE1E0M0}, {OpE2}, {OpE3M0}, {OpE4X1}, {OpE5M0}, + {OpE6M0}, {OpE7M0}, {OpE8X1}, {OpE9M0}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM0}, {OpEEM0}, {OpEFM0}, + {OpF0E0}, {OpF1E0M0X1}, {OpF2E0M0}, {OpF3M0}, {OpF4E0}, + {OpF5E0M0}, {OpF6E0M0}, {OpF7M0}, {OpF8}, {OpF9M0X1}, + {OpFAE0X1}, {OpFB}, {OpFCE0}, {OpFDM0X1}, {OpFEM0X1}, + {OpFFM0} }; -struct SOpcodes S9xOpcodesSlow[256] = -{ - { Op00 }, { Op01Slow }, { Op02 }, { Op03Slow }, { Op04Slow }, - { Op05Slow }, { Op06Slow }, { Op07Slow }, { Op08Slow }, { Op09Slow }, - { Op0ASlow }, { Op0BSlow }, { Op0CSlow }, { Op0DSlow }, { Op0ESlow }, - { Op0FSlow }, { Op10Slow }, { Op11Slow }, { Op12Slow }, { Op13Slow }, - { Op14Slow }, { Op15Slow }, { Op16Slow }, { Op17Slow }, { Op18 }, - { Op19Slow }, { Op1ASlow }, { Op1B }, { Op1CSlow }, { Op1DSlow }, - { Op1ESlow }, { Op1FSlow }, { Op20Slow }, { Op21Slow }, { Op22Slow }, - { Op23Slow }, { Op24Slow }, { Op25Slow }, { Op26Slow }, { Op27Slow }, - { Op28Slow }, { Op29Slow }, { Op2ASlow }, { Op2BSlow }, { Op2CSlow }, - { Op2DSlow }, { Op2ESlow }, { Op2FSlow }, { Op30Slow }, { Op31Slow }, - { Op32Slow }, { Op33Slow }, { Op34Slow }, { Op35Slow }, { Op36Slow }, - { Op37Slow }, { Op38 }, { Op39Slow }, { Op3ASlow }, { Op3B }, - { Op3CSlow }, { Op3DSlow }, { Op3ESlow }, { Op3FSlow }, { Op40Slow }, - { Op41Slow }, { Op42 }, { Op43Slow }, { Op44Slow }, { Op45Slow }, - { Op46Slow }, { Op47Slow }, { Op48Slow }, { Op49Slow }, { Op4ASlow }, - { Op4BSlow }, { Op4CSlow }, { Op4DSlow }, { Op4ESlow }, { Op4FSlow }, - { Op50Slow }, { Op51Slow }, { Op52Slow }, { Op53Slow }, { Op54Slow }, - { Op55Slow }, { Op56Slow }, { Op57Slow }, { Op58 }, { Op59Slow }, - { Op5ASlow }, { Op5B }, { Op5CSlow }, { Op5DSlow }, { Op5ESlow }, - { Op5FSlow }, { Op60Slow }, { Op61Slow }, { Op62Slow }, { Op63Slow }, - { Op64Slow }, { Op65Slow }, { Op66Slow }, { Op67Slow }, { Op68Slow }, - { Op69Slow }, { Op6ASlow }, { Op6BSlow }, { Op6CSlow }, { Op6DSlow }, - { Op6ESlow }, { Op6FSlow }, { Op70Slow }, { Op71Slow }, { Op72Slow }, - { Op73Slow }, { Op74Slow }, { Op75Slow }, { Op76Slow }, { Op77Slow }, - { Op78 }, { Op79Slow }, { Op7ASlow }, { Op7B }, { Op7CSlow }, - { Op7DSlow }, { Op7ESlow }, { Op7FSlow }, { Op80Slow }, { Op81Slow }, - { Op82Slow }, { Op83Slow }, { Op84Slow }, { Op85Slow }, { Op86Slow }, - { Op87Slow }, { Op88Slow }, { Op89Slow }, { Op8ASlow }, { Op8BSlow }, - { Op8CSlow }, { Op8DSlow }, { Op8ESlow }, { Op8FSlow }, { Op90Slow }, - { Op91Slow }, { Op92Slow }, { Op93Slow }, { Op94Slow }, { Op95Slow }, - { Op96Slow }, { Op97Slow }, { Op98Slow }, { Op99Slow }, { Op9A }, - { Op9BSlow }, { Op9CSlow }, { Op9DSlow }, { Op9ESlow }, { Op9FSlow }, - { OpA0Slow }, { OpA1Slow }, { OpA2Slow }, { OpA3Slow }, { OpA4Slow }, - { OpA5Slow }, { OpA6Slow }, { OpA7Slow }, { OpA8Slow }, { OpA9Slow }, - { OpAASlow }, { OpABSlow }, { OpACSlow }, { OpADSlow }, { OpAESlow }, - { OpAFSlow }, { OpB0Slow }, { OpB1Slow }, { OpB2Slow }, { OpB3Slow }, - { OpB4Slow }, { OpB5Slow }, { OpB6Slow }, { OpB7Slow }, { OpB8 }, - { OpB9Slow }, { OpBASlow }, { OpBBSlow }, { OpBCSlow }, { OpBDSlow }, - { OpBESlow }, { OpBFSlow }, { OpC0Slow }, { OpC1Slow }, { OpC2Slow }, - { OpC3Slow }, { OpC4Slow }, { OpC5Slow }, { OpC6Slow }, { OpC7Slow }, - { OpC8Slow }, { OpC9Slow }, { OpCASlow }, { OpCB }, { OpCCSlow }, - { OpCDSlow }, { OpCESlow }, { OpCFSlow }, { OpD0Slow }, { OpD1Slow }, - { OpD2Slow }, { OpD3Slow }, { OpD4Slow }, { OpD5Slow }, { OpD6Slow }, - { OpD7Slow }, { OpD8 }, { OpD9Slow }, { OpDASlow }, { OpDB }, - { OpDCSlow }, { OpDDSlow }, { OpDESlow }, { OpDFSlow }, { OpE0Slow }, - { OpE1Slow }, { OpE2Slow }, { OpE3Slow }, { OpE4Slow }, { OpE5Slow }, - { OpE6Slow }, { OpE7Slow }, { OpE8Slow }, { OpE9Slow }, { OpEA }, - { OpEB }, { OpECSlow }, { OpEDSlow }, { OpEESlow }, { OpEFSlow }, - { OpF0Slow }, { OpF1Slow }, { OpF2Slow }, { OpF3Slow }, { OpF4Slow }, - { OpF5Slow }, { OpF6Slow }, { OpF7Slow }, { OpF8 }, { OpF9Slow }, - { OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow }, - { OpFFSlow } +struct SOpcodes S9xOpcodesSlow[256] = { + {Op00}, {Op01Slow}, {Op02}, {Op03Slow}, {Op04Slow}, + {Op05Slow}, {Op06Slow}, {Op07Slow}, {Op08Slow}, {Op09Slow}, + {Op0ASlow}, {Op0BSlow}, {Op0CSlow}, {Op0DSlow}, {Op0ESlow}, + {Op0FSlow}, {Op10Slow}, {Op11Slow}, {Op12Slow}, {Op13Slow}, + {Op14Slow}, {Op15Slow}, {Op16Slow}, {Op17Slow}, {Op18}, + {Op19Slow}, {Op1ASlow}, {Op1B}, {Op1CSlow}, {Op1DSlow}, + {Op1ESlow}, {Op1FSlow}, {Op20Slow}, {Op21Slow}, {Op22Slow}, + {Op23Slow}, {Op24Slow}, {Op25Slow}, {Op26Slow}, {Op27Slow}, + {Op28Slow}, {Op29Slow}, {Op2ASlow}, {Op2BSlow}, {Op2CSlow}, + {Op2DSlow}, {Op2ESlow}, {Op2FSlow}, {Op30Slow}, {Op31Slow}, + {Op32Slow}, {Op33Slow}, {Op34Slow}, {Op35Slow}, {Op36Slow}, + {Op37Slow}, {Op38}, {Op39Slow}, {Op3ASlow}, {Op3B}, + {Op3CSlow}, {Op3DSlow}, {Op3ESlow}, {Op3FSlow}, {Op40Slow}, + {Op41Slow}, {Op42}, {Op43Slow}, {Op44Slow}, {Op45Slow}, + {Op46Slow}, {Op47Slow}, {Op48Slow}, {Op49Slow}, {Op4ASlow}, + {Op4BSlow}, {Op4CSlow}, {Op4DSlow}, {Op4ESlow}, {Op4FSlow}, + {Op50Slow}, {Op51Slow}, {Op52Slow}, {Op53Slow}, {Op54Slow}, + {Op55Slow}, {Op56Slow}, {Op57Slow}, {Op58}, {Op59Slow}, + {Op5ASlow}, {Op5B}, {Op5CSlow}, {Op5DSlow}, {Op5ESlow}, + {Op5FSlow}, {Op60Slow}, {Op61Slow}, {Op62Slow}, {Op63Slow}, + {Op64Slow}, {Op65Slow}, {Op66Slow}, {Op67Slow}, {Op68Slow}, + {Op69Slow}, {Op6ASlow}, {Op6BSlow}, {Op6CSlow}, {Op6DSlow}, + {Op6ESlow}, {Op6FSlow}, {Op70Slow}, {Op71Slow}, {Op72Slow}, + {Op73Slow}, {Op74Slow}, {Op75Slow}, {Op76Slow}, {Op77Slow}, + {Op78}, {Op79Slow}, {Op7ASlow}, {Op7B}, {Op7CSlow}, + {Op7DSlow}, {Op7ESlow}, {Op7FSlow}, {Op80Slow}, {Op81Slow}, + {Op82Slow}, {Op83Slow}, {Op84Slow}, {Op85Slow}, {Op86Slow}, + {Op87Slow}, {Op88Slow}, {Op89Slow}, {Op8ASlow}, {Op8BSlow}, + {Op8CSlow}, {Op8DSlow}, {Op8ESlow}, {Op8FSlow}, {Op90Slow}, + {Op91Slow}, {Op92Slow}, {Op93Slow}, {Op94Slow}, {Op95Slow}, + {Op96Slow}, {Op97Slow}, {Op98Slow}, {Op99Slow}, {Op9A}, + {Op9BSlow}, {Op9CSlow}, {Op9DSlow}, {Op9ESlow}, {Op9FSlow}, + {OpA0Slow}, {OpA1Slow}, {OpA2Slow}, {OpA3Slow}, {OpA4Slow}, + {OpA5Slow}, {OpA6Slow}, {OpA7Slow}, {OpA8Slow}, {OpA9Slow}, + {OpAASlow}, {OpABSlow}, {OpACSlow}, {OpADSlow}, {OpAESlow}, + {OpAFSlow}, {OpB0Slow}, {OpB1Slow}, {OpB2Slow}, {OpB3Slow}, + {OpB4Slow}, {OpB5Slow}, {OpB6Slow}, {OpB7Slow}, {OpB8}, + {OpB9Slow}, {OpBASlow}, {OpBBSlow}, {OpBCSlow}, {OpBDSlow}, + {OpBESlow}, {OpBFSlow}, {OpC0Slow}, {OpC1Slow}, {OpC2Slow}, + {OpC3Slow}, {OpC4Slow}, {OpC5Slow}, {OpC6Slow}, {OpC7Slow}, + {OpC8Slow}, {OpC9Slow}, {OpCASlow}, {OpCB}, {OpCCSlow}, + {OpCDSlow}, {OpCESlow}, {OpCFSlow}, {OpD0Slow}, {OpD1Slow}, + {OpD2Slow}, {OpD3Slow}, {OpD4Slow}, {OpD5Slow}, {OpD6Slow}, + {OpD7Slow}, {OpD8}, {OpD9Slow}, {OpDASlow}, {OpDB}, + {OpDCSlow}, {OpDDSlow}, {OpDESlow}, {OpDFSlow}, {OpE0Slow}, + {OpE1Slow}, {OpE2Slow}, {OpE3Slow}, {OpE4Slow}, {OpE5Slow}, + {OpE6Slow}, {OpE7Slow}, {OpE8Slow}, {OpE9Slow}, {OpEA}, + {OpEB}, {OpECSlow}, {OpEDSlow}, {OpEESlow}, {OpEFSlow}, + {OpF0Slow}, {OpF1Slow}, {OpF2Slow}, {OpF3Slow}, {OpF4Slow}, + {OpF5Slow}, {OpF6Slow}, {OpF7Slow}, {OpF8}, {OpF9Slow}, + {OpFASlow}, {OpFB}, {OpFCSlow}, {OpFDSlow}, {OpFESlow}, + {OpFFSlow} }; diff --git a/source/snes9x/cpuops.h b/source/snes9x/cpuops.h index 49c7701..06d8c16 100644 --- a/source/snes9x/cpuops.h +++ b/source/snes9x/cpuops.h @@ -159,14 +159,16 @@ **********************************************************************************/ + + #ifndef _CPUOPS_H_ #define _CPUOPS_H_ - -void S9xOpcode_NMI (void); -void S9xOpcode_IRQ (void); +void S9xOpcode_NMI (); +void S9xOpcode_IRQ (); #define CHECK_FOR_IRQ() \ -if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \ - S9xOpcode_IRQ() +if (CPU.IRQActive && !CheckFlag (IRQ) && !Settings.DisableIRQ) \ + S9xOpcode_IRQ() #endif + diff --git a/source/snes9x/crosshairs.cpp b/source/snes9x/crosshairs.cpp index 7d13764..c0ee542 100644 --- a/source/snes9x/crosshairs.cpp +++ b/source/snes9x/crosshairs.cpp @@ -159,508 +159,487 @@ **********************************************************************************/ + +#ifdef HAVE_CONFIG_H + #include +#endif +#include +#include + #ifdef HAVE_LIBPNG #include #endif + #include "port.h" #include "crosshairs.h" -static const char *crosshairs[32] = -{ - "` " // Crosshair 0 (no image) - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " ", +static char *crosshairs[32]={ + "` " /* Crosshair 0 (no image) */ + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " ", - "` " // Crosshair 1 (the classic small dot) - " " - " " - " " - " " - " " - " " - " #. " - " " - " " - " " - " " - " " - " " - " ", + "` " /* Crosshair 1 (the classic small dot) */ + " " + " " + " " + " " + " " + " " + " #. " + " " + " " + " " + " " + " " + " " + " ", - "` " // Crosshair 2 (a standard cross) - " " - " " - " " - " .#. " - " .#. " - " ...#... " - " ####### " - " ...#... " - " .#. " - " .#. " - " " - " " - " " - " ", + "` " /* Crosshair 2 (a standard cross) */ + " " + " " + " " + " .#. " + " .#. " + " ...#... " + " ####### " + " ...#... " + " .#. " + " .#. " + " " + " " + " " + " ", - "` .#. " // Crosshair 3 (a standard cross) - " .#. " - " .#. " - " .#. " - " .#. " - " .#. " - ".......#......." - "###############" - ".......#......." - " .#. " - " .#. " - " .#. " - " .#. " - " .#. " - " .#. ", + "` .#. " /* Crosshair 3 (a standard cross) */ + " .#. " + " .#. " + " .#. " + " .#. " + " .#. " + ".......#......." + "###############" + ".......#......." + " .#. " + " .#. " + " .#. " + " .#. " + " .#. " + " .#. ", - "` " // Crosshair 4 (an X) - " " - " " - " . . " - " .#. .#. " - " .#. .#. " - " .#.#. " - " .#. " - " .#.#. " - " .#. .#. " - " .#. .#. " - " . . " - " " - " " - " ", + "` " /* Crosshair 4 (an X) */ + " " + " " + " . . " + " .#. .#. " + " .#. .#. " + " .#.#. " + " .#. " + " .#.#. " + " .#. .#. " + " .#. .#. " + " . . " + " " + " " + " ", - "`. . " // Crosshair 5 (an X) - ".#. .#." - " .#. .#. " - " .#. .#. " - " .#. .#. " - " .#. .#. " - " .#.#. " - " .#. " - " .#.#. " - " .#. .#. " - " .#. .#. " - " .#. .#. " - " .#. .#. " - ".#. .#." - " . . ", + "`. . " /* Crosshair 5 (an X) */ + ".#. .#." + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#.#. " + " .#. " + " .#.#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + ".#. .#." + " . . ", - "` " // Crosshair 6 (a combo) - " " - " " - " " - " # . # " - " # . # " - " #.# " - " ...#... " - " #.# " - " # . # " - " # . # " - " " - " " - " " - " ", + "` " /* Crosshair 6 (a combo) */ + " " + " " + " " + " # . # " + " # . # " + " #.# " + " ...#... " + " #.# " + " # . # " + " # . # " + " " + " " + " " + " ", - "` . " // Crosshair 7 (a combo) - " # . # " - " # . # " - " # . # " - " # . # " - " # . # " - " #.# " - ".......#......." - " #.# " - " # . # " - " # . # " - " # . # " - " # . # " - " # . # " - " . ", + "` . " /* Crosshair 7 (a combo) */ + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " #.# " + ".......#......." + " #.# " + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " . ", - "` # " // Crosshair 8 (a diamond cross) - " #.# " - " # . # " - " # . # " - " # . # " - " # . # " - " # . # " - "#......#......#" - " # . # " - " # . # " - " # . # " - " # . # " - " # . # " - " #.# " - " # ", + "` # " /* Crosshair 8 (a diamond cross) */ + " #.# " + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + "#......#......#" + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " #.# " + " # ", - "` ### " // Crosshair 9 (a circle cross) - " ## . ## " - " # . # " - " # . # " - " # . # " - " # . # " - "# . #" - "#......#......#" - "# . #" - " # . # " - " # . # " - " # . # " - " # . # " - " ## . ## " - " ### ", + "` ### " /* Crosshair 9 (a circle cross) */ + " ## . ## " + " # . # " + " # . # " + " # . # " + " # . # " + "# . #" + "#......#......#" + "# . #" + " # . # " + " # . # " + " # . # " + " # . # " + " ## . ## " + " ### ", - "` .#. " // Crosshair 10 (a square cross) - " .#. " - " .#. " - " ....#.... " - " .#######. " - " .# #. " - "....# #...." - "##### #####" - "....# #...." - " .# #. " - " .#######. " - " ....#.... " - " .#. " - " .#. " - " .#. ", + "` .#. " /* Crosshair 10 (a square cross) */ + " .#. " + " .#. " + " ....#.... " + " .#######. " + " .# #. " + "....# #...." + "##### #####" + "....# #...." + " .# #. " + " .#######. " + " ....#.... " + " .#. " + " .#. " + " .#. ", - "` .#. " // Crosshair 11 (an interrupted cross) - " .#. " - " .#. " - " .#. " - " .#. " - " " - "..... ....." - "##### #####" - "..... ....." - " " - " .#. " - " .#. " - " .#. " - " .#. " - " .#. ", + "` .#. " /* Crosshair 11 (an interrupted cross) */ + " .#. " + " .#. " + " .#. " + " .#. " + " " + "..... ....." + "##### #####" + "..... ....." + " " + " .#. " + " .#. " + " .#. " + " .#. " + " .#. ", - "`. . " // Crosshair 12 (an interrupted X) - ".#. .#." - " .#. .#. " - " .#. .#. " - " .#. .#. " - " " - " " - " " - " " - " " - " .#. .#. " - " .#. .#. " - " .#. .#. " - ".#. .#." - " . . ", + "`. . " /* Crosshair 12 (an interrupted X) */ + ".#. .#." + " .#. .#. " + " .#. .#. " + " .#. .#. " + " " + " " + " " + " " + " " + " .#. .#. " + " .#. .#. " + " .#. .#. " + ".#. .#." + " . . ", - "` . " // Crosshair 13 (an interrupted combo) - " # . # " - " # . # " - " # . # " - " # . # " - " " - " " - "..... ....." - " " - " " - " # . # " - " # . # " - " # . # " - " # . # " - " . ", + "` . " /* Crosshair 13 (an interrupted combo) */ + " # . # " + " # . # " + " # . # " + " # . # " + " " + " " + "..... ....." + " " + " " + " # . # " + " # . # " + " # . # " + " # . # " + " . ", - "`#### #### " // Crosshair 14 - "#.... ....#" - "#. .#" - "#. .#" - "#. .#" - " # " - " # " - " ##### " - " # " - " # " - "#. .#" - "#. .#" - "#. .#" - "#.... ....#" - " #### #### ", + "`#### #### " /* Crosshair 14 */ + "#.... ....#" + "#. .#" + "#. .#" + "#. .#" + " # " + " # " + " ##### " + " # " + " # " + "#. .#" + "#. .#" + "#. .#" + "#.... ....#" + " #### #### ", - "` .# #. " // Crosshair 15 - " .# #. " - " .# #. " - "....# #...." - "##### #####" - " " - " " - " " - " " - " " - "##### #####" - "....# #...." - " .# #. " - " .# #. " - " .# #. ", + "` .# #. " /* Crosshair 15 */ + " .# #. " + " .# #. " + "....# #...." + "##### #####" + " " + " " + " " + " " + " " + "##### #####" + "....# #...." + " .# #. " + " .# #. " + " .# #. ", - "` # " // Crosshair 16 - " # " - " # " - " ....#.... " - " . # . " - " . # . " - " . # . " - "###############" - " . # . " - " . # . " - " . # . " - " ....#.... " - " # " - " # " - " # ", + "` # " /* Crosshair 16 */ + " # " + " # " + " ....#.... " + " . # . " + " . # . " + " . # . " + "###############" + " . # . " + " . # . " + " . # . " + " ....#.... " + " # " + " # " + " # ", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL }; +bool S9xLoadCrosshairFile(int idx, const char *filename){ + int i, r; + char *s; + FILE *fp; -bool S9xLoadCrosshairFile (int idx, const char *filename) -{ - if (idx < 1 || idx > 31) - return (false); + if(idx<1 || idx>31) return false; + if((s=(char *)calloc(15*15+1, sizeof(char)))==NULL){ + fprintf(stderr, "S9xLoadCrosshairFile: malloc error while reading "); + perror(filename); + return false; + } - char *s = (char *) calloc(15 * 15 + 1, sizeof(char)); - if (s == NULL) - { - fprintf(stderr, "S9xLoadCrosshairFile: malloc error while reading "); - perror(filename); - return (false); - } - - FILE *fp = fopen(filename, "rb"); - if (fp == NULL) - { - fprintf(stderr, "S9xLoadCrosshairFile: Couldn't open "); - perror(filename); - free(s); - return (false); - } - - size_t l = fread(s, 1, 8, fp); - if (l != 8) - { - fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); - free(s); - fclose(fp); - return (false); - } + if((fp=fopen(filename, "rb"))==NULL){ + fprintf(stderr, "S9xLoadCrosshairFile: Couldn't open "); + perror(filename); + free(s); + return false; + } + i=fread(s, 1, 8, fp); + if(i!=8){ + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); + free(s); + fclose(fp); + return false; + } #ifdef HAVE_LIBPNG - png_structp png_ptr; - png_infop info_ptr; + png_structp png_ptr; + png_infop info_ptr; - if (!png_sig_cmp((png_byte *) s, 0, 8)) - { - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - { - free(s); - fclose(fp); - return (false); - } + if(!png_sig_cmp((png_byte *)s, 0, 8)){ + png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr){ + free(s); + fclose(fp); + return false; + } + info_ptr=png_create_info_struct(png_ptr); + if(!info_ptr){ + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + free(s); + fclose(fp); + return false; + } - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); - free(s); - fclose(fp); - return (false); - } + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); - png_init_io(png_ptr, fp); - png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); + png_uint_32 width, height; + int bit_depth, color_type; - png_uint_32 width, height; - int bit_depth, color_type; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + if(color_type!=PNG_COLOR_TYPE_PALETTE){ + fprintf(stderr, "S9xLoadCrosshairFile: Input PNG is not a palettized image!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + free(s); + fclose(fp); + return false; + } + if(bit_depth==16) + png_set_strip_16(png_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - if (color_type != PNG_COLOR_TYPE_PALETTE) - { - fprintf(stderr, "S9xLoadCrosshairFile: Input PNG is not a palettized image!\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - free(s); - fclose(fp); - return (false); - } + if(width!=15 || height!=15){ + fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 15x15 PNG\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + free(s); + fclose(fp); + return false; + } - if (bit_depth == 16) - png_set_strip_16(png_ptr); + int num_palette=0, num_trans=0; + int fgcol=-1, bgcol=-1, transcol=-1; + png_color *pngpal; + png_byte *trans; - if (width != 15 || height != 15) - { - fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 15x15 PNG\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - free(s); - fclose(fp); - return (false); - } + png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette); + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); - png_color *pngpal; - png_byte *trans; - int num_palette = 0, num_trans = 0; - int transcol = -1, fgcol = -1, bgcol = -1; + if(num_palette!=3 || num_trans!=1){ + fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 3-color PNG with 1 trasnparent color\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + free(s); + fclose(fp); + return false; + } - png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette); - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + for(i=0; i<3; i++){ + if(trans[0]==i){ + transcol=i; + } else if(pngpal[i].red==0 && pngpal[i].green==0 && pngpal[i].blue==0){ + bgcol=i; + } else if(pngpal[i].red==255 && pngpal[i].green==255 && pngpal[i].blue==255){ + fgcol=i; + } + } - if (num_palette != 3 || num_trans != 1) - { - fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 3-color PNG with 1 trasnparent color\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - free(s); - fclose(fp); - return (false); - } + if(transcol<0 || fgcol<0 || bgcol<0){ + fprintf(stderr, "S9xLoadCrosshairFile: PNG must have 3 colors: white (fg), black (bg), and transparent.\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + free(s); + fclose(fp); + return false; + } - for (int i = 0; i < 3; i++) - { - if (trans[0] == i) - transcol = i; - else - if (pngpal[i].red == 0 && pngpal[i].green == 0 && pngpal[i].blue == 0) - bgcol = i; - else - if (pngpal[i].red == 255 && pngpal[i].green == 255 && pngpal[i].blue == 255) - fgcol = i; - } + png_set_packing(png_ptr); + png_read_update_info(png_ptr, info_ptr); + png_byte *row_pointer = new png_byte [png_get_rowbytes(png_ptr, info_ptr)]; - if (transcol < 0 || fgcol < 0 || bgcol < 0) - { - fprintf(stderr, "S9xLoadCrosshairFile: PNG must have 3 colors: white (fg), black (bg), and transparent.\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - free(s); - fclose(fp); - return (false); - } - - png_set_packing(png_ptr); - png_read_update_info(png_ptr, info_ptr); - png_byte *row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; - - for (int r = 0; r < 15 * 15; r += 15) - { - png_read_row(png_ptr, row_pointer, NULL); - - for (int i = 0; i < 15; i++) - { - if (row_pointer[i] == transcol) - s[r + i] = ' '; - else - if (row_pointer[i] == fgcol) - s[r + i] = '#'; - else - if (row_pointer[i] == bgcol) - s[r + i] = '.'; - else - { - fprintf(stderr, "S9xLoadCrosshairFile: WTF? This was supposed to be a 3-color PNG!\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - free(s); - fclose(fp); - return (false); - } - } - } - - s[15 * 15] = 0; - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - } - else + for(r=0; r<15*15; r+=15){ + png_read_row(png_ptr, row_pointer, NULL); + for(i=0; i<15; i++){ + if(row_pointer[i]==transcol) s[r+i]=' '; + else if(row_pointer[i]==fgcol) s[r+i]='#'; + else if(row_pointer[i]==bgcol) s[r+i]='.'; + else { + fprintf(stderr, "S9xLoadCrosshairFile: WTF? This was supposed to be a 3-color PNG!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + free(s); + fclose(fp); + return false; + } + } + } + s[15*15]=0; + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + } else #endif - { - l = fread(s + 8, 1, 15 - 8, fp); - if (l != 15 - 8) - { - fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); - free(s); - fclose(fp); - return (false); - } + { + i=fread(s+8, 1, 15-8, fp); + if(i!=15-8){ + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); + free(s); + fclose(fp); + return false; + } + if(getc(fp)!='\n'){ + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format!"); +#ifndef HAVE_LIBPNG + fprintf(stderr, " (note: PNG support is not available)"); +#endif + fprintf(stderr, "\n"); + free(s); + fclose(fp); + return false; + } + for(r=1; r<15; r++){ + i=fread(s+r*15, 1, 15, fp); + if(i!=15){ + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!"); +#ifndef HAVE_LIBPNG + fprintf(stderr, " (note: PNG support is not available)"); +#endif + fprintf(stderr, "\n"); + free(s); + fclose(fp); + return false; + } + if(getc(fp)!='\n'){ + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format!"); +#ifndef HAVE_LIBPNG + fprintf(stderr, " (note: PNG support is not available)"); +#endif + fprintf(stderr, "\n"); + free(s); + fclose(fp); + return false; + } + } + for(i=0; i<15*15; i++){ + if(s[i]!=' ' && s[i]!='#' && s[i]!='.'){ + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format!"); +#ifndef HAVE_LIBPNG + fprintf(stderr, " (note: PNG support is not available)"); +#endif + fprintf(stderr, "\n"); + free(s); + fclose(fp); + return false; + } + } + } + fclose(fp); - if (getc(fp) != '\n') - { - fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); - free(s); - fclose(fp); - return (false); - } - - for (int r = 1; r < 15; r++) - { - l = fread(s + r * 15, 1, 15, fp); - if (l != 15) - { - fprintf(stderr, "S9xLoadCrosshairFile: File is too short! (note: PNG support is not available)\n"); - free(s); - fclose(fp); - return (false); - } - - if (getc(fp) != '\n') - { - fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); - free(s); - fclose(fp); - return (false); - } - } - - for (int i = 0; i < 15 * 15; i++) - { - if (s[i] != ' ' && s[i] != '#' && s[i] != '.') - { - fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); - free(s); - fclose(fp); - return (false); - } - } - } - - fclose(fp); - - if (crosshairs[idx] != NULL && crosshairs[idx][0] != '`') - free((void *) crosshairs[idx]); - crosshairs[idx] = s; - - return (true); + if(crosshairs[idx]!=NULL && crosshairs[idx][0]!='`') free(crosshairs[idx]); + crosshairs[idx]=s; + return true; } -const char * S9xGetCrosshair (int idx) -{ - if (idx < 0 || idx > 31) - return (NULL); - - return (crosshairs[idx]); +const char *S9xGetCrosshair(int idx){ + if(idx<0 || idx>31) return NULL; + return crosshairs[idx]; } diff --git a/source/snes9x/crosshairs.h b/source/snes9x/crosshairs.h index b246178..b9c7ac5 100644 --- a/source/snes9x/crosshairs.h +++ b/source/snes9x/crosshairs.h @@ -159,59 +159,62 @@ **********************************************************************************/ -#ifndef _CROSSHAIRS_H_ -#define _CROSSHAIRS_H_ -// Read in the specified crosshair file, replacing whatever data might be in that slot. -// Available slots are 1-31. -// The input file must be a PNG or a text file. -// PNG: 15x15 pixels, palettized, with 3 colors (white, black, and transparent). -// text: 15 lines of 16 characters (counting the \n), consisting of ' ', '#', or '.'. +#ifndef CROSSHAIRS_H +#define CROSSHAIRS_H -bool S9xLoadCrosshairFile (int idx, const char *filename); +/* + * Read in the specified crosshair file, replacing whatever data might be in + * that slot. Available slots are 1-31. The input file must be a PNG file, + * 15x15 pixels, palettized, with 3 colors: white, black, and transparent. Or a + * text file, 15 lines of 16 characters (counting the \n), consisting of ' ', + * '#', or '.'. + */ +bool S9xLoadCrosshairFile(int idx, const char *filename); -// Return the specified crosshair. Woo-hoo. -// char * to a 225-byte string, with '#' marking foreground, '.' marking background, -// and anything else transparent. +/* + * Return the specified crosshair. Woo-hoo. char * to a 225-byte string, with + * '#' marking foreground, '.' marking background, and anything else + * transparent. + */ +const char *S9xGetCrosshair(int idx); -const char * S9xGetCrosshair (int idx); - -// In controls.cpp. Sets the crosshair for the specified device. Defaults are: -// cross fgcolor bgcolor -// Mouse 1: 1 White Black -// Mouse 2: 1 Purple White -// Superscope: 2 White Black -// Justifier 1: 4 Blue Black -// Justifier 2: 4 MagicPink Black -// -// Available colors are: Trans, Black, 25Grey, 50Grey, 75Grey, White, Red, Orange, -// Yellow, Green, Cyan, Sky, Blue, Violet, MagicPink, and Purple. -// You may also prefix a 't' (e.g. tBlue) for a 50%-transparent version. -// Use idx = -1 or fg/bg = NULL to keep the current setting. - -enum crosscontrols -{ - X_MOUSE1, - X_MOUSE2, - X_SUPERSCOPE, - X_JUSTIFIER1, - X_JUSTIFIER2 +/* + * In controls.cpp. Sets the crosshair for the specified device. Defaults are: + * cross fgcolor bgcolor + * Mouse 1: 1 White Black + * Mouse 2: 1 Purple White + * Superscope: 2 White Black + * Justifier 1: 4 Blue Black + * Justifier 2: 4 MagicPink Black + * + * Available colors are: Trans, Black, 25Grey, 50Grey, 75Grey, White, Red, + * Orange, Yellow, Green, Cyan, Sky, Blue, Violet, MagicPink, and Purple. You + * may also prefix a 't' (e.g. tBlue) for a 50%-transparent version. + * + * Use idx=-1 or fg/bg=NULL to keep the current setting. + */ +enum crosscontrols { + X_MOUSE1, + X_MOUSE2, + X_SUPERSCOPE, + X_JUSTIFIER1, + X_JUSTIFIER2 }; +void S9xSetControllerCrosshair(enum crosscontrols ctl, int8 idx, const char *fg, const char *bg); +void S9xGetControllerCrosshair(enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg); -void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg); -void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg); - -// In gfx.cpp, much like S9xDisplayChar() except it takes the parameters -// listed and looks up GFX.Screen. -// The 'crosshair' arg is a 15x15 image, with '#' meaning fgcolor, -// '.' meaning bgcolor, and anything else meaning transparent. -// Color values should be (RGB): -// 0 = transparent 4 = 23 23 23 8 = 31 31 0 12 = 0 0 31 -// 1 = 0 0 0 5 = 31 31 31 9 = 0 31 0 13 = 23 0 31 -// 2 = 8 8 8 6 = 31 0 0 10 = 0 31 31 14 = 31 0 31 -// 3 = 16 16 16 7 = 31 16 0 11 = 0 23 31 15 = 31 0 16 -// 16-31 are 50% transparent versions of 0-15. - -void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y); +/* + * In gfx.cpp, much like DisplayChar() except it takes the parameters listed + * and looks up GFX.Screen. The 'crosshair' arg is a 15x15 image, with '#' + * meaning fgcolor, '.' meaning bgcolor, and anything else meaning transparent. + * Color values should be (RGB): + * 0 = transparent 4=23 23 23 8=31 31 0 12= 0 0 31 + * 1 = 0 0 0 5=31 31 31 9= 0 31 0 13=23 0 31 + * 2 = 8 8 8 6=31 00 00 10= 0 31 31 14=31 0 31 + * 3 = 16 16 16 7=31 16 00 11= 0 23 31 15=31 0 16 + * 16-31 are 50% transparent versions of 0-15. + */ +void S9xDrawCrosshair(const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y); #endif diff --git a/source/snes9x/data.cpp b/source/snes9x/data.cpp new file mode 100644 index 0000000..6c7b563 --- /dev/null +++ b/source/snes9x/data.cpp @@ -0,0 +1,613 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#include "snes9x.h" + +uint8 add32_32 [32][32] = { +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f}, +{ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e, + 0x1f,0x1f}, +{ 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x1f,0x1f}, +{ 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11, + 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, + 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, + 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, + 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, + 0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, + 0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f} +}; + +uint8 add32_32_half [32][32] = { +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, + 0x0f,0x0f}, +{ 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, + 0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f, + 0x0f,0x10}, +{ 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08, + 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, + 0x10,0x10}, +{ 0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08, + 0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10, + 0x10,0x11}, +{ 0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09, + 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10, + 0x11,0x11}, +{ 0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09, + 0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11, + 0x11,0x12}, +{ 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a, + 0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11, + 0x12,0x12}, +{ 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a, + 0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12, + 0x12,0x13}, +{ 0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b, + 0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12, + 0x13,0x13}, +{ 0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b, + 0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13, + 0x13,0x14}, +{ 0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c, + 0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13, + 0x14,0x14}, +{ 0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c, + 0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14, + 0x14,0x15}, +{ 0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d, + 0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14, + 0x15,0x15}, +{ 0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, + 0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15, + 0x15,0x16}, +{ 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, + 0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15, + 0x16,0x16}, +{ 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, + 0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16, + 0x16,0x17}, +{ 0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f, + 0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16, + 0x17,0x17}, +{ 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, + 0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17, + 0x17,0x18}, +{ 0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10, + 0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17, + 0x18,0x18}, +{ 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10, + 0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18, + 0x18,0x19}, +{ 0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11, + 0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18, + 0x19,0x19}, +{ 0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11, + 0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19, + 0x19,0x1a}, +{ 0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12, + 0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19, + 0x1a,0x1a}, +{ 0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12, + 0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a, + 0x1a,0x1b}, +{ 0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13, + 0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a, + 0x1b,0x1b}, +{ 0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13, + 0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b, + 0x1b,0x1c}, +{ 0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14, + 0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b, + 0x1c,0x1c}, +{ 0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14, + 0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c, + 0x1c,0x1d}, +{ 0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15, + 0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c, + 0x1d,0x1d}, +{ 0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15, + 0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d, + 0x1d,0x1e}, +{ 0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16, + 0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d, + 0x1e,0x1e}, +{ 0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16, + 0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1e, + 0x1e,0x1f} +}; +uint8 sub32_32 [32][32] = { +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f}, +{ 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, + 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, + 0x1d,0x1e}, +{ 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, + 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d}, +{ 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, + 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, + 0x1b,0x1c}, +{ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, + 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1a,0x1b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x18}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, + 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, + 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, + 0x15,0x16}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, + 0x14,0x15}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, + 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, + 0x13,0x14}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, + 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11, + 0x12,0x13}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, + 0x0e,0x0f}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, + 0x0d,0x0e}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, + 0x0c,0x0d}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, + 0x0b,0x0c}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0a,0x0b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, + 0x07,0x08}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, + 0x06,0x07}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, + 0x04,0x05}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, + 0x03,0x04}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x02,0x03}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00} +}; + +uint8 sub32_32_half [32][32] = { +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, + 0x0f,0x0f}, +{ 0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, + 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, + 0x0e,0x0f}, +{ 0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06, + 0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, + 0x0e,0x0e}, +{ 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05, + 0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d, + 0x0d,0x0e}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05, + 0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c, + 0x0d,0x0d}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, + 0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c, + 0x0c,0x0d}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04, + 0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b, + 0x0c,0x0c}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, + 0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b, + 0x0b,0x0c}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03, + 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a, + 0x0b,0x0b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02, + 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a, + 0x0a,0x0b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02, + 0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09, + 0x0a,0x0a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, + 0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09, + 0x09,0x0a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08, + 0x09,0x09}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08, + 0x08,0x09}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, + 0x08,0x08}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x08}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, + 0x07,0x07}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06, + 0x06,0x07}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05, + 0x06,0x06}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05, + 0x05,0x06}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, + 0x05,0x05}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04, + 0x04,0x05}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, + 0x04,0x04}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03, + 0x03,0x04}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02, + 0x03,0x03}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02, + 0x02,0x03}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, + 0x02,0x02}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x01,0x02}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x01}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00} +}; + + +uint8 mul_brightness [16][32] = { +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02, + 0x02,0x02}, +{ 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04, + 0x04,0x04}, +{ 0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x03,0x03, + 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x06,0x06, + 0x06,0x06}, +{ 0x00,0x00,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x04, + 0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x08, + 0x08,0x08}, +{ 0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05, + 0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a, + 0x0a,0x0a}, +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x06, + 0x06,0x06,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0c, + 0x0c,0x0c}, +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, + 0x0e,0x0e}, +{ 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, + 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, + 0x10,0x11}, +{ 0x00,0x01,0x01,0x02,0x02,0x03,0x04,0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x08, + 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x10,0x10,0x11,0x11, + 0x12,0x13}, +{ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x09,0x09, + 0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0e,0x0f,0x0f,0x10,0x11,0x11,0x12,0x13,0x13, + 0x14,0x15}, +{ 0x00,0x01,0x01,0x02,0x03,0x04,0x04,0x05,0x06,0x07,0x07,0x08,0x09,0x0a,0x0a, + 0x0b,0x0c,0x0c,0x0d,0x0e,0x0f,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x15, + 0x16,0x17}, +{ 0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0b, + 0x0c,0x0d,0x0e,0x0e,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x16,0x16,0x17, + 0x18,0x19}, +{ 0x00,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0b,0x0c, + 0x0d,0x0e,0x0f,0x10,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x17,0x18,0x19, + 0x1a,0x1b}, +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, + 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d}, +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f} +}; + + diff --git a/source/snes9x/display.h b/source/snes9x/display.h index 79b884a..c571d71 100644 --- a/source/snes9x/display.h +++ b/source/snes9x/display.h @@ -159,63 +159,65 @@ **********************************************************************************/ + + #ifndef _DISPLAY_H_ #define _DISPLAY_H_ -enum s9x_getdirtype -{ - DEFAULT_DIR = 0, - HOME_DIR, - ROMFILENAME_DIR, - ROM_DIR, - SRAM_DIR, - SNAPSHOT_DIR, - SCREENSHOT_DIR, - SPC_DIR, +START_EXTERN_C +// Routines the port specific code has to implement +void S9xSetPalette (); +void S9xTextMode (); +void S9xGraphicsMode (); +void S9xParseArg (char **argv, int &index, int argc); +void S9xExtraUsage (); + +void S9xLoadConfigFiles(char **argv, int argc); +char *S9xParseArgs (char **argv, int argc); +void S9xUsage (); +void S9xInitDisplay (int argc, char **argv); +void S9xDeinitDisplay (); +void S9xInitInputDevices (); +void S9xSetTitle (const char *title); +void S9xProcessEvents (bool8 block); +void S9xPutImage (int width, int height); +void S9xParseDisplayArg (char **argv, int &index, int argc); +void S9xExtraDisplayUsage (); +void S9xToggleSoundChannel (int channel); +void S9xSetInfoString (const char *string); +int S9xMinCommandLineArgs (); +void S9xNextController (); +bool8 S9xLoadROMImage (const char *string); +const char *S9xSelectFilename (const char *def, const char *dir, + const char *ext, const char *title); +const char *S9xStringInput(const char *message); +const char *S9xChooseFilename (bool8 read_only); +bool8 S9xOpenSnapshotFile (const char *base, bool8 read_only, STREAM *file); +void S9xCloseSnapshotFile (STREAM file); + +const char *S9xBasename (const char *filename); + +int S9xFStrcmp (FILE *, const char *); + +enum s9x_getdirtype { + DEFAULT_DIR, + HOME_DIR, + ROM_DIR, + ROMFILENAME_DIR, + SNAPSHOT_DIR, + SRAM_DIR, + SCREENSHOT_DIR, + SPC_DIR, + PATCH_DIR, CHEAT_DIR, - IPS_DIR, + PACK_DIR, BIOS_DIR, - LOG_DIR, - LAST_DIR + LOG_DIR }; - -void S9xUsage (void); -char * S9xParseArgs (char **, int); -void S9xLoadConfigFiles (char **, int); -void S9xSetInfoString (const char *); - -// Routines the port has to implement even if it doesn't use them - -void S9xTextMode (void); -void S9xGraphicsMode (void); -void S9xSetPalette (void); -void S9xToggleSoundChannel (int); -bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *); -void S9xCloseSnapshotFile (STREAM); -const char * S9xStringInput (const char *); -const char * S9xGetDirectory (enum s9x_getdirtype); -const char * S9xGetFilename (const char *, enum s9x_getdirtype); -const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype); -const char * S9xChooseFilename (bool8); -const char * S9xBasename (const char *); - -// Routines the port has to implement if it uses command-line - -void S9xExtraUsage (void); -void S9xParseArg (char **, int &, int); - -// Routines the port may implement as needed - -void S9xExtraDisplayUsage (void); -void S9xParseDisplayArg (char **, int &, int); -int S9xMinCommandLineArgs (void); -void S9xSetTitle (const char *); -void S9xInitDisplay (int, char **); -void S9xDeinitDisplay (void); -void S9xPutImage (int, int); -void S9xInitInputDevices (void); -void S9xProcessEvents (bool8); -bool8 S9xLoadROMImage (const char *); -const char * S9xSelectFilename (const char *, const char *, const char *, const char *); +const char *S9xGetDirectory (enum s9x_getdirtype dirtype); +const char *S9xGetFilename (const char *extension, enum s9x_getdirtype dirtype); +const char *S9xGetFilenameInc (const char *, enum s9x_getdirtype); +END_EXTERN_C #endif + diff --git a/source/snes9x/dma.cpp b/source/snes9x/dma.cpp index a29628f..bc4d107 100644 --- a/source/snes9x/dma.cpp +++ b/source/snes9x/dma.cpp @@ -159,54 +159,61 @@ **********************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include "snes9x.h" #include "memmap.h" -#include "dma.h" -#include "apu/apu.h" -#include "sdd1emu.h" -#include "spc7110emu.h" -#ifdef DEBUGGER +#include "ppu.h" +#include "cpuexec.h" #include "missing.h" -#endif +#include "dma.h" +#include "apu.h" +#include "gfx.h" +#include "sa1.h" +#include "spc7110.h" +#include "sdd1emu.h" extern uint8 *HDMAMemPointers[8]; extern int HDMA_ModeByteCounts[8]; -extern SPC7110 s7emu; - static uint8 sdd1_decode_buffer[0x10000]; -static inline bool8 addCyclesInDMA (uint8); -static inline bool8 HDMAReadLineCount (int); +static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) +{ + return (*(uint32 *) p1 - *(uint32 *) p2); +} +// Add 8 cycles per byte, sync APU, and do HC related events. +// If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. static inline bool8 addCyclesInDMA (uint8 dma_channel) { - // Add 8 cycles per byte, sync APU, and do HC related events. - // If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. CPU.Cycles += SLOW_ONE_CYCLE; + S9xAPUExecute(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); if (CPU.HDMARanInDMA & (1 << dma_channel)) { CPU.HDMARanInDMA = 0; - #ifdef DEBUGGER - printf("HDMA and DMA use the same channel %d!\n", dma_channel); + #if 1 + //printf("HDMA and DMA use the same channel %d!\n", dma_channel); #endif // If HDMA triggers in the middle of DMA transfer and it uses the same channel, // it kills the DMA transfer immediately. $43x2 and $43x5 stop updating. - return (FALSE); + return FALSE; } CPU.HDMARanInDMA = 0; - return (TRUE); + return TRUE; } bool8 S9xDoDMA (uint8 Channel) { CPU.InDMA = TRUE; CPU.InDMAorHDMA = TRUE; - CPU.CurrentDMAorHDMAChannel = Channel; SDMA *d = &DMA[Channel]; @@ -240,8 +247,7 @@ bool8 S9xDoDMA (uint8 Channel) { CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; - CPU.CurrentDMAorHDMAChannel = -1; - return (FALSE); + return FALSE; } } @@ -255,18 +261,17 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; - CPU.CurrentDMAorHDMAChannel = -1; - return (TRUE); + return TRUE; } // Prepare for accessing $2118-2119 switch (d->BAddress) { - case 0x18: - case 0x19: - if (IPPU.RenderThisFrame) - FLUSH_REDRAW(); - break; + case 0x18: + case 0x19: + if (IPPU.RenderThisFrame) + FLUSH_REDRAW(); + break; } int32 inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); @@ -290,21 +295,70 @@ bool8 S9xDoDMA (uint8 Channel) // Hacky support for pre-decompressed S-DD1 data inc = !d->AAddressDecrement ? 1 : -1; - uint8 *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); - if (in_ptr) + if (Settings.SDD1Pack) // XXX: Settings.SDD1Pack == true -> on-the-fly decoding. Weird. { - in_ptr += d->AAddress; - SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); + // on-the-fly S-DD1 decoding + uint8 *in_ptr = GetBasePointer(((d->ABank << 16) | d->AAddress)); + if (in_ptr) + { + in_ptr += d->AAddress; + SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); + } + #ifdef DEBUGGER + else + { + sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + } + #endif + + in_sdd1_dma = sdd1_decode_buffer; } - #ifdef DEBUGGER else { - sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); - S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); - } - #endif + // S-DD1 graphics pack support + // XXX: Who still uses the graphics pack? + uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; + address |= Memory.FillRAM[0x4804 + ((d->ABank - 0xc0) >> 4)]; - in_sdd1_dma = sdd1_decode_buffer; + void *ptr = bsearch(&address, Memory.SDD1Index, Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); + if (ptr) + in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; + + if (!in_sdd1_dma) + { + // No matching decompressed data found. Must be some new graphics not encountered before. + // Log it if it hasn't been already. + uint8 *p = Memory.SDD1LoggedData; + bool8 found = FALSE; + uint8 SDD1Bank = Memory.FillRAM[0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; + + for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) + { + if (*(p + 0) == d->ABank || + *(p + 1) == (d->AAddress >> 8) && + *(p + 2) == (d->AAddress & 0xff) && + *(p + 3) == (count >> 8) && + *(p + 4) == (count & 0xff) && + *(p + 7) == SDD1Bank) + { + found = TRUE; + break; + } + } + + if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) + { + *(p + 0) = d->ABank; + *(p + 1) = d->AAddress >> 8; + *(p + 2) = d->AAddress & 0xff; + *(p + 3) = count >> 8; + *(p + 4) = count & 0xff; + *(p + 7) = SDD1Bank; + Memory.SDD1LoggedDataCount += 1; + } + } + } } Memory.FillRAM[0x4801] = 0; @@ -312,20 +366,45 @@ bool8 S9xDoDMA (uint8 Channel) // SPC7110 - uint8 *spc7110_dma = NULL; + uint8 *spc7110_dma = NULL; + bool8 s7_wrap = FALSE; - if (Settings.SPC7110) + if (Settings.SPC7110) { if (d->AAddress == 0x4800 || d->ABank == 0x50) { - spc7110_dma = new uint8[d->TransferBytes]; - for (int i = 0; i < d->TransferBytes; i++) - spc7110_dma[i] = s7emu.decomp.read(); + uint32 i, j; - int32 icount = s7emu.r4809 | (s7emu.r480a << 8); + i = (s7r.reg4805 | (s7r.reg4806 << 8)); + + #ifdef SPC7110_DEBUG + printf("SPC7110: DMA Transfer of %04X bytes from %02X%02X%02X:%02X, offset of %04X, internal bank of %04X, multiplier %02X\n", + d->TransferBytes, s7r.reg4803, s7r.reg4802, s7r.reg4801, s7r.reg4804, i, s7r.bank50Internal, s7r.AlignBy); + #endif + + i *= s7r.AlignBy; + i += s7r.bank50Internal; + i %= DECOMP_BUFFER_SIZE; + j = 0; + + if ((i + d->TransferBytes) < DECOMP_BUFFER_SIZE) + spc7110_dma = &s7r.bank50[i]; + else + { + spc7110_dma = new uint8[d->TransferBytes]; + j = DECOMP_BUFFER_SIZE - i; + memcpy(spc7110_dma, &s7r.bank50[i], j); + memcpy(&spc7110_dma[j], s7r.bank50, d->TransferBytes - j); + s7_wrap = TRUE; + } + + int32 icount = s7r.reg4809 | (s7r.reg480A << 8); icount -= d->TransferBytes; - s7emu.r4809 = icount & 0x00ff; - s7emu.r480a = (icount & 0xff00) >> 8; + s7r.reg4809 = 0x00ff & icount; + s7r.reg480A = (0xff00 & icount) >> 8; + + s7r.bank50Internal += d->TransferBytes; + s7r.bank50Internal %= DECOMP_BUFFER_SIZE; inc = 1; d->AAddress -= count; @@ -349,7 +428,7 @@ bool8 S9xDoDMA (uint8 Channel) int32 char_line_bytes = bytes_per_char * num_chars; uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; - uint8 *base = S9xGetBasePointer((d->ABank << 16) + addr); + uint8 *base = GetBasePointer((d->ABank << 16) + addr); if (!base) { sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); @@ -374,96 +453,96 @@ bool8 S9xDoDMA (uint8 Channel) switch (depth) { - case 2: - for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + case 2: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 2; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 2) { - uint8 *line = base + (num_chars - char_count) * 2; - for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 2) + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) { - uint8 *q = line; - for (int32 l = 0; l < 8; l++, q += bytes_per_line) + for (int32 b = 0; b < 2; b++) { - for (int32 b = 0; b < 2; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); - } - - p += 2; + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); } + + p += 2; } } + } + + break; + + case 4: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 4; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 4) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 4; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + p += 32 - 16; + } + } + + break; + + case 8: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 8; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 8) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + p += 64 - 16; + } break; - - case 4: - for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 4; - for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 4) - { - uint8 *q = line; - for (int32 l = 0; l < 8; l++, q += bytes_per_line) - { - for (int32 b = 0; b < 4; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); - } - - p += 2; - } - - p += 32 - 16; - } - } - - break; - - case 8: - for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 8; - for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 8) - { - uint8 *q = line; - for (int32 l = 0; l < 8; l++, q += bytes_per_line) - { - for (int32 b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - - p += 2; - } - - p += 64 - 16; - } - } - - break; + } } } } @@ -501,7 +580,7 @@ bool8 S9xDoDMA (uint8 Channel) // CPU -> PPU int32 b = 0; uint16 p = d->AAddress; - uint8 *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); + uint8 *base = GetBasePointer((d->ABank << 16) + d->AAddress); bool8 inWRAM_DMA; int32 rem = count; @@ -543,8 +622,7 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; \ CPU.InDMAorHDMA = FALSE; \ CPU.InWRAMDMAorHDMA = FALSE; \ - CPU.CurrentDMAorHDMAChannel = -1; \ - return (FALSE); \ + return FALSE; \ } while (1) @@ -574,7 +652,7 @@ bool8 S9xDoDMA (uint8 Channel) // This is a variation on Duff's Device. It is legal C/C++. switch (b) { - default: + default: while (count > 1) { Work = S9xGetByte((d->ABank << 16) + p); @@ -582,7 +660,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -606,7 +684,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = S9xGetByte((d->ABank << 16) + p); @@ -618,7 +696,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2100 + d->BAddress); UPDATE_COUNTERS; @@ -628,7 +706,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -638,7 +716,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -656,7 +734,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = S9xGetByte((d->ABank << 16) + p); @@ -668,7 +746,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -678,7 +756,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2102 + d->BAddress); UPDATE_COUNTERS; @@ -688,7 +766,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2103 + d->BAddress); UPDATE_COUNTERS; @@ -716,114 +794,114 @@ bool8 S9xDoDMA (uint8 Channel) { switch (d->BAddress) { - case 0x04: // OAMDATA + case 0x04: // OAMDATA + do + { + Work = *(base + p); + REGISTER_2104(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + + break; + + case 0x18: // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { do { Work = *(base + p); - REGISTER_2104(Work); + REGISTER_2118_linear(Work); UPDATE_COUNTERS; CHECK_SOUND(); } while (--count > 0); - - break; - - case 0x18: // VMDATAL - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2118_linear(Work); - UPDATE_COUNTERS; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2118_tile(Work); - UPDATE_COUNTERS; - CHECK_SOUND(); - } while (--count > 0); - } - - break; - - case 0x19: // VMDATAH - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2119_linear(Work); - UPDATE_COUNTERS; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2119_tile(Work); - UPDATE_COUNTERS; - CHECK_SOUND(); - } while (--count > 0); - } - - break; - - case 0x22: // CGDATA + } + else + { do { Work = *(base + p); - REGISTER_2122(Work); + REGISTER_2118_tile(Work); UPDATE_COUNTERS; CHECK_SOUND(); } while (--count > 0); + } - break; + break; - case 0x80: // WMDATA - if (!CPU.InWRAMDMAorHDMA) - { - do - { - Work = *(base + p); - REGISTER_2180(Work); - UPDATE_COUNTERS; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - UPDATE_COUNTERS; - CHECK_SOUND(); - } while (--count > 0); - } - - break; - - default: + case 0x19: // VMDATAH + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { do { Work = *(base + p); - S9xSetPPU(Work, 0x2100 + d->BAddress); + REGISTER_2119_linear(Work); UPDATE_COUNTERS; CHECK_SOUND(); } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } - break; + break; + + case 0x22: // CGDATA + do + { + Work = *(base + p); + REGISTER_2122(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + + break; + + case 0x80: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + { + do + { + Work = *(base + p); + REGISTER_2180(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + + break; + + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + + break; } } else @@ -839,7 +917,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: while (count > 1) { Work = *(base + p); @@ -847,7 +925,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = *(base + p); REGISTER_2119_linear(Work); UPDATE_COUNTERS; @@ -870,7 +948,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: while (count > 1) { Work = *(base + p); @@ -878,7 +956,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = *(base + p); REGISTER_2119_tile(Work); UPDATE_COUNTERS; @@ -903,7 +981,7 @@ bool8 S9xDoDMA (uint8 Channel) // DMA mode 1 general case switch (b) { - default: + default: while (count > 1) { Work = *(base + p); @@ -911,7 +989,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -936,7 +1014,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = *(base + p); @@ -948,7 +1026,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = *(base + p); S9xSetPPU(Work, 0x2100 + d->BAddress); UPDATE_COUNTERS; @@ -958,7 +1036,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -968,7 +1046,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -986,7 +1064,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = *(base + p); @@ -998,7 +1076,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -1008,7 +1086,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = *(base + p); S9xSetPPU(Work, 0x2102 + d->BAddress); UPDATE_COUNTERS; @@ -1018,7 +1096,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = *(base + p); S9xSetPPU(Work, 0x2103 + d->BAddress); UPDATE_COUNTERS; @@ -1043,7 +1121,7 @@ bool8 S9xDoDMA (uint8 Channel) if (rem <= 0) break; - base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); + base = GetBasePointer((d->ABank << 16) + d->AAddress); count = MEMMAP_BLOCK_SIZE; inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); @@ -1064,8 +1142,7 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; \ CPU.InDMAorHDMA = FALSE; \ CPU.InWRAMDMAorHDMA = FALSE; \ - CPU.CurrentDMAorHDMAChannel = -1; \ - return (FALSE); \ + return FALSE; \ } if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) @@ -1075,107 +1152,107 @@ bool8 S9xDoDMA (uint8 Channel) { switch (d->TransferMode) { - case 0: - case 2: - case 6: - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + case 0: + case 2: + case 6: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 1: + case 5: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 3: + case 7: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { UPDATE_COUNTERS; count--; + } - break; - - case 1: - case 5: - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - count--; - - break; - - case 3: - case 7: - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - count--; - - break; - - case 4: - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2102 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); - Work = S9xGetPPU(0x2103 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - count--; - - break; - - default: - #ifdef DEBUGGER - sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); - S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); - #endif - while (count) - { - UPDATE_COUNTERS; - count--; - } - - break; + break; } CHECK_SOUND(); @@ -1189,96 +1266,96 @@ bool8 S9xDoDMA (uint8 Channel) { switch (d->TransferMode) { - case 0: - case 2: - case 6: - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + case 0: + case 2: + case 6: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 1: + case 5: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 3: + case 7: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { UPDATE_COUNTERS; count--; + } - break; - - case 1: - case 5: - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - count--; - - break; - - case 3: - case 7: - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - count--; - - break; - - case 4: - Work = S9xGetPPU(0x2100 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2101 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2102 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - if (!--count) - break; - - Work = S9xGetPPU(0x2103 + d->BAddress); - S9xSetByte(Work, (d->ABank << 16) + d->AAddress); - UPDATE_COUNTERS; - count--; - - break; - - default: - #ifdef DEBUGGER - sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); - S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); - #endif - while (count) - { - UPDATE_COUNTERS; - count--; - } - - break; + break; } CHECK_SOUND(); @@ -1286,9 +1363,13 @@ bool8 S9xDoDMA (uint8 Channel) } } + // If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger + // after the DMA completes (even if /NMI goes high again before the DMA + // completes). In this case, there is a 24-30 cycle delay between the end of DMA + // and the NMI handler, time enough for an instruction or two. if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff)) { - Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; + Timings.NMITriggerPos = CPU.Cycles + 30; if (Timings.NMITriggerPos >= Timings.H_Max) Timings.NMITriggerPos -= Timings.H_Max; } @@ -1296,11 +1377,11 @@ bool8 S9xDoDMA (uint8 Channel) // Release the memory used in SPC7110 DMA if (Settings.SPC7110) { - if (spc7110_dma) + if (spc7110_dma && s7_wrap) delete [] spc7110_dma; } -#if 0 +#if 1 // sanity check if (d->TransferBytes != 0) fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes); @@ -1309,464 +1390,387 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; CPU.InWRAMDMAorHDMA = FALSE; - CPU.CurrentDMAorHDMAChannel = -1; - return (TRUE); + return TRUE; } -static inline bool8 HDMAReadLineCount (int d) -{ - // CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. +static inline bool8 HDMAReadLineCount(int d){ + //remember, InDMA is set. + //Get/Set incur no charges! + uint8 line = S9xGetByte ((DMA[d].ABank << 16) + DMA[d].Address); + CPU.Cycles+=SLOW_ONE_CYCLE; + if(!line){ + DMA[d].Repeat = FALSE; + DMA[d].LineCount = 128; + if(DMA[d].HDMAIndirectAddressing){ + if(PPU.HDMA&(0xfe<HDMAIndirectAddressing) { + ShiftedIBank = (p->IndirectBank << 16); + IAddr = p->IndirectAddress; + } else { + ShiftedIBank = (p->ABank << 16); + IAddr = p->Address; + } + if (!HDMAMemPointers [d]) { + HDMAMemPointers [d] = S9xGetMemPointer (ShiftedIBank + IAddr); + } - if (p->HDMAIndirectAddressing) - { - ShiftedIBank = (p->IndirectBank << 16); - IAddr = p->IndirectAddress; - } - else - { - ShiftedIBank = (p->ABank << 16); - IAddr = p->Address; - } + if (p->DoTransfer) { + // XXX: Hack for Uniracers, because we don't understand + // OAM Address Invalidation + if (p->BAddress == 0x04){ + if(SNESGameFixes.Uniracers){ + PPU.OAMAddr = 0x10c; + PPU.OAMFlip=0; + } + } - if (!HDMAMemPointers[d]) - HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr); +#ifdef DEBUGGER + if (Settings.TraceSoundDSP && p->DoTransfer && + p->BAddress >= 0x40 && p->BAddress <= 0x43) + S9xTraceSoundDSP ("Spooling data!!!\n"); + if (Settings.TraceHDMA && p->DoTransfer) + { + sprintf (String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", + p-DMA, p->ReverseTransfer? "read" : "write", + p->TransferMode, ShiftedIBank+IAddr, p->BAddress, + p->HDMAIndirectAddressing ? "ind" : "abs", + p->LineCount, + p->Repeat ? "yes" : "no ", CPU.V_Counter, + p->ABank, p->Address); + S9xMessage (S9X_TRACE, S9X_HDMA_TRACE, String); + } +#endif - if (p->DoTransfer) - { - // XXX: Hack for Uniracers, because we don't understand - // OAM Address Invalidation - if (p->BAddress == 0x04) - { - if (SNESGameFixes.Uniracers) - { - PPU.OAMAddr = 0x10c; - PPU.OAMFlip = 0; - } - } + if (!p->ReverseTransfer) { + if((IAddr&MEMMAP_MASK)+HDMA_ModeByteCounts[p->TransferMode]>=MEMMAP_BLOCK_SIZE){ + // HDMA REALLY-SLOW PATH + HDMAMemPointers[d]=NULL; +#define DOBYTE(Addr, RegOff) \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && ((uint16)(Addr))<0x2000)); \ + S9xSetPPU (S9xGetByte(ShiftedIBank + ((uint16)(Addr))), 0x2100 + p->BAddress + RegOff); + switch (p->TransferMode) { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + DOBYTE(IAddr, 0); + break; + case 5: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 1); + DOBYTE(IAddr+2, 0); + DOBYTE(IAddr+3, 1); + break; + case 1: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 1); + break; + case 2: + case 6: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 0); + break; + case 3: + case 7: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 0); + DOBYTE(IAddr+2, 1); + DOBYTE(IAddr+3, 1); + break; + case 4: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 1); + DOBYTE(IAddr+2, 2); + DOBYTE(IAddr+3, 3); + break; + } +#undef DOBYTE + } else { + CPU.InWRAMDMAorHDMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && IAddr<0x2000)); + if(!HDMAMemPointers[d]){ + // HDMA SLOW PATH + uint32 Addr = ShiftedIBank + IAddr; + switch (p->TransferMode) { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + S9xSetPPU (S9xGetByte(Addr), 0x2100 + p->BAddress); + break; + case 5: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + S9xSetPPU (S9xGetByte(Addr+0), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+1), 0x2101 + p->BAddress); + Addr+=2; + /* fall through */ + case 1: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + S9xSetPPU (S9xGetByte(Addr+0), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+1), 0x2101 + p->BAddress); + break; + case 2: + case 6: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + S9xSetPPU (S9xGetByte(Addr+0), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+1), 0x2100 + p->BAddress); + break; + case 3: + case 7: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + S9xSetPPU (S9xGetByte(Addr+0), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+1), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+2), 0x2101 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+3), 0x2101 + p->BAddress); + break; + case 4: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + S9xSetPPU (S9xGetByte(Addr+0), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+1), 0x2101 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+2), 0x2102 + p->BAddress); + S9xSetPPU (S9xGetByte(Addr+3), 0x2103 + p->BAddress); + break; + } + } else { + // HDMA FAST PATH + switch (p->TransferMode) { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + S9xSetPPU (*HDMAMemPointers [d]++, 0x2100 + p->BAddress); + break; + case 5: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); + HDMAMemPointers [d] += 2; + /* fall through */ + case 1: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); + HDMAMemPointers [d] += 2; + break; + case 2: + case 6: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); + HDMAMemPointers [d] += 2; + break; + case 3: + case 7: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 2), 0x2101 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 3), 0x2101 + p->BAddress); + HDMAMemPointers [d] += 4; + break; + case 4: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 2), 0x2102 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 3), 0x2103 + p->BAddress); + HDMAMemPointers [d] += 4; + break; + } + } + } + } else { + // REVERSE HDMA REALLY-SLOW PATH + // anomie says: Since this is apparently never used + // (otherwise we would have noticed before now), let's not + // bother with faster paths. + HDMAMemPointers[d]=NULL; +#define DOBYTE(Addr, RegOff) \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && ((uint16)(Addr))<0x2000)); \ + S9xSetByte (S9xGetPPU(0x2100 + p->BAddress + RegOff), ShiftedIBank + ((uint16)(Addr))); + switch (p->TransferMode) { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + DOBYTE(IAddr, 0); + break; + case 5: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 1); + DOBYTE(IAddr+2, 0); + DOBYTE(IAddr+3, 1); + break; + case 1: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 1); + break; + case 2: + case 6: + CPU.Cycles += 2*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 0); + break; + case 3: + case 7: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 0); + DOBYTE(IAddr+2, 1); + DOBYTE(IAddr+3, 1); + break; + case 4: + CPU.Cycles += 4*SLOW_ONE_CYCLE; + DOBYTE(IAddr+0, 0); + DOBYTE(IAddr+1, 1); + DOBYTE(IAddr+2, 2); + DOBYTE(IAddr+3, 3); + break; + } +#undef DOBYTE + } + if (p->HDMAIndirectAddressing){ + p->IndirectAddress += HDMA_ModeByteCounts [p->TransferMode]; + } else { + p->Address += HDMA_ModeByteCounts [p->TransferMode]; + } + } - #ifdef DEBUGGER - if (Settings.TraceHDMA && p->DoTransfer) - { - sprintf(String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", - p-DMA, p->ReverseTransfer? "read" : "write", - p->TransferMode, ShiftedIBank+IAddr, p->BAddress, - p->HDMAIndirectAddressing ? "ind" : "abs", - p->LineCount, - p->Repeat ? "yes" : "no ", (long) CPU.V_Counter, - p->ABank, p->Address); - S9xMessage(S9X_TRACE, S9X_HDMA_TRACE, String); - } - #endif + p->DoTransfer = !p->Repeat; + if (!--p->LineCount) { + if (!HDMAReadLineCount(d)) { + byte &= ~mask; + PPU.HDMAEnded |= mask; + p->DoTransfer = FALSE; + continue; + } + } else { + CPU.Cycles += SLOW_ONE_CYCLE; + } + } + } - if (!p->ReverseTransfer) - { - if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) - { - // HDMA REALLY-SLOW PATH - HDMAMemPointers[d] = NULL; + S9xAPUExecute(); - #define DOBYTE(Addr, RegOff) \ - CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ - (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ - S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16) (Addr))), 0x2100 + p->BAddress + (RegOff)); - - switch (p->TransferMode) - { - case 0: - CPU.Cycles += SLOW_ONE_CYCLE; - DOBYTE(IAddr, 0); - break; - - case 5: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 1); - DOBYTE(IAddr + 2, 0); - DOBYTE(IAddr + 3, 1); - break; - - case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 1); - break; - - case 2: - case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 0); - break; - - case 3: - case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 0); - DOBYTE(IAddr + 2, 1); - DOBYTE(IAddr + 3, 1); - break; - - case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 1); - DOBYTE(IAddr + 2, 2); - DOBYTE(IAddr + 3, 3); - break; - } - - #undef DOBYTE - } - else - { - CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || - (!(ShiftedIBank & 0x400000) && IAddr < 0x2000)); - - if (!HDMAMemPointers[d]) - { - // HDMA SLOW PATH - uint32 Addr = ShiftedIBank + IAddr; - - switch (p->TransferMode) - { - case 0: - CPU.Cycles += SLOW_ONE_CYCLE; - S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); - break; - - case 5: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); - Addr += 2; - /* fall through */ - case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); - break; - - case 2: - case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); - break; - - case 3: - case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); - break; - - case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); - S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); - break; - } - } - else - { - // HDMA FAST PATH - switch (p->TransferMode) - { - case 0: - CPU.Cycles += SLOW_ONE_CYCLE; - S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); - break; - - case 5: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); - HDMAMemPointers[d] += 2; - /* fall through */ - case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); - HDMAMemPointers[d] += 2; - break; - - case 2: - case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); - HDMAMemPointers[d] += 2; - break; - - case 3: - case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress); - HDMAMemPointers[d] += 4; - break; - - case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress); - S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); - HDMAMemPointers[d] += 4; - break; - } - } - } - } - else - { - // REVERSE HDMA REALLY-SLOW PATH - // anomie says: Since this is apparently never used - // (otherwise we would have noticed before now), let's not bother with faster paths. - HDMAMemPointers[d] = NULL; - - #define DOBYTE(Addr, RegOff) \ - CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ - (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ - S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + (RegOff)), ShiftedIBank + ((uint16) (Addr))); - - switch (p->TransferMode) - { - case 0: - CPU.Cycles += SLOW_ONE_CYCLE; - DOBYTE(IAddr, 0); - break; - - case 5: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 1); - DOBYTE(IAddr + 2, 0); - DOBYTE(IAddr + 3, 1); - break; - - case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 1); - break; - - case 2: - case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 0); - break; - - case 3: - case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 0); - DOBYTE(IAddr + 2, 1); - DOBYTE(IAddr + 3, 1); - break; - - case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; - DOBYTE(IAddr + 0, 0); - DOBYTE(IAddr + 1, 1); - DOBYTE(IAddr + 2, 2); - DOBYTE(IAddr + 3, 3); - break; - } - - #undef DOBYTE - } - - if (p->HDMAIndirectAddressing) - p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; - else - p->Address += HDMA_ModeByteCounts[p->TransferMode]; - } - - p->DoTransfer = !p->Repeat; - - if (!--p->LineCount) - { - if (!HDMAReadLineCount(d)) - { - byte &= ~mask; - PPU.HDMAEnded |= mask; - p->DoTransfer = FALSE; - continue; - } - } - else - CPU.Cycles += SLOW_ONE_CYCLE; - } - } - - CPU.InHDMA = FALSE; + CPU.InHDMA = FALSE; CPU.InDMAorHDMA = CPU.InDMA; CPU.InWRAMDMAorHDMA = temp; - CPU.CurrentDMAorHDMAChannel = tmpch; - return (byte); + return (byte); } -void S9xResetDMA (void) -{ - for (int d = 0; d < 8; d++) - { - DMA[d].ReverseTransfer = TRUE; - DMA[d].HDMAIndirectAddressing = TRUE; - DMA[d].AAddressFixed = TRUE; - DMA[d].AAddressDecrement = TRUE; - DMA[d].TransferMode = 7; - DMA[d].BAddress = 0xff; - DMA[d].AAddress = 0xffff; - DMA[d].ABank = 0xff; - DMA[d].DMACount_Or_HDMAIndirectAddress = 0xffff; - DMA[d].IndirectBank = 0xff; - DMA[d].Address = 0xffff; - DMA[d].Repeat = FALSE; - DMA[d].LineCount = 0x7f; - DMA[d].UnknownByte = 0xff; - DMA[d].DoTransfer = FALSE; +void S9xResetDMA () { + int d; + for (d = 0; d < 8; d++) { + DMA[d].ReverseTransfer = TRUE; + DMA[d].HDMAIndirectAddressing = TRUE; + DMA[d].AAddressFixed = TRUE; + DMA[d].AAddressDecrement = TRUE; + DMA[d].TransferMode = 7; + DMA[d].BAddress = 0xff; + DMA[d].AAddress = 0xffff; + DMA[d].ABank = 0xff; + DMA[d].DMACount_Or_HDMAIndirectAddress = 0xffff; + DMA[d].IndirectBank = 0xff; + DMA[d].Address = 0xffff; + DMA[d].Repeat = FALSE; + DMA[d].LineCount = 0x7f; + DMA[d].UnknownByte = 0xff; + DMA[d].DoTransfer = FALSE; DMA[d].UnusedBit43x0 = 1; - } + } } diff --git a/source/snes9x/dma.h b/source/snes9x/dma.h index 396811e..38c5666 100644 --- a/source/snes9x/dma.h +++ b/source/snes9x/dma.h @@ -159,37 +159,17 @@ **********************************************************************************/ + + #ifndef _DMA_H_ #define _DMA_H_ -struct SDMA -{ - bool8 ReverseTransfer; - bool8 HDMAIndirectAddressing; - bool8 UnusedBit43x0; - bool8 AAddressFixed; - bool8 AAddressDecrement; - uint8 TransferMode; - uint8 BAddress; - uint16 AAddress; - uint8 ABank; - uint16 DMACount_Or_HDMAIndirectAddress; - uint8 IndirectBank; - uint16 Address; - uint8 Repeat; - uint8 LineCount; - uint8 UnknownByte; - uint8 DoTransfer; -}; - -#define TransferBytes DMACount_Or_HDMAIndirectAddress -#define IndirectAddress DMACount_Or_HDMAIndirectAddress - -extern struct SDMA DMA[8]; - -bool8 S9xDoDMA (uint8); -void S9xStartHDMA (void); +START_EXTERN_C +void S9xResetDMA (); uint8 S9xDoHDMA (uint8); -void S9xResetDMA (void); +void S9xStartHDMA (); +bool8 S9xDoDMA (uint8); +END_EXTERN_C #endif + diff --git a/source/snes9x/dsp.h b/source/snes9x/dsp.h deleted file mode 100644 index 24cc62e..0000000 --- a/source/snes9x/dsp.h +++ /dev/null @@ -1,602 +0,0 @@ -/********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com) - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley, - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001-2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight, - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound DSP emulator code is derived from SNEeSe and OpenSPC: - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2007 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -**********************************************************************************/ - - -#ifndef _DSP1_H_ -#define _DSP1_H_ - -enum -{ - M_DSP1_LOROM_S, - M_DSP1_LOROM_L, - M_DSP1_HIROM, - M_DSP2_LOROM, - M_DSP3_LOROM, - M_DSP4_LOROM -}; - -struct SDSP0 -{ - uint32 maptype; - uint32 boundary; -}; - -struct SDSP1 -{ - bool8 waiting4command; - bool8 first_parameter; - uint8 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters[512]; - uint8 output[512]; - - int16 CentreX; - int16 CentreY; - int16 VOffset; - - int16 VPlane_C; - int16 VPlane_E; - - // Azimuth and Zenith angles - int16 SinAas; - int16 CosAas; - int16 SinAzs; - int16 CosAzs; - - // Clipped Zenith angle - int16 SinAZS; - int16 CosAZS; - int16 SecAZS_C1; - int16 SecAZS_E1; - int16 SecAZS_C2; - int16 SecAZS_E2; - - int16 Nx; - int16 Ny; - int16 Nz; - int16 Gx; - int16 Gy; - int16 Gz; - int16 C_Les; - int16 E_Les; - int16 G_Les; - - int16 matrixA[3][3]; - int16 matrixB[3][3]; - int16 matrixC[3][3]; - - int16 Op00Multiplicand; - int16 Op00Multiplier; - int16 Op00Result; - - int16 Op20Multiplicand; - int16 Op20Multiplier; - int16 Op20Result; - - int16 Op10Coefficient; - int16 Op10Exponent; - int16 Op10CoefficientR; - int16 Op10ExponentR; - - int16 Op04Angle; - int16 Op04Radius; - int16 Op04Sin; - int16 Op04Cos; - - int16 Op0CA; - int16 Op0CX1; - int16 Op0CY1; - int16 Op0CX2; - int16 Op0CY2; - - int16 Op02FX; - int16 Op02FY; - int16 Op02FZ; - int16 Op02LFE; - int16 Op02LES; - int16 Op02AAS; - int16 Op02AZS; - int16 Op02VOF; - int16 Op02VVA; - int16 Op02CX; - int16 Op02CY; - - int16 Op0AVS; - int16 Op0AA; - int16 Op0AB; - int16 Op0AC; - int16 Op0AD; - - int16 Op06X; - int16 Op06Y; - int16 Op06Z; - int16 Op06H; - int16 Op06V; - int16 Op06M; - - int16 Op01m; - int16 Op01Zr; - int16 Op01Xr; - int16 Op01Yr; - - int16 Op11m; - int16 Op11Zr; - int16 Op11Xr; - int16 Op11Yr; - - int16 Op21m; - int16 Op21Zr; - int16 Op21Xr; - int16 Op21Yr; - - int16 Op0DX; - int16 Op0DY; - int16 Op0DZ; - int16 Op0DF; - int16 Op0DL; - int16 Op0DU; - - int16 Op1DX; - int16 Op1DY; - int16 Op1DZ; - int16 Op1DF; - int16 Op1DL; - int16 Op1DU; - - int16 Op2DX; - int16 Op2DY; - int16 Op2DZ; - int16 Op2DF; - int16 Op2DL; - int16 Op2DU; - - int16 Op03F; - int16 Op03L; - int16 Op03U; - int16 Op03X; - int16 Op03Y; - int16 Op03Z; - - int16 Op13F; - int16 Op13L; - int16 Op13U; - int16 Op13X; - int16 Op13Y; - int16 Op13Z; - - int16 Op23F; - int16 Op23L; - int16 Op23U; - int16 Op23X; - int16 Op23Y; - int16 Op23Z; - - int16 Op14Zr; - int16 Op14Xr; - int16 Op14Yr; - int16 Op14U; - int16 Op14F; - int16 Op14L; - int16 Op14Zrr; - int16 Op14Xrr; - int16 Op14Yrr; - - int16 Op0EH; - int16 Op0EV; - int16 Op0EX; - int16 Op0EY; - - int16 Op0BX; - int16 Op0BY; - int16 Op0BZ; - int16 Op0BS; - - int16 Op1BX; - int16 Op1BY; - int16 Op1BZ; - int16 Op1BS; - - int16 Op2BX; - int16 Op2BY; - int16 Op2BZ; - int16 Op2BS; - - int16 Op28X; - int16 Op28Y; - int16 Op28Z; - int16 Op28R; - - int16 Op1CX; - int16 Op1CY; - int16 Op1CZ; - int16 Op1CXBR; - int16 Op1CYBR; - int16 Op1CZBR; - int16 Op1CXAR; - int16 Op1CYAR; - int16 Op1CZAR; - int16 Op1CX1; - int16 Op1CY1; - int16 Op1CZ1; - int16 Op1CX2; - int16 Op1CY2; - int16 Op1CZ2; - - uint16 Op0FRamsize; - uint16 Op0FPass; - - int16 Op2FUnknown; - int16 Op2FSize; - - int16 Op08X; - int16 Op08Y; - int16 Op08Z; - int16 Op08Ll; - int16 Op08Lh; - - int16 Op18X; - int16 Op18Y; - int16 Op18Z; - int16 Op18R; - int16 Op18D; - - int16 Op38X; - int16 Op38Y; - int16 Op38Z; - int16 Op38R; - int16 Op38D; -}; - -struct SDSP2 -{ - bool8 waiting4command; - uint8 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters[512]; - uint8 output[512]; - - bool8 Op05HasLen; - int32 Op05Len; - uint8 Op05Transparent; - - bool8 Op06HasLen; - int32 Op06Len; - - uint16 Op09Word1; - uint16 Op09Word2; - - bool8 Op0DHasLen; - int32 Op0DOutLen; - int32 Op0DInLen; -}; - -struct SDSP3 -{ - uint16 DR; - uint16 SR; - uint16 MemoryIndex; - - int16 WinLo; - int16 WinHi; - int16 AddLo; - int16 AddHi; - - uint16 Codewords; - uint16 Outwords; - uint16 Symbol; - uint16 BitCount; - uint16 Index; - uint16 Codes[512]; - uint16 BitsLeft; - uint16 ReqBits; - uint16 ReqData; - uint16 BitCommand; - uint8 BaseLength; - uint16 BaseCodes; - uint16 BaseCode; - uint8 CodeLengths[8]; - uint16 CodeOffsets[8]; - uint16 LZCode; - uint8 LZLength; - - uint16 X; - uint16 Y; - - uint8 Bitmap[8]; - uint8 Bitplane[8]; - uint16 BMIndex; - uint16 BPIndex; - uint16 Count; - - int16 op3e_x; - int16 op3e_y; - - int16 op1e_terrain[0x2000]; - int16 op1e_cost[0x2000]; - int16 op1e_weight[0x2000]; - - int16 op1e_cell; - int16 op1e_turn; - int16 op1e_search; - - int16 op1e_x; - int16 op1e_y; - - int16 op1e_min_radius; - int16 op1e_max_radius; - - int16 op1e_max_search_radius; - int16 op1e_max_path_radius; - - int16 op1e_lcv_radius; - int16 op1e_lcv_steps; - int16 op1e_lcv_turns; -}; - -struct SDSP4 -{ - bool8 waiting4command; - bool8 half_command; - uint16 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters[512]; - uint8 output[512]; - uint8 byte; - uint16 address; - - // op control - int8 Logic; // controls op flow - - // projection format - int16 lcv; // loop-control variable - int16 distance; // z-position into virtual world - int16 raster; // current raster line - int16 segments; // number of raster lines drawn - - // 1.15.16 or 1.15.0 [sign, integer, fraction] - int32 world_x; // line of x-projection in world - int32 world_y; // line of y-projection in world - int32 world_dx; // projection line x-delta - int32 world_dy; // projection line y-delta - int16 world_ddx; // x-delta increment - int16 world_ddy; // y-delta increment - int32 world_xenv; // world x-shaping factor - int16 world_yofs; // world y-vertical scroll - int16 view_x1; // current viewer-x - int16 view_y1; // current viewer-y - int16 view_x2; // future viewer-x - int16 view_y2; // future viewer-y - int16 view_dx; // view x-delta factor - int16 view_dy; // view y-delta factor - int16 view_xofs1; // current viewer x-vertical scroll - int16 view_yofs1; // current viewer y-vertical scroll - int16 view_xofs2; // future viewer x-vertical scroll - int16 view_yofs2; // future viewer y-vertical scroll - int16 view_yofsenv; // y-scroll shaping factor - int16 view_turnoff_x; // road turnoff data - int16 view_turnoff_dx; // road turnoff delta factor - - // drawing area - int16 viewport_cx; // x-center of viewport window - int16 viewport_cy; // y-center of render window - int16 viewport_left; // x-left of viewport - int16 viewport_right; // x-right of viewport - int16 viewport_top; // y-top of viewport - int16 viewport_bottom; // y-bottom of viewport - - // sprite structure - int16 sprite_x; // projected x-pos of sprite - int16 sprite_y; // projected y-pos of sprite - int16 sprite_attr; // obj attributes - bool8 sprite_size; // sprite size: 8x8 or 16x16 - int16 sprite_clipy; // visible line to clip pixels off - int16 sprite_count; - - // generic projection variables designed for two solid polygons + two polygon sides - int16 poly_clipLf[2][2]; // left clip boundary - int16 poly_clipRt[2][2]; // right clip boundary - int16 poly_ptr[2][2]; // HDMA structure pointers - int16 poly_raster[2][2]; // current raster line below horizon - int16 poly_top[2][2]; // top clip boundary - int16 poly_bottom[2][2]; // bottom clip boundary - int16 poly_cx[2][2]; // center for left/right points - int16 poly_start[2]; // current projection points - int16 poly_plane[2]; // previous z-plane distance - - // OAM - int16 OAM_attr[16]; // OAM (size, MSB) data - int16 OAM_index; // index into OAM table - int16 OAM_bits; // offset into OAM table - int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row) - int16 OAM_Row[32]; // current number of tiles per row -}; - -extern struct SDSP0 DSP0; -extern struct SDSP1 DSP1; -extern struct SDSP2 DSP2; -extern struct SDSP3 DSP3; -extern struct SDSP4 DSP4; - -uint8 S9xGetDSP (uint16); -void S9xSetDSP (uint8, uint16); -void S9xResetDSP (void); -uint8 DSP1GetByte (uint16); -void DSP1SetByte (uint8, uint16); -uint8 DSP2GetByte (uint16); -void DSP2SetByte (uint8, uint16); -uint8 DSP3GetByte (uint16); -void DSP3SetByte (uint8, uint16); -uint8 DSP4GetByte (uint16); -void DSP4SetByte (uint8, uint16); -void DSP3_Reset (void); - -extern uint8 (*GetDSP) (uint16); -extern void (*SetDSP) (uint8, uint16); - -#endif diff --git a/source/snes9x/dsp1.cpp b/source/snes9x/dsp1.cpp index f6be5c8..2ce54c9 100644 --- a/source/snes9x/dsp1.cpp +++ b/source/snes9x/dsp1.cpp @@ -158,1719 +158,897 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ -/* -Copyright (C) 1997-2006 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach ) - -http://www.zsnes.com -http://sourceforge.net/projects/zsnes - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ #include "snes9x.h" +#include "dsp1.h" +#include "missing.h" #include "memmap.h" +#include +#include + +#include "dsp1emu.c.inc" +#include "dsp2emu.c.inc" +#include "dsp3emu.c.inc" +#include "dsp4emu.c.inc" + +void (*SetDSP)(uint8, uint16)=&DSP1SetByte; +uint8 (*GetDSP)(uint16)=&DSP1GetByte; + +void S9xInitDSP1 () +{ + static bool8 init = FALSE; + + if (!init) + { + InitDSP (); + init = TRUE; + } +} + +void S9xResetDSP1 () +{ + S9xInitDSP1 (); + + DSP1.waiting4command = TRUE; + DSP1.in_count = 0; + DSP1.out_count = 0; + DSP1.in_index = 0; + DSP1.out_index = 0; + DSP1.first_parameter = TRUE; + + DSP4.waiting4command = TRUE; + //printf("DSP-4 Reset\n"); +} + +uint8 S9xGetDSP (uint16 address) +{ + uint8 t; #ifdef DEBUGGER -//#define DebugDSP1 + if (Settings.TraceDSP) + { + sprintf (String, "DSP read: 0x%04X", address); + S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); + } #endif -#ifdef DebugDSP1 -static FILE *LogFile = NULL; + t=(*GetDSP)(address); + //DSP1GetByte(address); + return (t); +} + +void S9xSetDSP (uint8 byte, uint16 address) +{ +#ifdef DEBUGGER + missing.unknowndsp_write = address; + if (Settings.TraceDSP) + { + sprintf (String, "DSP write: 0x%04X=0x%02X", address, byte); + S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); + } #endif - -static const uint16 DSP1ROM[1024] = -{ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, - 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, - 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, - 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, - 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, - 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, - 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, - 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, - 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, - 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, - 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, - 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, - 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, - 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, - 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, - 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, - 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, - 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, - 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, - 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, - 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, - 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, - 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, - 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, - 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, - 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, - 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, - 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, - 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, - 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, - 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, - 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, - 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, - 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, - 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, - 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, - 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, - 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, - 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, - 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, - 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, - 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, - 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, - 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, - 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, - 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, - 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, - 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, - 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, - 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, - 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, - 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, - 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, - 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, - 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, - 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, - 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, - 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, - 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, - 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, - 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, - 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, - 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, - 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, - 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, - 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, - 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, - 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, - 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, - 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, - 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, - 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, - 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, - 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, - 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, - 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, - 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, - 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, - 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, - 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, - 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, - 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, - 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, - 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, - 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, - 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, - 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, - 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, - 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, - 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, - 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, - 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, - 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff -}; - -static const int16 DSP1_MulTable[256] = -{ - 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, - 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, - 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, - 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, - 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, - 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, - 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, - 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, - 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, - 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, - 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, - 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, - 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, - 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, - 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, - 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, - 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, - 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, - 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, - 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, - 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, - 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, - 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, - 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, - 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, - 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, - 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, - 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, - 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, - 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, - 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, - 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321 -}; - -static const int16 DSP1_SinTable[256] = -{ - 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, - 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, - 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, - 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, - 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, - 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, - 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, - 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, - 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, - 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, - 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, - 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, - 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, - 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, - 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, - 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, - -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, - -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, - -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, - -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, - -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, - -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, - -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, - -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, - -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, - -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, - -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, - -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, - -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, - -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, - -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, - -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324 -}; - - -#ifdef DebugDSP1 - -static void Log_Message (char *Message, ...) -{ - char Msg[400]; - va_list ap; - - va_start(ap, Message); - vsprintf(Msg, Message, ap); - va_end(ap); - - strcat(Msg, "\r\n\0"); - fwrite(Msg, strlen(Msg), 1, LogFile); - fflush(LogFile); + (*SetDSP)(byte, address); + //DSP1SetByte(byte, address); } -static void Start_Log (void) +void DSP1SetByte(uint8 byte, uint16 address) { - LogFile = fopen("dsp1emu.log", "wb"); -} - -static void Stop_Log (void) -{ - if (LogFile) - { - fclose(LogFile); - LogFile = NULL; - } -} - -#endif - -static void DSP1_Op00 (void) -{ - DSP1.Op00Result = DSP1.Op00Multiplicand * DSP1.Op00Multiplier >> 15; - -#ifdef DebugDSP1 - Log_Message("OP00 MULT %d*%d/32768=%d", DSP1.Op00Multiplicand, DSP1.Op00Multiplier, DSP1.Op00Result); -#endif -} - -static void DSP1_Op20 (void) -{ - DSP1.Op20Result = DSP1.Op20Multiplicand * DSP1.Op20Multiplier >> 15; - DSP1.Op20Result++; - -#ifdef DebugDSP1 - Log_Message("OP20 MULT %d*%d/32768=%d", DSP1.Op20Multiplicand, DSP1.Op20Multiplier, DSP1.Op20Result); -#endif -} - -static void DSP1_Inverse (int16 Coefficient, int16 Exponent, int16 *iCoefficient, int16 *iExponent) -{ - // Step One: Division by Zero - if (Coefficient == 0x0000) - { - *iCoefficient = 0x7fff; - *iExponent = 0x002f; - } - else - { - int16 Sign = 1; - - // Step Two: Remove Sign - if (Coefficient < 0) - { - if (Coefficient < -32767) - Coefficient = -32767; - Coefficient = -Coefficient; - Sign = -1; - } - - // Step Three: Normalize - while (Coefficient < 0x4000) - { - Coefficient <<= 1; - Exponent--; - } - - // Step Four: Special Case - if (Coefficient == 0x4000) - { - if (Sign == 1) - *iCoefficient = 0x7fff; - else - { - *iCoefficient = -0x4000; - Exponent--; - } - } - else - { - // Step Five: Initial Guess - int16 i = DSP1ROM[((Coefficient - 0x4000) >> 7) + 0x0065]; - - // Step Six: Iterate "estimated" Newton's Method - i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; - i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; - - *iCoefficient = i * Sign; - } - - *iExponent = 1 - Exponent; - } -} - -static void DSP1_Op10 (void) -{ - DSP1_Inverse(DSP1.Op10Coefficient, DSP1.Op10Exponent, &DSP1.Op10CoefficientR, &DSP1.Op10ExponentR); - -#ifdef DebugDSP1 - Log_Message("OP10 INV %d*2^%d = %d*2^%d", DSP1.Op10Coefficient, DSP1.Op10Exponent, DSP1.Op10CoefficientR, DSP1.Op10ExponentR); -#endif -} - -static int16 DSP1_Sin (int16 Angle) -{ - int32 S; - - if (Angle < 0) - { - if (Angle == -32768) - return (0); - - return (-DSP1_Sin(-Angle)); - } - - S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15); - if (S > 32767) - S = 32767; - - return ((int16) S); -} - -static int16 DSP1_Cos (int16 Angle) -{ - int32 S; - - if (Angle < 0) - { - if (Angle == -32768) - return (-32768); - - Angle = -Angle; - } - - S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15); - if (S < -32768) - S = -32767; - - return ((int16) S); -} - -static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent) -{ - int16 i = 0x4000; - int16 e = 0; - - if (m < 0) - { - while ((m & i) && i) - { - i >>= 1; - e++; - } - } - else - { - while (!(m & i) && i) - { - i >>= 1; - e++; - } - } - - if (e > 0) - *Coefficient = m * DSP1ROM[0x21 + e] << 1; - else - *Coefficient = m; - - *Exponent -= e; -} - -static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Exponent) -{ - int16 n = Product & 0x7fff; - int16 m = Product >> 15; - int16 i = 0x4000; - int16 e = 0; - - if (m < 0) - { - while ((m & i) && i) - { - i >>= 1; - e++; - } - } - else - { - while (!(m & i) && i) - { - i >>= 1; - e++; - } - } - - if (e > 0) - { - *Coefficient = m * DSP1ROM[0x0021 + e] << 1; - - if (e < 15) - *Coefficient += n * DSP1ROM[0x0040 - e] >> 15; - else - { - i = 0x4000; - - if (m < 0) - { - while ((n & i) && i) - { - i >>= 1; - e++; - } - } - else - { - while (!(n & i) && i) - { - i >>= 1; - e++; - } - } - - if (e > 15) - *Coefficient = n * DSP1ROM[0x0012 + e] << 1; - else - *Coefficient += n; - } - } - else - *Coefficient = m; - - *Exponent = e; -} - -static int16 DSP1_Truncate (int16 C, int16 E) -{ - if (E > 0) - { - if (C > 0) - return (32767); - else - if (C < 0) - return (-32767); - } - else - { - if (E < 0) - return (C * DSP1ROM[0x0031 + E] >> 15); - } - - return (C); -} - -static void DSP1_Op04 (void) -{ - DSP1.Op04Sin = DSP1_Sin(DSP1.Op04Angle) * DSP1.Op04Radius >> 15; - DSP1.Op04Cos = DSP1_Cos(DSP1.Op04Angle) * DSP1.Op04Radius >> 15; -} - -static void DSP1_Op0C (void) -{ - DSP1.Op0CX2 = (DSP1.Op0CY1 * DSP1_Sin(DSP1.Op0CA) >> 15) + (DSP1.Op0CX1 * DSP1_Cos(DSP1.Op0CA) >> 15); - DSP1.Op0CY2 = (DSP1.Op0CY1 * DSP1_Cos(DSP1.Op0CA) >> 15) - (DSP1.Op0CX1 * DSP1_Sin(DSP1.Op0CA) >> 15); -} - -static void DSP1_Parameter (int16 Fx, int16 Fy, int16 Fz, int16 Lfe, int16 Les, int16 Aas, int16 Azs, int16 *Vof, int16 *Vva, int16 *Cx, int16 *Cy) -{ - const int16 MaxAZS_Exp[16] = - { - 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, - 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 - }; - - int16 CSec, C, E, MaxAZS, Aux; - int16 LfeNx, LfeNy, LfeNz; - int16 LesNx, LesNy, LesNz; - int16 CentreZ; - - // Copy Zenith angle for clipping - int16 AZS = Azs; - - // Store Sine and Cosine of Azimuth and Zenith angle - DSP1.SinAas = DSP1_Sin(Aas); - DSP1.CosAas = DSP1_Cos(Aas); - DSP1.SinAzs = DSP1_Sin(Azs); - DSP1.CosAzs = DSP1_Cos(Azs); - - DSP1.Nx = DSP1.SinAzs * -DSP1.SinAas >> 15; - DSP1.Ny = DSP1.SinAzs * DSP1.CosAas >> 15; - DSP1.Nz = DSP1.CosAzs * 0x7fff >> 15; - - LfeNx = Lfe * DSP1.Nx >> 15; - LfeNy = Lfe * DSP1.Ny >> 15; - LfeNz = Lfe * DSP1.Nz >> 15; - - // Center of Projection - DSP1.CentreX = Fx + LfeNx; - DSP1.CentreY = Fy + LfeNy; - CentreZ = Fz + LfeNz; - - LesNx = Les * DSP1.Nx >> 15; - LesNy = Les * DSP1.Ny >> 15; - LesNz = Les * DSP1.Nz >> 15; - - DSP1.Gx = DSP1.CentreX - LesNx; - DSP1.Gy = DSP1.CentreY - LesNy; - DSP1.Gz = CentreZ - LesNz; - - DSP1.E_Les = 0; - DSP1_Normalize(Les, &DSP1.C_Les, &DSP1.E_Les); - DSP1.G_Les = Les; - - E = 0; - DSP1_Normalize(CentreZ, &C, &E); - - DSP1.VPlane_C = C; - DSP1.VPlane_E = E; - - // Determine clip boundary and clip Zenith angle if necessary - MaxAZS = MaxAZS_Exp[-E]; - - if (AZS < 0) - { - MaxAZS = -MaxAZS; - if (AZS < MaxAZS + 1) - AZS = MaxAZS + 1; - } - else - { - if (AZS > MaxAZS) - AZS = MaxAZS; - } - - // Store Sine and Cosine of clipped Zenith angle - DSP1.SinAZS = DSP1_Sin(AZS); - DSP1.CosAZS = DSP1_Cos(AZS); - - DSP1_Inverse(DSP1.CosAZS, 0, &DSP1.SecAZS_C1, &DSP1.SecAZS_E1); - DSP1_Normalize(C * DSP1.SecAZS_C1 >> 15, &C, &E); - E += DSP1.SecAZS_E1; - - C = DSP1_Truncate(C, E) * DSP1.SinAZS >> 15; - - DSP1.CentreX += C * DSP1.SinAas >> 15; - DSP1.CentreY -= C * DSP1.CosAas >> 15; - - *Cx = DSP1.CentreX; - *Cy = DSP1.CentreY; - - // Raster number of imaginary center and horizontal line - *Vof = 0; - - if ((Azs != AZS) || (Azs == MaxAZS)) - { - if (Azs == -32768) - Azs = -32767; - - C = Azs - MaxAZS; - if (C >= 0) - C--; - Aux = ~(C << 2); - - C = Aux * DSP1ROM[0x0328] >> 15; - C = (C * Aux >> 15) + DSP1ROM[0x0327]; - *Vof -= (C * Aux >> 15) * Les >> 15; - - C = Aux * Aux >> 15; - Aux = (C * DSP1ROM[0x0324] >> 15) + DSP1ROM[0x0325]; - DSP1.CosAZS += (C * Aux >> 15) * DSP1.CosAZS >> 15; - } - - DSP1.VOffset = Les * DSP1.CosAZS >> 15; - - DSP1_Inverse(DSP1.SinAZS, 0, &CSec, &E); - DSP1_Normalize(DSP1.VOffset, &C, &E); - DSP1_Normalize(C * CSec >> 15, &C, &E); - - if (C == -32768) - { - C >>= 1; - E++; - } - - *Vva = DSP1_Truncate(-C, E); - - // Store Secant of clipped Zenith angle - DSP1_Inverse(DSP1.CosAZS, 0, &DSP1.SecAZS_C2, &DSP1.SecAZS_E2); -} - -static void DSP1_Raster (int16 Vs, int16 *An, int16 *Bn, int16 *Cn, int16 *Dn) -{ - int16 C, E, C1, E1; - - DSP1_Inverse((Vs * DSP1.SinAzs >> 15) + DSP1.VOffset, 7, &C, &E); - E += DSP1.VPlane_E; - - C1 = C * DSP1.VPlane_C >> 15; - E1 = E + DSP1.SecAZS_E2; - - DSP1_Normalize(C1, &C, &E); - - C = DSP1_Truncate(C, E); - - *An = C * DSP1.CosAas >> 15; - *Cn = C * DSP1.SinAas >> 15; - - DSP1_Normalize(C1 * DSP1.SecAZS_C2 >> 15, &C, &E1); - - C = DSP1_Truncate(C, E1); - - *Bn = C * -DSP1.SinAas >> 15; - *Dn = C * DSP1.CosAas >> 15; -} - -static void DSP1_Op02 (void) -{ - DSP1_Parameter(DSP1.Op02FX, DSP1.Op02FY, DSP1.Op02FZ, DSP1.Op02LFE, DSP1.Op02LES, DSP1.Op02AAS, DSP1.Op02AZS, &DSP1.Op02VOF, &DSP1.Op02VVA, &DSP1.Op02CX, &DSP1.Op02CY); -} - -static void DSP1_Op0A (void) -{ - DSP1_Raster(DSP1.Op0AVS, &DSP1.Op0AA, &DSP1.Op0AB, &DSP1.Op0AC, &DSP1.Op0AD); - DSP1.Op0AVS++; -} - -static int16 DSP1_ShiftR (int16 C, int16 E) -{ - return (C * DSP1ROM[0x0031 + E] >> 15); -} - -static void DSP1_Project (int16 X, int16 Y, int16 Z, int16 *H, int16 *V, int16 *M) -{ - int32 aux, aux4; - int16 E, E2, E3, E4, E5, refE, E6, E7; - int16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; - int16 Px, Py, Pz; - - E4 = E3 = E2 = E = E5 = 0; - - DSP1_NormalizeDouble((int32) X - DSP1.Gx, &Px, &E4); - DSP1_NormalizeDouble((int32) Y - DSP1.Gy, &Py, &E ); - DSP1_NormalizeDouble((int32) Z - DSP1.Gz, &Pz, &E3); - Px >>= 1; // to avoid overflows when calculating the scalar products - E4--; - Py >>= 1; - E--; - Pz >>= 1; - E3--; - - refE = (E < E3) ? E : E3; - refE = (refE < E4) ? refE : E4; - - Px = DSP1_ShiftR(Px, E4 - refE); // normalize them to the same exponent - Py = DSP1_ShiftR(Py, E - refE); - Pz = DSP1_ShiftR(Pz, E3 - refE); - - C11 =- (Px * DSP1.Nx >> 15); - C8 =- (Py * DSP1.Ny >> 15); - C9 =- (Pz * DSP1.Nz >> 15); - C12 = C11 + C8 + C9; // this cannot overflow! - - aux4 = C12; // de-normalization with 32-bits arithmetic - refE = 16 - refE; // refE can be up to 3 - if (refE >= 0) - aux4 <<= (refE); - else - aux4 >>= -(refE); - if (aux4 == -1) - aux4 = 0; // why? - aux4 >>= 1; - - aux = ((uint16) DSP1.G_Les) + aux4; // Les - the scalar product of P with the normal vector of the screen - DSP1_NormalizeDouble(aux, &C10, &E2); - E2 = 15 - E2; - - DSP1_Inverse(C10, 0, &C4, &E4); - C2 = C4 * DSP1.C_Les >> 15; // scale factor - - // H - E7 = 0; - C16 = Px * ( DSP1.CosAas * 0x7fff >> 15) >> 15; - C20 = Py * ( DSP1.SinAas * 0x7fff >> 15) >> 15; - C17 = C16 + C20; // scalar product of P with the normalized horizontal vector of the screen... - - C18 = C17 * C2 >> 15; // ... multiplied by the scale factor - DSP1_Normalize(C18, &C19, &E7); - *H = DSP1_Truncate(C19, DSP1.E_Les - E2 + refE + E7); - - // V - E6 = 0; - C21 = Px * ( DSP1.CosAzs * -DSP1.SinAas >> 15) >> 15; - C22 = Py * ( DSP1.CosAzs * DSP1.CosAas >> 15) >> 15; - C23 = Pz * (-DSP1.SinAzs * 0x7fff >> 15) >> 15; - C24 = C21 + C22 + C23; // scalar product of P with the normalized vertical vector of the screen... - - C26 = C24 * C2 >> 15; // ... multiplied by the scale factor - DSP1_Normalize(C26, &C25, &E6); - *V = DSP1_Truncate(C25, DSP1.E_Les - E2 + refE + E6); - - // M - DSP1_Normalize(C2, &C6, &E4); - *M = DSP1_Truncate(C6, E4 + DSP1.E_Les - E2 - 7); // M is the scale factor divided by 2^7 -} - -static void DSP1_Op06 (void) -{ - DSP1_Project(DSP1.Op06X, DSP1.Op06Y, DSP1.Op06Z, &DSP1.Op06H, &DSP1.Op06V, &DSP1.Op06M); -} - -static void DSP1_Op01 (void) -{ - int16 SinAz = DSP1_Sin(DSP1.Op01Zr); - int16 CosAz = DSP1_Cos(DSP1.Op01Zr); - int16 SinAy = DSP1_Sin(DSP1.Op01Yr); - int16 CosAy = DSP1_Cos(DSP1.Op01Yr); - int16 SinAx = DSP1_Sin(DSP1.Op01Xr); - int16 CosAx = DSP1_Cos(DSP1.Op01Xr); - - DSP1.Op01m >>= 1; - - DSP1.matrixA[0][0] = (DSP1.Op01m * CosAz >> 15) * CosAy >> 15; - DSP1.matrixA[0][1] = -((DSP1.Op01m * SinAz >> 15) * CosAy >> 15); - DSP1.matrixA[0][2] = DSP1.Op01m * SinAy >> 15; - - DSP1.matrixA[1][0] = ((DSP1.Op01m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op01m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); - DSP1.matrixA[1][1] = ((DSP1.Op01m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op01m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); - DSP1.matrixA[1][2] = -((DSP1.Op01m * SinAx >> 15) * CosAy >> 15); - - DSP1.matrixA[2][0] = ((DSP1.Op01m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op01m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); - DSP1.matrixA[2][1] = ((DSP1.Op01m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op01m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); - DSP1.matrixA[2][2] = (DSP1.Op01m * CosAx >> 15) * CosAy >> 15; -} - -static void DSP1_Op11 (void) -{ - int16 SinAz = DSP1_Sin(DSP1.Op11Zr); - int16 CosAz = DSP1_Cos(DSP1.Op11Zr); - int16 SinAy = DSP1_Sin(DSP1.Op11Yr); - int16 CosAy = DSP1_Cos(DSP1.Op11Yr); - int16 SinAx = DSP1_Sin(DSP1.Op11Xr); - int16 CosAx = DSP1_Cos(DSP1.Op11Xr); - - DSP1.Op11m >>= 1; - - DSP1.matrixB[0][0] = (DSP1.Op11m * CosAz >> 15) * CosAy >> 15; - DSP1.matrixB[0][1] = -((DSP1.Op11m * SinAz >> 15) * CosAy >> 15); - DSP1.matrixB[0][2] = DSP1.Op11m * SinAy >> 15; - - DSP1.matrixB[1][0] = ((DSP1.Op11m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op11m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); - DSP1.matrixB[1][1] = ((DSP1.Op11m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op11m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); - DSP1.matrixB[1][2] = -((DSP1.Op11m * SinAx >> 15) * CosAy >> 15); - - DSP1.matrixB[2][0] = ((DSP1.Op11m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op11m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); - DSP1.matrixB[2][1] = ((DSP1.Op11m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op11m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); - DSP1.matrixB[2][2] = (DSP1.Op11m * CosAx >> 15) * CosAy >> 15; -} - -static void DSP1_Op21 (void) -{ - int16 SinAz = DSP1_Sin(DSP1.Op21Zr); - int16 CosAz = DSP1_Cos(DSP1.Op21Zr); - int16 SinAy = DSP1_Sin(DSP1.Op21Yr); - int16 CosAy = DSP1_Cos(DSP1.Op21Yr); - int16 SinAx = DSP1_Sin(DSP1.Op21Xr); - int16 CosAx = DSP1_Cos(DSP1.Op21Xr); - - DSP1.Op21m >>= 1; - - DSP1.matrixC[0][0] = (DSP1.Op21m * CosAz >> 15) * CosAy >> 15; - DSP1.matrixC[0][1] = -((DSP1.Op21m * SinAz >> 15) * CosAy >> 15); - DSP1.matrixC[0][2] = DSP1.Op21m * SinAy >> 15; - - DSP1.matrixC[1][0] = ((DSP1.Op21m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op21m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); - DSP1.matrixC[1][1] = ((DSP1.Op21m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op21m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); - DSP1.matrixC[1][2] = -((DSP1.Op21m * SinAx >> 15) * CosAy >> 15); - - DSP1.matrixC[2][0] = ((DSP1.Op21m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op21m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); - DSP1.matrixC[2][1] = ((DSP1.Op21m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op21m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); - DSP1.matrixC[2][2] = (DSP1.Op21m * CosAx >> 15) * CosAy >> 15; -} - -static void DSP1_Op0D (void) -{ - DSP1.Op0DF = (DSP1.Op0DX * DSP1.matrixA[0][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[0][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[0][2] >> 15); - DSP1.Op0DL = (DSP1.Op0DX * DSP1.matrixA[1][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[1][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[1][2] >> 15); - DSP1.Op0DU = (DSP1.Op0DX * DSP1.matrixA[2][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[2][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[2][2] >> 15); - -#ifdef DebugDSP1 - Log_Message("OP0D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op0DX, DSP1.Op0DY, DSP1.Op0DZ, DSP1.Op0DF, DSP1.Op0DL, DSP1.Op0DU); -#endif -} - -static void DSP1_Op1D (void) -{ - DSP1.Op1DF = (DSP1.Op1DX * DSP1.matrixB[0][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[0][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[0][2] >> 15); - DSP1.Op1DL = (DSP1.Op1DX * DSP1.matrixB[1][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[1][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[1][2] >> 15); - DSP1.Op1DU = (DSP1.Op1DX * DSP1.matrixB[2][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[2][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[2][2] >> 15); - -#ifdef DebugDSP1 - Log_Message("OP1D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op1DX, DSP1.Op1DY, DSP1.Op1DZ, DSP1.Op1DF, DSP1.Op1DL, DSP1.Op1DU); -#endif -} - -static void DSP1_Op2D (void) -{ - DSP1.Op2DF = (DSP1.Op2DX * DSP1.matrixC[0][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[0][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[0][2] >> 15); - DSP1.Op2DL = (DSP1.Op2DX * DSP1.matrixC[1][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[1][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[1][2] >> 15); - DSP1.Op2DU = (DSP1.Op2DX * DSP1.matrixC[2][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[2][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[2][2] >> 15); - -#ifdef DebugDSP1 - Log_Message("OP2D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op2DX, DSP1.Op2DY, DSP1.Op2DZ, DSP1.Op2DF, DSP1.Op2DL, DSP1.Op2DU); -#endif -} - -static void DSP1_Op03 (void) -{ - DSP1.Op03X = (DSP1.Op03F * DSP1.matrixA[0][0] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][0] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][0] >> 15); - DSP1.Op03Y = (DSP1.Op03F * DSP1.matrixA[0][1] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][1] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][1] >> 15); - DSP1.Op03Z = (DSP1.Op03F * DSP1.matrixA[0][2] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][2] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][2] >> 15); - -#ifdef DebugDSP1 - Log_Message("OP03 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op03F, DSP1.Op03L, DSP1.Op03U, DSP1.Op03X, DSP1.Op03Y, DSP1.Op03Z); -#endif -} - -static void DSP1_Op13 (void) -{ - DSP1.Op13X = (DSP1.Op13F * DSP1.matrixB[0][0] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][0] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][0] >> 15); - DSP1.Op13Y = (DSP1.Op13F * DSP1.matrixB[0][1] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][1] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][1] >> 15); - DSP1.Op13Z = (DSP1.Op13F * DSP1.matrixB[0][2] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][2] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][2] >> 15); - -#ifdef DebugDSP1 - Log_Message("OP13 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op13F, DSP1.Op13L, DSP1.Op13U, DSP1.Op13X, DSP1.Op13Y, DSP1.Op13Z); -#endif -} - -static void DSP1_Op23 (void) -{ - DSP1.Op23X = (DSP1.Op23F * DSP1.matrixC[0][0] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][0] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][0] >> 15); - DSP1.Op23Y = (DSP1.Op23F * DSP1.matrixC[0][1] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][1] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][1] >> 15); - DSP1.Op23Z = (DSP1.Op23F * DSP1.matrixC[0][2] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][2] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][2] >> 15); - -#ifdef DebugDSP1 - Log_Message("OP23 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op23F, DSP1.Op23L, DSP1.Op23U, DSP1.Op23X, DSP1.Op23Y, DSP1.Op23Z); -#endif -} - -static void DSP1_Op14 (void) -{ - int16 CSec, ESec, CTan, CSin, C, E; - - DSP1_Inverse(DSP1_Cos(DSP1.Op14Xr), 0, &CSec, &ESec); - - // Rotation Around Z - DSP1_NormalizeDouble(DSP1.Op14U * DSP1_Cos(DSP1.Op14Yr) - DSP1.Op14F * DSP1_Sin(DSP1.Op14Yr), &C, &E); - - E = ESec - E; - - DSP1_Normalize(C * CSec >> 15, &C, &E); - - DSP1.Op14Zrr = DSP1.Op14Zr + DSP1_Truncate(C, E); - - // Rotation Around X - DSP1.Op14Xrr = DSP1.Op14Xr + (DSP1.Op14U * DSP1_Sin(DSP1.Op14Yr) >> 15) + (DSP1.Op14F * DSP1_Cos(DSP1.Op14Yr) >> 15); - - // Rotation Around Y - DSP1_NormalizeDouble(DSP1.Op14U * DSP1_Cos(DSP1.Op14Yr) + DSP1.Op14F * DSP1_Sin(DSP1.Op14Yr), &C, &E); - - E = ESec - E; - - DSP1_Normalize(DSP1_Sin(DSP1.Op14Xr), &CSin, &E); - - CTan = CSec * CSin >> 15; - - DSP1_Normalize(-(C * CTan >> 15), &C, &E); - - DSP1.Op14Yrr = DSP1.Op14Yr + DSP1_Truncate(C, E) + DSP1.Op14L; -} - -static void DSP1_Target (int16 H, int16 V, int16 *X, int16 *Y) -{ - int16 C, E, C1, E1; - - DSP1_Inverse((V * DSP1.SinAzs >> 15) + DSP1.VOffset, 8, &C, &E); - E += DSP1.VPlane_E; - - C1 = C * DSP1.VPlane_C >> 15; - E1 = E + DSP1.SecAZS_E1; - - H <<= 8; - - DSP1_Normalize(C1, &C, &E); - - C = DSP1_Truncate(C, E) * H >> 15; - - *X = DSP1.CentreX + (C * DSP1.CosAas >> 15); - *Y = DSP1.CentreY - (C * DSP1.SinAas >> 15); - - V <<= 8; - - DSP1_Normalize(C1 * DSP1.SecAZS_C1 >> 15, &C, &E1); - - C = DSP1_Truncate(C, E1) * V >> 15; - - *X += C * -DSP1.SinAas >> 15; - *Y += C * DSP1.CosAas >> 15; -} - -static void DSP1_Op0E (void) -{ - DSP1_Target(DSP1.Op0EH, DSP1.Op0EV, &DSP1.Op0EX, &DSP1.Op0EY); -} - -static void DSP1_Op0B (void) -{ - DSP1.Op0BS = (DSP1.Op0BX * DSP1.matrixA[0][0] + DSP1.Op0BY * DSP1.matrixA[0][1] + DSP1.Op0BZ * DSP1.matrixA[0][2]) >> 15; - -#ifdef DebugDSP1 - Log_Message("OP0B"); -#endif -} - -static void DSP1_Op1B (void) -{ - DSP1.Op1BS = (DSP1.Op1BX * DSP1.matrixB[0][0] + DSP1.Op1BY * DSP1.matrixB[0][1] + DSP1.Op1BZ * DSP1.matrixB[0][2]) >> 15; - -#ifdef DebugDSP1 - Log_Message("OP1B X: %d Y: %d Z: %d S: %d", DSP1.Op1BX, DSP1.Op1BY, DSP1.Op1BZ, DSP1.Op1BS); - Log_Message(" MX: %d MY: %d MZ: %d Scale: %d", (int16) (DSP1.matrixB[0][0] * 100), (int16) (DSP1.matrixB[0][1] * 100), (int16) (DSP1.matrixB[0][2] * 100), (int16) (sc2 * 100)); -#endif -} - -static void DSP1_Op2B (void) -{ - DSP1.Op2BS = (DSP1.Op2BX * DSP1.matrixC[0][0] + DSP1.Op2BY * DSP1.matrixC[0][1] + DSP1.Op2BZ * DSP1.matrixC[0][2]) >> 15; - -#ifdef DebugDSP1 - Log_Message("OP2B"); -#endif -} - -static void DSP1_Op08 (void) -{ - int32 op08Size = (DSP1.Op08X * DSP1.Op08X + DSP1.Op08Y * DSP1.Op08Y + DSP1.Op08Z * DSP1.Op08Z) << 1; - DSP1.Op08Ll = op08Size & 0xffff; - DSP1.Op08Lh = (op08Size >> 16) & 0xffff; - -#ifdef DebugDSP1 - Log_Message("OP08 %d,%d,%d", DSP1.Op08X, DSP1.Op08Y, DSP1.Op08Z); - Log_Message("OP08 ((OP08X^2)+(OP08Y^2)+(OP08Z^2))=%x", op08Size); -#endif -} - -static void DSP1_Op18 (void) -{ - DSP1.Op18D = (DSP1.Op18X * DSP1.Op18X + DSP1.Op18Y * DSP1.Op18Y + DSP1.Op18Z * DSP1.Op18Z - DSP1.Op18R * DSP1.Op18R) >> 15; - -#ifdef DebugDSP1 - Log_Message("OP18 X: %d Y: %d Z: %d R: %D DIFF %d", DSP1.Op18X, DSP1.Op18Y, DSP1.Op38Z, DSP1.Op18D); -#endif -} - -static void DSP1_Op38 (void) -{ - DSP1.Op38D = (DSP1.Op38X * DSP1.Op38X + DSP1.Op38Y * DSP1.Op38Y + DSP1.Op38Z * DSP1.Op38Z - DSP1.Op38R * DSP1.Op38R) >> 15; - DSP1.Op38D++; - -#ifdef DebugDSP1 - Log_Message("OP38 X: %d Y: %d Z: %d R: %D DIFF %d", DSP1.Op38X, DSP1.Op38Y, DSP1.Op38Z, DSP1.Op38D); -#endif -} - -static void DSP1_Op28 (void) -{ - int32 Radius = DSP1.Op28X * DSP1.Op28X + DSP1.Op28Y * DSP1.Op28Y + DSP1.Op28Z * DSP1.Op28Z; - - if (Radius == 0) - DSP1.Op28R = 0; - else - { - int16 C, E, Pos, Node1, Node2; - - DSP1_NormalizeDouble(Radius, &C, &E); - if (E & 1) - C = C * 0x4000 >> 15; - - Pos = C * 0x0040 >> 15; - - Node1 = DSP1ROM[0x00d5 + Pos]; - Node2 = DSP1ROM[0x00d6 + Pos]; - - DSP1.Op28R = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; - DSP1.Op28R >>= (E >> 1); - } - -#ifdef DebugDSP1 - Log_Message("OP28 X:%d Y:%d Z:%d", DSP1.Op28X, DSP1.Op28Y, DSP1.Op28Z); - Log_Message("OP28 Vector Length %d", DSP1.Op28R); -#endif -} - -static void DSP1_Op1C (void) -{ - // Rotate Around Op1CZ1 - DSP1.Op1CX1 = (DSP1.Op1CYBR * DSP1_Sin(DSP1.Op1CZ) >> 15) + (DSP1.Op1CXBR * DSP1_Cos(DSP1.Op1CZ) >> 15); - DSP1.Op1CY1 = (DSP1.Op1CYBR * DSP1_Cos(DSP1.Op1CZ) >> 15) - (DSP1.Op1CXBR * DSP1_Sin(DSP1.Op1CZ) >> 15); - DSP1.Op1CXBR = DSP1.Op1CX1; - DSP1.Op1CYBR = DSP1.Op1CY1; - - // Rotate Around Op1CY1 - DSP1.Op1CZ1 = (DSP1.Op1CXBR * DSP1_Sin(DSP1.Op1CY) >> 15) + (DSP1.Op1CZBR * DSP1_Cos(DSP1.Op1CY) >> 15); - DSP1.Op1CX1 = (DSP1.Op1CXBR * DSP1_Cos(DSP1.Op1CY) >> 15) - (DSP1.Op1CZBR * DSP1_Sin(DSP1.Op1CY) >> 15); - DSP1.Op1CXAR = DSP1.Op1CX1; - DSP1.Op1CZBR = DSP1.Op1CZ1; - - // Rotate Around Op1CX1 - DSP1.Op1CY1 = (DSP1.Op1CZBR * DSP1_Sin(DSP1.Op1CX) >> 15) + (DSP1.Op1CYBR * DSP1_Cos(DSP1.Op1CX) >> 15); - DSP1.Op1CZ1 = (DSP1.Op1CZBR * DSP1_Cos(DSP1.Op1CX) >> 15) - (DSP1.Op1CYBR * DSP1_Sin(DSP1.Op1CX) >> 15); - DSP1.Op1CYAR = DSP1.Op1CY1; - DSP1.Op1CZAR = DSP1.Op1CZ1; - -#ifdef DebugDSP1 - Log_Message("OP1C Apply Matrix CX:%d CY:%d CZ", DSP1.Op1CXAR, DSP1.Op1CYAR, DSP1.Op1CZAR); -#endif -} - -static void DSP1_Op0F (void) -{ - DSP1.Op0FPass = 0x0000; - -#ifdef DebugDSP1 - Log_Message("OP0F RAM Test Pass:%d", DSP1.Op0FPass); -#endif -} - -static void DSP1_Op2F (void) -{ - DSP1.Op2FSize = 0x100; -} - -void DSP1SetByte (uint8 byte, uint16 address) -{ - if (address < DSP0.boundary) - { - if ((DSP1.command == 0x0A || DSP1.command == 0x1A) && DSP1.out_count != 0) + if (address < DSP1.boundary) + { +// if ((address & 1) == 0) +// { + if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) { DSP1.out_count--; DSP1.out_index++; return; } - else - if (DSP1.waiting4command) + else if (DSP1.waiting4command) { - DSP1.command = byte; - DSP1.in_index = 0; + DSP1.command = byte; + DSP1.in_index = 0; DSP1.waiting4command = FALSE; DSP1.first_parameter = TRUE; - #ifdef DEBUGGER - //printf("OP%02X\n",byte); - #endif - +// printf("Op%02X\n",byte); + // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a switch (byte) { - case 0x00: DSP1.in_count = 2; break; - case 0x30: - case 0x10: DSP1.in_count = 2; break; - case 0x20: DSP1.in_count = 2; break; - case 0x24: - case 0x04: DSP1.in_count = 2; break; - case 0x08: DSP1.in_count = 3; break; - case 0x18: DSP1.in_count = 4; break; - case 0x28: DSP1.in_count = 3; break; - case 0x38: DSP1.in_count = 4; break; - case 0x2c: - case 0x0c: DSP1.in_count = 3; break; - case 0x3c: - case 0x1c: DSP1.in_count = 6; break; - case 0x32: - case 0x22: - case 0x12: - case 0x02: DSP1.in_count = 7; break; - case 0x0a: DSP1.in_count = 1; break; - case 0x3a: - case 0x2a: - case 0x1a: - DSP1.command = 0x1a; - DSP1.in_count = 1; - break; - case 0x16: - case 0x26: - case 0x36: - case 0x06: DSP1.in_count = 3; break; - case 0x1e: - case 0x2e: - case 0x3e: - case 0x0e: DSP1.in_count = 2; break; - case 0x05: - case 0x35: - case 0x31: - case 0x01: DSP1.in_count = 4; break; - case 0x15: - case 0x11: DSP1.in_count = 4; break; - case 0x25: - case 0x21: DSP1.in_count = 4; break; - case 0x09: - case 0x39: - case 0x3d: - case 0x0d: DSP1.in_count = 3; break; - case 0x19: - case 0x1d: DSP1.in_count = 3; break; - case 0x29: - case 0x2d: DSP1.in_count = 3; break; - case 0x33: - case 0x03: DSP1.in_count = 3; break; - case 0x13: DSP1.in_count = 3; break; - case 0x23: DSP1.in_count = 3; break; - case 0x3b: - case 0x0b: DSP1.in_count = 3; break; - case 0x1b: DSP1.in_count = 3; break; - case 0x2b: DSP1.in_count = 3; break; - case 0x34: - case 0x14: DSP1.in_count = 6; break; - case 0x07: - case 0x0f: DSP1.in_count = 1; break; - case 0x27: - case 0x2F: DSP1.in_count = 1; break; - case 0x17: - case 0x37: - case 0x3F: - DSP1.command = 0x1f; - case 0x1f: DSP1.in_count = 1; break; - default: - #ifdef DEBUGGER - //printf("OP%02X\n", byte); - #endif - case 0x80: - DSP1.in_count = 0; - DSP1.waiting4command = TRUE; - DSP1.first_parameter = TRUE; - break; + case 0x00: DSP1.in_count = 2; break; + case 0x30: + case 0x10: DSP1.in_count = 2; break; + case 0x20: DSP1.in_count = 2; break; + case 0x24: + case 0x04: DSP1.in_count = 2; break; + case 0x08: DSP1.in_count = 3; break; + case 0x18: DSP1.in_count = 4; break; + case 0x28: DSP1.in_count = 3; break; + case 0x38: DSP1.in_count = 4; break; + case 0x2c: + case 0x0c: DSP1.in_count = 3; break; + case 0x3c: + case 0x1c: DSP1.in_count = 6; break; + case 0x32: + case 0x22: + case 0x12: + case 0x02: DSP1.in_count = 7; break; + case 0x0a: DSP1.in_count = 1; break; + case 0x3a: + case 0x2a: + case 0x1a: + DSP1. command =0x1a; + DSP1.in_count = 1; break; + case 0x16: + case 0x26: + case 0x36: + case 0x06: DSP1.in_count = 3; break; + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: DSP1.in_count = 2; break; + case 0x05: + case 0x35: + case 0x31: + case 0x01: DSP1.in_count = 4; break; + case 0x15: + case 0x11: DSP1.in_count = 4; break; + case 0x25: + case 0x21: DSP1.in_count = 4; break; + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: DSP1.in_count = 3; break; + case 0x19: + case 0x1d: DSP1.in_count = 3; break; + case 0x29: + case 0x2d: DSP1.in_count = 3; break; + case 0x33: + case 0x03: DSP1.in_count = 3; break; + case 0x13: DSP1.in_count = 3; break; + case 0x23: DSP1.in_count = 3; break; + case 0x3b: + case 0x0b: DSP1.in_count = 3; break; + case 0x1b: DSP1.in_count = 3; break; + case 0x2b: DSP1.in_count = 3; break; + case 0x34: + case 0x14: DSP1.in_count = 6; break; + case 0x07: + case 0x0f: DSP1.in_count = 1; break; + case 0x27: + case 0x2F: DSP1.in_count=1; break; + case 0x17: + case 0x37: + case 0x3F: + DSP1.command=0x1f; + case 0x1f: DSP1.in_count = 1; break; + // case 0x80: DSP1.in_count = 2; break; + default: + //printf("Op%02X\n",byte); + case 0x80: + DSP1.in_count = 0; + DSP1.waiting4command = TRUE; + DSP1.first_parameter = TRUE; + break; } - - DSP1.in_count <<= 1; + DSP1.in_count<<=1; } else { - DSP1.parameters[DSP1.in_index] = byte; + DSP1.parameters [DSP1.in_index] = byte; DSP1.first_parameter = FALSE; DSP1.in_index++; } - if (DSP1.waiting4command || (DSP1.first_parameter && byte == 0x80)) + if (DSP1.waiting4command || + (DSP1.first_parameter && byte == 0x80)) { DSP1.waiting4command = TRUE; DSP1.first_parameter = FALSE; } - else - if (DSP1.first_parameter && (DSP1.in_count != 0 || (DSP1.in_count == 0 && DSP1.in_index == 0))) - ; + else if(DSP1.first_parameter && (DSP1.in_count != 0 || (DSP1.in_count==0&&DSP1.in_index==0))) + { + } +// else if (DSP1.first_parameter) +// { +// } else { if (DSP1.in_count) { + //DSP1.parameters [DSP1.in_index] |= (byte << 8); if (--DSP1.in_count == 0) { // Actually execute the command DSP1.waiting4command = TRUE; - DSP1.out_index = 0; - + DSP1.out_index = 0; switch (DSP1.command) { - case 0x1f: - DSP1.out_count = 2048; - break; + case 0x1f: + DSP1.out_count=2048; + break; + case 0x00: // Multiple + Op00Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op00Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - case 0x00: // Multiple - DSP1.Op00Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op00Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - - DSP1_Op00(); - - DSP1.out_count = 2; - DSP1.output[0] = DSP1.Op00Result & 0xFF; - DSP1.output[1] = (DSP1.Op00Result >> 8) & 0xFF; - break; - - case 0x20: // Multiple - DSP1.Op20Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op20Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - - DSP1_Op20(); - - DSP1.out_count = 2; - DSP1.output[0] = DSP1.Op20Result & 0xFF; - DSP1.output[1] = (DSP1.Op20Result >> 8) & 0xFF; - break; - - case 0x30: - case 0x10: // Inverse - DSP1.Op10Coefficient = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op10Exponent = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - - DSP1_Op10(); - - DSP1.out_count = 4; - DSP1.output[0] = (uint8) ( ((int16) DSP1.Op10CoefficientR) & 0xFF); - DSP1.output[1] = (uint8) ((((int16) DSP1.Op10CoefficientR) >> 8) & 0xFF); - DSP1.output[2] = (uint8) ( ((int16) DSP1.Op10ExponentR ) & 0xFF); - DSP1.output[3] = (uint8) ((((int16) DSP1.Op10ExponentR ) >> 8) & 0xFF); - break; - - case 0x24: - case 0x04: // Sin and Cos of angle - DSP1.Op04Angle = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op04Radius = (uint16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - - DSP1_Op04(); - - DSP1.out_count = 4; - DSP1.output[0] = (uint8) (DSP1.Op04Sin & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op04Sin >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op04Cos & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op04Cos >> 8) & 0xFF); - break; - - case 0x08: // Radius - DSP1.Op08X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op08Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op08Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op08(); - - DSP1.out_count = 4; - DSP1.output[0] = (uint8) ( ((int16) DSP1.Op08Ll) & 0xFF); - DSP1.output[1] = (uint8) ((((int16) DSP1.Op08Ll) >> 8) & 0xFF); - DSP1.output[2] = (uint8) ( ((int16) DSP1.Op08Lh) & 0xFF); - DSP1.output[3] = (uint8) ((((int16) DSP1.Op08Lh) >> 8) & 0xFF); - break; - - case 0x18: // Range - - DSP1.Op18X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op18Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op18Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - DSP1.Op18R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); - - DSP1_Op18(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op18D & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op18D >> 8) & 0xFF); - break; - - case 0x38: // Range - - DSP1.Op38X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op38Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op38Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - DSP1.Op38R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); - - DSP1_Op38(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op38D & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op38D >> 8) & 0xFF); - break; - - case 0x28: // Distance (vector length) - DSP1.Op28X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op28Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op28Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op28(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op28R & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op28R >> 8) & 0xFF); - break; - - case 0x2c: - case 0x0c: // Rotate (2D rotate) - DSP1.Op0CA = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op0CX1 = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op0CY1 = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op0C(); - - DSP1.out_count = 4; - DSP1.output[0] = (uint8) (DSP1.Op0CX2 & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op0CX2 >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op0CY2 & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op0CY2 >> 8) & 0xFF); - break; - - case 0x3c: - case 0x1c: // Polar (3D rotate) - DSP1.Op1CZ = (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); - //MK: reversed X and Y on neviksti and John's advice. - DSP1.Op1CY = (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); - DSP1.Op1CX = (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); - DSP1.Op1CXBR = (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); - DSP1.Op1CYBR = (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); - DSP1.Op1CZBR = (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); - - DSP1_Op1C(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op1CXAR & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op1CXAR >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op1CYAR & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op1CYAR >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op1CZAR & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op1CZAR >> 8) & 0xFF); - break; - - case 0x32: - case 0x22: - case 0x12: - case 0x02: // Parameter (Projection) - DSP1.Op02FX = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); - DSP1.Op02FY = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); - DSP1.Op02FZ = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); - DSP1.Op02LFE = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); - DSP1.Op02LES = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); - DSP1.Op02AAS = (uint16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); - DSP1.Op02AZS = (uint16) (DSP1.parameters[12] | (DSP1.parameters[13] << 8)); - - DSP1_Op02(); - - DSP1.out_count = 8; - DSP1.output[0] = (uint8) (DSP1.Op02VOF & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op02VOF >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op02VVA & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op02VVA >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op02CX & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op02CX >> 8) & 0xFF); - DSP1.output[6] = (uint8) (DSP1.Op02CY & 0xFF); - DSP1.output[7] = (uint8) ((DSP1.Op02CY >> 8) & 0xFF); - break; - - case 0x3a: - case 0x2a: - case 0x1a: // Raster mode 7 matrix data - case 0x0a: - DSP1.Op0AVS = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - - DSP1_Op0A(); - - DSP1.out_count = 8; - DSP1.output[0] = (uint8) (DSP1.Op0AA & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op0AA >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op0AB & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op0AB >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op0AC & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op0AC >> 8) & 0xFF); - DSP1.output[6] = (uint8) (DSP1.Op0AD & 0xFF); - DSP1.output[7] = (uint8) ((DSP1.Op0AD >> 8) & 0xFF); - DSP1.in_index = 0; - break; - - case 0x16: - case 0x26: - case 0x36: - case 0x06: // Project object - DSP1.Op06X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op06Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op06Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op06(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op06H & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op06H >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op06V & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op06V >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op06M & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op06M >> 8) & 0xFF); - break; - - case 0x1e: - case 0x2e: - case 0x3e: - case 0x0e: // Target - DSP1.Op0EH = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op0EV = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - - DSP1_Op0E(); - - DSP1.out_count = 4; - DSP1.output[0] = (uint8) (DSP1.Op0EX & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op0EX >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op0EY & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op0EY >> 8) & 0xFF); - break; - - // Extra commands used by Pilot Wings - case 0x05: - case 0x35: - case 0x31: - case 0x01: // Set attitude matrix A - DSP1.Op01m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op01Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op01Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - DSP1.Op01Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); - - DSP1_Op01(); - break; - - case 0x15: - case 0x11: // Set attitude matrix B - DSP1.Op11m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op11Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op11Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - DSP1.Op11Xr = (int16) (DSP1.parameters[7] | (DSP1.parameters[7] << 8)); - - DSP1_Op11(); - break; - - case 0x25: - case 0x21: // Set attitude matrix C - DSP1.Op21m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op21Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op21Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - DSP1.Op21Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); - - DSP1_Op21(); - break; - - case 0x09: - case 0x39: - case 0x3d: - case 0x0d: // Objective matrix A - DSP1.Op0DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op0DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op0DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op0D(); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (DSP1.Op0DF & 0xFF); - DSP1.output [1] = (uint8) ((DSP1.Op0DF >> 8) & 0xFF); - DSP1.output [2] = (uint8) (DSP1.Op0DL & 0xFF); - DSP1.output [3] = (uint8) ((DSP1.Op0DL >> 8) & 0xFF); - DSP1.output [4] = (uint8) (DSP1.Op0DU & 0xFF); - DSP1.output [5] = (uint8) ((DSP1.Op0DU >> 8) & 0xFF); - break; - - case 0x19: - case 0x1d: // Objective matrix B - DSP1.Op1DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op1DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op1DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op1D(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op1DF & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op1DF >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op1DL & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op1DL >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op1DU & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op1DU >> 8) & 0xFF); - break; - - case 0x29: - case 0x2d: // Objective matrix C - DSP1.Op2DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op2DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op2DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op2D(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op2DF & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op2DF >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op2DL & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op2DL >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op2DU & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op2DU >> 8) & 0xFF); - break; - - case 0x33: - case 0x03: // Subjective matrix A - DSP1.Op03F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op03L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op03U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op03(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op03X & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op03X >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op03Y & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op03Y >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op03Z & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op03Z >> 8) & 0xFF); - break; - - case 0x13: // Subjective matrix B - DSP1.Op13F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op13L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op13U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op13(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op13X & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op13X >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op13Y & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op13Y >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op13Z & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op13Z >> 8) & 0xFF); - break; - - case 0x23: // Subjective matrix C - DSP1.Op23F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op23L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op23U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op23(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op23X & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op23X >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op23Y & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op23Y >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op23Z & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op23Z >> 8) & 0xFF); - break; - - case 0x3b: - case 0x0b: - DSP1.Op0BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op0BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op0BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op0B(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op0BS & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op0BS >> 8) & 0xFF); - break; - - case 0x1b: - DSP1.Op1BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op1BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op1BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op1B(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op1BS & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op1BS >> 8) & 0xFF); - break; - - case 0x2b: - DSP1.Op2BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - DSP1.Op2BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); - DSP1.Op2BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); - - DSP1_Op2B(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op2BS & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op2BS >> 8) & 0xFF); - break; - - case 0x34: - case 0x14: - DSP1.Op14Zr = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); - DSP1.Op14Xr = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); - DSP1.Op14Yr = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); - DSP1.Op14U = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); - DSP1.Op14F = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); - DSP1.Op14L = (int16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); - - DSP1_Op14(); - - DSP1.out_count = 6; - DSP1.output[0] = (uint8) (DSP1.Op14Zrr & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op14Zrr >> 8) & 0xFF); - DSP1.output[2] = (uint8) (DSP1.Op14Xrr & 0xFF); - DSP1.output[3] = (uint8) ((DSP1.Op14Xrr >> 8) & 0xFF); - DSP1.output[4] = (uint8) (DSP1.Op14Yrr & 0xFF); - DSP1.output[5] = (uint8) ((DSP1.Op14Yrr >> 8) & 0xFF); - break; - - case 0x27: - case 0x2F: - DSP1.Op2FUnknown = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - - DSP1_Op2F(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op2FSize & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op2FSize >> 8) & 0xFF); - break; - - - case 0x07: - case 0x0F: - DSP1.Op0FRamsize = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); - - DSP1_Op0F(); - - DSP1.out_count = 2; - DSP1.output[0] = (uint8) (DSP1.Op0FPass & 0xFF); - DSP1.output[1] = (uint8) ((DSP1.Op0FPass >> 8) & 0xFF); - break; - - default: - break; + DSPOp00 (); + + DSP1.out_count = 2; + DSP1.output [0] = Op00Result&0xFF; + DSP1.output [1] = (Op00Result>>8)&0xFF; + break; + + case 0x20: // Multiple + Op20Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op20Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp20 (); + + DSP1.out_count = 2; + DSP1.output [0] = Op20Result&0xFF; + DSP1.output [1] = (Op20Result>>8)&0xFF; + break; + + case 0x30: + case 0x10: // Inverse + Op10Coefficient = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op10Exponent = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp10 (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (((int16) Op10CoefficientR)&0xFF); + DSP1.output [1] = (uint8) ((((int16) Op10CoefficientR)>>8)&0xFF); + DSP1.output [2] = (uint8) (((int16) Op10ExponentR)&0xff); + DSP1.output [3] = (uint8) ((((int16) Op10ExponentR)>>8)&0xff); + break; + + case 0x24: + case 0x04: // Sin and Cos of angle + Op04Angle = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op04Radius = (uint16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp04 (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op04Sin&0xFF); + DSP1.output [1] = (uint8) ((Op04Sin>>8)&0xFF); + DSP1.output [2] = (uint8) (Op04Cos&0xFF); + DSP1.output [3] = (uint8) ((Op04Cos>>8)&0xFF); + break; + + case 0x08: // Radius + Op08X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op08Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op08Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp08 (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (((int16) Op08Ll)&0xFF); + DSP1.output [1] = (uint8) ((((int16) Op08Ll)>>8)&0xFF); + DSP1.output [2] = (uint8) (((int16) Op08Lh)&0xFF); + DSP1.output [3] = (uint8) ((((int16) Op08Lh)>>8)&0xFF); + break; + + case 0x18: // Range + + Op18X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op18Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op18Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op18R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp18 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op18D&0xFF); + DSP1.output [1] = (uint8) ((Op18D>>8)&0xFF); + break; + + case 0x38: // Range + + Op38X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op38Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op38Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op38R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp38 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op38D&0xFF); + DSP1.output [1] = (uint8) ((Op38D>>8)&0xFF); + break; + + case 0x28: // Distance (vector length) + Op28X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op28Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op28Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp28 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op28R&0xFF); + DSP1.output [1] = (uint8) ((Op28R>>8)&0xFF); + break; + + case 0x2c: + case 0x0c: // Rotate (2D rotate) + Op0CA = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0CX1 = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0CY1 = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0C (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op0CX2&0xFF); + DSP1.output [1] = (uint8) ((Op0CX2>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0CY2&0xFF); + DSP1.output [3] = (uint8) ((Op0CY2>>8)&0xFF); + break; + + case 0x3c: + case 0x1c: // Polar (3D rotate) + Op1CZ = (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + //MK: reversed X and Y on neviksti and John's advice. + Op1CY = (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1CX = (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op1CXBR = (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op1CYBR = (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op1CZBR = (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + + DSPOp1C (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op1CXAR&0xFF); + DSP1.output [1] = (uint8) ((Op1CXAR>>8)&0xFF); + DSP1.output [2] = (uint8) (Op1CYAR&0xFF); + DSP1.output [3] = (uint8) ((Op1CYAR>>8)&0xFF); + DSP1.output [4] = (uint8) (Op1CZAR&0xFF); + DSP1.output [5] = (uint8) ((Op1CZAR>>8)&0xFF); + break; + + case 0x32: + case 0x22: + case 0x12: + case 0x02: // Parameter (Projection) + Op02FX = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op02FY = (short)(DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op02FZ = (short)(DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op02LFE = (short)(DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op02LES = (short)(DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op02AAS = (unsigned short)(DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + Op02AZS = (unsigned short)(DSP1.parameters [12]|(DSP1.parameters[13]<<8)); + + DSPOp02 (); + + DSP1.out_count = 8; + DSP1.output [0] = (uint8) (Op02VOF&0xFF); + DSP1.output [1] = (uint8) ((Op02VOF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op02VVA&0xFF); + DSP1.output [3] = (uint8) ((Op02VVA>>8)&0xFF); + DSP1.output [4] = (uint8) (Op02CX&0xFF); + DSP1.output [5] = (uint8) ((Op02CX>>8)&0xFF); + DSP1.output [6] = (uint8) (Op02CY&0xFF); + DSP1.output [7] = (uint8) ((Op02CY>>8)&0xFF); + break; + + case 0x3a: //1a Mirror + case 0x2a: //1a Mirror + case 0x1a: // Raster mode 7 matrix data + case 0x0a: + Op0AVS = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp0A (); + + DSP1.out_count = 8; + DSP1.output [0] = (uint8) (Op0AA&0xFF); + DSP1.output [2] = (uint8) (Op0AB&0xFF); + DSP1.output [4] = (uint8) (Op0AC&0xFF); + DSP1.output [6] = (uint8) (Op0AD&0xFF); + DSP1.output [1] = (uint8) ((Op0AA>>8)&0xFF); + DSP1.output [3] = (uint8) ((Op0AB>>8)&0xFF); + DSP1.output [5] = (uint8) ((Op0AC>>8)&0xFF); + DSP1.output [7] = (uint8) ((Op0AD>>8)&0xFF); + DSP1.in_index=0; + break; + + case 0x16: + case 0x26: + case 0x36: + case 0x06: // Project object + Op06X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op06Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op06Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp06 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op06H&0xff); + DSP1.output [1] = (uint8) ((Op06H>>8)&0xFF); + DSP1.output [2] = (uint8) (Op06V&0xFF); + DSP1.output [3] = (uint8) ((Op06V>>8)&0xFF); + DSP1.output [4] = (uint8) (Op06M&0xFF); + DSP1.output [5] = (uint8) ((Op06M>>8)&0xFF); + break; + + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: // Target + Op0EH = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0EV = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp0E (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op0EX&0xFF); + DSP1.output [1] = (uint8) ((Op0EX>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0EY&0xFF); + DSP1.output [3] = (uint8) ((Op0EY>>8)&0xFF); + break; + + // Extra commands used by Pilot Wings + case 0x05: + case 0x35: + case 0x31: + case 0x01: // Set attitude matrix A + Op01m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op01Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op01Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op01Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp01 (); + break; + + case 0x15: + case 0x11: // Set attitude matrix B + Op11m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op11Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op11Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op11Xr = (int16) (DSP1.parameters [7]|(DSP1.parameters[7]<<8)); + + DSPOp11 (); + break; + + case 0x25: + case 0x21: // Set attitude matrix C + Op21m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op21Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op21Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op21Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp21 (); + break; + + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: // Objective matrix A + Op0DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op0DF&0xFF); + DSP1.output [1] = (uint8) ((Op0DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0DL&0xFF); + DSP1.output [3] = (uint8) ((Op0DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op0DU&0xFF); + DSP1.output [5] = (uint8) ((Op0DU>>8)&0xFF); + break; + + case 0x19: + case 0x1d: // Objective matrix B + Op1DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op1DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp1D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op1DF&0xFF); + DSP1.output [1] = (uint8) ((Op1DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op1DL&0xFF); + DSP1.output [3] = (uint8) ((Op1DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op1DU&0xFF); + DSP1.output [5] = (uint8) ((Op1DU>>8)&0xFF); + break; + + case 0x29: + case 0x2d: // Objective matrix C + Op2DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op2DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op2DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp2D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op2DF&0xFF); + DSP1.output [1] = (uint8) ((Op2DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op2DL&0xFF); + DSP1.output [3] = (uint8) ((Op2DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op2DU&0xFF); + DSP1.output [5] = (uint8) ((Op2DU>>8)&0xFF); + break; + + case 0x33: + case 0x03: // Subjective matrix A + Op03F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op03L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op03U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp03 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op03X&0xFF); + DSP1.output [1] = (uint8) ((Op03X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op03Y&0xFF); + DSP1.output [3] = (uint8) ((Op03Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op03Z&0xFF); + DSP1.output [5] = (uint8) ((Op03Z>>8)&0xFF); + break; + + case 0x13: // Subjective matrix B + Op13F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op13L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op13U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp13 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op13X&0xFF); + DSP1.output [1] = (uint8) ((Op13X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op13Y&0xFF); + DSP1.output [3] = (uint8) ((Op13Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op13Z&0xFF); + DSP1.output [5] = (uint8) ((Op13Z>>8)&0xFF); + break; + + case 0x23: // Subjective matrix C + Op23F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op23L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op23U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp23 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op23X&0xFF); + DSP1.output [1] = (uint8) ((Op23X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op23Y&0xFF); + DSP1.output [3] = (uint8) ((Op23Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op23Z&0xFF); + DSP1.output [5] = (uint8) ((Op23Z>>8)&0xFF); + break; + + case 0x3b: + case 0x0b: + Op0BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op0BS&0xFF); + DSP1.output [1] = (uint8) ((Op0BS>>8)&0xFF); + break; + + case 0x1b: + Op1BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op1BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp1B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op1BS&0xFF); + DSP1.output [1] = (uint8) ((Op1BS>>8)&0xFF); + break; + + case 0x2b: + Op2BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op2BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op2BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp2B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op2BS&0xFF); + DSP1.output [1] = (uint8) ((Op2BS>>8)&0xFF); + break; + + case 0x34: + case 0x14: + Op14Zr = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op14Xr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op14Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op14U = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op14F = (int16) (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op14L = (int16) (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + + DSPOp14 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op14Zrr&0xFF); + DSP1.output [1] = (uint8) ((Op14Zrr>>8)&0xFF); + DSP1.output [2] = (uint8) (Op14Xrr&0xFF); + DSP1.output [3] = (uint8) ((Op14Xrr>>8)&0xFF); + DSP1.output [4] = (uint8) (Op14Yrr&0xFF); + DSP1.output [5] = (uint8) ((Op14Yrr>>8)&0xFF); + break; + + case 0x27: + case 0x2F: + Op2FUnknown = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp2F (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8)(Op2FSize&0xFF); + DSP1.output [1] = (uint8)((Op2FSize>>8)&0xFF); + break; + + + case 0x07: + case 0x0F: + Op0FRamsize = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp0F (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8)(Op0FPass&0xFF); + DSP1.output [1] = (uint8)((Op0FPass>>8)&0xFF); + break; + + default: + break; } } } } - } + } } -uint8 DSP1GetByte (uint16 address) +uint8 DSP1GetByte(uint16 address) { - uint8 t; - - if (address < DSP0.boundary) - { + uint8 t; + if (address < DSP1.boundary) + { if (DSP1.out_count) { - t = (uint8) DSP1.output[DSP1.out_index]; - - DSP1.out_index++; - - if (--DSP1.out_count == 0) - { - if (DSP1.command == 0x1a || DSP1.command == 0x0a) + //if ((address & 1) == 0) + t = (uint8) DSP1.output [DSP1.out_index]; + //else + //{ + // t = (uint8) (DSP1.output [DSP1.out_index] >> 8); + DSP1.out_index++; + if (--DSP1.out_count == 0) { - DSP1_Op0A(); - DSP1.out_count = 8; - DSP1.out_index = 0; - DSP1.output[0] = DSP1.Op0AA & 0xFF; - DSP1.output[1] = (DSP1.Op0AA >> 8) & 0xFF; - DSP1.output[2] = DSP1.Op0AB & 0xFF; - DSP1.output[3] = (DSP1.Op0AB >> 8) & 0xFF; - DSP1.output[4] = DSP1.Op0AC & 0xFF; - DSP1.output[5] = (DSP1.Op0AC >> 8) & 0xFF; - DSP1.output[6] = DSP1.Op0AD & 0xFF; - DSP1.output[7] = (DSP1.Op0AD >> 8) & 0xFF; + if (DSP1.command == 0x1a || DSP1.command == 0x0a) + { + DSPOp0A (); + DSP1.out_count = 8; + DSP1.out_index = 0; + DSP1.output [0] = (Op0AA&0xFF); + DSP1.output [1] = (Op0AA>>8)&0xFF; + DSP1.output [2] = (Op0AB&0xFF); + DSP1.output [3] = (Op0AB>>8)&0xFF; + DSP1.output [4] = (Op0AC&0xFF); + DSP1.output [5] = (Op0AC>>8)&0xFF; + DSP1.output [6] = (Op0AD&0xFF); + DSP1.output [7] = (Op0AD>>8)&0xFF; + } + if(DSP1.command==0x1f) + { + if((DSP1.out_index%2)!=0) + { + t=(uint8)DSP1ROM[DSP1.out_index>>1]; + } + else + { + t=DSP1ROM[DSP1.out_index>>1]>>8; + } + } } - - if (DSP1.command == 0x1f) - { - if ((DSP1.out_index % 2) != 0) - t = (uint8) DSP1ROM[DSP1.out_index >> 1]; - else - t = DSP1ROM[DSP1.out_index >> 1] >> 8; - } - } - - DSP1.waiting4command = TRUE; + DSP1.waiting4command = TRUE; + //} } else - t = 0xff; - } - else - t = 0x80; - - return (t); + { + // Top Gear 3000 requires this value.... + // if(4==Settings.DSPVersion) + t = 0xff; + //Ballz3d requires this one: + // else t = 0x00; + } + } + else t = 0x80; + return t; +} + +void DSP2SetByte(uint8 byte, uint16 address) +{ + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP1.waiting4command) + { + DSP1.command = byte; + DSP1.in_index = 0; + DSP1.waiting4command = FALSE; +// DSP1.first_parameter = TRUE; +// printf("Op%02X\n",byte); + switch (byte) + { + case 0x01:DSP1.in_count=32;break; + case 0x03:DSP1.in_count=1;break; + case 0x05:DSP1.in_count=1;break; + case 0x09:DSP1.in_count=4;break; + case 0x06:DSP1.in_count=1;break; + case 0x0D:DSP1.in_count=2;break; + default: + printf("Op%02X\n",byte); + case 0x0f:DSP1.in_count=0;break; + } + } + else + { + DSP1.parameters [DSP1.in_index] = byte; +// DSP1.first_parameter = FALSE; + DSP1.in_index++; + } + + if (DSP1.in_count==DSP1.in_index) + { + //DSP1.parameters [DSP1.in_index] |= (byte << 8); + // Actually execute the command + DSP1.waiting4command = TRUE; + DSP1.out_index = 0; + switch (DSP1.command) + { + case 0x0D: + if(DSP2Op0DHasLen) + { + DSP2Op0DHasLen=false; + DSP1.out_count=DSP2Op0DOutLen; + //execute Op5 + DSP2_Op0D(); + } + else + { + DSP2Op0DInLen=DSP1.parameters[0]; + DSP2Op0DOutLen=DSP1.parameters[1]; + DSP1.in_index=0; + DSP1.in_count=(DSP2Op0DInLen+1)>>1; + DSP2Op0DHasLen=true; + if(byte) + DSP1.waiting4command=false; + } + break; + case 0x06: + if(DSP2Op06HasLen) + { + DSP2Op06HasLen=false; + DSP1.out_count=DSP2Op06Len; + //execute Op5 + DSP2_Op06(); + } + else + { + DSP2Op06Len=DSP1.parameters[0]; + DSP1.in_index=0; + DSP1.in_count=DSP2Op06Len; + DSP2Op06HasLen=true; + if(byte) + DSP1.waiting4command=false; + } + break; + case 0x01: + DSP1.out_count=32; + DSP2_Op01(); + break; + case 0x09: + // Multiply - don't yet know if this is signed or unsigned + DSP2Op09Word1 = DSP1.parameters[0] | (DSP1.parameters[1]<<8); + DSP2Op09Word2 = DSP1.parameters[2] | (DSP1.parameters[3]<<8); + DSP1.out_count=4; +#ifdef FAST_LSB_WORD_ACCESS + *(uint32 *)DSP1.output = DSP2Op09Word1 * DSP2Op09Word2; +#else + uint32 temp; + temp=DSP2Op09Word1 * DSP2Op09Word2; + DSP1.output[0]=temp&0xFF; + DSP1.output[1]=(temp>>8)&0xFF; + DSP1.output[2]=(temp>>16)&0xFF; + DSP1.output[3]=(temp>>24)&0xFF; +#endif + break; + case 0x05: + if(DSP2Op05HasLen) + { + DSP2Op05HasLen=false; + DSP1.out_count=DSP2Op05Len; + //execute Op5 + DSP2_Op05(); + } + else + { + DSP2Op05Len=DSP1.parameters[0]; + DSP1.in_index=0; + DSP1.in_count=2*DSP2Op05Len; + DSP2Op05HasLen=true; + if(byte) + DSP1.waiting4command=false; + } + break; + + case 0x03: + DSP2Op05Transparent= DSP1.parameters[0]; + //DSP2Op03(); + break; + case 0x0f: + default: + break; + } + } + } +} + +uint8 DSP2GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP1.out_count) + { + t = (uint8) DSP1.output [DSP1.out_index]; + DSP1.out_index++; + if(DSP1.out_count==DSP1.out_index) + DSP1.out_count=0; + } + else + { + t = 0xff; + } + } + else t = 0x80; + return t; +} + +bool DSP4_init=FALSE; + +/* +extern uint8 dsp4_byte; +extern uint16 dsp4_address; +void InitDSP4(); +void DSP4_SetByte(); +void DSP4_GetByte(); +*/ + +void DSP4SetByte(uint8 byte, uint16 address) +{ + if (!DSP4_init) + { + InitDSP4(); + DSP4_init=TRUE; + } + if (address < DSP1.boundary) + { + dsp4_byte=byte; + dsp4_address=address; + DSP4_SetByte(); + } +} + +uint8 DSP4GetByte(uint16 address) +{ + if (address < DSP1.boundary) + { + dsp4_address=address; + DSP4_GetByte(); + return dsp4_byte; + } + return 0x80; } diff --git a/source/snes9x/reader.h b/source/snes9x/dsp1.h similarity index 84% rename from source/snes9x/reader.h rename to source/snes9x/dsp1.h index dd8e305..8a1074b 100644 --- a/source/snes9x/reader.h +++ b/source/snes9x/dsp1.h @@ -159,54 +159,64 @@ **********************************************************************************/ -#ifndef _READER_H_ -#define _READER_H_ -class Reader + +#ifndef _DSP1_H_ +#define _DSP1_H_ + +extern void (*SetDSP)(uint8, uint16); +extern uint8 (*GetDSP)(uint16); + +void DSP1SetByte(uint8 byte, uint16 address); +uint8 DSP1GetByte(uint16 address); + +void DSP2SetByte(uint8 byte, uint16 address); +uint8 DSP2GetByte(uint16 address); + +void DSP3SetByte(uint8 byte, uint16 address); +uint8 DSP3GetByte(uint16 address); +void DSP3_Reset(); + +void DSP4SetByte(uint8 byte, uint16 address); +uint8 DSP4GetByte(uint16 address); + +enum { - public: - Reader (void); - virtual ~Reader (void); - virtual int get_char (void) = 0; - virtual char * gets (char *, size_t) = 0; - virtual char * getline (void); // free() when done - virtual std::string getline (bool &); - virtual size_t read (char *, size_t) = 0; + M_DSP1_LOROM_S, + M_DSP1_LOROM_L, + M_DSP1_HIROM, + M_DSP2_LOROM, + M_DSP3_LOROM, + M_DSP4_LOROM }; -class fReader : public Reader -{ - public: - fReader (STREAM); - virtual ~fReader (void); - virtual int get_char (void); - virtual char * gets (char *, size_t); - virtual size_t read (char *, size_t); +struct SDSP1 { + uint8 version; + bool8 waiting4command; + bool8 first_parameter; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters [512]; + uint8 output [512]; - private: - STREAM fp; + uint8 temp_save_data [406]; + uint32 maptype; + uint32 boundary; }; -#ifdef UNZIP_SUPPORT +START_EXTERN_C +void S9xResetDSP1 (); +uint8 S9xGetDSP (uint16 Address); +void S9xSetDSP (uint8 Byte, uint16 Address); +void S9xPreSaveDSP1(); +void S9xPostLoadDSP1(); -#define unz_BUFFSIZ 1024 +extern struct SDSP1 DSP1; -class unzReader : public Reader -{ - public: - unzReader (unzFile &); - virtual ~unzReader (void); - virtual int get_char (void); - virtual char * gets (char *, size_t); - virtual size_t read (char *, size_t); +END_EXTERN_C - private: - unzFile file; - char buffer[unz_BUFFSIZ]; - char *head; - size_t numbytes; -}; - -#endif #endif diff --git a/source/snes9x/dsp1emu.c.inc b/source/snes9x/dsp1emu.c.inc new file mode 100644 index 0000000..cf44240 --- /dev/null +++ b/source/snes9x/dsp1emu.c.inc @@ -0,0 +1,1394 @@ +/* +Copyright (C) 1997-2006 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach ) + +http://www.zsnes.com +http://sourceforge.net/projects/zsnes + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//#define __ZSNES__ + +#if (defined __ZSNES__ && __UNIXSDL__) +#include "../gblhdr.h" +#else + +#include +#include +#include +#endif +//#define DebugDSP1 + +#ifdef DebugDSP1 + +FILE * LogFile = NULL; + +void Log_Message (char *Message, ...) +{ + char Msg[400]; + va_list ap; + + va_start(ap,Message); + vsprintf(Msg,Message,ap ); + va_end(ap); + + strcat(Msg,"\r\n\0"); + fwrite(Msg,strlen(Msg),1,LogFile); + fflush (LogFile); +} + +void Start_Log (void) +{ + char LogFileName[255]; +// [4/15/2001] char *p; + + strcpy(LogFileName,"dsp1emu.log\0"); + + LogFile = fopen(LogFileName,"wb"); +} + +void Stop_Log (void) +{ + if (LogFile) + { + fclose(LogFile); + LogFile = NULL; + } +} + +#endif + +const unsigned short DSP1ROM[1024] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, + 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, + 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, + 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, + 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, + 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, + 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, + 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, + 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, + 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, + 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, + 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, + 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, + 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, + 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, + 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, + 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, + 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, + 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, + 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, + 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, + 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, + 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, + 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, + 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, + 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, + 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, + 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, + 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, + 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, + 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, + 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, + 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, + 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, + 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, + 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, + 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, + 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, + 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, + 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, + 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, + 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, + 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, + 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, + 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, + 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, + 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, + 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, + 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, + 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, + 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, + 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, + 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, + 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, + 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, + 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, + 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, + 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, + 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, + 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, + 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, + 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, + 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, + 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, + 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, + 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, + 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, + 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, + 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, + 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, + 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, + 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, + 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, + 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; + +/***************************************************************************\ +* DSP1 code * +\***************************************************************************/ + +void InitDSP(void) +{ +#ifdef DebugDSP1 + Start_Log(); +#endif +} + +short Op00Multiplicand; +short Op00Multiplier; +short Op00Result; + +void DSPOp00() +{ + Op00Result= Op00Multiplicand * Op00Multiplier >> 15; + + #ifdef DebugDSP1 + Log_Message("OP00 MULT %d*%d/32768=%d",Op00Multiplicand,Op00Multiplier,Op00Result); + #endif +} + +short Op20Multiplicand; +short Op20Multiplier; +short Op20Result; + +void DSPOp20() +{ + Op20Result= Op20Multiplicand * Op20Multiplier >> 15; + Op20Result++; + + #ifdef DebugDSP1 + Log_Message("OP20 MULT %d*%d/32768=%d",Op20Multiplicand,Op20Multiplier,Op20Result); + #endif +} + +signed short Op10Coefficient; +signed short Op10Exponent; +signed short Op10CoefficientR; +signed short Op10ExponentR; + +void DSP1_Inverse(short Coefficient, short Exponent, short *iCoefficient, short *iExponent) +{ + // Step One: Division by Zero + if (Coefficient == 0x0000) + { + *iCoefficient = 0x7fff; + *iExponent = 0x002f; + } + else + { + short Sign = 1; + + // Step Two: Remove Sign + if (Coefficient < 0) + { + if (Coefficient < -32767) Coefficient = -32767; + Coefficient = -Coefficient; + Sign = -1; + } + + // Step Three: Normalize + while (Coefficient < 0x4000) + { + Coefficient <<= 1; + Exponent--; + } + + // Step Four: Special Case + if (Coefficient == 0x4000) + if (Sign == 1) *iCoefficient = 0x7fff; + else { + *iCoefficient = -0x4000; + Exponent--; + } + else { + // Step Five: Initial Guess + short i = DSP1ROM[((Coefficient - 0x4000) >> 7) + 0x0065]; + + // Step Six: Iterate "estimated" Newton's Method + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + + *iCoefficient = i * Sign; + } + + *iExponent = 1 - Exponent; + } +} + +void DSPOp10() +{ + DSP1_Inverse(Op10Coefficient, Op10Exponent, &Op10CoefficientR, &Op10ExponentR); + #ifdef DebugDSP1 + Log_Message("OP10 INV %d*2^%d = %d*2^%d", Op10Coefficient, Op10Exponent, Op10CoefficientR, Op10ExponentR); + #endif +} + +short Op04Angle; +short Op04Radius; +short Op04Sin; +short Op04Cos; + +const short DSP1_MulTable[256] = { + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, + 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, + 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, + 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, + 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, + 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, + 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, + 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, + 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, + 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, + 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, + 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, + 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, + 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, + 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, + 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, + 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, + 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, + 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, + 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, + 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, + 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, + 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, + 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, + 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, + 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, + 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, + 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, + 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, + 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, + 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, + 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; + +const short DSP1_SinTable[256] = { + 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, + 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, + 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, + 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, + 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, + 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, + 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, + -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, + -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, + -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, + -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, + -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, + -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, + -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, + -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, + -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, + -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; + +short DSP1_Sin(short Angle) +{ + int S; + if (Angle < 0) { + if (Angle == -32768) return 0; + return -DSP1_Sin(-Angle); + } + S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15); + if (S > 32767) S = 32767; + return (short) S; +} + +short DSP1_Cos(short Angle) +{ + int S; + if (Angle < 0) { + if (Angle == -32768) return -32768; + Angle = -Angle; + } + S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15); + if (S < -32768) S = -32767; + return (short) S; +} + +void DSP1_Normalize(short m, short *Coefficient, short *Exponent) +{ + short i = 0x4000; + short e = 0; + + if (m < 0) + while ((m & i) && i) { + i >>= 1; + e++; + } + else + while (!(m & i) && i) { + i >>= 1; + e++; + } + + if (e > 0) + *Coefficient = m * DSP1ROM[0x21 + e] << 1; + else + *Coefficient = m; + + *Exponent -= e; +} + +void DSP1_NormalizeDouble(int Product, short *Coefficient, short *Exponent) +{ + short n = Product & 0x7fff; + short m = Product >> 15; + short i = 0x4000; + short e = 0; + + if (m < 0) + while ((m & i) && i) { + i >>= 1; + e++; + } + else + while (!(m & i) && i) { + i >>= 1; + e++; + } + + if (e > 0) + { + *Coefficient = m * DSP1ROM[0x0021 + e] << 1; + + if (e < 15) + *Coefficient += n * DSP1ROM[0x0040 - e] >> 15; + else + { + i = 0x4000; + + if (m < 0) + while ((n & i) && i) { + i >>= 1; + e++; + } + else + while (!(n & i) && i) { + i >>= 1; + e++; + } + + if (e > 15) + *Coefficient = n * DSP1ROM[0x0012 + e] << 1; + else + *Coefficient += n; + } + } + else + *Coefficient = m; + + *Exponent = e; +} + +short DSP1_Truncate(short C, short E) +{ + if (E > 0) { + if (C > 0) return 32767; else if (C < 0) return -32767; + } else { + if (E < 0) return C * DSP1ROM[0x0031 + E] >> 15; + } + return C; +} + +void DSPOp04() +{ + Op04Sin = DSP1_Sin(Op04Angle) * Op04Radius >> 15; + Op04Cos = DSP1_Cos(Op04Angle) * Op04Radius >> 15; +} + +short Op0CA; +short Op0CX1; +short Op0CY1; +short Op0CX2; +short Op0CY2; + +void DSPOp0C() +{ + Op0CX2 = (Op0CY1 * DSP1_Sin(Op0CA) >> 15) + (Op0CX1 * DSP1_Cos(Op0CA) >> 15); + Op0CY2 = (Op0CY1 * DSP1_Cos(Op0CA) >> 15) - (Op0CX1 * DSP1_Sin(Op0CA) >> 15); +} + +short CentreX; +short CentreY; +short VOffset; + +short VPlane_C; +short VPlane_E; + +// Azimuth and Zenith angles +short SinAas; +short CosAas; +short SinAzs; +short CosAzs; + +// Clipped Zenith angle +short SinAZS; +short CosAZS; +short SecAZS_C1; +short SecAZS_E1; +short SecAZS_C2; +short SecAZS_E2; + +short Nx, Ny, Nz; +short Gx, Gy, Gz; +short C_Les, E_Les, G_Les; + +const short MaxAZS_Exp[16] = { + 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, + 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 +}; + +void DSP1_Parameter(short Fx, short Fy, short Fz, short Lfe, short Les, short Aas, short Azs, short *Vof, short *Vva, short *Cx, short *Cy) +{ + short CSec, C, E, MaxAZS, Aux; + short LfeNx, LfeNy, LfeNz; + short LesNx, LesNy, LesNz; + short CentreZ; + + // Copy Zenith angle for clipping + short AZS = Azs; + + // Store Sine and Cosine of Azimuth and Zenith angle + SinAas = DSP1_Sin(Aas); + CosAas = DSP1_Cos(Aas); + SinAzs = DSP1_Sin(Azs); + CosAzs = DSP1_Cos(Azs); + + Nx = SinAzs * -SinAas >> 15; + Ny = SinAzs * CosAas >> 15; + Nz = CosAzs * 0x7fff >> 15; + + LfeNx = Lfe*Nx>>15; + LfeNy = Lfe*Ny>>15; + LfeNz = Lfe*Nz>>15; + + // Center of Projection + CentreX = Fx+LfeNx; + CentreY = Fy+LfeNy; + CentreZ = Fz+LfeNz; + + LesNx = Les*Nx>>15; + LesNy = Les*Ny>>15; + LesNz = Les*Nz>>15; + + Gx=CentreX-LesNx; + Gy=CentreY-LesNy; + Gz=CentreZ-LesNz; + + E_Les=0; + DSP1_Normalize(Les, &C_Les, &E_Les); + G_Les = Les; + + E = 0; + DSP1_Normalize(CentreZ, &C, &E); + + VPlane_C = C; + VPlane_E = E; + + // Determine clip boundary and clip Zenith angle if necessary + MaxAZS = MaxAZS_Exp[-E]; + + if (AZS < 0) { + MaxAZS = -MaxAZS; + if (AZS < MaxAZS + 1) AZS = MaxAZS + 1; + } else { + if (AZS > MaxAZS) AZS = MaxAZS; + } + + // Store Sine and Cosine of clipped Zenith angle + SinAZS = DSP1_Sin(AZS); + CosAZS = DSP1_Cos(AZS); + + DSP1_Inverse(CosAZS, 0, &SecAZS_C1, &SecAZS_E1); + DSP1_Normalize(C * SecAZS_C1 >> 15, &C, &E); + E += SecAZS_E1; + + C = DSP1_Truncate(C, E) * SinAZS >> 15; + + CentreX += C * SinAas >> 15; + CentreY -= C * CosAas >> 15; + + *Cx = CentreX; + *Cy = CentreY; + + // Raster number of imaginary center and horizontal line + *Vof = 0; + + if ((Azs != AZS) || (Azs == MaxAZS)) + { + if (Azs == -32768) Azs = -32767; + + C = Azs - MaxAZS; + if (C >= 0) C--; + Aux = ~(C << 2); + + C = Aux * DSP1ROM[0x0328] >> 15; + C = (C * Aux >> 15) + DSP1ROM[0x0327]; + *Vof -= (C * Aux >> 15) * Les >> 15; + + C = Aux * Aux >> 15; + Aux = (C * DSP1ROM[0x0324] >> 15) + DSP1ROM[0x0325]; + CosAZS += (C * Aux >> 15) * CosAZS >> 15; + } + + VOffset = Les * CosAZS >> 15; + + DSP1_Inverse(SinAZS, 0, &CSec, &E); + DSP1_Normalize(VOffset, &C, &E); + DSP1_Normalize(C * CSec >> 15, &C, &E); + + if (C == -32768) { C >>= 1; E++; } + + *Vva = DSP1_Truncate(-C, E); + + // Store Secant of clipped Zenith angle + DSP1_Inverse(CosAZS, 0, &SecAZS_C2, &SecAZS_E2); +} + +void DSP1_Raster(short Vs, short *An, short *Bn, short *Cn, short *Dn) +{ + short C, E, C1, E1; + + DSP1_Inverse((Vs * SinAzs >> 15) + VOffset, 7, &C, &E); + E += VPlane_E; + + C1 = C * VPlane_C >> 15; + E1 = E + SecAZS_E2; + + DSP1_Normalize(C1, &C, &E); + + C = DSP1_Truncate(C, E); + + *An = C * CosAas >> 15; + *Cn = C * SinAas >> 15; + + DSP1_Normalize(C1 * SecAZS_C2 >> 15, &C, &E1); + + C = DSP1_Truncate(C, E1); + + *Bn = C * -SinAas >> 15; + *Dn = C * CosAas >> 15; +} + +short Op02FX; +short Op02FY; +short Op02FZ; +short Op02LFE; +short Op02LES; +short Op02AAS; +short Op02AZS; +short Op02VOF; +short Op02VVA; +short Op02CX; +short Op02CY; + +void DSPOp02() +{ + DSP1_Parameter(Op02FX, Op02FY, Op02FZ, Op02LFE, Op02LES, Op02AAS, Op02AZS, &Op02VOF, &Op02VVA, &Op02CX, &Op02CY); +} + +short Op0AVS; +short Op0AA; +short Op0AB; +short Op0AC; +short Op0AD; + +void DSPOp0A() +{ + DSP1_Raster(Op0AVS, &Op0AA, &Op0AB, &Op0AC, &Op0AD); + Op0AVS++; +} + + +short DSP1_ShiftR(short C, short E) +{ + return (C * DSP1ROM[0x0031 + E] >> 15); +} + +void DSP1_Project(short X, short Y, short Z, short *H, short *V, short *M) +{ + int aux, aux4; + short E, E2, E3, E4, E5, refE, E6, E7; + short C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; + short Px, Py, Pz; + + E4=E3=E2=E=E5=0; + + DSP1_NormalizeDouble((int)X-Gx, &Px, &E4); + DSP1_NormalizeDouble((int)Y-Gy, &Py, &E); + DSP1_NormalizeDouble((int)Z-Gz, &Pz, &E3); + Px>>=1; E4--; // to avoid overflows when calculating the scalar products + Py>>=1; E--; + Pz>>=1; E3--; + + refE = (E>15); + C8=- (Py*Ny>>15); + C9=- (Pz*Nz>>15); + C12=C11+C8+C9; // this cannot overflow! + + aux4=C12; // de-normalization with 32-bits arithmetic + refE = 16-refE; // refE can be up to 3 + if (refE>=0) + aux4 <<=(refE); + else + aux4 >>=-(refE); + if (aux4==-1) aux4 = 0; // why? + aux4>>=1; + + aux = ((unsigned short)G_Les) + aux4; // Les - the scalar product of P with the normal vector of the screen + DSP1_NormalizeDouble(aux, &C10, &E2); + E2 = 15-E2; + + DSP1_Inverse(C10, 0, &C4, &E4); + C2=C4*C_Les>>15; // scale factor + + + // H + E7=0; + C16= (Px*(CosAas*0x7fff>>15)>>15); + C20= (Py*(SinAas*0x7fff>>15)>>15); + C17=C16+C20; // scalar product of P with the normalized horizontal vector of the screen... + + C18=C17*C2>>15; // ... multiplied by the scale factor + DSP1_Normalize(C18, &C19, &E7); + *H=DSP1_Truncate(C19, E_Les-E2+refE+E7); + + // V + E6=0; + C21 = Px*(CosAzs*-SinAas>>15)>>15; + C22 = Py*(CosAzs*CosAas>>15)>>15; + C23 = Pz*(-SinAzs*0x7fff>>15)>>15; + C24=C21+C22+C23; // scalar product of P with the normalized vertical vector of the screen... + + C26=C24*C2>>15; // ... multiplied by the scale factor + DSP1_Normalize(C26, &C25, &E6); + *V=DSP1_Truncate(C25, E_Les-E2+refE+E6); + + // M + DSP1_Normalize(C2, &C6, &E4); + *M=DSP1_Truncate(C6, E4+E_Les-E2-7); // M is the scale factor divided by 2^7 +} + +short Op06X; +short Op06Y; +short Op06Z; +short Op06H; +short Op06V; +short Op06M; + +void DSPOp06() +{ + DSP1_Project(Op06X, Op06Y, Op06Z, &Op06H, &Op06V, &Op06M); +} + + +short matrixC[3][3]; +short matrixB[3][3]; +short matrixA[3][3]; + +short Op01m; +short Op01Zr; +short Op01Xr; +short Op01Yr; +short Op11m; +short Op11Zr; +short Op11Xr; +short Op11Yr; +short Op21m; +short Op21Zr; +short Op21Xr; +short Op21Yr; + +void DSPOp01() +{ + short SinAz = DSP1_Sin(Op01Zr); + short CosAz = DSP1_Cos(Op01Zr); + short SinAy = DSP1_Sin(Op01Yr); + short CosAy = DSP1_Cos(Op01Yr); + short SinAx = DSP1_Sin(Op01Xr); + short CosAx = DSP1_Cos(Op01Xr); + + Op01m >>= 1; + + matrixA[0][0] = (Op01m * CosAz >> 15) * CosAy >> 15; + matrixA[0][1] = -((Op01m * SinAz >> 15) * CosAy >> 15); + matrixA[0][2] = Op01m * SinAy >> 15; + + matrixA[1][0] = ((Op01m * SinAz >> 15) * CosAx >> 15) + (((Op01m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + matrixA[1][1] = ((Op01m * CosAz >> 15) * CosAx >> 15) - (((Op01m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + matrixA[1][2] = -((Op01m * SinAx >> 15) * CosAy >> 15); + + matrixA[2][0] = ((Op01m * SinAz >> 15) * SinAx >> 15) - (((Op01m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + matrixA[2][1] = ((Op01m * CosAz >> 15) * SinAx >> 15) + (((Op01m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + matrixA[2][2] = (Op01m * CosAx >> 15) * CosAy >> 15; +} + +void DSPOp11() +{ + short SinAz = DSP1_Sin(Op11Zr); + short CosAz = DSP1_Cos(Op11Zr); + short SinAy = DSP1_Sin(Op11Yr); + short CosAy = DSP1_Cos(Op11Yr); + short SinAx = DSP1_Sin(Op11Xr); + short CosAx = DSP1_Cos(Op11Xr); + + Op11m >>= 1; + + matrixB[0][0] = (Op11m * CosAz >> 15) * CosAy >> 15; + matrixB[0][1] = -((Op11m * SinAz >> 15) * CosAy >> 15); + matrixB[0][2] = Op11m * SinAy >> 15; + + matrixB[1][0] = ((Op11m * SinAz >> 15) * CosAx >> 15) + (((Op11m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + matrixB[1][1] = ((Op11m * CosAz >> 15) * CosAx >> 15) - (((Op11m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + matrixB[1][2] = -((Op11m * SinAx >> 15) * CosAy >> 15); + + matrixB[2][0] = ((Op11m * SinAz >> 15) * SinAx >> 15) - (((Op11m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + matrixB[2][1] = ((Op11m * CosAz >> 15) * SinAx >> 15) + (((Op11m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + matrixB[2][2] = (Op11m * CosAx >> 15) * CosAy >> 15; +} + +void DSPOp21() +{ + short SinAz = DSP1_Sin(Op21Zr); + short CosAz = DSP1_Cos(Op21Zr); + short SinAy = DSP1_Sin(Op21Yr); + short CosAy = DSP1_Cos(Op21Yr); + short SinAx = DSP1_Sin(Op21Xr); + short CosAx = DSP1_Cos(Op21Xr); + + Op21m >>= 1; + + matrixC[0][0] = (Op21m * CosAz >> 15) * CosAy >> 15; + matrixC[0][1] = -((Op21m * SinAz >> 15) * CosAy >> 15); + matrixC[0][2] = Op21m * SinAy >> 15; + + matrixC[1][0] = ((Op21m * SinAz >> 15) * CosAx >> 15) + (((Op21m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + matrixC[1][1] = ((Op21m * CosAz >> 15) * CosAx >> 15) - (((Op21m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + matrixC[1][2] = -((Op21m * SinAx >> 15) * CosAy >> 15); + + matrixC[2][0] = ((Op21m * SinAz >> 15) * SinAx >> 15) - (((Op21m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + matrixC[2][1] = ((Op21m * CosAz >> 15) * SinAx >> 15) + (((Op21m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + matrixC[2][2] = (Op21m * CosAx >> 15) * CosAy >> 15; +} + +short Op0DX; +short Op0DY; +short Op0DZ; +short Op0DF; +short Op0DL; +short Op0DU; +short Op1DX; +short Op1DY; +short Op1DZ; +short Op1DF; +short Op1DL; +short Op1DU; +short Op2DX; +short Op2DY; +short Op2DZ; +short Op2DF; +short Op2DL; +short Op2DU; + +void DSPOp0D() +{ + Op0DF = (Op0DX * matrixA[0][0] >> 15) + (Op0DY * matrixA[0][1] >> 15) + (Op0DZ * matrixA[0][2] >> 15); + Op0DL = (Op0DX * matrixA[1][0] >> 15) + (Op0DY * matrixA[1][1] >> 15) + (Op0DZ * matrixA[1][2] >> 15); + Op0DU = (Op0DX * matrixA[2][0] >> 15) + (Op0DY * matrixA[2][1] >> 15) + (Op0DZ * matrixA[2][2] >> 15); + + #ifdef DebugDSP1 + Log_Message("OP0D X: %d Y: %d Z: %d / F: %d L: %d U: %d",Op0DX,Op0DY,Op0DZ,Op0DF,Op0DL,Op0DU); + #endif +} + +void DSPOp1D() +{ + Op1DF = (Op1DX * matrixB[0][0] >> 15) + (Op1DY * matrixB[0][1] >> 15) + (Op1DZ * matrixB[0][2] >> 15); + Op1DL = (Op1DX * matrixB[1][0] >> 15) + (Op1DY * matrixB[1][1] >> 15) + (Op1DZ * matrixB[1][2] >> 15); + Op1DU = (Op1DX * matrixB[2][0] >> 15) + (Op1DY * matrixB[2][1] >> 15) + (Op1DZ * matrixB[2][2] >> 15); + + #ifdef DebugDSP1 + Log_Message("OP1D X: %d Y: %d Z: %d / F: %d L: %d U: %d",Op1DX,Op1DY,Op1DZ,Op1DF,Op1DL,Op1DU); + #endif +} + +void DSPOp2D() +{ + Op2DF = (Op2DX * matrixC[0][0] >> 15) + (Op2DY * matrixC[0][1] >> 15) + (Op2DZ * matrixC[0][2] >> 15); + Op2DL = (Op2DX * matrixC[1][0] >> 15) + (Op2DY * matrixC[1][1] >> 15) + (Op2DZ * matrixC[1][2] >> 15); + Op2DU = (Op2DX * matrixC[2][0] >> 15) + (Op2DY * matrixC[2][1] >> 15) + (Op2DZ * matrixC[2][2] >> 15); + + #ifdef DebugDSP1 + Log_Message("OP2D X: %d Y: %d Z: %d / F: %d L: %d U: %d",Op2DX,Op2DY,Op2DZ,Op2DF,Op2DL,Op2DU); + #endif +} + +short Op03F; +short Op03L; +short Op03U; +short Op03X; +short Op03Y; +short Op03Z; +short Op13F; +short Op13L; +short Op13U; +short Op13X; +short Op13Y; +short Op13Z; +short Op23F; +short Op23L; +short Op23U; +short Op23X; +short Op23Y; +short Op23Z; + +void DSPOp03() +{ + Op03X = (Op03F * matrixA[0][0] >> 15) + (Op03L * matrixA[1][0] >> 15) + (Op03U * matrixA[2][0] >> 15); + Op03Y = (Op03F * matrixA[0][1] >> 15) + (Op03L * matrixA[1][1] >> 15) + (Op03U * matrixA[2][1] >> 15); + Op03Z = (Op03F * matrixA[0][2] >> 15) + (Op03L * matrixA[1][2] >> 15) + (Op03U * matrixA[2][2] >> 15); + + #ifdef DebugDSP1 + Log_Message("OP03 F: %d L: %d U: %d / X: %d Y: %d Z: %d",Op03F,Op03L,Op03U,Op03X,Op03Y,Op03Z); + #endif +} + +void DSPOp13() +{ + Op13X = (Op13F * matrixB[0][0] >> 15) + (Op13L * matrixB[1][0] >> 15) + (Op13U * matrixB[2][0] >> 15); + Op13Y = (Op13F * matrixB[0][1] >> 15) + (Op13L * matrixB[1][1] >> 15) + (Op13U * matrixB[2][1] >> 15); + Op13Z = (Op13F * matrixB[0][2] >> 15) + (Op13L * matrixB[1][2] >> 15) + (Op13U * matrixB[2][2] >> 15); + + #ifdef DebugDSP1 + Log_Message("OP13 F: %d L: %d U: %d / X: %d Y: %d Z: %d",Op13F,Op13L,Op13U,Op13X,Op13Y,Op13Z); + #endif +} + +void DSPOp23() +{ + Op23X = (Op23F * matrixC[0][0] >> 15) + (Op23L * matrixC[1][0] >> 15) + (Op23U * matrixC[2][0] >> 15); + Op23Y = (Op23F * matrixC[0][1] >> 15) + (Op23L * matrixC[1][1] >> 15) + (Op23U * matrixC[2][1] >> 15); + Op23Z = (Op23F * matrixC[0][2] >> 15) + (Op23L * matrixC[1][2] >> 15) + (Op23U * matrixC[2][2] >> 15); + + #ifdef DebugDSP1 + Log_Message("OP23 F: %d L: %d U: %d / X: %d Y: %d Z: %d",Op23F,Op23L,Op23U,Op23X,Op23Y,Op23Z); + #endif +} + +short Op14Zr; +short Op14Xr; +short Op14Yr; +short Op14U; +short Op14F; +short Op14L; +short Op14Zrr; +short Op14Xrr; +short Op14Yrr; + +void DSPOp14() +{ + short CSec, ESec, CTan, CSin, C, E; + + DSP1_Inverse(DSP1_Cos(Op14Xr), 0, &CSec, &ESec); + + // Rotation Around Z + DSP1_NormalizeDouble(Op14U * DSP1_Cos(Op14Yr) - Op14F * DSP1_Sin(Op14Yr), &C, &E); + + E = ESec - E; + + DSP1_Normalize(C * CSec >> 15, &C, &E); + + Op14Zrr = Op14Zr + DSP1_Truncate(C, E); + + // Rotation Around X + Op14Xrr = Op14Xr + (Op14U * DSP1_Sin(Op14Yr) >> 15) + (Op14F * DSP1_Cos(Op14Yr) >> 15); + + // Rotation Around Y + DSP1_NormalizeDouble(Op14U * DSP1_Cos(Op14Yr) + Op14F * DSP1_Sin(Op14Yr), &C, &E); + + E = ESec - E; + + DSP1_Normalize(DSP1_Sin(Op14Xr), &CSin, &E); + + CTan = CSec * CSin >> 15; + + DSP1_Normalize(-(C * CTan >> 15), &C, &E); + + Op14Yrr = Op14Yr + DSP1_Truncate(C, E) + Op14L; +} + +void DSP1_Target(short H, short V, short *X, short *Y) +{ + short C, E, C1, E1; + + DSP1_Inverse((V * SinAzs >> 15) + VOffset, 8, &C, &E); + E += VPlane_E; + + C1 = C * VPlane_C >> 15; + E1 = E + SecAZS_E1; + + H <<= 8; + + DSP1_Normalize(C1, &C, &E); + + C = DSP1_Truncate(C, E) * H >> 15; + + *X = CentreX + (C * CosAas >> 15); + *Y = CentreY - (C * SinAas >> 15); + + V <<= 8; + + DSP1_Normalize(C1 * SecAZS_C1 >> 15, &C, &E1); + + C = DSP1_Truncate(C, E1) * V >> 15; + + *X += C * -SinAas >> 15; + *Y += C * CosAas >> 15; +} + +short Op0EH; +short Op0EV; +short Op0EX; +short Op0EY; + +void DSPOp0E() +{ + DSP1_Target(Op0EH, Op0EV, &Op0EX, &Op0EY); +} + +short Op0BX; +short Op0BY; +short Op0BZ; +short Op0BS; +short Op1BX; +short Op1BY; +short Op1BZ; +short Op1BS; +short Op2BX; +short Op2BY; +short Op2BZ; +short Op2BS; + +void DSPOp0B() +{ + Op0BS = (Op0BX * matrixA[0][0] + Op0BY * matrixA[0][1] + Op0BZ * matrixA[0][2]) >> 15; + + #ifdef DebugDSP1 + Log_Message("OP0B"); + #endif +} + +void DSPOp1B() +{ + Op1BS = (Op1BX * matrixB[0][0] + Op1BY * matrixB[0][1] + Op1BZ * matrixB[0][2]) >> 15; + + #ifdef DebugDSP1 + Log_Message("OP1B X: %d Y: %d Z: %d S: %d",Op1BX,Op1BY,Op1BZ,Op1BS); + Log_Message(" MX: %d MY: %d MZ: %d Scale: %d",(short)(matrixB[0][0]*100),(short)(matrixB[0][1]*100),(short)(matrixB[0][2]*100),(short)(sc2*100)); + #endif +} + +void DSPOp2B() +{ + Op2BS = (Op2BX * matrixC[0][0] + Op2BY * matrixC[0][1] + Op2BZ * matrixC[0][2]) >> 15; + + #ifdef DebugDSP1 + Log_Message("OP2B"); + #endif +} + +short Op08X,Op08Y,Op08Z,Op08Ll,Op08Lh; + +void DSPOp08() +{ + int Op08Size = (Op08X * Op08X + Op08Y * Op08Y + Op08Z * Op08Z) << 1; + Op08Ll = Op08Size & 0xffff; + Op08Lh = (Op08Size >> 16) & 0xffff; + + #ifdef DebugDSP1 + Log_Message("OP08 %d,%d,%d",Op08X,Op08Y,Op08Z); + Log_Message("OP08 ((Op08X^2)+(Op08Y^2)+(Op08X^2))=%x",Op08Size ); + #endif +} + +short Op18X,Op18Y,Op18Z,Op18R,Op18D; + +void DSPOp18() +{ + Op18D = (Op18X * Op18X + Op18Y * Op18Y + Op18Z * Op18Z - Op18R * Op18R) >> 15; + + #ifdef DebugDSP1 + Log_Message("Op18 X: %d Y: %d Z: %d R: %D DIFF %d",Op18X,Op18Y,Op38Z,Op18D); + #endif +} + +short Op38X,Op38Y,Op38Z,Op38R,Op38D; + +void DSPOp38() +{ + Op38D = (Op38X * Op38X + Op38Y * Op38Y + Op38Z * Op38Z - Op38R * Op38R) >> 15; + Op38D++; + + #ifdef DebugDSP1 + Log_Message("OP38 X: %d Y: %d Z: %d R: %D DIFF %d",Op38X,Op38Y,Op38Z,Op38D); + #endif +} + +short Op28X; +short Op28Y; +short Op28Z; +short Op28R; + +void DSPOp28() +{ + int Radius = Op28X * Op28X + Op28Y * Op28Y + Op28Z * Op28Z; + + if (Radius == 0) Op28R = 0; + else + { + short C, E, Pos, Node1, Node2; + DSP1_NormalizeDouble(Radius, &C, &E); + if (E & 1) C = C * 0x4000 >> 15; + + Pos = C * 0x0040 >> 15; + + Node1 = DSP1ROM[0x00d5 + Pos]; + Node2 = DSP1ROM[0x00d6 + Pos]; + + Op28R = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; + Op28R >>= (E >> 1); + } + + #ifdef DebugDSP1 + Log_Message("OP28 X:%d Y:%d Z:%d",Op28X,Op28Y,Op28Z); + Log_Message("OP28 Vector Length %d",Op28R); + #endif +} + +short Op1CX,Op1CY,Op1CZ; +short Op1CXBR,Op1CYBR,Op1CZBR,Op1CXAR,Op1CYAR,Op1CZAR; +short Op1CX1; +short Op1CY1; +short Op1CZ1; +short Op1CX2; +short Op1CY2; +short Op1CZ2; + +void DSPOp1C() +{ + // Rotate Around Op1CZ1 + Op1CX1 = (Op1CYBR * DSP1_Sin(Op1CZ) >> 15) + (Op1CXBR * DSP1_Cos(Op1CZ) >> 15); + Op1CY1 = (Op1CYBR * DSP1_Cos(Op1CZ) >> 15) - (Op1CXBR * DSP1_Sin(Op1CZ) >> 15); + Op1CXBR = Op1CX1; Op1CYBR = Op1CY1; + + // Rotate Around Op1CY1 + Op1CZ1 = (Op1CXBR * DSP1_Sin(Op1CY) >> 15) + (Op1CZBR * DSP1_Cos(Op1CY) >> 15); + Op1CX1 = (Op1CXBR * DSP1_Cos(Op1CY) >> 15) - (Op1CZBR * DSP1_Sin(Op1CY) >> 15); + Op1CXAR = Op1CX1; Op1CZBR = Op1CZ1; + + // Rotate Around Op1CX1 + Op1CY1 = (Op1CZBR * DSP1_Sin(Op1CX) >> 15) + (Op1CYBR * DSP1_Cos(Op1CX) >> 15); + Op1CZ1 = (Op1CZBR * DSP1_Cos(Op1CX) >> 15) - (Op1CYBR * DSP1_Sin(Op1CX) >> 15); + Op1CYAR = Op1CY1; Op1CZAR = Op1CZ1; + + #ifdef DebugDSP1 + Log_Message("OP1C Apply Matrix CX:%d CY:%d CZ",Op1CXAR,Op1CYAR,Op1CZAR); + #endif +} + +unsigned short Op0FRamsize; +unsigned short Op0FPass; + +void DSPOp0F() +{ + Op0FPass = 0x0000; + + #ifdef DebugDSP1 + Log_Message("OP0F RAM Test Pass:%d", Op0FPass); + #endif +} + +short Op2FUnknown; +short Op2FSize; + +void DSPOp2F() +{ + Op2FSize=0x100; +} + + + +// FIXME: many of these are unnecessary to save. But some of them are necessary, like Matrix* and maybe VPlane_* +// TODO: move the necessary ones into a global structure so it's not as ugly to save +#define SAVE_OR_LOAD_THE_VARIABLES() \ +S(Op00Multiplicand); \ +S(Op00Multiplier); \ +S(Op00Result); \ +S(Op20Multiplicand); \ +S(Op20Multiplier); \ +S(Op20Result); \ +S(Op10Coefficient); \ +S(Op10Exponent); \ +S(Op10CoefficientR); \ +S(Op10ExponentR); \ +S(Op04Angle); \ +S(Op04Radius); \ +S(Op04Sin); \ +S(Op04Cos); \ +S(Op0CA); \ +S(Op0CX1); \ +S(Op0CY1); \ +S(Op0CX2); \ +S(Op0CY2); \ +S(CentreX); \ +S(CentreY); \ +S(VOffset); \ +S(VPlane_C); \ +S(VPlane_E); \ +S(SinAas); \ +S(CosAas); \ +S(SinAzs); \ +S(CosAzs); \ +S(SinAZS); \ +S(CosAZS); \ +S(SecAZS_C1); \ +S(SecAZS_E1); \ +S(SecAZS_C2); \ +S(SecAZS_E2); \ +S(Nx); S(Ny); S(Nz); \ +S(Gx); S(Gy); S(Gz); \ +S(C_Les); S(E_Les); S(G_Les); \ +S(Op02FX); \ +S(Op02FY); \ +S(Op02FZ); \ +S(Op02LFE); \ +S(Op02LES); \ +S(Op02AAS); \ +S(Op02AZS); \ +S(Op02VOF); \ +S(Op02VVA); \ +S(Op02CX); \ +S(Op02CY); \ +S(Op0AVS); \ +S(Op0AA); \ +S(Op0AB); \ +S(Op0AC); \ +S(Op0AD); \ +S(Op06X); \ +S(Op06Y); \ +S(Op06Z); \ +S(Op06H); \ +S(Op06V); \ +S(Op06M); \ +S(matrixC); \ +S(matrixB); \ +S(matrixA); \ +S(Op01m); \ +S(Op01Zr); \ +S(Op01Xr); \ +S(Op01Yr); \ +S(Op11m); \ +S(Op11Zr); \ +S(Op11Xr); \ +S(Op11Yr); \ +S(Op21m); \ +S(Op21Zr); \ +S(Op21Xr); \ +S(Op21Yr); \ +S(Op0DX); \ +S(Op0DY); \ +S(Op0DZ); \ +S(Op0DF); \ +S(Op0DL); \ +S(Op0DU); \ +S(Op1DX); \ +S(Op1DY); \ +S(Op1DZ); \ +S(Op1DF); \ +S(Op1DL); \ +S(Op1DU); \ +S(Op2DX); \ +S(Op2DY); \ +S(Op2DZ); \ +S(Op2DF); \ +S(Op2DL); \ +S(Op2DU); \ +S(Op03F); \ +S(Op03L); \ +S(Op03U); \ +S(Op03X); \ +S(Op03Y); \ +S(Op03Z); \ +S(Op13F); \ +S(Op13L); \ +S(Op13U); \ +S(Op13X); \ +S(Op13Y); \ +S(Op13Z); \ +S(Op23F); \ +S(Op23L); \ +S(Op23U); \ +S(Op23X); \ +S(Op23Y); \ +S(Op23Z); \ +S(Op14Zr); \ +S(Op14Xr); \ +S(Op14Yr); \ +S(Op14U); \ +S(Op14F); \ +S(Op14L); \ +S(Op14Zrr); \ +S(Op14Xrr); \ +S(Op14Yrr); \ +S(Op0EH); \ +S(Op0EV); \ +S(Op0EX); \ +S(Op0EY); \ +S(Op0BX); \ +S(Op0BY); \ +S(Op0BZ); \ +S(Op0BS); \ +S(Op1BX); \ +S(Op1BY); \ +S(Op1BZ); \ +S(Op1BS); \ +S(Op2BX); \ +S(Op2BY); \ +S(Op2BZ); \ +S(Op2BS); \ +S(Op08X); S(Op08Y); S(Op08Z); S(Op08Ll); S(Op08Lh); \ +S(Op18X); S(Op18Y); S(Op18Z); S(Op18R); S(Op18D); \ +S(Op38X); S(Op38Y); S(Op38Z); S(Op38R); S(Op38D); \ +S(Op28X); \ +S(Op28Y); \ +S(Op28Z); \ +S(Op28R); \ +S(Op1CX); S(Op1CY); S(Op1CZ); \ +S(Op1CXBR); S(Op1CYBR); S(Op1CZBR); S(Op1CXAR); S(Op1CYAR); S(Op1CZAR); \ +S(Op1CX1); \ +S(Op1CY1); \ +S(Op1CZ1); \ +S(Op1CX2); \ +S(Op1CY2); \ +S(Op1CZ2); \ +S(Op0FRamsize); \ +S(Op0FPass); \ +S(Op2FUnknown); \ +S(Op2FSize); \ +// end + +void S9xPreSaveDSP1() +{ + int i = 0; +#define S(x) {memcpy(DSP1.temp_save_data + i, &(x), sizeof(x)); i += sizeof(x);} + SAVE_OR_LOAD_THE_VARIABLES(); +#undef S + assert(i == sizeof(DSP1.temp_save_data)); +} + +void S9xPostLoadDSP1() +{ + int i = 0; +#define S(x) {memcpy(&(x), DSP1.temp_save_data + i, sizeof(x)); i += sizeof(x);} + SAVE_OR_LOAD_THE_VARIABLES(); +#undef S + assert(i == sizeof(DSP1.temp_save_data)); +} diff --git a/source/snes9x/dsp2.cpp b/source/snes9x/dsp2emu.c.inc similarity index 57% rename from source/snes9x/dsp2.cpp rename to source/snes9x/dsp2emu.c.inc index 9f004ed..7512b2d 100644 --- a/source/snes9x/dsp2.cpp +++ b/source/snes9x/dsp2emu.c.inc @@ -159,84 +159,20 @@ **********************************************************************************/ -#include "snes9x.h" -#include "memmap.h" - -static void DSP2_Op01 (void); -static void DSP2_Op03 (void); -static void DSP2_Op05 (void); -static void DSP2_Op06 (void); -static void DSP2_Op09 (void); -static void DSP2_Op0D (void); -// convert bitmap to bitplane tile -static void DSP2_Op01 (void) -{ - // Op01 size is always 32 bytes input and output - // The hardware does strange things if you vary the size - - uint8 c0, c1, c2, c3; - uint8 *p1 = DSP2.parameters; - uint8 *p2a = DSP2.output; - uint8 *p2b = DSP2.output + 16; // halfway - - // Process 8 blocks of 4 bytes each - - for (int j = 0; j < 8; j++) - { - c0 = *p1++; - c1 = *p1++; - c2 = *p1++; - c3 = *p1++; - - *p2a++ = (c0 & 0x10) << 3 | - (c0 & 0x01) << 6 | - (c1 & 0x10) << 1 | - (c1 & 0x01) << 4 | - (c2 & 0x10) >> 1 | - (c2 & 0x01) << 2 | - (c3 & 0x10) >> 3 | - (c3 & 0x01); - - *p2a++ = (c0 & 0x20) << 2 | - (c0 & 0x02) << 5 | - (c1 & 0x20) | - (c1 & 0x02) << 3 | - (c2 & 0x20) >> 2 | - (c2 & 0x02) << 1 | - (c3 & 0x20) >> 4 | - (c3 & 0x02) >> 1; - - *p2b++ = (c0 & 0x40) << 1 | - (c0 & 0x04) << 4 | - (c1 & 0x40) >> 1 | - (c1 & 0x04) << 2 | - (c2 & 0x40) >> 3 | - (c2 & 0x04) | - (c3 & 0x40) >> 5 | - (c3 & 0x04) >> 2; - - *p2b++ = (c0 & 0x80) | - (c0 & 0x08) << 3 | - (c1 & 0x80) >> 2 | - (c1 & 0x08) << 1 | - (c2 & 0x80) >> 4 | - (c2 & 0x08) >> 1 | - (c3 & 0x80) >> 6 | - (c3 & 0x08) >> 3; - } -} - -// set transparent color -static void DSP2_Op03 (void) -{ - DSP2.Op05Transparent = DSP2.parameters[0]; -} - -// replace bitmap using transparent color -static void DSP2_Op05 (void) + +uint16 DSP2Op09Word1=0; +uint16 DSP2Op09Word2=0; +bool DSP2Op05HasLen=false; +int DSP2Op05Len=0; +bool DSP2Op06HasLen=false; +int DSP2Op06Len=0; +uint8 DSP2Op05Transparent=0; + +void DSP2_Op05 () { + uint8 color; // Overlay bitmap with transparency. // Input: // @@ -262,52 +198,136 @@ static void DSP2_Op05 (void) // size = 0. I don't think it's worth implementing this quirk unless it's // proven necessary. - uint8 color; - uint8 c1, c2; - uint8 *p1 = DSP2.parameters; - uint8 *p2 = DSP2.parameters + DSP2.Op05Len; - uint8 *p3 = DSP2.output; + int n; + unsigned char c1; + unsigned char c2; + unsigned char *p1 = DSP1.parameters; + unsigned char *p2 = &DSP1.parameters[DSP2Op05Len]; + unsigned char *p3 = DSP1.output; - color = DSP2.Op05Transparent & 0x0f; + color = DSP2Op05Transparent&0x0f; - for (int32 n = 0; n < DSP2.Op05Len; n++) + for( n = 0; n < DSP2Op05Len; n++ ) { c1 = *p1++; c2 = *p2++; - *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0: c2 & 0xf0) | (((c2 & 0x0f) == color) ? c1 & 0x0f: c2 & 0x0f); + *p3++ = ( ((c2 >> 4) == color ) ? c1 & 0xf0: c2 & 0xf0 ) | + ( ((c2 & 0x0f)==color) ? c1 & 0x0f: c2 & 0x0f ); } } -// reverse bitmap -static void DSP2_Op06 (void) +void DSP2_Op01 () +{ + // Op01 size is always 32 bytes input and output. + // The hardware does strange things if you vary the size. + + int j; + unsigned char c0, c1, c2, c3; + unsigned char *p1 = DSP1.parameters; + unsigned char *p2a = DSP1.output; + unsigned char *p2b = &DSP1.output[16]; // halfway + + // Process 8 blocks of 4 bytes each + + for ( j = 0; j < 8; j++ ) + { + c0 = *p1++; + c1 = *p1++; + c2 = *p1++; + c3 = *p1++; + + *p2a++ = (c0 & 0x10) << 3 | + (c0 & 0x01) << 6 | + (c1 & 0x10) << 1 | + (c1 & 0x01) << 4 | + (c2 & 0x10) >> 1 | + (c2 & 0x01) << 2 | + (c3 & 0x10) >> 3 | + (c3 & 0x01); + + *p2a++ = (c0 & 0x20) << 2 | + (c0 & 0x02) << 5 | + (c1 & 0x20) | + (c1 & 0x02) << 3 | + (c2 & 0x20) >> 2 | + (c2 & 0x02) << 1 | + (c3 & 0x20) >> 4 | + (c3 & 0x02) >> 1; + + *p2b++ = (c0 & 0x40) << 1 | + (c0 & 0x04) << 4 | + (c1 & 0x40) >> 1 | + (c1 & 0x04) << 2 | + (c2 & 0x40) >> 3 | + (c2 & 0x04) | + (c3 & 0x40) >> 5 | + (c3 & 0x04) >> 2; + + + *p2b++ = (c0 & 0x80) | + (c0 & 0x08) << 3 | + (c1 & 0x80) >> 2 | + (c1 & 0x08) << 1 | + (c2 & 0x80) >> 4 | + (c2 & 0x08) >> 1 | + (c3 & 0x80) >> 6 | + (c3 & 0x08) >> 3; + } + return; +} + +void DSP2_Op06 () { // Input: // size // bitmap - for (int32 i = 0, j = DSP2.Op06Len - 1; i < DSP2.Op06Len; i++, j--) - DSP2.output[j] = (DSP2.parameters[i] << 4) | (DSP2.parameters[i] >> 4); + int i, j; + + for ( i = 0, j = DSP2Op06Len - 1; i < DSP2Op06Len; i++, j-- ) + { + DSP1.output[j] = (DSP1.parameters[i] << 4) | (DSP1.parameters[i] >> 4); + } } -// multiply -static void DSP2_Op09 (void) +bool DSP2Op0DHasLen=false; +int DSP2Op0DOutLen=0; +int DSP2Op0DInLen=0; + +#ifndef DSP2_BIT_ACCURRATE_CODE + +// Scale bitmap based on input length out output length + +void DSP2_Op0D() { - DSP2.Op09Word1 = DSP2.parameters[0] | (DSP2.parameters[1] << 8); - DSP2.Op09Word2 = DSP2.parameters[2] | (DSP2.parameters[3] << 8); + // Overload's algorithm - use this unless doing hardware testing -#ifdef FAST_LSB_WORD_ACCESS - *(uint32 *) DSP2.output = DSP2.Op09Word1 * DSP2.Op09Word2; -#else - uint32 temp = DSP2.Op09Word1 * DSP2.Op09Word2; - DSP2.output[0] = temp & 0xFF; - DSP2.output[1] = (temp >> 8) & 0xFF; - DSP2.output[2] = (temp >> 16) & 0xFF; - DSP2.output[3] = (temp >> 24) & 0xFF; -#endif + // One note: the HW can do odd byte scaling but since we divide + // by two to get the count of bytes this won't work well for + // odd byte scaling (in any of the current algorithm implementations). + // So far I haven't seen Dungeon Master use it. + // If it does we can adjust the parameters and code to work with it + + int i; + int pixel_offset; + uint8 pixelarray[512]; + + for(i=0; i>1] >> 4; + else + pixelarray[i] = DSP1.parameters[pixel_offset>>1] & 0x0f; + } + + for ( i=0; i < DSP2Op0DOutLen; i++ ) + DSP1.output[i] = ( pixelarray[i<<1] << 4 ) | pixelarray[(i<<1)+1]; } -// scale bitmap -static void DSP2_Op0D (void) +#else + +void DSP2_Op0D() { // Bit accurate hardware algorithm - uses fixed point math // This should match the DSP2 Op0D output exactly @@ -323,198 +343,74 @@ static void DSP2_Op0D (void) // So far I haven't seen Dungeon Master use it. // If it does we can adjust the parameters and code to work with it - uint32 multiplier; // Any size int >= 32-bits - uint32 pixloc; // match size of multiplier - uint8 pixelarray[512]; - if (DSP2.Op0DInLen <= DSP2.Op0DOutLen) - multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 + uint32 multiplier; // Any size int >= 32-bits + uint32 pixloc; // match size of multiplier + int i, j; + uint8 pixelarray[512]; + + if (DSP2Op0DInLen <= DSP2Op0DOutLen) + multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 else - multiplier = (DSP2.Op0DInLen << 17) / ((DSP2.Op0DOutLen << 1) + 1); + multiplier = (DSP2Op0DInLen << 17) / ((DSP2Op0DOutLen<<1) + 1); pixloc = 0; - - for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) + for ( i=0; i < DSP2Op0DOutLen * 2; i++ ) { - int32 j = pixloc >> 16; + j = pixloc >> 16; - if (j & 1) - pixelarray[i] = DSP2.parameters[j >> 1] & 0x0f; + if ( j & 1 ) + pixelarray[i] = DSP1.parameters[j>>1] & 0x0f; else - pixelarray[i] = (DSP2.parameters[j >> 1] & 0xf0) >> 4; + pixelarray[i] = (DSP1.parameters[j>>1] & 0xf0) >> 4; pixloc += multiplier; } - for (int32 i = 0; i < DSP2.Op0DOutLen; i++) - DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; + for ( i=0; i < DSP2Op0DOutLen; i++ ) + DSP1.output[i] = ( pixelarray[i<<1] << 4 ) | pixelarray[(i<<1)+1]; } -/* -static void DSP2_Op0D (void) +#endif + +#if 0 // Probably no reason to use this code - it's not quite bit accurate and it doesn't look as good as Overload's algorithm + +void DSP2_Op0D() { - // Overload's algorithm - use this unless doing hardware testing + // Float implementation of Neviksti's algorithm + // This is the right algorithm to match the DSP2 bits but the precision + // of the PC float does not match the precision of the fixed point math + // on the DSP2 causing occasional one off data mismatches (which should + // be no problem because its just a one pixel difference in a scaled image + // to be displayed). - // One note: the HW can do odd byte scaling but since we divide - // by two to get the count of bytes this won't work well for - // odd byte scaling (in any of the current algorithm implementations). - // So far I haven't seen Dungeon Master use it. - // If it does we can adjust the parameters and code to work with it + float multiplier; + float pixloc; + int i, j; + uint8 pixelarray[512]; - int32 pixel_offset; - uint8 pixelarray[512]; - - for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) - { - pixel_offset = (i * DSP2.Op0DInLen) / DSP2.Op0DOutLen; - - if ((pixel_offset & 1) == 0) - pixelarray[i] = DSP2.parameters[pixel_offset >> 1] >> 4; - else - pixelarray[i] = DSP2.parameters[pixel_offset >> 1] & 0x0f; - } - - for (int32 i = 0; i < DSP2.Op0DOutLen; i++) - DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; -} -*/ - -void DSP2SetByte (uint8 byte, uint16 address) -{ - if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) - { - if (DSP2.waiting4command) - { - DSP2.command = byte; - DSP2.in_index = 0; - DSP2.waiting4command = FALSE; - - switch (byte) - { - case 0x01: DSP2.in_count = 32; break; - case 0x03: DSP2.in_count = 1; break; - case 0x05: DSP2.in_count = 1; break; - case 0x06: DSP2.in_count = 1; break; - case 0x09: DSP2.in_count = 4; break; - case 0x0D: DSP2.in_count = 2; break; - default: - #ifdef DEBUGGER - //printf("Op%02X\n", byte); - #endif - case 0x0f: DSP2.in_count = 0; break; - } - } - else - { - DSP2.parameters[DSP2.in_index] = byte; - DSP2.in_index++; - } - - if (DSP2.in_count == DSP2.in_index) - { - DSP2.waiting4command = TRUE; - DSP2.out_index = 0; - - switch (DSP2.command) - { - case 0x01: - DSP2.out_count = 32; - DSP2_Op01(); - break; - - case 0x03: - DSP2_Op03(); - break; - - case 0x05: - if (DSP2.Op05HasLen) - { - DSP2.Op05HasLen = FALSE; - DSP2.out_count = DSP2.Op05Len; - DSP2_Op05(); - } - else - { - DSP2.Op05Len = DSP2.parameters[0]; - DSP2.in_index = 0; - DSP2.in_count = 2 * DSP2.Op05Len; - DSP2.Op05HasLen = TRUE; - if (byte) - DSP2.waiting4command = FALSE; - } - - break; - - case 0x06: - if (DSP2.Op06HasLen) - { - DSP2.Op06HasLen = FALSE; - DSP2.out_count = DSP2.Op06Len; - DSP2_Op06(); - } - else - { - DSP2.Op06Len = DSP2.parameters[0]; - DSP2.in_index = 0; - DSP2.in_count = DSP2.Op06Len; - DSP2.Op06HasLen = TRUE; - if (byte) - DSP2.waiting4command = FALSE; - } - - break; - - case 0x09: - DSP2.out_count = 4; - DSP2_Op09(); - break; - - case 0x0D: - if (DSP2.Op0DHasLen) - { - DSP2.Op0DHasLen = FALSE; - DSP2.out_count = DSP2.Op0DOutLen; - DSP2_Op0D(); - } - else - { - DSP2.Op0DInLen = DSP2.parameters[0]; - DSP2.Op0DOutLen = DSP2.parameters[1]; - DSP2.in_index = 0; - DSP2.in_count = (DSP2.Op0DInLen + 1) >> 1; - DSP2.Op0DHasLen = TRUE; - if (byte) - DSP2.waiting4command = FALSE; - } - - break; - - case 0x0f: - default: - break; - } - } - } -} - -uint8 DSP2GetByte (uint16 address) -{ - uint8 t; - - if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) - { - if (DSP2.out_count) - { - t = (uint8) DSP2.output[DSP2.out_index]; - DSP2.out_index++; - if (DSP2.out_count == DSP2.out_index) - DSP2.out_count = 0; - } - else - t = 0xff; - } + if (DSP2Op0DInLen <= DSP2Op0DOutLen) + multiplier = (float) 1.0; else - t = 0x80; + multiplier = (float) ((DSP2Op0DInLen * 2.0) / (DSP2Op0DOutLen * 2.0 + 1.0)); - return (t); + pixloc = 0.0; + for ( i=0; i < DSP2Op0DOutLen * 2; i++ ) + { + // j = (int)(i * multiplier); + j = (int) pixloc; + + if ( j & 1 ) + pixelarray[i] = DSP1.parameters[j>>1] & 0x0f; + else + pixelarray[i] = (DSP1.parameters[j>>1] & 0xf0) >> 4; + + pixloc += multiplier; // use an add in the loop instead of multiply to increase loop speed + } + + for ( i=0; i < DSP2Op0DOutLen; i++ ) + DSP1.output[i] = ( pixelarray[i<<1] << 4 ) | pixelarray[(i<<1)+1]; } + +#endif + diff --git a/source/snes9x/dsp3.cpp b/source/snes9x/dsp3emu.c.inc similarity index 52% rename from source/snes9x/dsp3.cpp rename to source/snes9x/dsp3emu.c.inc index a8614c4..06b91c8 100644 --- a/source/snes9x/dsp3.cpp +++ b/source/snes9x/dsp3emu.c.inc @@ -159,13 +159,16 @@ **********************************************************************************/ -#include "snes9x.h" -#include "memmap.h" -static void (*SetDSP3) (void); -static const uint16 DSP3_DataROM[1024] = -{ +#ifndef __cplusplus +//C++ in C +typedef unsigned char bool; +#define true 1 +#define false 0 +#endif + +uint16 DSP3_DataROM[1024] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, @@ -296,957 +299,1004 @@ static const uint16 DSP3_DataROM[1024] = 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; -static bool8 DSP3_GetBits (uint8); -//static void DSP3_MemorySize (void); -static void DSP3_TestMemory (void); -static void DSP3_DumpDataROM (void); -static void DSP3_MemoryDump (void); -static void DSP3_Coordinate (void); -static void DSP3_Command (void); -static void DSP3_Decode_Data (void); -static void DSP3_Decode_Tree (void); -static void DSP3_Decode_Symbols (void); -static void DSP3_Decode (void); -static void DSP3_Decode_A (void); -static void DSP3_Convert (void); -static void DSP3_Convert_A (void); -static void DSP3_OP03 (void); -static void DSP3_OP06 (void); -static void DSP3_OP07 (void); -static void DSP3_OP07_A (void); -static void DSP3_OP07_B (void); -static void DSP3_OP0C (void); -//static void DSP3_OP0C_A (void); -static void DSP3_OP10 (void); -static void DSP3_OP1C (void); -static void DSP3_OP1C_A (void); -static void DSP3_OP1C_B (void); -static void DSP3_OP1C_C (void); -static void DSP3_OP1E (void); -static void DSP3_OP1E_A (void); -static void DSP3_OP1E_A1 (void); -static void DSP3_OP1E_A2 (void); -static void DSP3_OP1E_A3 (void); -static void DSP3_OP1E_B (void); -static void DSP3_OP1E_B1 (void); -static void DSP3_OP1E_B2 (void); -static void DSP3_OP1E_C (void); -static void DSP3_OP1E_C1 (void); -static void DSP3_OP1E_C2 (void); -static void DSP3_OP1E_D (int16, int16 *, int16 *); -static void DSP3_OP1E_D1 (int16, int16 *, int16 *); -static void DSP3_OP3E (void); +void (*SetDSP3)(); +void DSP3_Command(); +uint16 DSP3_DR; +uint16 DSP3_SR; +uint16 DSP3_MemoryIndex; -void DSP3_Reset (void) +void DSP3_Reset() { - DSP3.DR = 0x0080; - DSP3.SR = 0x0084; - SetDSP3 = &DSP3_Command; + DSP3_DR = 0x0080; + DSP3_SR = 0x0084; + SetDSP3 = &DSP3_Command; } -/* -static void DSP3_MemorySize (void) +void DSP3_MemorySize() { - DSP3.DR = 0x0300; - SetDSP3 = &DSP3_Reset; -} -*/ - -static void DSP3_TestMemory (void) -{ - DSP3.DR = 0x0000; + DSP3_DR = 0x0300; SetDSP3 = &DSP3_Reset; } -static void DSP3_DumpDataROM (void) +void DSP3_TestMemory() { - DSP3.DR = DSP3_DataROM[DSP3.MemoryIndex++]; - if (DSP3.MemoryIndex == 1024) + DSP3_DR = 0x0000; + SetDSP3 = &DSP3_Reset; +} + +void DSP3_DumpDataROM() +{ + DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++]; + if (DSP3_MemoryIndex == 1024) SetDSP3 = &DSP3_Reset; } -static void DSP3_MemoryDump (void) +void DSP3_MemoryDump() { - DSP3.MemoryIndex = 0; + DSP3_MemoryIndex = 0; SetDSP3 = &DSP3_DumpDataROM; DSP3_DumpDataROM(); } -static void DSP3_OP06 (void) +int16 DSP3_WinLo; +int16 DSP3_WinHi; + +void DSP3_OP06() { - DSP3.WinLo = (uint8) (DSP3.DR); - DSP3.WinHi = (uint8) (DSP3.DR >> 8); + DSP3_WinLo = (uint8)(DSP3_DR); + DSP3_WinHi = (uint8)(DSP3_DR >> 8); DSP3_Reset(); } -static void DSP3_OP03 (void) +void DSP3_OP03() { - int16 Lo = (uint8) (DSP3.DR); - int16 Hi = (uint8) (DSP3.DR >> 8); - int16 Ofs = (DSP3.WinLo * Hi << 1) + (Lo << 1); - - DSP3.DR = Ofs >> 1; + int16 Lo = (uint8)(DSP3_DR); + int16 Hi = (uint8)(DSP3_DR >> 8); + int16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1); + DSP3_DR = Ofs >> 1; SetDSP3 = &DSP3_Reset; } -static void DSP3_OP07_B (void) -{ - int16 Ofs = (DSP3.WinLo * DSP3.AddHi << 1) + (DSP3.AddLo << 1); +int16 DSP3_AddLo; +int16 DSP3_AddHi; - DSP3.DR = Ofs >> 1; +void DSP3_OP07_B() +{ + int16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1); + DSP3_DR = Ofs >> 1; SetDSP3 = &DSP3_Reset; } -static void DSP3_OP07_A (void) +void DSP3_OP07_A() { - int16 Lo = (uint8) (DSP3.DR); - int16 Hi = (uint8) (DSP3.DR >> 8); + int16 Lo = (uint8)(DSP3_DR); + int16 Hi = (uint8)(DSP3_DR >> 8); - if (Lo & 1) - Hi += (DSP3.AddLo & 1); + if (Lo & 1) Hi += (DSP3_AddLo & 1); - DSP3.AddLo += Lo; - DSP3.AddHi += Hi; + DSP3_AddLo += Lo; + DSP3_AddHi += Hi; - if (DSP3.AddLo < 0) - DSP3.AddLo += DSP3.WinLo; + if (DSP3_AddLo < 0) + DSP3_AddLo += DSP3_WinLo; else - if (DSP3.AddLo >= DSP3.WinLo) - DSP3.AddLo -= DSP3.WinLo; + if (DSP3_AddLo >= DSP3_WinLo) + DSP3_AddLo -= DSP3_WinLo; - if (DSP3.AddHi < 0) - DSP3.AddHi += DSP3.WinHi; + if (DSP3_AddHi < 0) + DSP3_AddHi += DSP3_WinHi; else - if (DSP3.AddHi >= DSP3.WinHi) - DSP3.AddHi -= DSP3.WinHi; + if (DSP3_AddHi >= DSP3_WinHi) + DSP3_AddHi -= DSP3_WinHi; - DSP3.DR = DSP3.AddLo | (DSP3.AddHi << 8) | ((DSP3.AddHi >> 8) & 0xff); + DSP3_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff); SetDSP3 = &DSP3_OP07_B; } -static void DSP3_OP07 (void) +void DSP3_OP07() { - uint32 dataOfs = ((DSP3.DR << 1) + 0x03b2) & 0x03ff; + uint32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff; - DSP3.AddHi = DSP3_DataROM[dataOfs]; - DSP3.AddLo = DSP3_DataROM[dataOfs + 1]; + DSP3_AddHi = DSP3_DataROM[dataOfs]; + DSP3_AddLo = DSP3_DataROM[dataOfs + 1]; SetDSP3 = &DSP3_OP07_A; - DSP3.SR = 0x0080; + DSP3_SR = 0x0080; } -static void DSP3_Coordinate (void) -{ - DSP3.Index++; +uint16 DSP3_Codewords; +uint16 DSP3_Outwords; +uint16 DSP3_Symbol; +uint16 DSP3_BitCount; +uint16 DSP3_Index; +uint16 DSP3_Codes[512]; +uint16 DSP3_BitsLeft; +uint16 DSP3_ReqBits; +uint16 DSP3_ReqData; +uint16 DSP3_BitCommand; +uint8 DSP3_BaseLength; +uint16 DSP3_BaseCodes; +uint16 DSP3_BaseCode; +uint8 DSP3_CodeLengths[8]; +uint16 DSP3_CodeOffsets[8]; +uint16 DSP3_LZCode; +uint8 DSP3_LZLength; - switch (DSP3.Index) +uint16 DSP3_X; +uint16 DSP3_Y; + +void DSP3_Coordinate() +{ + DSP3_Index++; + + switch (DSP3_Index) { - case 3: - if (DSP3.DR == 0xffff) + case 3: + { + if (DSP3_DR == 0xffff) DSP3_Reset(); break; - - case 4: - DSP3.X = DSP3.DR; + } + case 4: + { + DSP3_X = DSP3_DR; break; - - case 5: - DSP3.Y = DSP3.DR; - DSP3.DR = 1; + } + case 5: + { + DSP3_Y = DSP3_DR; + DSP3_DR = 1; break; - - case 6: - DSP3.DR = DSP3.X; + } + case 6: + { + DSP3_DR = DSP3_X; break; - - case 7: - DSP3.DR = DSP3.Y; - DSP3.Index = 0; + } + case 7: + { + DSP3_DR = DSP3_Y; + DSP3_Index = 0; break; + } } } -static void DSP3_Convert_A (void) +uint8 DSP3_Bitmap[8]; +uint8 DSP3_Bitplane[8]; +uint16 DSP3_BMIndex; +uint16 DSP3_BPIndex; +uint16 DSP3_Count; + +void DSP3_Convert_A() { - if (DSP3.BMIndex < 8) + if (DSP3_BMIndex < 8) { - DSP3.Bitmap[DSP3.BMIndex++] = (uint8) (DSP3.DR); - DSP3.Bitmap[DSP3.BMIndex++] = (uint8) (DSP3.DR >> 8); + DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR); + DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR >> 8); - if (DSP3.BMIndex == 8) + if (DSP3_BMIndex == 8) { - for (int i = 0; i < 8; i++) - { - for (int j = 0; j < 8; j++) + short i, j; + for (i=0; i < 8; i++) + for (j=0; j < 8; j++) { - DSP3.Bitplane[j] <<= 1; - DSP3.Bitplane[j] |= (DSP3.Bitmap[i] >> j) & 1; + DSP3_Bitplane[j] <<= 1; + DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1; } - } - DSP3.BPIndex = 0; - DSP3.Count--; + DSP3_BPIndex = 0; + DSP3_Count--; } } - if (DSP3.BMIndex == 8) + if (DSP3_BMIndex == 8) { - if (DSP3.BPIndex == 8) + if (DSP3_BPIndex == 8) { - if (!DSP3.Count) - DSP3_Reset(); - - DSP3.BMIndex = 0; + if (!DSP3_Count) DSP3_Reset(); + DSP3_BMIndex = 0; } else { - DSP3.DR = DSP3.Bitplane[DSP3.BPIndex++]; - DSP3.DR |= DSP3.Bitplane[DSP3.BPIndex++] << 8; + DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++]; + DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8; } } } -static void DSP3_Convert (void) +void DSP3_Convert() { - DSP3.Count = DSP3.DR; - DSP3.BMIndex = 0; + DSP3_Count = DSP3_DR; + DSP3_BMIndex = 0; SetDSP3 = &DSP3_Convert_A; } -static bool8 DSP3_GetBits (uint8 Count) +bool DSP3_GetBits(uint8 Count) { - if (!DSP3.BitsLeft) + if (!DSP3_BitsLeft) { - DSP3.BitsLeft = Count; - DSP3.ReqBits = 0; + DSP3_BitsLeft = Count; + DSP3_ReqBits = 0; } - do - { - if (!DSP3.BitCount) + do { + if (!DSP3_BitCount) { - DSP3.SR = 0xC0; - return (FALSE); + DSP3_SR = 0xC0; + return false; } - DSP3.ReqBits <<= 1; - if (DSP3.ReqData & 0x8000) - DSP3.ReqBits++; - DSP3.ReqData <<= 1; + DSP3_ReqBits <<= 1; + if (DSP3_ReqData & 0x8000) DSP3_ReqBits++; + DSP3_ReqData <<= 1; - DSP3.BitCount--; - DSP3.BitsLeft--; + DSP3_BitCount--; + DSP3_BitsLeft--; - } - while (DSP3.BitsLeft); + } while (DSP3_BitsLeft); - return (TRUE); + return true; } -static void DSP3_Decode_Data (void) +void DSP3_Decode_Data() { - if (!DSP3.BitCount) + if (!DSP3_BitCount) { - if (DSP3.SR & 0x40) + if (DSP3_SR & 0x40) { - DSP3.ReqData = DSP3.DR; - DSP3.BitCount += 16; + DSP3_ReqData = DSP3_DR; + DSP3_BitCount += 16; } else { - DSP3.SR = 0xC0; + DSP3_SR = 0xC0; return; } } - if (DSP3.LZCode == 1) + if (DSP3_LZCode == 1) { if (!DSP3_GetBits(1)) return; - if (DSP3.ReqBits) - DSP3.LZLength = 12; + if (DSP3_ReqBits) + DSP3_LZLength = 12; else - DSP3.LZLength = 8; + DSP3_LZLength = 8; - DSP3.LZCode++; + DSP3_LZCode++; } - if (DSP3.LZCode == 2) + if (DSP3_LZCode == 2) { - if (!DSP3_GetBits(DSP3.LZLength)) + if (!DSP3_GetBits(DSP3_LZLength)) return; - DSP3.LZCode = 0; - DSP3.Outwords--; - if (!DSP3.Outwords) - SetDSP3 = &DSP3_Reset; + DSP3_LZCode = 0; + DSP3_Outwords--; + if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset; - DSP3.SR = 0x80; - DSP3.DR = DSP3.ReqBits; + DSP3_SR = 0x80; + DSP3_DR = DSP3_ReqBits; return; } - if (DSP3.BaseCode == 0xffff) + if (DSP3_BaseCode == 0xffff) { - if (!DSP3_GetBits(DSP3.BaseLength)) + if (!DSP3_GetBits(DSP3_BaseLength)) return; - DSP3.BaseCode = DSP3.ReqBits; + DSP3_BaseCode = DSP3_ReqBits; } - if (!DSP3_GetBits(DSP3.CodeLengths[DSP3.BaseCode])) + if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode])) return; - DSP3.Symbol = DSP3.Codes[DSP3.CodeOffsets[DSP3.BaseCode] + DSP3.ReqBits]; - DSP3.BaseCode = 0xffff; + DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits]; + DSP3_BaseCode = 0xffff; - if (DSP3.Symbol & 0xff00) + if (DSP3_Symbol & 0xff00) { - DSP3.Symbol += 0x7f02; - DSP3.LZCode++; + DSP3_Symbol += 0x7f02; + DSP3_LZCode++; } else { - DSP3.Outwords--; - if (!DSP3.Outwords) + DSP3_Outwords--; + if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset; } - DSP3.SR = 0x80; - DSP3.DR = DSP3.Symbol; + DSP3_SR = 0x80; + DSP3_DR = DSP3_Symbol; } -static void DSP3_Decode_Tree (void) +void DSP3_Decode_Tree() { - if (!DSP3.BitCount) + if (!DSP3_BitCount) { - DSP3.ReqData = DSP3.DR; - DSP3.BitCount += 16; + DSP3_ReqData = DSP3_DR; + DSP3_BitCount += 16; } - if (!DSP3.BaseCodes) + if (!DSP3_BaseCodes) { DSP3_GetBits(1); - - if (DSP3.ReqBits) + if (DSP3_ReqBits) { - DSP3.BaseLength = 3; - DSP3.BaseCodes = 8; + DSP3_BaseLength = 3; + DSP3_BaseCodes = 8; } else { - DSP3.BaseLength = 2; - DSP3.BaseCodes = 4; + DSP3_BaseLength = 2; + DSP3_BaseCodes = 4; } } - while (DSP3.BaseCodes) + while (DSP3_BaseCodes) { if (!DSP3_GetBits(3)) return; - DSP3.ReqBits++; + DSP3_ReqBits++; - DSP3.CodeLengths[DSP3.Index] = (uint8) DSP3.ReqBits; - DSP3.CodeOffsets[DSP3.Index] = DSP3.Symbol; - DSP3.Index++; + DSP3_CodeLengths[DSP3_Index] = (uint8) DSP3_ReqBits; + DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol; + DSP3_Index++; - DSP3.Symbol += 1 << DSP3.ReqBits; - DSP3.BaseCodes--; + DSP3_Symbol += 1 << DSP3_ReqBits; + DSP3_BaseCodes--; } - DSP3.BaseCode = 0xffff; - DSP3.LZCode = 0; + DSP3_BaseCode = 0xffff; + DSP3_LZCode = 0; SetDSP3 = &DSP3_Decode_Data; - if (DSP3.BitCount) - DSP3_Decode_Data(); + if (DSP3_BitCount) DSP3_Decode_Data(); } -static void DSP3_Decode_Symbols (void) +void DSP3_Decode_Symbols() { - DSP3.ReqData = DSP3.DR; - DSP3.BitCount += 16; + DSP3_ReqData = DSP3_DR; + DSP3_BitCount += 16; - do - { - if (DSP3.BitCommand == 0xffff) + do { + + if (DSP3_BitCommand == 0xffff) { - if (!DSP3_GetBits(2)) - return; - - DSP3.BitCommand = DSP3.ReqBits; + if (!DSP3_GetBits(2)) return; + DSP3_BitCommand = DSP3_ReqBits; } - switch (DSP3.BitCommand) + switch (DSP3_BitCommand) { - case 0: - if (!DSP3_GetBits(9)) - return; - DSP3.Symbol = DSP3.ReqBits; + case 0: + { + if (!DSP3_GetBits(9)) return; + DSP3_Symbol = DSP3_ReqBits; break; - - case 1: - DSP3.Symbol++; + } + case 1: + { + DSP3_Symbol++; break; - - case 2: - if (!DSP3_GetBits(1)) - return; - DSP3.Symbol += 2 + DSP3.ReqBits; + } + case 2: + { + if (!DSP3_GetBits(1)) return; + DSP3_Symbol += 2 + DSP3_ReqBits; break; - - case 3: - if (!DSP3_GetBits(4)) - return; - DSP3.Symbol += 4 + DSP3.ReqBits; + } + case 3: + { + if (!DSP3_GetBits(4)) return; + DSP3_Symbol += 4 + DSP3_ReqBits; break; + } } - DSP3.BitCommand = 0xffff; + DSP3_BitCommand = 0xffff; - DSP3.Codes[DSP3.Index++] = DSP3.Symbol; - DSP3.Codewords--; + DSP3_Codes[DSP3_Index++] = DSP3_Symbol; + DSP3_Codewords--; - } - while (DSP3.Codewords); + } while (DSP3_Codewords); - DSP3.Index = 0; - DSP3.Symbol = 0; - DSP3.BaseCodes = 0; + DSP3_Index = 0; + DSP3_Symbol = 0; + DSP3_BaseCodes = 0; SetDSP3 = &DSP3_Decode_Tree; - if (DSP3.BitCount) - DSP3_Decode_Tree(); + if (DSP3_BitCount) DSP3_Decode_Tree(); } -static void DSP3_Decode_A (void) +void DSP3_Decode_A() { - DSP3.Outwords = DSP3.DR; + DSP3_Outwords = DSP3_DR; SetDSP3 = &DSP3_Decode_Symbols; - DSP3.BitCount = 0; - DSP3.BitsLeft = 0; - DSP3.Symbol = 0; - DSP3.Index = 0; - DSP3.BitCommand = 0xffff; - DSP3.SR = 0xC0; + DSP3_BitCount = 0; + DSP3_BitsLeft = 0; + DSP3_Symbol = 0; + DSP3_Index = 0; + DSP3_BitCommand = 0xffff; + DSP3_SR = 0xC0; } -static void DSP3_Decode (void) +void DSP3_Decode() { - DSP3.Codewords = DSP3.DR; + DSP3_Codewords = DSP3_DR; SetDSP3 = &DSP3_Decode_A; } + // Opcodes 1E/3E bit-perfect to 'dsp3-intro' log // src: adapted from SD Gundam X/G-Next -static void DSP3_OP3E (void) +int16 op3e_x; +int16 op3e_y; + +int16 op1e_terrain[0x2000]; +int16 op1e_cost[0x2000]; +int16 op1e_weight[0x2000]; + +int16 op1e_cell; +int16 op1e_turn; +int16 op1e_search; + +int16 op1e_x; +int16 op1e_y; + +int16 op1e_min_radius; +int16 op1e_max_radius; + +int16 op1e_max_search_radius; +int16 op1e_max_path_radius; + +int16 op1e_lcv_radius; +int16 op1e_lcv_steps; +int16 op1e_lcv_turns; + +void DSP3_OP3E() { - DSP3. op3e_x = (uint8) (DSP3.DR & 0x00ff); - DSP3. op3e_y = (uint8) ((DSP3.DR & 0xff00) >> 8); + op3e_x = (uint8)(DSP3_DR & 0x00ff); + op3e_y = (uint8)((DSP3_DR & 0xff00)>>8); DSP3_OP03(); - DSP3.op1e_terrain[DSP3.DR] = 0x00; - DSP3.op1e_cost[DSP3.DR] = 0xff; - DSP3.op1e_weight[DSP3.DR] = 0; + op1e_terrain[ DSP3_DR ] = 0x00; + op1e_cost[ DSP3_DR ] = 0xff; + op1e_weight[ DSP3_DR ] = 0; - DSP3.op1e_max_search_radius = 0; - DSP3.op1e_max_path_radius = 0; + op1e_max_search_radius = 0; + op1e_max_path_radius = 0; } -static void DSP3_OP1E (void) +void DSP3_OP1E_A(); +void DSP3_OP1E_A1(); +void DSP3_OP1E_A2(); +void DSP3_OP1E_A3(); + +void DSP3_OP1E_B(); +void DSP3_OP1E_B1(); +void DSP3_OP1E_B2(); + +void DSP3_OP1E_C(); +void DSP3_OP1E_C1(); +void DSP3_OP1E_C2(); + +void DSP3_OP1E_D( int16, int16 *, int16 * ); +void DSP3_OP1E_D1( int16 move, int16 *lo, int16 *hi ); + +void DSP3_OP1E() { - DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); - DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); + int lcv; - if (DSP3.op1e_min_radius == 0) - DSP3.op1e_min_radius++; + op1e_min_radius = (uint8)(DSP3_DR & 0x00ff); + op1e_max_radius = (uint8)((DSP3_DR & 0xff00)>>8); - if (DSP3.op1e_max_search_radius >= DSP3.op1e_min_radius) - DSP3.op1e_min_radius = DSP3.op1e_max_search_radius + 1; + if( op1e_min_radius == 0 ) + op1e_min_radius++; - if (DSP3.op1e_max_radius > DSP3.op1e_max_search_radius) - DSP3.op1e_max_search_radius = DSP3.op1e_max_radius; + if( op1e_max_search_radius >= op1e_min_radius ) + op1e_min_radius = op1e_max_search_radius+1; - DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; - DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + if( op1e_max_radius > op1e_max_search_radius ) + op1e_max_search_radius = op1e_max_radius; - DSP3.op1e_lcv_turns = 6; - DSP3.op1e_turn = 0; + op1e_lcv_radius = op1e_min_radius; + op1e_lcv_steps = op1e_min_radius; - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; + op1e_lcv_turns = 6; + op1e_turn = 0; - for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) - DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + op1e_x = op3e_x; + op1e_y = op3e_y; + + for( lcv = 0; lcv < op1e_min_radius; lcv++ ) + DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); DSP3_OP1E_A(); } -static void DSP3_OP1E_A (void) +void DSP3_OP1E_A() { - if (DSP3.op1e_lcv_steps == 0) - { - DSP3.op1e_lcv_radius++; + int lcv; - DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + if( op1e_lcv_steps == 0 ) { + op1e_lcv_radius++; - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; + op1e_lcv_steps = op1e_lcv_radius; - for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) - DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + op1e_x = op3e_x; + op1e_y = op3e_y; + + for( lcv = 0; lcv < op1e_lcv_radius; lcv++ ) + DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); } - if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) - { - DSP3.op1e_turn++; - DSP3.op1e_lcv_turns--; + if( op1e_lcv_radius > op1e_max_radius ) { + op1e_turn++; + op1e_lcv_turns--; - DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; - DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + op1e_lcv_radius = op1e_min_radius; + op1e_lcv_steps = op1e_min_radius; - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; + op1e_x = op3e_x; + op1e_y = op3e_y; - for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) - DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + for( lcv = 0; lcv < op1e_min_radius; lcv++ ) + DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); } - if (DSP3.op1e_lcv_turns == 0) - { - DSP3.DR = 0xffff; - DSP3.SR = 0x0080; + if( op1e_lcv_turns == 0 ) { + DSP3_DR = 0xffff; + DSP3_SR = 0x0080; SetDSP3 = &DSP3_OP1E_B; return; } - DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); DSP3_OP03(); - DSP3.op1e_cell = DSP3.DR; + op1e_cell = DSP3_DR; - DSP3.SR = 0x0080; + DSP3_SR = 0x0080; SetDSP3 = &DSP3_OP1E_A1; } -static void DSP3_OP1E_A1 (void) +void DSP3_OP1E_A1() { - DSP3.SR = 0x0084; + DSP3_SR = 0x0084; SetDSP3 = &DSP3_OP1E_A2; } -static void DSP3_OP1E_A2 (void) +void DSP3_OP1E_A2() { - DSP3.op1e_terrain[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); + op1e_terrain[ op1e_cell ] = (uint8)(DSP3_DR & 0x00ff); - DSP3.SR = 0x0084; + DSP3_SR = 0x0084; SetDSP3 = &DSP3_OP1E_A3; } -static void DSP3_OP1E_A3 (void) +void DSP3_OP1E_A3() { - DSP3.op1e_cost[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); + op1e_cost[ op1e_cell ] = (uint8)(DSP3_DR & 0x00ff); - if (DSP3.op1e_lcv_radius == 1) - { - if (DSP3.op1e_terrain[DSP3.op1e_cell] & 1) - DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; - else - DSP3.op1e_weight[DSP3.op1e_cell] = DSP3.op1e_cost[DSP3.op1e_cell]; + if( op1e_lcv_radius == 1 ) { + if( op1e_terrain[ op1e_cell ] & 1 ) { + op1e_weight[ op1e_cell ] = 0xff; + } else { + op1e_weight[ op1e_cell ] = op1e_cost[ op1e_cell ]; + } + } + else { + op1e_weight[ op1e_cell ] = 0xff; } - else - DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; - DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); - DSP3.op1e_lcv_steps--; + DSP3_OP1E_D( (int16)(op1e_turn+2), &op1e_x, &op1e_y ); + op1e_lcv_steps--; - DSP3.SR = 0x0080; + DSP3_SR = 0x0080; DSP3_OP1E_A(); } -static void DSP3_OP1E_B (void) -{ - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; - DSP3.op1e_lcv_radius = 1; - DSP3.op1e_search = 0; +void DSP3_OP1E_B() +{ + op1e_x = op3e_x; + op1e_y = op3e_y; + op1e_lcv_radius = 1; + + op1e_search = 0; DSP3_OP1E_B1(); SetDSP3 = &DSP3_OP1E_C; } -static void DSP3_OP1E_B1 (void) + +void DSP3_OP1E_B1() { - while (DSP3.op1e_lcv_radius < DSP3.op1e_max_radius) - { - DSP3.op1e_y--; + while( op1e_lcv_radius < op1e_max_radius ) { + op1e_y--; - DSP3.op1e_lcv_turns = 6; - DSP3.op1e_turn = 5; + op1e_lcv_turns = 6; + op1e_turn = 5; - while (DSP3.op1e_lcv_turns) - { - DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + while( op1e_lcv_turns ) { + op1e_lcv_steps = op1e_lcv_radius; - while (DSP3.op1e_lcv_steps) - { - DSP3_OP1E_D1(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + while( op1e_lcv_steps ) { + DSP3_OP1E_D1( op1e_turn, &op1e_x, &op1e_y ); - if (0 <= DSP3.op1e_y && DSP3.op1e_y < DSP3.WinHi && 0 <= DSP3.op1e_x && DSP3.op1e_x < DSP3.WinLo) - { - DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + if( 0 <= op1e_y && op1e_y < DSP3_WinHi && + 0 <= op1e_x && op1e_x < DSP3_WinLo ) { + DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); DSP3_OP03(); - DSP3.op1e_cell = DSP3.DR; - if (DSP3.op1e_cost[DSP3.op1e_cell] < 0x80 && DSP3.op1e_terrain[DSP3.op1e_cell] < 0x40) - DSP3_OP1E_B2(); // end cell perimeter + op1e_cell = DSP3_DR; + if( op1e_cost[ op1e_cell ] < 0x80 && + op1e_terrain[ op1e_cell ] < 0x40 ) { + DSP3_OP1E_B2(); + } // end cell perimeter } - DSP3.op1e_lcv_steps--; + op1e_lcv_steps--; } // end search line - DSP3.op1e_turn--; - if (DSP3.op1e_turn == 0) - DSP3.op1e_turn = 6; + op1e_turn--; + if( op1e_turn == 0 ) op1e_turn = 6; - DSP3.op1e_lcv_turns--; + op1e_lcv_turns--; } // end circle search - DSP3.op1e_lcv_radius++; + op1e_lcv_radius++; } // end radius search } -static void DSP3_OP1E_B2 (void) + +void DSP3_OP1E_B2() { - int16 cell; - int16 path; - int16 x, y; - int16 lcv_turns; + int16 cell; + int16 path; + int16 x,y; + int16 lcv_turns; path = 0xff; lcv_turns = 6; - while (lcv_turns) - { - x = DSP3.op1e_x; - y = DSP3.op1e_y; + while( lcv_turns ) { + x = op1e_x; + y = op1e_y; - DSP3_OP1E_D1(lcv_turns, &x, &y); + DSP3_OP1E_D1( lcv_turns, &x, &y ); - DSP3.DR = (uint8) (x) | ((uint8) (y) << 8); + DSP3_DR = (uint8)(x) | ((uint8)(y)<<8); DSP3_OP03(); - cell = DSP3.DR; + cell = DSP3_DR; - if (0 <= y && y < DSP3.WinHi && 0 <= x && x < DSP3.WinLo) - { - if (DSP3.op1e_terrain[cell] < 0x80 || DSP3.op1e_weight[cell] == 0) - { - if (DSP3.op1e_weight[cell] < path) - path = DSP3.op1e_weight[cell]; + if( 0 <= y && y < DSP3_WinHi && + 0 <= x && x < DSP3_WinLo ) { + + if( op1e_terrain[ cell ] < 0x80 || op1e_weight[ cell ] == 0 ) { + if( op1e_weight[ cell ] < path ) { + path = op1e_weight[ cell ]; + } } } // end step travel lcv_turns--; } // end while turns - if (path != 0xff) - DSP3.op1e_weight[DSP3.op1e_cell] = path + DSP3.op1e_cost[DSP3.op1e_cell]; + if( path != 0xff ) { + op1e_weight[ op1e_cell ] = path + op1e_cost[ op1e_cell ]; + } } -static void DSP3_OP1E_C (void) + +void DSP3_OP1E_C() { - DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); - DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); + int lcv; - if (DSP3.op1e_min_radius == 0) - DSP3.op1e_min_radius++; + op1e_min_radius = (uint8)(DSP3_DR & 0x00ff); + op1e_max_radius = (uint8)((DSP3_DR & 0xff00)>>8); - if (DSP3.op1e_max_path_radius >= DSP3.op1e_min_radius) - DSP3.op1e_min_radius = DSP3.op1e_max_path_radius + 1; + if( op1e_min_radius == 0 ) + op1e_min_radius++; - if (DSP3.op1e_max_radius > DSP3.op1e_max_path_radius) - DSP3.op1e_max_path_radius = DSP3.op1e_max_radius; + if( op1e_max_path_radius >= op1e_min_radius ) + op1e_min_radius = op1e_max_path_radius+1; - DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; - DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + if( op1e_max_radius > op1e_max_path_radius ) + op1e_max_path_radius = op1e_max_radius; - DSP3.op1e_lcv_turns = 6; - DSP3.op1e_turn = 0; + op1e_lcv_radius = op1e_min_radius; + op1e_lcv_steps = op1e_min_radius; - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; + op1e_lcv_turns = 6; + op1e_turn = 0; - for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) - DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + op1e_x = op3e_x; + op1e_y = op3e_y; + + for( lcv = 0; lcv < op1e_min_radius; lcv++ ) + DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); DSP3_OP1E_C1(); } -static void DSP3_OP1E_C1 (void) + +void DSP3_OP1E_C1() { - if (DSP3.op1e_lcv_steps == 0) - { - DSP3.op1e_lcv_radius++; + int lcv; - DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + if( op1e_lcv_steps == 0 ) { + op1e_lcv_radius++; - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; + op1e_lcv_steps = op1e_lcv_radius; - for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) - DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + op1e_x = op3e_x; + op1e_y = op3e_y; + + for( lcv = 0; lcv < op1e_lcv_radius; lcv++ ) + DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); } - if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) - { - DSP3.op1e_turn++; - DSP3.op1e_lcv_turns--; + if( op1e_lcv_radius > op1e_max_radius ) { + op1e_turn++; + op1e_lcv_turns--; - DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; - DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + op1e_lcv_radius = op1e_min_radius; + op1e_lcv_steps = op1e_min_radius; - DSP3.op1e_x = DSP3. op3e_x; - DSP3.op1e_y = DSP3. op3e_y; + op1e_x = op3e_x; + op1e_y = op3e_y; - for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) - DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + for( lcv = 0; lcv < op1e_min_radius; lcv++ ) + DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); } - if (DSP3.op1e_lcv_turns == 0) - { - DSP3.DR = 0xffff; - DSP3.SR = 0x0080; + if( op1e_lcv_turns == 0 ) { + DSP3_DR = 0xffff; + DSP3_SR = 0x0080; SetDSP3 = &DSP3_Reset; return; } - DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); DSP3_OP03(); - DSP3.op1e_cell = DSP3.DR; + op1e_cell = DSP3_DR; - DSP3.SR = 0x0080; + DSP3_SR = 0x0080; SetDSP3 = &DSP3_OP1E_C2; } -static void DSP3_OP1E_C2 (void) + +void DSP3_OP1E_C2() { - DSP3.DR = DSP3.op1e_weight[DSP3.op1e_cell]; + DSP3_DR = op1e_weight[ op1e_cell ]; - DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); - DSP3.op1e_lcv_steps--; + DSP3_OP1E_D( (int16)(op1e_turn+2), &op1e_x, &op1e_y ); + op1e_lcv_steps--; - DSP3.SR = 0x0084; + DSP3_SR = 0x0084; SetDSP3 = &DSP3_OP1E_C1; } -static void DSP3_OP1E_D (int16 move, int16 *lo, int16 *hi) + +void DSP3_OP1E_D( int16 move, int16 *lo, int16 *hi ) { - uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; - int16 Lo; - int16 Hi; + uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; + int16 Lo; + int16 Hi; - DSP3.AddHi = DSP3_DataROM[dataOfs]; - DSP3.AddLo = DSP3_DataROM[dataOfs + 1]; + DSP3_AddHi = DSP3_DataROM[dataOfs]; + DSP3_AddLo = DSP3_DataROM[dataOfs + 1]; - Lo = (uint8) (*lo); - Hi = (uint8) (*hi); + Lo = (uint8)(*lo); + Hi = (uint8)(*hi); - if (Lo & 1) - Hi += (DSP3.AddLo & 1); + if (Lo & 1) Hi += (DSP3_AddLo & 1); - DSP3.AddLo += Lo; - DSP3.AddHi += Hi; + DSP3_AddLo += Lo; + DSP3_AddHi += Hi; - if (DSP3.AddLo < 0) - DSP3.AddLo += DSP3.WinLo; + if (DSP3_AddLo < 0) + DSP3_AddLo += DSP3_WinLo; else - if (DSP3.AddLo >= DSP3.WinLo) - DSP3.AddLo -= DSP3.WinLo; + if (DSP3_AddLo >= DSP3_WinLo) + DSP3_AddLo -= DSP3_WinLo; - if (DSP3.AddHi < 0) - DSP3.AddHi += DSP3.WinHi; + if (DSP3_AddHi < 0) + DSP3_AddHi += DSP3_WinHi; else - if (DSP3.AddHi >= DSP3.WinHi) - DSP3.AddHi -= DSP3.WinHi; + if (DSP3_AddHi >= DSP3_WinHi) + DSP3_AddHi -= DSP3_WinHi; - *lo = DSP3.AddLo; - *hi = DSP3.AddHi; + *lo = DSP3_AddLo; + *hi = DSP3_AddHi; } -static void DSP3_OP1E_D1 (int16 move, int16 *lo, int16 *hi) -{ - const uint16 HiAdd[] = - { - 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 - }; - const uint16 LoAdd[] = - { +void DSP3_OP1E_D1( int16 move, int16 *lo, int16 *hi ) +{ + //uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; + int16 Lo; + int16 Hi; + + const unsigned short HiAdd[] = { + 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 + }; + const unsigned short LoAdd[] = { 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 }; - int16 Lo; - int16 Hi; - - if ((*lo) & 1) - DSP3.AddHi = HiAdd[move + 8]; + if( (*lo) & 1 ) + DSP3_AddHi = HiAdd[ move + 8 ]; else - DSP3.AddHi = HiAdd[move + 0]; + DSP3_AddHi = HiAdd[ move + 0 ]; + DSP3_AddLo = LoAdd[ move ]; - DSP3.AddLo = LoAdd[move]; + Lo = (uint8)(*lo); + Hi = (uint8)(*hi); - Lo = (uint8) (*lo); - Hi = (uint8) (*hi); + if (Lo & 1) Hi += (DSP3_AddLo & 1); - if (Lo & 1) - Hi += (DSP3.AddLo & 1); + DSP3_AddLo += Lo; + DSP3_AddHi += Hi; - DSP3.AddLo += Lo; - DSP3.AddHi += Hi; - - *lo = DSP3.AddLo; - *hi = DSP3.AddHi; + *lo = DSP3_AddLo; + *hi = DSP3_AddHi; } -static void DSP3_OP10 (void) + +void DSP3_OP10() { - if (DSP3.DR == 0xffff) + if( DSP3_DR == 0xffff ) { DSP3_Reset(); - else + } else { // absorb 2 bytes - DSP3.DR = DSP3.DR; + DSP3_DR = DSP3_DR; + } } -/* -static void DSP3_OP0C_A (void) + +void DSP3_OP0C_A() { // absorb 2 bytes - DSP3.DR = 0; + + DSP3_DR = 0; SetDSP3 = &DSP3_Reset; } -*/ -static void DSP3_OP0C (void) + +void DSP3_OP0C() { // absorb 2 bytes - DSP3.DR = 0; + + DSP3_DR = 0; //SetDSP3 = &DSP3_OP0C_A; SetDSP3 = &DSP3_Reset; } -static void DSP3_OP1C_C (void) + +void DSP3_OP1C_C() { // return 2 bytes - DSP3.DR = 0; + DSP3_DR = 0; SetDSP3 = &DSP3_Reset; } -static void DSP3_OP1C_B (void) + +void DSP3_OP1C_B() { + // absorb 2 bytes + // return 2 bytes - DSP3.DR = 0; + DSP3_DR = 0; SetDSP3 = &DSP3_OP1C_C; } -static void DSP3_OP1C_A (void) + +void DSP3_OP1C_A() { // absorb 2 bytes + SetDSP3 = &DSP3_OP1C_B; } -static void DSP3_OP1C (void) + +void DSP3_OP1C() { // absorb 2 bytes + SetDSP3 = &DSP3_OP1C_A; } -static void DSP3_Command (void) -{ - if (DSP3.DR < 0x40) - { - switch (DSP3.DR) - { - case 0x02: SetDSP3 = &DSP3_Coordinate; break; - case 0x03: SetDSP3 = &DSP3_OP03; break; - case 0x06: SetDSP3 = &DSP3_OP06; break; - case 0x07: SetDSP3 = &DSP3_OP07; return; - case 0x0c: SetDSP3 = &DSP3_OP0C; break; - case 0x0f: SetDSP3 = &DSP3_TestMemory; break; - case 0x10: SetDSP3 = &DSP3_OP10; break; - case 0x18: SetDSP3 = &DSP3_Convert; break; - case 0x1c: SetDSP3 = &DSP3_OP1C; break; - case 0x1e: SetDSP3 = &DSP3_OP1E; break; - case 0x1f: SetDSP3 = &DSP3_MemoryDump; break; - case 0x38: SetDSP3 = &DSP3_Decode; break; - case 0x3e: SetDSP3 = &DSP3_OP3E; break; - default: - return; - } - DSP3.SR = 0x0080; - DSP3.Index = 0; +void DSP3_Command() +{ + if (DSP3_DR < 0x40) + { + switch (DSP3_DR) + { + case 0x02: SetDSP3 = &DSP3_Coordinate; break; + case 0x03: SetDSP3 = &DSP3_OP03; break; + case 0x06: SetDSP3 = &DSP3_OP06; break; + case 0x07: SetDSP3 = &DSP3_OP07; return; + case 0x0c: SetDSP3 = &DSP3_OP0C; break; + case 0x0f: SetDSP3 = &DSP3_TestMemory; break; + case 0x10: SetDSP3 = &DSP3_OP10; break; + case 0x18: SetDSP3 = &DSP3_Convert; break; + case 0x1c: SetDSP3 = &DSP3_OP1C; break; + case 0x1e: SetDSP3 = &DSP3_OP1E; break; + case 0x1f: SetDSP3 = &DSP3_MemoryDump; break; + case 0x38: SetDSP3 = &DSP3_Decode; break; + case 0x3e: SetDSP3 = &DSP3_OP3E; break; + default: + return; + } + DSP3_SR = 0x0080; + DSP3_Index = 0; } } -void DSP3SetByte (uint8 byte, uint16 address) +void DSP3SetByte(uint8 byte, uint16 address) { - if (address < DSP0.boundary) - { - if (DSP3.SR & 0x04) + if (address < DSP1.boundary) + { + if (DSP3_SR & 0x04) { - DSP3.DR = (DSP3.DR & 0xff00) + byte; + DSP3_DR = (DSP3_DR & 0xff00) + byte; (*SetDSP3)(); } else { - DSP3.SR ^= 0x10; + DSP3_SR ^= 0x10; - if (DSP3.SR & 0x10) - DSP3.DR = (DSP3.DR & 0xff00) + byte; + if (DSP3_SR & 0x10) + DSP3_DR = (DSP3_DR & 0xff00) + byte; else { - DSP3.DR = (DSP3.DR & 0x00ff) + (byte << 8); + DSP3_DR = (DSP3_DR & 0x00ff) + (byte << 8); (*SetDSP3)(); } } } } -uint8 DSP3GetByte (uint16 address) +uint8 DSP3GetByte(uint16 address) { - if (address < DSP0.boundary) - { - uint8 byte; + if (address < DSP1.boundary) + { + uint8 byte; - if (DSP3.SR & 0x04) + if (DSP3_SR & 0x04) { - byte = (uint8) DSP3.DR; + byte = (uint8) DSP3_DR; (*SetDSP3)(); } else { - DSP3.SR ^= 0x10; + DSP3_SR ^= 0x10; - if (DSP3.SR & 0x10) - byte = (uint8) (DSP3.DR); + if (DSP3_SR & 0x10) + byte = (uint8) (DSP3_DR); else { - byte = (uint8) (DSP3.DR >> 8); + byte = (uint8) (DSP3_DR >> 8); (*SetDSP3)(); } } - return (byte); + return byte; } - return (uint8) DSP3.SR; + return (uint8) DSP3_SR; } diff --git a/source/snes9x/dsp4.cpp b/source/snes9x/dsp4.cpp deleted file mode 100644 index afb415f..0000000 --- a/source/snes9x/dsp4.cpp +++ /dev/null @@ -1,2204 +0,0 @@ -/********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com) - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley, - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001-2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight, - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound DSP emulator code is derived from SNEeSe and OpenSPC: - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2007 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -**********************************************************************************/ - -/* - Due recognition and credit are given on Overload's DSP website. - Thank those contributors for their hard work on this chip. - - Fixed-point math reminder: - [sign, integer, fraction] - 1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0') - 1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0') -*/ - - -#include "snes9x.h" -#include "memmap.h" - -#define DSP4_CLEAR_OUT() \ - { DSP4.out_count = 0; DSP4.out_index = 0; } - -#define DSP4_WRITE_BYTE(d) \ - { WRITE_WORD(DSP4.output + DSP4.out_count, (d)); DSP4.out_count++; } - -#define DSP4_WRITE_WORD(d) \ - { WRITE_WORD(DSP4.output + DSP4.out_count, (d)); DSP4.out_count += 2; } - -#ifndef MSB_FIRST -#define DSP4_WRITE_16_WORD(d) \ - { memcpy(DSP4.output + DSP4.out_count, (d), 32); DSP4.out_count += 32; } -#else -#define DSP4_WRITE_16_WORD(d) \ - { for (int p = 0; p < 16; p++) DSP4_WRITE_WORD((d)[p]); } -#endif - -// used to wait for dsp i/o -#define DSP4_WAIT(x) \ - DSP4.in_index = 0; DSP4.Logic = (x); return - -// 1.7.8 -> 1.15.16 -#define SEX78(a) (((int32) ((int16) (a))) << 8) - -// 1.15.0 -> 1.15.16 -#define SEX16(a) (((int32) ((int16) (a))) << 16) - -static int16 DSP4_READ_WORD (void); -static int32 DSP4_READ_DWORD (void); -static int16 DSP4_Inverse (int16); -static void DSP4_Multiply (int16, int16, int32 *); -static void DSP4_OP01 (void); -static void DSP4_OP03 (void); -static void DSP4_OP05 (void); -static void DSP4_OP06 (void); -static void DSP4_OP07 (void); -static void DSP4_OP08 (void); -static void DSP4_OP09 (void); -static void DSP4_OP0A (int16, int16 *, int16 *, int16 *, int16 *); -static void DSP4_OP0B (bool8 *, int16, int16, int16, bool8, bool8); -static void DSP4_OP0D (void); -static void DSP4_OP0E (void); -static void DSP4_OP0F (void); -static void DSP4_OP10 (void); -static void DSP4_OP11 (int16, int16, int16, int16, int16 *); -static void DSP4_SetByte (void); -static void DSP4_GetByte (void); - - -static int16 DSP4_READ_WORD (void) -{ - int16 out; - - out = READ_WORD(DSP4.parameters + DSP4.in_index); - DSP4.in_index += 2; - - return (out); -} - -static int32 DSP4_READ_DWORD (void) -{ - int32 out; - - out = READ_DWORD(DSP4.parameters + DSP4.in_index); - DSP4.in_index += 4; - - return (out); -} - -static int16 DSP4_Inverse (int16 value) -{ - // Attention: This lookup table is not verified - const uint16 div_lut[64] = - { - 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, - 0x1000, 0x0e38, 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, - 0x0800, 0x0787, 0x071c, 0x06bc, 0x0666, 0x0618, 0x05d1, 0x0590, - 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469, 0x0444, 0x0421, - 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348, - 0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, - 0x02aa, 0x029c, 0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, - 0x0249, 0x023e, 0x0234, 0x022b, 0x0222, 0x0219, 0x0210, 0x0208 - }; - - // saturate bounds - if (value < 0) - value = 0; - if (value > 63) - value = 63; - - return (div_lut[value]); -} - -static void DSP4_Multiply (int16 Multiplicand, int16 Multiplier, int32 *Product) -{ - *Product = (Multiplicand * Multiplier << 1) >> 1; -} - -static void DSP4_OP01 (void) -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - case 3: goto resume3; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - DSP4.world_y = DSP4_READ_DWORD(); - DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4.poly_top[0][0] = DSP4_READ_WORD(); - DSP4.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4.viewport_bottom = DSP4_READ_WORD(); - DSP4.world_x = DSP4_READ_DWORD(); - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4.world_yofs = DSP4_READ_WORD(); - DSP4.world_dy = DSP4_READ_DWORD(); - DSP4.world_dx = DSP4_READ_DWORD(); - DSP4.distance = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4.world_xenv = DSP4_READ_DWORD(); - DSP4.world_ddy = DSP4_READ_WORD(); - DSP4.world_ddx = DSP4_READ_WORD(); - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // initial (x, y, offset) at starting raster line - DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; - DSP4.view_y1 = DSP4.world_y >> 16; - DSP4.view_xofs1 = DSP4.world_x >> 16; - DSP4.view_yofs1 = DSP4.world_yofs; - DSP4.view_turnoff_x = 0; - DSP4.view_turnoff_dx = 0; - - // first raster line - DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // perspective projection of world (x, y, scroll) points - // based on the current projection lines - DSP4.view_x2 = (((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15) + (DSP4.view_turnoff_x * DSP4.distance >> 15); - DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; - DSP4.view_xofs2 = DSP4.view_x2; - DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; - - // 1. World x-location before transformation - // 2. Viewer x-position at the next - // 3. World y-location before perspective projection - // 4. Viewer y-position below the horizon - // 5. Number of raster lines drawn in this iteration - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); - DSP4_WRITE_WORD(DSP4.view_x2); - DSP4_WRITE_WORD(DSP4.world_y >> 16); - DSP4_WRITE_WORD(DSP4.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of raster lines used - DSP4.segments = DSP4.poly_raster[0][0] - DSP4.view_y2; - - // prevent overdraw - if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) - DSP4.segments = 0; - else - DSP4.poly_raster[0][0] = DSP4.view_y2; - - // don't draw outside the window - if (DSP4.view_y2 < DSP4.poly_top[0][0]) - { - DSP4.segments = 0; - - // flush remaining raster lines - if (DSP4.view_y1 >= DSP4.poly_top[0][0]) - DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; - py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); - y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) - { - // 1. HDMA memory pointer (bg1) - // 2. vertical scroll offset ($210E) - // 3. horizontal scroll offset ($210D) - DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); - DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); - DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); - - // update memory address - DSP4.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - //////////////////////////////////////////////////// - // Post-update - - // update new viewer (x, y, scroll) to last raster line drawn - DSP4.view_x1 = DSP4.view_x2; - DSP4.view_y1 = DSP4.view_y2; - DSP4.view_xofs1 = DSP4.view_xofs2; - DSP4.view_yofs1 = DSP4.view_yofs2; - - // add deltas for projection lines - DSP4.world_dx += SEX78(DSP4.world_ddx); - DSP4.world_dy += SEX78(DSP4.world_ddy); - - // update projection lines - DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); - DSP4.world_y += DSP4.world_dy; - - // update road turnoff position - DSP4.view_turnoff_x += DSP4.view_turnoff_dx; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1); - - resume1: - - // check for termination - DSP4.distance = DSP4_READ_WORD(); - if (DSP4.distance == -0x8000) - break; - - // road turnoff - if ((uint16) DSP4.distance == 0x8001) - { - DSP4.in_count = 6; - DSP4_WAIT(2); - - resume2: - - DSP4.distance = DSP4_READ_WORD(); - DSP4.view_turnoff_x = DSP4_READ_WORD(); - DSP4.view_turnoff_dx = DSP4_READ_WORD(); - - // factor in new changes - DSP4.view_x1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); - DSP4.view_xofs1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); - - // update stepping values - DSP4.view_turnoff_x += DSP4.view_turnoff_dx; - - DSP4.in_count = 2; - DSP4_WAIT(1); - } - - // already have 2 bytes read - DSP4.in_count = 6; - DSP4_WAIT(3); - - resume3: - - // inspect inputs - DSP4.world_ddy = DSP4_READ_WORD(); - DSP4.world_ddx = DSP4_READ_WORD(); - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // no envelope here - DSP4.world_xenv = 0; - } - while (1); - - // terminate op - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP03 (void) -{ - DSP4.OAM_RowMax = 33; - memset(DSP4.OAM_Row, 0, 64); -} - -static void DSP4_OP05 (void) -{ - DSP4.OAM_index = 0; - DSP4.OAM_bits = 0; - memset(DSP4.OAM_attr, 0, 32); - DSP4.sprite_count = 0; -} - -static void DSP4_OP06 (void) -{ - DSP4_CLEAR_OUT(); - DSP4_WRITE_16_WORD(DSP4.OAM_attr); -} - -static void DSP4_OP07 (void) -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - DSP4.world_y = DSP4_READ_DWORD(); - DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4.poly_top[0][0] = DSP4_READ_WORD(); - DSP4.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4.viewport_bottom = DSP4_READ_WORD(); - DSP4.world_x = DSP4_READ_DWORD(); - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4.world_yofs = DSP4_READ_WORD(); - DSP4.distance = DSP4_READ_WORD(); - DSP4.view_y2 = DSP4_READ_WORD(); - DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_x2 = DSP4_READ_WORD(); - DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // initial (x, y, offset) at starting raster line - DSP4.view_x1 = DSP4.world_x >> 16; - DSP4.view_y1 = DSP4.world_y >> 16; - DSP4.view_xofs1 = DSP4.view_x1; - DSP4.view_yofs1 = DSP4.world_yofs; - - // first raster line - DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // add shaping - DSP4.view_x2 += DSP4.view_dx; - DSP4.view_y2 += DSP4.view_dy; - - // vertical scroll calculation - DSP4.view_xofs2 = DSP4.view_x2; - DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; - - // 1. Viewer x-position at the next - // 2. Viewer y-position below the horizon - // 3. Number of raster lines drawn in this iteration - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(DSP4.view_x2); - DSP4_WRITE_WORD(DSP4.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of raster lines used - DSP4.segments = DSP4.view_y1 - DSP4.view_y2; - - // prevent overdraw - if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) - DSP4.segments = 0; - else - DSP4.poly_raster[0][0] = DSP4.view_y2; - - // don't draw outside the window - if (DSP4.view_y2 < DSP4.poly_top[0][0]) - { - DSP4.segments = 0; - - // flush remaining raster lines - if (DSP4.view_y1 >= DSP4.poly_top[0][0]) - DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; - py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); - y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) - { - // 1. HDMA memory pointer (bg2) - // 2. vertical scroll offset ($2110) - // 3. horizontal scroll offset ($210F) - DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); - DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); - DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); - - // update memory address - DSP4.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - ///////////////////////////////////////////////////// - // Post-update - - // update new viewer (x, y, scroll) to last raster line drawn - DSP4.view_x1 = DSP4.view_x2; - DSP4.view_y1 = DSP4.view_y2; - DSP4.view_xofs1 = DSP4.view_xofs2; - DSP4.view_yofs1 = DSP4.view_yofs2; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1); - - resume1: - - // check for opcode termination - DSP4.distance = DSP4_READ_WORD(); - if (DSP4.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 10; - DSP4_WAIT(2); - - resume2: - - // inspect inputs - DSP4.view_y2 = DSP4_READ_WORD(); - DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_x2 = DSP4_READ_WORD(); - DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_yofsenv = DSP4_READ_WORD(); - } - while (1); - - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP08 (void) -{ - int16 win_left, win_right; - int16 view_x[2], view_y[2]; - int16 envelope[2][2]; - - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs for two polygons - - // clip values - DSP4.poly_clipRt[0][0] = DSP4_READ_WORD(); - DSP4.poly_clipRt[0][1] = DSP4_READ_WORD(); - DSP4.poly_clipRt[1][0] = DSP4_READ_WORD(); - DSP4.poly_clipRt[1][1] = DSP4_READ_WORD(); - - DSP4.poly_clipLf[0][0] = DSP4_READ_WORD(); - DSP4.poly_clipLf[0][1] = DSP4_READ_WORD(); - DSP4.poly_clipLf[1][0] = DSP4_READ_WORD(); - DSP4.poly_clipLf[1][1] = DSP4_READ_WORD(); - - // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // polygon centering (left, right) - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_cx[0][1] = DSP4_READ_WORD(); - DSP4.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4.poly_cx[1][1] = DSP4_READ_WORD(); - - // HDMA pointer locations - DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[0][1] = DSP4_READ_WORD(); - DSP4.poly_ptr[1][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[1][1] = DSP4_READ_WORD(); - - // starting raster line below the horizon - DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4.poly_bottom[0][1] = DSP4_READ_WORD(); - DSP4.poly_bottom[1][0] = DSP4_READ_WORD(); - DSP4.poly_bottom[1][1] = DSP4_READ_WORD(); - - // top boundary line to clip - DSP4.poly_top[0][0] = DSP4_READ_WORD(); - DSP4.poly_top[0][1] = DSP4_READ_WORD(); - DSP4.poly_top[1][0] = DSP4_READ_WORD(); - DSP4.poly_top[1][1] = DSP4_READ_WORD(); - - // unknown - // (ex. 1P = $2FC8, $0034, $FF5C, $0035) - // - // (ex. 2P = $3178, $0034, $FFCC, $0035) - // (ex. 2P = $2FC8, $0034, $FFCC, $0035) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // look at guidelines for both polygon shapes - DSP4.distance = DSP4_READ_WORD(); - view_x[0] = DSP4_READ_WORD(); - view_y[0] = DSP4_READ_WORD(); - view_x[1] = DSP4_READ_WORD(); - view_y[1] = DSP4_READ_WORD(); - - // envelope shaping guidelines (one frame only) - envelope[0][0] = DSP4_READ_WORD(); - envelope[0][1] = DSP4_READ_WORD(); - envelope[1][0] = DSP4_READ_WORD(); - envelope[1][1] = DSP4_READ_WORD(); - - // starting base values to project from - DSP4.poly_start[0] = view_x[0]; - DSP4.poly_start[1] = view_x[1]; - - // starting raster lines to begin drawing - DSP4.poly_raster[0][0] = view_y[0]; - DSP4.poly_raster[0][1] = view_y[0]; - DSP4.poly_raster[1][0] = view_y[1]; - DSP4.poly_raster[1][1] = view_y[1]; - - // starting distances - DSP4.poly_plane[0] = DSP4.distance; - DSP4.poly_plane[1] = DSP4.distance; - - // SR = 0x00 - - // re-center coordinates - win_left = DSP4.poly_cx[0][0] - view_x[0] + envelope[0][0]; - win_right = DSP4.poly_cx[0][1] - view_x[0] + envelope[0][1]; - - // saturate offscreen data for polygon #1 - if (win_left < DSP4.poly_clipLf[0][0]) - win_left = DSP4.poly_clipLf[0][0]; - if (win_left > DSP4.poly_clipRt[0][0]) - win_left = DSP4.poly_clipRt[0][0]; - if (win_right < DSP4.poly_clipLf[0][1]) - win_right = DSP4.poly_clipLf[0][1]; - if (win_right > DSP4.poly_clipRt[0][1]) - win_right = DSP4.poly_clipRt[0][1]; - - // SR = 0x80 - - // initial output for polygon #1 - DSP4_CLEAR_OUT(); - DSP4_WRITE_BYTE(win_left & 0xff); - DSP4_WRITE_BYTE(win_right & 0xff); - - do - { - int16 polygon; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1); - - resume1: - - // terminate op - DSP4.distance = DSP4_READ_WORD(); - if (DSP4.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 16; - DSP4_WAIT(2); - - resume2: - - // look at guidelines for both polygon shapes - view_x[0] = DSP4_READ_WORD(); - view_y[0] = DSP4_READ_WORD(); - view_x[1] = DSP4_READ_WORD(); - view_y[1] = DSP4_READ_WORD(); - - // envelope shaping guidelines (one frame only) - envelope[0][0] = DSP4_READ_WORD(); - envelope[0][1] = DSP4_READ_WORD(); - envelope[1][0] = DSP4_READ_WORD(); - envelope[1][1] = DSP4_READ_WORD(); - - //////////////////////////////////////////////////// - // projection begins - - // init - DSP4_CLEAR_OUT(); - - ////////////////////////////////////////////// - // solid polygon renderer - 2 shapes - - for (polygon = 0; polygon < 2; polygon++) - { - int32 left_inc, right_inc; - int16 x1_final, x2_final; - int16 env[2][2]; - int16 poly; - - // SR = 0x00 - - // # raster lines to draw - DSP4.segments = DSP4.poly_raster[polygon][0] - view_y[polygon]; - - // prevent overdraw - if (DSP4.segments > 0) - { - // bump drawing cursor - DSP4.poly_raster[polygon][0] = view_y[polygon]; - DSP4.poly_raster[polygon][1] = view_y[polygon]; - } - else - DSP4.segments = 0; - - // don't draw outside the window - if (view_y[polygon] < DSP4.poly_top[polygon][0]) - { - DSP4.segments = 0; - - // flush remaining raster lines - if (view_y[polygon] >= DSP4.poly_top[polygon][0]) - DSP4.segments = view_y[polygon] - DSP4.poly_top[polygon][0]; - } - - // SR = 0x80 - - // tell user how many raster structures to read in - DSP4_WRITE_WORD(DSP4.segments); - - // normal parameters - poly = polygon; - - ///////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - int32 w_left, w_right; - - // road turnoff selection - if ((uint16) envelope[polygon][0] == (uint16) 0xc001) - poly = 1; - else - if (envelope[polygon][1] == 0x3fff) - poly = 1; - - /////////////////////////////////////////////// - // left side of polygon - - // perspective correction on additional shaping parameters - env[0][0] = envelope[polygon][0] * DSP4.poly_plane[poly] >> 15; - env[0][1] = envelope[polygon][0] * DSP4.distance >> 15; - - // project new shapes (left side) - x1_final = view_x[poly] + env[0][0]; - x2_final = DSP4.poly_start[poly] + env[0][1]; - - // interpolate between projected points with shaping - left_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4.segments) << 1; - if (DSP4.segments == 1) - left_inc = -left_inc; - - /////////////////////////////////////////////// - // right side of polygon - - // perspective correction on additional shaping parameters - env[1][0] = envelope[polygon][1] * DSP4.poly_plane[poly] >> 15; - env[1][1] = envelope[polygon][1] * DSP4.distance >> 15; - - // project new shapes (right side) - x1_final = view_x[poly] + env[1][0]; - x2_final = DSP4.poly_start[poly] + env[1][1]; - - // interpolate between projected points with shaping - right_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4.segments) << 1; - if (DSP4.segments == 1) - right_inc = -right_inc; - - /////////////////////////////////////////////// - // update each point on the line - - w_left = SEX16(DSP4.poly_cx[polygon][0] - DSP4.poly_start[poly] + env[0][0]); - w_right = SEX16(DSP4.poly_cx[polygon][1] - DSP4.poly_start[poly] + env[1][0]); - - // update distance drawn into world - DSP4.poly_plane[polygon] = DSP4.distance; - - // rasterize line - for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) - { - int16 x_left, x_right; - - // project new coordinates - w_left += left_inc; - w_right += right_inc; - - // grab integer portion, drop fraction (no rounding) - x_left = w_left >> 16; - x_right = w_right >> 16; - - // saturate offscreen data - if (x_left < DSP4.poly_clipLf[polygon][0]) - x_left = DSP4.poly_clipLf[polygon][0]; - if (x_left > DSP4.poly_clipRt[polygon][0]) - x_left = DSP4.poly_clipRt[polygon][0]; - if (x_right < DSP4.poly_clipLf[polygon][1]) - x_right = DSP4.poly_clipLf[polygon][1]; - if (x_right > DSP4.poly_clipRt[polygon][1]) - x_right = DSP4.poly_clipRt[polygon][1]; - - // 1. HDMA memory pointer - // 2. Left window position ($2126/$2128) - // 3. Right window position ($2127/$2129) - DSP4_WRITE_WORD(DSP4.poly_ptr[polygon][0]); - DSP4_WRITE_BYTE(x_left & 0xff); - DSP4_WRITE_BYTE(x_right & 0xff); - - // update memory pointers - DSP4.poly_ptr[polygon][0] -= 4; - DSP4.poly_ptr[polygon][1] -= 4; - } // end rasterize line - } - - //////////////////////////////////////////////// - // Post-update - - // new projection spot to continue rasterizing from - DSP4.poly_start[polygon] = view_x[poly]; - } // end polygon rasterizer - } - while (1); - - // unknown output - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(0); - - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP09 (void) -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - case 3: goto resume3; break; - case 4: goto resume4; break; - case 5: goto resume5; break; - case 6: goto resume6; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // grab screen information - DSP4.viewport_cx = DSP4_READ_WORD(); - DSP4.viewport_cy = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4.viewport_left = DSP4_READ_WORD(); - DSP4.viewport_right = DSP4_READ_WORD(); - DSP4.viewport_top = DSP4_READ_WORD(); - DSP4.viewport_bottom = DSP4_READ_WORD(); - - // starting raster line below the horizon - DSP4.poly_bottom[0][0] = DSP4.viewport_bottom - DSP4.viewport_cy; - DSP4.poly_raster[0][0] = 0x100; - - do - { - //////////////////////////////////////////////////// - // check for new sprites - - DSP4.in_count = 4; - DSP4_WAIT(1); - - resume1: - - //////////////////////////////////////////////// - // raster overdraw check - - DSP4.raster = DSP4_READ_WORD(); - - // continue updating the raster line where overdraw begins - if (DSP4.raster < DSP4.poly_raster[0][0]) - { - DSP4.sprite_clipy = DSP4.viewport_bottom - (DSP4.poly_bottom[0][0] - DSP4.raster); - DSP4.poly_raster[0][0] = DSP4.raster; - } - - ///////////////////////////////////////////////// - // identify sprite - - // op termination - DSP4.distance = DSP4_READ_WORD(); - if (DSP4.distance == -0x8000) - goto terminate; - - // no sprite - if (DSP4.distance == 0x0000) - continue; - - //////////////////////////////////////////////////// - // process projection information - - // vehicle sprite - if ((uint16) DSP4.distance == 0x9000) - { - int16 car_left, car_right, car_back; - int16 impact_left, impact_back; - int16 world_spx, world_spy; - int16 view_spx, view_spy; - uint16 energy; - - // we already have 4 bytes we want - DSP4.in_count = 14; - DSP4_WAIT(2); - - resume2: - - // filter inputs - energy = DSP4_READ_WORD(); - impact_back = DSP4_READ_WORD(); - car_back = DSP4_READ_WORD(); - impact_left = DSP4_READ_WORD(); - car_left = DSP4_READ_WORD(); - DSP4.distance = DSP4_READ_WORD(); - car_right = DSP4_READ_WORD(); - - // calculate car's world (x, y) values - world_spx = car_right - car_left; - world_spy = car_back; - - // add in collision vector [needs bit-twiddling] - world_spx -= energy * (impact_left - car_left) >> 16; - world_spy -= energy * (car_back - impact_back) >> 16; - - // perspective correction for world (x, y) - view_spx = world_spx * DSP4.distance >> 15; - view_spy = world_spy * DSP4.distance >> 15; - - // convert to screen values - DSP4.sprite_x = DSP4.viewport_cx + view_spx; - DSP4.sprite_y = DSP4.viewport_bottom - (DSP4.poly_bottom[0][0] - view_spy); - - // make the car's (x)-coordinate available - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(world_spx); - - // grab a few remaining vehicle values - DSP4.in_count = 4; - DSP4_WAIT(3); - - resume3: - - // add vertical lift factor - DSP4.sprite_y += DSP4_READ_WORD(); - } - // terrain sprite - else - { - int16 world_spx, world_spy; - int16 view_spx, view_spy; - - // we already have 4 bytes we want - DSP4.in_count = 10; - DSP4_WAIT(4); - - resume4: - - // sort loop inputs - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_raster[0][1] = DSP4_READ_WORD(); - world_spx = DSP4_READ_WORD(); - world_spy = DSP4_READ_WORD(); - - // compute base raster line from the bottom - DSP4.segments = DSP4.poly_bottom[0][0] - DSP4.raster; - - // perspective correction for world (x, y) - view_spx = world_spx * DSP4.distance >> 15; - view_spy = world_spy * DSP4.distance >> 15; - - // convert to screen values - DSP4.sprite_x = DSP4.viewport_cx + view_spx - DSP4.poly_cx[0][0]; - DSP4.sprite_y = DSP4.viewport_bottom - DSP4.segments + view_spy; - } - - // default sprite size: 16x16 - DSP4.sprite_size = 1; - DSP4.sprite_attr = DSP4_READ_WORD(); - - //////////////////////////////////////////////////// - // convert tile data to SNES OAM format - - do - { - int16 sp_x, sp_y, sp_attr, sp_dattr; - int16 sp_dx, sp_dy; - int16 pixels; - uint16 header; - bool8 draw; - - DSP4.in_count = 2; - DSP4_WAIT(5); - - resume5: - - draw = TRUE; - - // opcode termination - DSP4.raster = DSP4_READ_WORD(); - if (DSP4.raster == -0x8000) - goto terminate; - - // stop code - if (DSP4.raster == 0x0000 && !DSP4.sprite_size) - break; - - // toggle sprite size - if (DSP4.raster == 0x0000) - { - DSP4.sprite_size = !DSP4.sprite_size; - continue; - } - - // check for valid sprite header - header = DSP4.raster; - header >>= 8; - if (header != 0x20 && - header != 0x2e && // This is for attractor sprite - header != 0x40 && - header != 0x60 && - header != 0xa0 && - header != 0xc0 && - header != 0xe0) - break; - - // read in rest of sprite data - DSP4.in_count = 4; - DSP4_WAIT(6); - - resume6: - - draw = TRUE; - - ///////////////////////////////////// - // process tile data - - // sprite deltas - sp_dattr = DSP4.raster; - sp_dy = DSP4_READ_WORD(); - sp_dx = DSP4_READ_WORD(); - - // update coordinates to screen space - sp_x = DSP4.sprite_x + sp_dx; - sp_y = DSP4.sprite_y + sp_dy; - - // update sprite nametable/attribute information - sp_attr = DSP4.sprite_attr + sp_dattr; - - // allow partially visibile tiles - pixels = DSP4.sprite_size ? 15 : 7; - - DSP4_CLEAR_OUT(); - - // transparent tile to clip off parts of a sprite (overdraw) - if (DSP4.sprite_clipy - pixels <= sp_y && sp_y <= DSP4.sprite_clipy && sp_x >= DSP4.viewport_left - pixels && sp_x <= DSP4.viewport_right && DSP4.sprite_clipy >= DSP4.viewport_top - pixels && DSP4.sprite_clipy <= DSP4.viewport_bottom) - DSP4_OP0B(&draw, sp_x, DSP4.sprite_clipy, 0x00EE, DSP4.sprite_size, 0); - - // normal sprite tile - if (sp_x >= DSP4.viewport_left - pixels && sp_x <= DSP4.viewport_right && sp_y >= DSP4.viewport_top - pixels && sp_y <= DSP4.viewport_bottom && sp_y <= DSP4.sprite_clipy) - DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, DSP4.sprite_size, 0); - - // no following OAM data - DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1); - } - while (1); - } - while (1); - - terminate: - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP0A (int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4) -{ - const uint16 OP0A_Values[16] = - { - 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, - 0xfe80, 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 - }; - - *o4 = OP0A_Values[(n2 & 0x000f)]; - *o3 = OP0A_Values[(n2 & 0x00f0) >> 4]; - *o2 = OP0A_Values[(n2 & 0x0f00) >> 8]; - *o1 = OP0A_Values[(n2 & 0xf000) >> 12]; -} - -static void DSP4_OP0B (bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop) -{ - int16 Row1, Row2; - - // SR = 0x00 - - // align to nearest 8-pixel row - Row1 = (sp_y >> 3) & 0x1f; - Row2 = (Row1 + 1) & 0x1f; - - // check boundaries - if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))) - *draw = 0; - - if (size) - { - if (DSP4.OAM_Row[Row1] + 1 >= DSP4.OAM_RowMax) - *draw = 0; - if (DSP4.OAM_Row[Row2] + 1 >= DSP4.OAM_RowMax) - *draw = 0; - } - else - { - if (DSP4.OAM_Row[Row1] >= DSP4.OAM_RowMax) - *draw = 0; - } - - // emulator fail-safe (unknown if this really exists) - if (DSP4.sprite_count >= 128) - *draw = 0; - - // SR = 0x80 - - if (*draw) - { - // Row tiles - if (size) - { - DSP4.OAM_Row[Row1] += 2; - DSP4.OAM_Row[Row2] += 2; - } - else - DSP4.OAM_Row[Row1]++; - - // yield OAM output - DSP4_WRITE_WORD(1); - - // pack OAM data: x, y, name, attr - DSP4_WRITE_BYTE(sp_x & 0xff); - DSP4_WRITE_BYTE(sp_y & 0xff); - DSP4_WRITE_WORD(sp_attr); - - DSP4.sprite_count++; - - // OAM: size, msb data - // save post-oam table data for future retrieval - DSP4.OAM_attr[DSP4.OAM_index] |= ((sp_x < 0 || sp_x > 255) << DSP4.OAM_bits); - DSP4.OAM_bits++; - - DSP4.OAM_attr[DSP4.OAM_index] |= (size << DSP4.OAM_bits); - DSP4.OAM_bits++; - - // move to next byte in buffer - if (DSP4.OAM_bits == 16) - { - DSP4.OAM_bits = 0; - DSP4.OAM_index++; - } - } - else - if (stop) - // yield no OAM output - DSP4_WRITE_WORD(0); -} - -static void DSP4_OP0D (void) -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - DSP4.world_y = DSP4_READ_DWORD(); - DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4.poly_top[0][0] = DSP4_READ_WORD(); - DSP4.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4.viewport_bottom = DSP4_READ_WORD(); - DSP4.world_x = DSP4_READ_DWORD(); - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4.world_yofs = DSP4_READ_WORD(); - DSP4.world_dy = DSP4_READ_DWORD(); - DSP4.world_dx = DSP4_READ_DWORD(); - DSP4.distance = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4.world_xenv = SEX78(DSP4_READ_WORD()); - DSP4.world_ddy = DSP4_READ_WORD(); - DSP4.world_ddx = DSP4_READ_WORD(); - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // initial (x, y, offset) at starting raster line - DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; - DSP4.view_y1 = DSP4.world_y >> 16; - DSP4.view_xofs1 = DSP4.world_x >> 16; - DSP4.view_yofs1 = DSP4.world_yofs; - - // first raster line - DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // perspective projection of world (x, y, scroll) points - // based on the current projection lines - DSP4.view_x2 = (((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15) + (DSP4.view_turnoff_x * DSP4.distance >> 15); - DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; - DSP4.view_xofs2 = DSP4.view_x2; - DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; - - // 1. World x-location before transformation - // 2. Viewer x-position at the current - // 3. World y-location before perspective projection - // 4. Viewer y-position below the horizon - // 5. Number of raster lines drawn in this iteration - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); - DSP4_WRITE_WORD(DSP4.view_x2); - DSP4_WRITE_WORD(DSP4.world_y >> 16); - DSP4_WRITE_WORD(DSP4.view_y2); - - ////////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of raster lines used - DSP4.segments = DSP4.view_y1 - DSP4.view_y2; - - // prevent overdraw - if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) - DSP4.segments = 0; - else - DSP4.poly_raster[0][0] = DSP4.view_y2; - - // don't draw outside the window - if (DSP4.view_y2 < DSP4.poly_top[0][0]) - { - DSP4.segments = 0; - - // flush remaining raster lines - if (DSP4.view_y1 >= DSP4.poly_top[0][0]) - DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4.segments); - - ////////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; - py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); - y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) - { - // 1. HDMA memory pointer (bg1) - // 2. vertical scroll offset ($210E) - // 3. horizontal scroll offset ($210D) - DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); - DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); - DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); - - // update memory address - DSP4.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - ///////////////////////////////////////////////////// - // Post-update - - // update new viewer (x, y, scroll) to last raster line drawn - DSP4.view_x1 = DSP4.view_x2; - DSP4.view_y1 = DSP4.view_y2; - DSP4.view_xofs1 = DSP4.view_xofs2; - DSP4.view_yofs1 = DSP4.view_yofs2; - - // add deltas for projection lines - DSP4.world_dx += SEX78(DSP4.world_ddx); - DSP4.world_dy += SEX78(DSP4.world_ddy); - - // update projection lines - DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); - DSP4.world_y += DSP4.world_dy; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1); - - resume1: - - // inspect input - DSP4.distance = DSP4_READ_WORD(); - - // terminate op - if (DSP4.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 6; - DSP4_WAIT(2); - - resume2: - - // inspect inputs - DSP4.world_ddy = DSP4_READ_WORD(); - DSP4.world_ddx = DSP4_READ_WORD(); - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // no envelope here - DSP4.world_xenv = 0; - } - while (1); - - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP0E (void) -{ - DSP4.OAM_RowMax = 16; - memset(DSP4.OAM_Row, 0, 64); -} - -static void DSP4_OP0F (void) -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - case 3: goto resume3; break; - case 4: goto resume4; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - DSP4_READ_WORD(); // 0x0000 - DSP4.world_y = DSP4_READ_DWORD(); - DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4.poly_top[0][0] = DSP4_READ_WORD(); - DSP4.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4.viewport_bottom = DSP4_READ_WORD(); - DSP4.world_x = DSP4_READ_DWORD(); - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4.world_yofs = DSP4_READ_WORD(); - DSP4.world_dy = DSP4_READ_DWORD(); - DSP4.world_dx = DSP4_READ_DWORD(); - DSP4.distance = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4.world_xenv = DSP4_READ_DWORD(); - DSP4.world_ddy = DSP4_READ_WORD(); - DSP4.world_ddx = DSP4_READ_WORD(); - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // initial (x, y, offset) at starting raster line - DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; - DSP4.view_y1 = DSP4.world_y >> 16; - DSP4.view_xofs1 = DSP4.world_x >> 16; - DSP4.view_yofs1 = DSP4.world_yofs; - DSP4.view_turnoff_x = 0; - DSP4.view_turnoff_dx = 0; - - // first raster line - DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // perspective projection of world (x, y, scroll) points - // based on the current projection lines - DSP4.view_x2 = ((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15; - DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; - DSP4.view_xofs2 = DSP4.view_x2; - DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; - - // 1. World x-location before transformation - // 2. Viewer x-position at the next - // 3. World y-location before perspective projection - // 4. Viewer y-position below the horizon - // 5. Number of raster lines drawn in this iteration - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); - DSP4_WRITE_WORD(DSP4.view_x2); - DSP4_WRITE_WORD(DSP4.world_y >> 16); - DSP4_WRITE_WORD(DSP4.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of raster lines used - DSP4.segments = DSP4.poly_raster[0][0] - DSP4.view_y2; - - // prevent overdraw - if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) - DSP4.segments = 0; - else - DSP4.poly_raster[0][0] = DSP4.view_y2; - - // don't draw outside the window - if (DSP4.view_y2 < DSP4.poly_top[0][0]) - { - DSP4.segments = 0; - - // flush remaining raster lines - if (DSP4.view_y1 >= DSP4.poly_top[0][0]) - DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - for (DSP4.lcv = 0; DSP4.lcv < 4; DSP4.lcv++) - { - // grab inputs - DSP4.in_count = 4; - DSP4_WAIT(1); - - resume1: - - for (;;) - { - int16 dist; - int16 color, red, green, blue; - - dist = DSP4_READ_WORD(); - color = DSP4_READ_WORD(); - - // U1+B5+G5+R5 - red = color & 0x1f; - green = (color >> 5) & 0x1f; - blue = (color >> 10) & 0x1f; - - // dynamic lighting - red = (red * dist >> 15) & 0x1f; - green = (green * dist >> 15) & 0x1f; - blue = (blue * dist >> 15) & 0x1f; - color = red | (green << 5) | (blue << 10); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(color); - - break; - } - } - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; - py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); - y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) - { - // 1. HDMA memory pointer - // 2. vertical scroll offset ($210E) - // 3. horizontal scroll offset ($210D) - DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); - DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); - DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); - - // update memory address - DSP4.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - //////////////////////////////////////////////////// - // Post-update - - // update new viewer (x, y, scroll) to last raster line drawn - DSP4.view_x1 = DSP4.view_x2; - DSP4.view_y1 = DSP4.view_y2; - DSP4.view_xofs1 = DSP4.view_xofs2; - DSP4.view_yofs1 = DSP4.view_yofs2; - - // add deltas for projection lines - DSP4.world_dx += SEX78(DSP4.world_ddx); - DSP4.world_dy += SEX78(DSP4.world_ddy); - - // update projection lines - DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); - DSP4.world_y += DSP4.world_dy; - - // update road turnoff position - DSP4.view_turnoff_x += DSP4.view_turnoff_dx; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(2); - - resume2: - - // check for termination - DSP4.distance = DSP4_READ_WORD(); - if (DSP4.distance == -0x8000) - break; - - // road splice - if ((uint16) DSP4.distance == 0x8001) - { - DSP4.in_count = 6; - DSP4_WAIT(3); - - resume3: - - DSP4.distance = DSP4_READ_WORD(); - DSP4.view_turnoff_x = DSP4_READ_WORD(); - DSP4.view_turnoff_dx = DSP4_READ_WORD(); - - // factor in new changes - DSP4.view_x1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); - DSP4.view_xofs1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); - - // update stepping values - DSP4.view_turnoff_x += DSP4.view_turnoff_dx; - - DSP4.in_count = 2; - DSP4_WAIT(2); - } - - // already have 2 bytes in queue - DSP4.in_count = 6; - DSP4_WAIT(4); - - resume4: - - // inspect inputs - DSP4.world_ddy = DSP4_READ_WORD(); - DSP4.world_ddx = DSP4_READ_WORD(); - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // no envelope here - DSP4.world_xenv = 0; - } - while (1); - - // terminate op - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP10 (void) -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4.Logic) - { - case 1: goto resume1; break; - case 2: goto resume2; break; - case 3: goto resume3; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - DSP4_READ_WORD(); // 0x0000 - DSP4.world_y = DSP4_READ_DWORD(); - DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4.poly_top[0][0] = DSP4_READ_WORD(); - DSP4.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4.viewport_bottom = DSP4_READ_WORD(); - DSP4.world_x = DSP4_READ_DWORD(); - DSP4.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4.world_yofs = DSP4_READ_WORD(); - DSP4.distance = DSP4_READ_WORD(); - DSP4.view_y2 = DSP4_READ_WORD(); - DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_x2 = DSP4_READ_WORD(); - DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_yofsenv = DSP4_READ_WORD(); - - // initial (x, y, offset) at starting raster line - DSP4.view_x1 = DSP4.world_x >> 16; - DSP4.view_y1 = DSP4.world_y >> 16; - DSP4.view_xofs1 = DSP4.view_x1; - DSP4.view_yofs1 = DSP4.world_yofs; - - // first raster line - DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // add shaping - DSP4.view_x2 += DSP4.view_dx; - DSP4.view_y2 += DSP4.view_dy; - - // vertical scroll calculation - DSP4.view_xofs2 = DSP4.view_x2; - DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; - - // 1. Viewer x-position at the next - // 2. Viewer y-position below the horizon - // 3. Number of raster lines drawn in this iteration - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(DSP4.view_x2); - DSP4_WRITE_WORD(DSP4.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of raster lines used - DSP4.segments = DSP4.view_y1 - DSP4.view_y2; - - // prevent overdraw - if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) - DSP4.segments = 0; - else - DSP4.poly_raster[0][0] = DSP4.view_y2; - - // don't draw outside the window - if (DSP4.view_y2 < DSP4.poly_top[0][0]) - { - DSP4.segments = 0; - - // flush remaining raster lines - if (DSP4.view_y1 >= DSP4.poly_top[0][0]) - DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - for (DSP4.lcv = 0; DSP4.lcv < 4; DSP4.lcv++) - { - // grab inputs - DSP4.in_count = 4; - DSP4_WAIT(1); - - resume1: - - for (;;) - { - int16 dist; - int16 color, red, green, blue; - - dist = DSP4_READ_WORD(); - color = DSP4_READ_WORD(); - - // U1+B5+G5+R5 - red = color & 0x1f; - green = (color >> 5) & 0x1f; - blue = (color >> 10) & 0x1f; - - // dynamic lighting - red = (red * dist >> 15) & 0x1f; - green = (green * dist >> 15) & 0x1f; - blue = (blue * dist >> 15) & 0x1f; - color = red | (green << 5) | (blue << 10); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(color); - - break; - } - } - } - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; - py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); - y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) - { - // 1. HDMA memory pointer (bg2) - // 2. vertical scroll offset ($2110) - // 3. horizontal scroll offset ($210F) - DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); - DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); - DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); - - // update memory address - DSP4.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - ///////////////////////////////////////////////////// - // Post-update - - // update new viewer (x, y, scroll) to last raster line drawn - DSP4.view_x1 = DSP4.view_x2; - DSP4.view_y1 = DSP4.view_y2; - DSP4.view_xofs1 = DSP4.view_xofs2; - DSP4.view_yofs1 = DSP4.view_yofs2; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(2); - - resume2: - - // check for opcode termination - DSP4.distance = DSP4_READ_WORD(); - if (DSP4.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 10; - DSP4_WAIT(3); - - resume3: - - // inspect inputs - DSP4.view_y2 = DSP4_READ_WORD(); - DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; - DSP4.view_x2 = DSP4_READ_WORD(); - DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; - } - while (1); - - DSP4.waiting4command = TRUE; -} - -static void DSP4_OP11 (int16 A, int16 B, int16 C, int16 D, int16 *M) -{ - // 0x155 = 341 = Horizontal Width of the Screen - *M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); -} - -static void DSP4_SetByte (void) -{ - // clear pending read - if (DSP4.out_index < DSP4.out_count) - { - DSP4.out_index++; - return; - } - - if (DSP4.waiting4command) - { - if (DSP4.half_command) - { - DSP4.command |= (DSP4.byte << 8); - DSP4.in_index = 0; - DSP4.waiting4command = FALSE; - DSP4.half_command = FALSE; - DSP4.out_count = 0; - DSP4.out_index = 0; - - DSP4.Logic = 0; - - switch (DSP4.command) - { - case 0x0000: DSP4.in_count = 4; break; - case 0x0001: DSP4.in_count = 44; break; - case 0x0003: DSP4.in_count = 0; break; - case 0x0005: DSP4.in_count = 0; break; - case 0x0006: DSP4.in_count = 0; break; - case 0x0007: DSP4.in_count = 34; break; - case 0x0008: DSP4.in_count = 90; break; - case 0x0009: DSP4.in_count = 14; break; - case 0x000a: DSP4.in_count = 6; break; - case 0x000b: DSP4.in_count = 6; break; - case 0x000d: DSP4.in_count = 42; break; - case 0x000e: DSP4.in_count = 0; break; - case 0x000f: DSP4.in_count = 46; break; - case 0x0010: DSP4.in_count = 36; break; - case 0x0011: DSP4.in_count = 8; break; - default: - DSP4.waiting4command = TRUE; - break; - } - } - else - { - DSP4.command = DSP4.byte; - DSP4.half_command = TRUE; - } - } - else - { - DSP4.parameters[DSP4.in_index] = DSP4.byte; - DSP4.in_index++; - } - - if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index) - { - // Actually execute the command - DSP4.waiting4command = TRUE; - DSP4.out_index = 0; - DSP4.in_index = 0; - - switch (DSP4.command) - { - // 16-bit multiplication - case 0x0000: - { - int16 multiplier, multiplicand; - int32 product; - - multiplier = DSP4_READ_WORD(); - multiplicand = DSP4_READ_WORD(); - - DSP4_Multiply(multiplicand, multiplier, &product); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(product); - DSP4_WRITE_WORD(product >> 16); - - break; - } - - // single-player track projection - case 0x0001: - DSP4_OP01(); - break; - - // single-player selection - case 0x0003: - DSP4_OP03(); - break; - - // clear OAM - case 0x0005: - DSP4_OP05(); - break; - - // transfer OAM - case 0x0006: - DSP4_OP06(); - break; - - // single-player track turnoff projection - case 0x0007: - DSP4_OP07(); - break; - - // solid polygon projection - case 0x0008: - DSP4_OP08(); - break; - - // sprite projection - case 0x0009: - DSP4_OP09(); - break; - - // unknown - case 0x000A: - { - DSP4_READ_WORD(); - int16 in2a = DSP4_READ_WORD(); - DSP4_READ_WORD(); - int16 out1a, out2a, out3a, out4a; - - DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(out1a); - DSP4_WRITE_WORD(out2a); - DSP4_WRITE_WORD(out3a); - DSP4_WRITE_WORD(out4a); - - break; - } - - // set OAM - case 0x000B: - { - int16 sp_x = DSP4_READ_WORD(); - int16 sp_y = DSP4_READ_WORD(); - int16 sp_attr = DSP4_READ_WORD(); - bool8 draw = TRUE; - - DSP4_CLEAR_OUT(); - DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1); - - break; - } - - // multi-player track projection - case 0x000D: - DSP4_OP0D(); - break; - - // multi-player selection - case 0x000E: - DSP4_OP0E(); - break; - - // single-player track projection with lighting - case 0x000F: - DSP4_OP0F(); - break; - - // single-player track turnoff projection with lighting - case 0x0010: - DSP4_OP10(); - break; - - // unknown: horizontal mapping command - case 0x0011: - { - int16 a, b, c, d, m; - - d = DSP4_READ_WORD(); - c = DSP4_READ_WORD(); - b = DSP4_READ_WORD(); - a = DSP4_READ_WORD(); - - DSP4_OP11(a, b, c, d, &m); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(m); - - break; - } - - default: - break; - } - } -} - -static void DSP4_GetByte (void) -{ - if (DSP4.out_count) - { - DSP4.byte = (uint8) DSP4.output[DSP4.out_index & 0x1FF]; - - DSP4.out_index++; - if (DSP4.out_count == DSP4.out_index) - DSP4.out_count = 0; - } - else - DSP4.byte = 0xff; -} - -void DSP4SetByte (uint8 byte, uint16 address) -{ - if (address < DSP0.boundary) - { - DSP4.byte = byte; - DSP4.address = address; - DSP4_SetByte(); - } -} - -uint8 DSP4GetByte (uint16 address) -{ - if (address < DSP0.boundary) - { - DSP4.address = address; - DSP4_GetByte(); - return (DSP4.byte); - } - - return (0x80); -} diff --git a/source/snes9x/dsp4emu.c.inc b/source/snes9x/dsp4emu.c.inc new file mode 100644 index 0000000..2a65842 --- /dev/null +++ b/source/snes9x/dsp4emu.c.inc @@ -0,0 +1,2396 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#include "snes9x.h" +#include "memmap.h" +#include + + + +/* +Due recognition and credit are given on Overload's DSP website. +Thank those contributors for their hard work on this chip. + + +Fixed-point math reminder: + +[sign, integer, fraction] +1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0') +1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0') +*/ + +typedef struct +{ + bool8 waiting4command; + bool8 half_command; + uint16 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; +} SDSP4; + +SDSP4 DSP4; + +//Todo: get all of this into a struct for easy save stating + +// op control +int8 DSP4_Logic; // controls op flow + + +// projection format +int16 lcv; // loop-control variable +int16 distance; // z-position into virtual world +int16 raster; // current raster line +int16 segments; // number of raster lines drawn + +// 1.15.16 or 1.15.0 [sign, integer, fraction] +int32 world_x; // line of x-projection in world +int32 world_y; // line of y-projection in world +int32 world_dx; // projection line x-delta +int32 world_dy; // projection line y-delta +int16 world_ddx; // x-delta increment +int16 world_ddy; // y-delta increment +int32 world_xenv; // world x-shaping factor +int16 world_yofs; // world y-vertical scroll + +int16 view_x1; // current viewer-x +int16 view_y1; // current viewer-y +int16 view_x2; // future viewer-x +int16 view_y2; // future viewer-y +int16 view_dx; // view x-delta factor +int16 view_dy; // view y-delta factor +int16 view_xofs1; // current viewer x-vertical scroll +int16 view_yofs1; // current viewer y-vertical scroll +int16 view_xofs2; // future viewer x-vertical scroll +int16 view_yofs2; // future viewer y-vertical scroll +int16 view_yofsenv; // y-scroll shaping factor +int16 view_turnoff_x; // road turnoff data +int16 view_turnoff_dx; // road turnoff delta factor + + +// drawing area + +int16 viewport_cx; // x-center of viewport window +int16 viewport_cy; // y-center of render window +int16 viewport_left; // x-left of viewport +int16 viewport_right; // x-right of viewport +int16 viewport_top; // y-top of viewport +int16 viewport_bottom; // y-bottom of viewport + + +// sprite structure + +int16 sprite_x; // projected x-pos of sprite +int16 sprite_y; // projected y-pos of sprite +int16 sprite_attr; // obj attributes +bool8 sprite_size; // sprite size: 8x8 or 16x16 +int16 sprite_clipy; // visible line to clip pixels off +int16 sprite_count; + + +// generic projection variables designed for +// two solid polygons + two polygon sides + +int16 poly_clipLf[2][2]; // left clip boundary +int16 poly_clipRt[2][2]; // right clip boundary +int16 poly_ptr[2][2]; // HDMA structure pointers +int16 poly_raster[2][2]; // current raster line below horizon +int16 poly_top[2][2]; // top clip boundary +int16 poly_bottom[2][2]; // bottom clip boundary +int16 poly_cx[2][2]; // center for left/right points +int16 poly_start[2]; // current projection points +int16 poly_plane[2]; // previous z-plane distance + + +// OAM +int16 OAM_attr[16]; // OAM (size,MSB) data +int16 OAM_index; // index into OAM table +int16 OAM_bits; // offset into OAM table + +int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row) +int16 OAM_Row[32]; // current number of tiles per row + +////////////////////////////////////////////////////////////// + +// input protocol + +static int16 DSP4_READ_WORD() +{ + int16 out; + + out = READ_WORD(DSP4.parameters + DSP4.in_index); + DSP4.in_index += 2; + + return out; +} + +static int32 DSP4_READ_DWORD() +{ + int32 out; + + out = READ_DWORD(DSP4.parameters + DSP4.in_index); + DSP4.in_index += 4; + + return out; +} + + +////////////////////////////////////////////////////////////// + +// output protocol + +#define DSP4_CLEAR_OUT() \ +{ DSP4.out_count = 0; DSP4.out_index = 0; } + +#define DSP4_WRITE_BYTE( d ) \ +{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count++; } + +#define DSP4_WRITE_WORD( d ) \ +{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count += 2; } + +#ifndef MSB_FIRST +#define DSP4_WRITE_16_WORD( d ) \ +{ memcpy(DSP4.output + DSP4.out_count, ( d ), 32); DSP4.out_count += 32; } +#else +#define DSP4_WRITE_16_WORD( d ) \ +{ for (int p = 0; p < 16; p++) DSP4_WRITE_WORD((d)[p]); } +#endif + +#ifdef PRINT_OP +#define DSP4_WRITE_DEBUG( x, d ) \ + WRITE_WORD( nop + x, d ); +#endif + +#ifdef DEBUG_DSP +#define DSP4_WRITE_DEBUG( x, d ) \ + WRITE_WORD( nop + x, d ); +#endif + +////////////////////////////////////////////////////////////// + +// used to wait for dsp i/o + +#define DSP4_WAIT( x ) \ + DSP4.in_index = 0; DSP4_Logic = x; return; + +////////////////////////////////////////////////////////////// + +// 1.7.8 -> 1.15.16 +#define SEX78( a ) ( ( (int32) ( (int16) (a) ) ) << 8 ) + +// 1.15.0 -> 1.15.16 +#define SEX16( a ) ( ( (int32) ( (int16) (a) ) ) << 16 ) + +#ifdef PRINT_OP +#define U16( a ) ( (uint16) ( a ) ) +#endif + +#ifdef DEBUG_DSP +#define U16( a ) ( (uint16) ( a ) ) +#endif + +////////////////////////////////////////////////////////////// + +// Attention: This lookup table is not verified +const uint16 div_lut[64] = { 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, 0x1000, 0x0e38, + 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, 0x0800, 0x0787, 0x071c, 0x06bc, + 0x0666, 0x0618, 0x05d1, 0x0590, 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469, + 0x0444, 0x0421, 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348, + 0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, 0x02aa, 0x029c, + 0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, 0x0249, 0x023e, 0x0234, 0x022b, + 0x0222, 0x0219, 0x0210, 0x0208, }; + +int16 DSP4_Inverse(int16 value) +{ + // saturate bounds + if (value < 0) + { + value = 0; + } + if (value > 63) + { + value = 63; + } + + return div_lut[value]; +} + +////////////////////////////////////////////////////////////// + +// Prototype +void DSP4_OP0B(bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop); + +////////////////////////////////////////////////////////////// + +// OP00 +void DSP4_Multiply(int16 Multiplicand, int16 Multiplier, int32 *Product) +{ + *Product = (Multiplicand * Multiplier << 1) >> 1; +} + +////////////////////////////////////////////////////////////// + + +void DSP4_OP01() +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + case 3: + goto resume3; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + world_y = DSP4_READ_DWORD(); + poly_bottom[0][0] = DSP4_READ_WORD(); + poly_top[0][0] = DSP4_READ_WORD(); + poly_cx[1][0] = DSP4_READ_WORD(); + viewport_bottom = DSP4_READ_WORD(); + world_x = DSP4_READ_DWORD(); + poly_cx[0][0] = DSP4_READ_WORD(); + poly_ptr[0][0] = DSP4_READ_WORD(); + world_yofs = DSP4_READ_WORD(); + world_dy = DSP4_READ_DWORD(); + world_dx = DSP4_READ_DWORD(); + distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + world_xenv = DSP4_READ_DWORD(); + world_ddy = DSP4_READ_WORD(); + world_ddx = DSP4_READ_WORD(); + view_yofsenv = DSP4_READ_WORD(); + + // initial (x,y,offset) at starting raster line + view_x1 = (world_x + world_xenv) >> 16; + view_y1 = world_y >> 16; + view_xofs1 = world_x >> 16; + view_yofs1 = world_yofs; + view_turnoff_x = 0; + view_turnoff_dx = 0; + + // first raster line + poly_raster[0][0] = poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x,y,scroll) points + // based on the current projection lines + view_x2 = ( ( ( world_x + world_xenv ) >> 16 ) * distance >> 15 ) + ( view_turnoff_x * distance >> 15 ); + view_y2 = (world_y >> 16) * distance >> 15; + view_xofs2 = view_x2; + view_yofs2 = (world_yofs * distance >> 15) + poly_bottom[0][0] - view_y2; + + + // 1. World x-location before transformation + // 2. Viewer x-position at the next + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((world_x + world_xenv) >> 16); + DSP4_WRITE_WORD(view_x2); + DSP4_WRITE_WORD(world_y >> 16); + DSP4_WRITE_WORD(view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + segments = poly_raster[0][0] - view_y2; + + // prevent overdraw + if (view_y2 >= poly_raster[0][0]) + segments = 0; + else + poly_raster[0][0] = view_y2; + + // don't draw outside the window + if (view_y2 < poly_top[0][0]) + { + segments = 0; + + // flush remaining raster lines + if (view_y1 >= poly_top[0][0]) + segments = view_y1 - poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (view_xofs2 - view_xofs1) * DSP4_Inverse(segments) << 1; + py_dy = (view_yofs2 - view_yofs1) * DSP4_Inverse(segments) << 1; + + // starting step values + x_scroll = SEX16(poly_cx[0][0] + view_xofs1); + y_scroll = SEX16(-viewport_bottom + view_yofs1 + view_yofsenv + poly_cx[1][0] - world_yofs); + + // SR = 0x80 + + // rasterize line + for (lcv = 0; lcv < segments; lcv++) + { + // 1. HDMA memory pointer (bg1) + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + + DSP4_WRITE_WORD(poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + + // update memory address + poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + //////////////////////////////////////////////////// + // Post-update + + // update new viewer (x,y,scroll) to last raster line drawn + view_x1 = view_x2; + view_y1 = view_y2; + view_xofs1 = view_xofs2; + view_yofs1 = view_yofs2; + + // add deltas for projection lines + world_dx += SEX78(world_ddx); + world_dy += SEX78(world_ddy); + + // update projection lines + world_x += (world_dx + world_xenv); + world_y += world_dy; + + // update road turnoff position + view_turnoff_x += view_turnoff_dx; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1) resume1 : + + // check for termination + distance = DSP4_READ_WORD(); + if (distance == -0x8000) + break; + + // road turnoff + if( (uint16) distance == 0x8001 ) + { + DSP4.in_count = 6; + DSP4_WAIT(2) resume2: + + distance = DSP4_READ_WORD(); + view_turnoff_x = DSP4_READ_WORD(); + view_turnoff_dx = DSP4_READ_WORD(); + + // factor in new changes + view_x1 += ( view_turnoff_x * distance >> 15 ); + view_xofs1 += ( view_turnoff_x * distance >> 15 ); + + // update stepping values + view_turnoff_x += view_turnoff_dx; + + DSP4.in_count = 2; + DSP4_WAIT(1) + } + + // already have 2 bytes read + DSP4.in_count = 6; + DSP4_WAIT(3) resume3 : + + // inspect inputs + world_ddy = DSP4_READ_WORD(); + world_ddx = DSP4_READ_WORD(); + view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + world_xenv = 0; + } + while (1); + + // terminate op + DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + + +void DSP4_OP03() +{ + OAM_RowMax = 33; + memset(OAM_Row, 0, 64); +} + + +////////////////////////////////////////////////////////////// + + +void DSP4_OP05() +{ + OAM_index = 0; + OAM_bits = 0; + memset(OAM_attr, 0, 32); + sprite_count = 0; +} + + +////////////////////////////////////////////////////////////// + +void DSP4_OP06() +{ + DSP4_CLEAR_OUT(); + DSP4_WRITE_16_WORD(OAM_attr); +} + +////////////////////////////////////////////////////////////// + + +void DSP4_OP07() +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + world_y = DSP4_READ_DWORD(); + poly_bottom[0][0] = DSP4_READ_WORD(); + poly_top[0][0] = DSP4_READ_WORD(); + poly_cx[1][0] = DSP4_READ_WORD(); + viewport_bottom = DSP4_READ_WORD(); + world_x = DSP4_READ_DWORD(); + poly_cx[0][0] = DSP4_READ_WORD(); + poly_ptr[0][0] = DSP4_READ_WORD(); + world_yofs = DSP4_READ_WORD(); + distance = DSP4_READ_WORD(); + view_y2 = DSP4_READ_WORD(); + view_dy = DSP4_READ_WORD() * distance >> 15; + view_x2 = DSP4_READ_WORD(); + view_dx = DSP4_READ_WORD() * distance >> 15; + view_yofsenv = DSP4_READ_WORD(); + + // initial (x,y,offset) at starting raster line + view_x1 = world_x >> 16; + view_y1 = world_y >> 16; + view_xofs1 = view_x1; + view_yofs1 = world_yofs; + + // first raster line + poly_raster[0][0] = poly_bottom[0][0]; + + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // add shaping + view_x2 += view_dx; + view_y2 += view_dy; + + // vertical scroll calculation + view_xofs2 = view_x2; + view_yofs2 = (world_yofs * distance >> 15) + poly_bottom[0][0] - view_y2; + + // 1. Viewer x-position at the next + // 2. Viewer y-position below the horizon + // 3. Number of raster lines drawn in this iteration + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(view_x2); + DSP4_WRITE_WORD(view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + segments = view_y1 - view_y2; + + // prevent overdraw + if (view_y2 >= poly_raster[0][0]) + segments = 0; + else + poly_raster[0][0] = view_y2; + + // don't draw outside the window + if (view_y2 < poly_top[0][0]) + { + segments = 0; + + // flush remaining raster lines + if (view_y1 >= poly_top[0][0]) + segments = view_y1 - poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (view_xofs2 - view_xofs1) * DSP4_Inverse(segments) << 1; + py_dy = (view_yofs2 - view_yofs1) * DSP4_Inverse(segments) << 1; + + // starting step values + x_scroll = SEX16(poly_cx[0][0] + view_xofs1); + y_scroll = SEX16(-viewport_bottom + view_yofs1 + view_yofsenv + poly_cx[1][0] - world_yofs); + + // SR = 0x80 + + // rasterize line + for (lcv = 0; lcv < segments; lcv++) + { + // 1. HDMA memory pointer (bg2) + // 2. vertical scroll offset ($2110) + // 3. horizontal scroll offset ($210F) + + DSP4_WRITE_WORD(poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x,y,scroll) to last raster line drawn + view_x1 = view_x2; + view_y1 = view_y2; + view_xofs1 = view_xofs2; + view_yofs1 = view_yofs2; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1) resume1 : + + // check for opcode termination + distance = DSP4_READ_WORD(); + if (distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 10; + DSP4_WAIT(2) resume2 : + + // inspect inputs + view_y2 = DSP4_READ_WORD(); + view_dy = DSP4_READ_WORD() * distance >> 15; + view_x2 = DSP4_READ_WORD(); + view_dx = DSP4_READ_WORD() * distance >> 15; + view_yofsenv = DSP4_READ_WORD(); + } + while (1); + + DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + +void DSP4_OP08() +{ + int16 win_left, win_right; + int16 view_x[2], view_y[2]; + int16 envelope[2][2]; + + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs for two polygons + + // clip values + poly_clipRt[0][0] = DSP4_READ_WORD(); + poly_clipRt[0][1] = DSP4_READ_WORD(); + poly_clipRt[1][0] = DSP4_READ_WORD(); + poly_clipRt[1][1] = DSP4_READ_WORD(); + + poly_clipLf[0][0] = DSP4_READ_WORD(); + poly_clipLf[0][1] = DSP4_READ_WORD(); + poly_clipLf[1][0] = DSP4_READ_WORD(); + poly_clipLf[1][1] = DSP4_READ_WORD(); + + // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // polygon centering (left,right) + poly_cx[0][0] = DSP4_READ_WORD(); + poly_cx[0][1] = DSP4_READ_WORD(); + poly_cx[1][0] = DSP4_READ_WORD(); + poly_cx[1][1] = DSP4_READ_WORD(); + + // HDMA pointer locations + poly_ptr[0][0] = DSP4_READ_WORD(); + poly_ptr[0][1] = DSP4_READ_WORD(); + poly_ptr[1][0] = DSP4_READ_WORD(); + poly_ptr[1][1] = DSP4_READ_WORD(); + + // starting raster line below the horizon + poly_bottom[0][0] = DSP4_READ_WORD(); + poly_bottom[0][1] = DSP4_READ_WORD(); + poly_bottom[1][0] = DSP4_READ_WORD(); + poly_bottom[1][1] = DSP4_READ_WORD(); + + // top boundary line to clip + poly_top[0][0] = DSP4_READ_WORD(); + poly_top[0][1] = DSP4_READ_WORD(); + poly_top[1][0] = DSP4_READ_WORD(); + poly_top[1][1] = DSP4_READ_WORD(); + + // unknown + // (ex. 1P = $2FC8, $0034, $FF5C, $0035) + // + // (ex. 2P = $3178, $0034, $FFCC, $0035) + // (ex. 2P = $2FC8, $0034, $FFCC, $0035) + + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // look at guidelines for both polygon shapes + distance = DSP4_READ_WORD(); + view_x[0] = DSP4_READ_WORD(); + view_y[0] = DSP4_READ_WORD(); + view_x[1] = DSP4_READ_WORD(); + view_y[1] = DSP4_READ_WORD(); + + // envelope shaping guidelines (one frame only) + envelope[0][0] = DSP4_READ_WORD(); + envelope[0][1] = DSP4_READ_WORD(); + envelope[1][0] = DSP4_READ_WORD(); + envelope[1][1] = DSP4_READ_WORD(); + + // starting base values to project from + poly_start[0] = view_x[0]; + poly_start[1] = view_x[1]; + + // starting raster lines to begin drawing + poly_raster[0][0] = view_y[0]; + poly_raster[0][1] = view_y[0]; + poly_raster[1][0] = view_y[1]; + poly_raster[1][1] = view_y[1]; + + // starting distances + poly_plane[0] = distance; + poly_plane[1] = distance; + + // SR = 0x00 + + // re-center coordinates + win_left = poly_cx[0][0] - view_x[0] + envelope[0][0]; + win_right = poly_cx[0][1] - view_x[0] + envelope[0][1]; + + // saturate offscreen data for polygon #1 + if (win_left < poly_clipLf[0][0]) + { + win_left = poly_clipLf[0][0]; + } + if (win_left > poly_clipRt[0][0]) + { + win_left = poly_clipRt[0][0]; + } + if (win_right < poly_clipLf[0][1]) + { + win_right = poly_clipLf[0][1]; + } + if (win_right > poly_clipRt[0][1]) + { + win_right = poly_clipRt[0][1]; + } + + // SR = 0x80 + + // initial output for polygon #1 + DSP4_CLEAR_OUT(); + DSP4_WRITE_BYTE(win_left & 0xff); + DSP4_WRITE_BYTE(win_right & 0xff); + + + do + { + int16 polygon; + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1) resume1 : + + // terminate op + distance = DSP4_READ_WORD(); + if (distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 16; + + DSP4_WAIT(2) resume2 : + + // look at guidelines for both polygon shapes + view_x[0] = DSP4_READ_WORD(); + view_y[0] = DSP4_READ_WORD(); + view_x[1] = DSP4_READ_WORD(); + view_y[1] = DSP4_READ_WORD(); + + // envelope shaping guidelines (one frame only) + envelope[0][0] = DSP4_READ_WORD(); + envelope[0][1] = DSP4_READ_WORD(); + envelope[1][0] = DSP4_READ_WORD(); + envelope[1][1] = DSP4_READ_WORD(); + + //////////////////////////////////////////////////// + // projection begins + + // init + DSP4_CLEAR_OUT(); + + + ////////////////////////////////////////////// + // solid polygon renderer - 2 shapes + + for (polygon = 0; polygon < 2; polygon++) + { + int32 left_inc, right_inc; + int16 x1_final, x2_final; + int16 env[2][2]; + int16 poly; + + // SR = 0x00 + + // # raster lines to draw + segments = poly_raster[polygon][0] - view_y[polygon]; + + // prevent overdraw + if (segments > 0) + { + // bump drawing cursor + poly_raster[polygon][0] = view_y[polygon]; + poly_raster[polygon][1] = view_y[polygon]; + } + else + segments = 0; + + // don't draw outside the window + if (view_y[polygon] < poly_top[polygon][0]) + { + segments = 0; + + // flush remaining raster lines + if (view_y[polygon] >= poly_top[polygon][0]) + segments = view_y[polygon] - poly_top[polygon][0]; + } + + // SR = 0x80 + + // tell user how many raster structures to read in + DSP4_WRITE_WORD(segments); + + // normal parameters + poly = polygon; + + ///////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + int32 win_left, win_right; + + // road turnoff selection + if( (uint16) envelope[ polygon ][ 0 ] == (uint16) 0xc001 ) + poly = 1; + else if( envelope[ polygon ][ 1 ] == 0x3fff ) + poly = 1; + + /////////////////////////////////////////////// + // left side of polygon + + // perspective correction on additional shaping parameters + env[0][0] = envelope[polygon][0] * poly_plane[poly] >> 15; + env[0][1] = envelope[polygon][0] * distance >> 15; + + // project new shapes (left side) + x1_final = view_x[poly] + env[0][0]; + x2_final = poly_start[poly] + env[0][1]; + + // interpolate between projected points with shaping + left_inc = (x2_final - x1_final) * DSP4_Inverse(segments) << 1; + if (segments == 1) + left_inc = -left_inc; + + /////////////////////////////////////////////// + // right side of polygon + + // perspective correction on additional shaping parameters + env[1][0] = envelope[polygon][1] * poly_plane[poly] >> 15;; + env[1][1] = envelope[polygon][1] * distance >> 15; + + // project new shapes (right side) + x1_final = view_x[poly] + env[1][0]; + x2_final = poly_start[poly] + env[1][1]; + + + // interpolate between projected points with shaping + right_inc = (x2_final - x1_final) * DSP4_Inverse(segments) << 1; + if (segments == 1) + right_inc = -right_inc; + + /////////////////////////////////////////////// + // update each point on the line + + win_left = SEX16(poly_cx[polygon][0] - poly_start[poly] + env[0][0]); + win_right = SEX16(poly_cx[polygon][1] - poly_start[poly] + env[1][0]); + + // update distance drawn into world + poly_plane[polygon] = distance; + + // rasterize line + for (lcv = 0; lcv < segments; lcv++) + { + int16 x_left, x_right; + + // project new coordinates + win_left += left_inc; + win_right += right_inc; + + // grab integer portion, drop fraction (no rounding) + x_left = win_left >> 16; + x_right = win_right >> 16; + + // saturate offscreen data + if (x_left < poly_clipLf[polygon][0]) + x_left = poly_clipLf[polygon][0]; + if (x_left > poly_clipRt[polygon][0]) + x_left = poly_clipRt[polygon][0]; + if (x_right < poly_clipLf[polygon][1]) + x_right = poly_clipLf[polygon][1]; + if (x_right > poly_clipRt[polygon][1]) + x_right = poly_clipRt[polygon][1]; + + // 1. HDMA memory pointer + // 2. Left window position ($2126/$2128) + // 3. Right window position ($2127/$2129) + + DSP4_WRITE_WORD(poly_ptr[polygon][0]); + DSP4_WRITE_BYTE(x_left & 0xff); + DSP4_WRITE_BYTE(x_right & 0xff); + + + // update memory pointers + poly_ptr[polygon][0] -= 4; + poly_ptr[polygon][1] -= 4; + } // end rasterize line + } + + //////////////////////////////////////////////// + // Post-update + + // new projection spot to continue rasterizing from + poly_start[polygon] = view_x[poly]; + } // end polygon rasterizer + } + while (1); + + // unknown output + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(0); + + + DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + +void DSP4_OP09() +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + case 3: + goto resume3; break; + case 4: + goto resume4; break; + case 5: + goto resume5; break; + case 6: + goto resume6; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // grab screen information + viewport_cx = DSP4_READ_WORD(); + viewport_cy = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + viewport_left = DSP4_READ_WORD(); + viewport_right = DSP4_READ_WORD(); + viewport_top = DSP4_READ_WORD(); + viewport_bottom = DSP4_READ_WORD(); + + // starting raster line below the horizon + poly_bottom[0][0] = viewport_bottom - viewport_cy; + poly_raster[0][0] = 0x100; + + do + { + //////////////////////////////////////////////////// + // check for new sprites + + DSP4.in_count = 4; + DSP4_WAIT(1) resume1 : + + //////////////////////////////////////////////// + // raster overdraw check + + raster = DSP4_READ_WORD(); + + // continue updating the raster line where overdraw begins + if (raster < poly_raster[0][0]) + { + sprite_clipy = viewport_bottom - (poly_bottom[0][0] - raster); + poly_raster[0][0] = raster; + } + + ///////////////////////////////////////////////// + // identify sprite + + // op termination + distance = DSP4_READ_WORD(); + if (distance == -0x8000) + goto terminate; + + + // no sprite + if (distance == 0x0000) + { + continue; + } + + //////////////////////////////////////////////////// + // process projection information + + // vehicle sprite + if ((uint16) distance == 0x9000) + { + int16 car_left, car_right, car_back; + int16 impact_left, impact_back; + int16 world_spx, world_spy; + int16 view_spx, view_spy; + uint16 energy; + + // we already have 4 bytes we want + DSP4.in_count = 14; + DSP4_WAIT(2) resume2 : + + // filter inputs + energy = DSP4_READ_WORD(); + impact_back = DSP4_READ_WORD(); + car_back = DSP4_READ_WORD(); + impact_left = DSP4_READ_WORD(); + car_left = DSP4_READ_WORD(); + distance = DSP4_READ_WORD(); + car_right = DSP4_READ_WORD(); + + // calculate car's world (x,y) values + world_spx = car_right - car_left; + world_spy = car_back; + + // add in collision vector [needs bit-twiddling] + world_spx -= energy * (impact_left - car_left) >> 16; + world_spy -= energy * (car_back - impact_back) >> 16; + + // perspective correction for world (x,y) + view_spx = world_spx * distance >> 15; + view_spy = world_spy * distance >> 15; + + // convert to screen values + sprite_x = viewport_cx + view_spx; + sprite_y = viewport_bottom - (poly_bottom[0][0] - view_spy); + + // make the car's (x)-coordinate available + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(world_spx); + + // grab a few remaining vehicle values + DSP4.in_count = 4; + DSP4_WAIT(3) resume3 : + + // add vertical lift factor + sprite_y += DSP4_READ_WORD(); + } + // terrain sprite + else + { + int16 world_spx, world_spy; + int16 view_spx, view_spy; + + // we already have 4 bytes we want + DSP4.in_count = 10; + DSP4_WAIT(4) resume4 : + + // sort loop inputs + poly_cx[0][0] = DSP4_READ_WORD(); + poly_raster[0][1] = DSP4_READ_WORD(); + world_spx = DSP4_READ_WORD(); + world_spy = DSP4_READ_WORD(); + + // compute base raster line from the bottom + segments = poly_bottom[0][0] - raster; + + // perspective correction for world (x,y) + view_spx = world_spx * distance >> 15; + view_spy = world_spy * distance >> 15; + + // convert to screen values + sprite_x = viewport_cx + view_spx - poly_cx[0][0]; + sprite_y = viewport_bottom - segments + view_spy; + } + + // default sprite size: 16x16 + sprite_size = 1; + sprite_attr = DSP4_READ_WORD(); + + //////////////////////////////////////////////////// + // convert tile data to SNES OAM format + + do + { + uint16 header; + + int16 sp_x, sp_y, sp_attr, sp_dattr; + int16 sp_dx, sp_dy; + int16 pixels; + + bool8 draw; + + DSP4.in_count = 2; + DSP4_WAIT(5) resume5 : + + draw = TRUE; + + // opcode termination + raster = DSP4_READ_WORD(); + if (raster == -0x8000) + goto terminate; + + // stop code + if (raster == 0x0000 && !sprite_size) + break; + + // toggle sprite size + if (raster == 0x0000) + { + sprite_size = !sprite_size; + continue; + } + + // check for valid sprite header + header = raster; + header >>= 8; + if (header != 0x20 && + header != 0x2e && //This is for attractor sprite + header != 0x40 && + header != 0x60 && + header != 0xa0 && + header != 0xc0 && + header != 0xe0) + break; + + // read in rest of sprite data + DSP4.in_count = 4; + DSP4_WAIT(6) resume6 : + + draw = TRUE; + + ///////////////////////////////////// + // process tile data + + // sprite deltas + sp_dattr = raster; + sp_dy = DSP4_READ_WORD(); + sp_dx = DSP4_READ_WORD(); + + // update coordinates to screen space + sp_x = sprite_x + sp_dx; + sp_y = sprite_y + sp_dy; + + // update sprite nametable/attribute information + sp_attr = sprite_attr + sp_dattr; + + // allow partially visibile tiles + pixels = sprite_size ? 15 : 7; + + DSP4_CLEAR_OUT(); + + // transparent tile to clip off parts of a sprite (overdraw) + if (sprite_clipy - pixels <= sp_y && + sp_y <= sprite_clipy && + sp_x >= viewport_left - pixels && + sp_x <= viewport_right && + sprite_clipy >= viewport_top - pixels && + sprite_clipy <= viewport_bottom) + { + DSP4_OP0B(&draw, sp_x, sprite_clipy, 0x00EE, sprite_size, 0); + } + + + // normal sprite tile + if (sp_x >= viewport_left - pixels && + sp_x <= viewport_right && + sp_y >= viewport_top - pixels && + sp_y <= viewport_bottom && + sp_y <= sprite_clipy) + { + DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, sprite_size, 0); + } + + + // no following OAM data + DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1); + } + while (1); + } + while (1); + + terminate : DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + +const uint16 OP0A_Values[16] = { 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, 0xfe80, + 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 }; + +void DSP4_OP0A(int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4) +{ + *o4 = OP0A_Values[(n2 & 0x000f)]; + *o3 = OP0A_Values[(n2 & 0x00f0) >> 4]; + *o2 = OP0A_Values[(n2 & 0x0f00) >> 8]; + *o1 = OP0A_Values[(n2 & 0xf000) >> 12]; +} + +////////////////////////////////////////////////////////////// + +void DSP4_OP0B(bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop) +{ + int16 Row1, Row2; + + // SR = 0x00 + + // align to nearest 8-pixel row + Row1 = (sp_y >> 3) & 0x1f; + Row2 = (Row1 + 1) & 0x1f; + + // check boundaries + if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))) + { + *draw = 0; + } + if (size) + { + if (OAM_Row[Row1] + 1 >= OAM_RowMax) + *draw = 0; + if (OAM_Row[Row2] + 1 >= OAM_RowMax) + *draw = 0; + } + else + { + if (OAM_Row[Row1] >= OAM_RowMax) + { + *draw = 0; + } + } + + // emulator fail-safe (unknown if this really exists) + if (sprite_count >= 128) + { + *draw = 0; + } + + // SR = 0x80 + + if (*draw) + { + // Row tiles + if (size) + { + OAM_Row[Row1] += 2; + OAM_Row[Row2] += 2; + } + else + { + OAM_Row[Row1]++; + } + + // yield OAM output + DSP4_WRITE_WORD(1); + + // pack OAM data: x,y,name,attr + DSP4_WRITE_BYTE(sp_x & 0xff); + DSP4_WRITE_BYTE(sp_y & 0xff); + DSP4_WRITE_WORD(sp_attr); + + sprite_count++; + + // OAM: size,msb data + // save post-oam table data for future retrieval + OAM_attr[OAM_index] |= ((sp_x <0 || sp_x> 255) << OAM_bits); + OAM_bits++; + + OAM_attr[OAM_index] |= (size << OAM_bits); + OAM_bits++; + + // move to next byte in buffer + if (OAM_bits == 16) + { + OAM_bits = 0; + OAM_index++; + } + } + else if (stop) + { + // yield no OAM output + DSP4_WRITE_WORD(0); + } +} + +////////////////////////////////////////////////////////////// + +void DSP4_OP0D() +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + world_y = DSP4_READ_DWORD(); + poly_bottom[0][0] = DSP4_READ_WORD(); + poly_top[0][0] = DSP4_READ_WORD(); + poly_cx[1][0] = DSP4_READ_WORD(); + viewport_bottom = DSP4_READ_WORD(); + world_x = DSP4_READ_DWORD(); + poly_cx[0][0] = DSP4_READ_WORD(); + poly_ptr[0][0] = DSP4_READ_WORD(); + world_yofs = DSP4_READ_WORD(); + world_dy = DSP4_READ_DWORD(); + world_dx = DSP4_READ_DWORD(); + distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + world_xenv = SEX78(DSP4_READ_WORD()); + world_ddy = DSP4_READ_WORD(); + world_ddx = DSP4_READ_WORD(); + view_yofsenv = DSP4_READ_WORD(); + + // initial (x,y,offset) at starting raster line + view_x1 = (world_x + world_xenv) >> 16; + view_y1 = world_y >> 16; + view_xofs1 = world_x >> 16; + view_yofs1 = world_yofs; + + // first raster line + poly_raster[0][0] = poly_bottom[0][0]; + + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x,y,scroll) points + // based on the current projection lines + view_x2 = ( ( ( world_x + world_xenv ) >> 16 ) * distance >> 15 ) + ( view_turnoff_x * distance >> 15 ); + view_y2 = (world_y >> 16) * distance >> 15; + view_xofs2 = view_x2; + view_yofs2 = (world_yofs * distance >> 15) + poly_bottom[0][0] - view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the current + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((world_x + world_xenv) >> 16); + DSP4_WRITE_WORD(view_x2); + DSP4_WRITE_WORD(world_y >> 16); + DSP4_WRITE_WORD(view_y2); + + ////////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + segments = view_y1 - view_y2; + + // prevent overdraw + if (view_y2 >= poly_raster[0][0]) + segments = 0; + else + poly_raster[0][0] = view_y2; + + // don't draw outside the window + if (view_y2 < poly_top[0][0]) + { + segments = 0; + + // flush remaining raster lines + if (view_y1 >= poly_top[0][0]) + segments = view_y1 - poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(segments); + + ////////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (view_xofs2 - view_xofs1) * DSP4_Inverse(segments) << 1; + py_dy = (view_yofs2 - view_yofs1) * DSP4_Inverse(segments) << 1; + + // starting step values + x_scroll = SEX16(poly_cx[0][0] + view_xofs1); + y_scroll = SEX16(-viewport_bottom + view_yofs1 + view_yofsenv + poly_cx[1][0] - world_yofs); + + // SR = 0x80 + + // rasterize line + for (lcv = 0; lcv < segments; lcv++) + { + // 1. HDMA memory pointer (bg1) + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + + DSP4_WRITE_WORD(poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + + // update memory address + poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x,y,scroll) to last raster line drawn + view_x1 = view_x2; + view_y1 = view_y2; + view_xofs1 = view_xofs2; + view_yofs1 = view_yofs2; + + // add deltas for projection lines + world_dx += SEX78(world_ddx); + world_dy += SEX78(world_ddy); + + // update projection lines + world_x += (world_dx + world_xenv); + world_y += world_dy; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1) resume1 : + + // inspect input + distance = DSP4_READ_WORD(); + + // terminate op + if (distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 6; + DSP4_WAIT(2) resume2: + + // inspect inputs + world_ddy = DSP4_READ_WORD(); + world_ddx = DSP4_READ_WORD(); + view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + world_xenv = 0; + } + while (1); + + DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + + +void DSP4_OP0E() +{ + OAM_RowMax = 16; + memset(OAM_Row, 0, 64); +} + + +////////////////////////////////////////////////////////////// + +void DSP4_OP0F() +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + case 3: + goto resume3; break; + case 4: + goto resume4; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4_READ_WORD(); // 0x0000 + world_y = DSP4_READ_DWORD(); + poly_bottom[0][0] = DSP4_READ_WORD(); + poly_top[0][0] = DSP4_READ_WORD(); + poly_cx[1][0] = DSP4_READ_WORD(); + viewport_bottom = DSP4_READ_WORD(); + world_x = DSP4_READ_DWORD(); + poly_cx[0][0] = DSP4_READ_WORD(); + poly_ptr[0][0] = DSP4_READ_WORD(); + world_yofs = DSP4_READ_WORD(); + world_dy = DSP4_READ_DWORD(); + world_dx = DSP4_READ_DWORD(); + distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + world_xenv = DSP4_READ_DWORD(); + world_ddy = DSP4_READ_WORD(); + world_ddx = DSP4_READ_WORD(); + view_yofsenv = DSP4_READ_WORD(); + + // initial (x,y,offset) at starting raster line + view_x1 = (world_x + world_xenv) >> 16; + view_y1 = world_y >> 16; + view_xofs1 = world_x >> 16; + view_yofs1 = world_yofs; + view_turnoff_x = 0; + view_turnoff_dx = 0; + + // first raster line + poly_raster[0][0] = poly_bottom[0][0]; + + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x,y,scroll) points + // based on the current projection lines + view_x2 = ((world_x + world_xenv) >> 16) * distance >> 15; + view_y2 = (world_y >> 16) * distance >> 15; + view_xofs2 = view_x2; + view_yofs2 = (world_yofs * distance >> 15) + poly_bottom[0][0] - view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the next + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((world_x + world_xenv) >> 16); + DSP4_WRITE_WORD(view_x2); + DSP4_WRITE_WORD(world_y >> 16); + DSP4_WRITE_WORD(view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + segments = poly_raster[0][0] - view_y2; + + // prevent overdraw + if (view_y2 >= poly_raster[0][0]) + segments = 0; + else + poly_raster[0][0] = view_y2; + + // don't draw outside the window + if (view_y2 < poly_top[0][0]) + { + segments = 0; + + // flush remaining raster lines + if (view_y1 >= poly_top[0][0]) + segments = view_y1 - poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + for (lcv = 0; lcv < 4; lcv++) + { + // grab inputs + DSP4.in_count = 4; + DSP4_WAIT(1); + resume1 : + for (;;) + { + int16 distance; + int16 color, red, green, blue; + + distance = DSP4_READ_WORD(); + color = DSP4_READ_WORD(); + + // U1+B5+G5+R5 + red = color & 0x1f; + green = (color >> 5) & 0x1f; + blue = (color >> 10) & 0x1f; + + // dynamic lighting + red = (red * distance >> 15) & 0x1f; + green = (green * distance >> 15) & 0x1f; + blue = (blue * distance >> 15) & 0x1f; + color = red | (green << 5) | (blue << 10); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(color); + break; + } + } + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (view_xofs2 - view_xofs1) * DSP4_Inverse(segments) << 1; + py_dy = (view_yofs2 - view_yofs1) * DSP4_Inverse(segments) << 1; + + + // starting step values + x_scroll = SEX16(poly_cx[0][0] + view_xofs1); + y_scroll = SEX16(-viewport_bottom + view_yofs1 + view_yofsenv + poly_cx[1][0] - world_yofs); + + // SR = 0x80 + + // rasterize line + for (lcv = 0; lcv < segments; lcv++) + { + // 1. HDMA memory pointer + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + + DSP4_WRITE_WORD(poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + //////////////////////////////////////////////////// + // Post-update + + // update new viewer (x,y,scroll) to last raster line drawn + view_x1 = view_x2; + view_y1 = view_y2; + view_xofs1 = view_xofs2; + view_yofs1 = view_yofs2; + + // add deltas for projection lines + world_dx += SEX78(world_ddx); + world_dy += SEX78(world_ddy); + + // update projection lines + world_x += (world_dx + world_xenv); + world_y += world_dy; + + // update road turnoff position + view_turnoff_x += view_turnoff_dx; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(2) resume2: + + // check for termination + distance = DSP4_READ_WORD(); + if (distance == -0x8000) + break; + + // road splice + if( (uint16) distance == 0x8001 ) + { + DSP4.in_count = 6; + DSP4_WAIT(3) resume3: + + distance = DSP4_READ_WORD(); + view_turnoff_x = DSP4_READ_WORD(); + view_turnoff_dx = DSP4_READ_WORD(); + + // factor in new changes + view_x1 += ( view_turnoff_x * distance >> 15 ); + view_xofs1 += ( view_turnoff_x * distance >> 15 ); + + // update stepping values + view_turnoff_x += view_turnoff_dx; + + DSP4.in_count = 2; + DSP4_WAIT(2) + } + + // already have 2 bytes in queue + DSP4.in_count = 6; + DSP4_WAIT(4) resume4 : + + // inspect inputs + world_ddy = DSP4_READ_WORD(); + world_ddx = DSP4_READ_WORD(); + view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + world_xenv = 0; + } + while (1); + + // terminate op + DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + + +void DSP4_OP10() +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4_Logic) + { + case 1: + goto resume1; break; + case 2: + goto resume2; break; + case 3: + goto resume3; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + DSP4_READ_WORD(); // 0x0000 + world_y = DSP4_READ_DWORD(); + poly_bottom[0][0] = DSP4_READ_WORD(); + poly_top[0][0] = DSP4_READ_WORD(); + poly_cx[1][0] = DSP4_READ_WORD(); + viewport_bottom = DSP4_READ_WORD(); + world_x = DSP4_READ_DWORD(); + poly_cx[0][0] = DSP4_READ_WORD(); + poly_ptr[0][0] = DSP4_READ_WORD(); + world_yofs = DSP4_READ_WORD(); + distance = DSP4_READ_WORD(); + view_y2 = DSP4_READ_WORD(); + view_dy = DSP4_READ_WORD() * distance >> 15; + view_x2 = DSP4_READ_WORD(); + view_dx = DSP4_READ_WORD() * distance >> 15; + view_yofsenv = DSP4_READ_WORD(); + + // initial (x,y,offset) at starting raster line + view_x1 = world_x >> 16; + view_y1 = world_y >> 16; + view_xofs1 = view_x1; + view_yofs1 = world_yofs; + + // first raster line + poly_raster[0][0] = poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // add shaping + view_x2 += view_dx; + view_y2 += view_dy; + + // vertical scroll calculation + view_xofs2 = view_x2; + view_yofs2 = (world_yofs * distance >> 15) + poly_bottom[0][0] - view_y2; + + // 1. Viewer x-position at the next + // 2. Viewer y-position below the horizon + // 3. Number of raster lines drawn in this iteration + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(view_x2); + DSP4_WRITE_WORD(view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + segments = view_y1 - view_y2; + + // prevent overdraw + if (view_y2 >= poly_raster[0][0]) + segments = 0; + else + poly_raster[0][0] = view_y2; + + // don't draw outside the window + if (view_y2 < poly_top[0][0]) + { + segments = 0; + + // flush remaining raster lines + if (view_y1 >= poly_top[0][0]) + segments = view_y1 - poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + for (lcv = 0; lcv < 4; lcv++) + { + // grab inputs + DSP4.in_count = 4; + DSP4_WAIT(1); + resume1 : + for (;;) + { + int16 distance; + int16 color, red, green, blue; + + distance = DSP4_READ_WORD(); + color = DSP4_READ_WORD(); + + // U1+B5+G5+R5 + red = color & 0x1f; + green = (color >> 5) & 0x1f; + blue = (color >> 10) & 0x1f; + + // dynamic lighting + red = (red * distance >> 15) & 0x1f; + green = (green * distance >> 15) & 0x1f; + blue = (blue * distance >> 15) & 0x1f; + color = red | (green << 5) | (blue << 10); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(color); + break; + } + } + } + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (view_xofs2 - view_xofs1) * DSP4_Inverse(segments) << 1; + py_dy = (view_yofs2 - view_yofs1) * DSP4_Inverse(segments) << 1; + + // starting step values + x_scroll = SEX16(poly_cx[0][0] + view_xofs1); + y_scroll = SEX16(-viewport_bottom + view_yofs1 + view_yofsenv + poly_cx[1][0] - world_yofs); + + // SR = 0x80 + + // rasterize line + for (lcv = 0; lcv < segments; lcv++) + { + // 1. HDMA memory pointer (bg2) + // 2. vertical scroll offset ($2110) + // 3. horizontal scroll offset ($210F) + + DSP4_WRITE_WORD(poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x,y,scroll) to last raster line drawn + view_x1 = view_x2; + view_y1 = view_y2; + view_xofs1 = view_xofs2; + view_yofs1 = view_yofs2; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(2) resume2 : + + // check for opcode termination + distance = DSP4_READ_WORD(); + if (distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 10; + DSP4_WAIT(3) resume3 : + + + // inspect inputs + view_y2 = DSP4_READ_WORD(); + view_dy = DSP4_READ_WORD() * distance >> 15; + view_x2 = DSP4_READ_WORD(); + view_dx = DSP4_READ_WORD() * distance >> 15; + } + while (1); + + DSP4.waiting4command = TRUE; +} + +////////////////////////////////////////////////////////////// + +void DSP4_OP11(int16 A, int16 B, int16 C, int16 D, int16 *M) +{ + // 0x155 = 341 = Horizontal Width of the Screen + *M = ((A * 0x0155 >> 2) & 0xf000) | + ((B * 0x0155 >> 6) & 0x0f00) | + ((C * 0x0155 >> 10) & 0x00f0) | + ((D * 0x0155 >> 14) & 0x000f); +} + + + + + +///////////////////////////////////////////////////////////// +//Processing Code +///////////////////////////////////////////////////////////// +uint8 dsp4_byte; +uint16 dsp4_address; + +void InitDSP4() +{ + memset(&DSP4, 0, sizeof(DSP4)); + DSP4.waiting4command = TRUE; +} + +void DSP4_SetByte() +{ + // clear pending read + if (DSP4.out_index < DSP4.out_count) + { + DSP4.out_index++; + return; + } + + if (DSP4.waiting4command) + { + if (DSP4.half_command) + { + DSP4.command |= (dsp4_byte << 8); + DSP4.in_index = 0; + DSP4.waiting4command = FALSE; + DSP4.half_command = FALSE; + DSP4.out_count = 0; + DSP4.out_index = 0; + + DSP4_Logic = 0; + + + switch (DSP4.command) + { + case 0x0000: + DSP4.in_count = 4; break; + case 0x0001: + DSP4.in_count = 44; break; + case 0x0003: + DSP4.in_count = 0; break; + case 0x0005: + DSP4.in_count = 0; break; + case 0x0006: + DSP4.in_count = 0; break; + case 0x0007: + DSP4.in_count = 34; break; + case 0x0008: + DSP4.in_count = 90; break; + case 0x0009: + DSP4.in_count = 14; break; + case 0x000a: + DSP4.in_count = 6; break; + case 0x000b: + DSP4.in_count = 6; break; + case 0x000d: + DSP4.in_count = 42; break; + case 0x000e: + DSP4.in_count = 0; break; + case 0x000f: + DSP4.in_count = 46; break; + case 0x0010: + DSP4.in_count = 36; break; + case 0x0011: + DSP4.in_count = 8; break; + default: + DSP4.waiting4command = TRUE; + break; + } + } + else + { + DSP4.command = dsp4_byte; + DSP4.half_command = TRUE; + } + } + else + { + DSP4.parameters[DSP4.in_index] = dsp4_byte; + DSP4.in_index++; + } + + if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index) + { + // Actually execute the command + DSP4.waiting4command = TRUE; + DSP4.out_index = 0; + DSP4.in_index = 0; + + switch (DSP4.command) + { + // 16-bit multiplication + case 0x0000: + { + int16 multiplier, multiplicand; + int32 product; + + multiplier = DSP4_READ_WORD(); + multiplicand = DSP4_READ_WORD(); + + DSP4_Multiply(multiplicand, multiplier, &product); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(product); + DSP4_WRITE_WORD(product >> 16); + } + break; + + // single-player track projection + case 0x0001: + DSP4_OP01(); break; + + // single-player selection + case 0x0003: + DSP4_OP03(); break; + + // clear OAM + case 0x0005: + DSP4_OP05(); break; + + // transfer OAM + case 0x0006: + DSP4_OP06(); break; + + // single-player track turnoff projection + case 0x0007: + DSP4_OP07(); break; + + // solid polygon projection + case 0x0008: + DSP4_OP08(); break; + + // sprite projection + case 0x0009: + DSP4_OP09(); break; + + // unknown + case 0x000A: + { + //int16 in1a = DSP4_READ_WORD(); + int16 in2a = DSP4_READ_WORD(); + //int16 in3a = DSP4_READ_WORD(); + int16 out1a, out2a, out3a, out4a; + + DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(out1a); + DSP4_WRITE_WORD(out2a); + DSP4_WRITE_WORD(out3a); + DSP4_WRITE_WORD(out4a); + } + break; + + // set OAM + case 0x000B: + { + int16 sp_x = DSP4_READ_WORD(); + int16 sp_y = DSP4_READ_WORD(); + int16 sp_attr = DSP4_READ_WORD(); + bool8 draw = 1; + + DSP4_CLEAR_OUT(); + + DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1); + } + break; + + // multi-player track projection + case 0x000D: + DSP4_OP0D(); break; + + // multi-player selection + case 0x000E: + DSP4_OP0E(); break; + + // single-player track projection with lighting + case 0x000F: + DSP4_OP0F(); break; + + // single-player track turnoff projection with lighting + case 0x0010: + DSP4_OP10(); break; + + // unknown: horizontal mapping command + case 0x0011: + { + int16 a, b, c, d, m; + + + d = DSP4_READ_WORD(); + c = DSP4_READ_WORD(); + b = DSP4_READ_WORD(); + a = DSP4_READ_WORD(); + + DSP4_OP11(a, b, c, d, &m); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(m); + + break; + } + + default: + break; + } + } +} + +void DSP4_GetByte() +{ + if (DSP4.out_count) + { + dsp4_byte = (uint8) DSP4.output[DSP4.out_index&0x1FF]; + DSP4.out_index++; + if (DSP4.out_count == DSP4.out_index) + DSP4.out_count = 0; + } + else + { + dsp4_byte = 0xff; + } +} diff --git a/source/snes9x/font.h b/source/snes9x/font.h index f6fae04..1b126cc 100644 --- a/source/snes9x/font.h +++ b/source/snes9x/font.h @@ -159,151 +159,142 @@ **********************************************************************************/ -#ifndef _FONT_H_ -#define _FONT_H_ -static const char *font[] = -{ - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " . . . . .. . . ", - " .#. .#.#. . . ... .#. . . .##. .#. .#. . . . . ", - " .#. .#.#. .#.#. .###. .#..#. .#. .#. .#. .#. .#.#. .#. .#. ", - " .#. .#.#. .#####. .#.#. ..#. .#.#. .#. .#. .#. .#. ..#.. .... .#. ", - " .#. . . .#.#. .###. .#.. .#. . .#. .#. .###. .#####. .. .####. .. .#. ", - " . .#####. .#.#. .#..#. .#.#. .#. .#. .#. ..#.. .##. .... .##. .#. ", - " .#. .#.#. .###. . .#. .#.#. .#. .#. .#.#. .#. .#. .##. . ", - " . . . ... . . . . . . . . .#. .. ", - " . ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " . . .. .... . .... .. .... .. .. . ", - " .#. .#. .##. .####. .#. .####. .##. .####. .##. .##. .. .. . . .#. ", - ".#.#. .##. .#..#. ...#. .##. .#... .#.. ...#. .#..#. .#..#. .##. .##. .#. .... .#. .#.#. ", - ".#.#. .#. . .#. .##. .#.#. .###. .###. .#. .##. .#..#. .##. .##. .#. .####. .#. ..#. ", - ".#.#. .#. .#. ...#. .####. ...#. .#..#. .#. .#..#. .###. .. .. .#. .... .#. .#. ", - ".#.#. .#. .#.. .#..#. ..#. .#..#. .#..#. .#. .#..#. ..#. .##. .##. .#. .####. .#. . ", - " .#. .###. .####. .##. .#. .##. .##. .#. .##. .##. .##. .#. .#. .... .#. .#. ", - " . ... .... .. . .. .. . .. .. .. .#. . . . ", - " . ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " .. .. ... .. ... .... .... .. . . ... . . . . . . . . .. ", - " .##. .##. .###. .##. .###. .####. .####. .##. .#..#. .###. .#. .#..#. .#. .#. .#. .#. .#. .##. ", - ".#..#. .#..#. .#..#. .#..#. .#..#. .#... .#... .#..#. .#..#. .#. .#. .#.#. .#. .##.##. .##..#. .#..#. ", - ".#.##. .#..#. .###. .#. . .#..#. .###. .###. .#... .####. .#. .#. .##. .#. .#.#.#. .#.#.#. .#..#. ", - ".#.##. .####. .#..#. .#. . .#..#. .#.. .#.. .#.##. .#..#. .#. . .#. .##. .#. .#...#. .#.#.#. .#..#. ", - ".#... .#..#. .#..#. .#..#. .#..#. .#... .#. .#..#. .#..#. .#. .#..#. .#.#. .#... .#. .#. .#..##. .#..#. ", - " .##. .#..#. .###. .##. .###. .####. .#. .###. .#..#. .###. .##. .#..#. .####. .#. .#. .#. .#. .##. ", - " .. . . ... .. ... .... . ... . . ... .. . . .... . . . . .. ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " ... .. ... .. ... . . . . . . . . . . .... ... ... . ", - ".###. .##. .###. .##. .###. .#. .#. .#. .#. .#. .#. .#..#. .#.#. .####. .###. . .###. .#. ", - ".#..#. .#..#. .#..#. .#..#. .#. .#. .#. .#. .#. .#...#. .#..#. .#.#. ...#. .#.. .#. ..#. .#.#. ", - ".#..#. .#..#. .#..#. .#.. .#. .#. .#. .#. .#. .#.#.#. .##. .#.#. .#. .#. .#. .#. . . ", - ".###. .#..#. .###. ..#. .#. .#. .#. .#. .#. .#.#.#. .#..#. .#. .#. .#. .#. .#. ", - ".#.. .##.#. .#.#. .#..#. .#. .#...#. .#.#. .##.##. .#..#. .#. .#... .#.. .#. ..#. .... ", - ".#. .##. .#..#. .##. .#. .###. .#. .#. .#. .#..#. .#. .####. .###. . .###. .####. ", - " . ..#. . . .. . ... . . . . . . .... ... ... .... ", - " . ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " .. . . . . . . . .. ", - ".##. .#. .#. .#. .#. .#. .#. .#. .##. ", - " .#. ... .#.. .. ..#. .. .#.#. ... .#.. .. . .#.. .#. .. .. ... .. ", - " .#. .###. .###. .##. .###. .##. .#.. .###. .###. .##. .#. .#.#. .#. .##.##. .###. .##. ", - " . .#..#. .#..#. .#.. .#..#. .#.##. .###. .#..#. .#..#. .#. .#. .##. .#. .#.#.#. .#..#. .#..#. ", - " .#.##. .#..#. .#.. .#..#. .##.. .#. .##. .#..#. .#. ..#. .#.#. .#. .#...#. .#..#. .#..#. ", - " .#.#. .###. .##. .###. .##. .#. .#... .#..#. .###. .#.#. .#..#. .###. .#. .#. .#..#. .##. ", - " . . ... .. ... .. . .###. . . ... .#. . . ... . . . . .. ", - " ... . ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " . . . . . . ", - " .#. .#. .#. .#. .#.#. ", - " ... ... ... ... .#. . . . . . . . . . . .... .#. .#. .#. .#.#. ", - ".###. .###. .###. .###. .###. .#..#. .#.#. .#...#. .#..#. .#..#. .####. .##. .#. .##. . . ", - ".#..#. .#..#. .#..#. .##.. .#. .#..#. .#.#. .#.#.#. .##. .#..#. ..#. .#. .#. .#. ", - ".#..#. .#..#. .#. . ..##. .#.. .#..#. .#.#. .#.#.#. .##. .#.#. .#.. .#. .#. .#. ", - ".###. .###. .#. .###. .##. .###. .#. .#.#. .#..#. .#. .####. .#. .#. .#. ", - ".#.. ..#. . ... .. ... . . . . . .#. .... . . . ", - " . . . ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " .. ..... ", - " .##. .#####. ... . . . . .. ", - " .#. . .. ....#. .###. .#. .#. .#. .#.. .##. . . . ", - " .#. .#. .##. .#####. .#. .#. .###. ... .###. .###. .. .#. .#.#.#. ", - " . .#. .#. . .##. ....#. .#. .##. .#.#. .###. .#. .##.#. .##. .##. .#.#.#. ", - " .#. . .#. .#. .. ...#. .#. .#. ..#. .#. .##. .#.. ..#. .#. ...#. ", - " .#.#. .##. .#. .###. .#. .#. .#. .###. .#. .#. .####. .##. .##. ", - " .#. .. .#. ... . . . ... . . .... .. .. ", - " . . ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " .... . . ... . . . .... . . . .. . ..... . . . ", - " .####. .#. ..#.. .###. ...#. ..#.. ..#.. .####. .#... .... .#.#. .##..#. .#####. .#... .#. .#. ", - " .... ...#. .#. .#####. .#. .#####. .#####. .#####. .#..#. .####. .####. .#####. .. .#. ....#. .#####. .#. .#. ", - ".####. .##. .## .#...#. .#. ...#. ..#.#. ..#.. .# .#. .#..#. ...#. .#.#. .##..#. .#. .#..#. .#..#. ", - " .... .#. .#.# . .#. .#. .##. .#..#. .#####. .#. .#. . .#. .#. ..#. .. .#. .#. .#.#. . .#. ", - " .#. .#. ..#. ..#.. .#.#. .#..#. ..#.. . .#. .#. ...#. .#. ...#. .#.#. .#... ...#. ", - " .#. .#. .##. .#####. .#..#. .#..#. .#. .#. .#. .####. .#. .###. .#. .#. .###. .###. ", - " . . .. ..... . . . . . . . .... . ... . . ... ... ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " .... .. . . . ... . . ... .... . . . ..... . . ", - " .####. ..##. .#.#.#. .###. .#. ..#.. .###. .####. ..#.. .#. . . .#. .. .#####. .#. ..#.. ..... ", - " .#..#. .###. .#.#.#. ..... .#. .#####. ... ...#. .#####. .#. .#.#. .#..##. ....#. .#.#. .#####. .#####. ", - " .####. ..#. .#.#.#. .#####. .##. ..#.. .#.#. ....#. .#. .#.#. .###.. .#. .#..#. ..#.. .#. ", - ".#...#. .####. . ..#. ..#.. .#.#. .#. .#. .###. .#. .#. .#. .#.. .#. . .#. .#.#.#. .#.#. ", - " . .#. ..#. ...#. .#. .#.. ..#. ..... .#.#. .#.#.#. .#. .#. .#. .#.... ..#. .#. .#.#.#. .#. ", - " .#. .##. .###. .#. .#. .##. .#####. .#. .#. ..#.. .#. .#. .#. .####. .##. .#. ..#.. .#. ", - " . .. ... . . .. ..... . . . . . . .... .. . . . ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " .. . . ... . .... .... . . . . . ..... . . . . ", - " .##. .#. .#. .###. .#... ... .####. .####. .#..#. .#.#. .#. ..... .#####. ....#. .#.#. .#. ", - " ..#. .#. . .#. .#. .#.##. .###. ...#. ..... .#..#. .#.#. .#. .#####. .#...#. .###.#. .#.#. .#.#. ", - " .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", - " ..#. .#..#. .##. ..#.. .#.#. ..#. ..#. ....#. . .#. .#.#. .#..#. .#...#. .#. .#. . ", - " .##. .####. ..#.#. .#.. .#. ...#. ...#. ..#. ..#. .#.#. .#.#. .#####. ..#. ...#. ", - " ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", - " . . .. ... . ..... .... .. ... . .. .. . . .. ... ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " +static char *font[] = { +" . . . . .. . . ", +" .#. .#.#. . . ... .#. . . .##. .#. .#. . . . . ", +" .#. .#.#. .#.#. .###. .#..#. .#. .#. .#. .#. .#.#. .#. .#. ", +" .#. .#.#. .#####. .#.#. ..#. .#.#. .#. .#. .#. .#. ..#.. .... .#. ", +" .#. . . .#.#. .###. .#.. .#. . .#. .#. .###. .#####. .. .####. .. .#. ", +" . .#####. .#.#. .#..#. .#.#. .#. .#. .#. ..#.. .##. .... .##. .#. ", +" .#. .#.#. .###. . .#. .#.#. .#. .#. .#.#. .#. .#. .##. . ", +" . . . ... . . . . . . . . .#. .. ", +" . ", +" . . .. .... . .... .. .... .. .. . ", +" .#. .#. .##. .####. .#. .####. .##. .####. .##. .##. .. .. . . .#. ", +".#.#. .##. .#..#. ...#. .##. .#... .#.. ...#. .#..#. .#..#. .##. .##. .#. .... .#. .#.#. ", +".#.#. .#. . .#. .##. .#.#. .###. .###. .#. .##. .#..#. .##. .##. .#. .####. .#. ..#. ", +".#.#. .#. .#. ...#. .####. ...#. .#..#. .#. .#..#. .###. .. .. .#. .... .#. .#. ", +".#.#. .#. .#.. .#..#. ..#. .#..#. .#..#. .#. .#..#. ..#. .##. .##. .#. .####. .#. . ", +" .#. .###. .####. .##. .#. .##. .##. .#. .##. .##. .##. .#. .#. .... .#. .#. ", +" . ... .... .. . .. .. . .. .. .. .#. . . . ", +" . ", +" .. .. ... .. ... .... .... .. . . ... . . . . . . . . .. ", +" .##. .##. .###. .##. .###. .####. .####. .##. .#..#. .###. .#. .#..#. .#. .#. .#. .#. .#. .##. ", +".#..#. .#..#. .#..#. .#..#. .#..#. .#... .#... .#..#. .#..#. .#. .#. .#.#. .#. .##.##. .##..#. .#..#. ", +".#.##. .#..#. .###. .#. . .#..#. .###. .###. .#... .####. .#. .#. .##. .#. .#.#.#. .#.#.#. .#..#. ", +".#.##. .####. .#..#. .#. . .#..#. .#.. .#.. .#.##. .#..#. .#. . .#. .##. .#. .#...#. .#.#.#. .#..#. ", +".#... .#..#. .#..#. .#..#. .#..#. .#... .#. .#..#. .#..#. .#. .#..#. .#.#. .#... .#. .#. .#..##. .#..#. ", +" .##. .#..#. .###. .##. .###. .####. .#. .###. .#..#. .###. .##. .#..#. .####. .#. .#. .#. .#. .##. ", +" .. . . ... .. ... .... . ... . . ... .. . . .... . . . . .. ", +" ", +" ... .. ... .. ... . . . . . . . . . . .... ... ... . ", +".###. .##. .###. .##. .###. .#. .#. .#. .#. .#. .#. .#..#. .#.#. .####. .###. . .###. .#. ", +".#..#. .#..#. .#..#. .#..#. .#. .#. .#. .#. .#. .#...#. .#..#. .#.#. ...#. .#.. .#. ..#. .#.#. ", +".#..#. .#..#. .#..#. .#.. .#. .#. .#. .#. .#. .#.#.#. .##. .#.#. .#. .#. .#. .#. . . ", +".###. .#..#. .###. ..#. .#. .#. .#. .#. .#. .#.#.#. .#..#. .#. .#. .#. .#. .#. ", +".#.. .##.#. .#.#. .#..#. .#. .#...#. .#.#. .##.##. .#..#. .#. .#... .#.. .#. ..#. .... ", +".#. .##. .#..#. .##. .#. .###. .#. .#. .#. .#..#. .#. .####. .###. . .###. .####. ", +" . ..#. . . .. . ... . . . . . . .... ... ... .... ", +" . ", +" .. . . . . . . . .. ", +".##. .#. .#. .#. .#. .#. .#. .#. .##. ", +" .#. ... .#.. .. ..#. .. .#.#. ... .#.. .. . .#.. .#. .. .. ... .. ", +" .#. .###. .###. .##. .###. .##. .#.. .###. .###. .##. .#. .#.#. .#. .##.##. .###. .##. ", +" . .#..#. .#..#. .#.. .#..#. .#.##. .###. .#..#. .#..#. .#. .#. .##. .#. .#.#.#. .#..#. .#..#. ", +" .#.##. .#..#. .#.. .#..#. .##.. .#. .##. .#..#. .#. ..#. .#.#. .#. .#...#. .#..#. .#..#. ", +" .#.#. .###. .##. .###. .##. .#. .#... .#..#. .###. .#.#. .#..#. .###. .#. .#. .#..#. .##. ", +" . . ... .. ... .. . .###. . . ... .#. . . ... . . . . .. ", +" ... . ", +" . . . . . . ", +" .#. .#. .#. .#. .#.#. ", +" ... ... ... ... .#. . . . . . . . . . . .... .#. .#. .#. .#.#. ", +".###. .###. .###. .###. .###. .#..#. .#.#. .#...#. .#..#. .#..#. .####. .##. .#. .##. . . ", +".#..#. .#..#. .#..#. .##.. .#. .#..#. .#.#. .#.#.#. .##. .#..#. ..#. .#. .#. .#. ", +".#..#. .#..#. .#. . ..##. .#.. .#..#. .#.#. .#.#.#. .##. .#.#. .#.. .#. .#. .#. ", +".###. .###. .#. .###. .##. .###. .#. .#.#. .#..#. .#. .####. .#. .#. .#. ", +".#.. ..#. . ... .. ... . . . . . .#. .... . . . ", +" . . . ", + +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", + +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", + +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +" .. ..... ", +" .##. .#####. ... . . . . .. ", +" .#. . .. ....#. .###. .#. .#. .#. .#.. .##. . . . ", +" .#. .#. .##. .#####. .#. .#. .###. ... .###. .###. .. .#. .#.#.#. ", +" . .#. .#. . .##. ....#. .#. .##. .#.#. .###. .#. .##.#. .##. .##. .#.#.#. ", +" .#. . .#. .#. .. ...#. .#. .#. ..#. .#. .##. .#.. ..#. .#. ...#. ", +" .#.#. .##. .#. .###. .#. .#. .#. .###. .#. .#. .####. .##. .##. ", +" .#. .. .#. ... . . . ... . . .... .. .. ", +" . . ", +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +" .... . . ... . . . .... . . . .. . ..... . . . ", +" .####. .#. ..#.. .###. ...#. ..#.. ..#.. .####. .#... .... .#.#. .##..#. .#####. .#... .#. .#. ", +" .... ...#. .#. .#####. .#. .#####. .#####. .#####. .#..#. .####. .####. .#####. .. .#. ....#. .#####. .#. .#. ", +".####. .##. .## .#...#. .#. ...#. ..#.#. ..#.. .# .#. .#..#. ...#. .#.#. .##..#. .#. .#..#. .#..#. ", +" .... .#. .#.# . .#. .#. .##. .#..#. .#####. .#. .#. . .#. .#. ..#. .. .#. .#. .#.#. . .#. ", +" .#. .#. ..#. ..#.. .#.#. .#..#. ..#.. . .#. .#. ...#. .#. ...#. .#.#. .#... ...#. ", +" .#. .#. .##. .#####. .#..#. .#..#. .#. .#. .#. .####. .#. .###. .#. .#. .###. .###. ", +" . . .. ..... . . . . . . . .... . ... . . ... ... ", +" ", +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +" .... .. . . . ... . . ... .... . . . ..... . . ", +" .####. ..##. .#.#.#. .###. .#. ..#.. .###. .####. ..#.. .#. . . .#. .. .#####. .#. ..#.. ..... ", +" .#..#. .###. .#.#.#. ..... .#. .#####. ... ...#. .#####. .#. .#.#. .#..##. ....#. .#.#. .#####. .#####. ", +" .####. ..#. .#.#.#. .#####. .##. ..#.. .#.#. ....#. .#. .#.#. .###.. .#. .#..#. ..#.. .#. ", +".#...#. .####. . ..#. ..#.. .#.#. .#. .#. .###. .#. .#. .#. .#.. .#. . .#. .#.#.#. .#.#. ", +" . .#. ..#. ...#. .#. .#.. ..#. ..... .#.#. .#.#.#. .#. .#. .#. .#.... ..#. .#. .#.#.#. .#. ", +" .#. .##. .###. .#. .#. .##. .#####. .#. .#. ..#.. .#. .#. .#. .####. .##. .#. ..#.. .#. ", +" . .. ... . . .. ..... . . . . . . .... .. . . . ", +" ", +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +" .. . . ... . .... .... . . . . . ..... . . . . ", +" .##. .#. .#. .###. .#... ... .####. .####. .#..#. .#.#. .#. ..... .#####. ....#. .#.#. .#. ", +" ..#. .#. . .#. .#. .#.##. .###. ...#. ..... .#..#. .#.#. .#. .#####. .#...#. .###.#. .#.#. .#.#. ", +" .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", +" ..#. .#..#. .##. ..#.. .#.#. ..#. ..#. ....#. . .#. .#.#. .#..#. .#...#. .#. .#. . ", +" .##. .####. ..#.#. .#.. .#. ...#. ...#. ..#. ..#. .#.#. .#.#. .#####. ..#. ...#. ", +" ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", +" . . .. ... . ..... .... .. ... . .. .. . . .. ... ", +" ", + +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", + +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" " }; -#endif diff --git a/source/snes9x/fxdbg.cpp b/source/snes9x/fxdbg.cpp index d3b5e31..f51c94d 100644 --- a/source/snes9x/fxdbg.cpp +++ b/source/snes9x/fxdbg.cpp @@ -159,1251 +159,325 @@ **********************************************************************************/ -#ifdef DEBUGGER -#include "snes9x.h" -#include "fxinst.h" + #include "fxemu.h" +#include "fxinst.h" +#include +#include + +extern const char *fx_apvMnemonicTable[]; +extern struct FxRegs_s GSU; + /* When printing a line from the pipe, it could look like this: - 01:8006 f4 fb 86 iwt r4, #$86fb + 01:8006 f4 fb 86 iwt r4,#$86fb The values are: - program bank : 01 - adress : 8006 - values at memory address 8006 : f4 fb 86 - instruction in the pipe : iwt r4, #$86fb + program bank: 01 + adress: 8006 + values at memory address 8006: f4 fb 86 + instruction in the pipe: iwt r4,#$86fb - Note! If the instruction has more than one byte (like in 'iwt') and the instruction is in a delay slot, - the second and third byte displayed will not be the same as those used. - Since the instrction is in a delay slot, - the first byte of the instruction will be taken from the pipe at the address after the branch instruction, - and the next one or two bytes will be taken from the address that the branch points to. - This is a bit complicated, but I've taken this into account, in this debug function. - (See the diffrence of how the values vPipe1 and vPipe2 are read, compared to the values vByte1 and vByte2) -*/ + Note! If the instruction has more than one byte (like in 'iwt') + and the instruction is in a delay slot, the second and third + byte displayed will not be the same as those used. + Since the instrction is in a delay slot, the first byte + of the instruction will be taken from the pipe at the address + after the branch instruction, and the next one or two bytes + will be taken from the address that the branch points to. + This is a bit complicated, but I've taken this into account, + in this debug function. (See the diffrence of how the values + vPipe1 and vPipe2 are read, compared to the values vByte1 and + vByte2) -/* -static const char *fx_apvMnemonicTable[] = + */ +void FxPipeString(char * pvString) { - // ALT0 Table - - // 00 - 0f - "stop", - "nop", - "cache", - "lsr", - "rol", - "bra $%04x", - "blt $%04x", - "bge $%04x", - "bne $%04x", - "beq $%04x", - "bpl $%04x", - "bmi $%04x", - "bcc $%04x", - "bcs $%04x", - "bvc $%04x", - "bvs $%04x", - - // 10 - 1f - "to r0", - "to r1", - "to r2", - "to r3", - "to r4", - "to r5", - "to r6", - "to r7", - "to r8", - "to r9", - "to r10", - "to r11", - "to r12", - "to r13", - "to r14", - "to r15", - - // 20 - 2f - "with r0", - "with r1", - "with r2", - "with r3", - "with r4", - "with r5", - "with r6", - "with r7", - "with r8", - "with r9", - "with r10", - "with r11", - "with r12", - "with r13", - "with r14", - "with r15", - - // 30 - 3f - "stw (r0)", - "stw (r1)", - "stw (r2)", - "stw (r3)", - "stw (r4)", - "stw (r5)", - "stw (r6)", - "stw (r7)", - "stw (r8)", - "stw (r9)", - "stw (r10)", - "stw (r11)", - "loop", - "alt1", - "alt2", - "alt3", - - // 40 - 4f - "ldw (r0)", - "ldw (r1)", - "ldw (r2)", - "ldw (r3)", - "ldw (r4)", - "ldw (r5)", - "ldw (r6)", - "ldw (r7)", - "ldw (r8)", - "ldw (r9)", - "ldw (r10)", - "ldw (r11)", - "plot", - "swap", - "color", - "not", - - // 50 - 5f - "add r0", - "add r1", - "add r2", - "add r3", - "add r4", - "add r5", - "add r6", - "add r7", - "add r8", - "add r9", - "add r10", - "add r11", - "add r12", - "add r13", - "add r14", - "add r15", - - // 60 - 6f - "sub r0", - "sub r1", - "sub r2", - "sub r3", - "sub r4", - "sub r5", - "sub r6", - "sub r7", - "sub r8", - "sub r9", - "sub r10", - "sub r11", - "sub r12", - "sub r13", - "sub r14", - "sub r15", - - // 70 - 7f - "merge", - "and r1", - "and r2", - "and r3", - "and r4", - "and r5", - "and r6", - "and r7", - "and r8", - "and r9", - "and r10", - "and r11", - "and r12", - "and r13", - "and r14", - "and r15", - - // 80 - 8f - "mult r0", - "mult r1", - "mult r2", - "mult r3", - "mult r4", - "mult r5", - "mult r6", - "mult r7", - "mult r8", - "mult r9", - "mult r10", - "mult r11", - "mult r12", - "mult r13", - "mult r14", - "mult r15", - - // 90 - 9f - "sbk", - "link #1", - "link #2", - "link #3", - "link #4", - "sex", - "asr", - "ror", - "jmp (r8)", - "jmp (r9)", - "jmp (r10)", - "jmp (r11)", - "jmp (r12)", - "jmp (r13)", - "lob", - "fmult", - - // a0 - af - "ibt r0, #$%02x", - "ibt r1, #$%02x", - "ibt r2, #$%02x", - "ibt r3, #$%02x", - "ibt r4, #$%02x", - "ibt r5, #$%02x", - "ibt r6, #$%02x", - "ibt r7, #$%02x", - "ibt r8, #$%02x", - "ibt r9, #$%02x", - "ibt r10, #$%02x", - "ibt r11, #$%02x", - "ibt r12, #$%02x", - "ibt r13, #$%02x", - "ibt r14, #$%02x", - "ibt r15, #$%02x", - - // b0 - bf - "from r0", - "from r1", - "from r2", - "from r3", - "from r4", - "from r5", - "from r6", - "from r7", - "from r8", - "from r9", - "from r10", - "from r11", - "from r12", - "from r13", - "from r14", - "from r15", - - // c0 - cf - "hib", - "or r1", - "or r2", - "or r3", - "or r4", - "or r5", - "or r6", - "or r7", - "or r8", - "or r9", - "or r10", - "or r11", - "or r12", - "or r13", - "or r14", - "or r15", - - // d0 - df - "inc r0", - "inc r1", - "inc r2", - "inc r3", - "inc r4", - "inc r5", - "inc r6", - "inc r7", - "inc r8", - "inc r9", - "inc r10", - "inc r11", - "inc r12", - "inc r13", - "inc r14", - "getc", - - // e0 - ef - "dec r0", - "dec r1", - "dec r2", - "dec r3", - "dec r4", - "dec r5", - "dec r6", - "dec r7", - "dec r8", - "dec r9", - "dec r10", - "dec r11", - "dec r12", - "dec r13", - "dec r14", - "getb", - - // f0 - ff - "iwt r0, #$%04x", - "iwt r1, #$%04x", - "iwt r2, #$%04x", - "iwt r3, #$%04x", - "iwt r4, #$%04x", - "iwt r5, #$%04x", - "iwt r6, #$%04x", - "iwt r7, #$%04x", - "iwt r8, #$%04x", - "iwt r9, #$%04x", - "iwt r10, #$%04x", - "iwt r11, #$%04x", - "iwt r12, #$%04x", - "iwt r13, #$%04x", - "iwt r14, #$%04x", - "iwt r15, #$%04x", - - // ALT1 Table - - // 00 - 0f - "stop", - "nop", - "cache", - "lsr", - "rol", - "bra $%04x", - "blt $%04x", - "bge $%04x", - "bne $%04x", - "beq $%04x", - "bpl $%04x", - "bmi $%04x", - "bcc $%04x", - "bcs $%04x", - "bvc $%04x", - "bvs $%04x", - - // 10 - 1f - "to r0", - "to r1", - "to r2", - "to r3", - "to r4", - "to r5", - "to r6", - "to r7", - "to r8", - "to r9", - "to r10", - "to r11", - "to r12", - "to r13", - "to r14", - "to r15", - - // 20 - 2f - "with r0", - "with r1", - "with r2", - "with r3", - "with r4", - "with r5", - "with r6", - "with r7", - "with r8", - "with r9", - "with r10", - "with r11", - "with r12", - "with r13", - "with r14", - "with r15", - - // 30 - 3f - "stb (r0)", - "stb (r1)", - "stb (r2)", - "stb (r3)", - "stb (r4)", - "stb (r5)", - "stb (r6)", - "stb (r7)", - "stb (r8)", - "stb (r9)", - "stb (r10)", - "stb (r11)", - "loop", - "alt1", - "alt2", - "alt3", - - // 40 - 4f - "ldb (r0)", - "ldb (r1)", - "ldb (r2)", - "ldb (r3)", - "ldb (r4)", - "ldb (r5)", - "ldb (r6)", - "ldb (r7)", - "ldb (r8)", - "ldb (r9)", - "ldb (r10)", - "ldb (r11)", - "rpix", - "swap", - "cmode", - "not", - - // 50 - 5f - "adc r0", - "adc r1", - "adc r2", - "adc r3", - "adc r4", - "adc r5", - "adc r6", - "adc r7", - "adc r8", - "adc r9", - "adc r10", - "adc r11", - "adc r12", - "adc r13", - "adc r14", - "adc r15", - - // 60 - 6f - "sbc r0", - "sbc r1", - "sbc r2", - "sbc r3", - "sbc r4", - "sbc r5", - "sbc r6", - "sbc r7", - "sbc r8", - "sbc r9", - "sbc r10", - "sbc r11", - "sbc r12", - "sbc r13", - "sbc r14", - "sbc r15", - - // 70 - 7f - "merge", - "bic r1", - "bic r2", - "bic r3", - "bic r4", - "bic r5", - "bic r6", - "bic r7", - "bic r8", - "bic r9", - "bic r10", - "bic r11", - "bic r12", - "bic r13", - "bic r14", - "bic r15", - - // 80 - 8f - "umult r0", - "umult r1", - "umult r2", - "umult r3", - "umult r4", - "umult r5", - "umult r6", - "umult r7", - "umult r8", - "umult r9", - "umult r10", - "umult r11", - "umult r12", - "umult r13", - "umult r14", - "umult r15", - - // 90 - 9f - "sbk", - "link #1", - "link #2", - "link #3", - "link #4", - "sex", - "div2", - "ror", - "ljmp (r8)", - "ljmp (r9)", - "ljmp (r10)", - "ljmp (r11)", - "ljmp (r12)", - "ljmp (r13)", - "lob", - "lmult", - - // a0 - af - "lms r0, ($%04x)", - "lms r1, ($%04x)", - "lms r2, ($%04x)", - "lms r3, ($%04x)", - "lms r4, ($%04x)", - "lms r5, ($%04x)", - "lms r6, ($%04x)", - "lms r7, ($%04x)", - "lms r8, ($%04x)", - "lms r9, ($%04x)", - "lms r10, ($%04x)", - "lms r11, ($%04x)", - "lms r12, ($%04x)", - "lms r13, ($%04x)", - "lms r14, ($%04x)", - "lms r15, ($%04x)", - - // b0 - bf - "from r0", - "from r1", - "from r2", - "from r3", - "from r4", - "from r5", - "from r6", - "from r7", - "from r8", - "from r9", - "from r10", - "from r11", - "from r12", - "from r13", - "from r14", - "from r15", - - // c0 - cf - "hib", - "xor r1", - "xor r2", - "xor r3", - "xor r4", - "xor r5", - "xor r6", - "xor r7", - "xor r8", - "xor r9", - "xor r10", - "xor r11", - "xor r12", - "xor r13", - "xor r14", - "xor r15", - - // d0 - df - "inc r0", - "inc r1", - "inc r2", - "inc r3", - "inc r4", - "inc r5", - "inc r6", - "inc r7", - "inc r8", - "inc r9", - "inc r10", - "inc r11", - "inc r12", - "inc r13", - "inc r14", - "getc", - - // e0 - ef - "dec r0", - "dec r1", - "dec r2", - "dec r3", - "dec r4", - "dec r5", - "dec r6", - "dec r7", - "dec r8", - "dec r9", - "dec r10", - "dec r11", - "dec r12", - "dec r13", - "dec r14", - "getbh", - - // f0 - ff - "lm r0, ($%04x)", - "lm r1, ($%04x)", - "lm r2, ($%04x)", - "lm r3, ($%04x)", - "lm r4, ($%04x)", - "lm r5, ($%04x)", - "lm r6, ($%04x)", - "lm r7, ($%04x)", - "lm r8, ($%04x)", - "lm r9, ($%04x)", - "lm r10, ($%04x)", - "lm r11, ($%04x)", - "lm r12, ($%04x)", - "lm r13, ($%04x)", - "lm r14, ($%04x)", - "lm r15, ($%04x)", - - // ALT2 Table - - // 00 - 0f - "stop", - "nop", - "cache", - "lsr", - "rol", - "bra $%04x", - "blt $%04x", - "bge $%04x", - "bne $%04x", - "beq $%04x", - "bpl $%04x", - "bmi $%04x", - "bcc $%04x", - "bcs $%04x", - "bvc $%04x", - "bvs $%04x", - - // 10 - 1f - "to r0", - "to r1", - "to r2", - "to r3", - "to r4", - "to r5", - "to r6", - "to r7", - "to r8", - "to r9", - "to r10", - "to r11", - "to r12", - "to r13", - "to r14", - "to r15", - - // 20 - 2f - "with r0", - "with r1", - "with r2", - "with r3", - "with r4", - "with r5", - "with r6", - "with r7", - "with r8", - "with r9", - "with r10", - "with r11", - "with r12", - "with r13", - "with r14", - "with r15", - - // 30 - 3f - "stw (r0)", - "stw (r1)", - "stw (r2)", - "stw (r3)", - "stw (r4)", - "stw (r5)", - "stw (r6)", - "stw (r7)", - "stw (r8)", - "stw (r9)", - "stw (r10)", - "stw (r11)", - "loop", - "alt1", - "alt2", - "alt3", - - // 40 - 4f - "ldw (r0)", - "ldw (r1)", - "ldw (r2)", - "ldw (r3)", - "ldw (r4)", - "ldw (r5)", - "ldw (r6)", - "ldw (r7)", - "ldw (r8)", - "ldw (r9)", - "ldw (r10)", - "ldw (r11)", - "plot", - "swap", - "color", - "not", - - // 50 - 5f - "add #0", - "add #1", - "add #2", - "add #3", - "add #4", - "add #5", - "add #6", - "add #7", - "add #8", - "add #9", - "add #10", - "add #11", - "add #12", - "add #13", - "add #14", - "add #15", - - // 60 - 6f - "sub #0", - "sub #1", - "sub #2", - "sub #3", - "sub #4", - "sub #5", - "sub #6", - "sub #7", - "sub #8", - "sub #9", - "sub #10", - "sub #11", - "sub #12", - "sub #13", - "sub #14", - "sub #15", - - // 70 - 7f - "merge", - "and #1", - "and #2", - "and #3", - "and #4", - "and #5", - "and #6", - "and #7", - "and #8", - "and #9", - "and #10", - "and #11", - "and #12", - "and #13", - "and #14", - "and #15", - - // 80 - 8f - "mult #0", - "mult #1", - "mult #2", - "mult #3", - "mult #4", - "mult #5", - "mult #6", - "mult #7", - "mult #8", - "mult #9", - "mult #10", - "mult #11", - "mult #12", - "mult #13", - "mult #14", - "mult #15", - - // 90 - 9f - "sbk", - "link #1", - "link #2", - "link #3", - "link #4", - "sex", - "asr", - "ror", - "jmp (r8)", - "jmp (r9)", - "jmp (r10)", - "jmp (r11)", - "jmp (r12)", - "jmp (r13)", - "lob", - "fmult", - - // a0 - af - "sms ($%04x), r0", - "sms ($%04x), r1", - "sms ($%04x), r2", - "sms ($%04x), r3", - "sms ($%04x), r4", - "sms ($%04x), r5", - "sms ($%04x), r6", - "sms ($%04x), r7", - "sms ($%04x), r8", - "sms ($%04x), r9", - "sms ($%04x), r10", - "sms ($%04x), r11", - "sms ($%04x), r12", - "sms ($%04x), r13", - "sms ($%04x), r14", - "sms ($%04x), r15", - - // b0 - bf - "from r0", - "from r1", - "from r2", - "from r3", - "from r4", - "from r5", - "from r6", - "from r7", - "from r8", - "from r9", - "from r10", - "from r11", - "from r12", - "from r13", - "from r14", - "from r15", - - // c0 - cf - "hib", - "or #1", - "or #2", - "or #3", - "or #4", - "or #5", - "or #6", - "or #7", - "or #8", - "or #9", - "or #10", - "or #11", - "or #12", - "or #13", - "or #14", - "or #15", - - // d0 - df - "inc r0", - "inc r1", - "inc r2", - "inc r3", - "inc r4", - "inc r5", - "inc r6", - "inc r7", - "inc r8", - "inc r9", - "inc r10", - "inc r11", - "inc r12", - "inc r13", - "inc r14", - "ramb", - - // e0 - ef - "dec r0", - "dec r1", - "dec r2", - "dec r3", - "dec r4", - "dec r5", - "dec r6", - "dec r7", - "dec r8", - "dec r9", - "dec r10", - "dec r11", - "dec r12", - "dec r13", - "dec r14", - "getbl", - - // f0 - ff - "sm ($%04x), r0", - "sm ($%04x), r1", - "sm ($%04x), r2", - "sm ($%04x), r3", - "sm ($%04x), r4", - "sm ($%04x), r5", - "sm ($%04x), r6", - "sm ($%04x), r7", - "sm ($%04x), r8", - "sm ($%04x), r9", - "sm ($%04x), r10", - "sm ($%04x), r11", - "sm ($%04x), r12", - "sm ($%04x), r13", - "sm ($%04x), r14", - "sm ($%04x), r15", - - // ALT3 Table - - // 00 - 0f - "stop", - "nop", - "cache", - "lsr", - "rol", - "bra $%04x", - "blt $%04x", - "bge $%04x", - "bne $%04x", - "beq $%04x", - "bpl $%04x", - "bmi $%04x", - "bcc $%04x", - "bcs $%04x", - "bvc $%04x", - "bvs $%04x", - - // 10 - 1f - "to r0", - "to r1", - "to r2", - "to r3", - "to r4", - "to r5", - "to r6", - "to r7", - "to r8", - "to r9", - "to r10", - "to r11", - "to r12", - "to r13", - "to r14", - "to r15", - - // 20 - 2f - "with r0", - "with r1", - "with r2", - "with r3", - "with r4", - "with r5", - "with r6", - "with r7", - "with r8", - "with r9", - "with r10", - "with r11", - "with r12", - "with r13", - "with r14", - "with r15", - - // 30 - 3f - "stb (r0)", - "stb (r1)", - "stb (r2)", - "stb (r3)", - "stb (r4)", - "stb (r5)", - "stb (r6)", - "stb (r7)", - "stb (r8)", - "stb (r9)", - "stb (r10)", - "stb (r11)", - "loop", - "alt1", - "alt2", - "alt3", - - // 40 - 4f - "ldb (r0)", - "ldb (r1)", - "ldb (r2)", - "ldb (r3)", - "ldb (r4)", - "ldb (r5)", - "ldb (r6)", - "ldb (r7)", - "ldb (r8)", - "ldb (r9)", - "ldb (r10)", - "ldb (r11)", - "rpix", - "swap", - "cmode", - "not", - - // 50 - 5f - "adc #0", - "adc #1", - "adc #2", - "adc #3", - "adc #4", - "adc #5", - "adc #6", - "adc #7", - "adc #8", - "adc #9", - "adc #10", - "adc #11", - "adc #12", - "adc #13", - "adc #14", - "adc #15", - - // 60 - 6f - "cmp r0", - "cmp r1", - "cmp r2", - "cmp r3", - "cmp r4", - "cmp r5", - "cmp r6", - "cmp r7", - "cmp r8", - "cmp r9", - "cmp r10", - "cmp r11", - "cmp r12", - "cmp r13", - "cmp r14", - "cmp r15", - - // 70 - 7f - "merge", - "bic #1", - "bic #2", - "bic #3", - "bic #4", - "bic #5", - "bic #6", - "bic #7", - "bic #8", - "bic #9", - "bic #10", - "bic #11", - "bic #12", - "bic #13", - "bic #14", - "bic #15", - - // 80 - 8f - "umult #0", - "umult #1", - "umult #2", - "umult #3", - "umult #4", - "umult #5", - "umult #6", - "umult #7", - "umult #8", - "umult #9", - "umult #10", - "umult #11", - "umult #12", - "umult #13", - "umult #14", - "umult #15", - - // 90 - 9f - "sbk", - "link #1", - "link #2", - "link #3", - "link #4", - "sex", - "div2", - "ror", - "ljmp (r8)", - "ljmp (r9)", - "ljmp (r10)", - "ljmp (r11)", - "ljmp (r12)", - "ljmp (r13)", - "lob", - "lmult", - - // a0 - af - "lms r0, ($%04x)", - "lms r1, ($%04x)", - "lms r2, ($%04x)", - "lms r3, ($%04x)", - "lms r4, ($%04x)", - "lms r5, ($%04x)", - "lms r6, ($%04x)", - "lms r7, ($%04x)", - "lms r8, ($%04x)", - "lms r9, ($%04x)", - "lms r10, ($%04x)", - "lms r11, ($%04x)", - "lms r12, ($%04x)", - "lms r13, ($%04x)", - "lms r14, ($%04x)", - "lms r15, ($%04x)", - - // b0 - bf - "from r0", - "from r1", - "from r2", - "from r3", - "from r4", - "from r5", - "from r6", - "from r7", - "from r8", - "from r9", - "from r10", - "from r11", - "from r12", - "from r13", - "from r14", - "from r15", - - // c0 - cf - "hib", - "xor #1", - "xor #2", - "xor #3", - "xor #4", - "xor #5", - "xor #6", - "xor #7", - "xor #8", - "xor #9", - "xor #10", - "xor #11", - "xor #12", - "xor #13", - "xor #14", - "xor #15", - - // d0 - df - "inc r0", - "inc r1", - "inc r2", - "inc r3", - "inc r4", - "inc r5", - "inc r6", - "inc r7", - "inc r8", - "inc r9", - "inc r10", - "inc r11", - "inc r12", - "inc r13", - "inc r14", - "romb", - - // e0 - ef - "dec r0", - "dec r1", - "dec r2", - "dec r3", - "dec r4", - "dec r5", - "dec r6", - "dec r7", - "dec r8", - "dec r9", - "dec r10", - "dec r11", - "dec r12", - "dec r13", - "dec r14", - "getbs", - - // f0 - ff - "lm r0, ($%04x)", - "lm r1, ($%04x)", - "lm r2, ($%04x)", - "lm r3, ($%04x)", - "lm r4, ($%04x)", - "lm r5, ($%04x)", - "lm r6, ($%04x)", - "lm r7, ($%04x)", - "lm r8, ($%04x)", - "lm r9, ($%04x)", - "lm r10, ($%04x)", - "lm r11, ($%04x)", - "lm r12, ($%04x)", - "lm r13, ($%04x)", - "lm r14, ($%04x)", - "lm r15, ($%04x)" -}; -*/ - -/* -static void FxPipeString (char *pvString) -{ - uint32 vOpcode = (GSU.vStatusReg & 0x300) | ((uint32) PIPE); - const char *m = fx_apvMnemonicTable[vOpcode]; - uint8 vPipe1, vPipe2, vByte1, vByte2; - uint8 vPipeBank = GSU.vPipeAdr >> 16; - char *p; - - // The next two bytes after the pipe's address - vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr + 1)]; - vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr + 2)]; - - // The actual next two bytes to be read - vByte1 = PRGBANK(USEX16(R15)); - vByte2 = PRGBANK(USEX16(R15 + 1)); - - // Print ROM address of the pipe - sprintf(pvString, "%02x:%04x %02x ", USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); - p = &pvString[strlen(pvString)]; - - if (PIPE >= 0x05 && PIPE <= 0x0f) // Check if it's a branch instruction - { - sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); - #ifdef BRANCH_DELAY_RELATIVE - sprintf(p, m, USEX16(R15 + SEX8(vByte1) + 1)); - #else - sprintf(p, m, USEX16(R15 + SEX8(vByte1) - 1)); - #endif - } - else - if (PIPE >= 0x10 && PIPE <= 0x1f && TF(B)) // Check for 'move' instruction - sprintf(p, "move r%d, r%d", USEX8(PIPE & 0x0f), (uint32) (GSU.pvSreg - GSU.avReg)); - else - if (PIPE >= 0xa0 && PIPE <= 0xaf) // Check for 'ibt', 'lms' or 'sms' - { - sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); - if ((GSU.vStatusReg & 0x300) == 0x100 || (GSU.vStatusReg & 0x300) == 0x200) - sprintf(p, m, USEX16(vByte1) << 1); - else - sprintf(p, m, USEX16(vByte1)); - } - else - if (PIPE >= 0xb0 && PIPE <= 0xbf && TF(B)) // Check for 'moves' - sprintf(p, "moves r%d, r%d", (uint32) (GSU.pvDreg - GSU.avReg), USEX8(PIPE & 0x0f)); - else - if (PIPE >= 0xf0) // Check for 'iwt', 'lm' or 'sm' - { - sprintf(&pvString[11], "%02x %02x ", USEX8(vPipe1), USEX8(vPipe2)); - sprintf(p, m, USEX8(vByte1) | (USEX16(vByte2) << 8)); - } - else // Normal instruction - strcpy(p, m); -} -*/ - + char *p; + uint32 vOpcode = (GSU.vStatusReg & 0x300) | ((uint32)PIPE); + const char *m = fx_apvMnemonicTable[vOpcode]; + uint8 vPipe1,vPipe2,vByte1,vByte2; + uint8 vPipeBank = GSU.vPipeAdr >> 16; + + /* The next two bytes after the pipe's address */ + vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+1)]; + vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+2)]; + + /* The actual next two bytes to be read */ + vByte1 = PRGBANK(USEX16(R15)); + vByte2 = PRGBANK(USEX16(R15+1)); + + /* Print ROM address of the pipe */ + sprintf(pvString, "%02x:%04x %02x ", + USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); + p = &pvString[strlen(pvString)]; + + /* Check if it's a branch instruction */ + if( PIPE >= 0x05 && PIPE <= 0x0f ) + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); +#ifdef BRANCH_DELAY_RELATIVE + sprintf(p, m, USEX16(R15 + SEX8(vByte1) + 1 ) ); +#else + sprintf(p, m, USEX16(R15 + SEX8(vByte1) - 1 ) ); #endif + } + /* Check for 'move' instruction */ + else if( PIPE >= 0x10 && PIPE <= 0x1f && TF(B) ) + sprintf(p, "move r%d,r%d", USEX8(PIPE & 0x0f), (uint32)(GSU.pvSreg - GSU.avReg)); + /* Check for 'ibt', 'lms' or 'sms' */ + else if( PIPE >= 0xa0 && PIPE <= 0xaf ) + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); + if( (GSU.vStatusReg & 0x300) == 0x100 || (GSU.vStatusReg & 0x300) == 0x200 ) + sprintf(p, m, USEX16(vByte1) << 1 ); + else + sprintf(p, m, USEX16(vByte1) ); + } + /* Check for 'moves' */ + else if( PIPE >= 0xb0 && PIPE <= 0xbf && TF(B) ) + sprintf(p, "moves r%d,r%d", (uint32)(GSU.pvDreg - GSU.avReg), USEX8(PIPE & 0x0f)); + /* Check for 'iwt', 'lm' or 'sm' */ + else if( PIPE >= 0xf0 ) + { + sprintf(&pvString[11], "%02x %02x ", USEX8(vPipe1), USEX8(vPipe2)); + sprintf(p, m, USEX8(vByte1) | (USEX16(vByte2)<<8) ); + } + /* Normal instruction */ + else + strcpy(p, m); +} + +const char *fx_apvMnemonicTable[] = +{ + /* + * ALT0 Table + */ + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", + "stw (r8)","stw (r9)","stw (r10)","stw (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldw (r0)","ldw (r1)","ldw (r2)", "ldw (r3)", "ldw (r4)", "ldw (r5)", "ldw (r6)", "ldw (r7)", + "ldw (r8)","ldw (r9)","ldw (r10)","ldw (r11)","plot", "swap", "color", "not", + /* 50 - 5f */ + "add r0", "add r1", "add r2", "add r3", "add r4", "add r5", "add r6", "add r7", + "add r8", "add r9", "add r10", "add r11", "add r12", "add r13", "add r14", "add r15", + /* 60 - 6f */ + "sub r0", "sub r1", "sub r2", "sub r3", "sub r4", "sub r5", "sub r6", "sub r7", + "sub r8", "sub r9", "sub r10", "sub r11", "sub r12", "sub r13", "sub r14", "sub r15", + /* 70 - 7f */ + "merge", "and r1", "and r2", "and r3", "and r4", "and r5", "and r6", "and r7", + "and r8", "and r9", "and r10", "and r11", "and r12", "and r13", "and r14", "and r15", + /* 80 - 8f */ + "mult r0", "mult r1", "mult r2", "mult r3", "mult r4", "mult r5", "mult r6", "mult r7", + "mult r8", "mult r9", "mult r10", "mult r11", "mult r12", "mult r13", "mult r14", "mult r15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "asr", "ror", + "jmp (r8)","jmp (r9)","jmp (r10)","jmp (r11)","jmp (r12)","jmp (r13)","lob", "fmult", + /* a0 - af */ + "ibt r0,#$%02x", "ibt r1,#$%02x", "ibt r2,#$%02x", "ibt r3,#$%02x", + "ibt r4,#$%02x", "ibt r5,#$%02x", "ibt r6,#$%02x", "ibt r7,#$%02x", + "ibt r8,#$%02x", "ibt r9,#$%02x", "ibt r10,#$%02x", "ibt r11,#$%02x", + "ibt r12,#$%02x", "ibt r13,#$%02x", "ibt r14,#$%02x", "ibt r15,#$%02x", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "or r1", "or r2", "or r3", "or r4", "or r5", "or r6", "or r7", + "or r8", "or r9", "or r10", "or r11", "or r12", "or r13", "or r14", "or r15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "getc", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getb", + /* f0 - ff */ + "iwt r0,#$%04x", "iwt r1,#$%04x", "iwt r2,#$%04x", "iwt r3,#$%04x", + "iwt r4,#$%04x", "iwt r5,#$%04x", "iwt r6,#$%04x", "iwt r7,#$%04x", + "iwt r8,#$%04x", "iwt r9,#$%04x", "iwt r10,#$%04x", "iwt r11,#$%04x", + "iwt r12,#$%04x", "iwt r13,#$%04x", "iwt r14,#$%04x", "iwt r15,#$%04x", + + /* + * ALT1 Table + */ + + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", + "stb (r8)","stb (r9)","stb (r10)","stb (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldb (r0)","ldb (r1)","ldb (r2)", "ldb (r3)", "ldb (r4)", "ldb (r5)", "ldb (r6)", "ldb (r7)", + "ldb (r8)","ldb (r9)","ldb (r10)","ldb (r11)","rpix", "swap", "cmode", "not", + /* 50 - 5f */ + "adc r0", "adc r1", "adc r2", "adc r3", "adc r4", "adc r5", "adc r6", "adc r7", + "adc r8", "adc r9", "adc r10", "adc r11", "adc r12", "adc r13", "adc r14", "adc r15", + /* 60 - 6f */ + "sbc r0", "sbc r1", "sbc r2", "sbc r3", "sbc r4", "sbc r5", "sbc r6", "sbc r7", + "sbc r8", "sbc r9", "sbc r10", "sbc r11", "sbc r12", "sbc r13", "sbc r14", "sbc r15", + /* 70 - 7f */ + "merge", "bic r1", "bic r2", "bic r3", "bic r4", "bic r5", "bic r6", "bic r7", + "bic r8", "bic r9", "bic r10", "bic r11", "bic r12", "bic r13", "bic r14", "bic r15", + /* 80 - 8f */ + "umult r0","umult r1","umult r2", "umult r3", "umult r4", "umult r5", "umult r6", "umult r7", + "umult r8","umult r9","umult r10","umult r11","umult r12","umult r13","umult r14","umult r15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "div2", "ror", + "ljmp (r8)","ljmp (r9)","ljmp (r10)","ljmp (r11)", "ljmp (r12)", "ljmp (r13)", "lob", "lmult", + /* a0 - af */ + "lms r0,($%04x)", "lms r1,($%04x)", "lms r2,($%04x)", "lms r3,($%04x)", + "lms r4,($%04x)", "lms r5,($%04x)", "lms r6,($%04x)", "lms r7,($%04x)", + "lms r8,($%04x)", "lms r9,($%04x)", "lms r10,($%04x)", "lms r11,($%04x)", + "lms r12,($%04x)", "lms r13,($%04x)", "lms r14,($%04x)", "lms r15,($%04x)", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "xor r1", "xor r2", "xor r3", "xor r4", "xor r5", "xor r6", "xor r7", + "xor r8", "xor r9", "xor r10", "xor r11", "xor r12", "xor r13", "xor r14", "xor r15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "getc", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbh", + /* f0 - ff */ + "lm r0,($%04x)", "lm r1,($%04x)", "lm r2,($%04x)", "lm r3,($%04x)", + "lm r4,($%04x)", "lm r5,($%04x)", "lm r6,($%04x)", "lm r7,($%04x)", + "lm r8,($%04x)", "lm r9,($%04x)", "lm r10,($%04x)", "lm r11,($%04x)", + "lm r12,($%04x)", "lm r13,($%04x)", "lm r14,($%04x)", "lm r15,($%04x)", + + /* + * ALT2 Table + */ + + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", + "stw (r8)","stw (r9)","stw (r10)","stw (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldw (r0)","ldw (r1)","ldw (r2)", "ldw (r3)", "ldw (r4)", "ldw (r5)", "ldw (r6)", "ldw (r7)", + "ldw (r8)","ldw (r9)","ldw (r10)","ldw (r11)","plot", "swap", "color", "not", + /* 50 - 5f */ + "add #0", "add #1", "add #2", "add #3", "add #4", "add #5", "add #6", "add #7", + "add #8", "add #9", "add #10", "add #11", "add #12", "add #13", "add #14", "add #15", + /* 60 - 6f */ + "sub #0", "sub #1", "sub #2", "sub #3", "sub #4", "sub #5", "sub #6", "sub #7", + "sub #8", "sub #9", "sub #10", "sub #11", "sub #12", "sub #13", "sub #14", "sub #15", + /* 70 - 7f */ + "merge", "and #1", "and #2", "and #3", "and #4", "and #5", "and #6", "and #7", + "and #8", "and #9", "and #10", "and #11", "and #12", "and #13", "and #14", "and #15", + /* 80 - 8f */ + "mult #0", "mult #1", "mult #2", "mult #3", "mult #4", "mult #5", "mult #6", "mult #7", + "mult #8", "mult #9", "mult #10", "mult #11", "mult #12", "mult #13", "mult #14", "mult #15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "asr", "ror", + "jmp (r8)","jmp (r9)","jmp (r10)","jmp (r11)","jmp (r12)","jmp (r13)","lob", "fmult", + /* a0 - af */ + "sms ($%04x),r0", "sms ($%04x),r1", "sms ($%04x),r2", "sms ($%04x),r3", + "sms ($%04x),r4", "sms ($%04x),r5", "sms ($%04x),r6", "sms ($%04x),r7", + "sms ($%04x),r8", "sms ($%04x),r9", "sms ($%04x),r10", "sms ($%04x),r11", + "sms ($%04x),r12", "sms ($%04x),r13", "sms ($%04x),r14", "sms ($%04x),r15", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "or #1", "or #2", "or #3", "or #4", "or #5", "or #6", "or #7", + "or #8", "or #9", "or #10", "or #11", "or #12", "or #13", "or #14", "or #15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "ramb", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbl", + /* f0 - ff */ + "sm ($%04x),r0", "sm ($%04x),r1", "sm ($%04x),r2", "sm ($%04x),r3", + "sm ($%04x),r4", "sm ($%04x),r5", "sm ($%04x),r6", "sm ($%04x),r7", + "sm ($%04x),r8", "sm ($%04x),r9", "sm ($%04x),r10", "sm ($%04x),r11", + "sm ($%04x),r12", "sm ($%04x),r13", "sm ($%04x),r14", "sm ($%04x),r15", + + /* + * ALT3 Table + */ + + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", + "stb (r8)","stb (r9)","stb (r10)","stb (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldb (r0)","ldb (r1)","ldb (r2)", "ldb (r3)", "ldb (r4)", "ldb (r5)", "ldb (r6)", "ldb (r7)", + "ldb (r8)","ldb (r9)","ldb (r10)","ldb (r11)","rpix", "swap", "cmode", "not", + /* 50 - 5f */ + "adc #0", "adc #1", "adc #2", "adc #3", "adc #4", "adc #5", "adc #6", "adc #7", + "adc #8", "adc #9", "adc #10", "adc #11", "adc #12", "adc #13", "adc #14", "adc #15", + /* 60 - 6f */ + "cmp r0", "cmp r1", "cmp r2", "cmp r3", "cmp r4", "cmp r5", "cmp r6", "cmp r7", + "cmp r8", "cmp r9", "cmp r10", "cmp r11", "cmp r12", "cmp r13", "cmp r14", "cmp r15", + /* 70 - 7f */ + "merge", "bic #1", "bic #2", "bic #3", "bic #4", "bic #5", "bic #6", "bic #7", + "bic #8", "bic #9", "bic #10", "bic #11", "bic #12", "bic #13", "bic #14", "bic #15", + /* 80 - 8f */ + "umult #0","umult #1","umult #2", "umult #3", "umult #4", "umult #5", "umult #6", "umult #7", + "umult #8","umult #9","umult #10","umult #11","umult #12","umult #13","umult #14","umult #15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "div2", "ror", + "ljmp (r8)","ljmp (r9)","ljmp (r10)","ljmp (r11)", "ljmp (r12)", "ljmp (r13)", "lob", "lmult", + /* a0 - af */ + "lms r0,($%04x)", "lms r1,($%04x)", "lms r2,($%04x)", "lms r3,($%04x)", + "lms r4,($%04x)", "lms r5,($%04x)", "lms r6,($%04x)", "lms r7,($%04x)", + "lms r8,($%04x)", "lms r9,($%04x)", "lms r10,($%04x)", "lms r11,($%04x)", + "lms r12,($%04x)", "lms r13,($%04x)", "lms r14,($%04x)", "lms r15,($%04x)", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "xor #1", "xor #2", "xor #3", "xor #4", "xor #5", "xor #6", "xor #7", + "xor #8", "xor #9", "xor #10", "xor #11", "xor #12", "xor #13", "xor #14", "xor #15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "romb", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbs", + /* f0 - ff */ + "lm r0,($%04x)", "lm r1,($%04x)", "lm r2,($%04x)", "lm r3,($%04x)", + "lm r4,($%04x)", "lm r5,($%04x)", "lm r6,($%04x)", "lm r7,($%04x)", + "lm r8,($%04x)", "lm r9,($%04x)", "lm r10,($%04x)", "lm r11,($%04x)", + "lm r12,($%04x)", "lm r13,($%04x)", "lm r14,($%04x)", "lm r15,($%04x)", +}; + diff --git a/source/snes9x/fxemu.cpp b/source/snes9x/fxemu.cpp index 69da874..2b7e660 100644 --- a/source/snes9x/fxemu.cpp +++ b/source/snes9x/fxemu.cpp @@ -159,813 +159,644 @@ **********************************************************************************/ -#include "snes9x.h" -#include "memmap.h" -#include "fxinst.h" + #include "fxemu.h" +#include "fxinst.h" +#include +#include +#include -static void FxReset (struct FxInfo_s *); -static void fx_readRegisterSpace (void); -static void fx_writeRegisterSpace (void); -static void fx_updateRamBank (uint8); -static void fx_dirtySCBR (void); -static bool8 fx_checkStartAddress (void); -static uint32 FxEmulate (uint32); -static void FxCacheWriteAccess (uint16); -static void FxFlushCache (void); +/* The FxChip Emulator's internal variables */ +struct FxRegs_s GSU = FxRegs_s_null; +uint32 (**fx_ppfFunctionTable)(uint32) = 0; +void (**fx_ppfPlotTable)() = 0; +void (**fx_ppfOpcodeTable)() = 0; -void S9xInitSuperFX (void) +#if 0 +void fx_setCache() { - memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s)); + uint32 c; + GSU.bCacheActive = TRUE; + GSU.pvRegisters[0x3e] &= 0xf0; + c = (uint32)GSU.pvRegisters[0x3e]; + c |= ((uint32)GSU.pvRegisters[0x3f])<<8; + if(c == GSU.vCacheBaseReg) + return; + GSU.vCacheBaseReg = c; + GSU.vCacheFlags = 0; + if(c < (0x10000-512)) + { + uint8 const* t = &ROM(c); + memcpy(GSU.pvCache,t,512); + } + else + { + uint8 const* t1; + uint8 const* t2; + uint32 i = 0x10000 - c; + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache,t1,i); + memcpy(&GSU.pvCache[i],t2,512-i); + } } - -void S9xResetSuperFX (void) -{ - // FIXME: Snes9x can't execute CPU and SuperFX at a time. Don't ask me what is 0.417 :P - SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max)))); - SuperFX.oneLineDone = FALSE; - SuperFX.vFlags = 0; - FxReset(&SuperFX); -} - -void S9xSetSuperFX (uint8 byte, uint16 address) -{ - switch (address) - { - case 0x3030: - if ((Memory.FillRAM[0x3030] ^ byte) & FLG_G) - { - Memory.FillRAM[0x3030] = byte; - if (byte & FLG_G) - { - if (!SuperFX.oneLineDone) - { - S9xSuperFXExec(); - SuperFX.oneLineDone = TRUE; - } - } - else - FxFlushCache(); - } - else - Memory.FillRAM[0x3030] = byte; - - break; - - case 0x3031: - Memory.FillRAM[0x3031] = byte; - break; - - case 0x3033: - Memory.FillRAM[0x3033] = byte; - break; - - case 0x3034: - Memory.FillRAM[0x3034] = byte & 0x7f; - break; - - case 0x3036: - Memory.FillRAM[0x3036] = byte & 0x7f; - break; - - case 0x3037: - Memory.FillRAM[0x3037] = byte; - break; - - case 0x3038: - Memory.FillRAM[0x3038] = byte; - fx_dirtySCBR(); - break; - - case 0x3039: - Memory.FillRAM[0x3039] = byte; - break; - - case 0x303a: - Memory.FillRAM[0x303a] = byte; - break; - - case 0x303b: - break; - - case 0x303c: - Memory.FillRAM[0x303c] = byte; - fx_updateRamBank(byte); - break; - - case 0x303f: - Memory.FillRAM[0x303f] = byte; - break; - - case 0x301f: - Memory.FillRAM[0x301f] = byte; - Memory.FillRAM[0x3000 + GSU_SFR] |= FLG_G; - if (!SuperFX.oneLineDone) - { - S9xSuperFXExec(); - SuperFX.oneLineDone = TRUE; - } - - break; - - default: - Memory.FillRAM[address] = byte; - if (address >= 0x3100) - FxCacheWriteAccess(address); - - break; - } -} - -uint8 S9xGetSuperFX (uint16 address) -{ - uint8 byte; - - byte = Memory.FillRAM[address]; -#ifdef CPU_SHUTDOWN - if (address == 0x3030) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; #endif - if (address == 0x3031) - { - S9xClearIRQ(GSU_IRQ_SOURCE); - Memory.FillRAM[0x3031] = byte & 0x7f; - } - return (byte); +void FxCacheWriteAccess(uint16 vAddress) +{ +#if 0 + if(!GSU.bCacheActive) + { + uint8 v = GSU.pvCache[GSU.pvCache[vAddress&0x1ff]; + fx_setCache(); + GSU.pvCache[GSU.pvCache[vAddress&0x1ff] = v; + } +#endif + if((vAddress & 0x00f) == 0x00f) + GSU.vCacheFlags |= 1 << ((vAddress&0x1f0) >> 4); } -void S9xSuperFXExec (void) +void FxFlushCache() { - if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18) - { - FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine); - - uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8); - if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) - S9xSetIRQ(GSU_IRQ_SOURCE); - } + GSU.vCacheFlags = 0; + GSU.vCacheBaseReg = 0; + GSU.bCacheActive = FALSE; +// GSU.vPipe = 0x1; } -static void FxReset (struct FxInfo_s *psFxInfo) +static void fx_backupCache() { - // Clear all internal variables - memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s)); - - // Set default registers - GSU.pvSreg = GSU.pvDreg = &R0; - - // Set RAM and ROM pointers - GSU.pvRegisters = psFxInfo->pvRegisters; - GSU.nRamBanks = psFxInfo->nRamBanks; - GSU.pvRam = psFxInfo->pvRam; - GSU.nRomBanks = psFxInfo->nRomBanks; - GSU.pvRom = psFxInfo->pvRom; - GSU.vPrevScreenHeight = ~0; - GSU.vPrevMode = ~0; - - // The GSU can't access more than 2mb (16mbits) - if (GSU.nRomBanks > 0x20) - GSU.nRomBanks = 0x20; - - // Clear FxChip register space - memset(GSU.pvRegisters, 0, 0x300); - - // Set FxChip version Number - GSU.pvRegisters[0x3b] = 0; - - // Make ROM bank table - for (int i = 0; i < 256; i++) +#if 0 + uint32 i; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + if(v) + for(i=0; i<32; i++) { - uint32 b = i & 0x7f; - - if (b >= 0x40) + if(v&1) + { + if(c < (0x10000-16)) { - if (GSU.nRomBanks > 1) - b %= GSU.nRomBanks; - else - b &= 1; - - GSU.apvRomBank[i] = &GSU.pvRom[b << 16]; + uint8 * t = &GSU.pvPrgBank[c]; + memcpy(&GSU.avCacheBackup[i<<4],t,16); + memcpy(t,&GSU.pvCache[i<<4],16); } else { - b %= GSU.nRomBanks * 2; - GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x200000]; + uint8 * t1; + uint8 * t2; + uint32 a = 0x10000 - c; + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(&GSU.avCacheBackup[i<<4],t1,a); + memcpy(t1,&GSU.pvCache[i<<4],a); + memcpy(&GSU.avCacheBackup[(i<<4)+a],t2,16-a); + memcpy(t2,&GSU.pvCache[(i<<4)+a],16-a); } + } + c = USEX16(c+16); + v >>= 1; } - - // Make RAM bank table - for (int i = 0; i < 4; i++) - { - GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; - GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; - } - - // Start with a nop in the pipe - GSU.vPipe = 0x01; - - // Set pointer to GSU cache - GSU.pvCache = &GSU.pvRegisters[0x100]; - - fx_readRegisterSpace(); +#endif } -static void fx_readRegisterSpace (void) +static void fx_restoreCache() { - static uint32 avHeight[] = { 128, 160, 192, 256 }; - static uint32 avMult[] = { 16, 32, 32, 64 }; - - uint8 *p; - int n; - - GSU.vErrorCode = 0; - - // Update R0-R15 - p = GSU.pvRegisters; - for (int i = 0; i < 16; i++) +#if 0 + uint32 i; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + if(v) + for(i=0; i<32; i++) { - GSU.avReg[i] = *p++; - GSU.avReg[i] += ((uint32) (*p++)) << 8; + if(v&1) + { + if(c < (0x10000-16)) + { + uint8 * t = &GSU.pvPrgBank[c]; + memcpy(t,&GSU.avCacheBackup[i<<4],16); + memcpy(&GSU.pvCache[i<<4],t,16); + } + else + { + uint8 * t1; + uint8 * t2; + uint32 a = 0x10000 - c; + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(t1,&GSU.avCacheBackup[i<<4],a); + memcpy(&GSU.pvCache[i<<4],t1,a); + memcpy(t2,&GSU.avCacheBackup[(i<<4)+a],16-a); + memcpy(&GSU.pvCache[(i<<4)+a],t2,16-a); + } + } + c = USEX16(c+16); + v >>= 1; } - - // Update other registers - p = GSU.pvRegisters; - GSU.vStatusReg = (uint32) p[GSU_SFR]; - GSU.vStatusReg |= ((uint32) p[GSU_SFR + 1]) << 8; - GSU.vPrgBankReg = (uint32) p[GSU_PBR]; - GSU.vRomBankReg = (uint32) p[GSU_ROMBR]; - GSU.vRamBankReg = ((uint32) p[GSU_RAMBR]) & (FX_RAM_BANKS - 1); - GSU.vCacheBaseReg = (uint32) p[GSU_CBR]; - GSU.vCacheBaseReg |= ((uint32) p[GSU_CBR + 1]) << 8; - - // Update status register variables - GSU.vZero = !(GSU.vStatusReg & FLG_Z); - GSU.vSign = (GSU.vStatusReg & FLG_S) << 12; - GSU.vOverflow = (GSU.vStatusReg & FLG_OV) << 16; - GSU.vCarry = (GSU.vStatusReg & FLG_CY) >> 2; - - // Set bank pointers - GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; - GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; - GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; - - // Set screen pointers - GSU.pvScreenBase = &GSU.pvRam[USEX8(p[GSU_SCBR]) << 10]; - n = (int) (!!(p[GSU_SCMR] & 0x04)); - n |= ((int) (!!(p[GSU_SCMR] & 0x20))) << 1; - GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[n]; - GSU.vMode = p[GSU_SCMR] & 0x03; - - if (n == 3) - GSU.vScreenSize = (256 / 8) * (256 / 8) * 32; - else - GSU.vScreenSize = (GSU.vScreenHeight / 8) * (256 / 8) * avMult[GSU.vMode]; - - if (GSU.vPlotOptionReg & 0x10) // OBJ Mode (for drawing into sprites) - GSU.vScreenHeight = 256; - - if (GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) - GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; - - GSU.pfPlot = fx_PlotTable[GSU.vMode]; - GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; - - fx_OpcodeTable[0x04c] = GSU.pfPlot; - fx_OpcodeTable[0x14c] = GSU.pfRpix; - fx_OpcodeTable[0x24c] = GSU.pfPlot; - fx_OpcodeTable[0x34c] = GSU.pfRpix; - - fx_computeScreenPointers(); - - //fx_backupCache(); +#endif } -static void fx_writeRegisterSpace (void) +void fx_flushCache() { - uint8 *p; - - p = GSU.pvRegisters; - for (int i = 0; i < 16; i++) - { - *p++ = (uint8) GSU.avReg[i]; - *p++ = (uint8) (GSU.avReg[i] >> 8); - } - - // Update status register - if (USEX16(GSU.vZero) == 0) - SF(Z); - else - CF(Z); - - if (GSU.vSign & 0x8000) - SF(S); - else - CF(S); - - if (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) - SF(OV); - else - CF(OV); - - if (GSU.vCarry) - SF(CY); - else - CF(CY); - - p = GSU.pvRegisters; - p[GSU_SFR] = (uint8) GSU.vStatusReg; - p[GSU_SFR + 1] = (uint8) (GSU.vStatusReg >> 8); - p[GSU_PBR] = (uint8) GSU.vPrgBankReg; - p[GSU_ROMBR] = (uint8) GSU.vRomBankReg; - p[GSU_RAMBR] = (uint8) GSU.vRamBankReg; - p[GSU_CBR] = (uint8) GSU.vCacheBaseReg; - p[GSU_CBR + 1] = (uint8) (GSU.vCacheBaseReg >> 8); - - //fx_restoreCache(); + fx_restoreCache(); + GSU.vCacheFlags = 0; + GSU.bCacheActive = FALSE; } -// Update RamBankReg and RAM Bank pointer -static void fx_updateRamBank (uint8 byte) + +void fx_updateRamBank(uint8 Byte) { // Update BankReg and Bank pointer - GSU.vRamBankReg = (uint32) byte & (FX_RAM_BANKS - 1); - GSU.pvRamBank = GSU.apvRamBank[byte & 0x3]; + GSU.vRamBankReg = (uint32)Byte & (FX_RAM_BANKS-1); + GSU.pvRamBank = GSU.apvRamBank[Byte & 0x3]; } -// SCBR write seen. We need to update our cached screen pointers -static void fx_dirtySCBR (void) + +static void fx_readRegisterSpace() +{ + int i; + uint8 *p; + static uint32 avHeight[] = { 128, 160, 192, 256 }; + static uint32 avMult[] = { 16, 32, 32, 64 }; + + GSU.vErrorCode = 0; + + /* Update R0-R15 */ + p = GSU.pvRegisters; + for(i=0; i<16; i++) + { + GSU.avReg[i] = *p++; + GSU.avReg[i] += ((uint32)(*p++)) << 8; + } + + /* Update other registers */ + p = GSU.pvRegisters; + GSU.vStatusReg = (uint32)p[GSU_SFR]; + GSU.vStatusReg |= ((uint32)p[GSU_SFR+1]) << 8; + GSU.vPrgBankReg = (uint32)p[GSU_PBR]; + GSU.vRomBankReg = (uint32)p[GSU_ROMBR]; + GSU.vRamBankReg = ((uint32)p[GSU_RAMBR]) & (FX_RAM_BANKS-1); + GSU.vCacheBaseReg = (uint32)p[GSU_CBR]; + GSU.vCacheBaseReg |= ((uint32)p[GSU_CBR+1]) << 8; + + /* Update status register variables */ + GSU.vZero = !(GSU.vStatusReg & FLG_Z); + GSU.vSign = (GSU.vStatusReg & FLG_S) << 12; + GSU.vOverflow = (GSU.vStatusReg & FLG_OV) << 16; + GSU.vCarry = (GSU.vStatusReg & FLG_CY) >> 2; + + /* Set bank pointers */ + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; + + /* Set screen pointers */ + GSU.pvScreenBase = &GSU.pvRam[ USEX8(p[GSU_SCBR]) << 10 ]; + i = (int)(!!(p[GSU_SCMR] & 0x04)); + i |= ((int)(!!(p[GSU_SCMR] & 0x20))) << 1; + GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[i]; + GSU.vMode = p[GSU_SCMR] & 0x03; +#if 0 + if(GSU.vMode == 2) + error illegal color depth GSU.vMode; +#endif + if(i == 3) + GSU.vScreenSize = (256/8) * (256/8) * 32; + else + GSU.vScreenSize = (GSU.vScreenHeight/8) * (256/8) * avMult[GSU.vMode]; + if (GSU.vPlotOptionReg & 0x10) + { + /* OBJ Mode (for drawing into sprites) */ + GSU.vScreenHeight = 256; + } +#if 0 + if(GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) + error illegal address for screen base register +#else + if(GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) + GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; +#endif + GSU.pfPlot = fx_apfPlotTable[GSU.vMode]; + GSU.pfRpix = fx_apfPlotTable[GSU.vMode + 5]; + + fx_ppfOpcodeTable[0x04c] = GSU.pfPlot; + fx_ppfOpcodeTable[0x14c] = GSU.pfRpix; + fx_ppfOpcodeTable[0x24c] = GSU.pfPlot; + fx_ppfOpcodeTable[0x34c] = GSU.pfRpix; + + fx_computeScreenPointers (); + + fx_backupCache(); +} + +void fx_dirtySCBR() { GSU.vSCBRDirty = TRUE; } -static bool8 fx_checkStartAddress (void) +void fx_computeScreenPointers () { - // Check if we start inside the cache - if (GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg + 512)) - return (TRUE); + if (GSU.vMode != GSU.vPrevMode || + GSU.vPrevScreenHeight != GSU.vScreenHeight || + GSU.vSCBRDirty) + { + int i; - /* - // Check if we're in an unused area - if (GSU.vPrgBankReg < 0x40 && R15 < 0x8000) - return (FALSE); - */ + GSU.vSCBRDirty = FALSE; - if (GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) - return (FALSE); - - if (GSU.vPrgBankReg >= 0x74) - return (FALSE); - - // Check if we're in RAM and the RAN flag is not set - if (GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR & (1 << 3))) - return (FALSE); - - // If not, we're in ROM, so check if the RON flag is set - if (!(SCMR & (1 << 4))) - return (FALSE); - - return (TRUE); -} - -// Execute until the next stop instruction -static uint32 FxEmulate (uint32 nInstructions) -{ - uint32 vCount; - - // Read registers and initialize GSU session - fx_readRegisterSpace(); - - // Check if the start address is valid - if (!fx_checkStartAddress()) + /* Make a list of pointers to the start of each screen column */ + switch (GSU.vScreenHeight) { - CF(G); - fx_writeRegisterSpace(); - /* - GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; - return (FX_ERROR_ILLEGAL_ADDRESS); - */ - - return (0); - } - - // Execute GSU session - CF(IRQ); - - /* - if (GSU.bBreakPoint) - vCount = fx_run_to_breakpoint(nInstructions); - else - */ - vCount = fx_run(nInstructions); - - // Store GSU registers - fx_writeRegisterSpace(); - - // Check for error code - if (GSU.vErrorCode) - return (GSU.vErrorCode); - else - return (vCount); -} - -void fx_computeScreenPointers (void) -{ - if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) - { - GSU.vSCBRDirty = FALSE; - - // Make a list of pointers to the start of each screen column - switch (GSU.vScreenHeight) + case 128: + switch (GSU.vMode) { - case 128: - switch (GSU.vMode) - { - case 0: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = i << 8; - } - - break; - - case 1: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = i << 9; - } - - break; - - case 2: - case 3: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = i << 10; - } - - break; - } - - break; - - case 160: - switch (GSU.vMode) - { - case 0: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = (i << 8) + (i << 6); - } - - break; - - case 1: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = (i << 9) + (i << 7); - } - - break; - - case 2: - case 3: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = (i << 10) + (i << 8); - } - - break; - } - - break; - - case 192: - switch (GSU.vMode) - { - case 0: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = (i << 8) + (i << 7); - } - - break; - - case 1: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = (i << 9) + (i << 8); - } - - break; - - case 2: - case 3: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = (i << 10) + (i << 9); - } - - break; - } - - break; - - case 256: - switch (GSU.vMode) - { - case 0: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 9) + ((i & 0xf) << 8); - GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); - } - - break; - - case 1: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 10) + ((i & 0xf) << 9); - GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); - } - - break; - - case 2: - case 3: - for (int i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 11) + ((i & 0xf) << 10); - GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); - } - - break; - } - - break; - } - - GSU.vPrevMode = GSU.vMode; - GSU.vPrevScreenHeight = GSU.vScreenHeight; - } -} - -// Write access to the cache -static void FxCacheWriteAccess (uint16 vAddress) -{ - /* - if (!GSU.bCacheActive) - { - uint8 v = GSU.pvCache[GSU.pvCache[vAddress & 0x1ff]; - fx_setCache(); - GSU.pvCache[GSU.pvCache[vAddress & 0x1ff] = v; - } - */ - - if ((vAddress & 0x00f) == 0x00f) - GSU.vCacheFlags |= 1 << ((vAddress & 0x1f0) >> 4); -} - -static void FxFlushCache (void) -{ - GSU.vCacheFlags = 0; - GSU.vCacheBaseReg = 0; - GSU.bCacheActive = FALSE; - //GSU.vPipe = 0x1; -} - -void fx_flushCache (void) -{ - //fx_restoreCache(); - GSU.vCacheFlags = 0; - GSU.bCacheActive = FALSE; -} - -/* -static void fx_setCache (void) -{ - uint32 c; - - GSU.bCacheActive = TRUE; - GSU.pvRegisters[0x3e] &= 0xf0; - - c = (uint32) GSU.pvRegisters[0x3e]; - c |= ((uint32) GSU.pvRegisters[0x3f]) << 8; - if (c == GSU.vCacheBaseReg) - return; - - GSU.vCacheBaseReg = c; - GSU.vCacheFlags = 0; - - if (c < (0x10000 - 512)) - { - const uint8 *t = &ROM(c); - memcpy(GSU.pvCache, t, 512); - } - else - { - const uint8 *t1, *t2; - uint32 i = 0x10000 - c; - - t1 = &ROM(c); - t2 = &ROM(0); - memcpy(GSU.pvCache, t1, i); - memcpy(&GSU.pvCache[i], t2, 512 - i); - } -} -*/ - -/* -static void fx_backupCache (void) -{ - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - - if (v) - { - for (int i = 0; i < 32; i++) - { - if (v & 1) + case 0: + for (i = 0; i < 32; i++) { - if (c < (0x10000 - 16)) - { - uint8 *t = &GSU.pvPrgBank[c]; - memcpy(&GSU.avCacheBackup[i << 4], t, 16); - memcpy(t, &GSU.pvCache[i << 4], 16); - } - else - { - uint8 *t1, *t2; - uint32 a = 0x10000 - c; - - t1 = &GSU.pvPrgBank[c]; - t2 = &GSU.pvPrgBank[0]; - memcpy(&GSU.avCacheBackup[i << 4], t1, a); - memcpy(t1, &GSU.pvCache[i << 4], a); - memcpy(&GSU.avCacheBackup[(i << 4) + a], t2, 16 - a); - memcpy(t2, &GSU.pvCache[(i << 4) + a], 16 - a); - } + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = i << 8; } - - c = USEX16(c + 16); - v >>= 1; - } - } -} -*/ - -/* -static void fx_restoreCache() -{ - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - - if (v) - { - for (int i = 0; i < 32; i++) - { - if (v & 1) + break; + case 1: + for (i = 0; i < 32; i++) { - if (c < (0x10000 - 16)) - { - uint8 *t = &GSU.pvPrgBank[c]; - memcpy(t, &GSU.avCacheBackup[i << 4], 16); - memcpy(&GSU.pvCache[i << 4], t, 16); - } - else - { - uint8 *t1, *t2; - uint32 a = 0x10000 - c; - - t1 = &GSU.pvPrgBank[c]; - t2 = &GSU.pvPrgBank[0]; - memcpy(t1, &GSU.avCacheBackup[i << 4], a); - memcpy(&GSU.pvCache[i << 4], t1, a); - memcpy(t2, &GSU.avCacheBackup[(i << 4) + a], 16 - a); - memcpy(&GSU.pvCache[(i << 4) + a], t2, 16 - a); - } + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = i << 9; } - - c = USEX16(c + 16); - v >>= 1; + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = i << 10; + } + break; } + break; + case 160: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 6); + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = (i << 9) + (i << 7); + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = (i << 10) + (i << 8); + } + break; + } + break; + case 192: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 7); + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = (i << 9) + (i << 8); + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = (i << 10) + (i << 9); + } + break; + } + break; + case 256: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + + ((i & 0x10) << 9) + ((i & 0xf) << 8); + GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + + ((i & 0x10) << 10) + ((i & 0xf) << 9); + GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + + ((i & 0x10) << 11) + ((i & 0xf) << 10); + GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); + } + break; + } + break; } + GSU.vPrevMode = GSU.vMode; + GSU.vPrevScreenHeight = GSU.vScreenHeight; + } } -*/ -// Breakpoints -/* -static void FxBreakPointSet (uint32 vAddress) +static void fx_writeRegisterSpace() { - GSU.bBreakPoint = TRUE; - GSU.vBreakPoint = USEX16(vAddress); + int i; + uint8 *p; + + p = GSU.pvRegisters; + for(i=0; i<16; i++) + { + *p++ = (uint8)GSU.avReg[i]; + *p++ = (uint8)(GSU.avReg[i] >> 8); + } + + /* Update status register */ + if( USEX16(GSU.vZero) == 0 ) SF(Z); + else CF(Z); + if( GSU.vSign & 0x8000 ) SF(S); + else CF(S); + if(GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) SF(OV); + else CF(OV); + if(GSU.vCarry) SF(CY); + else CF(CY); + + p = GSU.pvRegisters; + p[GSU_SFR] = (uint8)GSU.vStatusReg; + p[GSU_SFR+1] = (uint8)(GSU.vStatusReg>>8); + p[GSU_PBR] = (uint8)GSU.vPrgBankReg; + p[GSU_ROMBR] = (uint8)GSU.vRomBankReg; + p[GSU_RAMBR] = (uint8)GSU.vRamBankReg; + p[GSU_CBR] = (uint8)GSU.vCacheBaseReg; + p[GSU_CBR+1] = (uint8)(GSU.vCacheBaseReg>>8); + + fx_restoreCache(); } -*/ -/* -static void FxBreakPointClear (void) +/* Reset the FxChip */ +void FxReset(struct FxInit_s *psFxInfo) { - GSU.bBreakPoint = FALSE; -} -*/ + int i; + static uint32 (**appfFunction[])(uint32) = { + &fx_apfFunctionTable[0], +#if 0 + &fx_a_apfFunctionTable[0], + &fx_r_apfFunctionTable[0], + &fx_ar_apfFunctionTable[0], +#endif + }; + static void (**appfPlot[])() = { + &fx_apfPlotTable[0], +#if 0 + &fx_a_apfPlotTable[0], + &fx_r_apfPlotTable[0], + &fx_ar_apfPlotTable[0], +#endif + }; + static void (**appfOpcode[])() = { + &fx_apfOpcodeTable[0], +#if 0 + &fx_a_apfOpcodeTable[0], + &fx_r_apfOpcodeTable[0], + &fx_ar_apfOpcodeTable[0], +#endif + }; -// Step by step execution -/* -static uint32 FxStepOver (uint32 nInstructions) -{ - uint32 vCount; + /* Get function pointers for the current emulation mode */ + fx_ppfFunctionTable = appfFunction[psFxInfo->vFlags & 0x3]; + fx_ppfPlotTable = appfPlot[psFxInfo->vFlags & 0x3]; + fx_ppfOpcodeTable = appfOpcode[psFxInfo->vFlags & 0x3]; - fx_readRegisterSpace(); + /* Clear all internal variables */ + memset((uint8*)&GSU,0,sizeof(struct FxRegs_s)); - if (!fx_checkStartAddress()) + /* Set default registers */ + GSU.pvSreg = GSU.pvDreg = &R0; + + /* Set RAM and ROM pointers */ + GSU.pvRegisters = psFxInfo->pvRegisters; + GSU.nRamBanks = psFxInfo->nRamBanks; + GSU.pvRam = psFxInfo->pvRam; + GSU.nRomBanks = psFxInfo->nRomBanks; + GSU.pvRom = psFxInfo->pvRom; + GSU.vPrevScreenHeight = ~0; + GSU.vPrevMode = ~0; + + /* The GSU can't access more than 2mb (16mbits) */ + if(GSU.nRomBanks > 0x20) + GSU.nRomBanks = 0x20; + + /* Clear FxChip register space */ + memset(GSU.pvRegisters,0,0x300); + + /* Set FxChip version Number */ + GSU.pvRegisters[0x3b] = 0; + + /* Make ROM bank table */ + for(i=0; i<256; i++) + { + uint32 b = i & 0x7f; + if (b >= 0x40) { - CF(G); - #if 0 - GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; - return (FX_ERROR_ILLEGAL_ADDRESS); - #else - return (0); - #endif + if (GSU.nRomBanks > 1) + b %= GSU.nRomBanks; + else + b &= 1; + + GSU.apvRomBank[i] = &GSU.pvRom[ b << 16 ]; } - - if (PIPE >= 0xf0) - GSU.vStepPoint = USEX16(R15 + 3); else - if ((PIPE >= 0x05 && PIPE <= 0x0f) || (PIPE >= 0xa0 && PIPE <= 0xaf)) - GSU.vStepPoint = USEX16(R15 + 2); - else - GSU.vStepPoint = USEX16(R15 + 1); + { + b %= GSU.nRomBanks * 2; + GSU.apvRomBank[i] = &GSU.pvRom[ (b << 16) + 0x200000]; + } + } - vCount = fx_step_over(nInstructions); + /* Make RAM bank table */ + for(i=0; i<4; i++) + { + GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; + GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; + } + /* Start with a nop in the pipe */ + GSU.vPipe = 0x01; + + /* Set pointer to GSU cache */ + GSU.pvCache = &GSU.pvRegisters[0x100]; + + fx_readRegisterSpace(); +} + +static uint8 fx_checkStartAddress() +{ + /* Check if we start inside the cache */ + if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) + return TRUE; + + /* Check if we're in an unused area */ +#if 0 + if(GSU.vPrgBankReg < 0x40 && R15 < 0x8000) + return FALSE; +#endif + if(GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) + return FALSE; + if(GSU.vPrgBankReg >= 0x74) + return FALSE; + + /* Check if we're in RAM and the RAN flag is not set */ + if(GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR&(1<<3)) ) + return FALSE; + + /* If not, we're in ROM, so check if the RON flag is set */ + if(!(SCMR&(1<<4))) + return FALSE; + + return TRUE; +} + +/* Execute until the next stop instruction */ +int FxEmulate(uint32 nInstructions) +{ + uint32 vCount; + + /* Read registers and initialize GSU session */ + fx_readRegisterSpace(); + + /* Check if the start address is valid */ + if(!fx_checkStartAddress()) + { + CF(G); fx_writeRegisterSpace(); +#if 0 + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return FX_ERROR_ILLEGAL_ADDRESS; +#else + return 0; +#endif + } - if (GSU.vErrorCode) - return (GSU.vErrorCode); - else - return (vCount); + /* Execute GSU session */ + CF(IRQ); + + if(GSU.bBreakPoint) + vCount = fx_ppfFunctionTable[FX_FUNCTION_RUN_TO_BREAKPOINT](nInstructions); + else + vCount = fx_ppfFunctionTable[FX_FUNCTION_RUN](nInstructions); + + /* Store GSU registers */ + fx_writeRegisterSpace(); + + /* Check for error code */ + if(GSU.vErrorCode) + return GSU.vErrorCode; + else + return vCount; } -*/ -// Errors -/* -static int FxGetErrorCode (void) +/* Breakpoints */ +void FxBreakPointSet(uint32 vAddress) { - return (GSU.vErrorCode); + GSU.bBreakPoint = TRUE; + GSU.vBreakPoint = USEX16(vAddress); } -*/ - -/* -static int FxGetIllegalAddress (void) +void FxBreakPointClear() { - return (GSU.vIllegalAddress); + GSU.bBreakPoint = FALSE; } -*/ -// Access to internal registers -/* -static uint32 FxGetColorRegister (void) +/* Step by step execution */ +int FxStepOver(uint32 nInstructions) { - return (GSU.vColorReg & 0xff); -} -*/ + uint32 vCount; + fx_readRegisterSpace(); -/* -static uint32 FxGetPlotOptionRegister (void) -{ - return (GSU.vPlotOptionReg & 0x1f); -} -*/ + /* Check if the start address is valid */ + if(!fx_checkStartAddress()) + { + CF(G); +#if 0 + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return FX_ERROR_ILLEGAL_ADDRESS; +#else + return 0; +#endif + } -/* -static uint32 FxGetSourceRegisterIndex (void) -{ - return (GSU.pvSreg - GSU.avReg); + if( PIPE >= 0xf0 ) + GSU.vStepPoint = USEX16(R15+3); + else if( (PIPE >= 0x05 && PIPE <= 0x0f) || (PIPE >= 0xa0 && PIPE <= 0xaf) ) + GSU.vStepPoint = USEX16(R15+2); + else + GSU.vStepPoint = USEX16(R15+1); + vCount = fx_ppfFunctionTable[FX_FUNCTION_STEP_OVER](nInstructions); + fx_writeRegisterSpace(); + if(GSU.vErrorCode) + return GSU.vErrorCode; + else + return vCount; } -*/ -/* -static uint32 FxGetDestinationRegisterIndex (void) +/* Errors */ +int FxGetErrorCode() { - return (GSU.pvDreg - GSU.avReg); + return GSU.vErrorCode; } -*/ -// Get the byte currently in the pipe -/* -static uint8 FxPipe (void) +int FxGetIllegalAddress() { - return (GSU.vPipe); + return GSU.vIllegalAddress; } -*/ + +/* Access to internal registers */ +uint32 FxGetColorRegister() +{ + return GSU.vColorReg & 0xff; +} + +uint32 FxGetPlotOptionRegister() +{ + return GSU.vPlotOptionReg & 0x1f; +} + +uint32 FxGetSourceRegisterIndex() +{ + return GSU.pvSreg - GSU.avReg; +} + +uint32 FxGetDestinationRegisterIndex() +{ + return GSU.pvDreg - GSU.avReg; +} + +uint8 FxPipe() +{ + return GSU.vPipe; +} + diff --git a/source/snes9x/fxemu.h b/source/snes9x/fxemu.h index bd7e422..a9e1ee4 100644 --- a/source/snes9x/fxemu.h +++ b/source/snes9x/fxemu.h @@ -159,62 +159,76 @@ **********************************************************************************/ + #ifndef _FXEMU_H_ -#define _FXEMU_H_ +#define _FXEMU_H_ 1 -#ifndef ZSNES_FX +#include "port.h" -// The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator -struct FxInfo_s +/* The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator */ +struct FxInit_s { - uint32 vFlags; - uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 - uint32 nRamBanks; // Number of 64kb-banks in GSU-RAM/BackupRAM (banks 0x70-0x73) - uint8 *pvRam; // Pointer to GSU-RAM - uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM - uint8 *pvRom; // Pointer to Cart-ROM + uint32 vFlags; + uint8 * pvRegisters; /* 768 bytes located in the memory at address 0x3000 */ + uint32 nRamBanks; /* Number of 64kb-banks in GSU-RAM/BackupRAM (banks 0x70-0x73) */ + uint8 * pvRam; /* Pointer to GSU-RAM */ + uint32 nRomBanks; /* Number of 32kb-banks in Cart-ROM */ + uint8 * pvRom; /* Pointer to Cart-ROM */ uint32 speedPerLine; bool8 oneLineDone; }; -extern struct FxInfo_s SuperFX; +/* Reset the FxChip */ +extern void FxReset(struct FxInit_s *psFxInfo); -void S9xInitSuperFX (void); -void S9xSetSuperFX (uint8, uint16); -uint8 S9xGetSuperFX (uint16); -void fx_flushCache (void); -void fx_computeScreenPointers (void); -uint32 fx_run (uint32); +/* Execute until the next stop instruction */ +extern int FxEmulate(uint32 nInstructions); -#define FX_BREAKPOINT (-1) -#define FX_ERROR_ILLEGAL_ADDRESS (-2) +/* Write access to the cache */ +extern void FxCacheWriteAccess(uint16 vAddress); +extern void FxFlushCache(); /* Callled when the G flag in SFR is set to zero */ -#else +/* Breakpoint */ +extern void FxBreakPointSet(uint32 vAddress); +extern void FxBreakPointClear(); -extern uint8 *SFXPlotTable; +/* Step by step execution */ +extern int FxStepOver(uint32 nInstructions); -#define S9xSetSuperFX S9xSuperFXWriteReg -#define S9xGetSuperFX S9xSuperFXReadReg +/* Errors */ +extern int FxGetErrorCode(); +extern int FxGetIllegalAddress(); -START_EXTERN_C -void S9xSuperFXWriteReg (uint8, uint32); -uint8 S9xSuperFXReadReg (uint32); -void S9xSuperFXPreSaveState (void); -void S9xSuperFXPostSaveState (void); -void S9xSuperFXPostLoadState (void); -END_EXTERN_C +/* Access to internal registers */ +extern uint32 FxGetColorRegister(); +extern uint32 FxGetPlotOptionRegister(); +extern uint32 FxGetSourceRegisterIndex(); +extern uint32 FxGetDestinationRegisterIndex(); + +/* Get string for opcode currently in the pipe */ +extern void FxPipeString(char * pvString); + +/* Get the byte currently in the pipe */ +extern uint8 FxPipe(); + +/* SCBR write seen. We need to update our cached screen pointers */ +extern void fx_dirtySCBR (void); + +/* Update RamBankReg and RAM Bank pointer */ +extern void fx_updateRamBank(uint8 Byte); + +/* Option flags */ +#define FX_FLAG_ADDRESS_CHECKING 0x01 +#define FX_FLAG_ROM_BUFFER 0x02 + +/* Return codes from FxEmulate(), FxStepInto() or FxStepOver() */ +#define FX_BREAKPOINT -1 +#define FX_ERROR_ILLEGAL_ADDRESS -2 + +/* Return the number of bytes in an opcode */ +#define OPCODE_BYTES(op) ((((op)>=0x05&&(op)<=0xf)||((op)>=0xa0&&(op)<=0xaf))?2:(((op)>=0xf0)?3:1)) + +extern void fx_computeScreenPointers (); #endif -#ifdef ZSNES_FX -START_EXTERN_C -#endif - -void S9xResetSuperFX (void); -void S9xSuperFXExec (void); - -#ifdef ZSNES_FX -END_EXTERN_C -#endif - -#endif diff --git a/source/snes9x/fxinst.cpp b/source/snes9x/fxinst.cpp index fc564d4..e669e9d 100644 --- a/source/snes9x/fxinst.cpp +++ b/source/snes9x/fxinst.cpp @@ -159,4250 +159,1832 @@ **********************************************************************************/ -#include "snes9x.h" -#include "fxinst.h" -#include "fxemu.h" -// Set this define if you wish the plot instruction to check for y-pos limits (I don't think it's nessecary) +#define FX_DO_ROMBUFFER + +#include "fxemu.h" +#include "fxinst.h" +#include +#include + +extern struct FxRegs_s GSU; +int gsu_bank [512] = {0}; + +/* Set this define if you wish the plot instruction to check for y-pos limits */ +/* (I don't think it's nessecary) */ #define CHECK_LIMITS +/* Codes used: + * + * rn = a GSU register (r0-r15) + * #n = 4 bit immediate value + * #pp = 8 bit immediate value + * (yy) = 8 bit word address (0x0000 - 0x01fe) + * #xx = 16 bit immediate value + * (xx) = 16 bit address (0x0000 - 0xffff) + * + */ -/* - Codes used: - rn = a GSU register (r0 - r15) - #n = 4 bit immediate value - #pp = 8 bit immediate value - (yy) = 8 bit word address (0x0000 - 0x01fe) - #xx = 16 bit immediate value - (xx) = 16 bit address (0x0000 - 0xffff) -*/ - -// 00 - stop - stop GSU execution (and maybe generate an IRQ) -static void fx_stop (void) +/* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ +static void fx_stop() { - CF(G); - GSU.vCounter = 0; - GSU.vInstCount = GSU.vCounter; + CF(G); + GSU.vCounter = 0; + GSU.vInstCount = GSU.vCounter; - // Check if we need to generate an IRQ - if (!(GSU.pvRegisters[GSU_CFGR] & 0x80)) - SF(IRQ); + /* Check if we need to generate an IRQ */ + if(!(GSU.pvRegisters[GSU_CFGR] & 0x80)) + SF(IRQ); - GSU.vPlotOptionReg = 0; - GSU.vPipe = 1; - CLRFLAGS; - R15++; + GSU.vPlotOptionReg = 0; + GSU.vPipe = 1; + CLRFLAGS; + R15++; } -// 01 - nop - no operation -static void fx_nop (void) -{ - CLRFLAGS; - R15++; -} +/* 01 - nop - no operation */ +static void fx_nop() { CLRFLAGS; R15++; } -// 02 - cache - reintialize GSU cache -static void fx_cache (void) -{ - uint32 c = R15 & 0xfff0; +extern void fx_flushCache(); - if (GSU.vCacheBaseReg != c || !GSU.bCacheActive) +/* 02 - cache - reintialize GSU cache */ +static void fx_cache() +{ + uint32 c = R15 & 0xfff0; + if(GSU.vCacheBaseReg != c || !GSU.bCacheActive) + { + fx_flushCache(); + GSU.vCacheBaseReg = c; + GSU.bCacheActive = TRUE; +#if 0 + if(c < (0x10000-512)) { - fx_flushCache(); - GSU.vCacheBaseReg = c; - GSU.bCacheActive = TRUE; - - #if 0 - if (c < (0x10000 - 512)) - { - const uint8 *t = &ROM(c); - memcpy(GSU.pvCache, t, 512); - } - else - { - const uint8 *t1, t2; - uint32 i = 0x10000 - c; - t1 = &ROM(c); - t2 = &ROM(0); - memcpy(GSU.pvCache, t1, i); - memcpy(&GSU.pvCache[i], t2, 512 - i); - } - #endif + uint8 const* t = &ROM(c); + memcpy(GSU.pvCache,t,512); } - - CLRFLAGS; - R15++; + else + { + uint8 const* t1; + uint8 const* t2; + uint32 i = 0x10000 - c; + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache,t1,i); + memcpy(&GSU.pvCache[i],t2,512-i); + } +#endif + } + R15++; + CLRFLAGS; } -// 03 - lsr - logic shift right -static void fx_lsr (void) +/* 03 - lsr - logic shift right */ +static void fx_lsr() { - uint32 v; - GSU.vCarry = SREG & 1; - v = USEX16(SREG) >> 1; - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; + uint32 v; + GSU.vCarry = SREG & 1; + v = USEX16(SREG) >> 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -// 04 - rol - rotate left -static void fx_rol (void) +/* 04 - rol - rotate left */ +static void fx_rol() { - uint32 v = USEX16((SREG << 1) + GSU.vCarry); - GSU.vCarry = (SREG >> 15) & 1; - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; + uint32 v = USEX16((SREG << 1) + GSU.vCarry); + GSU.vCarry = (SREG >> 15) & 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -// 05 - bra - branch always -static void fx_bra (void) -{ - uint8 v = PIPE; - R15++; - FETCHPIPE; - R15 += SEX8(v); -} +/* 05 - bra - branch always */ +static void fx_bra() { uint8 v = PIPE; R15++; FETCHPIPE; R15 += SEX8(v); } -// Branch on condition -#define BRA_COND(cond) \ - uint8 v = PIPE; \ - R15++; \ - FETCHPIPE; \ - if (cond) \ - R15 += SEX8(v); \ - else \ - R15++ +/* Branch on condition */ +#define BRA_COND(cond) uint8 v = PIPE; R15++; FETCHPIPE; if(cond) R15 += SEX8(v); else R15++; -#define TEST_S (GSU.vSign & 0x8000) -#define TEST_Z (USEX16(GSU.vZero) == 0) -#define TEST_OV (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) -#define TEST_CY (GSU.vCarry & 1) +#define TEST_S (GSU.vSign & 0x8000) +#define TEST_Z (USEX16(GSU.vZero) == 0) +#define TEST_OV (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) +#define TEST_CY (GSU.vCarry & 1) -// 06 - blt - branch on less than -static void fx_blt (void) -{ - BRA_COND((TEST_S != 0) != (TEST_OV != 0)); -} +/* 06 - blt - branch on less than */ +static void fx_blt() { BRA_COND( (TEST_S!=0) != (TEST_OV!=0) ); } -// 07 - bge - branch on greater or equals -static void fx_bge (void) -{ - BRA_COND((TEST_S != 0) == (TEST_OV != 0)); -} +/* 07 - bge - branch on greater or equals */ +static void fx_bge() { BRA_COND( (TEST_S!=0) == (TEST_OV!=0)); } -// 08 - bne - branch on not equal -static void fx_bne (void) -{ - BRA_COND(!TEST_Z); -} +/* 08 - bne - branch on not equal */ +static void fx_bne() { BRA_COND( !TEST_Z ); } -// 09 - beq - branch on equal -static void fx_beq (void) -{ - BRA_COND(TEST_Z); -} +/* 09 - beq - branch on equal */ +static void fx_beq() { BRA_COND( TEST_Z ); } -// 0a - bpl - branch on plus -static void fx_bpl (void) -{ - BRA_COND(!TEST_S); -} +/* 0a - bpl - branch on plus */ +static void fx_bpl() { BRA_COND( !TEST_S ); } -// 0b - bmi - branch on minus -static void fx_bmi (void) -{ - BRA_COND(TEST_S); -} +/* 0b - bmi - branch on minus */ +static void fx_bmi() { BRA_COND( TEST_S ); } -// 0c - bcc - branch on carry clear -static void fx_bcc (void) -{ - BRA_COND(!TEST_CY); -} +/* 0c - bcc - branch on carry clear */ +static void fx_bcc() { BRA_COND( !TEST_CY ); } -// 0d - bcs - branch on carry set -static void fx_bcs (void) -{ - BRA_COND(TEST_CY); -} +/* 0d - bcs - branch on carry set */ +static void fx_bcs() { BRA_COND( TEST_CY ); } -// 0e - bvc - branch on overflow clear -static void fx_bvc (void) -{ - BRA_COND(!TEST_OV); -} +/* 0e - bvc - branch on overflow clear */ +static void fx_bvc() { BRA_COND( !TEST_OV ); } -// 0f - bvs - branch on overflow set -static void fx_bvs (void) -{ - BRA_COND(TEST_OV); -} +/* 0f - bvs - branch on overflow set */ +static void fx_bvs() { BRA_COND( TEST_OV ); } -// 10-1f - to rn - set register n as destination register -// 10-1f (B) - move rn - move one register to another (if B flag is set) +/* 10-1f - to rn - set register n as destination register */ +/* 10-1f(B) - move rn - move one register to another (if B flag is set) */ #define FX_TO(reg) \ - if (TF(B)) \ - { \ - GSU.avReg[(reg)] = SREG; \ - CLRFLAGS; \ - } \ - else \ - GSU.pvDreg = &GSU.avReg[reg]; \ - R15++ - +if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; } \ +else { GSU.pvDreg = &GSU.avReg[reg]; } R15++; #define FX_TO_R14(reg) \ - if (TF(B)) \ - { \ - GSU.avReg[(reg)] = SREG; \ - CLRFLAGS; \ - READR14; \ - } \ - else \ - GSU.pvDreg = &GSU.avReg[reg]; \ - R15++ - +if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; READR14; } \ +else { GSU.pvDreg = &GSU.avReg[reg]; } R15++; #define FX_TO_R15(reg) \ - if (TF(B)) \ - { \ - GSU.avReg[(reg)] = SREG; \ - CLRFLAGS; \ - } \ - else \ - { \ - GSU.pvDreg = &GSU.avReg[reg]; \ - R15++; \ - } +if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; } \ +else { GSU.pvDreg = &GSU.avReg[reg]; R15++; } +static void fx_to_r0() { FX_TO(0); } +static void fx_to_r1() { FX_TO(1); } +static void fx_to_r2() { FX_TO(2); } +static void fx_to_r3() { FX_TO(3); } +static void fx_to_r4() { FX_TO(4); } +static void fx_to_r5() { FX_TO(5); } +static void fx_to_r6() { FX_TO(6); } +static void fx_to_r7() { FX_TO(7); } +static void fx_to_r8() { FX_TO(8); } +static void fx_to_r9() { FX_TO(9); } +static void fx_to_r10() { FX_TO(10); } +static void fx_to_r11() { FX_TO(11); } +static void fx_to_r12() { FX_TO(12); } +static void fx_to_r13() { FX_TO(13); } +static void fx_to_r14() { FX_TO_R14(14); } +static void fx_to_r15() { FX_TO_R15(15); } -static void fx_to_r0 (void) -{ - FX_TO(0); -} +/* 20-2f - to rn - set register n as source and destination register */ +#define FX_WITH(reg) SF(B); GSU.pvSreg = GSU.pvDreg = &GSU.avReg[reg]; R15++; +static void fx_with_r0() { FX_WITH(0); } +static void fx_with_r1() { FX_WITH(1); } +static void fx_with_r2() { FX_WITH(2); } +static void fx_with_r3() { FX_WITH(3); } +static void fx_with_r4() { FX_WITH(4); } +static void fx_with_r5() { FX_WITH(5); } +static void fx_with_r6() { FX_WITH(6); } +static void fx_with_r7() { FX_WITH(7); } +static void fx_with_r8() { FX_WITH(8); } +static void fx_with_r9() { FX_WITH(9); } +static void fx_with_r10() { FX_WITH(10); } +static void fx_with_r11() { FX_WITH(11); } +static void fx_with_r12() { FX_WITH(12); } +static void fx_with_r13() { FX_WITH(13); } +static void fx_with_r14() { FX_WITH(14); } +static void fx_with_r15() { FX_WITH(15); } -static void fx_to_r1 (void) -{ - FX_TO(1); -} - -static void fx_to_r2 (void) -{ - FX_TO(2); -} - -static void fx_to_r3 (void) -{ - FX_TO(3); -} - -static void fx_to_r4 (void) -{ - FX_TO(4); -} - -static void fx_to_r5 (void) -{ - FX_TO(5); -} - -static void fx_to_r6 (void) -{ - FX_TO(6); -} - -static void fx_to_r7 (void) -{ - FX_TO(7); -} - -static void fx_to_r8 (void) -{ - FX_TO(8); -} - -static void fx_to_r9 (void) -{ - FX_TO(9); -} - -static void fx_to_r10 (void) -{ - FX_TO(10); -} - -static void fx_to_r11 (void) -{ - FX_TO(11); -} - -static void fx_to_r12 (void) -{ - FX_TO(12); -} - -static void fx_to_r13 (void) -{ - FX_TO(13); -} - -static void fx_to_r14 (void) -{ - FX_TO_R14(14); -} - -static void fx_to_r15 (void) -{ - FX_TO_R15(15); -} - -// 20-2f - to rn - set register n as source and destination register -#define FX_WITH(reg) \ - SF(B); \ - GSU.pvSreg = GSU.pvDreg = &GSU.avReg[reg]; \ - R15++ - -static void fx_with_r0 (void) -{ - FX_WITH(0); -} - -static void fx_with_r1 (void) -{ - FX_WITH(1); -} - -static void fx_with_r2 (void) -{ - FX_WITH(2); -} - -static void fx_with_r3 (void) -{ - FX_WITH(3); -} - -static void fx_with_r4 (void) -{ - FX_WITH(4); -} - -static void fx_with_r5 (void) -{ - FX_WITH(5); -} - -static void fx_with_r6 (void) -{ - FX_WITH(6); -} - -static void fx_with_r7 (void) -{ - FX_WITH(7); -} - -static void fx_with_r8 (void) -{ - FX_WITH(8); -} - -static void fx_with_r9 (void) -{ - FX_WITH(9); -} - -static void fx_with_r10 (void) -{ - FX_WITH(10); -} - -static void fx_with_r11 (void) -{ - FX_WITH(11); -} - -static void fx_with_r12 (void) -{ - FX_WITH(12); -} - -static void fx_with_r13 (void) -{ - FX_WITH(13); -} - -static void fx_with_r14 (void) -{ - FX_WITH(14); -} - -static void fx_with_r15 (void) -{ - FX_WITH(15); -} - -// 30-3b - stw (rn) - store word +/* 30-3b - stw (rn) - store word */ #define FX_STW(reg) \ - GSU.vLastRamAdr = GSU.avReg[reg]; \ - RAM(GSU.avReg[reg]) = (uint8) SREG; \ - RAM(GSU.avReg[reg] ^ 1) = (uint8) (SREG >> 8); \ - CLRFLAGS; \ - R15++ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +RAM(GSU.avReg[reg]) = (uint8)SREG; \ +RAM(GSU.avReg[reg]^1) = (uint8)(SREG>>8); \ +CLRFLAGS; R15++ +static void fx_stw_r0() { FX_STW(0); } +static void fx_stw_r1() { FX_STW(1); } +static void fx_stw_r2() { FX_STW(2); } +static void fx_stw_r3() { FX_STW(3); } +static void fx_stw_r4() { FX_STW(4); } +static void fx_stw_r5() { FX_STW(5); } +static void fx_stw_r6() { FX_STW(6); } +static void fx_stw_r7() { FX_STW(7); } +static void fx_stw_r8() { FX_STW(8); } +static void fx_stw_r9() { FX_STW(9); } +static void fx_stw_r10() { FX_STW(10); } +static void fx_stw_r11() { FX_STW(11); } -static void fx_stw_r0 (void) -{ - FX_STW(0); -} - -static void fx_stw_r1 (void) -{ - FX_STW(1); -} - -static void fx_stw_r2 (void) -{ - FX_STW(2); -} - -static void fx_stw_r3 (void) -{ - FX_STW(3); -} - -static void fx_stw_r4 (void) -{ - FX_STW(4); -} - -static void fx_stw_r5 (void) -{ - FX_STW(5); -} - -static void fx_stw_r6 (void) -{ - FX_STW(6); -} - -static void fx_stw_r7 (void) -{ - FX_STW(7); -} - -static void fx_stw_r8 (void) -{ - FX_STW(8); -} - -static void fx_stw_r9 (void) -{ - FX_STW(9); -} - -static void fx_stw_r10 (void) -{ - FX_STW(10); -} - -static void fx_stw_r11 (void) -{ - FX_STW(11); -} - -// 30-3b (ALT1) - stb (rn) - store byte +/* 30-3b(ALT1) - stb (rn) - store byte */ #define FX_STB(reg) \ - GSU.vLastRamAdr = GSU.avReg[reg]; \ - RAM(GSU.avReg[reg]) = (uint8) SREG; \ - CLRFLAGS; \ - R15++ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +RAM(GSU.avReg[reg]) = (uint8)SREG; \ +CLRFLAGS; R15++ +static void fx_stb_r0() { FX_STB(0); } +static void fx_stb_r1() { FX_STB(1); } +static void fx_stb_r2() { FX_STB(2); } +static void fx_stb_r3() { FX_STB(3); } +static void fx_stb_r4() { FX_STB(4); } +static void fx_stb_r5() { FX_STB(5); } +static void fx_stb_r6() { FX_STB(6); } +static void fx_stb_r7() { FX_STB(7); } +static void fx_stb_r8() { FX_STB(8); } +static void fx_stb_r9() { FX_STB(9); } +static void fx_stb_r10() { FX_STB(10); } +static void fx_stb_r11() { FX_STB(11); } -static void fx_stb_r0 (void) +/* 3c - loop - decrement loop counter, and branch on not zero */ +static void fx_loop() { - FX_STB(0); -} - -static void fx_stb_r1 (void) -{ - FX_STB(1); -} - -static void fx_stb_r2 (void) -{ - FX_STB(2); -} - -static void fx_stb_r3 (void) -{ - FX_STB(3); -} - -static void fx_stb_r4 (void) -{ - FX_STB(4); -} - -static void fx_stb_r5 (void) -{ - FX_STB(5); -} - -static void fx_stb_r6 (void) -{ - FX_STB(6); -} - -static void fx_stb_r7 (void) -{ - FX_STB(7); -} - -static void fx_stb_r8 (void) -{ - FX_STB(8); -} - -static void fx_stb_r9 (void) -{ - FX_STB(9); -} - -static void fx_stb_r10 (void) -{ - FX_STB(10); -} - -static void fx_stb_r11 (void) -{ - FX_STB(11); -} - -// 3c - loop - decrement loop counter, and branch on not zero -static void fx_loop (void) -{ - GSU.vSign = GSU.vZero = --R12; - if ((uint16) R12 != 0) - R15 = R13; - else - R15++; - CLRFLAGS; -} - -// 3d - alt1 - set alt1 mode -static void fx_alt1 (void) -{ - SF(ALT1); - CF(B); + GSU.vSign = GSU.vZero = --R12; + if( (uint16) R12 != 0 ) + R15 = R13; + else R15++; + + CLRFLAGS; } -// 3e - alt2 - set alt2 mode -static void fx_alt2 (void) +/* 3d - alt1 - set alt1 mode */ +static void fx_alt1() { SF(ALT1); CF(B); R15++; } + +/* 3e - alt2 - set alt2 mode */ +static void fx_alt2() { SF(ALT2); CF(B); R15++; } + +/* 3f - alt3 - set alt3 mode */ +static void fx_alt3() { SF(ALT1); SF(ALT2); CF(B); R15++; } + +/* 40-4b - ldw (rn) - load word from RAM */ +#define FX_LDW(reg) uint32 v; \ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +v = (uint32)RAM(GSU.avReg[reg]); \ +v |= ((uint32)RAM(GSU.avReg[reg]^1))<<8; \ +R15++; DREG = v; \ +TESTR14; \ +CLRFLAGS +static void fx_ldw_r0() { FX_LDW(0); } +static void fx_ldw_r1() { FX_LDW(1); } +static void fx_ldw_r2() { FX_LDW(2); } +static void fx_ldw_r3() { FX_LDW(3); } +static void fx_ldw_r4() { FX_LDW(4); } +static void fx_ldw_r5() { FX_LDW(5); } +static void fx_ldw_r6() { FX_LDW(6); } +static void fx_ldw_r7() { FX_LDW(7); } +static void fx_ldw_r8() { FX_LDW(8); } +static void fx_ldw_r9() { FX_LDW(9); } +static void fx_ldw_r10() { FX_LDW(10); } +static void fx_ldw_r11() { FX_LDW(11); } + +/* 40-4b(ALT1) - ldb (rn) - load byte */ +#define FX_LDB(reg) uint32 v; \ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +v = (uint32)RAM(GSU.avReg[reg]); \ +R15++; DREG = v; \ +TESTR14; \ +CLRFLAGS +static void fx_ldb_r0() { FX_LDB(0); } +static void fx_ldb_r1() { FX_LDB(1); } +static void fx_ldb_r2() { FX_LDB(2); } +static void fx_ldb_r3() { FX_LDB(3); } +static void fx_ldb_r4() { FX_LDB(4); } +static void fx_ldb_r5() { FX_LDB(5); } +static void fx_ldb_r6() { FX_LDB(6); } +static void fx_ldb_r7() { FX_LDB(7); } +static void fx_ldb_r8() { FX_LDB(8); } +static void fx_ldb_r9() { FX_LDB(9); } +static void fx_ldb_r10() { FX_LDB(10); } +static void fx_ldb_r11() { FX_LDB(11); } + +/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_2bit() { - SF(ALT2); - CF(B); - R15++; -} + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; -// 3f - alt3 - set alt3 mode -static void fx_alt3 (void) -{ - SF(ALT1); - SF(ALT2); - CF(B); - R15++; -} - -// 40-4b - ldw (rn) - load word from RAM -#define FX_LDW(reg) \ - uint32 v; \ - GSU.vLastRamAdr = GSU.avReg[reg]; \ - v = (uint32) RAM(GSU.avReg[reg]); \ - v |= ((uint32) RAM(GSU.avReg[reg] ^ 1)) << 8; \ - R15++; \ - DREG = v; \ - TESTR14; \ - CLRFLAGS - -static void fx_ldw_r0 (void) -{ - FX_LDW(0); -} - -static void fx_ldw_r1 (void) -{ - FX_LDW(1); -} - -static void fx_ldw_r2 (void) -{ - FX_LDW(2); -} - -static void fx_ldw_r3 (void) -{ - FX_LDW(3); -} - -static void fx_ldw_r4 (void) -{ - FX_LDW(4); -} - -static void fx_ldw_r5 (void) -{ - FX_LDW(5); -} - -static void fx_ldw_r6 (void) -{ - FX_LDW(6); -} - -static void fx_ldw_r7 (void) -{ - FX_LDW(7); -} - -static void fx_ldw_r8 (void) -{ - FX_LDW(8); -} - -static void fx_ldw_r9 (void) -{ - FX_LDW(9); -} - -static void fx_ldw_r10 (void) -{ - FX_LDW(10); -} - -static void fx_ldw_r11 (void) -{ - FX_LDW(11); -} - -// 40-4b (ALT1) - ldb (rn) - load byte -#define FX_LDB(reg) \ - uint32 v; \ - GSU.vLastRamAdr = GSU.avReg[reg]; \ - v = (uint32) RAM(GSU.avReg[reg]); \ - R15++; \ - DREG = v; \ - TESTR14; \ - CLRFLAGS - -static void fx_ldb_r0 (void) -{ - FX_LDB(0); -} - -static void fx_ldb_r1 (void) -{ - FX_LDB(1); -} - -static void fx_ldb_r2 (void) -{ - FX_LDB(2); -} - -static void fx_ldb_r3 (void) -{ - FX_LDB(3); -} - -static void fx_ldb_r4 (void) -{ - FX_LDB(4); -} - -static void fx_ldb_r5 (void) -{ - FX_LDB(5); -} - -static void fx_ldb_r6 (void) -{ - FX_LDB(6); -} - -static void fx_ldb_r7 (void) -{ - FX_LDB(7); -} - -static void fx_ldb_r8 (void) -{ - FX_LDB(8); -} - -static void fx_ldb_r9 (void) -{ - FX_LDB(9); -} - -static void fx_ldb_r10 (void) -{ - FX_LDB(10); -} - -static void fx_ldb_r11 (void) -{ - FX_LDB(11); -} - -// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color -static void fx_plot_2bit (void) -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v, c; - - R15++; - CLRFLAGS; - R1++; + R15++; + CLRFLAGS; + R1++; #ifdef CHECK_LIMITS - if (y >= GSU.vScreenHeight) - return; + if(y >= GSU.vScreenHeight) return; #endif + if(GSU.vPlotOptionReg & 0x02) + c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; + else + c = (uint8)GSU.vColorReg; - if (GSU.vPlotOptionReg & 0x02) - c = (x ^ y) & 1 ? (uint8) (GSU.vColorReg >> 4) : (uint8) GSU.vColorReg; - else - c = (uint8) GSU.vColorReg; + if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); - if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) - return; - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x & 7); - - if (c & 0x01) - a[0] |= v; - else - a[0] &= ~v; - - if (c & 0x02) - a[1] |= v; - else - a[1] &= ~v; + if(c & 0x01) a[0] |= v; + else a[0] &= ~v; + if(c & 0x02) a[1] |= v; + else a[1] &= ~v; } -// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y -static void fx_rpix_2bit (void) +/* 2c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static void fx_rpix_2bit() { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; - R15++; - CLRFLAGS; + R15++; + CLRFLAGS; +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + DREG = 0; + DREG |= ((uint32)((a[0] & v) != 0)) << 0; + DREG |= ((uint32)((a[1] & v) != 0)) << 1; + TESTR14; +} + +/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_4bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; + + R15++; + CLRFLAGS; + R1++; #ifdef CHECK_LIMITS - if (y >= GSU.vScreenHeight) - return; + if(y >= GSU.vScreenHeight) return; #endif + if(GSU.vPlotOptionReg & 0x02) + c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; + else + c = (uint8)GSU.vColorReg; - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x & 7); + if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; - DREG = 0; - DREG |= ((uint32) ((a[0] & v) != 0)) << 0; - DREG |= ((uint32) ((a[1] & v) != 0)) << 1; - TESTR14; + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + if(c & 0x01) a[0x00] |= v; + else a[0x00] &= ~v; + if(c & 0x02) a[0x01] |= v; + else a[0x01] &= ~v; + if(c & 0x04) a[0x10] |= v; + else a[0x10] &= ~v; + if(c & 0x08) a[0x11] |= v; + else a[0x11] &= ~v; } -// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color -static void fx_plot_4bit (void) +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static void fx_rpix_4bit() { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v, c; + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; - R15++; - CLRFLAGS; - R1++; + R15++; + CLRFLAGS; #ifdef CHECK_LIMITS - if (y >= GSU.vScreenHeight) - return; + if(y >= GSU.vScreenHeight) return; #endif - if (GSU.vPlotOptionReg & 0x02) - c = (x ^ y) & 1 ? (uint8) (GSU.vColorReg >> 4) : (uint8) GSU.vColorReg; - else - c = (uint8) GSU.vColorReg; + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); - if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) - return; - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x & 7); - - if (c & 0x01) - a[0x00] |= v; - else - a[0x00] &= ~v; - - if (c & 0x02) - a[0x01] |= v; - else - a[0x01] &= ~v; - - if (c & 0x04) - a[0x10] |= v; - else - a[0x10] &= ~v; - - if (c & 0x08) - a[0x11] |= v; - else - a[0x11] &= ~v; + DREG = 0; + DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; + TESTR14; } -// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y -static void fx_rpix_4bit (void) +/* 8c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_8bit() { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; - R15++; - CLRFLAGS; + R15++; + CLRFLAGS; + R1++; #ifdef CHECK_LIMITS - if (y >= GSU.vScreenHeight) - return; + if(y >= GSU.vScreenHeight) return; #endif + c = (uint8)GSU.vColorReg; + if( !(GSU.vPlotOptionReg & 0x10) ) + { + if( !(GSU.vPlotOptionReg & 0x01) && !(c&0xf)) return; + } + else + if( !(GSU.vPlotOptionReg & 0x01) && !c) return; - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x & 7); + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); - DREG = 0; - DREG |= ((uint32) ((a[0x00] & v) != 0)) << 0; - DREG |= ((uint32) ((a[0x01] & v) != 0)) << 1; - DREG |= ((uint32) ((a[0x10] & v) != 0)) << 2; - DREG |= ((uint32) ((a[0x11] & v) != 0)) << 3; - TESTR14; + if(c & 0x01) a[0x00] |= v; + else a[0x00] &= ~v; + if(c & 0x02) a[0x01] |= v; + else a[0x01] &= ~v; + if(c & 0x04) a[0x10] |= v; + else a[0x10] &= ~v; + if(c & 0x08) a[0x11] |= v; + else a[0x11] &= ~v; + if(c & 0x10) a[0x20] |= v; + else a[0x20] &= ~v; + if(c & 0x20) a[0x21] |= v; + else a[0x21] &= ~v; + if(c & 0x40) a[0x30] |= v; + else a[0x30] &= ~v; + if(c & 0x80) a[0x31] |= v; + else a[0x31] &= ~v; } -// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color -static void fx_plot_8bit (void) +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static void fx_rpix_8bit() { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v, c; + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; - R15++; - CLRFLAGS; - R1++; + R15++; + CLRFLAGS; #ifdef CHECK_LIMITS - if (y >= GSU.vScreenHeight) - return; + if(y >= GSU.vScreenHeight) return; #endif + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); - c = (uint8) GSU.vColorReg; - if (!(GSU.vPlotOptionReg & 0x10)) - { - if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) - return; - } - else - if (!(GSU.vPlotOptionReg & 0x01) && !c) - return; - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x & 7); - - if (c & 0x01) - a[0x00] |= v; - else - a[0x00] &= ~v; - - if (c & 0x02) - a[0x01] |= v; - else - a[0x01] &= ~v; - - if (c & 0x04) - a[0x10] |= v; - else - a[0x10] &= ~v; - - if (c & 0x08) - a[0x11] |= v; - else - a[0x11] &= ~v; - - if (c & 0x10) - a[0x20] |= v; - else - a[0x20] &= ~v; - - if (c & 0x20) - a[0x21] |= v; - else - a[0x21] &= ~v; - - if (c & 0x40) - a[0x30] |= v; - else - a[0x30] &= ~v; - - if (c & 0x80) - a[0x31] |= v; - else - a[0x31] &= ~v; + DREG = 0; + DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; + DREG |= ((uint32)((a[0x20] & v) != 0)) << 4; + DREG |= ((uint32)((a[0x21] & v) != 0)) << 5; + DREG |= ((uint32)((a[0x30] & v) != 0)) << 6; + DREG |= ((uint32)((a[0x31] & v) != 0)) << 7; + GSU.vZero = DREG; + TESTR14; } -// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y -static void fx_rpix_8bit (void) +/* 4o - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_obj() { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; - - R15++; - CLRFLAGS; - -#ifdef CHECK_LIMITS - if (y >= GSU.vScreenHeight) - return; -#endif - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x & 7); - - DREG = 0; - DREG |= ((uint32) ((a[0x00] & v) != 0)) << 0; - DREG |= ((uint32) ((a[0x01] & v) != 0)) << 1; - DREG |= ((uint32) ((a[0x10] & v) != 0)) << 2; - DREG |= ((uint32) ((a[0x11] & v) != 0)) << 3; - DREG |= ((uint32) ((a[0x20] & v) != 0)) << 4; - DREG |= ((uint32) ((a[0x21] & v) != 0)) << 5; - DREG |= ((uint32) ((a[0x30] & v) != 0)) << 6; - DREG |= ((uint32) ((a[0x31] & v) != 0)) << 7; - GSU.vZero = DREG; - TESTR14; + //printf ("ERROR fx_plot_obj called\n"); } -// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color -static void fx_plot_obj (void) +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static void fx_rpix_obj() { -#ifdef DEBUGGER - fprintf(stderr, "ERROR fx_plot_obj called\n"); -#endif + //printf ("ERROR fx_rpix_obj called\n"); } -// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y -static void fx_rpix_obj (void) +/* 4d - swap - swap upper and lower byte of a register */ +static void fx_swap() { -#ifdef DEBUGGER - fprintf(stderr, "ERROR fx_rpix_obj called\n"); -#endif + uint8 c = (uint8)SREG; + uint8 d = (uint8)(SREG>>8); + uint32 v = (((uint32)c)<<8)|((uint32)d); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -// 4d - swap - swap upper and lower byte of a register -static void fx_swap (void) +/* 4e - color - copy source register to color register */ +static void fx_color() { - uint8 c = (uint8) SREG; - uint8 d = (uint8) (SREG >> 8); - uint32 v = (((uint32) c) << 8) | ((uint32) d); - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; + uint8 c = (uint8)SREG; + if(GSU.vPlotOptionReg & 0x04) + c = (c&0xf0) | (c>>4); + if(GSU.vPlotOptionReg & 0x08) + { + GSU.vColorReg &= 0xf0; + GSU.vColorReg |= c & 0x0f; + } + else + GSU.vColorReg = USEX8(c); + CLRFLAGS; + R15++; } -// 4e - color - copy source register to color register -static void fx_color (void) +/* 4e(ALT1) - cmode - set plot option register */ +static void fx_cmode() { - uint8 c = (uint8) SREG; + GSU.vPlotOptionReg = SREG; - if (GSU.vPlotOptionReg & 0x04) - c = (c & 0xf0) | (c >> 4); - if (GSU.vPlotOptionReg & 0x08) - { - GSU.vColorReg &= 0xf0; - GSU.vColorReg |= c & 0x0f; - } - else - GSU.vColorReg = USEX8(c); + if(GSU.vPlotOptionReg & 0x10) + { + /* OBJ Mode (for drawing into sprites) */ + GSU.vScreenHeight = 256; + } + else + GSU.vScreenHeight = GSU.vScreenRealHeight; - CLRFLAGS; - R15++; + fx_computeScreenPointers (); + CLRFLAGS; + R15++; } -// 4e (ALT1) - cmode - set plot option register -static void fx_cmode (void) +/* 4f - not - perform exclusive exor with 1 on all bits */ +static void fx_not() { - GSU.vPlotOptionReg = SREG; - - if (GSU.vPlotOptionReg & 0x10) - GSU.vScreenHeight = 256; // OBJ Mode (for drawing into sprites) - else - GSU.vScreenHeight = GSU.vScreenRealHeight; - - fx_computeScreenPointers(); - CLRFLAGS; - R15++; + uint32 v = ~SREG; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -// 4f - not - perform exclusive exor with 1 on all bits -static void fx_not (void) -{ - uint32 v = ~SREG; - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -// 50-5f - add rn - add, register + register +/* 50-5f - add rn - add, register + register */ #define FX_ADD(reg) \ - int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]); \ - GSU.vCarry = s >= 0x10000; \ - GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]); \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_add_r0() { FX_ADD(0); } +static void fx_add_r1() { FX_ADD(1); } +static void fx_add_r2() { FX_ADD(2); } +static void fx_add_r3() { FX_ADD(3); } +static void fx_add_r4() { FX_ADD(4); } +static void fx_add_r5() { FX_ADD(5); } +static void fx_add_r6() { FX_ADD(6); } +static void fx_add_r7() { FX_ADD(7); } +static void fx_add_r8() { FX_ADD(8); } +static void fx_add_r9() { FX_ADD(9); } +static void fx_add_r10() { FX_ADD(10); } +static void fx_add_r11() { FX_ADD(11); } +static void fx_add_r12() { FX_ADD(12); } +static void fx_add_r13() { FX_ADD(13); } +static void fx_add_r14() { FX_ADD(14); } +static void fx_add_r15() { FX_ADD(15); } -static void fx_add_r0 (void) -{ - FX_ADD(0); -} - -static void fx_add_r1 (void) -{ - FX_ADD(1); -} - -static void fx_add_r2 (void) -{ - FX_ADD(2); -} - -static void fx_add_r3 (void) -{ - FX_ADD(3); -} - -static void fx_add_r4 (void) -{ - FX_ADD(4); -} - -static void fx_add_r5 (void) -{ - FX_ADD(5); -} - -static void fx_add_r6 (void) -{ - FX_ADD(6); -} - -static void fx_add_r7 (void) -{ - FX_ADD(7); -} - -static void fx_add_r8 (void) -{ - FX_ADD(8); -} - -static void fx_add_r9 (void) -{ - FX_ADD(9); -} - -static void fx_add_r10 (void) -{ - FX_ADD(10); -} - -static void fx_add_r11 (void) -{ - FX_ADD(11); -} - -static void fx_add_r12 (void) -{ - FX_ADD(12); -} - -static void fx_add_r13 (void) -{ - FX_ADD(13); -} - -static void fx_add_r14 (void) -{ - FX_ADD(14); -} - -static void fx_add_r15 (void) -{ - FX_ADD(15); -} - -// 50-5f (ALT1) - adc rn - add with carry, register + register +/* 50-5f(ALT1) - adc rn - add with carry, register + register */ #define FX_ADC(reg) \ - int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]) + SEX16(GSU.vCarry); \ - GSU.vCarry = s >= 0x10000; \ - GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]) + SEX16(GSU.vCarry); \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_adc_r0() { FX_ADC(0); } +static void fx_adc_r1() { FX_ADC(1); } +static void fx_adc_r2() { FX_ADC(2); } +static void fx_adc_r3() { FX_ADC(3); } +static void fx_adc_r4() { FX_ADC(4); } +static void fx_adc_r5() { FX_ADC(5); } +static void fx_adc_r6() { FX_ADC(6); } +static void fx_adc_r7() { FX_ADC(7); } +static void fx_adc_r8() { FX_ADC(8); } +static void fx_adc_r9() { FX_ADC(9); } +static void fx_adc_r10() { FX_ADC(10); } +static void fx_adc_r11() { FX_ADC(11); } +static void fx_adc_r12() { FX_ADC(12); } +static void fx_adc_r13() { FX_ADC(13); } +static void fx_adc_r14() { FX_ADC(14); } +static void fx_adc_r15() { FX_ADC(15); } -static void fx_adc_r0 (void) -{ - FX_ADC(0); -} - -static void fx_adc_r1 (void) -{ - FX_ADC(1); -} - -static void fx_adc_r2 (void) -{ - FX_ADC(2); -} - -static void fx_adc_r3 (void) -{ - FX_ADC(3); -} - -static void fx_adc_r4 (void) -{ - FX_ADC(4); -} - -static void fx_adc_r5 (void) -{ - FX_ADC(5); -} - -static void fx_adc_r6 (void) -{ - FX_ADC(6); -} - -static void fx_adc_r7 (void) -{ - FX_ADC(7); -} - -static void fx_adc_r8 (void) -{ - FX_ADC(8); -} - -static void fx_adc_r9 (void) -{ - FX_ADC(9); -} - -static void fx_adc_r10 (void) -{ - FX_ADC(10); -} - -static void fx_adc_r11 (void) -{ - FX_ADC(11); -} - -static void fx_adc_r12 (void) -{ - FX_ADC(12); -} - -static void fx_adc_r13 (void) -{ - FX_ADC(13); -} - -static void fx_adc_r14 (void) -{ - FX_ADC(14); -} - -static void fx_adc_r15 (void) -{ - FX_ADC(15); -} - -// 50-5f (ALT2) - add #n - add, register + immediate +/* 50-5f(ALT2) - add #n - add, register + immediate */ #define FX_ADD_I(imm) \ - int32 s = SUSEX16(SREG) + imm; \ - GSU.vCarry = s >= 0x10000; \ - GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) + imm; \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_add_i0() { FX_ADD_I(0); } +static void fx_add_i1() { FX_ADD_I(1); } +static void fx_add_i2() { FX_ADD_I(2); } +static void fx_add_i3() { FX_ADD_I(3); } +static void fx_add_i4() { FX_ADD_I(4); } +static void fx_add_i5() { FX_ADD_I(5); } +static void fx_add_i6() { FX_ADD_I(6); } +static void fx_add_i7() { FX_ADD_I(7); } +static void fx_add_i8() { FX_ADD_I(8); } +static void fx_add_i9() { FX_ADD_I(9); } +static void fx_add_i10() { FX_ADD_I(10); } +static void fx_add_i11() { FX_ADD_I(11); } +static void fx_add_i12() { FX_ADD_I(12); } +static void fx_add_i13() { FX_ADD_I(13); } +static void fx_add_i14() { FX_ADD_I(14); } +static void fx_add_i15() { FX_ADD_I(15); } -static void fx_add_i0 (void) -{ - FX_ADD_I(0); -} - -static void fx_add_i1 (void) -{ - FX_ADD_I(1); -} - -static void fx_add_i2 (void) -{ - FX_ADD_I(2); -} - -static void fx_add_i3 (void) -{ - FX_ADD_I(3); -} - -static void fx_add_i4 (void) -{ - FX_ADD_I(4); -} - -static void fx_add_i5 (void) -{ - FX_ADD_I(5); -} - -static void fx_add_i6 (void) -{ - FX_ADD_I(6); -} - -static void fx_add_i7 (void) -{ - FX_ADD_I(7); -} - -static void fx_add_i8 (void) -{ - FX_ADD_I(8); -} - -static void fx_add_i9 (void) -{ - FX_ADD_I(9); -} - -static void fx_add_i10 (void) -{ - FX_ADD_I(10); -} - -static void fx_add_i11 (void) -{ - FX_ADD_I(11); -} - -static void fx_add_i12 (void) -{ - FX_ADD_I(12); -} - -static void fx_add_i13 (void) -{ - FX_ADD_I(13); -} - -static void fx_add_i14 (void) -{ - FX_ADD_I(14); -} - -static void fx_add_i15 (void) -{ - FX_ADD_I(15); -} - -// 50-5f (ALT3) - adc #n - add with carry, register + immediate +/* 50-5f(ALT3) - adc #n - add with carry, register + immediate */ #define FX_ADC_I(imm) \ - int32 s = SUSEX16(SREG) + imm + SUSEX16(GSU.vCarry); \ - GSU.vCarry = s >= 0x10000; \ - GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) + imm + SUSEX16(GSU.vCarry); \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_adc_i0() { FX_ADC_I(0); } +static void fx_adc_i1() { FX_ADC_I(1); } +static void fx_adc_i2() { FX_ADC_I(2); } +static void fx_adc_i3() { FX_ADC_I(3); } +static void fx_adc_i4() { FX_ADC_I(4); } +static void fx_adc_i5() { FX_ADC_I(5); } +static void fx_adc_i6() { FX_ADC_I(6); } +static void fx_adc_i7() { FX_ADC_I(7); } +static void fx_adc_i8() { FX_ADC_I(8); } +static void fx_adc_i9() { FX_ADC_I(9); } +static void fx_adc_i10() { FX_ADC_I(10); } +static void fx_adc_i11() { FX_ADC_I(11); } +static void fx_adc_i12() { FX_ADC_I(12); } +static void fx_adc_i13() { FX_ADC_I(13); } +static void fx_adc_i14() { FX_ADC_I(14); } +static void fx_adc_i15() { FX_ADC_I(15); } -static void fx_adc_i0 (void) -{ - FX_ADC_I(0); -} - -static void fx_adc_i1 (void) -{ - FX_ADC_I(1); -} - -static void fx_adc_i2 (void) -{ - FX_ADC_I(2); -} - -static void fx_adc_i3 (void) -{ - FX_ADC_I(3); -} - -static void fx_adc_i4 (void) -{ - FX_ADC_I(4); -} - -static void fx_adc_i5 (void) -{ - FX_ADC_I(5); -} - -static void fx_adc_i6 (void) -{ - FX_ADC_I(6); -} - -static void fx_adc_i7 (void) -{ - FX_ADC_I(7); -} - -static void fx_adc_i8 (void) -{ - FX_ADC_I(8); -} - -static void fx_adc_i9 (void) -{ - FX_ADC_I(9); -} - -static void fx_adc_i10 (void) -{ - FX_ADC_I(10); -} - -static void fx_adc_i11 (void) -{ - FX_ADC_I(11); -} - -static void fx_adc_i12 (void) -{ - FX_ADC_I(12); -} - -static void fx_adc_i13 (void) -{ - FX_ADC_I(13); -} - -static void fx_adc_i14 (void) -{ - FX_ADC_I(14); -} - -static void fx_adc_i15 (void) -{ - FX_ADC_I(15); -} - -// 60-6f - sub rn - subtract, register - register +/* 60-6f - sub rn - subtract, register - register */ #define FX_SUB(reg) \ - int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ - GSU.vCarry = s >= 0; \ - GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_sub_r0() { FX_SUB(0); } +static void fx_sub_r1() { FX_SUB(1); } +static void fx_sub_r2() { FX_SUB(2); } +static void fx_sub_r3() { FX_SUB(3); } +static void fx_sub_r4() { FX_SUB(4); } +static void fx_sub_r5() { FX_SUB(5); } +static void fx_sub_r6() { FX_SUB(6); } +static void fx_sub_r7() { FX_SUB(7); } +static void fx_sub_r8() { FX_SUB(8); } +static void fx_sub_r9() { FX_SUB(9); } +static void fx_sub_r10() { FX_SUB(10); } +static void fx_sub_r11() { FX_SUB(11); } +static void fx_sub_r12() { FX_SUB(12); } +static void fx_sub_r13() { FX_SUB(13); } +static void fx_sub_r14() { FX_SUB(14); } +static void fx_sub_r15() { FX_SUB(15); } -static void fx_sub_r0 (void) -{ - FX_SUB(0); -} - -static void fx_sub_r1 (void) -{ - FX_SUB(1); -} - -static void fx_sub_r2 (void) -{ - FX_SUB(2); -} - -static void fx_sub_r3 (void) -{ - FX_SUB(3); -} - -static void fx_sub_r4 (void) -{ - FX_SUB(4); -} - -static void fx_sub_r5 (void) -{ - FX_SUB(5); -} - -static void fx_sub_r6 (void) -{ - FX_SUB(6); -} - -static void fx_sub_r7 (void) -{ - FX_SUB(7); -} - -static void fx_sub_r8 (void) -{ - FX_SUB(8); -} - -static void fx_sub_r9 (void) -{ - FX_SUB(9); -} - -static void fx_sub_r10 (void) -{ - FX_SUB(10); -} - -static void fx_sub_r11 (void) -{ - FX_SUB(11); -} - -static void fx_sub_r12 (void) -{ - FX_SUB(12); -} - -static void fx_sub_r13 (void) -{ - FX_SUB(13); -} - -static void fx_sub_r14 (void) -{ - FX_SUB(14); -} - -static void fx_sub_r15 (void) -{ - FX_SUB(15); -} - -// 60-6f (ALT1) - sbc rn - subtract with carry, register - register +/* 60-6f(ALT1) - sbc rn - subtract with carry, register - register */ #define FX_SBC(reg) \ - int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]) - (SUSEX16(GSU.vCarry ^ 1)); \ - GSU.vCarry = s >= 0; \ - GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]) - (SUSEX16(GSU.vCarry^1)); \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_sbc_r0() { FX_SBC(0); } +static void fx_sbc_r1() { FX_SBC(1); } +static void fx_sbc_r2() { FX_SBC(2); } +static void fx_sbc_r3() { FX_SBC(3); } +static void fx_sbc_r4() { FX_SBC(4); } +static void fx_sbc_r5() { FX_SBC(5); } +static void fx_sbc_r6() { FX_SBC(6); } +static void fx_sbc_r7() { FX_SBC(7); } +static void fx_sbc_r8() { FX_SBC(8); } +static void fx_sbc_r9() { FX_SBC(9); } +static void fx_sbc_r10() { FX_SBC(10); } +static void fx_sbc_r11() { FX_SBC(11); } +static void fx_sbc_r12() { FX_SBC(12); } +static void fx_sbc_r13() { FX_SBC(13); } +static void fx_sbc_r14() { FX_SBC(14); } +static void fx_sbc_r15() { FX_SBC(15); } -static void fx_sbc_r0 (void) -{ - FX_SBC(0); -} - -static void fx_sbc_r1 (void) -{ - FX_SBC(1); -} - -static void fx_sbc_r2 (void) -{ - FX_SBC(2); -} - -static void fx_sbc_r3 (void) -{ - FX_SBC(3); -} - -static void fx_sbc_r4 (void) -{ - FX_SBC(4); -} - -static void fx_sbc_r5 (void) -{ - FX_SBC(5); -} - -static void fx_sbc_r6 (void) -{ - FX_SBC(6); -} - -static void fx_sbc_r7 (void) -{ - FX_SBC(7); -} - -static void fx_sbc_r8 (void) -{ - FX_SBC(8); -} - -static void fx_sbc_r9 (void) -{ - FX_SBC(9); -} - -static void fx_sbc_r10 (void) -{ - FX_SBC(10); -} - -static void fx_sbc_r11 (void) -{ - FX_SBC(11); -} - -static void fx_sbc_r12 (void) -{ - FX_SBC(12); -} - -static void fx_sbc_r13 (void) -{ - FX_SBC(13); -} - -static void fx_sbc_r14 (void) -{ - FX_SBC(14); -} - -static void fx_sbc_r15 (void) -{ - FX_SBC(15); -} - -// 60-6f (ALT2) - sub #n - subtract, register - immediate +/* 60-6f(ALT2) - sub #n - subtract, register - immediate */ #define FX_SUB_I(imm) \ - int32 s = SUSEX16(SREG) - imm; \ - GSU.vCarry = s >= 0; \ - GSU.vOverflow = (SREG ^ imm) & (SREG ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - DREG = s; \ - TESTR14; \ - CLRFLAGS +int32 s = SUSEX16(SREG) - imm; \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ imm) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static void fx_sub_i0() { FX_SUB_I(0); } +static void fx_sub_i1() { FX_SUB_I(1); } +static void fx_sub_i2() { FX_SUB_I(2); } +static void fx_sub_i3() { FX_SUB_I(3); } +static void fx_sub_i4() { FX_SUB_I(4); } +static void fx_sub_i5() { FX_SUB_I(5); } +static void fx_sub_i6() { FX_SUB_I(6); } +static void fx_sub_i7() { FX_SUB_I(7); } +static void fx_sub_i8() { FX_SUB_I(8); } +static void fx_sub_i9() { FX_SUB_I(9); } +static void fx_sub_i10() { FX_SUB_I(10); } +static void fx_sub_i11() { FX_SUB_I(11); } +static void fx_sub_i12() { FX_SUB_I(12); } +static void fx_sub_i13() { FX_SUB_I(13); } +static void fx_sub_i14() { FX_SUB_I(14); } +static void fx_sub_i15() { FX_SUB_I(15); } -static void fx_sub_i0 (void) -{ - FX_SUB_I(0); -} - -static void fx_sub_i1 (void) -{ - FX_SUB_I(1); -} - -static void fx_sub_i2 (void) -{ - FX_SUB_I(2); -} - -static void fx_sub_i3 (void) -{ - FX_SUB_I(3); -} - -static void fx_sub_i4 (void) -{ - FX_SUB_I(4); -} - -static void fx_sub_i5 (void) -{ - FX_SUB_I(5); -} - -static void fx_sub_i6 (void) -{ - FX_SUB_I(6); -} - -static void fx_sub_i7 (void) -{ - FX_SUB_I(7); -} - -static void fx_sub_i8 (void) -{ - FX_SUB_I(8); -} - -static void fx_sub_i9 (void) -{ - FX_SUB_I(9); -} - -static void fx_sub_i10 (void) -{ - FX_SUB_I(10); -} - -static void fx_sub_i11 (void) -{ - FX_SUB_I(11); -} - -static void fx_sub_i12 (void) -{ - FX_SUB_I(12); -} - -static void fx_sub_i13 (void) -{ - FX_SUB_I(13); -} - -static void fx_sub_i14 (void) -{ - FX_SUB_I(14); -} - -static void fx_sub_i15 (void) -{ - FX_SUB_I(15); -} - -// 60-6f (ALT3) - cmp rn - compare, register, register +/* 60-6f(ALT3) - cmp rn - compare, register, register */ #define FX_CMP(reg) \ - int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ - GSU.vCarry = s >= 0; \ - GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ - GSU.vSign = s; \ - GSU.vZero = s; \ - R15++; \ - CLRFLAGS +int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; \ +CLRFLAGS; +static void fx_cmp_r0() { FX_CMP(0); } +static void fx_cmp_r1() { FX_CMP(1); } +static void fx_cmp_r2() { FX_CMP(2); } +static void fx_cmp_r3() { FX_CMP(3); } +static void fx_cmp_r4() { FX_CMP(4); } +static void fx_cmp_r5() { FX_CMP(5); } +static void fx_cmp_r6() { FX_CMP(6); } +static void fx_cmp_r7() { FX_CMP(7); } +static void fx_cmp_r8() { FX_CMP(8); } +static void fx_cmp_r9() { FX_CMP(9); } +static void fx_cmp_r10() { FX_CMP(10); } +static void fx_cmp_r11() { FX_CMP(11); } +static void fx_cmp_r12() { FX_CMP(12); } +static void fx_cmp_r13() { FX_CMP(13); } +static void fx_cmp_r14() { FX_CMP(14); } +static void fx_cmp_r15() { FX_CMP(15); } -static void fx_cmp_r0 (void) +/* 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) */ +static void fx_merge() { - FX_CMP(0); + uint32 v = (R7&0xff00) | ((R8&0xff00)>>8); + R15++; DREG = v; + GSU.vOverflow = (v & 0xc0c0) << 16; + GSU.vZero = !(v & 0xf0f0); + GSU.vSign = ((v | (v<<8)) & 0x8000); + GSU.vCarry = (v & 0xe0e0) != 0; + TESTR14; + CLRFLAGS; } -static void fx_cmp_r1 (void) -{ - FX_CMP(1); -} - -static void fx_cmp_r2 (void) -{ - FX_CMP(2); -} - -static void fx_cmp_r3 (void) -{ - FX_CMP(3); -} - -static void fx_cmp_r4 (void) -{ - FX_CMP(4); -} - -static void fx_cmp_r5 (void) -{ - FX_CMP(5); -} - -static void fx_cmp_r6 (void) -{ - FX_CMP(6); -} - -static void fx_cmp_r7 (void) -{ - FX_CMP(7); -} - -static void fx_cmp_r8 (void) -{ - FX_CMP(8); -} - -static void fx_cmp_r9 (void) -{ - FX_CMP(9); -} - -static void fx_cmp_r10 (void) -{ - FX_CMP(10); -} - -static void fx_cmp_r11 (void) -{ - FX_CMP(11); -} - -static void fx_cmp_r12 (void) -{ - FX_CMP(12); -} - -static void fx_cmp_r13 (void) -{ - FX_CMP(13); -} - -static void fx_cmp_r14 (void) -{ - FX_CMP(14); -} - -static void fx_cmp_r15 (void) -{ - FX_CMP(15); -} - -// 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) -static void fx_merge (void) -{ - uint32 v = (R7 & 0xff00) | ((R8 & 0xff00) >> 8); - R15++; - DREG = v; - GSU.vOverflow = (v & 0xc0c0) << 16; - GSU.vZero = !(v & 0xf0f0); - GSU.vSign = ((v | (v << 8)) & 0x8000); - GSU.vCarry = (v & 0xe0e0) != 0; - TESTR14; - CLRFLAGS; -} - -// 71-7f - and rn - reister & register +/* 71-7f - and rn - reister & register */ #define FX_AND(reg) \ - uint32 v = SREG & GSU.avReg[reg]; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG & GSU.avReg[reg]; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_and_r1() { FX_AND(1); } +static void fx_and_r2() { FX_AND(2); } +static void fx_and_r3() { FX_AND(3); } +static void fx_and_r4() { FX_AND(4); } +static void fx_and_r5() { FX_AND(5); } +static void fx_and_r6() { FX_AND(6); } +static void fx_and_r7() { FX_AND(7); } +static void fx_and_r8() { FX_AND(8); } +static void fx_and_r9() { FX_AND(9); } +static void fx_and_r10() { FX_AND(10); } +static void fx_and_r11() { FX_AND(11); } +static void fx_and_r12() { FX_AND(12); } +static void fx_and_r13() { FX_AND(13); } +static void fx_and_r14() { FX_AND(14); } +static void fx_and_r15() { FX_AND(15); } -static void fx_and_r1 (void) -{ - FX_AND(1); -} - -static void fx_and_r2 (void) -{ - FX_AND(2); -} - -static void fx_and_r3 (void) -{ - FX_AND(3); -} - -static void fx_and_r4 (void) -{ - FX_AND(4); -} - -static void fx_and_r5 (void) -{ - FX_AND(5); -} - -static void fx_and_r6 (void) -{ - FX_AND(6); -} - -static void fx_and_r7 (void) -{ - FX_AND(7); -} - -static void fx_and_r8 (void) -{ - FX_AND(8); -} - -static void fx_and_r9 (void) -{ - FX_AND(9); -} - -static void fx_and_r10 (void) -{ - FX_AND(10); -} - -static void fx_and_r11 (void) -{ - FX_AND(11); -} - -static void fx_and_r12 (void) -{ - FX_AND(12); -} - -static void fx_and_r13 (void) -{ - FX_AND(13); -} - -static void fx_and_r14 (void) -{ - FX_AND(14); -} - -static void fx_and_r15 (void) -{ - FX_AND(15); -} - -// 71-7f (ALT1) - bic rn - reister & ~register +/* 71-7f(ALT1) - bic rn - reister & ~register */ #define FX_BIC(reg) \ - uint32 v = SREG & ~GSU.avReg[reg]; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG & ~GSU.avReg[reg]; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_bic_r1() { FX_BIC(1); } +static void fx_bic_r2() { FX_BIC(2); } +static void fx_bic_r3() { FX_BIC(3); } +static void fx_bic_r4() { FX_BIC(4); } +static void fx_bic_r5() { FX_BIC(5); } +static void fx_bic_r6() { FX_BIC(6); } +static void fx_bic_r7() { FX_BIC(7); } +static void fx_bic_r8() { FX_BIC(8); } +static void fx_bic_r9() { FX_BIC(9); } +static void fx_bic_r10() { FX_BIC(10); } +static void fx_bic_r11() { FX_BIC(11); } +static void fx_bic_r12() { FX_BIC(12); } +static void fx_bic_r13() { FX_BIC(13); } +static void fx_bic_r14() { FX_BIC(14); } +static void fx_bic_r15() { FX_BIC(15); } -static void fx_bic_r1 (void) -{ - FX_BIC(1); -} - -static void fx_bic_r2 (void) -{ - FX_BIC(2); -} - -static void fx_bic_r3 (void) -{ - FX_BIC(3); -} - -static void fx_bic_r4 (void) -{ - FX_BIC(4); -} - -static void fx_bic_r5 (void) -{ - FX_BIC(5); -} - -static void fx_bic_r6 (void) -{ - FX_BIC(6); -} - -static void fx_bic_r7 (void) -{ - FX_BIC(7); -} - -static void fx_bic_r8 (void) -{ - FX_BIC(8); -} - -static void fx_bic_r9 (void) -{ - FX_BIC(9); -} - -static void fx_bic_r10 (void) -{ - FX_BIC(10); -} - -static void fx_bic_r11 (void) -{ - FX_BIC(11); -} - -static void fx_bic_r12 (void) -{ - FX_BIC(12); -} - -static void fx_bic_r13 (void) -{ - FX_BIC(13); -} - -static void fx_bic_r14 (void) -{ - FX_BIC(14); -} - -static void fx_bic_r15 (void) -{ - FX_BIC(15); -} - -// 71-7f (ALT2) - and #n - reister & immediate +/* 71-7f(ALT2) - and #n - reister & immediate */ #define FX_AND_I(imm) \ - uint32 v = SREG & imm; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG & imm; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_and_i1() { FX_AND_I(1); } +static void fx_and_i2() { FX_AND_I(2); } +static void fx_and_i3() { FX_AND_I(3); } +static void fx_and_i4() { FX_AND_I(4); } +static void fx_and_i5() { FX_AND_I(5); } +static void fx_and_i6() { FX_AND_I(6); } +static void fx_and_i7() { FX_AND_I(7); } +static void fx_and_i8() { FX_AND_I(8); } +static void fx_and_i9() { FX_AND_I(9); } +static void fx_and_i10() { FX_AND_I(10); } +static void fx_and_i11() { FX_AND_I(11); } +static void fx_and_i12() { FX_AND_I(12); } +static void fx_and_i13() { FX_AND_I(13); } +static void fx_and_i14() { FX_AND_I(14); } +static void fx_and_i15() { FX_AND_I(15); } -static void fx_and_i1 (void) -{ - FX_AND_I(1); -} - -static void fx_and_i2 (void) -{ - FX_AND_I(2); -} - -static void fx_and_i3 (void) -{ - FX_AND_I(3); -} - -static void fx_and_i4 (void) -{ - FX_AND_I(4); -} - -static void fx_and_i5 (void) -{ - FX_AND_I(5); -} - -static void fx_and_i6 (void) -{ - FX_AND_I(6); -} - -static void fx_and_i7 (void) -{ - FX_AND_I(7); -} - -static void fx_and_i8 (void) -{ - FX_AND_I(8); -} - -static void fx_and_i9 (void) -{ - FX_AND_I(9); -} - -static void fx_and_i10 (void) -{ - FX_AND_I(10); -} - -static void fx_and_i11 (void) -{ - FX_AND_I(11); -} - -static void fx_and_i12 (void) -{ - FX_AND_I(12); -} - -static void fx_and_i13 (void) -{ - FX_AND_I(13); -} - -static void fx_and_i14 (void) -{ - FX_AND_I(14); -} - -static void fx_and_i15 (void) -{ - FX_AND_I(15); -} - -// 71-7f (ALT3) - bic #n - reister & ~immediate +/* 71-7f(ALT3) - bic #n - reister & ~immediate */ #define FX_BIC_I(imm) \ - uint32 v = SREG & ~imm; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG & ~imm; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_bic_i1() { FX_BIC_I(1); } +static void fx_bic_i2() { FX_BIC_I(2); } +static void fx_bic_i3() { FX_BIC_I(3); } +static void fx_bic_i4() { FX_BIC_I(4); } +static void fx_bic_i5() { FX_BIC_I(5); } +static void fx_bic_i6() { FX_BIC_I(6); } +static void fx_bic_i7() { FX_BIC_I(7); } +static void fx_bic_i8() { FX_BIC_I(8); } +static void fx_bic_i9() { FX_BIC_I(9); } +static void fx_bic_i10() { FX_BIC_I(10); } +static void fx_bic_i11() { FX_BIC_I(11); } +static void fx_bic_i12() { FX_BIC_I(12); } +static void fx_bic_i13() { FX_BIC_I(13); } +static void fx_bic_i14() { FX_BIC_I(14); } +static void fx_bic_i15() { FX_BIC_I(15); } -static void fx_bic_i1 (void) -{ - FX_BIC_I(1); -} - -static void fx_bic_i2 (void) -{ - FX_BIC_I(2); -} - -static void fx_bic_i3 (void) -{ - FX_BIC_I(3); -} - -static void fx_bic_i4 (void) -{ - FX_BIC_I(4); -} - -static void fx_bic_i5 (void) -{ - FX_BIC_I(5); -} - -static void fx_bic_i6 (void) -{ - FX_BIC_I(6); -} - -static void fx_bic_i7 (void) -{ - FX_BIC_I(7); -} - -static void fx_bic_i8 (void) -{ - FX_BIC_I(8); -} - -static void fx_bic_i9 (void) -{ - FX_BIC_I(9); -} - -static void fx_bic_i10 (void) -{ - FX_BIC_I(10); -} - -static void fx_bic_i11 (void) -{ - FX_BIC_I(11); -} - -static void fx_bic_i12 (void) -{ - FX_BIC_I(12); -} - -static void fx_bic_i13 (void) -{ - FX_BIC_I(13); -} - -static void fx_bic_i14 (void) -{ - FX_BIC_I(14); -} - -static void fx_bic_i15 (void) -{ - FX_BIC_I(15); -} - -// 80-8f - mult rn - 8 bit to 16 bit signed multiply, register * register +/* 80-8f - mult rn - 8 bit to 16 bit signed multiply, register * register */ #define FX_MULT(reg) \ - uint32 v = (uint32) (SEX8(SREG) * SEX8(GSU.avReg[reg])); \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = (uint32)(SEX8(SREG) * SEX8(GSU.avReg[reg])); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_mult_r0() { FX_MULT(0); } +static void fx_mult_r1() { FX_MULT(1); } +static void fx_mult_r2() { FX_MULT(2); } +static void fx_mult_r3() { FX_MULT(3); } +static void fx_mult_r4() { FX_MULT(4); } +static void fx_mult_r5() { FX_MULT(5); } +static void fx_mult_r6() { FX_MULT(6); } +static void fx_mult_r7() { FX_MULT(7); } +static void fx_mult_r8() { FX_MULT(8); } +static void fx_mult_r9() { FX_MULT(9); } +static void fx_mult_r10() { FX_MULT(10); } +static void fx_mult_r11() { FX_MULT(11); } +static void fx_mult_r12() { FX_MULT(12); } +static void fx_mult_r13() { FX_MULT(13); } +static void fx_mult_r14() { FX_MULT(14); } +static void fx_mult_r15() { FX_MULT(15); } -static void fx_mult_r0 (void) -{ - FX_MULT(0); -} - -static void fx_mult_r1 (void) -{ - FX_MULT(1); -} - -static void fx_mult_r2 (void) -{ - FX_MULT(2); -} - -static void fx_mult_r3 (void) -{ - FX_MULT(3); -} - -static void fx_mult_r4 (void) -{ - FX_MULT(4); -} - -static void fx_mult_r5 (void) -{ - FX_MULT(5); -} - -static void fx_mult_r6 (void) -{ - FX_MULT(6); -} - -static void fx_mult_r7 (void) -{ - FX_MULT(7); -} - -static void fx_mult_r8 (void) -{ - FX_MULT(8); -} - -static void fx_mult_r9 (void) -{ - FX_MULT(9); -} - -static void fx_mult_r10 (void) -{ - FX_MULT(10); -} - -static void fx_mult_r11 (void) -{ - FX_MULT(11); -} - -static void fx_mult_r12 (void) -{ - FX_MULT(12); -} - -static void fx_mult_r13 (void) -{ - FX_MULT(13); -} - -static void fx_mult_r14 (void) -{ - FX_MULT(14); -} - -static void fx_mult_r15 (void) -{ - FX_MULT(15); -} - -// 80-8f (ALT1) - umult rn - 8 bit to 16 bit unsigned multiply, register * register +/* 80-8f(ALT1) - umult rn - 8 bit to 16 bit unsigned multiply, register * register */ #define FX_UMULT(reg) \ - uint32 v = USEX8(SREG) * USEX8(GSU.avReg[reg]); \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = USEX8(SREG) * USEX8(GSU.avReg[reg]); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_umult_r0() { FX_UMULT(0); } +static void fx_umult_r1() { FX_UMULT(1); } +static void fx_umult_r2() { FX_UMULT(2); } +static void fx_umult_r3() { FX_UMULT(3); } +static void fx_umult_r4() { FX_UMULT(4); } +static void fx_umult_r5() { FX_UMULT(5); } +static void fx_umult_r6() { FX_UMULT(6); } +static void fx_umult_r7() { FX_UMULT(7); } +static void fx_umult_r8() { FX_UMULT(8); } +static void fx_umult_r9() { FX_UMULT(9); } +static void fx_umult_r10() { FX_UMULT(10); } +static void fx_umult_r11() { FX_UMULT(11); } +static void fx_umult_r12() { FX_UMULT(12); } +static void fx_umult_r13() { FX_UMULT(13); } +static void fx_umult_r14() { FX_UMULT(14); } +static void fx_umult_r15() { FX_UMULT(15); } -static void fx_umult_r0 (void) -{ - FX_UMULT(0); -} - -static void fx_umult_r1 (void) -{ - FX_UMULT(1); -} - -static void fx_umult_r2 (void) -{ - FX_UMULT(2); -} - -static void fx_umult_r3 (void) -{ - FX_UMULT(3); -} - -static void fx_umult_r4 (void) -{ - FX_UMULT(4); -} - -static void fx_umult_r5 (void) -{ - FX_UMULT(5); -} - -static void fx_umult_r6 (void) -{ - FX_UMULT(6); -} - -static void fx_umult_r7 (void) -{ - FX_UMULT(7); -} - -static void fx_umult_r8 (void) -{ - FX_UMULT(8); -} - -static void fx_umult_r9 (void) -{ - FX_UMULT(9); -} - -static void fx_umult_r10 (void) -{ - FX_UMULT(10); -} - -static void fx_umult_r11 (void) -{ - FX_UMULT(11); -} - -static void fx_umult_r12 (void) -{ - FX_UMULT(12); -} - -static void fx_umult_r13 (void) -{ - FX_UMULT(13); -} - -static void fx_umult_r14 (void) -{ - FX_UMULT(14); -} - -static void fx_umult_r15 (void) -{ - FX_UMULT(15); -} - -// 80-8f (ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate +/* 80-8f(ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate */ #define FX_MULT_I(imm) \ - uint32 v = (uint32) (SEX8(SREG) * ((int32) imm)); \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = (uint32) (SEX8(SREG) * ((int32)imm)); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_mult_i0() { FX_MULT_I(0); } +static void fx_mult_i1() { FX_MULT_I(1); } +static void fx_mult_i2() { FX_MULT_I(2); } +static void fx_mult_i3() { FX_MULT_I(3); } +static void fx_mult_i4() { FX_MULT_I(4); } +static void fx_mult_i5() { FX_MULT_I(5); } +static void fx_mult_i6() { FX_MULT_I(6); } +static void fx_mult_i7() { FX_MULT_I(7); } +static void fx_mult_i8() { FX_MULT_I(8); } +static void fx_mult_i9() { FX_MULT_I(9); } +static void fx_mult_i10() { FX_MULT_I(10); } +static void fx_mult_i11() { FX_MULT_I(11); } +static void fx_mult_i12() { FX_MULT_I(12); } +static void fx_mult_i13() { FX_MULT_I(13); } +static void fx_mult_i14() { FX_MULT_I(14); } +static void fx_mult_i15() { FX_MULT_I(15); } -static void fx_mult_i0 (void) -{ - FX_MULT_I(0); -} - -static void fx_mult_i1 (void) -{ - FX_MULT_I(1); -} - -static void fx_mult_i2 (void) -{ - FX_MULT_I(2); -} - -static void fx_mult_i3 (void) -{ - FX_MULT_I(3); -} - -static void fx_mult_i4 (void) -{ - FX_MULT_I(4); -} - -static void fx_mult_i5 (void) -{ - FX_MULT_I(5); -} - -static void fx_mult_i6 (void) -{ - FX_MULT_I(6); -} - -static void fx_mult_i7 (void) -{ - FX_MULT_I(7); -} - -static void fx_mult_i8 (void) -{ - FX_MULT_I(8); -} - -static void fx_mult_i9 (void) -{ - FX_MULT_I(9); -} - -static void fx_mult_i10 (void) -{ - FX_MULT_I(10); -} - -static void fx_mult_i11 (void) -{ - FX_MULT_I(11); -} - -static void fx_mult_i12 (void) -{ - FX_MULT_I(12); -} - -static void fx_mult_i13 (void) -{ - FX_MULT_I(13); -} - -static void fx_mult_i14 (void) -{ - FX_MULT_I(14); -} - -static void fx_mult_i15 (void) -{ - FX_MULT_I(15); -} - -// 80-8f (ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate +/* 80-8f(ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate */ #define FX_UMULT_I(imm) \ - uint32 v = USEX8(SREG) * ((uint32) imm); \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = USEX8(SREG) * ((uint32)imm); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_umult_i0() { FX_UMULT_I(0); } +static void fx_umult_i1() { FX_UMULT_I(1); } +static void fx_umult_i2() { FX_UMULT_I(2); } +static void fx_umult_i3() { FX_UMULT_I(3); } +static void fx_umult_i4() { FX_UMULT_I(4); } +static void fx_umult_i5() { FX_UMULT_I(5); } +static void fx_umult_i6() { FX_UMULT_I(6); } +static void fx_umult_i7() { FX_UMULT_I(7); } +static void fx_umult_i8() { FX_UMULT_I(8); } +static void fx_umult_i9() { FX_UMULT_I(9); } +static void fx_umult_i10() { FX_UMULT_I(10); } +static void fx_umult_i11() { FX_UMULT_I(11); } +static void fx_umult_i12() { FX_UMULT_I(12); } +static void fx_umult_i13() { FX_UMULT_I(13); } +static void fx_umult_i14() { FX_UMULT_I(14); } +static void fx_umult_i15() { FX_UMULT_I(15); } -static void fx_umult_i0 (void) +/* 90 - sbk - store word to last accessed RAM address */ +static void fx_sbk() { - FX_UMULT_I(0); + RAM(GSU.vLastRamAdr) = (uint8)SREG; + RAM(GSU.vLastRamAdr^1) = (uint8)(SREG>>8); + CLRFLAGS; + R15++; } -static void fx_umult_i1 (void) +/* 91-94 - link #n - R11 = R15 + immediate */ +#define FX_LINK_I(lkn) R11 = R15 + lkn; CLRFLAGS; R15++ +static void fx_link_i1() { FX_LINK_I(1); } +static void fx_link_i2() { FX_LINK_I(2); } +static void fx_link_i3() { FX_LINK_I(3); } +static void fx_link_i4() { FX_LINK_I(4); } + +/* 95 - sex - sign extend 8 bit to 16 bit */ +static void fx_sex() { - FX_UMULT_I(1); + uint32 v = (uint32)SEX8(SREG); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -static void fx_umult_i2 (void) +/* 96 - asr - aritmetric shift right by one */ +static void fx_asr() { - FX_UMULT_I(2); + uint32 v; + GSU.vCarry = SREG & 1; + v = (uint32)(SEX16(SREG)>>1); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -static void fx_umult_i3 (void) +/* 96(ALT1) - div2 - aritmetric shift right by one */ +static void fx_div2() { - FX_UMULT_I(3); + uint32 v; + int32 s = SEX16(SREG); + GSU.vCarry = s & 1; + if(s == -1) + v = 0; + else + v = (uint32)(s>>1); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -static void fx_umult_i4 (void) +/* 97 - ror - rotate right by one */ +static void fx_ror() { - FX_UMULT_I(4); + uint32 v = (USEX16(SREG)>>1) | (GSU.vCarry<<15); + GSU.vCarry = SREG & 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; } -static void fx_umult_i5 (void) -{ - FX_UMULT_I(5); -} - -static void fx_umult_i6 (void) -{ - FX_UMULT_I(6); -} - -static void fx_umult_i7 (void) -{ - FX_UMULT_I(7); -} - -static void fx_umult_i8 (void) -{ - FX_UMULT_I(8); -} - -static void fx_umult_i9 (void) -{ - FX_UMULT_I(9); -} - -static void fx_umult_i10 (void) -{ - FX_UMULT_I(10); -} - -static void fx_umult_i11 (void) -{ - FX_UMULT_I(11); -} - -static void fx_umult_i12 (void) -{ - FX_UMULT_I(12); -} - -static void fx_umult_i13 (void) -{ - FX_UMULT_I(13); -} - -static void fx_umult_i14 (void) -{ - FX_UMULT_I(14); -} - -static void fx_umult_i15 (void) -{ - FX_UMULT_I(15); -} - -// 90 - sbk - store word to last accessed RAM address -static void fx_sbk (void) -{ - RAM(GSU.vLastRamAdr) = (uint8) SREG; - RAM(GSU.vLastRamAdr ^ 1) = (uint8) (SREG >> 8); - CLRFLAGS; - R15++; -} - -// 91-94 - link #n - R11 = R15 + immediate -#define FX_LINK_I(lkn) \ - R11 = R15 + lkn; \ - CLRFLAGS; \ - R15++ - -static void fx_link_i1 (void) -{ - FX_LINK_I(1); -} - -static void fx_link_i2 (void) -{ - FX_LINK_I(2); -} - -static void fx_link_i3 (void) -{ - FX_LINK_I(3); -} - -static void fx_link_i4 (void) -{ - FX_LINK_I(4); -} - -// 95 - sex - sign extend 8 bit to 16 bit -static void fx_sex (void) -{ - uint32 v = (uint32) SEX8(SREG); - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -// 96 - asr - aritmetric shift right by one -static void fx_asr (void) -{ - uint32 v; - GSU.vCarry = SREG & 1; - v = (uint32) (SEX16(SREG) >> 1); - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -// 96 (ALT1) - div2 - aritmetric shift right by one -static void fx_div2 (void) -{ - uint32 v; - int32 s = SEX16(SREG); - GSU.vCarry = s & 1; - if (s == -1) - v = 0; - else - v = (uint32) (s >> 1); - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -// 97 - ror - rotate right by one -static void fx_ror (void) -{ - uint32 v = (USEX16(SREG) >> 1) | (GSU.vCarry << 15); - GSU.vCarry = SREG & 1; - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -// 98-9d - jmp rn - jump to address of register +/* 98-9d - jmp rn - jump to address of register */ #define FX_JMP(reg) \ - R15 = GSU.avReg[reg]; \ - CLRFLAGS +R15 = GSU.avReg[reg]; \ +CLRFLAGS; +static void fx_jmp_r8() { FX_JMP(8); } +static void fx_jmp_r9() { FX_JMP(9); } +static void fx_jmp_r10() { FX_JMP(10); } +static void fx_jmp_r11() { FX_JMP(11); } +static void fx_jmp_r12() { FX_JMP(12); } +static void fx_jmp_r13() { FX_JMP(13); } -static void fx_jmp_r8 (void) -{ - FX_JMP(8); -} - -static void fx_jmp_r9 (void) -{ - FX_JMP(9); -} - -static void fx_jmp_r10 (void) -{ - FX_JMP(10); -} - -static void fx_jmp_r11 (void) -{ - FX_JMP(11); -} - -static void fx_jmp_r12 (void) -{ - FX_JMP(12); -} - -static void fx_jmp_r13 (void) -{ - FX_JMP(13); -} - -// 98-9d (ALT1) - ljmp rn - set program bank to source register and jump to address of register +/* 98-9d(ALT1) - ljmp rn - set program bank to source register and jump to address of register */ #define FX_LJMP(reg) \ - GSU.vPrgBankReg = GSU.avReg[reg] & 0x7f; \ - GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; \ - R15 = SREG; \ - GSU.bCacheActive = FALSE; \ - fx_cache(); \ - R15-- +GSU.vPrgBankReg = GSU.avReg[reg] & 0x7f; \ +GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; \ +R15 = SREG; \ +GSU.bCacheActive = FALSE; fx_cache(); R15--; +static void fx_ljmp_r8() { FX_LJMP(8); } +static void fx_ljmp_r9() { FX_LJMP(9); } +static void fx_ljmp_r10() { FX_LJMP(10); } +static void fx_ljmp_r11() { FX_LJMP(11); } +static void fx_ljmp_r12() { FX_LJMP(12); } +static void fx_ljmp_r13() { FX_LJMP(13); } -static void fx_ljmp_r8 (void) +/* 9e - lob - set upper byte to zero (keep low byte) */ +static void fx_lob() { - FX_LJMP(8); + uint32 v = USEX8(SREG); + R15++; DREG = v; + GSU.vSign = v<<8; + GSU.vZero = v<<8; + TESTR14; + CLRFLAGS; } -static void fx_ljmp_r9 (void) +/* 9f - fmult - 16 bit to 32 bit signed multiplication, upper 16 bits only */ +static void fx_fmult() { - FX_LJMP(9); + uint32 v; + uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); + v = c >> 16; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + GSU.vCarry = (c >> 15) & 1; + TESTR14; + CLRFLAGS; } -static void fx_ljmp_r10 (void) +/* 9f(ALT1) - lmult - 16 bit to 32 bit signed multiplication */ +static void fx_lmult() { - FX_LJMP(10); + uint32 v; + uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); + R4 = c; + v = c >> 16; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + /* XXX R6 or R4? */ + GSU.vCarry = (R4 >> 15) & 1; /* should it be bit 15 of R4 instead? */ + TESTR14; + CLRFLAGS; } -static void fx_ljmp_r11 (void) -{ - FX_LJMP(11); -} - -static void fx_ljmp_r12 (void) -{ - FX_LJMP(12); -} - -static void fx_ljmp_r13 (void) -{ - FX_LJMP(13); -} - -// 9e - lob - set upper byte to zero (keep low byte) -static void fx_lob (void) -{ - uint32 v = USEX8(SREG); - R15++; - DREG = v; - GSU.vSign = v << 8; - GSU.vZero = v << 8; - TESTR14; - CLRFLAGS; -} - -// 9f - fmult - 16 bit to 32 bit signed multiplication, upper 16 bits only -static void fx_fmult (void) -{ - uint32 v; - uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); - v = c >> 16; - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - GSU.vCarry = (c >> 15) & 1; - TESTR14; - CLRFLAGS; -} - -// 9f (ALT1) - lmult - 16 bit to 32 bit signed multiplication -static void fx_lmult (void) -{ - uint32 v; - uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); - R4 = c; - v = c >> 16; - R15++; - DREG = v; - GSU.vSign = v; - GSU.vZero = v; - // XXX: R6 or R4? - GSU.vCarry = (R4 >> 15) & 1; // should it be bit 15 of R4 instead ? - TESTR14; - CLRFLAGS; -} - -// a0-af - ibt rn, #pp - immediate byte transfer +/* a0-af - ibt rn,#pp - immediate byte transfer */ #define FX_IBT(reg) \ - uint8 v = PIPE; \ - R15++; \ - FETCHPIPE; \ - R15++; \ - GSU.avReg[reg] = SEX8(v); \ - CLRFLAGS +uint8 v = PIPE; R15++; \ +FETCHPIPE; R15++; \ +GSU.avReg[reg] = SEX8(v); \ +CLRFLAGS; +static void fx_ibt_r0() { FX_IBT(0); } +static void fx_ibt_r1() { FX_IBT(1); } +static void fx_ibt_r2() { FX_IBT(2); } +static void fx_ibt_r3() { FX_IBT(3); } +static void fx_ibt_r4() { FX_IBT(4); } +static void fx_ibt_r5() { FX_IBT(5); } +static void fx_ibt_r6() { FX_IBT(6); } +static void fx_ibt_r7() { FX_IBT(7); } +static void fx_ibt_r8() { FX_IBT(8); } +static void fx_ibt_r9() { FX_IBT(9); } +static void fx_ibt_r10() { FX_IBT(10); } +static void fx_ibt_r11() { FX_IBT(11); } +static void fx_ibt_r12() { FX_IBT(12); } +static void fx_ibt_r13() { FX_IBT(13); } +static void fx_ibt_r14() { FX_IBT(14); READR14; } +static void fx_ibt_r15() { FX_IBT(15); } -static void fx_ibt_r0 (void) -{ - FX_IBT(0); -} - -static void fx_ibt_r1 (void) -{ - FX_IBT(1); -} - -static void fx_ibt_r2 (void) -{ - FX_IBT(2); -} - -static void fx_ibt_r3 (void) -{ - FX_IBT(3); -} - -static void fx_ibt_r4 (void) -{ - FX_IBT(4); -} - -static void fx_ibt_r5 (void) -{ - FX_IBT(5); -} - -static void fx_ibt_r6 (void) -{ - FX_IBT(6); -} - -static void fx_ibt_r7 (void) -{ - FX_IBT(7); -} - -static void fx_ibt_r8 (void) -{ - FX_IBT(8); -} - -static void fx_ibt_r9 (void) -{ - FX_IBT(9); -} - -static void fx_ibt_r10 (void) -{ - FX_IBT(10); -} - -static void fx_ibt_r11 (void) -{ - FX_IBT(11); -} - -static void fx_ibt_r12 (void) -{ - FX_IBT(12); -} - -static void fx_ibt_r13 (void) -{ - FX_IBT(13); -} - -static void fx_ibt_r14 (void) -{ - FX_IBT(14); - READR14; -} - -static void fx_ibt_r15 (void) -{ - FX_IBT(15); -} - -// a0-af (ALT1) - lms rn, (yy) - load word from RAM (short address) +/* a0-af(ALT1) - lms rn,(yy) - load word from RAM (short address) */ #define FX_LMS(reg) \ - GSU.vLastRamAdr = ((uint32) PIPE) << 1; \ - R15++; \ - FETCHPIPE; \ - R15++; \ - GSU.avReg[reg] = (uint32) RAM(GSU.vLastRamAdr); \ - GSU.avReg[reg] |= ((uint32) RAM(GSU.vLastRamAdr + 1)) << 8; \ - CLRFLAGS +GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ +R15++; FETCHPIPE; R15++; \ +GSU.avReg[reg] = (uint32)RAM(GSU.vLastRamAdr); \ +GSU.avReg[reg] |= ((uint32)RAM(GSU.vLastRamAdr+1))<<8; \ +CLRFLAGS; +static void fx_lms_r0() { FX_LMS(0); } +static void fx_lms_r1() { FX_LMS(1); } +static void fx_lms_r2() { FX_LMS(2); } +static void fx_lms_r3() { FX_LMS(3); } +static void fx_lms_r4() { FX_LMS(4); } +static void fx_lms_r5() { FX_LMS(5); } +static void fx_lms_r6() { FX_LMS(6); } +static void fx_lms_r7() { FX_LMS(7); } +static void fx_lms_r8() { FX_LMS(8); } +static void fx_lms_r9() { FX_LMS(9); } +static void fx_lms_r10() { FX_LMS(10); } +static void fx_lms_r11() { FX_LMS(11); } +static void fx_lms_r12() { FX_LMS(12); } +static void fx_lms_r13() { FX_LMS(13); } +static void fx_lms_r14() { FX_LMS(14); READR14; } +static void fx_lms_r15() { FX_LMS(15); } -static void fx_lms_r0 (void) -{ - FX_LMS(0); -} - -static void fx_lms_r1 (void) -{ - FX_LMS(1); -} - -static void fx_lms_r2 (void) -{ - FX_LMS(2); -} - -static void fx_lms_r3 (void) -{ - FX_LMS(3); -} - -static void fx_lms_r4 (void) -{ - FX_LMS(4); -} - -static void fx_lms_r5 (void) -{ - FX_LMS(5); -} - -static void fx_lms_r6 (void) -{ - FX_LMS(6); -} - -static void fx_lms_r7 (void) -{ - FX_LMS(7); -} - -static void fx_lms_r8 (void) -{ - FX_LMS(8); -} - -static void fx_lms_r9 (void) -{ - FX_LMS(9); -} - -static void fx_lms_r10 (void) -{ - FX_LMS(10); -} - -static void fx_lms_r11 (void) -{ - FX_LMS(11); -} - -static void fx_lms_r12 (void) -{ - FX_LMS(12); -} - -static void fx_lms_r13 (void) -{ - FX_LMS(13); -} - -static void fx_lms_r14 (void) -{ - FX_LMS(14); - READR14; -} - -static void fx_lms_r15 (void) -{ - FX_LMS(15); -} - -// a0-af (ALT2) - sms (yy), rn - store word in RAM (short address) -// XXX: If rn == r15, is the value of r15 before or after the extra byte is read ? +/* a0-af(ALT2) - sms (yy),rn - store word in RAM (short address) */ +/* If rn == r15, is the value of r15 before or after the extra byte is read? */ #define FX_SMS(reg) \ - uint32 v = GSU.avReg[reg]; \ - GSU.vLastRamAdr = ((uint32) PIPE) << 1; \ - R15++; \ - FETCHPIPE; \ - RAM(GSU.vLastRamAdr) = (uint8) v; \ - RAM(GSU.vLastRamAdr + 1) = (uint8) (v >> 8); \ - CLRFLAGS; \ - R15++ +uint32 v = GSU.avReg[reg]; \ +GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ +R15++; FETCHPIPE; \ +RAM(GSU.vLastRamAdr) = (uint8)v; \ +RAM(GSU.vLastRamAdr+1) = (uint8)(v>>8); \ +CLRFLAGS; R15++; +static void fx_sms_r0() { FX_SMS(0); } +static void fx_sms_r1() { FX_SMS(1); } +static void fx_sms_r2() { FX_SMS(2); } +static void fx_sms_r3() { FX_SMS(3); } +static void fx_sms_r4() { FX_SMS(4); } +static void fx_sms_r5() { FX_SMS(5); } +static void fx_sms_r6() { FX_SMS(6); } +static void fx_sms_r7() { FX_SMS(7); } +static void fx_sms_r8() { FX_SMS(8); } +static void fx_sms_r9() { FX_SMS(9); } +static void fx_sms_r10() { FX_SMS(10); } +static void fx_sms_r11() { FX_SMS(11); } +static void fx_sms_r12() { FX_SMS(12); } +static void fx_sms_r13() { FX_SMS(13); } +static void fx_sms_r14() { FX_SMS(14); } +static void fx_sms_r15() { FX_SMS(15); } -static void fx_sms_r0 (void) -{ - FX_SMS(0); -} - -static void fx_sms_r1 (void) -{ - FX_SMS(1); -} - -static void fx_sms_r2 (void) -{ - FX_SMS(2); -} - -static void fx_sms_r3 (void) -{ - FX_SMS(3); -} - -static void fx_sms_r4 (void) -{ - FX_SMS(4); -} - -static void fx_sms_r5 (void) -{ - FX_SMS(5); -} - -static void fx_sms_r6 (void) -{ - FX_SMS(6); -} - -static void fx_sms_r7 (void) -{ - FX_SMS(7); -} - -static void fx_sms_r8 (void) -{ - FX_SMS(8); -} - -static void fx_sms_r9 (void) -{ - FX_SMS(9); -} - -static void fx_sms_r10 (void) -{ - FX_SMS(10); -} - -static void fx_sms_r11 (void) -{ - FX_SMS(11); -} - -static void fx_sms_r12 (void) -{ - FX_SMS(12); -} - -static void fx_sms_r13 (void) -{ - FX_SMS(13); -} - -static void fx_sms_r14 (void) -{ - FX_SMS(14); -} - -static void fx_sms_r15 (void) -{ - FX_SMS(15); -} - -// b0-bf - from rn - set source register -// b0-bf (B) - moves rn - move register to register, and set flags, (if B flag is set) +/* b0-bf - from rn - set source register */ +/* b0-bf(B) - moves rn - move register to register, and set flags, (if B flag is set) */ #define FX_FROM(reg) \ - if (TF(B)) \ - { \ - uint32 v = GSU.avReg[reg]; \ - R15++; \ - DREG = v; \ - GSU.vOverflow = (v & 0x80) << 16; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS; \ - } \ - else \ - { \ - GSU.pvSreg = &GSU.avReg[reg]; \ - R15++; \ - } +if(TF(B)) { uint32 v = GSU.avReg[reg]; R15++; DREG = v; \ +GSU.vOverflow = (v&0x80) << 16; GSU.vSign = v; GSU.vZero = v; TESTR14; CLRFLAGS; } \ +else { GSU.pvSreg = &GSU.avReg[reg]; R15++; } +static void fx_from_r0() { FX_FROM(0); } +static void fx_from_r1() { FX_FROM(1); } +static void fx_from_r2() { FX_FROM(2); } +static void fx_from_r3() { FX_FROM(3); } +static void fx_from_r4() { FX_FROM(4); } +static void fx_from_r5() { FX_FROM(5); } +static void fx_from_r6() { FX_FROM(6); } +static void fx_from_r7() { FX_FROM(7); } +static void fx_from_r8() { FX_FROM(8); } +static void fx_from_r9() { FX_FROM(9); } +static void fx_from_r10() { FX_FROM(10); } +static void fx_from_r11() { FX_FROM(11); } +static void fx_from_r12() { FX_FROM(12); } +static void fx_from_r13() { FX_FROM(13); } +static void fx_from_r14() { FX_FROM(14); } +static void fx_from_r15() { FX_FROM(15); } -static void fx_from_r0 (void) +/* c0 - hib - move high-byte to low-byte */ +static void fx_hib() { - FX_FROM(0); + uint32 v = USEX8(SREG>>8); + R15++; DREG = v; + GSU.vSign = v<<8; + GSU.vZero = v<<8; + TESTR14; + CLRFLAGS; } -static void fx_from_r1 (void) -{ - FX_FROM(1); -} - -static void fx_from_r2 (void) -{ - FX_FROM(2); -} - -static void fx_from_r3 (void) -{ - FX_FROM(3); -} - -static void fx_from_r4 (void) -{ - FX_FROM(4); -} - -static void fx_from_r5 (void) -{ - FX_FROM(5); -} - -static void fx_from_r6 (void) -{ - FX_FROM(6); -} - -static void fx_from_r7 (void) -{ - FX_FROM(7); -} - -static void fx_from_r8 (void) -{ - FX_FROM(8); -} - -static void fx_from_r9 (void) -{ - FX_FROM(9); -} - -static void fx_from_r10 (void) -{ - FX_FROM(10); -} - -static void fx_from_r11 (void) -{ - FX_FROM(11); -} - -static void fx_from_r12 (void) -{ - FX_FROM(12); -} - -static void fx_from_r13 (void) -{ - FX_FROM(13); -} - -static void fx_from_r14 (void) -{ - FX_FROM(14); -} - -static void fx_from_r15 (void) -{ - FX_FROM(15); -} - -// c0 - hib - move high-byte to low-byte -static void fx_hib (void) -{ - uint32 v = USEX8(SREG >> 8); - R15++; - DREG = v; - GSU.vSign = v << 8; - GSU.vZero = v << 8; - TESTR14; - CLRFLAGS; -} - -// c1-cf - or rn +/* c1-cf - or rn */ #define FX_OR(reg) \ - uint32 v = SREG | GSU.avReg[reg]; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG | GSU.avReg[reg]; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_or_r1() { FX_OR(1); } +static void fx_or_r2() { FX_OR(2); } +static void fx_or_r3() { FX_OR(3); } +static void fx_or_r4() { FX_OR(4); } +static void fx_or_r5() { FX_OR(5); } +static void fx_or_r6() { FX_OR(6); } +static void fx_or_r7() { FX_OR(7); } +static void fx_or_r8() { FX_OR(8); } +static void fx_or_r9() { FX_OR(9); } +static void fx_or_r10() { FX_OR(10); } +static void fx_or_r11() { FX_OR(11); } +static void fx_or_r12() { FX_OR(12); } +static void fx_or_r13() { FX_OR(13); } +static void fx_or_r14() { FX_OR(14); } +static void fx_or_r15() { FX_OR(15); } -static void fx_or_r1 (void) -{ - FX_OR(1); -} - -static void fx_or_r2 (void) -{ - FX_OR(2); -} - -static void fx_or_r3 (void) -{ - FX_OR(3); -} - -static void fx_or_r4 (void) -{ - FX_OR(4); -} - -static void fx_or_r5 (void) -{ - FX_OR(5); -} - -static void fx_or_r6 (void) -{ - FX_OR(6); -} - -static void fx_or_r7 (void) -{ - FX_OR(7); -} - -static void fx_or_r8 (void) -{ - FX_OR(8); -} - -static void fx_or_r9 (void) -{ - FX_OR(9); -} - -static void fx_or_r10 (void) -{ - FX_OR(10); -} - -static void fx_or_r11 (void) -{ - FX_OR(11); -} - -static void fx_or_r12 (void) -{ - FX_OR(12); -} - -static void fx_or_r13 (void) -{ - FX_OR(13); -} - -static void fx_or_r14 (void) -{ - FX_OR(14); -} - -static void fx_or_r15 (void) -{ - FX_OR(15); -} - -// c1-cf (ALT1) - xor rn +/* c1-cf(ALT1) - xor rn */ #define FX_XOR(reg) \ - uint32 v = SREG ^ GSU.avReg[reg]; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG ^ GSU.avReg[reg]; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_xor_r1() { FX_XOR(1); } +static void fx_xor_r2() { FX_XOR(2); } +static void fx_xor_r3() { FX_XOR(3); } +static void fx_xor_r4() { FX_XOR(4); } +static void fx_xor_r5() { FX_XOR(5); } +static void fx_xor_r6() { FX_XOR(6); } +static void fx_xor_r7() { FX_XOR(7); } +static void fx_xor_r8() { FX_XOR(8); } +static void fx_xor_r9() { FX_XOR(9); } +static void fx_xor_r10() { FX_XOR(10); } +static void fx_xor_r11() { FX_XOR(11); } +static void fx_xor_r12() { FX_XOR(12); } +static void fx_xor_r13() { FX_XOR(13); } +static void fx_xor_r14() { FX_XOR(14); } +static void fx_xor_r15() { FX_XOR(15); } -static void fx_xor_r1 (void) -{ - FX_XOR(1); -} - -static void fx_xor_r2 (void) -{ - FX_XOR(2); -} - -static void fx_xor_r3 (void) -{ - FX_XOR(3); -} - -static void fx_xor_r4 (void) -{ - FX_XOR(4); -} - -static void fx_xor_r5 (void) -{ - FX_XOR(5); -} - -static void fx_xor_r6 (void) -{ - FX_XOR(6); -} - -static void fx_xor_r7 (void) -{ - FX_XOR(7); -} - -static void fx_xor_r8 (void) -{ - FX_XOR(8); -} - -static void fx_xor_r9 (void) -{ - FX_XOR(9); -} - -static void fx_xor_r10 (void) -{ - FX_XOR(10); -} - -static void fx_xor_r11 (void) -{ - FX_XOR(11); -} - -static void fx_xor_r12 (void) -{ - FX_XOR(12); -} - -static void fx_xor_r13 (void) -{ - FX_XOR(13); -} - -static void fx_xor_r14 (void) -{ - FX_XOR(14); -} - -static void fx_xor_r15 (void) -{ - FX_XOR(15); -} - -// c1-cf (ALT2) - or #n +/* c1-cf(ALT2) - or #n */ #define FX_OR_I(imm) \ - uint32 v = SREG | imm; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG | imm; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_or_i1() { FX_OR_I(1); } +static void fx_or_i2() { FX_OR_I(2); } +static void fx_or_i3() { FX_OR_I(3); } +static void fx_or_i4() { FX_OR_I(4); } +static void fx_or_i5() { FX_OR_I(5); } +static void fx_or_i6() { FX_OR_I(6); } +static void fx_or_i7() { FX_OR_I(7); } +static void fx_or_i8() { FX_OR_I(8); } +static void fx_or_i9() { FX_OR_I(9); } +static void fx_or_i10() { FX_OR_I(10); } +static void fx_or_i11() { FX_OR_I(11); } +static void fx_or_i12() { FX_OR_I(12); } +static void fx_or_i13() { FX_OR_I(13); } +static void fx_or_i14() { FX_OR_I(14); } +static void fx_or_i15() { FX_OR_I(15); } -static void fx_or_i1 (void) -{ - FX_OR_I(1); -} - -static void fx_or_i2 (void) -{ - FX_OR_I(2); -} - -static void fx_or_i3 (void) -{ - FX_OR_I(3); -} - -static void fx_or_i4 (void) -{ - FX_OR_I(4); -} - -static void fx_or_i5 (void) -{ - FX_OR_I(5); -} - -static void fx_or_i6 (void) -{ - FX_OR_I(6); -} - -static void fx_or_i7 (void) -{ - FX_OR_I(7); -} - -static void fx_or_i8 (void) -{ - FX_OR_I(8); -} - -static void fx_or_i9 (void) -{ - FX_OR_I(9); -} - -static void fx_or_i10 (void) -{ - FX_OR_I(10); -} - -static void fx_or_i11 (void) -{ - FX_OR_I(11); -} - -static void fx_or_i12 (void) -{ - FX_OR_I(12); -} - -static void fx_or_i13 (void) -{ - FX_OR_I(13); -} - -static void fx_or_i14 (void) -{ - FX_OR_I(14); -} - -static void fx_or_i15 (void) -{ - FX_OR_I(15); -} - -// c1-cf (ALT3) - xor #n +/* c1-cf(ALT3) - xor #n */ #define FX_XOR_I(imm) \ - uint32 v = SREG ^ imm; \ - R15++; \ - DREG = v; \ - GSU.vSign = v; \ - GSU.vZero = v; \ - TESTR14; \ - CLRFLAGS +uint32 v = SREG ^ imm; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static void fx_xor_i1() { FX_XOR_I(1); } +static void fx_xor_i2() { FX_XOR_I(2); } +static void fx_xor_i3() { FX_XOR_I(3); } +static void fx_xor_i4() { FX_XOR_I(4); } +static void fx_xor_i5() { FX_XOR_I(5); } +static void fx_xor_i6() { FX_XOR_I(6); } +static void fx_xor_i7() { FX_XOR_I(7); } +static void fx_xor_i8() { FX_XOR_I(8); } +static void fx_xor_i9() { FX_XOR_I(9); } +static void fx_xor_i10() { FX_XOR_I(10); } +static void fx_xor_i11() { FX_XOR_I(11); } +static void fx_xor_i12() { FX_XOR_I(12); } +static void fx_xor_i13() { FX_XOR_I(13); } +static void fx_xor_i14() { FX_XOR_I(14); } +static void fx_xor_i15() { FX_XOR_I(15); } -static void fx_xor_i1 (void) -{ - FX_XOR_I(1); -} - -static void fx_xor_i2 (void) -{ - FX_XOR_I(2); -} - -static void fx_xor_i3 (void) -{ - FX_XOR_I(3); -} - -static void fx_xor_i4 (void) -{ - FX_XOR_I(4); -} - -static void fx_xor_i5 (void) -{ - FX_XOR_I(5); -} - -static void fx_xor_i6 (void) -{ - FX_XOR_I(6); -} - -static void fx_xor_i7 (void) -{ - FX_XOR_I(7); -} - -static void fx_xor_i8 (void) -{ - FX_XOR_I(8); -} - -static void fx_xor_i9 (void) -{ - FX_XOR_I(9); -} - -static void fx_xor_i10 (void) -{ - FX_XOR_I(10); -} - -static void fx_xor_i11 (void) -{ - FX_XOR_I(11); -} - -static void fx_xor_i12 (void) -{ - FX_XOR_I(12); -} - -static void fx_xor_i13 (void) -{ - FX_XOR_I(13); -} - -static void fx_xor_i14 (void) -{ - FX_XOR_I(14); -} - -static void fx_xor_i15 (void) -{ - FX_XOR_I(15); -} - -// d0-de - inc rn - increase by one +/* d0-de - inc rn - increase by one */ #define FX_INC(reg) \ - GSU.avReg[reg] += 1; \ - GSU.vSign = GSU.avReg[reg]; \ - GSU.vZero = GSU.avReg[reg]; \ - CLRFLAGS; \ - R15++ +GSU.avReg[reg] += 1; \ +GSU.vSign = GSU.avReg[reg]; \ +GSU.vZero = GSU.avReg[reg]; \ +CLRFLAGS; R15++; +static void fx_inc_r0() { FX_INC(0); } +static void fx_inc_r1() { FX_INC(1); } +static void fx_inc_r2() { FX_INC(2); } +static void fx_inc_r3() { FX_INC(3); } +static void fx_inc_r4() { FX_INC(4); } +static void fx_inc_r5() { FX_INC(5); } +static void fx_inc_r6() { FX_INC(6); } +static void fx_inc_r7() { FX_INC(7); } +static void fx_inc_r8() { FX_INC(8); } +static void fx_inc_r9() { FX_INC(9); } +static void fx_inc_r10() { FX_INC(10); } +static void fx_inc_r11() { FX_INC(11); } +static void fx_inc_r12() { FX_INC(12); } +static void fx_inc_r13() { FX_INC(13); } +static void fx_inc_r14() { FX_INC(14); READR14; } -static void fx_inc_r0 (void) -{ - FX_INC(0); -} - -static void fx_inc_r1 (void) -{ - FX_INC(1); -} - -static void fx_inc_r2 (void) -{ - FX_INC(2); -} - -static void fx_inc_r3 (void) -{ - FX_INC(3); -} - -static void fx_inc_r4 (void) -{ - FX_INC(4); -} - -static void fx_inc_r5 (void) -{ - FX_INC(5); -} - -static void fx_inc_r6 (void) -{ - FX_INC(6); -} - -static void fx_inc_r7 (void) -{ - FX_INC(7); -} - -static void fx_inc_r8 (void) -{ - FX_INC(8); -} - -static void fx_inc_r9 (void) -{ - FX_INC(9); -} - -static void fx_inc_r10 (void) -{ - FX_INC(10); -} - -static void fx_inc_r11 (void) -{ - FX_INC(11); -} - -static void fx_inc_r12 (void) -{ - FX_INC(12); -} - -static void fx_inc_r13 (void) -{ - FX_INC(13); -} - -static void fx_inc_r14 (void) -{ - FX_INC(14); - READR14; -} - -// df - getc - transfer ROM buffer to color register -static void fx_getc (void) +/* df - getc - transfer ROM buffer to color register */ +static void fx_getc() { #ifndef FX_DO_ROMBUFFER - uint8 c = ROM(R14); + uint8 c; + c = ROM(R14); #else - uint8 c = GSU.vRomBuffer; + uint8 c = GSU.vRomBuffer; #endif - - if (GSU.vPlotOptionReg & 0x04) - c = (c & 0xf0) | (c >> 4); - - if (GSU.vPlotOptionReg & 0x08) - { - GSU.vColorReg &= 0xf0; - GSU.vColorReg |= c & 0x0f; - } - else - GSU.vColorReg = USEX8(c); - - CLRFLAGS; - R15++; + if(GSU.vPlotOptionReg & 0x04) + c = (c&0xf0) | (c>>4); + if(GSU.vPlotOptionReg & 0x08) + { + GSU.vColorReg &= 0xf0; + GSU.vColorReg |= c & 0x0f; + } + else + GSU.vColorReg = USEX8(c); + CLRFLAGS; + R15++; } -// df (ALT2) - ramb - set current RAM bank -static void fx_ramb (void) +/* df(ALT2) - ramb - set current RAM bank */ +static void fx_ramb() { - GSU.vRamBankReg = SREG & (FX_RAM_BANKS - 1); - GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; - CLRFLAGS; - R15++; + GSU.vRamBankReg = SREG & (FX_RAM_BANKS-1); + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + CLRFLAGS; + R15++; } -// df (ALT3) - romb - set current ROM bank -static void fx_romb (void) +/* df(ALT3) - romb - set current ROM bank */ +static void fx_romb() { - GSU.vRomBankReg = USEX8(SREG) & 0x7f; - GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; - CLRFLAGS; - R15++; + GSU.vRomBankReg = USEX8(SREG) & 0x7f; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + CLRFLAGS; + R15++; } -// e0-ee - dec rn - decrement by one +/* e0-ee - dec rn - decrement by one */ #define FX_DEC(reg) \ - GSU.avReg[reg] -= 1; \ - GSU.vSign = GSU.avReg[reg]; \ - GSU.vZero = GSU.avReg[reg]; \ - CLRFLAGS; \ - R15++ +GSU.avReg[reg] -= 1; \ +GSU.vSign = GSU.avReg[reg]; \ +GSU.vZero = GSU.avReg[reg]; \ +CLRFLAGS; R15++; +static void fx_dec_r0() { FX_DEC(0); } +static void fx_dec_r1() { FX_DEC(1); } +static void fx_dec_r2() { FX_DEC(2); } +static void fx_dec_r3() { FX_DEC(3); } +static void fx_dec_r4() { FX_DEC(4); } +static void fx_dec_r5() { FX_DEC(5); } +static void fx_dec_r6() { FX_DEC(6); } +static void fx_dec_r7() { FX_DEC(7); } +static void fx_dec_r8() { FX_DEC(8); } +static void fx_dec_r9() { FX_DEC(9); } +static void fx_dec_r10() { FX_DEC(10); } +static void fx_dec_r11() { FX_DEC(11); } +static void fx_dec_r12() { FX_DEC(12); } +static void fx_dec_r13() { FX_DEC(13); } +static void fx_dec_r14() { FX_DEC(14); READR14; } -static void fx_dec_r0 (void) +/* ef - getb - get byte from ROM at address R14 */ +static void fx_getb() { - FX_DEC(0); -} - -static void fx_dec_r1 (void) -{ - FX_DEC(1); -} - -static void fx_dec_r2 (void) -{ - FX_DEC(2); -} - -static void fx_dec_r3 (void) -{ - FX_DEC(3); -} - -static void fx_dec_r4 (void) -{ - FX_DEC(4); -} - -static void fx_dec_r5 (void) -{ - FX_DEC(5); -} - -static void fx_dec_r6 (void) -{ - FX_DEC(6); -} - -static void fx_dec_r7 (void) -{ - FX_DEC(7); -} - -static void fx_dec_r8 (void) -{ - FX_DEC(8); -} - -static void fx_dec_r9 (void) -{ - FX_DEC(9); -} - -static void fx_dec_r10 (void) -{ - FX_DEC(10); -} - -static void fx_dec_r11 (void) -{ - FX_DEC(11); -} - -static void fx_dec_r12 (void) -{ - FX_DEC(12); -} - -static void fx_dec_r13 (void) -{ - FX_DEC(13); -} - -static void fx_dec_r14 (void) -{ - FX_DEC(14); - READR14; -} - -// ef - getb - get byte from ROM at address R14 -static void fx_getb (void) -{ - uint32 v; + uint32 v; #ifndef FX_DO_ROMBUFFER - v = (uint32) ROM(R14); + v = (uint32)ROM(R14); #else - v = (uint32) GSU.vRomBuffer; + v = (uint32)GSU.vRomBuffer; #endif - R15++; - DREG = v; - TESTR14; - CLRFLAGS; + R15++; DREG = v; + TESTR14; + CLRFLAGS; } -// ef (ALT1) - getbh - get high-byte from ROM at address R14 -static void fx_getbh (void) +/* ef(ALT1) - getbh - get high-byte from ROM at address R14 */ +static void fx_getbh() { - uint32 v; + uint32 v; #ifndef FX_DO_ROMBUFFER - uint32 c = (uint32) ROM(R14); + uint32 c; + c = (uint32)ROM(R14); #else - uint32 c = USEX8(GSU.vRomBuffer); + uint32 c = USEX8(GSU.vRomBuffer); #endif - v = USEX8(SREG) | (c << 8); - R15++; - DREG = v; - TESTR14; - CLRFLAGS; + v = USEX8(SREG) | (c<<8); + R15++; DREG = v; + TESTR14; + CLRFLAGS; } -// ef (ALT2) - getbl - get low-byte from ROM at address R14 -static void fx_getbl (void) +/* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ +static void fx_getbl() { - uint32 v; + uint32 v; #ifndef FX_DO_ROMBUFFER - uint32 c = (uint32) ROM(R14); + uint32 c; + c = (uint32)ROM(R14); #else - uint32 c = USEX8(GSU.vRomBuffer); + uint32 c = USEX8(GSU.vRomBuffer); #endif - v = (SREG & 0xff00) | c; - R15++; - DREG = v; - TESTR14; - CLRFLAGS; + v = (SREG & 0xff00) | c; + R15++; DREG = v; + TESTR14; + CLRFLAGS; } -// ef (ALT3) - getbs - get sign extended byte from ROM at address R14 -static void fx_getbs (void) +/* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ +static void fx_getbs() { - uint32 v; + uint32 v; #ifndef FX_DO_ROMBUFFER - int8 c; - c = ROM(R14); - v = SEX8(c); + int8 c; + c = ROM(R14); + v = SEX8(c); #else - v = SEX8(GSU.vRomBuffer); + v = SEX8(GSU.vRomBuffer); #endif - R15++; - DREG = v; - TESTR14; - CLRFLAGS; + R15++; DREG = v; + TESTR14; + CLRFLAGS; } -// f0-ff - iwt rn, #xx - immediate word transfer to register +/* f0-ff - iwt rn,#xx - immediate word transfer to register */ #define FX_IWT(reg) \ - uint32 v = PIPE; \ - R15++; \ - FETCHPIPE; \ - R15++; \ - v |= USEX8(PIPE) << 8; \ - FETCHPIPE; \ - R15++; \ - GSU.avReg[reg] = v; \ - CLRFLAGS +uint32 v = PIPE; R15++; FETCHPIPE; R15++; \ +v |= USEX8(PIPE) << 8; FETCHPIPE; R15++; \ +GSU.avReg[reg] = v; \ +CLRFLAGS; +static void fx_iwt_r0() { FX_IWT(0); } +static void fx_iwt_r1() { FX_IWT(1); } +static void fx_iwt_r2() { FX_IWT(2); } +static void fx_iwt_r3() { FX_IWT(3); } +static void fx_iwt_r4() { FX_IWT(4); } +static void fx_iwt_r5() { FX_IWT(5); } +static void fx_iwt_r6() { FX_IWT(6); } +static void fx_iwt_r7() { FX_IWT(7); } +static void fx_iwt_r8() { FX_IWT(8); } +static void fx_iwt_r9() { FX_IWT(9); } +static void fx_iwt_r10() { FX_IWT(10); } +static void fx_iwt_r11() { FX_IWT(11); } +static void fx_iwt_r12() { FX_IWT(12); } +static void fx_iwt_r13() { FX_IWT(13); } +static void fx_iwt_r14() { FX_IWT(14); READR14; } +static void fx_iwt_r15() { FX_IWT(15); } -static void fx_iwt_r0 (void) -{ - FX_IWT(0); -} - -static void fx_iwt_r1 (void) -{ - FX_IWT(1); -} - -static void fx_iwt_r2 (void) -{ - FX_IWT(2); -} - -static void fx_iwt_r3 (void) -{ - FX_IWT(3); -} - -static void fx_iwt_r4 (void) -{ - FX_IWT(4); -} - -static void fx_iwt_r5 (void) -{ - FX_IWT(5); -} - -static void fx_iwt_r6 (void) -{ - FX_IWT(6); -} - -static void fx_iwt_r7 (void) -{ - FX_IWT(7); -} - -static void fx_iwt_r8 (void) -{ - FX_IWT(8); -} - -static void fx_iwt_r9 (void) -{ - FX_IWT(9); -} - -static void fx_iwt_r10 (void) -{ - FX_IWT(10); -} - -static void fx_iwt_r11 (void) -{ - FX_IWT(11); -} - -static void fx_iwt_r12 (void) -{ - FX_IWT(12); -} - -static void fx_iwt_r13 (void) -{ - FX_IWT(13); -} - -static void fx_iwt_r14 (void) -{ - FX_IWT(14); - READR14; -} - -static void fx_iwt_r15 (void) -{ - FX_IWT(15); -} - -// f0-ff (ALT1) - lm rn, (xx) - load word from RAM +/* f0-ff(ALT1) - lm rn,(xx) - load word from RAM */ #define FX_LM(reg) \ - GSU.vLastRamAdr = PIPE; \ - R15++; \ - FETCHPIPE; \ - R15++; \ - GSU.vLastRamAdr |= USEX8(PIPE) << 8; \ - FETCHPIPE; \ - R15++; \ - GSU.avReg[reg] = RAM(GSU.vLastRamAdr); \ - GSU.avReg[reg] |= USEX8(RAM(GSU.vLastRamAdr ^ 1)) << 8; \ - CLRFLAGS +GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ +GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; R15++; \ +GSU.avReg[reg] = RAM(GSU.vLastRamAdr); \ +GSU.avReg[reg] |= USEX8(RAM(GSU.vLastRamAdr^1)) << 8; \ +CLRFLAGS; +static void fx_lm_r0() { FX_LM(0); } +static void fx_lm_r1() { FX_LM(1); } +static void fx_lm_r2() { FX_LM(2); } +static void fx_lm_r3() { FX_LM(3); } +static void fx_lm_r4() { FX_LM(4); } +static void fx_lm_r5() { FX_LM(5); } +static void fx_lm_r6() { FX_LM(6); } +static void fx_lm_r7() { FX_LM(7); } +static void fx_lm_r8() { FX_LM(8); } +static void fx_lm_r9() { FX_LM(9); } +static void fx_lm_r10() { FX_LM(10); } +static void fx_lm_r11() { FX_LM(11); } +static void fx_lm_r12() { FX_LM(12); } +static void fx_lm_r13() { FX_LM(13); } +static void fx_lm_r14() { FX_LM(14); READR14; } +static void fx_lm_r15() { FX_LM(15); } -static void fx_lm_r0 (void) -{ - FX_LM(0); -} - -static void fx_lm_r1 (void) -{ - FX_LM(1); -} - -static void fx_lm_r2 (void) -{ - FX_LM(2); -} - -static void fx_lm_r3 (void) -{ - FX_LM(3); -} - -static void fx_lm_r4 (void) -{ - FX_LM(4); -} - -static void fx_lm_r5 (void) -{ - FX_LM(5); -} - -static void fx_lm_r6 (void) -{ - FX_LM(6); -} - -static void fx_lm_r7 (void) -{ - FX_LM(7); -} - -static void fx_lm_r8 (void) -{ - FX_LM(8); -} - -static void fx_lm_r9 (void) -{ - FX_LM(9); -} - -static void fx_lm_r10 (void) -{ - FX_LM(10); -} - -static void fx_lm_r11 (void) -{ - FX_LM(11); -} - -static void fx_lm_r12 (void) -{ - FX_LM(12); -} - -static void fx_lm_r13 (void) -{ - FX_LM(13); -} - -static void fx_lm_r14 (void) -{ - FX_LM(14); - READR14; -} - -static void fx_lm_r15 (void) -{ - FX_LM(15); -} - -// f0-ff (ALT2) - sm (xx), rn - store word in RAM -// XXX: If rn == r15, is the value of r15 before or after the extra bytes are read ? +/* f0-ff(ALT2) - sm (xx),rn - store word in RAM */ +/* If rn == r15, is the value of r15 before or after the extra bytes are read? */ #define FX_SM(reg) \ - uint32 v = GSU.avReg[reg]; \ - GSU.vLastRamAdr = PIPE; \ - R15++; \ - FETCHPIPE; \ - R15++; \ - GSU.vLastRamAdr |= USEX8(PIPE) << 8; \ - FETCHPIPE; \ - RAM(GSU.vLastRamAdr) = (uint8) v; \ - RAM(GSU.vLastRamAdr ^ 1) = (uint8) (v >> 8); \ - CLRFLAGS; \ - R15++ +uint32 v = GSU.avReg[reg]; \ +GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ +GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; \ +RAM(GSU.vLastRamAdr) = (uint8)v; \ +RAM(GSU.vLastRamAdr^1) = (uint8)(v>>8); \ +CLRFLAGS; R15++; +static void fx_sm_r0() { FX_SM(0); } +static void fx_sm_r1() { FX_SM(1); } +static void fx_sm_r2() { FX_SM(2); } +static void fx_sm_r3() { FX_SM(3); } +static void fx_sm_r4() { FX_SM(4); } +static void fx_sm_r5() { FX_SM(5); } +static void fx_sm_r6() { FX_SM(6); } +static void fx_sm_r7() { FX_SM(7); } +static void fx_sm_r8() { FX_SM(8); } +static void fx_sm_r9() { FX_SM(9); } +static void fx_sm_r10() { FX_SM(10); } +static void fx_sm_r11() { FX_SM(11); } +static void fx_sm_r12() { FX_SM(12); } +static void fx_sm_r13() { FX_SM(13); } +static void fx_sm_r14() { FX_SM(14); } +static void fx_sm_r15() { FX_SM(15); } -static void fx_sm_r0 (void) +/*** GSU executions functions ***/ + +static uint32 fx_run(uint32 nInstructions) { - FX_SM(0); -} - -static void fx_sm_r1 (void) -{ - FX_SM(1); -} - -static void fx_sm_r2 (void) -{ - FX_SM(2); -} - -static void fx_sm_r3 (void) -{ - FX_SM(3); -} - -static void fx_sm_r4 (void) -{ - FX_SM(4); -} - -static void fx_sm_r5 (void) -{ - FX_SM(5); -} - -static void fx_sm_r6 (void) -{ - FX_SM(6); -} - -static void fx_sm_r7 (void) -{ - FX_SM(7); -} - -static void fx_sm_r8 (void) -{ - FX_SM(8); -} - -static void fx_sm_r9 (void) -{ - FX_SM(9); -} - -static void fx_sm_r10 (void) -{ - FX_SM(10); -} - -static void fx_sm_r11 (void) -{ - FX_SM(11); -} - -static void fx_sm_r12 (void) -{ - FX_SM(12); -} - -static void fx_sm_r13 (void) -{ - FX_SM(13); -} - -static void fx_sm_r14 (void) -{ - FX_SM(14); -} - -static void fx_sm_r15 (void) -{ - FX_SM(15); -} - -// GSU executions functions - -uint32 fx_run (uint32 nInstructions) -{ - GSU.vCounter = nInstructions; - READR14; - while (TF(G) && (GSU.vCounter-- > 0)) - FX_STEP; -#if 0 + GSU.vCounter = nInstructions; + READR14; + while( TF(G) && (GSU.vCounter-- > 0) ) + FX_STEP; + /* #ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); #endif -#endif - - return (nInstructions - GSU.vInstCount); -} - -/* -uint32 fx_run_to_breakpoint (uint32 nInstructions) -{ - uint32 vCounter = 0; - - while (TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - - if (USEX16(R15) == GSU.vBreakPoint) - { - GSU.vErrorCode = FX_BREAKPOINT; - break; - } - } - -#if 0 -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); -#endif -#endif - - return (vCounter); -} */ - -/* -uint32 fx_step_over (uint32 nInstructions) -{ - uint32 vCounter = 0; - - while (TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - - if (USEX16(R15) == GSU.vBreakPoint) - { - GSU.vErrorCode = FX_BREAKPOINT; - break; - } - - if (USEX16(R15) == GSU.vStepPoint) - break; - } - -#if 0 -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); -#endif -#endif - - return (vCounter); + return (nInstructions - GSU.vInstCount); } -*/ -// Special table for the different plot configurations - -void (*fx_PlotTable[]) (void) = +static uint32 fx_run_to_breakpoint(uint32 nInstructions) { - &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, - &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj + uint32 vCounter = 0; + while(TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + if(USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + } + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return vCounter; +} + +static uint32 fx_step_over(uint32 nInstructions) +{ + uint32 vCounter = 0; + while(TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + if(USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + if(USEX16(R15) == GSU.vStepPoint) + break; + } + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return vCounter; +} + +#ifdef FX_FUNCTION_TABLE +uint32 (*FX_FUNCTION_TABLE[])(uint32) = +#else +uint32 (*fx_apfFunctionTable[])(uint32) = +#endif +{ + &fx_run, + &fx_run_to_breakpoint, + &fx_step_over, }; -// Opcode table +/*** Special table for the different plot configurations ***/ -void (*fx_OpcodeTable[]) (void) = +#ifdef FX_PLOT_TABLE +void (*FX_PLOT_TABLE[])() = +#else +void (*fx_apfPlotTable[])() = +#endif { - // ALT0 Table - - // 00 - 0f - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - // 10 - 1f - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - // 20 - 2f - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - // 30 - 3f - &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, - &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - // 40 - 4f - &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, - &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit, &fx_swap, &fx_color, &fx_not, - // 50 - 5f - &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, - &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, - // 60 - 6f - &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, - &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, - // 70 - 7f - &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, - &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, - // 80 - 8f - &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, - &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, - // 90 - 9f - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, - &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, - // a0 - af - &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, - &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, - // b0 - bf - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - // c0 - cf - &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, - &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, - // d0 - df - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, - // e0 - ef - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, - // f0 - ff - &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, - &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, - - // ALT1 Table - - // 00 - 0f - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - // 10 - 1f - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - // 20 - 2f - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - // 30 - 3f - &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, - &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - // 40 - 4f - &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, - &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit, &fx_swap, &fx_cmode, &fx_not, - // 50 - 5f - &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, - &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, - // 60 - 6f - &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, - &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, - // 70 - 7f - &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, - &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, - // 80 - 8f - &fx_umult_r0, &fx_umult_r1, &fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, - &fx_umult_r8, &fx_umult_r9, &fx_umult_r10, &fx_umult_r11, &fx_umult_r12, &fx_umult_r13, &fx_umult_r14, &fx_umult_r15, - // 90 - 9f - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, - &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, - // a0 - af - &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, - &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, - // b0 - bf - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - // c0 - cf - &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, - &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, - // d0 - df - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, - // e0 - ef - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, - // f0 - ff - &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, - &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, - - // ALT2 Table - - // 00 - 0f - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - // 10 - 1f - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - // 20 - 2f - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - // 30 - 3f - &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, - &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - // 40 - 4f - &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, - &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit, &fx_swap, &fx_color, &fx_not, - // 50 - 5f - &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, - &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, - // 60 - 6f - &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, - &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, - // 70 - 7f - &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, - &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, - // 80 - 8f - &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, - &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, - // 90 - 9f - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, - &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, - // a0 - af - &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, - &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, - // b0 - bf - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - // c0 - cf - &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, - &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, - // d0 - df - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, - // e0 - ef - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, - // f0 - ff - &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, - &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, - - // ALT3 Table - - // 00 - 0f - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - // 10 - 1f - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - // 20 - 2f - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - // 30 - 3f - &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, - &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - // 40 - 4f - &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, - &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit, &fx_swap, &fx_cmode, &fx_not, - // 50 - 5f - &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, - &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, - // 60 - 6f - &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, - &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, - // 70 - 7f - &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, - &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, - // 80 - 8f - &fx_umult_i0, &fx_umult_i1, &fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, - &fx_umult_i8, &fx_umult_i9, &fx_umult_i10, &fx_umult_i11, &fx_umult_i12, &fx_umult_i13, &fx_umult_i14, &fx_umult_i15, - // 90 - 9f - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, - &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, - // a0 - af - &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, - &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, - // b0 - bf - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - // c0 - cf - &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, - &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, - // d0 - df - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, - // e0 - ef - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, - // f0 - ff - &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, - &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15 + &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, + &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj, }; + +/*** Opcode table ***/ + +#ifdef FX_OPCODE_TABLE +void (*FX_OPCODE_TABLE[])() = +#else +void (*fx_apfOpcodeTable[])() = +#endif +{ + /* + * ALT0 Table + */ + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, + /* 50 - 5f */ + &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, + &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, + /* 60 - 6f */ + &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, + &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, + /* 70 - 7f */ + &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, + &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, + /* 80 - 8f */ + &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, + &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + /* a0 - af */ + &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, + &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, + &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, + /* f0 - ff */ + &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, + &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, + + /* + * ALT1 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, + /* 50 - 5f */ + &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, + &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, + /* 60 - 6f */ + &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, + &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, + /* 70 - 7f */ + &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, + &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, + /* 80 - 8f */ + &fx_umult_r0,&fx_umult_r1,&fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, + &fx_umult_r8,&fx_umult_r9,&fx_umult_r10,&fx_umult_r11,&fx_umult_r12,&fx_umult_r13,&fx_umult_r14,&fx_umult_r15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + /* a0 - af */ + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, + &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, + /* f0 - ff */ + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, + + /* + * ALT2 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, + /* 50 - 5f */ + &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, + &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, + /* 60 - 6f */ + &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, + &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, + /* 70 - 7f */ + &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, + &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, + /* 80 - 8f */ + &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, + &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + /* a0 - af */ + &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, + &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, + &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, + /* f0 - ff */ + &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, + &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, + + /* + * ALT3 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, + /* 50 - 5f */ + &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, + &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, + /* 60 - 6f */ + &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, + &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, + /* 70 - 7f */ + &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, + &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, + /* 80 - 8f */ + &fx_umult_i0,&fx_umult_i1,&fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, + &fx_umult_i8,&fx_umult_i9,&fx_umult_i10,&fx_umult_i11,&fx_umult_i12,&fx_umult_i13,&fx_umult_i14,&fx_umult_i15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + /* a0 - af */ + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, + &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, + /* f0 - ff */ + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, +}; + diff --git a/source/snes9x/fxinst.h b/source/snes9x/fxinst.h index 498e027..e78e682 100644 --- a/source/snes9x/fxinst.h +++ b/source/snes9x/fxinst.h @@ -159,74 +159,73 @@ **********************************************************************************/ -#ifndef _FXINST_H_ -#define _FXINST_H_ -#ifndef ZSNES_FX +#ifndef _FXINST_H_ +#define _FXINST_H_ 1 /* * FxChip(GSU) register space specification - * (Register address space 3000-32ff) + * (Register address space 3000->32ff) * * The 16 generic 16 bit registers: * (Some have a special function in special circumstances) - * 3000 - R0 default source/destination register - * 3002 - R1 pixel plot X position register - * 3004 - R2 pixel plot Y position register + * 3000 - R0 default source/destination register + * 3002 - R1 pixel plot X position register + * 3004 - R2 pixel plot Y position register * 3006 - R3 - * 3008 - R4 lower 16 bit result of lmult + * 3008 - R4 lower 16 bit result of lmult * 300a - R5 - * 300c - R6 multiplier for fmult and lmult - * 300e - R7 fixed point texel X position for merge - * 3010 - R8 fixed point texel Y position for merge + * 300c - R6 multiplier for fmult and lmult + * 300e - R7 fixed point texel X position for merge + * 3010 - R8 fixed point texel Y position for merge * 3012 - R9 * 3014 - R10 - * 3016 - R11 return address set by link - * 3018 - R12 loop counter - * 301a - R13 loop point address - * 301c - R14 rom address for getb, getbh, getbl, getbs - * 301e - R15 program counter + * 3016 - R11 return address set by link + * 3018 - R12 loop counter + * 301a - R13 loop point address + * 301c - R14 rom address for getb, getbh, getbl, getbs + * 301e - R15 program counter * - * 3020-302f - unused + * 3020-302f - unused * * Other internal registers - * 3030 - SFR status flag register (16bit) - * 3032 - unused - * 3033 - BRAMR Backup RAM register (8bit) - * 3034 - PBR program bank register (8bit) - * 3035 - unused - * 3036 - ROMBR rom bank register (8bit) - * 3037 - CFGR control flags register (8bit) - * 3038 - SCBR screen base register (8bit) - * 3039 - CLSR clock speed register (8bit) - * 303a - SCMR screen mode register (8bit) - * 303b - VCR version code register (8bit) (read only) - * 303c - RAMBR ram bank register (8bit) - * 303d - unused - * 303e - CBR cache base register (16bit) + * 3030 - SFR status flag register (16bit) + * 3032 - unused + * 3033 - BRAMR Backup RAM register (8bit) + * 3034 - PBR program bank register (8bit) + * 3035 - unused + * 3036 - ROMBR rom bank register (8bit) + * 3037 - CFGR control flags register (8bit) + * 3038 - SCBR screen base register (8bit) + * 3039 - CLSR clock speed register (8bit) + * 303a - SCMR screen mode register (8bit) + * 303b - VCR version code register (8bit) (read only) + * 303c - RAMBR ram bank register (8bit) + * 303d - unused + * 303e - CBR cache base register (16bit) * - * 3040-30ff - unused + * 3040-30ff - unused * - * 3100-32ff - CACHERAM 512 bytes of GSU cache memory + * 3100-32ff - CACHERAM 512 bytes of GSU cache memory * * SFR status flag register bits: * 0 - - * 1 Z Zero flag - * 2 CY Carry flag - * 3 S Sign flag - * 4 OV Overflow flag - * 5 G Go flag (set to 1 when the GSU is running) - * 6 R Set to 1 when reading ROM using R14 address + * 1 Z Zero flag + * 2 CY Carry flag + * 3 S Sign flag + * 4 OV Overflow flag + * 5 G Go flag (set to 1 when the GSU is running) + * 6 R Set to 1 when reading ROM using R14 address * 7 - - * 8 ALT1 Mode set-up flag for the next instruction - * 9 ALT2 Mode set-up flag for the next instruction - * 10 IL Immediate lower 8-bit flag - * 11 IH Immediate higher 8-bit flag - * 12 B Set to 1 when the WITH instruction is executed + * 8 ALT1 Mode set-up flag for the next instruction + * 9 ALT2 Mode set-up flag for the next instruction + * 10 IL Immediate lower 8-bit flag + * 11 IH Immediate higher 8-bit flag + * 12 B Set to 1 when the WITH instruction is executed * 13 - * 14 - - * 15 IRQ Set to 1 when GSU caused an interrupt - * Set to 0 when read by 658c16 + * 15 IRQ Set to 1 when GSU caused an interrupt + * Set to 0 when read by 658c16 * * BRAMR = 0, BackupRAM is disabled * BRAMR = 1, BackupRAM is enabled @@ -237,44 +236,44 @@ * 2 - * 3 - * 4 - - * 5 MS0 Multiplier speed, 0=standard, 1=high speed + * 5 MS0 Multiplier speed, 0=standard, 1=high speed * 6 - - * 7 IRQ Set to 1 when GSU interrupt request is masked + * 7 IRQ Set to 1 when GSU interrupt request is masked * * CLSR clock speed register bits: - * 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz + * 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz * * SCMR screen mode register bits: - * 0 MD0 color depth mode bit 0 - * 1 MD1 color depth mode bit 1 - * 2 HT0 screen height bit 1 - * 3 RAN RAM access control - * 4 RON ROM access control - * 5 HT1 screen height bit 2 + * 0 MD0 color depth mode bit 0 + * 1 MD1 color depth mode bit 1 + * 2 HT0 screen height bit 1 + * 3 RAN RAM access control + * 4 RON ROM access control + * 5 HT1 screen height bit 2 * 6 - * 7 - * - * RON = 0 SNES CPU has ROM access - * RON = 1 GSU has ROM access + * RON = 0 SNES CPU has ROM access + * RON = 1 GSU has ROM access * - * RAN = 0 SNES has game pak RAM access - * RAN = 1 GSU has game pak RAM access + * RAN = 0 SNES has game pak RAM access + * RAN = 1 GSU has game pak RAM access * - * HT1 HT0 Screen height mode - * 0 0 128 pixels high - * 0 1 160 pixels high - * 1 0 192 pixels high - * 1 1 OBJ mode + * HT1 HT0 Screen height mode + * 0 0 128 pixels high + * 0 1 160 pixels high + * 1 0 192 pixels high + * 1 1 OBJ mode * - * MD1 MD0 Color depth mode - * 0 0 4 color mode - * 0 1 16 color mode - * 1 0 not used - * 1 1 256 color mode + * MD1 MD0 Color depth mode + * 0 0 4 color mode + * 0 1 16 color mode + * 1 0 not used + * 1 1 256 color mode * * CBR cache base register bits: - * 15-4 Specify base address for data to cache from ROM or RAM - * 3-0 Are 0 when address is read + * 15-4 Specify base address for data to cache from ROM or RAM + * 3-0 Are 0 when address is read * * Write access to the program counter (301e) from * the SNES-CPU will start the GSU, and it will not @@ -282,247 +281,270 @@ * */ -// Number of banks in GSU RAM -#define FX_RAM_BANKS 4 +/* Number of banks in GSU RAM */ +#define FX_RAM_BANKS 4 -// Emulate proper R14 ROM access (slower, but safer) -#define FX_DO_ROMBUFFER +/* Emulate proper R14 ROM access (slower, but safer) */ +/* #define FX_DO_ROMBUFFER */ -// Address checking (definately slow) -//#define FX_ADDRESS_CHECK +/* Address checking (definately slow) */ +/* #define FX_ADDRESS_CHECK */ struct FxRegs_s { - // FxChip registers - uint32 avReg[16]; // 16 Generic registers - uint32 vColorReg; // Internal color register - uint32 vPlotOptionReg; // Plot option register - uint32 vStatusReg; // Status register - uint32 vPrgBankReg; // Program bank index register - uint32 vRomBankReg; // Rom bank index register - uint32 vRamBankReg; // Ram bank index register - uint32 vCacheBaseReg; // Cache base address register - uint32 vCacheFlags; // Saying what parts of the cache was written to - uint32 vLastRamAdr; // Last RAM address accessed - uint32 *pvDreg; // Pointer to current destination register - uint32 *pvSreg; // Pointer to current source register - uint8 vRomBuffer; // Current byte read by R14 - uint8 vPipe; // Instructionset pipe - uint32 vPipeAdr; // The address of where the pipe was read from + /* FxChip registers */ + uint32 avReg[16]; /* 16 Generic registers */ + uint32 vColorReg; /* Internal color register */ + uint32 vPlotOptionReg; /* Plot option register */ + uint32 vStatusReg; /* Status register */ + uint32 vPrgBankReg; /* Program bank index register */ + uint32 vRomBankReg; /* Rom bank index register */ + uint32 vRamBankReg; /* Ram bank index register */ + uint32 vCacheBaseReg; /* Cache base address register */ + uint32 vCacheFlags; /* Saying what parts of the cache was written to */ + uint32 vLastRamAdr; /* Last RAM address accessed */ + uint32 * pvDreg; /* Pointer to current destination register */ + uint32 * pvSreg; /* Pointer to current source register */ + uint8 vRomBuffer; /* Current byte read by R14 */ + uint8 vPipe; /* Instructionset pipe */ + uint32 vPipeAdr; /* The address of where the pipe was read from */ - // Status register optimization stuff - uint32 vSign; // v & 0x8000 - uint32 vZero; // v == 0 - uint32 vCarry; // a value of 1 or 0 - int32 vOverflow; // (v >= 0x8000 || v < -0x8000) + /* status register optimization stuff */ + uint32 vSign; /* v & 0x8000 */ + uint32 vZero; /* v == 0 */ + uint32 vCarry; /* a value of 1 or 0 */ + int32 vOverflow; /* (v >= 0x8000 || v < -0x8000) */ - // Other emulator variables - int32 vErrorCode; - uint32 vIllegalAddress; + /* Other emulator variables */ - uint8 bBreakPoint; - uint32 vBreakPoint; - uint32 vStepPoint; + int32 vErrorCode; + uint32 vIllegalAddress; - uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 - uint32 nRamBanks; // Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) - uint8 *pvRam; // Pointer to FxRam - uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM - uint8 *pvRom; // Pointer to Cart-ROM + uint8 bBreakPoint; + uint32 vBreakPoint; + uint32 vStepPoint; - uint32 vMode; // Color depth/mode - uint32 vPrevMode; // Previous depth - uint8 *pvScreenBase; - uint8 *apvScreen[32]; // Pointer to each of the 32 screen colums - int32 x[32]; - uint32 vScreenHeight; // 128, 160, 192 or 256 (could be overriden by cmode) - uint32 vScreenRealHeight; // 128, 160, 192 or 256 - uint32 vPrevScreenHeight; - uint32 vScreenSize; - void (*pfPlot) (void); - void (*pfRpix) (void); + uint8 * pvRegisters; /* 768 bytes located in the memory at address 0x3000 */ + uint32 nRamBanks; /* Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) */ + uint8 * pvRam; /* Pointer to FxRam */ + uint32 nRomBanks; /* Number of 32kb-banks in Cart-ROM */ + uint8 * pvRom; /* Pointer to Cart-ROM */ - uint8 *pvRamBank; // Pointer to current RAM-bank - uint8 *pvRomBank; // Pointer to current ROM-bank - uint8 *pvPrgBank; // Pointer to current program ROM-bank + uint32 vMode; /* Color depth/mode */ + uint32 vPrevMode; /* Previous depth */ + uint8 * pvScreenBase; + uint8 * apvScreen[32]; /* Pointer to each of the 32 screen colums */ + int32 x[32]; + uint32 vScreenHeight; /* 128, 160, 192 or 256 (could be overriden by cmode) */ + uint32 vScreenRealHeight; /* 128, 160, 192 or 256 */ + uint32 vPrevScreenHeight; + uint32 vScreenSize; + void (*pfPlot)(); + void (*pfRpix)(); - uint8 *apvRamBank[FX_RAM_BANKS]; // Ram bank table (max 256kb) - uint8 *apvRomBank[256]; // Rom bank table + uint8 * pvRamBank; /* Pointer to current RAM-bank */ + uint8 * pvRomBank; /* Pointer to current ROM-bank */ + uint8 * pvPrgBank; /* Pointer to current program ROM-bank */ - uint8 bCacheActive; - uint8 *pvCache; // Pointer to the GSU cache - uint8 avCacheBackup[512]; // Backup of ROM when the cache has replaced it - uint32 vCounter; - uint32 vInstCount; - uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating + uint8 * apvRamBank[FX_RAM_BANKS];/* Ram bank table (max 256kb) */ + uint8 * apvRomBank[256]; /* Rom bank table */ + + uint8 bCacheActive; + uint8 * pvCache; /* Pointer to the GSU cache */ + uint8 avCacheBackup[512]; /* Backup of ROM when the cache has replaced it */ + uint32 vCounter; + uint32 vInstCount; + uint32 vSCBRDirty; /* if SCBR is written, our cached screen pointers need updating */ }; -extern struct FxRegs_s GSU; +#define FxRegs_s_null { \ + {0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, NULL, 0, NULL, 0, NULL, 0, \ + 0, NULL, {NULL}, {0}, 0, 0, 0, 0, NULL, NULL, \ + NULL, NULL, NULL, {NULL}, {NULL}, 0, NULL, {0}, 0, 0, \ + 0, \ +} -// GSU registers -#define GSU_R0 0x000 -#define GSU_R1 0x002 -#define GSU_R2 0x004 -#define GSU_R3 0x006 -#define GSU_R4 0x008 -#define GSU_R5 0x00a -#define GSU_R6 0x00c -#define GSU_R7 0x00e -#define GSU_R8 0x010 -#define GSU_R9 0x012 -#define GSU_R10 0x014 -#define GSU_R11 0x016 -#define GSU_R12 0x018 -#define GSU_R13 0x01a -#define GSU_R14 0x01c -#define GSU_R15 0x01e -#define GSU_SFR 0x030 -#define GSU_BRAMR 0x033 -#define GSU_PBR 0x034 -#define GSU_ROMBR 0x036 -#define GSU_CFGR 0x037 -#define GSU_SCBR 0x038 -#define GSU_CLSR 0x039 -#define GSU_SCMR 0x03a -#define GSU_VCR 0x03b -#define GSU_RAMBR 0x03c -#define GSU_CBR 0x03e -#define GSU_CACHERAM 0x100 +/* GSU registers */ +#define GSU_R0 0x000 +#define GSU_R1 0x002 +#define GSU_R2 0x004 +#define GSU_R3 0x006 +#define GSU_R4 0x008 +#define GSU_R5 0x00a +#define GSU_R6 0x00c +#define GSU_R7 0x00e +#define GSU_R8 0x010 +#define GSU_R9 0x012 +#define GSU_R10 0x014 +#define GSU_R11 0x016 +#define GSU_R12 0x018 +#define GSU_R13 0x01a +#define GSU_R14 0x01c +#define GSU_R15 0x01e +#define GSU_SFR 0x030 +#define GSU_BRAMR 0x033 +#define GSU_PBR 0x034 +#define GSU_ROMBR 0x036 +#define GSU_CFGR 0x037 +#define GSU_SCBR 0x038 +#define GSU_CLSR 0x039 +#define GSU_SCMR 0x03a +#define GSU_VCR 0x03b +#define GSU_RAMBR 0x03c +#define GSU_CBR 0x03e +#define GSU_CACHERAM 0x100 -// SFR flags -#define FLG_Z (1 << 1) -#define FLG_CY (1 << 2) -#define FLG_S (1 << 3) -#define FLG_OV (1 << 4) -#define FLG_G (1 << 5) -#define FLG_R (1 << 6) -#define FLG_ALT1 (1 << 8) -#define FLG_ALT2 (1 << 9) -#define FLG_IL (1 << 10) -#define FLG_IH (1 << 11) -#define FLG_B (1 << 12) -#define FLG_IRQ (1 << 15) +/* SFR flags */ +#define FLG_Z (1<<1) +#define FLG_CY (1<<2) +#define FLG_S (1<<3) +#define FLG_OV (1<<4) +#define FLG_G (1<<5) +#define FLG_R (1<<6) +#define FLG_ALT1 (1<<8) +#define FLG_ALT2 (1<<9) +#define FLG_IL (1<<10) +#define FLG_IH (1<<11) +#define FLG_B (1<<12) +#define FLG_IRQ (1<<15) -// Test flag -#define TF(a) (GSU.vStatusReg & FLG_##a) -#define CF(a) (GSU.vStatusReg &= ~FLG_##a) -#define SF(a) (GSU.vStatusReg |= FLG_##a) +/* Test flag */ +#define TF(a) (GSU.vStatusReg & FLG_##a ) +#define CF(a) (GSU.vStatusReg &= ~FLG_##a ) +#define SF(a) (GSU.vStatusReg |= FLG_##a ) -// Test and set flag if condition, clear if not -#define TS(a, b) GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a)) +/* Test and set flag if condition, clear if not */ +#define TS(a,b) GSU.vStatusReg = ( (GSU.vStatusReg & (~FLG_##a)) | ( (!!(##b)) * FLG_##a ) ) -// Testing ALT1 & ALT2 bits -#define ALT0 (!TF(ALT1) && !TF(ALT2)) -#define ALT1 ( TF(ALT1) && !TF(ALT2)) -#define ALT2 (!TF(ALT1) && TF(ALT2)) -#define ALT3 ( TF(ALT1) && TF(ALT2)) +/* Testing ALT1 & ALT2 bits */ +#define ALT0 (!TF(ALT1)&&!TF(ALT2)) +#define ALT1 (TF(ALT1)&&!TF(ALT2)) +#define ALT2 (!TF(ALT1)&&TF(ALT2)) +#define ALT3 (TF(ALT1)&&TF(ALT2)) -// Sign extend from 8/16 bit to 32 bit -#define SEX8(a) ((int32) ((int8) (a))) -#define SEX16(a) ((int32) ((int16) (a))) +/* Sign extend from 8/16 bit to 32 bit */ +#define SEX16(a) ((int32)((int16)(a))) +#define SEX8(a) ((int32)((int8)(a))) -// Unsign extend from 8/16 bit to 32 bit -#define USEX8(a) ((uint32) ((uint8) (a))) -#define USEX16(a) ((uint32) ((uint16) (a))) -#define SUSEX16(a) ((int32) ((uint16) (a))) +/* Unsign extend from 8/16 bit to 32 bit */ +#define USEX16(a) ((uint32)((uint16)(a))) +#define USEX8(a) ((uint32)((uint8)(a))) -// Set/Clr Sign and Zero flag -#define TSZ(num) TS(S, ((num) & 0x8000)); TS(Z, (!USEX16(num))) +#define SUSEX16(a) ((int32)((uint16)(a))) -// Clear flags -#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1 | FLG_ALT2 | FLG_B); GSU.pvDreg = GSU.pvSreg = &R0 +/* Set/Clr Sign and Zero flag */ +#define TSZ(num) TS(S, (num & 0x8000)); TS(Z, (!USEX16(num)) ) -// Read current RAM-Bank -#define RAM(adr) GSU.pvRamBank[USEX16(adr)] +/* Clear flags */ +#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1|FLG_ALT2|FLG_B); GSU.pvDreg = GSU.pvSreg = &R0; -// Read current ROM-Bank -#define ROM(idx) GSU.pvRomBank[USEX16(idx)] +/* Read current RAM-Bank */ +#define RAM(adr) GSU.pvRamBank[USEX16(adr)] -// Access the current value in the pipe -#define PIPE GSU.vPipe +/* Read current ROM-Bank */ +#define ROM(idx) (GSU.pvRomBank[USEX16(idx)]) -// Access data in the current program bank -#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] +/* Access the current value in the pipe */ +#define PIPE GSU.vPipe -// Update pipe from ROM +/* Access data in the current program bank */ +#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] + +/* Update pipe from ROM */ #if 0 -#define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg << 16) + R15; } +#define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg<<16) + R15; } #else -#define FETCHPIPE { PIPE = PRGBANK(R15); } +#define FETCHPIPE { PIPE = PRGBANK(R15); } #endif -// ABS -#define ABS(x) ((x) < 0 ? -(x) : (x)) +/* ABS */ +#define ABS(x) ((x)<0?-(x):(x)) -// Access source register -#define SREG (*GSU.pvSreg) +/* Access source register */ +#define SREG (*GSU.pvSreg) -// Access destination register -#define DREG (*GSU.pvDreg) +/* Access destination register */ +#define DREG (*GSU.pvDreg) #ifndef FX_DO_ROMBUFFER -// Don't read R14 +/* Don't read R14 */ #define READR14 -// Don't test and/or read R14 +/* Don't test and/or read R14 */ #define TESTR14 #else -// Read R14 -#define READR14 GSU.vRomBuffer = ROM(R14) +/* Read R14 */ +#define READR14 GSU.vRomBuffer = ROM(R14) -// Test and/or read R14 -#define TESTR14 if (GSU.pvDreg == &R14) READR14 +/* Test and/or read R14 */ +#define TESTR14 if(GSU.pvDreg == &R14) READR14 #endif -// Access to registers -#define R0 GSU.avReg[0] -#define R1 GSU.avReg[1] -#define R2 GSU.avReg[2] -#define R3 GSU.avReg[3] -#define R4 GSU.avReg[4] -#define R5 GSU.avReg[5] -#define R6 GSU.avReg[6] -#define R7 GSU.avReg[7] -#define R8 GSU.avReg[8] -#define R9 GSU.avReg[9] -#define R10 GSU.avReg[10] -#define R11 GSU.avReg[11] -#define R12 GSU.avReg[12] -#define R13 GSU.avReg[13] -#define R14 GSU.avReg[14] -#define R15 GSU.avReg[15] -#define SFR GSU.vStatusReg -#define PBR GSU.vPrgBankReg -#define ROMBR GSU.vRomBankReg -#define RAMBR GSU.vRamBankReg -#define CBR GSU.vCacheBaseReg -#define SCBR USEX8(GSU.pvRegisters[GSU_SCBR]) -#define SCMR USEX8(GSU.pvRegisters[GSU_SCMR]) -#define COLR GSU.vColorReg -#define POR GSU.vPlotOptionReg -#define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR]) -#define VCR USEX8(GSU.pvRegisters[GSU_VCR]) -#define CFGR USEX8(GSU.pvRegisters[GSU_CFGR]) -#define CLSR USEX8(GSU.pvRegisters[GSU_CLSR]) +/* Access to registers */ +#define R0 GSU.avReg[0] +#define R1 GSU.avReg[1] +#define R2 GSU.avReg[2] +#define R3 GSU.avReg[3] +#define R4 GSU.avReg[4] +#define R5 GSU.avReg[5] +#define R6 GSU.avReg[6] +#define R7 GSU.avReg[7] +#define R8 GSU.avReg[8] +#define R9 GSU.avReg[9] +#define R10 GSU.avReg[10] +#define R11 GSU.avReg[11] +#define R12 GSU.avReg[12] +#define R13 GSU.avReg[13] +#define R14 GSU.avReg[14] +#define R15 GSU.avReg[15] +#define SFR GSU.vStatusReg +#define PBR GSU.vPrgBankReg +#define ROMBR GSU.vRomBankReg +#define RAMBR GSU.vRamBankReg +#define CBR GSU.vCacheBaseReg +#define SCBR USEX8(GSU.pvRegisters[GSU_SCBR]) +#define SCMR USEX8(GSU.pvRegisters[GSU_SCMR]) +#define COLR GSU.vColorReg +#define POR GSU.vPlotOptionReg +#define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR]) +#define VCR USEX8(GSU.pvRegisters[GSU_VCR]) +#define CFGR USEX8(GSU.pvRegisters[GSU_CFGR]) +#define CLSR USEX8(GSU.pvRegisters[GSU_CLSR]) -// Execute instruction from the pipe, and fetch next byte to the pipe -#define FX_STEP \ -{ \ - uint32 vOpcode = (uint32) PIPE; \ - FETCHPIPE; \ - (*fx_OpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \ -} +/* Execute instruction from the pipe, and fetch next byte to the pipe */ +#define FX_STEP { uint32 vOpcode = (uint32)PIPE; FETCHPIPE; \ +(*fx_ppfOpcodeTable[ (GSU.vStatusReg & 0x300) | vOpcode ])(); } \ -extern void (*fx_PlotTable[]) (void); -extern void (*fx_OpcodeTable[]) (void); +#define FX_FUNCTION_RUN 0 +#define FX_FUNCTION_RUN_TO_BREAKPOINT 1 +#define FX_FUNCTION_STEP_OVER 2 -// Set this define if branches are relative to the instruction in the delay slot (I think they are) +extern uint32 (**fx_ppfFunctionTable)(uint32); +extern void (**fx_ppfPlotTable)(); +extern void (**fx_ppfOpcodeTable)(); + +extern uint32 (*fx_apfFunctionTable[])(uint32); +extern void (*fx_apfOpcodeTable[])(); +extern void (*fx_apfPlotTable[])(); +extern uint32 (*fx_a_apfFunctionTable[])(uint32); +extern void (*fx_a_apfOpcodeTable[])(); +extern void (*fx_a_apfPlotTable[])(); +extern uint32 (*fx_r_apfFunctionTable[])(uint32); +extern void (*fx_r_apfOpcodeTable[])(); +extern void (*fx_r_apfPlotTable[])(); +extern uint32 (*fx_ar_apfFunctionTable[])(uint32); +extern void (*fx_ar_apfOpcodeTable[])(); +extern void (*fx_ar_apfPlotTable[])(); + +/* Set this define if branches are relative to the instruction in the delay slot */ +/* (I think they are) */ #define BRANCH_DELAY_RELATIVE #endif -#endif diff --git a/source/snes9x/getset.h b/source/snes9x/getset.h index b295953..d962381 100644 --- a/source/snes9x/getset.h +++ b/source/snes9x/getset.h @@ -159,730 +159,797 @@ **********************************************************************************/ + + #ifndef _GETSET_H_ #define _GETSET_H_ +#include "ppu.h" +#include "dsp1.h" #include "cpuexec.h" -#include "dsp.h" #include "sa1.h" #include "spc7110.h" -#include "c4.h" #include "obc1.h" #include "seta.h" #include "bsx.h" -extern uint8 OpenBus; - -inline uint8 S9xGetByte (uint32 Address) +extern "C" { - int block; - uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed[block]; - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - #ifdef CPU_SHUTDOWN - if (Memory.BlockIsRAM[block]) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif - return (*(GetAddress + (Address & 0xffff))); - } - - switch ((pint) GetAddress) - { - case CMemory::MAP_CPU: - return (S9xGetCPU(Address & 0xffff)); - - case CMemory::MAP_PPU: - if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) - return (OpenBus); - return (S9xGetPPU(Address & 0xffff)); - - case CMemory::MAP_LOROM_SRAM: - case CMemory::MAP_SA1RAM: - // Address & 0x7fff : offset into bank - // Address & 0xff0000 : bank - // bank >> 1 | offset : SRAM address, unbound - // unbound & SRAMMask : SRAM offset - return (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))); - - case CMemory::MAP_LOROM_SRAM_B: - return (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))); - - case CMemory::MAP_HIROM_SRAM: - case CMemory::MAP_RONLY_SRAM: - return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); - - case CMemory::MAP_BWRAM: - return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); - - case CMemory::MAP_DSP: - return (S9xGetDSP(Address & 0xffff)); - - case CMemory::MAP_SPC7110_ROM: - return (S9xGetSPC7110Byte(Address)); - - case CMemory::MAP_SPC7110_DRAM: - return (S9xGetSPC7110(0x4800)); - - case CMemory::MAP_C4: - return (S9xGetC4(Address & 0xffff)); - - case CMemory::MAP_OBC_RAM: - return (S9xGetOBC1(Address & 0xffff)); - - case CMemory::MAP_SETA_DSP: - return (S9xGetSetaDSP(Address)); - - case CMemory::MAP_SETA_RISC: - return (S9xGetST018(Address)); - - case CMemory::MAP_BSX: - return (S9xGetBSX(Address)); - - case CMemory::MAP_NONE: - default: - return (OpenBus); - } + extern uint8 OpenBus; } -inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) +INLINE uint8 S9xGetByte (uint32 Address) { - uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); - if ((Address & mask) == mask) - { - PC_t a; + int block; + uint8 *GetAddress = Memory.Map [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; - OpenBus = S9xGetByte(Address); + if(!CPU.InDMAorHDMA) + CPU.Cycles += Memory.MemorySpeed [block]; - switch (w) - { - case WRAP_PAGE: - a.xPBPC = Address; - a.B.xPCl++; - return (OpenBus | (S9xGetByte(a.xPBPC) << 8)); - - case WRAP_BANK: - a.xPBPC = Address; - a.W.xPC++; - return (OpenBus | (S9xGetByte(a.xPBPC) << 8)); - - case WRAP_NONE: - default: - return (OpenBus | (S9xGetByte(Address + 1) << 8)); - } - } - - int block; - uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += (Memory.MemorySpeed[block] << 1); - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - #ifdef CPU_SHUTDOWN - if (Memory.BlockIsRAM[block]) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif - return (READ_WORD(GetAddress + (Address & 0xffff))); - } - - switch ((pint) GetAddress) - { - case CMemory::MAP_CPU: - return (S9xGetCPU(Address & 0xffff) | (S9xGetCPU((Address + 1) & 0xffff) << 8)); - - case CMemory::MAP_PPU: - if (CPU.InDMAorHDMA) - { - OpenBus = S9xGetByte(Address); - return (OpenBus | (S9xGetByte(Address + 1) << 8)); - } - - return (S9xGetPPU(Address & 0xffff) | (S9xGetPPU((Address + 1) & 0xffff) << 8)); - - case CMemory::MAP_LOROM_SRAM: - case CMemory::MAP_SA1RAM: - if (Memory.SRAMMask >= MEMMAP_MASK) - return (READ_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))); - else - return ((*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) | - ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8)); - - case CMemory::MAP_LOROM_SRAM_B: - if (Multi.sramMaskB >= MEMMAP_MASK) - return (READ_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))); - else - return ((*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) | - ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8)); - - case CMemory::MAP_HIROM_SRAM: - case CMemory::MAP_RONLY_SRAM: - if (Memory.SRAMMask >= MEMMAP_MASK) - return (READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); - else - return ((*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | - (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8))); - - case CMemory::MAP_BWRAM: - return (READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); - - case CMemory::MAP_DSP: - return (S9xGetDSP(Address & 0xffff) | (S9xGetDSP((Address + 1) & 0xffff) << 8)); - - case CMemory::MAP_SPC7110_ROM: - return (S9xGetSPC7110Byte(Address) | (S9xGetSPC7110Byte(Address + 1) << 8)); - - case CMemory::MAP_SPC7110_DRAM: - return (S9xGetSPC7110(0x4800) | (S9xGetSPC7110(0x4800) << 8)); - - case CMemory::MAP_C4: - return (S9xGetC4(Address & 0xffff) | (S9xGetC4((Address + 1) & 0xffff) << 8)); - - case CMemory::MAP_OBC_RAM: - return (S9xGetOBC1(Address & 0xffff) | (S9xGetOBC1((Address + 1) & 0xffff) << 8)); - - case CMemory::MAP_SETA_DSP: - return (S9xGetSetaDSP(Address) | (S9xGetSetaDSP(Address + 1) << 8)); - - case CMemory::MAP_SETA_RISC: - return (S9xGetST018(Address) | (S9xGetST018(Address + 1) << 8)); - - case CMemory::MAP_BSX: - return (S9xGetBSX(Address) | (S9xGetBSX(Address + 1) << 8)); - - case CMemory::MAP_NONE: - default: - return (OpenBus | (OpenBus << 8)); - } -} - -inline void S9xSetByte (uint8 Byte, uint32 Address) -{ + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + if (Memory.BlockIsRAM [block]) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; #endif + return (*(GetAddress + (Address & 0xffff))); + } - int block; - uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + switch ((pint) GetAddress) + { + case CMemory::MAP_PPU: + if(CPU.InDMAorHDMA && (Address&0xff00)==0x2100) return OpenBus; + return (S9xGetPPU (Address & 0xffff)); + case CMemory::MAP_CPU: + return (S9xGetCPU (Address & 0xffff)); + case CMemory::MAP_DSP: + return (S9xGetDSP (Address & 0xffff)); + case CMemory::MAP_SA1RAM: + case CMemory::MAP_LOROM_SRAM: + //Address &0x7FFF -offset into bank + //Address&0xFF0000 -bank + //bank>>1 | offset = s-ram address, unbound + //unbound & SRAMMask = Sram offset + return (*(Memory.SRAM + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Memory.SRAMMask))); - if (!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed[block]; + case CMemory::MAP_LOROM_SRAM_B: + return (*(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB))); - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) - { - #ifdef CPU_SHUTDOWN - SetAddress += (Address & 0xffff); - *SetAddress = Byte; + case CMemory::MAP_RONLY_SRAM: + case CMemory::MAP_HIROM_SRAM: + return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); - if (Settings.SA1) - { - if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) - { - SA1.Executing = SA1.S9xOpcodes != NULL; - SA1.WaitCounter = 0; - } - } - #else - *(SetAddress + (Address & 0xffff)) = Byte; - #endif - return; - } + case CMemory::MAP_BWRAM: + return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); - switch ((pint) SetAddress) - { - case CMemory::MAP_CPU: - S9xSetCPU(Byte, Address & 0xffff); - return; + case CMemory::MAP_C4: + return (S9xGetC4 (Address & 0xffff)); - case CMemory::MAP_PPU: - if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) - return; - S9xSetPPU(Byte, Address & 0xffff); - return; + case CMemory::MAP_SPC7110_ROM: +#ifdef SPC7110_DEBUG + printf("reading spc7110 ROM (byte) at %06X\n", Address); +#endif + return S9xGetSPC7110Byte(Address); - case CMemory::MAP_LOROM_SRAM: - if (Memory.SRAMMask) - { - *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = Byte; - CPU.SRAMModified = TRUE; - } + case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG + printf("reading Bank 50 (byte)\n"); +#endif + return S9xGetSPC7110(0x4800); - return; + case CMemory::MAP_OBC_RAM: + return GetOBC1(Address & 0xffff); - case CMemory::MAP_LOROM_SRAM_B: - if (Multi.sramMaskB) - { - *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = Byte; - CPU.SRAMModified = TRUE; - } + case CMemory::MAP_SETA_DSP: + return S9xGetSetaDSP(Address); - return; + case CMemory::MAP_SETA_RISC: + return S9xGetST018(Address); - case CMemory::MAP_HIROM_SRAM: - if (Memory.SRAMMask) - { - *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte; - CPU.SRAMModified = TRUE; - } + case CMemory::MAP_BSX: + return S9xGetBSX(Address); - return; - - case CMemory::MAP_BWRAM: - *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; - CPU.SRAMModified = TRUE; - return; - - case CMemory::MAP_SA1RAM: - *(Memory.SRAM + (Address & 0xffff)) = Byte; - SA1.Executing = !SA1.Waiting; - return; - - case CMemory::MAP_DSP: - S9xSetDSP(Byte, Address & 0xffff); - return; - - case CMemory::MAP_C4: - S9xSetC4(Byte, Address & 0xffff); - return; - - case CMemory::MAP_OBC_RAM: - S9xSetOBC1(Byte, Address & 0xffff); - return; - - case CMemory::MAP_SETA_DSP: - S9xSetSetaDSP(Byte, Address); - return; - - case CMemory::MAP_SETA_RISC: - S9xSetST018(Byte, Address); - return; - - case CMemory::MAP_BSX: - S9xSetBSX(Byte, Address); - return; - - case CMemory::MAP_NONE: - default: - return; - } + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("DEBUG R(B) %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + return OpenBus; + } } -inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01) +#ifdef NO_INLINE_SET_GET +INLINE uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w) +#else +INLINE uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w=WRAP_NONE) +#endif { - uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); - if ((Address & mask) == mask) - { - PC_t a; + uint32 mask=MEMMAP_MASK&(w==WRAP_PAGE?0xff:(w==WRAP_BANK?0xffff:0xffffff)); + if ((Address & mask) == mask) + { + OpenBus=S9xGetByte(Address); + switch(w){ + case WRAP_PAGE: + { + PC_t a; + a.xPBPC = Address; + a.B.xPCl++; + return (OpenBus | (S9xGetByte (a.xPBPC) << 8)); + } + case WRAP_BANK: + { + PC_t a; + a.xPBPC = Address; + a.W.xPC++; + return (OpenBus | (S9xGetByte (a.xPBPC) << 8)); + } + case WRAP_NONE: + default: + return (OpenBus | (S9xGetByte (Address + 1) << 8)); + } + } + int block; + uint8 *GetAddress = Memory.Map [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; - if (!o) - S9xSetByte((uint8) Word, Address); + if(!CPU.InDMAorHDMA) + CPU.Cycles += (Memory.MemorySpeed [block]<<1); - switch (w) - { - case WRAP_PAGE: - a.xPBPC = Address; - a.B.xPCl++; - S9xSetByte(Word >> 8, a.xPBPC); - break; - - case WRAP_BANK: - a.xPBPC = Address; - a.W.xPC++; - S9xSetByte(Word >> 8, a.xPBPC); - break; - - case WRAP_NONE: - default: - S9xSetByte(Word >> 8, Address + 1); - break; - } - - if (o) - S9xSetByte((uint8) Word, Address); - - return; - } + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { #ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; + if (Memory.BlockIsRAM [block]) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; +#endif + return READ_WORD(GetAddress + (Address & 0xffff)); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_PPU: + if(CPU.InDMAorHDMA){ + OpenBus=S9xGetByte (Address); + return (OpenBus | (S9xGetByte (Address + 1) << 8)); + } + return (S9xGetPPU (Address & 0xffff) | + (S9xGetPPU ((Address + 1) & 0xffff) << 8)); + case CMemory::MAP_CPU: + return (S9xGetCPU (Address & 0xffff) | + (S9xGetCPU ((Address + 1) & 0xffff) << 8)); + case CMemory::MAP_DSP: +#ifdef DSP_DUMMY_LOOPS + printf("Get DSP Word @ %06X\n", Address); +#endif + return (S9xGetDSP (Address & 0xffff) | + (S9xGetDSP ((Address + 1) & 0xffff) << 8)); + case CMemory::MAP_SA1RAM: + case CMemory::MAP_LOROM_SRAM: + //Address &0x7FFF -offset into bank + //Address&0xFF0000 -bank + //bank>>1 | offset = s-ram address, unbound + //unbound & SRAMMask = Sram offset + if(Memory.SRAMMask>=MEMMAP_MASK){ + return READ_WORD(Memory.SRAM + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Memory.SRAMMask)); + } else { + /* no READ_WORD here, since if Memory.SRAMMask=0x7ff + * then the high byte doesn't follow the low byte. */ + return + (*(Memory.SRAM + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Memory.SRAMMask)))| + ((*(Memory.SRAM + (((((Address+1)&0xFF0000)>>1) |((Address+1)&0x7FFF)) &Memory.SRAMMask)))<<8); + } + + case CMemory::MAP_LOROM_SRAM_B: + if(Multi.sramMaskB>=MEMMAP_MASK){ + return READ_WORD(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB)); + } else { + return + (*(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB)))| + ((*(Multi.sramB + (((((Address+1)&0xFF0000)>>1) |((Address+1)&0x7FFF)) &Multi.sramMaskB)))<<8); + } + + case CMemory::MAP_RONLY_SRAM: + case CMemory::MAP_HIROM_SRAM: + if(Memory.SRAMMask>=MEMMAP_MASK){ + return READ_WORD(Memory.SRAM + + (((Address & 0x7fff) - 0x6000 + + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + } else { + /* no READ_WORD here, since if Memory.SRAMMask=0x7ff + * then the high byte doesn't follow the low byte. */ + return (*(Memory.SRAM + + (((Address & 0x7fff) - 0x6000 + + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | + (*(Memory.SRAM + + ((((Address + 1) & 0x7fff) - 0x6000 + + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8)); + } + + case CMemory::MAP_BWRAM: + return READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + + case CMemory::MAP_C4: + return (S9xGetC4 (Address & 0xffff) | + (S9xGetC4 ((Address + 1) & 0xffff) << 8)); + + case CMemory::MAP_SPC7110_ROM: +#ifdef SPC7110_DEBUG + printf("reading spc7110 ROM (word) at %06X\n", Address); +#endif + return (S9xGetSPC7110Byte(Address)| + (S9xGetSPC7110Byte (Address+1))<<8); + case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG + printf("reading Bank 50 (word)\n"); +#endif + return (S9xGetSPC7110(0x4800)| + (S9xGetSPC7110 (0x4800) << 8)); + case CMemory::MAP_OBC_RAM: + return GetOBC1(Address&0xFFFF)| (GetOBC1((Address+1)&0xFFFF)<<8); + + case CMemory::MAP_SETA_DSP: + return S9xGetSetaDSP(Address)| (S9xGetSetaDSP((Address+1))<<8); + + case CMemory::MAP_SETA_RISC: + return S9xGetST018(Address)| (S9xGetST018((Address+1))<<8); + + case CMemory::MAP_BSX: + return S9xGetBSX(Address)| (S9xGetBSX((Address+1))<<8); + + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("DEBUG R(W) %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + return (OpenBus | (OpenBus<<8)); + } +} + +INLINE void S9xSetByte (uint8 Byte, uint32 Address) +{ +#if defined(CPU_SHUTDOWN) + CPU.WaitAddress = 0xffffffff; +#endif + int block; + uint8 *SetAddress = Memory.WriteMap [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; + + if (!CPU.InDMAorHDMA) + CPU.Cycles += Memory.MemorySpeed [block]; + + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { +#ifdef CPU_SHUTDOWN + SetAddress += Address & 0xffff; + if (SetAddress == SA1.WaitByteAddress1 || + SetAddress == SA1.WaitByteAddress2) + { + SA1.Executing = SA1.S9xOpcodes != NULL; + SA1.WaitCounter = 0; + } + *SetAddress = Byte; +#else + *(SetAddress + (Address & 0xffff)) = Byte; +#endif + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_PPU: + if(CPU.InDMAorHDMA && (Address&0xff00)==0x2100) return; + S9xSetPPU (Byte, Address & 0xffff); + return; + + case CMemory::MAP_CPU: + S9xSetCPU (Byte, Address & 0xffff); + return; + + case CMemory::MAP_DSP: +#ifdef DSP_DUMMY_LOOPS + printf("DSP Byte: %02X to %06X\n", Byte, Address); +#endif + S9xSetDSP (Byte, Address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Memory.SRAMMask))=Byte; + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) + { + *(Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Multi.sramMaskB))=Byte; + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_HIROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte; + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_BWRAM: + *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; + CPU.SRAMModified = TRUE; + return; + + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (Address & 0xffff)) = Byte; + SA1.Executing = !SA1.Waiting; + break; + + case CMemory::MAP_C4: + S9xSetC4 (Byte, Address & 0xffff); + return; + + case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG + printf("Writing Byte at %06X\n", Address); +#endif + s7r.bank50[(Address & 0xffff)]= (uint8) Byte; + break; + + case CMemory::MAP_OBC_RAM: + SetOBC1(Byte, Address &0xFFFF); + return; + + case CMemory::MAP_SETA_DSP: + S9xSetSetaDSP(Byte,Address); + return; + + case CMemory::MAP_SETA_RISC: + S9xSetST018(Byte,Address); + return; + + case CMemory::MAP_BSX: + S9xSetBSX(Byte,Address); + return; + + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("W(B) %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + return; + } +} + +#ifdef NO_INLINE_SET_GET +INLINE void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w, enum s9xwriteorder_t o) +#else +INLINE void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w=WRAP_NONE, enum s9xwriteorder_t o=WRITE_01) +#endif +{ + uint32 mask=MEMMAP_MASK&(w==WRAP_PAGE?0xff:(w==WRAP_BANK?0xffff:0xffffff)); + if ((Address & mask) == mask) + { + if(!o) S9xSetByte(Word&0x00FF, Address); + switch(w){ + case WRAP_PAGE: + { + PC_t a; + a.xPBPC = Address; + a.B.xPCl++; + S9xSetByte(Word>>8, a.xPBPC); + } + case WRAP_BANK: + { + PC_t a; + a.xPBPC = Address; + a.W.xPC++; + S9xSetByte(Word>>8, a.xPBPC); + } + case WRAP_NONE: + default: + S9xSetByte(Word>>8, Address+1); + } + if(o) S9xSetByte(Word&0x00FF, Address); + return; + } + +#if defined(CPU_SHUTDOWN) + CPU.WaitAddress = 0xffffffff; +#endif + int block; + uint8 *SetAddress = Memory.WriteMap [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; + + if (!CPU.InDMAorHDMA) + CPU.Cycles += Memory.MemorySpeed [block] << 1; + + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { +#ifdef CPU_SHUTDOWN + SetAddress += Address & 0xffff; + if (SetAddress == SA1.WaitByteAddress1 || + SetAddress == SA1.WaitByteAddress2) + { + SA1.Executing = SA1.S9xOpcodes != NULL; + SA1.WaitCounter = 0; + } + WRITE_WORD(SetAddress, Word); +#else + WRITE_WORD(SetAddress + (Address & 0xffff), Word); +#endif + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_PPU: + if(CPU.InDMAorHDMA){ + if((Address&0xff00)!=0x2100) S9xSetPPU((uint8)Word, Address&0xffff); + if(((Address+1)&0xff00)!=0x2100) S9xSetPPU(Word>>8, (Address+1)&0xffff); + return; + } + if(o){ + S9xSetPPU (Word >> 8, (Address & 0xffff) + 1); + S9xSetPPU ((uint8) Word, Address & 0xffff); + } else { + S9xSetPPU ((uint8) Word, Address & 0xffff); + S9xSetPPU (Word >> 8, (Address & 0xffff) + 1); + } + return; + + case CMemory::MAP_CPU: + if(o){ + S9xSetCPU (Word >> 8, (Address & 0xffff) + 1); + S9xSetCPU ((uint8) Word, (Address & 0xffff)); + } else { + S9xSetCPU ((uint8) Word, (Address & 0xffff)); + S9xSetCPU (Word >> 8, (Address & 0xffff) + 1); + } + return; + + case CMemory::MAP_DSP: +#ifdef DSP_DUMMY_LOOPS + printf("DSP Word: %04X to %06X\n", Word, Address); +#endif + if(o){ + S9xSetDSP (Word >> 8, (Address & 0xffff) + 1); + S9xSetDSP ((uint8) Word, (Address & 0xffff)); + } else { + S9xSetDSP ((uint8) Word, (Address & 0xffff)); + S9xSetDSP (Word >> 8, (Address & 0xffff) + 1); + } + return; + + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) { + if(Memory.SRAMMask>=MEMMAP_MASK){ + WRITE_WORD(Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))&Memory.SRAMMask), Word); + } else { + /* no WRITE_WORD here, since if Memory.SRAMMask=0x7ff + * then the high byte doesn't follow the low byte. */ + *(Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Memory.SRAMMask)) = (uint8) Word; + *(Memory.SRAM + (((((Address+1)&0xFF0000)>>1)|((Address+1)&0x7FFF))& Memory.SRAMMask)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) { + if(Multi.sramMaskB>=MEMMAP_MASK){ + WRITE_WORD(Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))&Multi.sramMaskB), Word); + } else { + *(Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Multi.sramMaskB)) = (uint8) Word; + *(Multi.sramB + (((((Address+1)&0xFF0000)>>1)|((Address+1)&0x7FFF))& Multi.sramMaskB)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_HIROM_SRAM: + if (Memory.SRAMMask) { + if(Memory.SRAMMask>=MEMMAP_MASK){ + WRITE_WORD(Memory.SRAM + + (((Address & 0x7fff) - 0x6000 + + ((Address & 0xf0000) >> 3) & Memory.SRAMMask)), Word); + } else { + /* no WRITE_WORD here, since if Memory.SRAMMask=0x7ff + * then the high byte doesn't follow the low byte. */ + *(Memory.SRAM + + (((Address & 0x7fff) - 0x6000 + + ((Address & 0xf0000) >> 3) & Memory.SRAMMask))) = (uint8) Word; + *(Memory.SRAM + + ((((Address + 1) & 0x7fff) - 0x6000 + + (((Address + 1) & 0xf0000) >> 3) & Memory.SRAMMask))) = (uint8) (Word >> 8); + } + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_BWRAM: + WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word); + CPU.SRAMModified = TRUE; + return; + + case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG + printf("Writing Word at %06X\n", Address); +#endif + WRITE_WORD(s7r.bank50+(Address & 0xffff), Word); + break; + + case CMemory::MAP_SA1RAM: + WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); + SA1.Executing = !SA1.Waiting; + break; + + case CMemory::MAP_C4: + if(o){ + S9xSetC4 ((uint8) (Word >> 8), (Address + 1) & 0xffff); + S9xSetC4 (Word & 0xff, Address & 0xffff); + } else { + S9xSetC4 (Word & 0xff, Address & 0xffff); + S9xSetC4 ((uint8) (Word >> 8), (Address + 1) & 0xffff); + } + return; + + case CMemory::MAP_OBC_RAM: + if(o){ + SetOBC1((uint8) (Word >> 8), (Address + 1) & 0xffff); + SetOBC1(Word & 0xff, Address &0xFFFF); + } else { + SetOBC1(Word & 0xff, Address &0xFFFF); + SetOBC1 ((uint8) (Word >> 8), (Address + 1) & 0xffff); + } + return; + + case CMemory::MAP_SETA_DSP: + if(o){ + S9xSetSetaDSP ((uint8) (Word >> 8),(Address + 1)); + S9xSetSetaDSP (Word & 0xff, Address); + } else { + S9xSetSetaDSP (Word & 0xff, Address); + S9xSetSetaDSP ((uint8) (Word >> 8),(Address + 1)); + } + return; + + case CMemory::MAP_SETA_RISC: + if(o){ + S9xSetST018 ((uint8) (Word >> 8),(Address + 1)); + S9xSetST018 (Word & 0xff, Address); + } else { + S9xSetST018 (Word & 0xff, Address); + S9xSetST018 ((uint8) (Word >> 8),(Address + 1)); + } + return; + + case CMemory::MAP_BSX: + if(o){ + S9xSetBSX ((uint8) (Word >> 8),(Address + 1)); + S9xSetBSX (Word & 0xff, Address); + } else { + S9xSetBSX (Word & 0xff, Address); + S9xSetBSX ((uint8) (Word >> 8),(Address + 1)); + } + return; + + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("W(W) %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + return; + } +} + +INLINE uint8 *GetBasePointer (uint32 Address) +{ + uint8 *GetAddress = Memory.Map [((Address&0xffffff) >> MEMMAP_SHIFT)]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress); + + switch ((pint) GetAddress) + { +// case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG +// printf("Getting Base pointer to DRAM\n"); +#endif +// { +// return s7r.bank50; +// } + + case CMemory::MAP_SPC7110_ROM: +#ifdef SPC7110_DEBUG + printf("Getting Base pointer to SPC7110ROM\n"); +#endif + return Get7110BasePtr(Address); + + case CMemory::MAP_SA1RAM: + return (Memory.SRAM); + + case CMemory::MAP_LOROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Memory.SRAMMask) - (Address&0xffff)); + + case CMemory::MAP_LOROM_SRAM_B: + if((Multi.sramMaskB&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Multi.sramMaskB) - (Address&0xffff)); + + case CMemory::MAP_BWRAM: + return (Memory.BWRAM - 0x6000 - (Address&0x8000)); + + case CMemory::MAP_HIROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address&0xffff)); + + case CMemory::MAP_C4: + return (S9xGetBasePointerC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetBasePointerOBC1(Address & 0xffff)); + + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("GBP %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + return (0); + } +} + +INLINE uint8 *S9xGetMemPointer (uint32 Address) +{ + uint8 *GetAddress = Memory.Map [((Address&0xffffff) >> MEMMAP_SHIFT)]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress + (Address&0xffff)); + + switch ((pint) GetAddress) + { +// case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG +// printf("Getting Mem pointer to DRAM\n"); +#endif +// { +// return s7r.bank50 + (Address&0xffff); +// } + + case CMemory::MAP_SPC7110_ROM: +#ifdef SPC7110_DEBUG + printf("Getting Mem pointer to SPC7110ROM\n"); +#endif + return Get7110BasePtr(Address) + (Address&0xffff); + + case CMemory::MAP_SA1RAM: + return (Memory.SRAM + (Address&0xffff)); + + case CMemory::MAP_LOROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Memory.SRAMMask)); + + case CMemory::MAP_LOROM_SRAM_B: + if((Multi.sramMaskB&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Multi.sramMaskB)); + + case CMemory::MAP_BWRAM: + return (Memory.BWRAM - 0x6000 + (Address&0x7fff)); + + case CMemory::MAP_HIROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + + case CMemory::MAP_C4: + return (S9xGetMemPointerC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetMemPointerOBC1(Address & 0xffff)); + + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("GMP %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + return (0); + } +} + +INLINE void S9xSetPCBase (uint32 Address) +{ + Registers.PBPC = Address & 0xffffff; + ICPU.ShiftedPB = Address & 0xff0000; + + int block; + uint8 *GetAddress = Memory.Map [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; + + CPU.MemSpeed = Memory.MemorySpeed [block]; + CPU.MemSpeedx2 = CPU.MemSpeed << 1; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST){ + CPU.PCBase = GetAddress; + return; + } + + switch ((pint) GetAddress) + { +// case CMemory::MAP_SPC7110_DRAM: +#ifdef SPC7110_DEBUG +// printf("Getting Base pointer to DRAM\n"); +#endif +// { +// CPU.PCBase = s7r.bank50; +// return; +// } + + case CMemory::MAP_SPC7110_ROM: +#ifdef SPC7110_DEBUG + printf("Getting Base pointer to SPC7110ROM\n"); +#endif + CPU.PCBase = Get7110BasePtr(Address); + return; + + case CMemory::MAP_SA1RAM: + CPU.PCBase = Memory.SRAM; + return; + + case CMemory::MAP_LOROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK){ + CPU.PCBase = NULL; + } else { + CPU.PCBase = (Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Memory.SRAMMask)) - (Address&0xffff); + } + return; + + case CMemory::MAP_LOROM_SRAM_B: + if((Multi.sramMaskB&MEMMAP_MASK)!=MEMMAP_MASK){ + CPU.PCBase = NULL; + } else { + CPU.PCBase = (Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Multi.sramMaskB)) - (Address&0xffff); + } + return; + + case CMemory::MAP_BWRAM: + CPU.PCBase = (Memory.BWRAM - 0x6000 - (Address&0x8000)); + return; + + case CMemory::MAP_HIROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK){ + CPU.PCBase = NULL; + } else { + CPU.PCBase = (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (Address&0xffff); + } + return; + + case CMemory::MAP_C4: + CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff); + return; + + case CMemory::MAP_OBC_RAM: + CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff); + return; + + case CMemory::MAP_BSX: + CPU.PCBase = S9xGetBasePointerBSX(Address); + return; + + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("SBP %06x\n", Address); +#endif + default: + case CMemory::MAP_NONE: + CPU.PCBase = NULL; + return; + } +} #endif - int block; - uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += (Memory.MemorySpeed[block] << 1); - - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) - { - #ifdef CPU_SHUTDOWN - SetAddress += (Address & 0xffff); - WRITE_WORD(SetAddress, Word); - - if (Settings.SA1) - { - if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) - { - SA1.Executing = SA1.S9xOpcodes != NULL; - SA1.WaitCounter = 0; - } - } - #else - WRITE_WORD(SetAddress + (Address & 0xffff), Word); - #endif - return; - } - - switch ((pint) SetAddress) - { - case CMemory::MAP_CPU: - if (o) - { - S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); - S9xSetCPU((uint8) Word, Address & 0xffff); - } - else - { - S9xSetCPU((uint8) Word, Address & 0xffff); - S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); - } - - return; - - case CMemory::MAP_PPU: - if (CPU.InDMAorHDMA) - { - if ((Address & 0xff00) != 0x2100) - S9xSetPPU((uint8) Word, Address & 0xffff); - if (((Address + 1) & 0xff00) != 0x2100) - S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); - return; - } - - if (o) - { - S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); - S9xSetPPU((uint8) Word, Address & 0xffff); - } - else - { - S9xSetPPU((uint8) Word, Address & 0xffff); - S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); - } - - return; - - case CMemory::MAP_LOROM_SRAM: - if (Memory.SRAMMask) - { - if (Memory.SRAMMask >= MEMMAP_MASK) - WRITE_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask), Word); - else - { - *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = (uint8) Word; - *(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask)) = Word >> 8; - } - - CPU.SRAMModified = TRUE; - } - - return; - - case CMemory::MAP_LOROM_SRAM_B: - if (Multi.sramMaskB) - { - if (Multi.sramMaskB >= MEMMAP_MASK) - WRITE_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB), Word); - else - { - *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = (uint8) Word; - *(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB)) = Word >> 8; - } - - CPU.SRAMModified = TRUE; - } - - return; - - case CMemory::MAP_HIROM_SRAM: - if (Memory.SRAMMask) - { - if (Memory.SRAMMask >= MEMMAP_MASK) - WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask), Word); - else - { - *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = (uint8) Word; - *(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) = Word >> 8; - } - - CPU.SRAMModified = TRUE; - } - - return; - - case CMemory::MAP_BWRAM: - WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word); - CPU.SRAMModified = TRUE; - return; - - case CMemory::MAP_SA1RAM: - WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); - SA1.Executing = !SA1.Waiting; - return; - - case CMemory::MAP_DSP: - if (o) - { - S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); - S9xSetDSP((uint8) Word, Address & 0xffff); - } - else - { - S9xSetDSP((uint8) Word, Address & 0xffff); - S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); - } - - return; - - case CMemory::MAP_C4: - if (o) - { - S9xSetC4(Word >> 8, (Address + 1) & 0xffff); - S9xSetC4((uint8) Word, Address & 0xffff); - } - else - { - S9xSetC4((uint8) Word, Address & 0xffff); - S9xSetC4(Word >> 8, (Address + 1) & 0xffff); - } - - return; - - case CMemory::MAP_OBC_RAM: - if (o) - { - S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); - S9xSetOBC1((uint8) Word, Address & 0xffff); - } - else - { - S9xSetOBC1((uint8) Word, Address & 0xffff); - S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); - } - - return; - - case CMemory::MAP_SETA_DSP: - if (o) - { - S9xSetSetaDSP(Word >> 8, Address + 1); - S9xSetSetaDSP((uint8) Word, Address); - } - else - { - S9xSetSetaDSP((uint8) Word, Address); - S9xSetSetaDSP(Word >> 8, Address + 1); - } - - return; - - case CMemory::MAP_SETA_RISC: - if (o) - { - S9xSetST018(Word >> 8, Address + 1); - S9xSetST018((uint8) Word, Address); - } - else - { - S9xSetST018((uint8) Word, Address); - S9xSetST018(Word >> 8, Address + 1); - } - - return; - - case CMemory::MAP_BSX: - if (o) - { - S9xSetBSX(Word >> 8, Address + 1); - S9xSetBSX((uint8) Word, Address); - } - else - { - S9xSetBSX((uint8) Word, Address); - S9xSetBSX(Word >> 8, Address + 1); - } - - return; - - case CMemory::MAP_NONE: - default: - return; - } -} - -inline void S9xSetPCBase (uint32 Address) -{ - Registers.PBPC = Address & 0xffffff; - ICPU.ShiftedPB = Address & 0xff0000; - - int block; - uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - CPU.MemSpeed = Memory.MemorySpeed[block]; - CPU.MemSpeedx2 = CPU.MemSpeed << 1; - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - CPU.PCBase = GetAddress; - return; - } - - switch ((pint) GetAddress) - { - case CMemory::MAP_LOROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - CPU.PCBase = NULL; - else - CPU.PCBase = Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff); - return; - - case CMemory::MAP_LOROM_SRAM_B: - if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) - CPU.PCBase = NULL; - else - CPU.PCBase = Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff); - return; - - case CMemory::MAP_HIROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - CPU.PCBase = NULL; - else - CPU.PCBase = Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff); - return; - - case CMemory::MAP_BWRAM: - CPU.PCBase = Memory.BWRAM - 0x6000 - (Address & 0x8000); - return; - - case CMemory::MAP_SA1RAM: - CPU.PCBase = Memory.SRAM; - return; - - case CMemory::MAP_SPC7110_ROM: - CPU.PCBase = S9xGetBasePointerSPC7110(Address); - return; - - case CMemory::MAP_C4: - CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff); - return; - - case CMemory::MAP_OBC_RAM: - CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff); - return; - - case CMemory::MAP_BSX: - CPU.PCBase = S9xGetBasePointerBSX(Address); - return; - - case CMemory::MAP_NONE: - default: - CPU.PCBase = NULL; - return; - } -} - -inline uint8 * S9xGetBasePointer (uint32 Address) -{ - uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (GetAddress); - - switch ((pint) GetAddress) - { - case CMemory::MAP_LOROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - return (NULL); - return (Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff)); - - case CMemory::MAP_LOROM_SRAM_B: - if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) - return (NULL); - return (Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff)); - - case CMemory::MAP_HIROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - return (NULL); - return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff)); - - case CMemory::MAP_BWRAM: - return (Memory.BWRAM - 0x6000 - (Address & 0x8000)); - - case CMemory::MAP_SA1RAM: - return (Memory.SRAM); - - case CMemory::MAP_SPC7110_ROM: - return (S9xGetBasePointerSPC7110(Address)); - - case CMemory::MAP_C4: - return (S9xGetBasePointerC4(Address & 0xffff)); - - case CMemory::MAP_OBC_RAM: - return (S9xGetBasePointerOBC1(Address & 0xffff)); - - case CMemory::MAP_NONE: - default: - return (NULL); - } -} - -inline uint8 * S9xGetMemPointer (uint32 Address) -{ - uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (GetAddress + (Address & 0xffff)); - - switch ((pint) GetAddress) - { - case CMemory::MAP_LOROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - return (NULL); - return (Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); - - case CMemory::MAP_LOROM_SRAM_B: - if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) - return (NULL); - return (Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); - - case CMemory::MAP_HIROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - return (NULL); - return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); - - case CMemory::MAP_BWRAM: - return (Memory.BWRAM - 0x6000 + (Address & 0x7fff)); - - case CMemory::MAP_SA1RAM: - return (Memory.SRAM + (Address & 0xffff)); - - case CMemory::MAP_SPC7110_ROM: - return (S9xGetBasePointerSPC7110(Address) + (Address & 0xffff)); - - case CMemory::MAP_C4: - return (S9xGetMemPointerC4(Address & 0xffff)); - - case CMemory::MAP_OBC_RAM: - return (S9xGetMemPointerOBC1(Address & 0xffff)); - - case CMemory::MAP_NONE: - default: - return (NULL); - } -} - -#endif diff --git a/source/snes9x/gfx.cpp b/source/snes9x/gfx.cpp index c5bfae7..80a439d 100644 --- a/source/snes9x/gfx.cpp +++ b/source/snes9x/gfx.cpp @@ -159,2131 +159,1830 @@ **********************************************************************************/ + + +#include #include "snes9x.h" +#include "cpuexec.h" +#include "gfx.h" #include "ppu.h" #include "tile.h" -#include "controls.h" -#include "crosshairs.h" -#include "cheats.h" -#include "movie.h" -#include "screenshot.h" -#include "font.h" #include "display.h" +#include "controls.h" +#include "screenshot.h" -extern struct SCheatData Cheat; -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData[240]; +#include "cheats.h" -void S9xComputeClipWindows (void); +#ifndef NGC +#include "movie.h" +#endif -static int font_width = 8, font_height = 9; +#include "font.h" +static int font_width = 8; +static int font_height = 9; -static void SetupOBJ (void); -static void DrawOBJS (int); -static void DisplayFrameRate (void); -static void DisplayPressedKeys (void); -static void DisplayWatchedAddresses (void); -static void DisplayStringFromBottom (const char *, int, int, bool); -static void DrawBackground (int, uint8, uint8); -static void DrawBackgroundMosaic (int, uint8, uint8); -static void DrawBackgroundOffset (int, uint8, uint8, int); -static void DrawBackgroundOffsetMosaic (int, uint8, uint8, int); -static inline void DrawBackgroundMode7 (int, void (*DrawMath) (uint32, uint32, int), void (*DrawNomath) (uint32, uint32, int), int); -static inline void DrawBackdrop (void); -static inline void RenderScreen (bool8); -static uint16 get_crosshair_color (uint8); +// private text-displaying functions +static void S9xDisplayPressedKeys (); +static void S9xDisplayFrameRate (); +static void S9xDisplayString (const char *string, int linesFromBottom=5, int pixelsFromLeft=1, bool allowWrap=true); +#ifndef NGC +static void S9xDisplayWatchedAddresses (); +#endif +// shared params for the above functions and DisplayChar +uint16* display_screen = NULL; +int display_ppl, display_width, display_height; +int display_fontwidth = font_width, display_fontheight = font_height, display_hfontaccessscale = 1, display_vfontaccessscale = 1; +bool8 display_paramsinited = FALSE; +#define DisplayString (S9xCustomDisplayString ? S9xCustomDisplayString : S9xDisplayString) -#define TILE_PLUS(t, x) (((t) & 0xfc00) | ((t + x) & 0x3ff)) +void ComputeClipWindows (); +extern struct SLineData LineData[240]; +extern struct SLineMatrixData LineMatrixData [240]; -bool8 S9xGraphicsInit (void) -{ - S9xInitTileRenderer(); - ZeroMemory(BlackColourMap, 256 * sizeof(uint16)); +bool8 S9xGraphicsInit(){ + S9xInitTileRenderer(); + ZeroMemory(BlackColourMap, 256*sizeof(uint16)); #ifdef GFX_MULTI_FORMAT - if (GFX.BuildPixel == NULL) - S9xSetRenderPixelFormat(RGB565); + if(GFX.BuildPixel==NULL) S9xSetRenderPixelFormat(RGB565); #endif - GFX.DoInterlace = 0; - GFX.InterlaceFrame = 0; - GFX.RealPPL = GFX.Pitch >> 1; - IPPU.OBJChanged = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - Settings.BG_Forced = 0; - S9xFixColourBrightness(); + GFX.DoInterlace=0; + GFX.InterlaceFrame=0; + Settings.BG_Forced=0; + IPPU.OBJChanged=TRUE; + IPPU.DirectColourMapsNeedRebuild=TRUE; + GFX.RealPPL=GFX.Pitch>>1; + S9xFixColourBrightness(); - GFX.X2 = (uint16 *) malloc(sizeof(uint16) * 0x10000); - GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000); + GFX.X2=GFX.ZERO_OR_X2=GFX.ZERO=NULL; + if(!(GFX.X2=(uint16*)memalign(32, sizeof(uint16)*0x10000))) goto FAIL; +#if !defined(NEW_COLOUR_BLENDING) + if(!(GFX.ZERO_OR_X2=(uint16*)memalign(32, sizeof(uint16)*0x10000))) goto FAIL; +#endif + if(!(GFX.ZERO=(uint16*)memalign(32, sizeof(uint16)*0x10000))) goto FAIL; - GFX.ScreenSize = GFX.Pitch / 2 * SNES_HEIGHT_EXTENDED * (Settings.SupportHiRes ? 2 : 1); - GFX.SubScreen = (uint16 *) malloc(GFX.ScreenSize * sizeof(uint16)); - GFX.ZBuffer = (uint8 *) malloc(GFX.ScreenSize); - GFX.SubZBuffer = (uint8 *) malloc(GFX.ScreenSize); + GFX.ScreenSize=GFX.Pitch/2*SNES_HEIGHT_EXTENDED*(Settings.SupportHiRes?2:1); + if(!(GFX.SubScreen=(uint16*)memalign(32, GFX.ScreenSize*sizeof(uint16)))) goto FAIL; + if(!(GFX.ZBuffer=(uint8*)memalign(32, GFX.ScreenSize))) goto FAIL; + if(!(GFX.SubZBuffer=(uint8*)memalign(32, GFX.ScreenSize))) goto FAIL; - if (!GFX.X2 || !GFX.ZERO || !GFX.SubScreen || !GFX.ZBuffer || !GFX.SubZBuffer) - { - S9xGraphicsDeinit(); - return (FALSE); - } + uint32 r, g, b; + /* Lookup table for color addition */ + for(r=0; r<=MAX_RED; r++){ + uint32 r2=r<<1; if(r2>MAX_RED) r2=MAX_RED; + for(g=0; g<=MAX_GREEN; g++){ + uint32 g2=g<<1; if(g2>MAX_GREEN) g2=MAX_GREEN; + for(b=0; b<=MAX_BLUE; b++){ + uint32 b2=b<<1; if(b2>MAX_BLUE) b2=MAX_BLUE; + GFX.X2[BUILD_PIXEL2(r,g,b)]=BUILD_PIXEL2(r2,g2,b2); + GFX.X2[BUILD_PIXEL2(r,g,b) & ~ALPHA_BITS_MASK]=BUILD_PIXEL2(r2,g2,b2); + } + } + } - // Lookup table for color addition - ZeroMemory(GFX.X2, 0x10000 * sizeof(uint16)); - for (uint32 r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r << 1; - if (r2 > MAX_RED) - r2 = MAX_RED; - - for (uint32 g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g << 1; - if (g2 > MAX_GREEN) - g2 = MAX_GREEN; - - for (uint32 b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b << 1; - if (b2 > MAX_BLUE) - b2 = MAX_BLUE; - - GFX.X2[BUILD_PIXEL2(r, g, b)] = BUILD_PIXEL2(r2, g2, b2); - GFX.X2[BUILD_PIXEL2(r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2(r2, g2, b2); - } - } - } - - // Lookup table for 1/2 color subtraction - ZeroMemory(GFX.ZERO, 0x10000 * sizeof(uint16)); - for (uint32 r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if (r2 & 0x10) - r2 &= ~0x10; - else - r2 = 0; - - for (uint32 g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if (g2 & GREEN_HI_BIT) - g2 &= ~GREEN_HI_BIT; - else - g2 = 0; - - for (uint32 b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if (b2 & 0x10) - b2 &= ~0x10; - else - b2 = 0; - - GFX.ZERO[BUILD_PIXEL2(r, g, b)] = BUILD_PIXEL2(r2, g2, b2); - GFX.ZERO[BUILD_PIXEL2(r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2(r2, g2, b2); - } - } - } - - return (TRUE); -} - -void S9xGraphicsDeinit (void) -{ - if (GFX.X2) { free(GFX.X2); GFX.X2 = NULL; } - if (GFX.ZERO) { free(GFX.ZERO); GFX.ZERO = NULL; } - if (GFX.SubScreen) { free(GFX.SubScreen); GFX.SubScreen = NULL; } - if (GFX.ZBuffer) { free(GFX.ZBuffer); GFX.ZBuffer = NULL; } - if (GFX.SubZBuffer) { free(GFX.SubZBuffer); GFX.SubZBuffer = NULL; } -} - -void S9xBuildDirectColourMaps (void) -{ - IPPU.XB = mul_brightness[PPU.Brightness]; - - for (uint32 p = 0; p < 8; p++) - for (uint32 c = 0; c < 256; c++) - DirectColourMaps[p][c] = BUILD_PIXEL(IPPU.XB[((c & 7) << 2) | ((p & 1) << 1)], IPPU.XB[((c & 0x38) >> 1) | (p & 2)], IPPU.XB[((c & 0xc0) >> 3) | (p & 4)]); - - IPPU.DirectColourMapsNeedRebuild = FALSE; -} - -void S9xStartScreenRefresh (void) -{ - if (IPPU.RenderThisFrame) - { - if (GFX.DoInterlace && GFX.InterlaceFrame == 0) - GFX.InterlaceFrame = 1; - else - { - if (!S9xInitUpdate()) - { - IPPU.RenderThisFrame = FALSE; - return; - } - - GFX.InterlaceFrame = 0; - if (GFX.DoInterlace) - GFX.DoInterlace--; - - IPPU.MaxBrightness = PPU.Brightness; - - IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8; - if (PPU.BGMode == 5 || PPU.BGMode == 6) - { - IPPU.Interlace = Memory.FillRAM[0x2133] & 1; - IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2; - } - - if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ)) - { - GFX.RealPPL = GFX.Pitch >> 1; - IPPU.DoubleWidthPixels = TRUE; - IPPU.RenderedScreenWidth = SNES_WIDTH << 1; - if (IPPU.Interlace || IPPU.InterlaceOBJ) - { - GFX.PPL = GFX.RealPPL << 1; - IPPU.DoubleHeightPixels = TRUE; - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - GFX.DoInterlace++; - } - else - { - GFX.PPL = GFX.RealPPL; - IPPU.DoubleHeightPixels = FALSE; - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - } - } - else - { - IPPU.DoubleWidthPixels = FALSE; - IPPU.DoubleHeightPixels = FALSE; - IPPU.RenderedScreenWidth = SNES_WIDTH; - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - #ifdef USE_OPENGL - if (Settings.OpenGLEnable) - GFX.RealPPL = GFX.PPL = SNES_WIDTH; - else - #endif - GFX.RealPPL = GFX.PPL = GFX.Pitch >> 1; - } - - IPPU.RenderedFramesCount++; - } - - PPU.MosaicStart = 0; - PPU.RecomputeClipWindows = TRUE; - IPPU.PreviousLine = IPPU.CurrentLine = 0; - - ZeroMemory(GFX.ZBuffer, GFX.ScreenSize); - ZeroMemory(GFX.SubZBuffer, GFX.ScreenSize); - } - - if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) - { - IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; - IPPU.RenderedFramesCount = 0; - IPPU.FrameCount = 0; - } - - if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0) - GFX.InfoString = NULL; - - IPPU.TotalEmulatedFrames++; -} - -void S9xEndScreenRefresh (void) -{ - if (IPPU.RenderThisFrame) - { - FLUSH_REDRAW(); - - if (GFX.DoInterlace && GFX.InterlaceFrame == 0) - { - S9xControlEOF(); - S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); - } - else - { - if (IPPU.ColorsChanged) - { - uint32 saved = PPU.CGDATA[0]; - IPPU.ColorsChanged = FALSE; - S9xSetPalette(); - PPU.CGDATA[0] = saved; - } - - S9xControlEOF(); - - if (Settings.TakeScreenshot) - S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); - - if (Settings.AutoDisplayMessages) - S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1); - - S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); - } - } - else - S9xControlEOF(); - - S9xApplyCheats(); - -#ifdef DEBUGGER - if (CPU.Flags & FRAME_ADVANCE_FLAG) - { - if (ICPU.FrameAdvanceCount) - { - ICPU.FrameAdvanceCount--; - IPPU.RenderThisFrame = TRUE; - IPPU.FrameSkip = 0; - } - else - { - CPU.Flags &= ~FRAME_ADVANCE_FLAG; - CPU.Flags |= DEBUG_MODE_FLAG; - } - } +#if !defined(NEW_COLOUR_BLENDING) + /* Lookup table for color subtraction */ + ZeroMemory(GFX.ZERO_OR_X2, 0x10000*sizeof(uint16)); + for(r=0; r<=MAX_RED; r++){ + uint32 r2=r; if(r2&0x10) r2=(r2<<1)&MAX_RED; else r2=0; +#if !defined(OLD_COLOUR_BLENDING) + if(r2==0) r2=1; +#endif + for(g=0; g<=MAX_GREEN; g++){ + uint32 g2=g; if(g2&GREEN_HI_BIT) g2=(g2<<1)&MAX_GREEN; else g2=0; +#if !defined(OLD_COLOUR_BLENDING) + if(g2==0) g2=1; +#endif + for(b=0; b<=MAX_BLUE; b++){ + uint32 b2=b; if(b2&0x10) b2=(b2<<1)&MAX_BLUE; else b2=0; +#if !defined(OLD_COLOUR_BLENDING) + if(b2==0) b2=1; +#endif + GFX.ZERO_OR_X2[BUILD_PIXEL2(r,g,b)]=BUILD_PIXEL2(r2,g2,b2); + GFX.ZERO_OR_X2[BUILD_PIXEL2(r,g,b) & ~ALPHA_BITS_MASK]=BUILD_PIXEL2(r2,g2,b2); + } + } + } #endif - if (CPU.SRAMModified) - { - if (!CPU.AutoSaveTimer) - { - if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) - CPU.SRAMModified = FALSE; - } - else - { - if (!--CPU.AutoSaveTimer) - { - S9xAutoSaveSRAM(); - CPU.SRAMModified = FALSE; - } - } - } + /* Lookup table for 1/2 color subtraction */ + ZeroMemory(GFX.ZERO, 0x10000*sizeof(uint16)); + for(r=0; r<=MAX_RED; r++){ + uint32 r2=r; if(r2&0x10) r2&=~0x10; else r2=0; + for(g=0; g<=MAX_GREEN; g++){ + uint32 g2=g; if(g2&GREEN_HI_BIT) g2&=~GREEN_HI_BIT; else g2=0; + for(b=0; b<=MAX_BLUE; b++){ + uint32 b2=b; if(b2&0x10) b2&=~0x10; else b2=0; + GFX.ZERO[BUILD_PIXEL2(r,g,b)]=BUILD_PIXEL2(r2,g2,b2); + GFX.ZERO[BUILD_PIXEL2(r,g,b) & ~ALPHA_BITS_MASK]=BUILD_PIXEL2(r2,g2,b2); + } + } + } + + GFX.Repainting = FALSE; + + return TRUE; + +FAIL: + S9xGraphicsDeinit(); + return FALSE; } -void RenderLine (uint8 C) -{ - if (IPPU.RenderThisFrame) - { - LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; - LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; - LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; - LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; +void S9xGraphicsDeinit(void){ + if(GFX.X2) free(GFX.X2); GFX.X2=NULL; + if(GFX.ZERO_OR_X2) free(GFX.ZERO_OR_X2); GFX.ZERO_OR_X2=NULL; + if(GFX.ZERO) free(GFX.ZERO); GFX.ZERO=NULL; + if(GFX.SubScreen) free(GFX.SubScreen); GFX.SubScreen=NULL; + if(GFX.ZBuffer) free(GFX.ZBuffer); GFX.ZBuffer=NULL; + if(GFX.SubZBuffer) free(GFX.SubZBuffer); GFX.SubZBuffer=NULL; +} - if (PPU.BGMode == 7) - { - struct SLineMatrixData *p = &LineMatrixData[C]; - p->MatrixA = PPU.MatrixA; - p->MatrixB = PPU.MatrixB; - p->MatrixC = PPU.MatrixC; - p->MatrixD = PPU.MatrixD; - p->CentreX = PPU.CentreX; - p->CentreY = PPU.CentreY; - p->M7HOFS = PPU.M7HOFS; - p->M7VOFS = PPU.M7VOFS; - } - else - { +void S9xBuildDirectColourMaps(void){ + IPPU.XB=mul_brightness[PPU.Brightness]; + + for(uint32 p=0; p<8; p++){ + for(uint32 c=0; c<256; c++){ + DirectColourMaps[p][c]=BUILD_PIXEL(IPPU.XB[((c&7)<<2) | ((p&1)<<1)], + IPPU.XB[((c&0x38)>>1) | (p&2)], + IPPU.XB[((c&0xc0)>>3) | (p&4)]); + } + } + IPPU.DirectColourMapsNeedRebuild=FALSE; +} + +void S9xStartScreenRefresh(){ + if(GFX.InfoStringTimeout>0 && --GFX.InfoStringTimeout==0) + GFX.InfoString=NULL; + + if(IPPU.RenderThisFrame){ + if(GFX.DoInterlace && GFX.InterlaceFrame==0){ + GFX.InterlaceFrame=1; + } else { + if(!S9xInitUpdate()){ + IPPU.RenderThisFrame=FALSE; + return; + } + GFX.InterlaceFrame=0; + if(GFX.DoInterlace) GFX.DoInterlace--; + IPPU.RenderedFramesCount++; + IPPU.MaxBrightness=PPU.Brightness; + if(PPU.BGMode==5 || PPU.BGMode==6){ + IPPU.Interlace = (Memory.FillRAM[0x2133]&1); + IPPU.InterlaceOBJ = (Memory.FillRAM[0x2133]&2); + } + IPPU.PseudoHires = Memory.FillRAM[0x2133]&8; + if(Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ)){ + GFX.RealPPL = GFX.Pitch>>1; + IPPU.DoubleWidthPixels = TRUE; + IPPU.RenderedScreenWidth = 512; + if(IPPU.Interlace || IPPU.InterlaceOBJ){ + GFX.PPL = GFX.RealPPL<<1; + IPPU.DoubleHeightPixels = TRUE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight<<1; + GFX.DoInterlace++; + } else { + GFX.PPL = GFX.RealPPL; + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + } + } else { + IPPU.DoubleWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenWidth = 256; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; +#ifdef USE_GLIDE + if(Settings.GlideEnable) { + // Speed up hack for Glide: render low res. SNES images + // into a handy 256x256 sized buffer that can be uploaded + // into texture memory with one Glide call without having + // to copy it into a second, suitably sized buffer first. + GFX.RealPPL = GFX.PPL = 256; + } else +#endif +#ifdef USE_OPENGL + if(Settings.OpenGLEnable) { + // Ditto for OpenGL + GFX.RealPPL = GFX.PPL = 256; + } else +#endif + { + GFX.RealPPL = GFX.PPL = GFX.Pitch>>1; + } + } + } + PPU.MosaicStart=0; + IPPU.PreviousLine=IPPU.CurrentLine=0; + PPU.RecomputeClipWindows=TRUE; + ZeroMemory(GFX.ZBuffer, GFX.ScreenSize); + ZeroMemory(GFX.SubZBuffer, GFX.ScreenSize); + } + if(++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) { + IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; + IPPU.RenderedFramesCount = 0; + IPPU.FrameCount = 0; + } +} + +void RenderLine(uint8 C) { + if(IPPU.RenderThisFrame) { + LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; + LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; + LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; + LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; + + if(PPU.BGMode==7) { + struct SLineMatrixData *p = &LineMatrixData [C]; + p->MatrixA = PPU.MatrixA; + p->MatrixB = PPU.MatrixB; + p->MatrixC = PPU.MatrixC; + p->MatrixD = PPU.MatrixD; + p->CentreX = PPU.CentreX; + p->CentreY = PPU.CentreY; + p->M7HOFS = PPU.M7HOFS; + p->M7VOFS = PPU.M7VOFS; + } else { LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; - } - - IPPU.CurrentLine = C + 1; - } - else - { - // if we're not rendering this frame, we still need to update this - // XXX: Check ForceBlank? Or anything else? - if (IPPU.OBJChanged) - SetupOBJ(); - PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags; - } + } + IPPU.CurrentLine = C + 1; + } else { + /* if we're not rendering this frame, we still need to update this */ + // XXX: Check ForceBlank? Or anything else? + if(IPPU.OBJChanged) S9xSetupOBJ(); + PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags; + } } -static inline void RenderScreen (bool8 sub) +bool watchesCleared=false; +#ifndef NGC +void S9xDisplayWatchedAddresses () { - uint8 BGActive; - int D; - - if (!sub) + if(!watchesCleared) { - GFX.S = GFX.Screen; - if (GFX.DoInterlace && GFX.InterlaceFrame) - GFX.S += GFX.RealPPL; - GFX.DB = GFX.ZBuffer; - GFX.Clip = IPPU.Clip[0]; - BGActive = Memory.FillRAM[0x212c] & ~Settings.BG_Forced; - D = 32; - } - else - { - GFX.S = GFX.SubScreen; - GFX.DB = GFX.SubZBuffer; - GFX.Clip = IPPU.Clip[1]; - BGActive = Memory.FillRAM[0x212d] & ~Settings.BG_Forced; - D = (Memory.FillRAM[0x2130] & 2) << 4; // 'do math' depth flag + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + watches[i].on = false; + watchesCleared = true; } - if (BGActive & 0x10) + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) { - BG.TileAddress = PPU.OBJNameBase; - BG.NameSelect = PPU.OBJNameSelect; - BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 0x10); - BG.StartPalette = 128; - S9xSelectTileConverter(4, FALSE, sub, FALSE); - S9xSelectTileRenderers(PPU.BGMode, sub, TRUE); - DrawOBJS(D + 4); - } - - BG.NameSelect = 0; - S9xSelectTileRenderers(PPU.BGMode, sub, FALSE); - - #define DO_BG(n, pal, depth, hires, offset, Zh, Zl, voffoff) \ - if (BGActive & (1 << n)) \ - { \ - BG.StartPalette = pal; \ - BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & (1 << n)); \ - BG.TileSizeH = (!hires && PPU.BG[n].BGSize) ? 16 : 8; \ - BG.TileSizeV = (PPU.BG[n].BGSize) ? 16 : 8; \ - S9xSelectTileConverter(depth, hires, sub, PPU.BGMosaic[n]); \ - \ - if (offset) \ - { \ - BG.OffsetSizeH = (!hires && PPU.BG[2].BGSize) ? 16 : 8; \ - BG.OffsetSizeV = (PPU.BG[2].BGSize) ? 16 : 8; \ - \ - if (PPU.BGMosaic[n] && (hires || PPU.Mosaic > 1)) \ - DrawBackgroundOffsetMosaic(n, D + Zh, D + Zl, voffoff); \ - else \ - DrawBackgroundOffset(n, D + Zh, D + Zl, voffoff); \ - } \ - else \ - { \ - if (PPU.BGMosaic[n] && (hires || PPU.Mosaic > 1)) \ - DrawBackgroundMosaic(n, D + Zh, D + Zl); \ - else \ - DrawBackground(n, D + Zh, D + Zl); \ - } \ - } - - switch (PPU.BGMode) - { - case 0: - DO_BG(0, 0, 2, FALSE, FALSE, 15, 11, 0); - DO_BG(1, 32, 2, FALSE, FALSE, 14, 10, 0); - DO_BG(2, 64, 2, FALSE, FALSE, 7, 3, 0); - DO_BG(3, 96, 2, FALSE, FALSE, 6, 2, 0); + if(!watches[i].on) break; - case 1: - DO_BG(0, 0, 4, FALSE, FALSE, 15, 11, 0); - DO_BG(1, 0, 4, FALSE, FALSE, 14, 10, 0); - DO_BG(2, 0, 2, FALSE, FALSE, (PPU.BG3Priority ? 17 : 7), 3, 0); - break; + int32 displayNumber = 0; - case 2: - DO_BG(0, 0, 4, FALSE, TRUE, 15, 7, 8); - DO_BG(1, 0, 4, FALSE, TRUE, 11, 3, 8); - break; + extern struct SCheatData Cheat; + for(int r=0;r= PPU.ScreenHeight) - GFX.EndY = PPU.ScreenHeight - 1; - - if (!PPU.ForcedBlanking) - { - // If force blank, may as well completely skip all this. We only did - // the OBJ because (AFAWK) the RTO flags are updated even during force-blank. - - if (PPU.RecomputeClipWindows) - { - S9xComputeClipWindows(); - PPU.RecomputeClipWindows = FALSE; - } - - if (Settings.SupportHiRes) - { - if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ)) - { - #ifdef USE_OPENGL - if (Settings.OpenGLEnable && GFX.RealPPL == 256) - { - // Have to back out of the speed up hack where the low res. - // SNES image was rendered into a 256x239 sized buffer, - // ignoring the true, larger size of the buffer. - GFX.RealPPL = GFX.Pitch >> 1; - - for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) - { - register uint16 *p = GFX.Screen + y * GFX.PPL + 255; - register uint16 *q = GFX.Screen + y * GFX.RealPPL + 510; - - for (register int x = 255; x >= 0; x--, p--, q -= 2) - *q = *(q + 1) = *p; - } - - GFX.PPL = GFX.RealPPL; // = GFX.Pitch >> 1 above - } - else - #endif - { - // Have to back out of the regular speed hack - for (register uint32 y = 0; y < GFX.StartY; y++) - { - register uint16 *p = GFX.Screen + y * GFX.PPL + 255; - register uint16 *q = GFX.Screen + y * GFX.PPL + 510; - - for (register int x = 255; x >= 0; x--, p--, q -= 2) - *q = *(q + 1) = *p; - } - } - - IPPU.DoubleWidthPixels = TRUE; - IPPU.RenderedScreenWidth = 512; - } - - if (!IPPU.DoubleHeightPixels && (IPPU.Interlace || IPPU.InterlaceOBJ)) - { - IPPU.DoubleHeightPixels = TRUE; - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - GFX.PPL = GFX.RealPPL << 1; - GFX.DoInterlace = 2; - - for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) - memmove(GFX.Screen + y * GFX.PPL, GFX.Screen + y * GFX.RealPPL, IPPU.RenderedScreenWidth * sizeof(uint16)); - } - } - - if ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2131] & 0x3f)) - GFX.FixedColour = BUILD_PIXEL(IPPU.XB[PPU.FixedColourRed], IPPU.XB[PPU.FixedColourGreen], IPPU.XB[PPU.FixedColourBlue]); - - if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || - ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2130] & 2) && (Memory.FillRAM[0x2131] & 0x3f) && (Memory.FillRAM[0x212d] & 0x1f))) - // If hires (Mode 5/6 or pseudo-hires) or math is to be done - // involving the subscreen, then we need to render the subscreen... - RenderScreen(TRUE); - - RenderScreen(FALSE); - } - else - { - const uint16 black = BUILD_PIXEL(0, 0, 0); - - GFX.S = GFX.Screen + GFX.StartY * GFX.PPL; - if (GFX.DoInterlace && GFX.InterlaceFrame) - GFX.S += GFX.RealPPL; - - for (uint32 l = GFX.StartY; l <= GFX.EndY; l++, GFX.S += GFX.PPL) - for (int x = 0; x < IPPU.RenderedScreenWidth; x++) - GFX.S[x] = black; - } - - IPPU.PreviousLine = IPPU.CurrentLine; -} - -static void SetupOBJ (void) -{ - int SmallWidth, SmallHeight, LargeWidth, LargeHeight; - - switch (PPU.OBJSizeSelect) - { - case 0: - SmallWidth = SmallHeight = 8; - LargeWidth = LargeHeight = 16; - break; - - case 1: - SmallWidth = SmallHeight = 8; - LargeWidth = LargeHeight = 32; - break; - - case 2: - SmallWidth = SmallHeight = 8; - LargeWidth = LargeHeight = 64; - break; - - case 3: - SmallWidth = SmallHeight = 16; - LargeWidth = LargeHeight = 32; - break; - - case 4: - SmallWidth = SmallHeight = 16; - LargeWidth = LargeHeight = 64; - break; - - case 5: - default: - SmallWidth = SmallHeight = 32; - LargeWidth = LargeHeight = 64; - break; - - case 6: - SmallWidth = 16; SmallHeight = 32; - LargeWidth = 32; LargeHeight = 64; - break; - - case 7: - SmallWidth = 16; SmallHeight = 32; - LargeWidth = LargeHeight = 32; - break; - } - - int inc = IPPU.InterlaceOBJ ? 2 : 1; - - // OK, we have three cases here. Either there's no priority, priority is - // normal FirstSprite, or priority is FirstSprite+Y. The first two are - // easy, the last is somewhat more ... interesting. So we split them up. - - int Height; - uint8 S; - - if (!PPU.OAMPriorityRotation || !(PPU.OAMFlip & PPU.OAMAddr & 1)) // normal case - { - uint8 LineOBJ[SNES_HEIGHT_EXTENDED]; - ZeroMemory(LineOBJ, sizeof(LineOBJ)); - - for (int i = 0; i < SNES_HEIGHT_EXTENDED; i++) - { - GFX.OBJLines[i].RTOFlags = 0; - GFX.OBJLines[i].Tiles = 34; - for (int j = 0; j < 32; j++) - GFX.OBJLines[i].OBJ[j].Sprite = -1; - } - - uint8 FirstSprite = PPU.FirstSprite; - S = FirstSprite; - - do - { - if (PPU.OBJ[S].Size) - { - GFX.OBJWidths[S] = LargeWidth; - Height = LargeHeight; - } - else - { - GFX.OBJWidths[S] = SmallWidth; - Height = SmallHeight; - } - - int HPos = PPU.OBJ[S].HPos; - if (HPos == -256) - HPos = 0; - - if (HPos > -GFX.OBJWidths[S] && HPos <= 256) - { - if (HPos < 0) - GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3; - else - if (HPos + GFX.OBJWidths[S] > 255) - GFX.OBJVisibleTiles[S] = (256 - HPos + 7) >> 3; - else - GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; - - for (uint8 line = 0, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc) - { - if (Y >= SNES_HEIGHT_EXTENDED) - continue; - - if (LineOBJ[Y] >= 32) - { - GFX.OBJLines[Y].RTOFlags |= 0x40; - continue; - } - - GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; - if (GFX.OBJLines[Y].Tiles < 0) - GFX.OBJLines[Y].RTOFlags |= 0x80; - - GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = S; - if (PPU.OBJ[S].VFlip) - // Yes, Width not Height. It so happens that the - // sprites with H=2*W flip as two WxW sprites. - GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line ^ (GFX.OBJWidths[S] - 1); - else - GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line; - - LineOBJ[Y]++; - } - } - - S = (S + 1) & 0x7f; - } while (S != FirstSprite); - - for (int Y = 1; Y < SNES_HEIGHT_EXTENDED; Y++) - GFX.OBJLines[Y].RTOFlags |= GFX.OBJLines[Y - 1].RTOFlags; - } - else // evil FirstSprite+Y case - { - // First, find out which sprites are on which lines - uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128]; - ZeroMemory(OBJOnLine, sizeof(OBJOnLine)); - - for (S = 0; S < 128; S++) - { - if (PPU.OBJ[S].Size) - { - GFX.OBJWidths[S] = LargeWidth; - Height = LargeHeight; - } - else - { - GFX.OBJWidths[S] = SmallWidth; - Height = SmallHeight; - } - - int HPos = PPU.OBJ[S].HPos; - if (HPos == -256) - HPos = 256; - - if (HPos > -GFX.OBJWidths[S] && HPos <= 256) - { - if (HPos < 0) - GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3; - else - if (HPos + GFX.OBJWidths[S] >= 257) - GFX.OBJVisibleTiles[S] = (257 - HPos + 7) >> 3; - else - GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; - - for (uint8 line = 0, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc) - { - if (Y >= SNES_HEIGHT_EXTENDED) - continue; - - if (PPU.OBJ[S].VFlip) - // Yes, Width not Height. It so happens that the - // sprites with H=2*W flip as two WxW sprites. - OBJOnLine[Y][S] = (line ^ (GFX.OBJWidths[S] - 1)) | 0x80; - else - OBJOnLine[Y][S] = line | 0x80; - } - } - } - - // Now go through and pull out those OBJ that are actually visible. - int j; - for (int Y = 0; Y < SNES_HEIGHT_EXTENDED; Y++) - { - GFX.OBJLines[Y].RTOFlags = Y ? GFX.OBJLines[Y - 1].RTOFlags : 0; - GFX.OBJLines[Y].Tiles = 34; - - uint8 FirstSprite = (PPU.FirstSprite + Y) & 0x7f; - S = FirstSprite; - j = 0; - - do - { - if (OBJOnLine[Y][S]) - { - if (j >= 32) - { - GFX.OBJLines[Y].RTOFlags |= 0x40; - break; - } - - GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; - if (GFX.OBJLines[Y].Tiles < 0) - GFX.OBJLines[Y].RTOFlags |= 0x80; - GFX.OBJLines[Y].OBJ[j].Sprite = S; - GFX.OBJLines[Y].OBJ[j++].Line = OBJOnLine[Y][S] & ~0x80; - } - - S = (S + 1) & 0x7f; - } while (S != FirstSprite); - - if (j < 32) - GFX.OBJLines[Y].OBJ[j].Sprite = -1; - } - } - - IPPU.OBJChanged = FALSE; -} - -static void DrawOBJS (int D) -{ - CHECK_SOUND(); - - void (*DrawTile) (uint32, uint32, uint32, uint32) = NULL; - void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32) = NULL; - - int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; - BG.InterlaceLine = GFX.InterlaceFrame ? 8 : 0; - GFX.Z1 = 2; - - for (uint32 Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL) - { - int I = 0; - int tiles = GFX.OBJLines[Y].Tiles; - - for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I < 32; S = GFX.OBJLines[Y].OBJ[++I].Sprite) - { - tiles += GFX.OBJVisibleTiles[S]; - if (tiles <= 0) - continue; - - int BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line << 1) + (PPU.OBJ[S].Name & 0xf0)) & 0xf0) | (PPU.OBJ[S].Name & 0x100) | (PPU.OBJ[S].Palette << 10); - int TileX = PPU.OBJ[S].Name & 0x0f; - int TileLine = (GFX.OBJLines[Y].OBJ[I].Line & 7) * 8; - if (IPPU.InterlaceOBJ) - TileLine >>= 1; - int TileInc = 1; - - if (PPU.OBJ[S].HFlip) - { - TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; - BaseTile |= H_FLIP; - TileInc = -1; - } - - GFX.Z2 = D + PPU.OBJ[S].Priority * 4; - - int DrawMode = 3; - int clip = 0, next_clip = -1000; - int X = PPU.OBJ[S].HPos; - if (X == -256) - X = 256; - - for (int t = tiles, O = Offset + X * PixWidth; X <= 256 && X < PPU.OBJ[S].HPos + GFX.OBJWidths[S]; TileX = (TileX + TileInc) & 0x0f, X += 8, O += 8 * PixWidth) - { - if (X < -7 || --t < 0 || X == 256) - continue; - - for (int x = X; x < X + 8;) - { - if (x >= next_clip) - { - for (; clip < GFX.Clip[4].Count && GFX.Clip[4].Left[clip] <= x; clip++) ; - if (clip == 0 || x >= GFX.Clip[4].Right[clip - 1]) - { - DrawMode = 0; - next_clip = ((clip < GFX.Clip[4].Count) ? GFX.Clip[4].Left[clip] : 1000); - } - else - { - DrawMode = GFX.Clip[4].DrawMode[clip - 1]; - next_clip = GFX.Clip[4].Right[clip - 1]; - GFX.ClipColors = !(DrawMode & 1); - - if (BG.EnableMath && (PPU.OBJ[S].Palette & 4) && (DrawMode & 2)) - { - DrawTile = GFX.DrawTileMath; - DrawClippedTile = GFX.DrawClippedTileMath; - } - else - { - DrawTile = GFX.DrawTileNomath; - DrawClippedTile = GFX.DrawClippedTileNomath; - } - } - } - - if (x == X && x + 8 < next_clip) - { - if (DrawMode) - DrawTile(BaseTile | TileX, O, TileLine, 1); - x += 8; - } - else - { - int w = (next_clip <= X + 8) ? next_clip - x : X + 8 - x; - if (DrawMode) - DrawClippedTile(BaseTile | TileX, O, x - X, w, TileLine, 1); - x += w; - } - } - } - } - } -} - -static void DrawBackground (int bg, uint8 Zh, uint8 Zl) -{ - CHECK_SOUND(); - - BG.TileAddress = PPU.BG[bg].NameBase << 1; - - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; - if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC1 -= 0x8000; - SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; - if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC2 -= 0x8000; - SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; - if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC3 -= 0x8000; - - uint32 Lines; - int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; - int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; - int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; - - void (*DrawTile) (uint32, uint32, uint32, uint32); - void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32); - - for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) - { - GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); - - if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) - { - DrawTile = GFX.DrawTileMath; - DrawClippedTile = GFX.DrawClippedTileMath; - } + if(watches[i].format==1) + sprintf(buf, "%s,%du = %u", watches[i].desc, watches[i].size, (unsigned int)displayNumber); + else if(watches[i].format==3) + sprintf(buf, "%s,%dx = %X", watches[i].desc, watches[i].size, (unsigned int)displayNumber); else { - DrawTile = GFX.DrawTileNomath; - DrawClippedTile = GFX.DrawClippedTileNomath; + // signed + if(watches[i].size == 1) + displayNumber = (int32)((int8)displayNumber); + else if(watches[i].size == 2) + displayNumber = (int32)((int16)displayNumber); + else if(watches[i].size == 3) + if(displayNumber >= 8388608) + displayNumber -= 16777216; + + sprintf(buf, "%s,%ds = %d", watches[i].desc, watches[i].size, (int)displayNumber); } - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) - { - uint32 Y2 = IPPU.Interlace ? Y * 2 + GFX.InterlaceFrame : Y; - uint32 VOffset = LineData[Y].BG[bg].VOffset + (IPPU.Interlace ? 1 : 0); - uint32 HOffset = LineData[Y].BG[bg].HOffset; - int VirtAlign = ((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0); - for (Lines = 1; Lines < GFX.LinesPerTile - VirtAlign; Lines++) - { - if ((VOffset != LineData[Y + Lines].BG[bg].VOffset) || (HOffset != LineData[Y + Lines].BG[bg].HOffset)) - break; - } - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY - Y + 1; - - VirtAlign <<= 3; - - uint32 t1, t2; - uint32 TilemapRow = (VOffset + Y2) >> OffsetShift; - BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; - - if ((VOffset + Y2) & 8) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - - uint16 *b1, *b2; - - if (TilemapRow & 0x20) - { - b1 = SC2; - b2 = SC3; - } - else - { - b1 = SC0; - b2 = SC1; - } - - b1 += (TilemapRow & 0x1f) << 5; - b2 += (TilemapRow & 0x1f) << 5; - - uint32 Left = GFX.Clip[bg].Left[clip]; - uint32 Right = GFX.Clip[bg].Right[clip]; - uint32 Offset = Left * PixWidth + Y * GFX.PPL; - uint32 HPos = (HOffset + Left) & OffsetMask; - uint32 HTile = HPos >> 3; - uint16 *t; - - if (BG.TileSizeH == 8) - { - if (HTile > 31) - t = b2 + (HTile & 0x1f); - else - t = b1 + HTile; - } - else - { - if (HTile > 63) - t = b2 + ((HTile >> 1) & 0x1f); - else - t = b1 + (HTile >> 1); - } - - uint32 Width = Right - Left; - - if (HPos & 7) - { - uint32 l = HPos & 7; - uint32 w = 8 - l; - if (w > Width) - w = Width; - - Offset -= l * PixWidth; - Tile = READ_WORD(t); - GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; - - if (BG.TileSizeV == 16) - Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); - - if (BG.TileSizeH == 8) - { - DrawClippedTile(Tile, Offset, l, w, VirtAlign, Lines); - t++; - if (HTile == 31) - t = b2; - else - if (HTile == 63) - t = b1; - } - else - { - if (!(Tile & H_FLIP)) - DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, l, w, VirtAlign, Lines); - else - DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, l, w, VirtAlign, Lines); - t += HTile & 1; - if (HTile == 63) - t = b2; - else - if (HTile == 127) - t = b1; - } - - HTile++; - Offset += 8 * PixWidth; - Width -= w; - } - - while (Width >= 8) - { - Tile = READ_WORD(t); - GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; - - if (BG.TileSizeV == 16) - Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); - - if (BG.TileSizeH == 8) - { - DrawTile(Tile, Offset, VirtAlign, Lines); - t++; - if (HTile == 31) - t = b2; - else - if (HTile == 63) - t = b1; - } - else - { - if (!(Tile & H_FLIP)) - DrawTile(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, Lines); - else - DrawTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, Lines); - t += HTile & 1; - if (HTile == 63) - t = b2; - else - if (HTile == 127) - t = b1; - } - - HTile++; - Offset += 8 * PixWidth; - Width -= 8; - } - - if (Width) - { - Tile = READ_WORD(t); - GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; - - if (BG.TileSizeV == 16) - Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); - - if (BG.TileSizeH == 8) - DrawClippedTile(Tile, Offset, 0, Width, VirtAlign, Lines); - else - { - if (!(Tile & H_FLIP)) - DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, 0, Width, VirtAlign, Lines); - else - DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, 0, Width, VirtAlign, Lines); - } - } - } + DisplayString(buf, 6+i, 1, false); } } +#endif -static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl) +void S9xReRefresh () { - CHECK_SOUND(); + if(Settings.StopEmulation) + return; - BG.TileAddress = PPU.BG[bg].NameBase << 1; - - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; - if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC1 -= 0x8000; - SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; - if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC2 -= 0x8000; - SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; - if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC3 -= 0x8000; - - int Lines; - int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; - int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; - int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; - - void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32); - - int MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % PPU.Mosaic; - - for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) - { - GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); - - if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) - DrawPix = GFX.DrawMosaicPixelMath; - else - DrawPix = GFX.DrawMosaicPixelNomath; - - for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic) - { - uint32 Y2 = IPPU.Interlace ? Y * 2 : Y; - uint32 VOffset = LineData[Y].BG[bg].VOffset + (IPPU.Interlace ? 1 : 0); - uint32 HOffset = LineData[Y].BG[bg].HOffset; - - Lines = PPU.Mosaic - MosaicStart; - if (Y + MosaicStart + Lines > GFX.EndY) - Lines = GFX.EndY - Y - MosaicStart + 1; - - int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3; - - uint32 t1, t2; - uint32 TilemapRow = (VOffset + Y2) >> OffsetShift; - BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; - - if ((VOffset + Y2) & 8) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - - uint16 *b1, *b2; - - if (TilemapRow & 0x20) - { - b1 = SC2; - b2 = SC3; - } - else - { - b1 = SC0; - b2 = SC1; - } - - b1 += (TilemapRow & 0x1f) << 5; - b2 += (TilemapRow & 0x1f) << 5; - - uint32 Left = GFX.Clip[bg].Left[clip]; - uint32 Right = GFX.Clip[bg].Right[clip]; - uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL; - uint32 HPos = (HOffset + Left - (Left % PPU.Mosaic)) & OffsetMask; - uint32 HTile = HPos >> 3; - uint16 *t; - - if (BG.TileSizeH == 8) - { - if (HTile > 31) - t = b2 + (HTile & 0x1f); - else - t = b1 + HTile; - } - else - { - if (HTile > 63) - t = b2 + ((HTile >> 1) & 0x1f); - else - t = b1 + (HTile >> 1); - } - - uint32 Width = Right - Left; - - HPos &= 7; - - while (Left < Right) - { - uint32 w = PPU.Mosaic - (Left % PPU.Mosaic); - if (w > Width) - w = Width; - - Tile = READ_WORD(t); - GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; - - if (BG.TileSizeV == 16) - Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); - - if (BG.TileSizeH == 8) - DrawPix(Tile, Offset, VirtAlign, HPos & 7, w, Lines); - else - { - if (!(Tile & H_FLIP)) - DrawPix(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); - else - DrawPix(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); - } - - HPos += PPU.Mosaic; - - while (HPos >= 8) - { - HPos -= 8; - - if (BG.TileSizeH == 8) - { - t++; - if (HTile == 31) - t = b2; - else - if (HTile == 63) - t = b1; - } - else - { - t += HTile & 1; - if (HTile == 63) - t = b2; - else - if (HTile == 127) - t = b1; - } - - HTile++; - } - - Offset += w * PixWidth; - Width -= w; - Left += w; - } - - MosaicStart = 0; - } - } + GFX.Repainting = TRUE; + S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight/*, Settings.SixteenBit*/); + GFX.Repainting = FALSE; } -static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff) -{ - CHECK_SOUND(); - BG.TileAddress = PPU.BG[bg].NameBase << 1; +void S9xEndScreenRefresh() { + if(IPPU.RenderThisFrame) { + FLUSH_REDRAW(); + if(GFX.DoInterlace && GFX.InterlaceFrame==0){ + S9xControlEOF(); + S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } else { + if(IPPU.ColorsChanged) { + uint32 saved = PPU.CGDATA[0]; + IPPU.ColorsChanged = FALSE; + S9xSetPalette (); + PPU.CGDATA[0] = saved; + } - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; - uint16 *BPS0, *BPS1, *BPS2, *BPS3; +#ifndef NGC + if(Settings.TakeScreenshot) + S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); +#endif + S9xControlEOF(); - BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; - BPS1 = (PPU.BG[2].SCSize & 1) ? BPS0 + 1024 : BPS0; - if (BPS1 >= (uint16 *) (Memory.VRAM + 0x10000)) - BPS1 -= 0x8000; - BPS2 = (PPU.BG[2].SCSize & 2) ? BPS1 + 1024 : BPS0; - if (BPS2 >= (uint16 *) (Memory.VRAM + 0x10000)) - BPS2 -= 0x8000; - BPS3 = (PPU.BG[2].SCSize & 1) ? BPS2 + 1024 : BPS2; - if (BPS3 >= (uint16 *) (Memory.VRAM + 0x10000)) - BPS3 -= 0x8000; + if(Settings.AutoDisplayMessages || Settings.OpenGLEnable || Settings.GlideEnable) + S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1); - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; - if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC1 -= 0x8000; - SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; - if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC2 -= 0x8000; - SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; - if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC3 -= 0x8000; + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } + } else { + S9xControlEOF(); + } - int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; - int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; - int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff; - int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3; - int OffsetEnableMask = 0x2000 << bg; - int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + S9xApplyCheats(); - void (*DrawTile) (uint32, uint32, uint32, uint32); - void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32); - - for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) - { - GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); - - if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) - { - DrawTile = GFX.DrawTileMath; - DrawClippedTile = GFX.DrawClippedTileMath; - } - else - { - DrawTile = GFX.DrawTileNomath; - DrawClippedTile = GFX.DrawClippedTileNomath; - } - - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) - { - uint32 Y2 = IPPU.Interlace ? Y * 2 + GFX.InterlaceFrame : Y; - uint32 VOff = LineData[Y].BG[2].VOffset - 1; - uint32 HOff = LineData[Y].BG[2].HOffset; - uint32 HOffsetRow = VOff >> Offset2Shift; - uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; - uint16 *s, *s1, *s2; - - if (HOffsetRow & 0x20) - { - s1 = BPS2; - s2 = BPS3; - } - else - { - s1 = BPS0; - s2 = BPS1; - } - - s1 += (HOffsetRow & 0x1f) << 5; - s2 += (HOffsetRow & 0x1f) << 5; - s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); - int32 VOffsetOffset = s - s1; - - uint32 Left = GFX.Clip[bg].Left[clip]; - uint32 Right = GFX.Clip[bg].Right[clip]; - uint32 Offset = Left * PixWidth + Y * GFX.PPL; - uint32 LineHOffset = LineData[Y].BG[bg].HOffset; - bool8 left_edge = (Left < (8 - (LineHOffset & 7))); - uint32 Width = Right - Left; - - while (Left < Right) - { - uint32 VOffset, HOffset; - - if (left_edge) - { - // SNES cannot do OPT for leftmost tile column - VOffset = LineData[Y].BG[bg].VOffset; - HOffset = LineHOffset; - left_edge = FALSE; - } - else - { - int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3; - - if (BG.OffsetSizeH == 8) - { - if (HOffTile > 31) - s = s2 + (HOffTile & 0x1f); - else - s = s1 + HOffTile; - } - else - { - if (HOffTile > 63) - s = s2 + ((HOffTile >> 1) & 0x1f); - else - s = s1 + (HOffTile >> 1); - } - - uint16 HCellOffset = READ_WORD(s); - uint16 VCellOffset; - - if (VOffOff) - VCellOffset = READ_WORD(s + VOffsetOffset); - else - { - if (HCellOffset & 0x8000) - { - VCellOffset = HCellOffset; - HCellOffset = 0; - } - else - VCellOffset = 0; - } - - if (VCellOffset & OffsetEnableMask) - VOffset = VCellOffset + 1; - else - VOffset = LineData[Y].BG[bg].VOffset; - - if (HCellOffset & OffsetEnableMask) - HOffset = (HCellOffset & ~7) | (LineHOffset & 7); - else - HOffset = LineHOffset; - } - - if (IPPU.Interlace) - VOffset++; - - uint32 t1, t2; - int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3; - int TilemapRow = (VOffset + Y2) >> OffsetShift; - BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; - - if ((VOffset + Y2) & 8) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - - uint16 *b1, *b2; - - if (TilemapRow & 0x20) - { - b1 = SC2; - b2 = SC3; - } - else - { - b1 = SC0; - b2 = SC1; - } - - b1 += (TilemapRow & 0x1f) << 5; - b2 += (TilemapRow & 0x1f) << 5; - - uint32 HPos = (HOffset + Left) & OffsetMask; - uint32 HTile = HPos >> 3; - uint16 *t; - - if (BG.TileSizeH == 8) - { - if (HTile > 31) - t = b2 + (HTile & 0x1f); - else - t = b1 + HTile; - } - else - { - if (HTile > 63) - t = b2 + ((HTile >> 1) & 0x1f); - else - t = b1 + (HTile >> 1); - } - - uint32 l = HPos & 7; - uint32 w = 8 - l; - if (w > Width) - w = Width; - - Offset -= l * PixWidth; - Tile = READ_WORD(t); - GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; - - if (BG.TileSizeV == 16) - Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); - - if (BG.TileSizeH == 8) - { - DrawClippedTile(Tile, Offset, l, w, VirtAlign, 1); - } - else - { - if (!(Tile & H_FLIP)) - DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, l, w, VirtAlign, 1); - else - DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, l, w, VirtAlign, 1); - } - - Left += w; - Offset += 8 * PixWidth; - Width -= w; - } - } - } +#ifdef DEBUGGER + if(CPU.Flags & FRAME_ADVANCE_FLAG) { + if(ICPU.FrameAdvanceCount) { + ICPU.FrameAdvanceCount--; + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + } else { + CPU.Flags &= ~FRAME_ADVANCE_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + } +#endif + if(CPU.SRAMModified) { + if(!CPU.AutoSaveTimer) { + if(!(CPU.AutoSaveTimer=Settings.AutoSaveDelay*Memory.ROMFramesPerSecond)) + CPU.SRAMModified=FALSE; + } else { + if(!--CPU.AutoSaveTimer) { + S9xAutoSaveSRAM(); + CPU.SRAMModified=FALSE; + } + } + } + ++IPPU.TotalEmulatedFrames; } -static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff) -{ - CHECK_SOUND(); - BG.TileAddress = PPU.BG[bg].NameBase << 1; +void S9xSetupOBJ() { + int SmallWidth, SmallHeight; + int LargeWidth, LargeHeight; - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; - uint16 *BPS0, *BPS1, *BPS2, *BPS3; + switch(PPU.OBJSizeSelect) { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + default: + case 5: + SmallWidth = SmallHeight = 32; + LargeWidth = LargeHeight = 64; + break; + case 6: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = 32; LargeHeight = 64; + break; + case 7: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } + int inc=IPPU.InterlaceOBJ?2:1; - BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; - BPS1 = (PPU.BG[2].SCSize & 1) ? BPS0 + 1024 : BPS0; - if (BPS1 >= (uint16 *) (Memory.VRAM + 0x10000)) - BPS1 -= 0x8000; - BPS2 = (PPU.BG[2].SCSize & 2) ? BPS1 + 1024 : BPS0; - if (BPS2 >= (uint16 *) (Memory.VRAM + 0x10000)) - BPS2 -= 0x8000; - BPS3 = (PPU.BG[2].SCSize & 1) ? BPS2 + 1024 : BPS2; - if (BPS3 >= (uint16 *) (Memory.VRAM + 0x10000)) - BPS3 -= 0x8000; + /* OK, we have three cases here. Either there's no priority, priority is + * normal FirstSprite, or priority is FirstSprite+Y. The first two are + * easy, the last is somewhat more ... interesting. So we split them up. */ - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; - if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC1 -= 0x8000; - SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; - if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC2 -= 0x8000; - SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; - if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) - SC3 -= 0x8000; + int Height; + uint8 S; - int Lines; - int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; - int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; - int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff; - int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3; - int OffsetEnableMask = 0x2000 << bg; - int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + if(!PPU.OAMPriorityRotation || !(PPU.OAMFlip&PPU.OAMAddr&1)){ + /* normal case */ + uint8 LineOBJ[SNES_HEIGHT_EXTENDED]; + memset(LineOBJ, 0, sizeof(LineOBJ)); + for(int i=0; i-GFX.OBJWidths[S] && HPos<=256) + { + if(HPos<0){ + GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3; + } else if(HPos+GFX.OBJWidths[S]>255){ + GFX.OBJVisibleTiles[S]=(256-HPos+7)>>3; + } else { + GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3; + } + for(uint8 line=0, Y=(uint8)(PPU.OBJ[S].VPos&0xff); line=SNES_HEIGHT_EXTENDED) continue; + if(LineOBJ[Y]>=32){ + GFX.OBJLines[Y].RTOFlags|=0x40; + continue; + } + GFX.OBJLines[Y].Tiles-=GFX.OBJVisibleTiles[S]; + if(GFX.OBJLines[Y].Tiles<0) GFX.OBJLines[Y].RTOFlags|=0x80; + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite=S; + if(PPU.OBJ[S].VFlip){ + // Yes, Width not Height. It so happens that the + // sprites with H=2*W flip as two WxW sprites. + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line=line^(GFX.OBJWidths[S]-1); + } else { + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line=line; + } + LineOBJ[Y]++; + } + } + S=(S+1)&0x7F; + } while(S!=FirstSprite); - void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32); + for(int Y=1; Y-GFX.OBJWidths[S] && HPos<=256) + { + if(HPos<0){ + GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3; + } else if(HPos+GFX.OBJWidths[S]>=257){ + GFX.OBJVisibleTiles[S]=(257-HPos+7)>>3; + } else { + GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3; + } + for(uint8 line=0, Y=(uint8)(PPU.OBJ[S].VPos&0xff); line=SNES_HEIGHT_EXTENDED) continue; + if(PPU.OBJ[S].VFlip){ + // Yes, Width not Height. It so happens that the + // sprites with H=2*W flip as two WxW sprites. + OBJOnLine[Y][S]=(line^(GFX.OBJWidths[S]-1)) | 0x80; + } else { + OBJOnLine[Y][S]=line | 0x80; + } + } + } + } - if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) - DrawPix = GFX.DrawMosaicPixelMath; - else - DrawPix = GFX.DrawMosaicPixelNomath; + /* Now go through and pull out those OBJ that are actually visible. */ + int j; + for(int Y=0; Y=32){ + GFX.OBJLines[Y].RTOFlags|=0x40; + break; + } + GFX.OBJLines[Y].Tiles-=GFX.OBJVisibleTiles[S]; + if(GFX.OBJLines[Y].Tiles<0) GFX.OBJLines[Y].RTOFlags|=0x80; + GFX.OBJLines[Y].OBJ[j].Sprite=S; + GFX.OBJLines[Y].OBJ[j++].Line=OBJOnLine[Y][S]&~0x80; + } + S=(S+1)&0x7F; + } while(S!=FirstSprite); + if(j<32) GFX.OBJLines[Y].OBJ[j].Sprite=-1; + } + } - Lines = PPU.Mosaic - MosaicStart; - if (Y + MosaicStart + Lines > GFX.EndY) - Lines = GFX.EndY - Y - MosaicStart + 1; - - uint32 HOffsetRow = VOff >> Offset2Shift; - uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; - uint16 *s, *s1, *s2; - - if (HOffsetRow & 0x20) - { - s1 = BPS2; - s2 = BPS3; - } - else - { - s1 = BPS0; - s2 = BPS1; - } - - s1 += (HOffsetRow & 0x1f) << 5; - s2 += (HOffsetRow & 0x1f) << 5; - s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); - int32 VOffsetOffset = s - s1; - - uint32 Left = GFX.Clip[bg].Left[clip]; - uint32 Right = GFX.Clip[bg].Right[clip]; - uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL; - uint32 LineHOffset = LineData[Y].BG[bg].HOffset; - bool8 left_edge = (Left < (8 - (LineHOffset & 7))); - uint32 Width = Right - Left; - - while (Left < Right) - { - uint32 VOffset, HOffset; - - if (left_edge) - { - // SNES cannot do OPT for leftmost tile column - VOffset = LineData[Y].BG[bg].VOffset; - HOffset = LineHOffset; - left_edge = FALSE; - } - else - { - int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3; - - if (BG.OffsetSizeH == 8) - { - if (HOffTile > 31) - s = s2 + (HOffTile & 0x1f); - else - s = s1 + HOffTile; - } - else - { - if (HOffTile > 63) - s = s2 + ((HOffTile >> 1) & 0x1f); - else - s = s1 + (HOffTile >> 1); - } - - uint16 HCellOffset = READ_WORD(s); - uint16 VCellOffset; - - if (VOffOff) - VCellOffset = READ_WORD(s + VOffsetOffset); - else - { - if (HCellOffset & 0x8000) - { - VCellOffset = HCellOffset; - HCellOffset = 0; - } - else - VCellOffset = 0; - } - - if (VCellOffset & OffsetEnableMask) - VOffset = VCellOffset + 1; - else - VOffset = LineData[Y].BG[bg].VOffset; - - if (HCellOffset & OffsetEnableMask) - HOffset = (HCellOffset & ~7) | (LineHOffset & 7); - else - HOffset = LineHOffset; - } - - if (IPPU.Interlace) - VOffset++; - - uint32 t1, t2; - int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3; - int TilemapRow = (VOffset + Y2) >> OffsetShift; - BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; - - if ((VOffset + Y2) & 8) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - - uint16 *b1, *b2; - - if (TilemapRow & 0x20) - { - b1 = SC2; - b2 = SC3; - } - else - { - b1 = SC0; - b2 = SC1; - } - - b1 += (TilemapRow & 0x1f) << 5; - b2 += (TilemapRow & 0x1f) << 5; - - uint32 HPos = (HOffset + Left - (Left % PPU.Mosaic)) & OffsetMask; - uint32 HTile = HPos >> 3; - uint16 *t; - - if (BG.TileSizeH == 8) - { - if (HTile > 31) - t = b2 + (HTile & 0x1f); - else - t = b1 + HTile; - } - else - { - if (HTile > 63) - t = b2 + ((HTile >> 1) & 0x1f); - else - t = b1 + (HTile >> 1); - } - - uint32 w = PPU.Mosaic - (Left % PPU.Mosaic); - if (w > Width) - w = Width; - - Tile = READ_WORD(t); - GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; - - if (BG.TileSizeV == 16) - Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); - - if (BG.TileSizeH == 8) - DrawPix(Tile, Offset, VirtAlign, HPos & 7, w, Lines); - else - { - if (!(Tile & H_FLIP)) - DrawPix(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); - else - if (!(Tile & V_FLIP)) - DrawPix(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); - } - - Left += w; - Offset += w * PixWidth; - Width -= w; - } - - MosaicStart = 0; - } - } + IPPU.OBJChanged = FALSE; } -static inline void DrawBackgroundMode7 (int bg, void (*DrawMath) (uint32, uint32, int), void (*DrawNomath) (uint32, uint32, int), int D) -{ - CHECK_SOUND(); +void DrawOBJS(int D){ + CHECK_SOUND(); - for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) - { - GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + void (*DrawTile)(uint32,uint32,uint32,uint32)=NULL; + void (*DrawClippedTile)(uint32,uint32,uint32,uint32,uint32,uint32)=NULL; - if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) - DrawMath(GFX.Clip[bg].Left[clip], GFX.Clip[bg].Right[clip], D); - else - DrawNomath(GFX.Clip[bg].Left[clip], GFX.Clip[bg].Right[clip], D); - } + int PixWidth = IPPU.DoubleWidthPixels?2:1; + GFX.Z1=2; + BG.InterlaceLine = GFX.InterlaceFrame?8:0; + + for(uint32 Y=GFX.StartY, Offset=Y*GFX.PPL; Y<=GFX.EndY; Y++, Offset+=GFX.PPL){ + int I = 0; + int tiles=GFX.OBJLines[Y].Tiles; + for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I<32; S = GFX.OBJLines[Y].OBJ[++I].Sprite) + { + tiles+=GFX.OBJVisibleTiles[S]; + if(tiles<=0){ + continue; + } + + int BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line<<1) + (PPU.OBJ[S].Name&0xf0))&0xf0) | (PPU.OBJ[S].Name&0x100) | (PPU.OBJ[S].Palette << 10); + int TileX = PPU.OBJ[S].Name&0x0f; + int TileLine = (GFX.OBJLines[Y].OBJ[I].Line&7)*8; + if(IPPU.InterlaceOBJ) TileLine>>=1; + int TileInc = 1; + + if (PPU.OBJ[S].HFlip) + { + TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; + BaseTile |= H_FLIP; + TileInc = -1; + } + + GFX.Z2 = D+PPU.OBJ[S].Priority*4; + + int DrawMode=3; + int clip=0, next_clip=-1000; + int X=PPU.OBJ[S].HPos; if(X==-256) X=256; + for(int t=tiles, O=Offset+X*PixWidth; X<=256 && X=next_clip){ + for(; clip=GFX.Clip[4].Right[clip-1]){ + DrawMode=0; + next_clip=((clip=(uint16*)(Memory.VRAM+0x10000)) SC1-=0x8000; + SC2=(PPU.BG[bg].SCSize&2)?SC1+1024:SC0; + if(SC2>=(uint16*)(Memory.VRAM+0x10000)) SC2-=0x8000; + SC3=(PPU.BG[bg].SCSize&1)?SC2+1024:SC2; + if(SC3>=(uint16*)(Memory.VRAM+0x10000)) SC3-=0x8000; + + uint32 Lines; + int OffsetMask = (BG.TileSizeH==16)?0x3ff:0x1ff; + int OffsetShift = (BG.TileSizeV==16)?4:3; + int PixWidth = IPPU.DoubleWidthPixels?2:1; + + void (*DrawTile)(uint32,uint32,uint32,uint32); + void (*DrawClippedTile)(uint32,uint32,uint32,uint32,uint32,uint32); + for(int clip=0; clip>(IPPU.Interlace?1:0); + + for(Lines=1; LinesGFX.EndY) Lines=GFX.EndY-Y+1; + VirtAlign<<=3; + + uint32 TilemapRow = (VOffset+Y2)>>OffsetShift; + BG.InterlaceLine = ((VOffset+Y2)&1)<<3; + uint32 t1, t2; + if(((VOffset+Y2)&8)){ + t1=16; t2=0; + } else { + t1=0; t2=16; + } + uint16 *b1; + uint16 *b2; + if(TilemapRow&0x20) { + b1=SC2; b2=SC3; + } else { + b1=SC0; b2=SC1; + } + b1+=(TilemapRow&0x1f)<<5; + b2+=(TilemapRow&0x1f)<<5; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left*PixWidth+Y*GFX.PPL; + uint32 HPos = (HOffset+Left)&OffsetMask; + uint32 HTile = HPos>>3; + uint16 *t; + if(BG.TileSizeH==8){ + if(HTile>31) + t=b2+(HTile&0x1f); + else + t=b1+HTile; + } else { + if(HTile>63) + t=b2+((HTile>>1)&0x1f); + else + t=b1+(HTile>>1); + } + + uint32 Width = Right-Left; + if(HPos&7) { + uint32 l=HPos&7; + uint32 w=8-l; + if(w>Width) w=Width; + Offset-=l*PixWidth; + Tile=READ_WORD(t); + GFX.Z1=GFX.Z2=(Tile&0x2000)?Zh:Zl; + if(BG.TileSizeV==16) + Tile=TILE_PLUS(Tile, ((Tile&V_FLIP)?t2:t1)); + if(BG.TileSizeH==8){ + DrawClippedTile(Tile, Offset, l, w, VirtAlign, Lines); + t++; + if(HTile==31) t=b2; + else if(HTile==63) t=b1; + } else { + if(!(Tile&H_FLIP)){ + DrawClippedTile(TILE_PLUS(Tile, (HTile&1)), Offset, l, w, VirtAlign, Lines); + } else { + DrawClippedTile(TILE_PLUS(Tile, 1-(HTile&1)), Offset, l, w, VirtAlign, Lines); + } + t+=HTile&1; + if(HTile==63) t=b2; + else if(HTile==127) t=b1; + } + HTile++; + Offset+=8*PixWidth; + Width-=w; + } + while(Width>=8){ + Tile=READ_WORD(t); + GFX.Z1=GFX.Z2=(Tile&0x2000)?Zh:Zl; + if(BG.TileSizeV==16) + Tile=TILE_PLUS(Tile, ((Tile&V_FLIP)?t2:t1)); + if(BG.TileSizeH==8){ + DrawTile(Tile, Offset, VirtAlign, Lines); + t++; + if(HTile==31) t=b2; + else if(HTile==63) t=b1; + } else { + if(!(Tile&H_FLIP)){ + DrawTile(TILE_PLUS(Tile, (HTile&1)), Offset, VirtAlign, Lines); + } else { + DrawTile(TILE_PLUS(Tile, 1-(HTile&1)), Offset, VirtAlign, Lines); + } + t+=HTile&1; + if(HTile==63) t=b2; + else if(HTile==127) t=b1; + } + HTile++; + Offset+=8*PixWidth; + Width-=8; + } + if(Width){ + Tile=READ_WORD(t); + GFX.Z1=GFX.Z2=(Tile&0x2000)?Zh:Zl; + if(BG.TileSizeV==16) + Tile=TILE_PLUS(Tile, ((Tile&V_FLIP)?t2:t1)); + if(BG.TileSizeH==8){ + DrawClippedTile(Tile, Offset, 0, Width, VirtAlign, Lines); + } else { + if(!(Tile&H_FLIP)){ + DrawClippedTile(TILE_PLUS(Tile, (HTile&1)), Offset, 0, Width, VirtAlign, Lines); + } else { + DrawClippedTile(TILE_PLUS(Tile, 1-(HTile&1)), Offset, 0, Width, VirtAlign, Lines); + } + } + } + } + } } -void S9xReRefresh (void) -{ - // Be careful when calling this function from the thread other than the emulation one... - // Here it's assumed no drawing occurs from the emulation thread when Settings.Paused is TRUE. - if (Settings.Paused) - S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); +static void DrawBackgroundMosaic(int bg, uint8 Zh, uint8 Zl){ + CHECK_SOUND(); + + BG.TileAddress = PPU.BG[bg].NameBase<<1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + + SC0=(uint16*)&Memory.VRAM[PPU.BG[bg].SCBase<<1]; + SC1=(PPU.BG[bg].SCSize&1)?SC0+1024:SC0; + if(SC1>=(uint16*)(Memory.VRAM+0x10000)) SC1-=0x8000; + SC2=(PPU.BG[bg].SCSize&2)?SC1+1024:SC0; + if(SC2>=(uint16*)(Memory.VRAM+0x10000)) SC2-=0x8000; + SC3=(PPU.BG[bg].SCSize&1)?SC2+1024:SC2; + if(SC3>=(uint16*)(Memory.VRAM+0x10000)) SC3-=0x8000; + + int Lines; + int OffsetMask = (BG.TileSizeH==16)?0x3ff:0x1ff; + int OffsetShift = (BG.TileSizeV==16)?4:3; + int PixWidth = IPPU.DoubleWidthPixels?2:1; + + void (*DrawPix)(uint32,uint32,uint32,uint32,uint32,uint32); + + int MosaicStart = ((uint32)GFX.StartY-PPU.MosaicStart)%PPU.Mosaic; + for(int clip=0; clipGFX.EndY) Lines=GFX.EndY-Y-MosaicStart+1; + int VirtAlign = (((Y2 + VOffset)&7)>>(IPPU.Interlace?1:0))<<3; + + uint32 TilemapRow = (VOffset+Y2)>>OffsetShift; + BG.InterlaceLine = ((VOffset+Y2)&1)<<3; + uint32 t1, t2; + if(((VOffset+Y2)&8)){ + t1=16; t2=0; + } else { + t1=0; t2=16; + } + uint16 *b1; + uint16 *b2; + if(TilemapRow&0x20) { + b1=SC2; b2=SC3; + } else { + b1=SC0; b2=SC1; + } + b1+=(TilemapRow&0x1f)<<5; + b2+=(TilemapRow&0x1f)<<5; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left*PixWidth+(Y+MosaicStart)*GFX.PPL; + uint32 HPos = (HOffset+Left-(Left%PPU.Mosaic))&OffsetMask; + uint32 HTile = HPos>>3; + uint16 *t; + if(BG.TileSizeH==8){ + if(HTile>31) + t=b2+(HTile&0x1f); + else + t=b1+HTile; + } else { + if(HTile>63) + t=b2+((HTile>>1)&0x1f); + else + t=b1+(HTile>>1); + } + + uint32 Width = Right-Left; + HPos&=7; + while(LeftWidth) w=Width; + Tile=READ_WORD(t); + GFX.Z1=GFX.Z2=(Tile&0x2000)?Zh:Zl; + if(BG.TileSizeV==16) + Tile=TILE_PLUS(Tile, ((Tile&V_FLIP)?t2:t1)); + if(BG.TileSizeH==8){ + DrawPix(Tile, Offset, VirtAlign, HPos&7, w, Lines); + } else { + if(!(Tile&H_FLIP)){ + DrawPix(TILE_PLUS(Tile, (HTile&1)), Offset, VirtAlign, HPos&7, w, Lines); + } else { + DrawPix(TILE_PLUS(Tile, 1-(HTile&1)), Offset, VirtAlign, HPos&7, w, Lines); + } + } + HPos+=PPU.Mosaic; + while(HPos>=8){ + HPos-=8; + if(BG.TileSizeH==8){ + t++; + if(HTile==31) t=b2; + else if(HTile==63) t=b1; + } else { + t+=HTile&1; + if(HTile==63) t=b2; + else if(HTile==127) t=b1; + } + HTile++; + } + Offset+=w*PixWidth; + Width-=w; + Left+=w; + } + MosaicStart=0; + } + } } +static void DrawBackgroundOffset(int bg, uint8 Zh, uint8 Zl, int VOffOff){ + CHECK_SOUND(); + + BG.TileAddress = PPU.BG[bg].NameBase<<1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + uint16 *BPS0, *BPS1, *BPS2, *BPS3; + + BPS0=(uint16*)&Memory.VRAM[PPU.BG[2].SCBase<<1]; + BPS1=(PPU.BG[2].SCSize&1)?BPS0+1024:BPS0; + if(BPS1>=(uint16*)(Memory.VRAM+0x10000)) BPS1-=0x8000; + BPS2=(PPU.BG[2].SCSize&2)?BPS1+1024:BPS0; + if(BPS2>=(uint16*)(Memory.VRAM+0x10000)) BPS2-=0x8000; + BPS3=(PPU.BG[2].SCSize&1)?BPS2+1024:BPS2; + if(BPS3>=(uint16*)(Memory.VRAM+0x10000)) BPS3-=0x8000; + + SC0=(uint16*)&Memory.VRAM[PPU.BG[bg].SCBase<<1]; + SC1=(PPU.BG[bg].SCSize&1)?SC0+1024:SC0; + if(SC1>=(uint16*)(Memory.VRAM+0x10000)) SC1-=0x8000; + SC2=(PPU.BG[bg].SCSize&2)?SC1+1024:SC0; + if(SC2>=(uint16*)(Memory.VRAM+0x10000)) SC2-=0x8000; + SC3=(PPU.BG[bg].SCSize&1)?SC2+1024:SC2; + if(SC3>=(uint16*)(Memory.VRAM+0x10000)) SC3-=0x8000; + + int OffsetMask = (BG.TileSizeH==16)?0x3ff:0x1ff; + int OffsetShift = (BG.TileSizeV==16)?4:3; + int Offset2Mask = (BG.OffsetSizeH==16)?0x3ff:0x1ff; + int Offset2Shift = (BG.OffsetSizeV==16)?4:3; + int OffsetEnableMask = 0x2000<>Offset2Shift; + uint32 VOffsetRow = (VOff+VOffOff)>>Offset2Shift; + uint16 *s, *s1, *s2; + if(HOffsetRow&0x20){ + s1=BPS2; s2=BPS3; + } else { + s1=BPS0; s2=BPS1; + } + s1+=(HOffsetRow&0x1f)<<5; + s2+=(HOffsetRow&0x1f)<<5; + s=((VOffsetRow&0x20)?BPS2:BPS0)+((VOffsetRow&0x1f)<<5); + int32 VOffsetOffset = s-s1; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left*PixWidth+Y*GFX.PPL; + uint32 LineHOffset = LineData[Y].BG[bg].HOffset; + bool8 left_edge = (Left<(8-(LineHOffset&7))); + uint32 Width = Right-Left; + + while(Left>3; + if(BG.OffsetSizeH==8){ + if(HOffTile>31) + s=s2+(HOffTile&0x1f); + else + s=s1+HOffTile; + } else { + if(HOffTile>63) + s=s2+((HOffTile>>1)&0x1f); + else + s=s1+(HOffTile>>1); + } + uint16 HCellOffset = READ_WORD(s); + uint16 VCellOffset; + if(VOffOff){ + VCellOffset = READ_WORD(s+VOffsetOffset); + } else { + if(HCellOffset&0x8000){ + VCellOffset=HCellOffset; + HCellOffset=0; + } else { + VCellOffset=0; + } + } + if(VCellOffset&OffsetEnableMask){ + VOffset=VCellOffset+1; + } else { + VOffset=LineData[Y].BG[bg].VOffset; + } + if(HCellOffset&OffsetEnableMask){ + HOffset=(HCellOffset&~7)|(LineHOffset&7); + } else { + HOffset=LineHOffset; + } + } + if(IPPU.Interlace) VOffset++; + + int VirtAlign = (((Y2+VOffset)&7)>>(IPPU.Interlace?1:0))<<3; + int TilemapRow=(VOffset+Y2)>>OffsetShift; + BG.InterlaceLine = ((VOffset+Y2)&1)<<3; + uint32 t1, t2; + if(((VOffset+Y2)&8)){ + t1=16; t2=0; + } else { + t1=0; t2=16; + } + uint16 *b1, *b2; + if(TilemapRow&0x20) { + b1=SC2; b2=SC3; + } else { + b1=SC0; b2=SC1; + } + b1+=(TilemapRow&0x1f)<<5; + b2+=(TilemapRow&0x1f)<<5; + + uint32 HPos = (HOffset+Left)&OffsetMask; + uint32 HTile = HPos>>3; + uint16 *t; + if(BG.TileSizeH==8){ + if(HTile>31) + t=b2+(HTile&0x1f); + else + t=b1+HTile; + } else { + if(HTile>63) + t=b2+((HTile>>1)&0x1f); + else + t=b1+(HTile>>1); + } + + uint32 l=HPos&7; + uint32 w=8-l; + if(w>Width) w=Width; + Offset-=l*PixWidth; + Tile=READ_WORD(t); + GFX.Z1=GFX.Z2=(Tile&0x2000)?Zh:Zl; + if(BG.TileSizeV==16) + Tile=TILE_PLUS(Tile, ((Tile&V_FLIP)?t2:t1)); + if(BG.TileSizeH==8){ + DrawClippedTile(Tile, Offset, l, w, VirtAlign, 1); + } else { + if(!(Tile&H_FLIP)){ + DrawClippedTile(TILE_PLUS(Tile, (HTile&1)), Offset, l, w, VirtAlign, 1); + } else { + DrawClippedTile(TILE_PLUS(Tile, 1-(HTile&1)), Offset, l, w, VirtAlign, 1); + } + } + Left+=w; + Offset+=8*PixWidth; + Width-=w; + } + } + } +} + +static void DrawBackgroundOffsetMosaic(int bg, uint8 Zh, uint8 Zl, int VOffOff){ + CHECK_SOUND(); + + BG.TileAddress = PPU.BG[bg].NameBase<<1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + uint16 *BPS0, *BPS1, *BPS2, *BPS3; + + BPS0=(uint16*)&Memory.VRAM[PPU.BG[2].SCBase<<1]; + BPS1=(PPU.BG[2].SCSize&1)?BPS0+1024:BPS0; + if(BPS1>=(uint16*)(Memory.VRAM+0x10000)) BPS1-=0x8000; + BPS2=(PPU.BG[2].SCSize&2)?BPS1+1024:BPS0; + if(BPS2>=(uint16*)(Memory.VRAM+0x10000)) BPS2-=0x8000; + BPS3=(PPU.BG[2].SCSize&1)?BPS2+1024:BPS2; + if(BPS3>=(uint16*)(Memory.VRAM+0x10000)) BPS3-=0x8000; + + SC0=(uint16*)&Memory.VRAM[PPU.BG[bg].SCBase<<1]; + SC1=(PPU.BG[bg].SCSize&1)?SC0+1024:SC0; + if(SC1>=(uint16*)(Memory.VRAM+0x10000)) SC1-=0x8000; + SC2=(PPU.BG[bg].SCSize&2)?SC1+1024:SC0; + if(SC2>=(uint16*)(Memory.VRAM+0x10000)) SC2-=0x8000; + SC3=(PPU.BG[bg].SCSize&1)?SC2+1024:SC2; + if(SC3>=(uint16*)(Memory.VRAM+0x10000)) SC3-=0x8000; + + int Lines; + int OffsetMask = (BG.TileSizeH==16)?0x3ff:0x1ff; + int OffsetShift = (BG.TileSizeV==16)?4:3; + int Offset2Mask = (BG.OffsetSizeH==16)?0x3ff:0x1ff; + int Offset2Shift = (BG.OffsetSizeV==16)?4:3; + int OffsetEnableMask = 0x2000<GFX.EndY) Lines=GFX.EndY-Y-MosaicStart+1; + + uint32 VOff = LineData[Y].BG[2].VOffset - 1; + uint32 HOff = LineData[Y].BG[2].HOffset; + + uint32 HOffsetRow = VOff>>Offset2Shift; + uint32 VOffsetRow = (VOff+VOffOff)>>Offset2Shift; + uint16 *s, *s1, *s2; + if(HOffsetRow&0x20){ + s1=BPS2; s2=BPS3; + } else { + s1=BPS0; s2=BPS1; + } + s1+=(HOffsetRow&0x1f)<<5; + s2+=(HOffsetRow&0x1f)<<5; + s=((VOffsetRow&0x20)?BPS2:BPS0)+((VOffsetRow&0x1f)<<5); + int32 VOffsetOffset = s-s1; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left*PixWidth+(Y+MosaicStart)*GFX.PPL; + uint32 LineHOffset = LineData[Y].BG[bg].HOffset; + bool8 left_edge = (Left<(8-(LineHOffset&7))); + uint32 Width = Right-Left; + + while(Left>3; + if(BG.OffsetSizeH==8){ + if(HOffTile>31) + s=s2+(HOffTile&0x1f); + else + s=s1+HOffTile; + } else { + if(HOffTile>63) + s=s2+((HOffTile>>1)&0x1f); + else + s=s1+(HOffTile>>1); + } + uint16 HCellOffset = READ_WORD(s); + uint16 VCellOffset; + if(VOffOff){ + VCellOffset = READ_WORD(s+VOffsetOffset); + } else { + if(HCellOffset&0x8000){ + VCellOffset=HCellOffset; + HCellOffset=0; + } else { + VCellOffset=0; + } + } + if(VCellOffset&OffsetEnableMask){ + VOffset=VCellOffset+1; + } else { + VOffset=LineData[Y].BG[bg].VOffset; + } + if(HCellOffset&OffsetEnableMask){ + HOffset=(HCellOffset&~7)|(LineHOffset&7); + } else { + HOffset=LineHOffset; + } + } + if(IPPU.Interlace) VOffset++; + + int VirtAlign = (((Y2+VOffset)&7)>>(IPPU.Interlace?1:0))<<3; + int TilemapRow=(VOffset+Y2)>>OffsetShift; + BG.InterlaceLine = ((VOffset+Y2)&1)<<3; + uint32 t1, t2; + if(((VOffset+Y2)&8)){ + t1=16; t2=0; + } else { + t1=0; t2=16; + } + uint16 *b1, *b2; + if(TilemapRow&0x20) { + b1=SC2; b2=SC3; + } else { + b1=SC0; b2=SC1; + } + b1+=(TilemapRow&0x1f)<<5; + b2+=(TilemapRow&0x1f)<<5; + + uint32 HPos = (HOffset+Left-(Left%PPU.Mosaic))&OffsetMask; + uint32 HTile = HPos>>3; + uint16 *t; + if(BG.TileSizeH==8){ + if(HTile>31) + t=b2+(HTile&0x1f); + else + t=b1+HTile; + } else { + if(HTile>63) + t=b2+((HTile>>1)&0x1f); + else + t=b1+(HTile>>1); + } + + uint32 w=PPU.Mosaic-(Left%PPU.Mosaic); + if(w>Width) w=Width; + Tile=READ_WORD(t); + GFX.Z1=GFX.Z2=(Tile&0x2000)?Zh:Zl; + if(BG.TileSizeV==16) + Tile=TILE_PLUS(Tile, ((Tile&V_FLIP)?t2:t1)); + if(BG.TileSizeH==8){ + DrawPix(Tile, Offset, VirtAlign, HPos&7, w, Lines); + } else { + if(!(Tile&H_FLIP)){ + DrawPix(TILE_PLUS(Tile, (HTile&1)), Offset, VirtAlign, HPos&7, w, Lines); + } else if(!(Tile&V_FLIP)){ + DrawPix(TILE_PLUS(Tile, 1-(HTile&1)), Offset, VirtAlign, HPos&7, w, Lines); + } + } + Left+=w; + Offset+=w*PixWidth; + Width-=w; + } + MosaicStart=0; + } + } +} + +static inline void DrawBackgroundMode7(int bg, void (*DrawMath)(uint32,uint32,int), void (*DrawNomath)(uint32,uint32,int), int D){ + CHECK_SOUND(); + + for(int clip=0; clip1)) \ + DrawBackgroundOffsetMosaic(n, D+Zh, D+Zl, voffoff); \ + else \ + DrawBackgroundOffset(n, D+Zh, D+Zl, voffoff); \ + } else { \ + if(PPU.BGMosaic[n] && (hires || PPU.Mosaic>1)) \ + DrawBackgroundMosaic(n, D+Zh, D+Zl); \ + else \ + DrawBackground(n, D+Zh, D+Zl); \ + } \ + } + switch(PPU.BGMode){ + case 0: + DO_BG(0, 0, 2, FALSE, FALSE, 15, 11, 0); + DO_BG(1, 32, 2, FALSE, FALSE, 14, 10, 0); + DO_BG(2, 64, 2, FALSE, FALSE, 7, 3, 0); + DO_BG(3, 96, 2, FALSE, FALSE, 6, 2, 0); + break; + case 1: + DO_BG(0, 0, 4, FALSE, FALSE, 15, 11, 0); + DO_BG(1, 0, 4, FALSE, FALSE, 14, 10, 0); + DO_BG(2, 0, 2, FALSE, FALSE, (PPU.BG3Priority?17:7), 3, 0); + break; + case 2: + DO_BG(0, 0, 4, FALSE, TRUE, 15, 7, 8); + DO_BG(1, 0, 4, FALSE, TRUE, 11, 3, 8); + break; + case 3: + DO_BG(0, 0, 8, FALSE, FALSE, 15, 7, 0); + DO_BG(1, 0, 4, FALSE, FALSE, 11, 3, 0); + break; + case 4: + DO_BG(0, 0, 8, FALSE, TRUE, 15, 7, 0); + DO_BG(1, 0, 2, FALSE, TRUE, 11, 3, 0); + break; + case 5: + DO_BG(0, 0, 4, TRUE, FALSE, 15, 7, 0); + DO_BG(1, 0, 2, TRUE, FALSE, 11, 3, 0); + break; + case 6: + DO_BG(0, 0, 4, TRUE, TRUE, 15, 7, 8); + break; + case 7: + if(BGActive&0x01){ + BG.EnableMath = !sub && (Memory.FillRAM[0x2131]&1); + DrawBackgroundMode7(0, GFX.DrawMode7BG1Math, GFX.DrawMode7BG1Nomath,D); + } + if((Memory.FillRAM[0x2133]&0x40) && (BGActive&0x02)){ + BG.EnableMath = !sub && (Memory.FillRAM[0x2131]&2); + DrawBackgroundMode7(1, GFX.DrawMode7BG2Math, GFX.DrawMode7BG2Nomath,D); + } + break; + } +#undef DO_BG + + BG.EnableMath = !sub && (Memory.FillRAM[0x2131]&0x20); + DrawBackdrop(); +} + + +void S9xUpdateScreen() { + if(IPPU.OBJChanged) S9xSetupOBJ(); + // XXX: Check ForceBlank? Or anything else? + PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags; + + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) + GFX.EndY = PPU.ScreenHeight - 1; + + if(!PPU.ForcedBlanking){ + /* If force blank, may as well completely skip all this. We only did + * the OBJ because (AFAWK) the RTO flags are updated even during + * force-blank */ + + if(PPU.RecomputeClipWindows) { + ComputeClipWindows(); + PPU.RecomputeClipWindows=FALSE; + } + + if (Settings.SupportHiRes){ + if(!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ)){ +#if defined (USE_GLIDE) || defined (USE_OPENGL) + if ( +#ifdef USE_GLIDE + (Settings.GlideEnable && GFX.RealPPL == 256) || +#endif +#ifdef USE_OPENGL + (Settings.OpenGLEnable && GFX.RealPPL == 256) || +#endif + 0) + { + // Have to back out of the speed up hack where the low res. + // SNES image was rendered into a 256x239 sized buffer, + // ignoring the true, larger size of the buffer. + GFX.RealPPL = GFX.Pitch>>1; + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--){ + register uint16 *p = GFX.Screen + y * GFX.PPL + 255; + register uint16 *q = GFX.Screen + y * GFX.RealPPL + 510; + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + GFX.PPL = GFX.RealPPL; // = GFX.Pitch>>1 above + } else +#endif + { + // Have to back out of the regular speed hack + for (register uint32 y = 0; y < GFX.StartY; y++) + { + register uint16 *p = GFX.Screen + y * GFX.PPL + 255; + register uint16 *q = GFX.Screen + y * GFX.PPL + 510; + + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + } + IPPU.DoubleWidthPixels = TRUE; + IPPU.RenderedScreenWidth = 512; + } + if(!IPPU.DoubleHeightPixels && (IPPU.Interlace || IPPU.InterlaceOBJ)){ + IPPU.DoubleHeightPixels = TRUE; + GFX.PPL=GFX.RealPPL<<1; + IPPU.RenderedScreenHeight=PPU.ScreenHeight<<1; + GFX.DoInterlace=2; + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--){ + memmove (GFX.Screen + y * GFX.PPL, + GFX.Screen + y * GFX.RealPPL, + IPPU.RenderedScreenWidth*sizeof(uint16)); + } + } + } + + if((Memory.FillRAM[0x2130]&0x30)!=0x30 && (Memory.FillRAM[0x2131]&0x3f)) + GFX.FixedColour = BUILD_PIXEL(IPPU.XB[PPU.FixedColourRed], + IPPU.XB[PPU.FixedColourGreen], + IPPU.XB[PPU.FixedColourBlue]); + + if(PPU.BGMode==5 || PPU.BGMode==6 || IPPU.PseudoHires || + ((Memory.FillRAM[0x2130]&0x30)!=0x30 && (Memory.FillRAM[0x2130]&2) && + (Memory.FillRAM[0x2131]&0x3f) && (Memory.FillRAM[0x212d]&0x1f))){ + /* If hires (Mode 5/6 or pseudo-hires) or math is to be done + * involving the subscreen, then we need to render the subscreen... + */ + RenderScreen(TRUE); + } + RenderScreen(FALSE); + } else { + GFX.S = GFX.Screen+GFX.StartY*GFX.PPL; + if(GFX.DoInterlace && GFX.InterlaceFrame) GFX.S+=GFX.RealPPL; + uint16 black=BUILD_PIXEL(0,0,0); + for(uint32 l=GFX.StartY; l<=GFX.EndY; l++, GFX.S+=GFX.PPL){ + for(int x=0; x 0) + if(Settings.InitialInfoStringTimeout > 0) { GFX.InfoString = string; GFX.InfoStringTimeout = Settings.InitialInfoStringTimeout; - S9xReRefresh(); - } -} -void S9xDisplayChar (uint16 *s, uint8 c) -{ - const uint16 black = BUILD_PIXEL(0, 0, 0); - - int line = ((c - 32) >> 4) * font_height; - int offset = ((c - 32) & 15) * font_width; - - for (int h = 0; h < font_height; h++, line++, s += GFX.RealPPL - font_width) - { - for (int w = 0; w < font_width; w++, s++) + if (Settings.Paused && !unfreezing_from_stream) { - char p = font[line][offset + w]; - - if (p == '#') - *s = Settings.DisplayColor; - else - if (p == '.') - *s = black; + //refresh screen to show new message immediately + S9xReRefresh(); } } } -static void DisplayStringFromBottom (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) +static inline void FontPixToScreen(char p, uint16 *s) { - if (linesFromBottom <= 0) + if(p == '#') + { + *s = Settings.DisplayColor; + } + else if(p == '.') + { + static const uint16 black = BUILD_PIXEL(0,0,0); + *s = black; + } +} + +void DisplayChar(uint16 *s, uint8 c) { + int line = ((c - 32) >> 4) * display_fontheight; + int offset = ((c - 32) & 15) * display_fontwidth; + int h, w; + if(!display_paramsinited) display_ppl = Settings.OpenGLEnable ? IPPU.RenderedScreenWidth : GFX.RealPPL; + if(display_hfontaccessscale == 1 && display_vfontaccessscale == 1) { + for(h=0; h max_chars && !allowWrap && display_hfontaccessscale > 1) { - if (char_count >= max_chars || (uint8) string[i] < 32) + display_fontwidth /= display_hfontaccessscale; + display_hfontaccessscale--; + display_fontwidth *= display_hfontaccessscale; + + max_chars = display_width / (display_fontwidth-display_hfontaccessscale); + } + + // loop through and draw the characters + for(int i = 0 ; i < len ; i++, char_count++) + { + if(char_count >= max_chars || (unsigned char)string[i] < 32) { - if (!allowWrap) + if(!allowWrap) break; - dst += font_height * GFX.RealPPL - (font_width - 1) * max_chars; - if (dst >= GFX.Screen + IPPU.RenderedScreenHeight * GFX.RealPPL) + Screen -= /*Settings.SixteenBit ? (display_fontwidth-display_hfontaccessscale)*sizeof(uint16)*max_chars :*/ (display_fontwidth-display_hfontaccessscale)*max_chars; + Screen += display_fontheight * display_ppl; + if(Screen >= display_screen + display_ppl * display_height) break; char_count -= max_chars; } + if((unsigned char) string[i]<32) continue; - if ((uint8) string[i] < 32) - continue; + DisplayChar(Screen, string[i]); + Screen += /*Settings.SixteenBit ? (display_fontwidth-display_hfontaccessscale)*sizeof(uint16) :*/ (display_fontwidth-display_hfontaccessscale); + } - S9xDisplayChar(dst, string[i]); - dst += font_width - 1; + // revert temporary change to font scale, if any + if(display_hfontaccessscale != prev_hfont_access_scale) + { + display_hfontaccessscale = prev_hfont_access_scale; + display_fontwidth *= display_hfontaccessscale; } } -static void DisplayFrameRate (void) +// input display +static void S9xDisplayPressedKeys () { - char string[10]; -#ifdef DEBUGGER - const int len = 8; - sprintf(string, "%02d/%02d %02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond, (int) IPPU.FrameCount); -#else - const int len = 5; - sprintf(string, "%02d/%02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond); +#ifndef NGC + uint16 MovieGetJoypad(int i); + bool MovieGetMouse(int i, uint8 out [5]); + bool MovieGetScope(int i, uint8 out [6]); + bool MovieGetJustifier(int i, uint8 out [11]); #endif - S9xDisplayString(string, 1, IPPU.RenderedScreenWidth - (font_width - 1) * len - 1, false); -} + enum controllers controller; + int8 ids[4]; -static void DisplayPressedKeys (void) -{ - static char KeyMap[] = { '0', '1', '2', 'R', 'L', 'X', 'A', '>', '<', 'v', '^', 'S', 's', 'Y', 'B' }; - static int KeyOrder[] = { 8, 10, 7, 9, 0, 6, 14, 13, 5, 1, 4, 3, 2, 11, 12 }; // < ^ > v A B Y X L R S s + int line = 1; +#ifndef NGC + const static char KeyMap[]= {'0','1','2','R','L','X','A','>','<','v','^','S','s','Y','B'}; + const static int KeyOrder[]={8,10,7,9, 0, 6,14,13,5, 1, 4,3, 2, 11,12}; // < ^ > v A B Y X L R S s +#endif + char string[255]; + int len; - enum controllers controller; - int line = 1; - int8 ids[4]; - char string[255]; - - for (int port = 0; port < 2; port++) - { - S9xGetController(port, &controller, &ids[0], &ids[1], &ids[2], &ids[3]); - - switch (controller) + S9xGetController(1, &controller, &ids[0],&ids[1],&ids[2],&ids[3]); +#ifndef NGC + bool singlePlayer = (controller == CTL_NONE || (controller == CTL_JOYPAD && !(MovieGetJoypad(1) & 0xffff))); +#else + bool singlePlayer = (controller == CTL_NONE || (controller == CTL_JOYPAD)); +#endif + for(int port = 0; port < 2; port++) + { + S9xGetController(port, &controller, &ids[0],&ids[1],&ids[2],&ids[3]); + for(int idid = 0; idid < 4; idid++) { - case CTL_MOUSE: - { - uint8 buf[5]; - MovieGetMouse(port, buf); - int16 x = ((uint16 *) buf)[0]; - int16 y = ((uint16 *) buf)[1]; - uint8 buttons = buf[4]; - sprintf(string, "#%d %d: (%04d,%04d) %c%c", port, ids[0], x, y, - (buttons & 0x40) ? 'L' : ' ', (buttons & 0x80) ? 'R' : ' '); - S9xDisplayString(string, line++, 1, false); - break; - } + const int id = ids[idid]; + if(id == -1) + continue; - case CTL_SUPERSCOPE: + bool skip = false; + switch(controller) { - uint8 buf[6]; - MovieGetScope(port, buf); - int16 x = ((uint16 *) buf)[0]; - int16 y = ((uint16 *) buf)[1]; - uint8 buttons = buf[4]; - sprintf(string, "#%d %d: (%03d,%03d) %c%c%c%c", port, ids[0], x, y, - (buttons & 0x80) ? 'F' : ' ', (buttons & 0x40) ? 'C' : ' ', - (buttons & 0x20) ? 'T' : ' ', (buttons & 0x10) ? 'P' : ' '); - S9xDisplayString(string, line++, 1, false); - break; - } + default: { + skip = true; + } break; - case CTL_JUSTIFIER: - { - uint8 buf[11]; - MovieGetJustifier(port, buf); - int16 x1 = ((uint16 *) buf)[0]; - int16 x2 = ((uint16 *) buf)[1]; - int16 y1 = ((uint16 *) buf)[2]; - int16 y2 = ((uint16 *) buf)[3]; - uint8 buttons = buf[8]; - bool8 offscreen1 = buf[9]; - bool8 offscreen2 = buf[10]; - sprintf(string, "#%d %d: (%03d,%03d) %c%c%c / (%03d,%03d) %c%c%c", port, ids[0], - x1, y1, (buttons & 0x80) ? 'T' : ' ', (buttons & 0x20) ? 'S' : ' ', offscreen1 ? 'O' : ' ', - x2, y2, (buttons & 0x40) ? 'T' : ' ', (buttons & 0x10) ? 'S' : ' ', offscreen2 ? 'O' : ' '); - S9xDisplayString(string, line++, 1, false); - break; - } - - case CTL_JOYPAD: - { - sprintf(string, "#%d %d: ", port, ids[0]); - uint16 pad = MovieGetJoypad(ids[0]); - for (int i = 0; i < 15; i++) - { - int j = KeyOrder[i]; - int mask = (1 << (j + 1)); - string[6 + i]= (pad & mask) ? KeyMap[j] : ' '; - } - - S9xDisplayString(string, line++, 1, false); - break; - } - - case CTL_MP5: - { - for (int n = 0; n < 4; n++) - { - if (ids[n] != -1) + case CTL_MP5: + singlePlayer = false; + // no break: + case CTL_JOYPAD: { + if(line < id+1) + line = id+1; +#ifndef NGC + uint16 tempJoypad = MovieGetJoypad(id); + if(!(tempJoypad & 0xffff) && id > 0) + skip = true; + else { - sprintf(string, "#%d %d: ", port, ids[n]); - uint16 pad = MovieGetJoypad(ids[n]); - for (int i = 0; i < 15; i++) + sprintf(string, !singlePlayer?"P%d: ":" ",id+1); + + for (int i=0; i < 15; i++) { int j = KeyOrder[i]; - int mask = (1 << (j + 1)); - string[6 + i]= (pad & mask) ? KeyMap[j] : ' '; + int mask = (1 << (j+1)); + string[strlen("P?: ")+i]= ((tempJoypad & mask)!=0) ? KeyMap[j] : ' '; } - - S9xDisplayString(string, line++, 1, false); } - } +#endif + } break; - break; + case CTL_MOUSE: { +#ifndef NGC + uint8 buf [5] = {0}; + MovieGetMouse(id, buf); + int16 x = ((uint16*)buf)[0]; + int16 y = ((uint16*)buf)[1]; + uint8 buttons = buf[4]; + //if(delta_x < 0) delta_x = 128|-delta_x; + //if(delta_y < 0) delta_y = 128|-delta_y; + sprintf(string, "(%4d,%4d) %c%c", x, y, (buttons&0x40)?'L':' ', (buttons&0x80)?'R':' '); +#endif + } break; + + case CTL_SUPERSCOPE: { +#ifndef NGC + uint8 buf [6] = {0}; + MovieGetScope(id, buf); + int16 x = ((uint16*)buf)[0]; + int16 y = ((uint16*)buf)[1]; + uint8 buttons = buf[4]; + sprintf(string, "(%3d,%3d) %c%c%c%c", x, y, (buttons&0x80)?'F':' ', (buttons&0x40)?'C':' ', (buttons&0x20)?'T':' ', (buttons&0x10)?'P':' '); +#endif + } break; + + case CTL_JUSTIFIER: { +#ifndef NGC + uint8 buf [11] = {0}; + MovieGetJustifier(port, buf); + int16 x1 = ((uint16*)buf)[0]; + int16 x2 = ((uint16*)buf)[1]; + int16 y1 = ((uint16*)buf)[2]; + int16 y2 = ((uint16*)buf)[3]; + uint8 buttons = buf[8]; + bool8 offscreen1 = buf[9]; + bool8 offscreen2 = buf[10]; + if(id == 1) + sprintf(string, "(%3d,%3d) %c%c%c / (%3d,%3d) %c%c%c", x1, y1, (buttons&0x80)?'T':' ', (buttons&0x20)?'S':' ', offscreen1?'O':' ', x2, y2, (buttons&0x40)?'T':' ', (buttons&0x10)?'S':' ', offscreen2?'O':' '); + else + sprintf(string, "(%3d,%3d) %c%c%c", x1, y1, (buttons&0x80)?'T':' ', (buttons&0x20)?'S':' ', offscreen1?'O':' '); +#endif + } break; } - case CTL_NONE: - { - sprintf(string, "#%d -", port); - S9xDisplayString(string, line++, 1, false); - break; - } + if(skip) + continue; + + len=strlen(string); + + DisplayString(string, line, 1, false); + + line++; } } } -static void DisplayWatchedAddresses (void) +void S9xDisplayMessages(uint16 *screen, int ppl, int width, int height, int scale) { - for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) - { - if (!watches[i].on) - break; + display_screen = screen; + display_ppl = ppl; + display_width = width; + display_height = height; + display_fontwidth = font_width * scale; + display_fontheight = font_height * scale; + display_hfontaccessscale = scale; + display_vfontaccessscale = scale; + display_paramsinited = TRUE; - int32 displayNumber = 0; - char buf[32]; - - for (int r = 0; r < watches[i].size; r++) - displayNumber += (Cheat.CWatchRAM[(watches[i].address - 0x7E0000) + r]) << (8 * r); - - if (watches[i].format == 1) - sprintf(buf, "%s,%du = %u", watches[i].desc, watches[i].size, (unsigned int) displayNumber); - else - if (watches[i].format == 3) - sprintf(buf, "%s,%dx = %X", watches[i].desc, watches[i].size, (unsigned int) displayNumber); - else // signed - { - if (watches[i].size == 1) - displayNumber = (int32) ((int8) displayNumber); - else - if (watches[i].size == 2) - displayNumber = (int32) ((int16) displayNumber); - else - if (watches[i].size == 3) - if (displayNumber >= 8388608) - displayNumber -= 16777216; - - sprintf(buf, "%s,%ds = %d", watches[i].desc, watches[i].size, (int) displayNumber); - } - - S9xDisplayString(buf, 6 + i, 1, false); - } -} - -void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int scale) -{ if (Settings.DisplayFrameRate) - DisplayFrameRate(); + S9xDisplayFrameRate(); - if (Settings.DisplayWatchedAddresses) - DisplayWatchedAddresses(); + if (Settings.DisplayPressedKeys==2) + S9xDisplayPressedKeys(); - if (Settings.DisplayPressedKeys) - DisplayPressedKeys(); - - if (Settings.DisplayMovieFrame && S9xMovieActive()) - S9xDisplayString(GFX.FrameDisplayString, 1, 1, false); + if (GFX.FrameDisplay +#ifndef NGC + && S9xMovieActive() +#endif +#ifdef NETPLAY_SUPPORT + || Settings.NetPlay +#endif + ) + DisplayString(GFX.FrameDisplayString, 4, 1, false); if (GFX.InfoString && *GFX.InfoString) - S9xDisplayString(GFX.InfoString, 5, 1, true); + DisplayString(GFX.InfoString, 5, 1, !GFX.FrameDisplay +#ifndef NGC +|| (!S9xMovieActive() +#ifdef NETPLAY_SUPPORT + && !Settings.NetPlay +#endif + ) +#endif + ); + +#ifndef NGC + if (Settings.DisplayWatchedAddresses) + S9xDisplayWatchedAddresses(); +#endif + display_paramsinited = FALSE; + display_fontwidth = font_width; + display_fontheight = font_height; + display_hfontaccessscale = 1; + display_vfontaccessscale = 1; } -static uint16 get_crosshair_color (uint8 color) -{ - switch (color & 15) - { - case 0: return (BUILD_PIXEL( 0, 0, 0)); // transparent, shouldn't be used - case 1: return (BUILD_PIXEL( 0, 0, 0)); // Black - case 2: return (BUILD_PIXEL( 8, 8, 8)); // 25Grey - case 3: return (BUILD_PIXEL(16, 16, 16)); // 50Grey - case 4: return (BUILD_PIXEL(23, 23, 23)); // 75Grey - case 5: return (BUILD_PIXEL(31, 31, 31)); // White - case 6: return (BUILD_PIXEL(31, 0, 0)); // Red - case 7: return (BUILD_PIXEL(31, 16, 0)); // Orange - case 8: return (BUILD_PIXEL(31, 31, 0)); // Yellow - case 9: return (BUILD_PIXEL( 0, 31, 0)); // Green - case 10: return (BUILD_PIXEL( 0, 31, 31)); // Cyan - case 11: return (BUILD_PIXEL( 0, 23, 31)); // Sky - case 12: return (BUILD_PIXEL( 0, 0, 31)); // Blue - case 13: return (BUILD_PIXEL(23, 0, 31)); // Violet - case 14: return (BUILD_PIXEL(31, 0, 31)); // Magenta - case 15: return (BUILD_PIXEL(31, 0, 16)); // Purple - } +#include "crosshairs.h" - return (0); +static uint16 get_crosshair_color(uint8 color){ + switch(color&15){ + case 0: return BUILD_PIXEL(0,0,0); // transparent, shouldn't be used + case 1: return BUILD_PIXEL(0,0,0); // Black + case 2: return BUILD_PIXEL(8,8,8); // 25Grey + case 3: return BUILD_PIXEL(16,16,16); // 50Grey + case 4: return BUILD_PIXEL(23,23,23); // 75Grey + case 5: return BUILD_PIXEL(31,31,31); // White + case 6: return BUILD_PIXEL(31,0,0); // Red + case 7: return BUILD_PIXEL(31,16,0); // Orange + case 8: return BUILD_PIXEL(31,31,0); // Yellow + case 9: return BUILD_PIXEL(0,31,0); // Green + case 10: return BUILD_PIXEL(0,31,31); // Cyan + case 11: return BUILD_PIXEL(0,23,31); // Sky + case 12: return BUILD_PIXEL(0,0,31); // Blue + case 13: return BUILD_PIXEL(23,0,31); // Violet + case 14: return BUILD_PIXEL(31,0,31); // Magenta + case 15: return BUILD_PIXEL(31,0,16); // Purple + } + return 0; // stupid compiler warning } -void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y) -{ - if (!crosshair) - return; +void S9xDrawCrosshair(const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y) { + int16 r, rx=1, c, cx=1, W, H, rws; - int16 r, rx = 1, c, cx = 1, W = SNES_WIDTH, H = PPU.ScreenHeight; - uint16 fg, bg; - - x -= 7; - y -= 7; - - if (IPPU.DoubleWidthPixels) { cx = 2; x *= 2; W *= 2; } - if (IPPU.DoubleHeightPixels) { rx = 2; y *= 2; H *= 2; } - - fg = get_crosshair_color(fgcolor); - bg = get_crosshair_color(bgcolor); - - // XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it... -#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) - if (x >= 0 && y >= 0) + W=256; H=PPU.ScreenHeight; + x-=7; y-=7; + if(IPPU.DoubleWidthPixels){ cx=2; x*=2; W*=2; } + if(IPPU.DoubleHeightPixels){ rx=2; y*=2; H*=2; } + if(crosshair==NULL) return; + if(GFX.Screen==NULL) return; + if(Settings.StopEmulation) return; + uint16 fg, bg; + fg=get_crosshair_color(fgcolor); + bg=get_crosshair_color(bgcolor); +#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) // XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it... + if(x >= 0 && y >= 0) #endif { - uint16 *s = GFX.Screen + y * GFX.RealPPL + x; + uint16 *s = GFX.Screen + y * GFX.RealPPL + x; + rws = Settings.OpenGLEnable ? IPPU.RenderedScreenWidth : GFX.RealPPL; + for(r=0; r<15*rx; r++, s+=rws-15*cx) { + if(y+r<0){ s+=15*cx; continue; } // if y is negative, skip line + if(y+r>=H) break; // if y is past bottom, stop + for(c=0; c<15*cx; c++, s++) { + if(x+c<0 || s=W){ s+=15*cx-c; break; } // if x is past right, go to next line + uint8 p = crosshair[(r/rx)*15+(c/cx)]; - for (r = 0; r < 15 * rx; r++, s += GFX.RealPPL - 15 * cx) - { - if (y + r < 0) - { - s += 15 * cx; - continue; - } - - if (y + r >= H) - break; - - for (c = 0; c < 15 * cx; c++, s++) - { - if (x + c < 0 || s < GFX.Screen) - continue; - - if (x + c >= W) - { - s += 15 * cx - c; - break; - } - - uint8 p = crosshair[(r / rx) * 15 + (c / cx)]; - - if (p == '#' && fgcolor) - *s = (fgcolor & 0x10) ? COLOR_ADD1_2(fg, *s) : fg; - else - if (p == '.' && bgcolor) - *s = (bgcolor & 0x10) ? COLOR_ADD1_2(*s, bg) : bg; - } - } - } + if(p == '#' && fgcolor) { + *s=(fgcolor&0x10)?COLOR_ADD1_2(fg,*s):fg; + } else if(p == '.' && bgcolor) { + *s=(bgcolor&0x10)?COLOR_ADD1_2(*s,bg):bg; + } + } + } + } } + #ifdef GFX_MULTI_FORMAT #define _BUILD_PIXEL(F) \ -uint32 BuildPixel##F (uint32 R, uint32 G, uint32 B) \ +uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \ { \ - return (BUILD_PIXEL_##F(R, G, B)); \ + return (BUILD_PIXEL_##F(R,G,B)); \ +}\ +uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL2_##F(R,G,B)); \ } \ -\ -uint32 BuildPixel2##F (uint32 R, uint32 G, uint32 B) \ +void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ { \ - return (BUILD_PIXEL2_##F(R, G, B)); \ -} \ -\ -void DecomposePixel##F (uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ -{ \ - DECOMPOSE_PIXEL_##F(pixel, R, G, B); \ + DECOMPOSE_PIXEL_##F(pixel,R,G,B); \ } _BUILD_PIXEL(RGB565) @@ -2295,69 +1994,73 @@ _BUILD_PIXEL(GBR555) _BUILD_PIXEL(RGB5551) #define _BUILD_SETUP(F) \ -GFX.BuildPixel = BuildPixel##F; \ -GFX.BuildPixel2 = BuildPixel2##F; \ -GFX.DecomposePixel = DecomposePixel##F; \ -RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ -GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ -BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ -RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ -GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ -BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ -MAX_RED = MAX_RED_##F; \ -MAX_GREEN = MAX_GREEN_##F; \ -MAX_BLUE = MAX_BLUE_##F; \ -SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ -GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ -RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | GREEN_LOW_BIT_MASK_##F | BLUE_LOW_BIT_MASK_##F); \ -RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | GREEN_HI_BIT_MASK_##F | BLUE_HI_BIT_MASK_##F); \ -RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_##F | GREEN_HI_BIT_MASK_##F | BLUE_HI_BIT_MASK_##F) << 1; \ -RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ -FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ -SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ -THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ -ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ -FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ -TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ -HIGH_BITS_SHIFTED_TWO_MASK = ((FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & ~TWO_LOW_BITS_MASK) >> 2; +GFX.BuildPixel = BuildPixel##F; \ +GFX.BuildPixel2 = BuildPixel2##F; \ +GFX.DecomposePixel = DecomposePixel##F; \ +RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ +GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ +BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ +RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ +GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ +BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ +MAX_RED = MAX_RED_##F; \ +MAX_GREEN = MAX_GREEN_##F; \ +MAX_BLUE = MAX_BLUE_##F; \ +GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ +SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ +RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \ + GREEN_LOW_BIT_MASK_##F | \ + BLUE_LOW_BIT_MASK_##F); \ +RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \ + GREEN_HI_BIT_MASK_##F | \ + BLUE_HI_BIT_MASK_##F); \ +RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \ + GREEN_HI_BIT_MASK_##F | \ + BLUE_HI_BIT_MASK_##F) << 1); \ +RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ +FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ +SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ +THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ +ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ +FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ +TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ +HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \ + ~TWO_LOW_BITS_MASK ) >> 2); bool8 S9xSetRenderPixelFormat (int format) { - switch (format) - { - case RGB565: - _BUILD_SETUP(RGB565) - return (TRUE); + extern uint32 current_graphic_format; - case RGB555: - _BUILD_SETUP(RGB555) - return (TRUE); + current_graphic_format = format; - case BGR565: - _BUILD_SETUP(BGR565) - return (TRUE); - - case BGR555: - _BUILD_SETUP(BGR555) - return (TRUE); - - case GBR565: - _BUILD_SETUP(GBR565) - return (TRUE); - - case GBR555: - _BUILD_SETUP(GBR555) - return (TRUE); - - case RGB5551: - _BUILD_SETUP(RGB5551) - return (TRUE); - - default: - break; - } - - return (FALSE); + switch (format) + { + case RGB565: + _BUILD_SETUP(RGB565) + return (TRUE); + case RGB555: + _BUILD_SETUP(RGB555) + return (TRUE); + case BGR565: + _BUILD_SETUP(BGR565) + return (TRUE); + case BGR555: + _BUILD_SETUP(BGR555) + return (TRUE); + case GBR565: + _BUILD_SETUP(GBR565) + return (TRUE); + case GBR555: + _BUILD_SETUP(GBR555) + return (TRUE); + case RGB5551: + _BUILD_SETUP(RGB5551) + return (TRUE); + default: + break; + } + return (FALSE); } - #endif + +void (*S9xCustomDisplayString) (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) = NULL; diff --git a/source/snes9x/gfx.h b/source/snes9x/gfx.h index 78a0fde..1946174 100644 --- a/source/snes9x/gfx.h +++ b/source/snes9x/gfx.h @@ -159,150 +159,177 @@ **********************************************************************************/ + + #ifndef _GFX_H_ #define _GFX_H_ -struct SGFX -{ - uint16 *Screen; - uint16 *SubScreen; - uint8 *ZBuffer; - uint8 *SubZBuffer; - uint32 Pitch; - uint32 ScreenSize; - uint16 *S; - uint8 *DB; - uint16 *X2; - uint16 *ZERO; - uint32 RealPPL; // true PPL of Screen buffer - uint32 PPL; // number of pixels on each of Screen buffer - uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace) - uint16 *ScreenColors; // screen colors for rendering main - uint16 *RealScreenColors; // screen colors, ignoring color window clipping - uint8 Z1; // depth for comparison - uint8 Z2; // depth to save - uint32 FixedColour; - uint8 DoInterlace; - uint8 InterlaceFrame; - uint32 StartY; - uint32 EndY; - bool8 ClipColors; - uint8 OBJWidths[128]; - uint8 OBJVisibleTiles[128]; +#include "port.h" +#include "snes9x.h" - struct ClipData *Clip; +struct SGFX{ + // Initialize these variables + uint16 *Screen; + uint16 *SubScreen; + uint8 *ZBuffer; + uint8 *SubZBuffer; + uint32 Pitch; + uint32 ScreenSize; - struct - { - uint8 RTOFlags; - int16 Tiles; + uint16 *S; + uint8 *DB; - struct - { - int8 Sprite; - uint8 Line; - } OBJ[32]; - } OBJLines[SNES_HEIGHT_EXTENDED]; + // Setup in call to S9xGraphicsInit() + uint16 *X2; + uint16 *ZERO_OR_X2; + uint16 *ZERO; + + uint32 RealPPL; // True PPL of Screen buffer. + uint32 PPL; // Number of pixels on each of Screen buffer + uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace) + uint16 *ScreenColors; // Screen colors for rendering main + uint16 *RealScreenColors; // Screen colors, ignoring color window clipping + uint8 Z1; // Depth for comparison + uint8 Z2; // Depth to save + uint32 FixedColour; + const char *InfoString; + uint32 InfoStringTimeout; + char FrameDisplayString[256]; + bool8 FrameDisplay; + bool8 Repainting; // True if the frame is being re-drawn + uint8 DoInterlace; + uint8 InterlaceFrame; + uint32 StartY; + uint32 EndY; + struct ClipData *Clip; + bool8 ClipColors; + uint8 OBJWidths[128]; + uint8 OBJVisibleTiles[128]; + struct { + uint8 RTOFlags; + int16 Tiles; + struct { + int8 Sprite; + uint8 Line; + } OBJ[32]; + } OBJLines [SNES_HEIGHT_EXTENDED]; #ifdef GFX_MULTI_FORMAT - uint32 PixelFormat; - uint32 (*BuildPixel) (uint32, uint32, uint32); - uint32 (*BuildPixel2) (uint32, uint32, uint32); - void (*DecomposePixel) (uint32, uint32 &, uint32 &, uint32 &); + uint32 PixelFormat; + uint32 (*BuildPixel) (uint32 R, uint32 G, uint32 B); + uint32 (*BuildPixel2) (uint32 R, uint32 G, uint32 B); + void (*DecomposePixel) (uint32 Pixel, uint32 &R, uint32 &G, uint32 &B); #endif - void (*DrawBackdropMath) (uint32, uint32, uint32); - void (*DrawBackdropNomath) (uint32, uint32, uint32); - void (*DrawTileMath) (uint32, uint32, uint32, uint32); - void (*DrawTileNomath) (uint32, uint32, uint32, uint32); - void (*DrawClippedTileMath) (uint32, uint32, uint32, uint32, uint32, uint32); - void (*DrawClippedTileNomath) (uint32, uint32, uint32, uint32, uint32, uint32); - void (*DrawMosaicPixelMath) (uint32, uint32, uint32, uint32, uint32, uint32); - void (*DrawMosaicPixelNomath) (uint32, uint32, uint32, uint32, uint32, uint32); - void (*DrawMode7BG1Math) (uint32, uint32, int); - void (*DrawMode7BG1Nomath) (uint32, uint32, int); - void (*DrawMode7BG2Math) (uint32, uint32, int); - void (*DrawMode7BG2Nomath) (uint32, uint32, int); - - const char *InfoString; - uint32 InfoStringTimeout; - char FrameDisplayString[256]; + void (*DrawBackdropMath)(uint32,uint32,uint32); + void (*DrawBackdropNomath)(uint32,uint32,uint32); + void (*DrawTileMath)(uint32,uint32,uint32,uint32); + void (*DrawTileNomath)(uint32,uint32,uint32,uint32); + void (*DrawClippedTileMath)(uint32,uint32,uint32,uint32,uint32,uint32); + void (*DrawClippedTileNomath)(uint32,uint32,uint32,uint32,uint32,uint32); + void (*DrawMosaicPixelMath)(uint32,uint32,uint32,uint32,uint32,uint32); + void (*DrawMosaicPixelNomath)(uint32,uint32,uint32,uint32,uint32,uint32); + void (*DrawMode7BG1Math)(uint32,uint32,int); + void (*DrawMode7BG1Nomath)(uint32,uint32,int); + void (*DrawMode7BG2Math)(uint32,uint32,int); + void (*DrawMode7BG2Nomath)(uint32,uint32,int); }; -struct SBG -{ - uint8 (*ConvertTile) (uint8 *, uint32, uint32); - uint8 (*ConvertTileFlip) (uint8 *, uint32, uint32); - - uint32 TileSizeH; - uint32 TileSizeV; - uint32 OffsetSizeH; - uint32 OffsetSizeV; - uint32 TileShift; - uint32 TileAddress; - uint32 NameSelect; - uint32 SCBase; - - uint32 StartPalette; - uint32 PaletteShift; - uint32 PaletteMask; - uint8 EnableMath; - uint8 InterlaceLine; - - uint8 *Buffer; - uint8 *BufferFlip; - uint8 *Buffered; - uint8 *BufferedFlip; - bool8 DirectColourMode; +struct SLineData { + struct { + uint16 VOffset; + uint16 HOffset; + } BG [4]; }; -struct SLineData -{ - struct - { - uint16 VOffset; - uint16 HOffset; - } BG[4]; +#define H_FLIP 0x4000 +#define V_FLIP 0x8000 +#define BLANK_TILE 2 + +struct SBG { + uint8 (*ConvertTile)(uint8 *,uint32,uint32); + uint8 (*ConvertTileFlip)(uint8 *,uint32,uint32); + + uint32 TileSizeH; + uint32 TileSizeV; + uint32 OffsetSizeH; + uint32 OffsetSizeV; + uint32 TileShift; + uint32 TileAddress; + uint32 NameSelect; + uint32 SCBase; + + uint32 StartPalette; + uint32 PaletteShift; + uint32 PaletteMask; + uint8 EnableMath; + uint8 InterlaceLine; + + uint8 *Buffer, *BufferFlip; + uint8 *Buffered, *BufferedFlip; + bool8 DirectColourMode; }; struct SLineMatrixData { - short MatrixA; - short MatrixB; - short MatrixC; - short MatrixD; - short CentreX; - short CentreY; - short M7HOFS; - short M7VOFS; + short MatrixA; + short MatrixB; + short MatrixC; + short MatrixD; + short CentreX; + short CentreY; + short M7HOFS; + short M7VOFS; }; -extern uint16 BlackColourMap[256]; -extern uint16 DirectColourMaps[8][256]; -extern uint8 mul_brightness[16][32]; -extern struct SBG BG; -extern struct SGFX GFX; +extern SBG BG; +extern uint16 BlackColourMap [256]; +extern uint16 DirectColourMaps [8][256]; -#define H_FLIP 0x4000 -#define V_FLIP 0x8000 -#define BLANK_TILE 2 +extern uint8 add32_32 [32][32]; +extern uint8 add32_32_half [32][32]; +extern uint8 sub32_32 [32][32]; +extern uint8 sub32_32_half [32][32]; +extern uint8 mul_brightness [16][32]; + +// Could use BSWAP instruction on Intel port... +#define SWAP_DWORD(dw) dw = ((dw & 0xff) << 24) | ((dw & 0xff00) << 8) | \ + ((dw & 0xff0000) >> 8) | ((dw & 0xff000000) >> 24) + +#define SUB_SCREEN_DEPTH 0 +#define MAIN_SCREEN_DEPTH 32 + +#if defined(OLD_COLOUR_BLENDING) +#define COLOR_ADD(C1, C2) \ +GFX.X2 [((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK)] +#else +#define COLOR_ADD(C1, C2) \ +(GFX.X2 [((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK)] | \ + (((C1) ^ (C2)) & RGB_LOW_BITS_MASK)) +#endif #define COLOR_ADD1_2(C1, C2) \ - ((((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ - ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ - ((C1) & (C2) & RGB_LOW_BITS_MASK)) | ALPHA_BITS_MASK) +(((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK) | ALPHA_BITS_MASK) -#define COLOR_ADD(C1, C2) \ - (GFX.X2[((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ - ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ - ((C1) & (C2) & RGB_LOW_BITS_MASK)] | \ - (((C1) ^ (C2)) & RGB_LOW_BITS_MASK)) +#if defined(OLD_COLOUR_BLENDING) +#define COLOR_SUB(C1, C2) \ +GFX.ZERO_OR_X2 [(((C1) | RGB_HI_BITS_MASKx2) - \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] +#elif !defined(NEW_COLOUR_BLENDING) +#define COLOR_SUB(C1, C2) \ +(GFX.ZERO_OR_X2 [(((C1) | RGB_HI_BITS_MASKx2) - \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] + \ +((C1) & RGB_LOW_BITS_MASK) - ((C2) & RGB_LOW_BITS_MASK)) +#else +inline uint16 COLOR_SUB(uint16, uint16); -#define COLOR_SUB1_2(C1, C2) \ - GFX.ZERO[(((C1) | RGB_HI_BITS_MASKx2) - \ - ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] - -inline uint16 COLOR_SUB (uint16 C1, uint16 C2) +inline uint16 COLOR_SUB(uint16 C1, uint16 C2) { uint16 mC1, mC2, v = ALPHA_BITS_MASK; @@ -318,33 +345,44 @@ inline uint16 COLOR_SUB (uint16 C1, uint16 C2) mC2 = C2 & THIRD_COLOR_MASK; if (mC1 > mC2) v += (mC1 - mC2); - return (v); + return v; } - -void S9xStartScreenRefresh (void); -void S9xEndScreenRefresh (void); -void S9xUpdateScreen (void); -void S9xBuildDirectColourMaps (void); -void RenderLine (uint8); -void S9xComputeClipWindows (void); -void S9xDisplayChar (uint16 *, uint8); -// called automatically unless Settings.AutoDisplayMessages is false -void S9xDisplayMessages (uint16 *, int, int, int, int); -#ifdef GFX_MULTI_FORMAT -bool8 S9xSetRenderPixelFormat (int); #endif -// external port interface which must be implemented or initialised for each port -bool8 S9xGraphicsInit (void); -void S9xGraphicsDeinit (void); +#define COLOR_SUB1_2(C1, C2) \ +GFX.ZERO [(((C1) | RGB_HI_BITS_MASKx2) - \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] + +START_EXTERN_C +void S9xStartScreenRefresh (); +void S9xDrawScanLine (uint8 Line); +void S9xEndScreenRefresh (); +void S9xSetupOBJ (); +void S9xUpdateScreen (); +void RenderLine (uint8 line); +void S9xBuildDirectColourMaps (); + +void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int scale); // called automatically unless Settings.AutoDisplayMessages is false + +extern struct SGFX GFX; + +// External port interface which must be implemented or initialised for each +// port. +bool8 S9xGraphicsInit (); +void S9xGraphicsDeinit(); bool8 S9xInitUpdate (void); -bool8 S9xDeinitUpdate (int, int); -bool8 S9xContinueUpdate (int, int); -void S9xReRefresh (void); -void S9xSetPalette (void); -void S9xSyncSpeed (void); +bool8 S9xDeinitUpdate (int Width, int Height); +bool8 S9xContinueUpdate (int Width, int Height); +void S9xSetPalette (); +void S9xSyncSpeed (); -// called instead of S9xDisplayString if set to non-NULL -extern void (*S9xCustomDisplayString) (const char *, int, int, bool); +extern void (*S9xCustomDisplayString) (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); // called instead of S9xDisplayString if set to non-NULL + +#ifdef GFX_MULTI_FORMAT +bool8 S9xSetRenderPixelFormat (int format); +#endif + +END_EXTERN_C #endif + diff --git a/source/snes9x/globals.cpp b/source/snes9x/globals.cpp index 2d02e71..65cff41 100644 --- a/source/snes9x/globals.cpp +++ b/source/snes9x/globals.cpp @@ -159,236 +159,235 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" +#include "ppu.h" +#include "dsp1.h" +#include "missing.h" +#include "cpuexec.h" +#include "s9xdebug.h" +#include "apu.h" #include "dma.h" -#include "apu/apu.h" -#include "fxinst.h" #include "fxemu.h" -#include "srtc.h" +#include "gfx.h" +#include "soundux.h" #include "cheats.h" +#include "sa1.h" +#include "bsx.h" +#include "spc7110.h" #ifdef NETPLAY_SUPPORT #include "netplay.h" #endif -#ifdef DEBUGGER -#include "debug.h" -#include "missing.h" -#endif -struct SCPUState CPU; -struct SICPU ICPU; -struct SRegisters Registers; -struct SPPU PPU; -struct InternalPPU IPPU; -struct SDMA DMA[8]; -struct STimings Timings; -struct SGFX GFX; -struct SBG BG; -struct SLineData LineData[240]; -struct SLineMatrixData LineMatrixData[240]; -struct SDSP0 DSP0; -struct SDSP1 DSP1; -struct SDSP2 DSP2; -struct SDSP3 DSP3; -struct SDSP4 DSP4; -struct SSA1 SA1; -struct SSA1Registers SA1Registers; -struct SST010 ST010; -struct SST011 ST011; -struct SST018 ST018; -struct SOBC1 OBC1; -struct SSPC7110Snapshot s7snap; -struct SSRTCSnapshot srtcsnap; -struct SRTCData RTCData; -struct SBSX BSX; -struct SMulti Multi; -struct SSettings Settings; -struct SSNESGameFixes SNESGameFixes; -#ifdef NETPLAY_SUPPORT -struct SNetPlay NetPlay; -#endif -#ifdef DEBUGGER -struct Missing missing; -#endif -struct SCheatData Cheat; -struct Watch watches[16]; -#ifndef ZSNES_FX -struct FxRegs_s GSU; -struct FxInfo_s SuperFX; -#endif -CMemory Memory; +START_EXTERN_C +char String[513]; -char String[513]; -uint8 OpenBus = 0; -uint8 *HDMAMemPointers[8]; -uint16 BlackColourMap[256]; -uint16 DirectColourMaps[8][256]; +struct Missing missing; -SnesModel M1SNES = { 1, 3, 2 }; -SnesModel M2SNES = { 2, 4, 3 }; -SnesModel *Model = &M1SNES; +struct SICPU ICPU; + +struct SCPUState CPU; + +struct STimings Timings; + +struct SRegisters Registers; + +struct SAPU APU; + +struct SIAPU IAPU; + +struct SAPURegisters APURegisters; + +struct SSettings Settings; + +struct SSA1Registers SA1Registers; + +struct SSA1 SA1; + +struct SBSX BSX; + +struct SMulti Multi; + +SSoundData SoundData; #if defined(ZSNES_FX) || defined(ZSNES_C4) -uint8 *ROM = NULL; -uint8 *SRAM = NULL; -uint8 *RegRAM = NULL; +uint8 *ROM = NULL; +uint8 *SRAM = NULL; +uint8 *RegRAM = NULL; #endif -#ifdef ZSNES_FX -uint8 *SFXPlotTable = NULL; + +CMemory Memory; + +struct SSNESGameFixes SNESGameFixes; + +unsigned char OpenBus = 0; + + +END_EXTERN_C + +struct SDSP1 DSP1; + +SnesModel M1SNES={1,3,2}; +SnesModel M2SNES={2,4,3}; +SnesModel* Model=&M1SNES; + +#ifndef ZSNES_FX +struct FxInit_s SuperFX; +#else +START_EXTERN_C +uint8 *SFXPlotTable = NULL; +END_EXTERN_C #endif +struct SPPU PPU; +struct InternalPPU IPPU; + +struct SDMA DMA[8]; + +uint8 *HDMAMemPointers [8]; +uint8 *HDMABasePointers [8]; + +struct SBG BG; + +struct SGFX GFX; +struct SLineData LineData[240]; +struct SLineMatrixData LineMatrixData [240]; + #ifdef GFX_MULTI_FORMAT -uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565; -uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565; -uint32 BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_RGB565; -uint32 RED_HI_BIT_MASK = RED_HI_BIT_MASK_RGB565; -uint32 GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_RGB565; -uint32 BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_RGB565; -uint32 MAX_RED = MAX_RED_RGB565; -uint32 MAX_GREEN = MAX_GREEN_RGB565; -uint32 MAX_BLUE = MAX_BLUE_RGB565; -uint32 SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_RGB565; -uint32 GREEN_HI_BIT = (MAX_GREEN_RGB565 + 1) >> 1; -uint32 RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_RGB565 | GREEN_LOW_BIT_MASK_RGB565 | BLUE_LOW_BIT_MASK_RGB565); -uint32 RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_RGB565 | GREEN_HI_BIT_MASK_RGB565 | BLUE_HI_BIT_MASK_RGB565); -uint32 RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_RGB565 | GREEN_HI_BIT_MASK_RGB565 | BLUE_HI_BIT_MASK_RGB565) << 1; -uint32 RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; -uint32 FIRST_COLOR_MASK = FIRST_COLOR_MASK_RGB565; -uint32 SECOND_COLOR_MASK = SECOND_COLOR_MASK_RGB565; -uint32 THIRD_COLOR_MASK = THIRD_COLOR_MASK_RGB565; -uint32 ALPHA_BITS_MASK = ALPHA_BITS_MASK_RGB565; -uint32 FIRST_THIRD_COLOR_MASK = 0; -uint32 TWO_LOW_BITS_MASK = 0; -uint32 HIGH_BITS_SHIFTED_TWO_MASK = 0; + +uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565; +uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565; +uint32 BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_RGB565; +uint32 RED_HI_BIT_MASK = RED_HI_BIT_MASK_RGB565; +uint32 GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_RGB565; +uint32 BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_RGB565; +uint32 MAX_RED = MAX_RED_RGB565; +uint32 MAX_GREEN = MAX_GREEN_RGB565; +uint32 MAX_BLUE = MAX_BLUE_RGB565; +uint32 SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_RGB565; +uint32 GREEN_HI_BIT = (MAX_GREEN_RGB565 + 1) >> 1; +uint32 RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_RGB565 | + GREEN_LOW_BIT_MASK_RGB565 | + BLUE_LOW_BIT_MASK_RGB565); +uint32 RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_RGB565 | + GREEN_HI_BIT_MASK_RGB565 | + BLUE_HI_BIT_MASK_RGB565); +uint32 RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_RGB565 | + GREEN_HI_BIT_MASK_RGB565 | + BLUE_HI_BIT_MASK_RGB565) << 1; +uint32 RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; +uint32 FIRST_COLOR_MASK = FIRST_COLOR_MASK_RGB565; +uint32 SECOND_COLOR_MASK = SECOND_COLOR_MASK_RGB565; +uint32 THIRD_COLOR_MASK = THIRD_COLOR_MASK_RGB565; +uint32 ALPHA_BITS_MASK = ALPHA_BITS_MASK_RGB565; +uint32 FIRST_THIRD_COLOR_MASK = 0; +uint32 TWO_LOW_BITS_MASK = 0; +uint32 HIGH_BITS_SHIFTED_TWO_MASK = 0; + +uint32 current_graphic_format = RGB565; #endif -uint16 SignExtend[2] = -{ - 0x0000, - 0xff00 +uint8 GetBank = 0; +struct SCheatData Cheat; + +volatile SoundStatus so; + +int32 Loop[16]; +int32 Echo[24000]; +int32 FilterTaps[8]; +int32 MixBuffer[SOUND_BUFFER_SIZE]; +int32 EchoBuffer[SOUND_BUFFER_SIZE]; +int32 DummyEchoBuffer[SOUND_BUFFER_SIZE]; +uint32 FIRIndex = 0; + +uint16 SignExtend [2] = { + 0x00, 0xff00 }; -int HDMA_ModeByteCounts[8] = -{ - 1, 2, 2, 4, 4, 4, 2, 4 +//modified per anomie Mode 5 findings +int HDMA_ModeByteCounts [8] = { + 1, 2, 2, 4, 4, 4, 2, 4 }; -uint8 mul_brightness[16][32] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, - { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04 }, - { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06 }, - { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, - 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08 }, - { 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, - 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a }, - { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, - 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c }, - { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, - 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e }, - { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, - 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x11 }, - { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, - 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13 }, - { 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09, 0x0a, - 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15 }, - { 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, - 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17 }, - { 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, - 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19 }, - { 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, - 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1b }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f } +uint16 BlackColourMap [256]; +uint16 DirectColourMaps [8][256]; + +uint32 HeadMask [4] = { +#ifdef LSB_FIRST + 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000 +#else + 0xffffffff, 0x00ffffff, 0x0000ffff, 0x000000ff +#endif }; -uint8 S9xOpLengthsM0X0[256] = -{ -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 - 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 - 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 - 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 - 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 - 3, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B - 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D - 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +uint32 TailMask [5] = { +#ifdef LSB_FIRST + 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff +#else + 0x00000000, 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff +#endif }; -uint8 S9xOpLengthsM0X1[256] = +START_EXTERN_C +uint8 APUROM [64] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 - 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 - 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 - 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 - 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F + 0xCD,0xEF,0xBD,0xE8,0x00,0xC6,0x1D,0xD0,0xFC,0x8F,0xAA,0xF4,0x8F, + 0xBB,0xF5,0x78,0xCC,0xF4,0xD0,0xFB,0x2F,0x19,0xEB,0xF4,0xD0,0xFC, + 0x7E,0xF4,0xD0,0x0B,0xE4,0xF5,0xCB,0xF4,0xD7,0x00,0xFC,0xD0,0xF3, + 0xAB,0x01,0x10,0xEF,0x7E,0xF4,0x10,0xEB,0xBA,0xF6,0xDA,0x00,0xBA, + 0xF4,0xC4,0xF4,0xDD,0x5D,0xD0,0xDB,0x1F,0x00,0x00,0xC0,0xFF }; -uint8 S9xOpLengthsM1X0[256] = +#ifdef NETPLAY_SUPPORT +struct SNetPlay NetPlay; +#endif + +// Raw SPC700 instruction cycle lengths +int32 S9xAPUCycleLengths [256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 - 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 - 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 - 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 - 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 - 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B - 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D - 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, + /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, + /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, + /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, + /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, + /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, + /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, + /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, + /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, + /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5, + /* A0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, + /* B0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, + /* C0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, + /* D0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 5, 5, 2, 2, 6, 3, + /* E0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, + /* F0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 }; -uint8 S9xOpLengthsM1X1[256] = +// Actual data used by CPU emulation, will be scaled by APUReset routine +// to be relative to the 65c816 instruction lengths. +int32 S9xAPUCycles [256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 - 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 - 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 - 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 - 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 - 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B - 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C - 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D - 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E - 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, + /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, + /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, + /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, + /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, + /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, + /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, + /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, + /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, + /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5, + /* A0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, + /* B0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, + /* C0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, + /* D0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 5, 5, 2, 2, 6, 3, + /* E0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, + /* F0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 }; + +END_EXTERN_C + diff --git a/source/snes9x/language.h b/source/snes9x/language.h index a0fa607..3bf22f9 100644 --- a/source/snes9x/language.h +++ b/source/snes9x/language.h @@ -159,28 +159,30 @@ **********************************************************************************/ -#ifndef _LANGUAGE_H_ -#define _LANGUAGE_H_ -// Movie Messages -#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" -#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" -#define MOVIE_INFO_REPLAY "Movie replay" -#define MOVIE_INFO_RECORD "Movie record" -#define MOVIE_INFO_RERECORD "Movie re-record" -#define MOVIE_INFO_REWIND "Movie rewind" -#define MOVIE_INFO_STOP "Movie stop" -#define MOVIE_INFO_END "Movie end" -#define MOVIE_INFO_SNAPSHOT "Movie snapshot" -#define MOVIE_ERR_SNAPSHOT_INCONSISTENT "Snapshot inconsistent with movie" -// Snapshot Messages -#define SAVE_INFO_SNAPSHOT "Saved" -#define SAVE_INFO_LOAD "Loaded" -#define SAVE_INFO_OOPS "Auto-saving 'oops' snapshot" -#define SAVE_ERR_WRONG_FORMAT "File not in Snes9x snapshot format" -#define SAVE_ERR_WRONG_VERSION "Incompatable snapshot version" -#define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for snapshot not found" -#define SAVE_ERR_SAVE_NOT_FOUND "Snapshot %s does not exist" +/* This file is for core emulator messages. Use a port-specific file for * + * GUI strings and the like. Thank you. */ + +/* Movie Messages */ + +#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" +#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" +#define MOVIE_INFO_REPLAY "Movie replay" +#define MOVIE_INFO_RECORD "Movie record" +#define MOVIE_INFO_RERECORD "Movie re-record" +#define MOVIE_INFO_REWIND "Movie rewind" +#define MOVIE_INFO_STOP "Movie stop" +#define MOVIE_INFO_END "Movie end" +#define MOVIE_INFO_SNAPSHOT "Movie snapshot" +#define MOVIE_ERR_SNAPSHOT_INCONSISTENT "Snapshot inconsistent with movie" + +/* Snapshot Messages */ + +#define SAVE_INFO_SNAPSHOT "Saved" +#define SAVE_INFO_LOAD "Loaded" +#define SAVE_ERR_WRONG_FORMAT "File not in Snes9x freeze format" +#define SAVE_ERR_WRONG_VERSION "Incompatable Snes9x freeze file format version" +#define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for freeze file not found" +#define SAVE_ERR_SAVE_NOT_FOUND "Save file %s does not exist." -#endif diff --git a/source/snes9x/memmap.cpp b/source/snes9x/memmap.cpp index a5ed61d..972136a 100644 --- a/source/snes9x/memmap.cpp +++ b/source/snes9x/memmap.cpp @@ -159,721 +159,92 @@ **********************************************************************************/ -#include + +#include #include + +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include #include +#ifdef __linux +#include +#endif + +#ifdef __W32_HEAP +#include +#endif + +#include "memmap.h" +#include "display.h" +#include "cpuexec.h" +#include "ppu.h" +#include "apu.h" +#include "dsp1.h" +#include "sa1.h" +#include "sdd1.h" +#include "spc7110.h" +#include "seta.h" +#include "srtc.h" +#include "bsx.h" +#include "cheats.h" + +#ifndef NGC +#include "reader.h" +#else +#include + +extern unsigned long SNESROMSize; +#endif + +#include "controls.h" +//#include "movie.h" + +#ifndef ZSNES_FX +#include "fxemu.h" +#endif + #ifdef UNZIP_SUPPORT -#include "unzip/unzip.h" +#include "unzip.h" #endif #ifdef JMA_SUPPORT #include "jma/s9x-jma.h" #endif -#include "snes9x.h" -#include "memmap.h" -#include "apu/apu.h" -#include "fxemu.h" -#include "sdd1.h" -#include "srtc.h" -#include "controls.h" -#include "cheats.h" -#include "movie.h" -#include "reader.h" -#include "display.h" +#ifdef __WIN32__ +#ifndef _XBOX +#include "win32/wsnes9x.h" // FIXME: shouldn't be necessary +#endif +#endif -#ifdef GEKKO -extern int WiiFileLoader(); -extern void WiiLoadPatch(); -extern void WiiSetupCheats(); +#ifdef __WIN32__ +#define snprintf _snprintf // needs ANSI compliant name #endif #ifndef SET_UI_COLOR -#define SET_UI_COLOR(r, g, b) ; +#define SET_UI_COLOR(r,g,b) ; #endif #ifndef max -#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef min -#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ZSNES_FX +extern struct FxInit_s SuperFX; +#else +EXTERN_C uint8 *SFXPlotTable; #endif static bool8 stopMovie = TRUE; -static char LastRomFilename[PATH_MAX + 1] = ""; - -// from NSRT -static const char *nintendo_licensees[] = -{ - "Unlicensed", - "Nintendo", - "Rocket Games/Ajinomoto", - "Imagineer-Zoom", - "Gray Matter", - "Zamuse", - "Falcom", - NULL, - "Capcom", - "Hot B Co.", - "Jaleco", - "Coconuts Japan", - "Coconuts Japan/G.X.Media", - "Micronet", - "Technos", - "Mebio Software", - "Shouei System", - "Starfish", - NULL, - "Mitsui Fudosan/Dentsu", - NULL, - "Warashi Inc.", - NULL, - "Nowpro", - NULL, - "Game Village", - "IE Institute", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Banarex", - "Starfish", - "Infocom", - "Electronic Arts Japan", - NULL, - "Cobra Team", - "Human/Field", - "KOEI", - "Hudson Soft", - "S.C.P./Game Village", - "Yanoman", - NULL, - "Tecmo Products", - "Japan Glary Business", - "Forum/OpenSystem", - "Virgin Games (Japan)", - "SMDE", - "Yojigen", - NULL, - "Daikokudenki", - NULL, - NULL, - NULL, - NULL, - NULL, - "Creatures Inc.", - "TDK Deep Impresion", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Destination Software/KSS", - "Sunsoft/Tokai Engineering", - "POW (Planning Office Wada)/VR 1 Japan", - "Micro World", - NULL, - "San-X", - "Enix", - "Loriciel/Electro Brain", - "Kemco Japan", - "Seta Co.,Ltd.", - "Culture Brain", - "Irem Corp.", - "Palsoft", - "Visit Co., Ltd.", - "Intec", - "System Sacom", - "Poppo", - "Ubisoft Japan", - NULL, - "Media Works", - "NEC InterChannel", - "Tam", - "Gajin/Jordan", - "Smilesoft", - NULL, - NULL, - "Mediakite", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Viacom", - "Carrozzeria", - "Dynamic", - NULL, - "Magifact", - "Hect", - "Codemasters", - "Taito/GAGA Communications", - "Laguna", - "Telstar Fun & Games/Event/Taito", - NULL, - "Arcade Zone Ltd.", - "Entertainment International/Empire Software", - "Loriciel", - "Gremlin Graphics", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Seika Corp.", - "UBI SOFT Entertainment Software", - "Sunsoft US", - NULL, - "Life Fitness", - NULL, - "System 3", - "Spectrum Holobyte", - NULL, - "Irem", - NULL, - "Raya Systems", - "Renovation Products", - "Malibu Games", - NULL, - "Eidos/U.S. Gold", - "Playmates Interactive", - NULL, - NULL, - "Fox Interactive", - "Time Warner Interactive", - NULL, - NULL, - NULL, - NULL, - NULL, - "Disney Interactive", - NULL, - "Black Pearl", - NULL, - "Advanced Productions", - NULL, - NULL, - "GT Interactive", - "RARE", - "Crave Entertainment", - "Absolute Entertainment", - "Acclaim", - "Activision", - "American Sammy", - "Take 2/GameTek", - "Hi Tech", - "LJN Ltd.", - NULL, - "Mattel", - NULL, - "Mindscape/Red Orb Entertainment", - "Romstar", - "Taxan", - "Midway/Tradewest", - NULL, - "American Softworks Corp.", - "Majesco Sales Inc.", - "3DO", - NULL, - NULL, - "Hasbro", - "NewKidCo", - "Telegames", - "Metro3D", - NULL, - "Vatical Entertainment", - "LEGO Media", - NULL, - "Xicat Interactive", - "Cryo Interactive", - NULL, - NULL, - "Red Storm Entertainment", - "Microids", - NULL, - "Conspiracy/Swing", - "Titus", - "Virgin Interactive", - "Maxis", - NULL, - "LucasArts Entertainment", - NULL, - NULL, - "Ocean", - NULL, - "Electronic Arts", - NULL, - "Laser Beam", - NULL, - NULL, - "Elite Systems", - "Electro Brain", - "The Learning Company", - "BBC", - NULL, - "Software 2000", - NULL, - "BAM! Entertainment", - "Studio 3", - NULL, - NULL, - NULL, - "Classified Games", - NULL, - "TDK Mediactive", - NULL, - "DreamCatcher", - "JoWood Produtions", - "SEGA", - "Wannado Edition", - "LSP (Light & Shadow Prod.)", - "ITE Media", - "Infogrames", - "Interplay", - "JVC (US)", - "Parker Brothers", - NULL, - "SCI (Sales Curve Interactive)/Storm", - NULL, - NULL, - "THQ Software", - "Accolade Inc.", - "Triffix Entertainment", - NULL, - "Microprose Software", - "Universal Interactive/Sierra/Simon & Schuster", - NULL, - "Kemco", - "Rage Software", - "Encore", - NULL, - "Zoo", - "Kiddinx", - "Simon & Schuster Interactive", - "Asmik Ace Entertainment Inc./AIA", - "Empire Interactive", - NULL, - NULL, - "Jester Interactive", - NULL, - "Rockstar Games", - "Scholastic", - "Ignition Entertainment", - "Summitsoft", - "Stadlbauer", - NULL, - NULL, - NULL, - "Misawa", - "Teichiku", - "Namco Ltd.", - "LOZC", - "KOEI", - NULL, - "Tokuma Shoten Intermedia", - "Tsukuda Original", - "DATAM-Polystar", - NULL, - NULL, - "Bullet-Proof Software", - "Vic Tokai Inc.", - NULL, - "Character Soft", - "I'Max", - "Saurus", - NULL, - NULL, - "General Entertainment", - NULL, - NULL, - "I'Max", - "Success", - NULL, - "SEGA Japan", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Takara", - "Chun Soft", - "Video System Co., Ltd./McO'River", - "BEC", - NULL, - "Varie", - "Yonezawa/S'pal", - "Kaneko", - NULL, - "Victor Interactive Software/Pack-in-Video", - "Nichibutsu/Nihon Bussan", - "Tecmo", - "Imagineer", - NULL, - NULL, - "Nova", - "Den'Z", - "Bottom Up", - NULL, - "TGL (Technical Group Laboratory)", - NULL, - "Hasbro Japan", - NULL, - "Marvelous Entertainment", - NULL, - "Keynet Inc.", - "Hands-On Entertainment", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Telenet", - "Hori", - NULL, - NULL, - "Konami", - "K.Amusement Leasing Co.", - "Kawada", - "Takara", - NULL, - "Technos Japan Corp.", - "JVC (Europe/Japan)/Victor Musical Industries", - NULL, - "Toei Animation", - "Toho", - NULL, - "Namco", - "Media Rings Corp.", - "J-Wing", - NULL, - "Pioneer LDC", - "KID", - "Mediafactory", - NULL, - NULL, - NULL, - "Infogrames Hudson", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Acclaim Japan", - "ASCII Co./Nexoft", - "Bandai", - NULL, - "Enix", - NULL, - "HAL Laboratory/Halken", - "SNK", - NULL, - "Pony Canyon Hanbai", - "Culture Brain", - "Sunsoft", - "Toshiba EMI", - "Sony Imagesoft", - NULL, - "Sammy", - "Magical", - "Visco", - NULL, - "Compile", - NULL, - "MTO Inc.", - NULL, - "Sunrise Interactive", - NULL, - "Global A Entertainment", - "Fuuki", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Taito", - NULL, - "Kemco", - "Square", - "Tokuma Shoten", - "Data East", - "Tonkin House", - NULL, - "KOEI", - NULL, - "Konami/Ultra/Palcom", - "NTVIC/VAP", - "Use Co., Ltd.", - "Meldac", - "Pony Canyon (Japan)/FCI (US)", - "Angel/Sotsu Agency/Sunrise", - "Yumedia/Aroma Co., Ltd.", - NULL, - NULL, - "Boss", - "Axela/Crea-Tech", - "Sekaibunka-Sha/Sumire kobo/Marigul Management Inc.", - "Konami Computer Entertainment Osaka", - NULL, - NULL, - "Enterbrain", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Taito/Disco", - "Sofel", - "Quest Corp.", - "Sigma", - "Ask Kodansha", - NULL, - "Naxat", - "Copya System", - "Capcom Co., Ltd.", - "Banpresto", - "TOMY", - "Acclaim/LJN Japan", - NULL, - "NCS", - "Human Entertainment", - "Altron", - "Jaleco", - "Gaps Inc.", - NULL, - NULL, - NULL, - NULL, - NULL, - "Elf", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Jaleco", - NULL, - "Yutaka", - "Varie", - "T&ESoft", - "Epoch Co., Ltd.", - NULL, - "Athena", - "Asmik", - "Natsume", - "King Records", - "Atlus", - "Epic/Sony Records (Japan)", - NULL, - "IGS (Information Global Service)", - NULL, - "Chatnoir", - "Right Stuff", - NULL, - "NTT COMWARE", - NULL, - "Spike", - "Konami Computer Entertainment Tokyo", - "Alphadream Corp.", - NULL, - "Sting", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "A Wave", - "Motown Software", - "Left Field Entertainment", - "Extreme Entertainment Group", - "TecMagik", - NULL, - NULL, - NULL, - NULL, - "Cybersoft", - NULL, - "Psygnosis", - NULL, - NULL, - "Davidson/Western Tech.", - "Unlicensed", - NULL, - NULL, - NULL, - NULL, - "The Game Factory Europe", - "Hip Games", - "Aspyr", - NULL, - NULL, - "Mastiff", - "iQue", - "Digital Tainment Pool", - "XS Games", - "Daiwon", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "PCCW Japan", - NULL, - NULL, - "KiKi Co. Ltd.", - "Open Sesame Inc.", - "Sims", - "Broccoli", - "Avex", - "D3 Publisher", - NULL, - "Konami Computer Entertainment Japan", - NULL, - "Square-Enix", - "KSG", - "Micott & Basara Inc.", - NULL, - "Orbital Media", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "The Game Factory USA", - NULL, - NULL, - "Treasure", - "Aruze", - "Ertain", - "SNK Playmore", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "Yojigen" -}; +static char LastRomFilename[_MAX_PATH + 1] = ""; static const uint32 crc32Table[256] = { @@ -931,18 +302,20 @@ static bool8 is_SufamiTurbo_Cart (uint8 *, uint32); static bool8 is_SameGame_BIOS (uint8 *, uint32); static bool8 is_SameGame_Add_On (uint8 *, uint32); static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); +#ifndef NGC static long ReadInt (Reader *, unsigned); static bool8 ReadIPSPatch (Reader *, long, int32 &); -#ifdef UNZIP_SUPPORT static int unzFindExtension (unzFile &, const char *, bool restart = TRUE, bool print = TRUE); #endif - // deinterleave static void S9xDeinterleaveType1 (int size, uint8 *base) { - Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); - SET_UI_COLOR(0, 255, 0); + if (Settings.DisplayColor == 0xffff) + { + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); + } uint8 blocks[256]; int nblocks = size >> 16; @@ -953,7 +326,7 @@ static void S9xDeinterleaveType1 (int size, uint8 *base) blocks[i * 2 + 1] = i; } - uint8 *tmp = (uint8 *) malloc(0x8000); + uint8 *tmp = (uint8 *) memalign(32, 0x8000); if (tmp) { for (int i = 0; i < nblocks * 2; i++) @@ -980,8 +353,11 @@ static void S9xDeinterleaveType1 (int size, uint8 *base) static void S9xDeinterleaveType2 (int size, uint8 *base) { // for odd Super FX images - Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); - SET_UI_COLOR(255, 119, 25); + if (Settings.DisplayColor == 0xffff || Settings.DisplayColor == BUILD_PIXEL(0, 31, 0)) + { + Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); + SET_UI_COLOR(255, 119, 25); + } uint8 blocks[256]; int nblocks = size >> 16; @@ -994,7 +370,7 @@ static void S9xDeinterleaveType2 (int size, uint8 *base) for (int i = 0; i < nblocks * 2; i++) blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2); - uint8 *tmp = (uint8 *) malloc(0x10000); + uint8 *tmp = (uint8 *) memalign(32, 0x10000); if (tmp) { for (int i = 0; i < nblocks * 2; i++) @@ -1024,10 +400,13 @@ static void S9xDeinterleaveGD24 (int size, uint8 *base) if (size != 0x300000) return; - Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); - SET_UI_COLOR(0, 255, 255); + if (Settings.DisplayColor == 0xffff) + { + Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); + SET_UI_COLOR(0, 255, 255); + } - uint8 *tmp = (uint8 *) malloc(0x80000); + uint8 *tmp = (uint8 *) memalign(32, 0x80000); if (tmp) { memmove(tmp, &base[0x180000], 0x80000); @@ -1045,26 +424,26 @@ static void S9xDeinterleaveGD24 (int size, uint8 *base) bool8 CMemory::Init (void) { - RAM = (uint8 *) malloc(0x20000); - SRAM = (uint8 *) malloc(0x20000); - VRAM = (uint8 *) malloc(0x10000); - ROM = (uint8 *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000); + RAM = (uint8 *) memalign(32, 0x20000); + SRAM = (uint8 *) memalign(32, 0x20000); + VRAM = (uint8 *) memalign(32, 0x10000); + ROM = (uint8 *) memalign(32, MAX_ROM_SIZE + 0x200 + 0x8000); - IPPU.TileCache[TILE_2BIT] = (uint8 *) malloc(MAX_2BIT_TILES * 64); - IPPU.TileCache[TILE_4BIT] = (uint8 *) malloc(MAX_4BIT_TILES * 64); - IPPU.TileCache[TILE_8BIT] = (uint8 *) malloc(MAX_8BIT_TILES * 64); - IPPU.TileCache[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES * 64); - IPPU.TileCache[TILE_2BIT_ODD] = (uint8 *) malloc(MAX_2BIT_TILES * 64); - IPPU.TileCache[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES * 64); - IPPU.TileCache[TILE_4BIT_ODD] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT] = (uint8 *) memalign(32, MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT] = (uint8 *) memalign(32, MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_8BIT] = (uint8 *) memalign(32, MAX_8BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_EVEN] = (uint8 *) memalign(32, MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_ODD] = (uint8 *) memalign(32, MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_EVEN] = (uint8 *) memalign(32, MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_ODD] = (uint8 *) memalign(32, MAX_4BIT_TILES * 64); - IPPU.TileCached[TILE_2BIT] = (uint8 *) malloc(MAX_2BIT_TILES); - IPPU.TileCached[TILE_4BIT] = (uint8 *) malloc(MAX_4BIT_TILES); - IPPU.TileCached[TILE_8BIT] = (uint8 *) malloc(MAX_8BIT_TILES); - IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES); - IPPU.TileCached[TILE_2BIT_ODD] = (uint8 *) malloc(MAX_2BIT_TILES); - IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES); - IPPU.TileCached[TILE_4BIT_ODD] = (uint8 *) malloc(MAX_4BIT_TILES); + IPPU.TileCached[TILE_2BIT] = (uint8 *) memalign(32, MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT] = (uint8 *) memalign(32, MAX_4BIT_TILES); + IPPU.TileCached[TILE_8BIT] = (uint8 *) memalign(32, MAX_8BIT_TILES); + IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) memalign(32, MAX_2BIT_TILES); + IPPU.TileCached[TILE_2BIT_ODD] = (uint8 *) memalign(32, MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) memalign(32, MAX_4BIT_TILES); + IPPU.TileCached[TILE_4BIT_ODD] = (uint8 *) memalign(32, MAX_4BIT_TILES); if (!RAM || !SRAM || !VRAM || !ROM || !IPPU.TileCache[TILE_2BIT] || @@ -1118,7 +497,6 @@ bool8 CMemory::Init (void) ROM += 0x8000; C4RAM = ROM + 0x400000 + 8192 * 8; // C4 - OBC1RAM = ROM + 0x400000; // OBC1 BIOSROM = ROM + 0x300000; // BS BSRAM = ROM + 0x400000; // BS @@ -1138,6 +516,9 @@ bool8 CMemory::Init (void) SuperFX.pvRom = (uint8 *) ROM; #endif + SDD1Data = NULL; + SDD1Index = NULL; + PostRomInitFunc = NULL; return (TRUE); @@ -1145,6 +526,12 @@ bool8 CMemory::Init (void) void CMemory::Deinit (void) { + // XXX: Please remove port specific codes +#ifdef __W32_HEAP + if (_HEAPOK! = _heapchk()) + MessageBox(GUI.hWnd, "CMemory::Deinit", "Heap Corrupt", MB_OK); +#endif + if (RAM) { free(RAM); @@ -1185,10 +572,27 @@ void CMemory::Deinit (void) } } + FreeSDD1Data(); + Safe(NULL); SafeANK(NULL); } +void CMemory::FreeSDD1Data (void) +{ + if (SDD1Index) + { + free(SDD1Index); + SDD1Index = NULL; + } + + if (SDD1Data) + { + free(SDD1Data); + SDD1Data = NULL; + } +} + // file management and ROM detection static bool8 allASCII (uint8 *b, int size) @@ -1359,136 +763,7 @@ uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf) return (size); } -uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) -{ - // <- ROM size without header - // ** Memory.HeaderCount - // ** Memory.ROMFilename - int32 totalSize = 0; - char fname[PATH_MAX + 1]; - char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1]; - char *ext; - -#if defined(__WIN32__) || defined(__MACOSX__) - ext = &exts[1]; -#else - ext = &exts[0]; -#endif - - memset(NSRTHeader, 0, sizeof(NSRTHeader)); - HeaderCount = 0; - - _splitpath(filename, drive, dir, name, exts); - _makepath(fname, drive, dir, name, exts); - - int nFormat = FILE_DEFAULT; - if (strcasecmp(ext, "zip") == 0) - nFormat = FILE_ZIP; - else - if (strcasecmp(ext, "jma") == 0) - nFormat = FILE_JMA; - - switch (nFormat) - { - case FILE_ZIP: - { - #ifdef UNZIP_SUPPORT - if (!LoadZip(fname, &totalSize, &HeaderCount, buffer)) - { - S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive."); - return (0); - } - - strcpy(ROMFilename, fname); - #else - S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support."); - return (0); - #endif - break; - } - - case FILE_JMA: - { - #ifdef JMA_SUPPORT - size_t size = load_jma_file(fname, buffer); - if (!size) - { - S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive."); - return (0); - } - - totalSize = HeaderRemove(size, HeaderCount, buffer); - - strcpy(ROMFilename, fname); - #else - S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support."); - return (0); - #endif - break; - } - - case FILE_DEFAULT: - default: - { - STREAM fp = OPEN_STREAM(fname, "rb"); - if (!fp) - return (0); - - strcpy(ROMFilename, fname); - - int len = 0; - uint32 size = 0; - bool8 more = FALSE; - uint8 *ptr = buffer; - - do - { - size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp); - CLOSE_STREAM(fp); - - size = HeaderRemove(size, HeaderCount, ptr); - totalSize += size; - ptr += size; - - // check for multi file roms - if (ptr - buffer < maxsize + 0x200 && - (isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9')) - { - more = TRUE; - ext[0]++; - _makepath(fname, drive, dir, name, exts); - } - else - if (ptr - buffer < maxsize + 0x200 && - (((len = strlen(name)) == 7 || len == 8) && - strncasecmp(name, "sf", 2) == 0 && - isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) && - isalpha(name[len - 1]))) - { - more = TRUE; - name[len - 1]++; - _makepath(fname, drive, dir, name, exts); - } - else - more = FALSE; - - } while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL); - - break; - } - } - - if (HeaderCount == 0) - S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); - else - if (HeaderCount == 1) - S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it)."); - else - S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them)."); - - return ((uint32) totalSize); -} bool8 CMemory::LoadROM (const char *filename) { @@ -1497,11 +772,13 @@ bool8 CMemory::LoadROM (const char *filename) if (!filename || !*filename) return (FALSE); +#ifndef NGC ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); - +#endif /* you don't want to do that: ROM already loaded */ + again: - Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); + Settings.DisplayColor = 0xffff; SET_UI_COLOR(255, 255, 255); CalculatedSize = 0; @@ -1509,22 +786,13 @@ again: int32 totalFileSize; -#ifdef GEKKO - totalFileSize = WiiFileLoader(); -#else totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); -#endif - if (!totalFileSize) return (FALSE); - +#ifndef NGC if (!Settings.NoPatch) -#ifdef GEKKO - WiiLoadPatch(); -#else CheckForIPSPatch(filename, HeaderCount != 0, totalFileSize); #endif - int hi_score, lo_score; hi_score = ScoreHiROM(FALSE); @@ -1551,12 +819,18 @@ again: (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a) ExtendedFormat = YEAH; - // if both vectors are invalid, it's type 1 interleaved LoROM + // if both vectors are invalid, it's type 1 LoROM if (ExtendedFormat == NOPE && ((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) && ((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000)) { - if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved) + if (Settings.DisplayColor == 0xffff) + { + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); + } + + if (!Settings.ForceInterleaved) S9xDeinterleaveType1(totalFileSize, ROM); } @@ -1587,7 +861,7 @@ again: bool8 interleaved, tales = FALSE; - interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24; + interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) { @@ -1701,7 +975,7 @@ again: if (tales) { - uint8 *tmp = (uint8 *) malloc(CalculatedSize - 0x400000); + uint8 *tmp = (uint8 *) memalign(32, CalculatedSize - 0x400000); if (tmp) { S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM..."); @@ -1712,29 +986,178 @@ again: } } - if (strncmp(LastRomFilename, filename, PATH_MAX + 1)) + if (strncmp(LastRomFilename, filename, _MAX_PATH)) { - strncpy(LastRomFilename, filename, PATH_MAX + 1); - LastRomFilename[PATH_MAX] = 0; + strncpy(LastRomFilename, filename, _MAX_PATH); + LastRomFilename[_MAX_PATH] = 0; } + FreeSDD1Data(); + if (CleanUp7110) + (*CleanUp7110)(); + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; -#ifdef GEKKO - WiiSetupCheats(); -#else - S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + +#ifndef NGC + S9xLoadCheatFile(S9xGetFilename(".cht", PATCH_DIR)); #endif + InitROM(); S9xInitCheatData(); +#ifndef NGC S9xApplyCheats(); +#endif S9xReset(); return (TRUE); } +uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) +{ + // <- ROM size without header + // ** Memory.HeaderCount + // ** Memory.ROMFilename + + int32 totalSize = 0; +#ifndef NGC + char fname[_MAX_PATH + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1]; + char *ext; + +#if defined(__WIN32__) || defined(__MACOSX__) + ext = &exts[1]; +#else + ext = &exts[0]; +#endif +#endif + + memset(NSRTHeader, 0, sizeof(NSRTHeader)); + HeaderCount = 0; +#ifndef NGC + _splitpath(filename, drive, dir, name, exts); + _makepath(fname, drive, dir, name, exts); + int nFormat = FILE_DEFAULT; + if (strcasecmp(ext, "zip") == 0) + nFormat = FILE_ZIP; + else + if (strcasecmp(ext, "jma") == 0) + nFormat = FILE_JMA; + + switch (nFormat) + { + case FILE_ZIP: + { +#ifdef UNZIP_SUPPORT + if (!LoadZip(fname, &totalSize, &HeaderCount, buffer)) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive."); + return (0); + } + + strcpy(ROMFilename, fname); +#else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support."); + return (0); +#endif + break; + } + + case FILE_JMA: + { +#ifdef JMA_SUPPORT + size_t size = load_jma_file(fname, buffer); + if (!size) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive."); + return (0); + } + + totalSize = HeaderRemove(size, HeaderCount, buffer); + + strcpy(ROMFilename, fname); +#else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support."); + return (0); +#endif + break; + } + + case FILE_DEFAULT: + default: + { + STREAM fp = OPEN_STREAM(fname, "rb"); + if (!fp) + return (0); + + strcpy(ROMFilename, fname); + + int len = 0; + uint32 size = 0; + bool8 more = FALSE; + uint8 *ptr = buffer; + + do + { + size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp); + CLOSE_STREAM(fp); + + size = HeaderRemove(size, HeaderCount, ptr); + totalSize += size; + ptr += size; + + // check for multi file roms + if (ptr - buffer < maxsize + 0x200 && + (isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9')) + { + more = TRUE; + ext[0]++; + _makepath(fname, drive, dir, name, exts); + } + else + if (ptr - buffer < maxsize + 0x200 && + (((len = strlen(name)) == 7 || len == 8) && + strncasecmp(name, "sf", 2) == 0 && + isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) && + isalpha(name[len - 1]))) + { + more = TRUE; + name[len - 1]++; + _makepath(fname, drive, dir, name, exts); + } + else + more = FALSE; + + } while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL); + + break; + } + +#else + /*** Nintendo Wii/Gamecube ROM File Loader + By now we've already loaded the ROM into main memory + This is simply a modified version of FILE_DEFAULT + ***/ + HeaderCount = 0; + uint8 *ptr = buffer; + uint32 size = SNESROMSize; + + size = HeaderRemove(size, HeaderCount, ptr); + ptr += size; + totalSize += size; +#endif + if (HeaderCount == 0) + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); + else + if (HeaderCount == 1) + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it)."); + else + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them)."); + + return ((uint32) totalSize); +} bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) { bool8 r = TRUE; @@ -1742,7 +1165,7 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); - Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); + Settings.DisplayColor = 0xffff; SET_UI_COLOR(255, 255, 255); CalculatedSize = 0; @@ -1794,15 +1217,23 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) return (FALSE); } + FreeSDD1Data(); + if (CleanUp7110) + (*CleanUp7110)(); + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; - S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); +#ifndef NGC + S9xLoadCheatFile(S9xGetFilename(".cht", PATCH_DIR)); +#endif InitROM(); S9xInitCheatData(); +#ifndef NGC S9xApplyCheats(); +#endif S9xReset(); @@ -1821,9 +1252,10 @@ bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) Multi.sramSizeA = 4; // ROM[0x37]? Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; - if (!Settings.NoPatch) +#ifndef NGC + if (!Settings.NoPatch) CheckForIPSPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - +#endif strcpy(Multi.fileNameA, cartA); memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); } @@ -1845,16 +1277,17 @@ bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) Multi.sramSizeB = 4; // ROM[0x37]? Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0; +#ifndef NGC if (!Settings.NoPatch) CheckForIPSPatch(cartB, HeaderCount != 0, Multi.cartSizeB); - +#endif strcpy(Multi.fileNameB, cartB); memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB); } FILE *fp; size_t size; - char path[PATH_MAX + 1]; + char path[_MAX_PATH + 1]; strcpy(path, S9xGetDirectory(BIOS_DIR)); strcat(path, SLASH_STR); @@ -1898,9 +1331,10 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) Multi.sramSizeB = 0; Multi.sramMaskB = 0; +#ifndef NGC if (!Settings.NoPatch) CheckForIPSPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - +#endif strcpy(Multi.fileNameA, cartA); if (cartB && cartB[0]) @@ -1923,37 +1357,23 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadSRTC (void) +bool8 CMemory::LoadLastROM (void) { - FILE *fp; - - fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb"); - if (!fp) + if (Multi.cartType) return (FALSE); - fread(RTCData.reg, 1, 20, fp); - fclose(fp); + bool8 r; - return (TRUE); -} + stopMovie = FALSE; + r = LoadROM(LastRomFilename); + stopMovie = TRUE; -bool8 CMemory::SaveSRTC (void) -{ - FILE *fp; - - fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb"); - if (!fp) - return (FALSE); - - fwrite(RTCData.reg, 1, 20, fp); - fclose(fp); - - return (TRUE); + return (r); } void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) { - if (onlyNonSavedSRAM) + if(onlyNonSavedSRAM) if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM return; @@ -1962,17 +1382,18 @@ void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) bool8 CMemory::LoadSRAM (const char *filename) { + ClearSRAM(); + +#ifndef NGC FILE *file; int size, len; - char sramName[PATH_MAX + 1]; - + char sramName[_MAX_PATH + 1]; strcpy(sramName, filename); - ClearSRAM(); if (Multi.cartType && Multi.sramSizeB) { - char temp[PATH_MAX + 1]; + char temp[_MAX_PATH + 1]; strcpy(temp, ROMFilename); strcpy(ROMFilename, Multi.fileNameB); @@ -2005,8 +1426,18 @@ bool8 CMemory::LoadSRAM (const char *filename) if (len - size == 512) memmove(SRAM, SRAM + 512, size); - if (Settings.SRTC || Settings.SPC7110RTC) - LoadSRTC(); + if (len == size + SRTC_SRAM_PAD) + { + S9xSRTCPostLoadState(); + S9xResetSRTC(); + rtc.index = -1; + rtc.mode = MODE_READ; + } + else + S9xHardResetSRTC(); + + if (Settings.SPC7110RTC) + S9xLoadSPC7110RTC(&rtc_f9); return (TRUE); } @@ -2015,7 +1446,7 @@ bool8 CMemory::LoadSRAM (const char *filename) { // The BS game's SRAM was not found // Try to read BS-X.srm instead - char path[PATH_MAX + 1]; + char path[_MAX_PATH + 1]; strcpy(path, S9xGetDirectory(SRAM_DIR)); strcat(path, SLASH_STR); @@ -2030,18 +1461,25 @@ bool8 CMemory::LoadSRAM (const char *filename) memmove(SRAM, SRAM + 512, size); S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead."); + S9xHardResetSRTC(); return (TRUE); } else { S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found, BS-X.srm wasn't found either."); + S9xHardResetSRTC(); return (FALSE); } } + S9xHardResetSRTC(); return (FALSE); } + if (Settings.SDD1) + S9xSDD1LoadLoggedData(); +#endif + return (TRUE); } @@ -2055,13 +1493,13 @@ bool8 CMemory::SaveSRAM (const char *filename) FILE *file; int size; - char sramName[PATH_MAX + 1]; + char sramName[_MAX_PATH + 1]; strcpy(sramName, filename); if (Multi.cartType && Multi.sramSizeB) { - char name[PATH_MAX + 1], temp[PATH_MAX + 1]; + char name[_MAX_PATH + 1], temp[_MAX_PATH + 1]; strcpy(temp, ROMFilename); strcpy(ROMFilename, Multi.fileNameB); @@ -2074,15 +1512,25 @@ bool8 CMemory::SaveSRAM (const char *filename) { fwrite((char *) Multi.sramB, size, 1, file); fclose(file); - #ifdef __linux +#ifdef __linux chown(name, getuid(), getgid()); - #endif +#endif } strcpy(ROMFilename, temp); } size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; + + if (Settings.SRTC) + { + size += SRTC_SRAM_PAD; + S9xSRTCPreSaveState(); + } + + if (Settings.SDD1) + S9xSDD1SaveLoggedData(); + if (size > 0x20000) size = 0x20000; @@ -2093,12 +1541,11 @@ bool8 CMemory::SaveSRAM (const char *filename) { fwrite((char *) SRAM, size, 1, file); fclose(file); - #ifdef __linux +#ifdef __linux chown(sramName, getuid(), getgid()); - #endif - - if (Settings.SRTC || Settings.SPC7110RTC) - SaveSRTC(); +#endif + if (Settings.SPC7110RTC) + S9xSaveSPC7110RTC(&rtc_f9); return (TRUE); } @@ -2140,7 +1587,7 @@ char * CMemory::Safe (const char *s) free(safe); safe_len = len + 1; - safe = (char *) malloc(safe_len); + safe = (char *) memalign(32, safe_len); } for (int i = 0; i < len; i++) @@ -2179,7 +1626,7 @@ char * CMemory::SafeANK (const char *s) free(safe); safe_len = len + 1; - safe = (char *) malloc(safe_len); + safe = (char *) memalign(32, safe_len); } for (int i = 0; i < len; i++) @@ -2208,9 +1655,9 @@ void CMemory::ParseSNESHeader (uint8 *RomHeader) if (bs) { - if (!(((RomHeader[0x29] & 0x20) && CalculatedSize < 0x100000) || + /*if (!(((RomHeader[0x29] & 0x20) && CalculatedSize < 0x100000) || (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000))) - printf("BS: Size mismatch\n"); + printf("BS: Size mismatch\n");*/ // FIXME int p = 0; @@ -2231,42 +1678,34 @@ void CMemory::ParseSNESHeader (uint8 *RomHeader) memmove(ROMId, &RomHeader[0x02], 4); - if (RomHeader[0x2A] != 0x33) - CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F); + if (RomHeader[0x2A] == 0x33) + memmove(CompanyId, &RomHeader[0x00], 2); else - if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01])) - { - int l, r, l2, r2; - l = toupper(RomHeader[0x00]); - r = toupper(RomHeader[0x01]); - l2 = (l > '9') ? l - '7' : l - '0'; - r2 = (r > '9') ? r - '7' : r - '0'; - CompanyId = l2 * 36 + r2; - } + sprintf(CompanyId, "%02X", RomHeader[0x2A]); } void CMemory::InitROM (void) { + Settings.DSP1Master = FALSE; Settings.SuperFX = FALSE; - Settings.DSP = 0; Settings.SA1 = FALSE; Settings.C4 = FALSE; Settings.SDD1 = FALSE; + Settings.SRTC = FALSE; Settings.SPC7110 = FALSE; Settings.SPC7110RTC = FALSE; - Settings.OBC1 = FALSE; - Settings.SETA = 0; - Settings.SRTC = FALSE; Settings.BS = FALSE; + Settings.OBC1 = FALSE; + Settings.SETA = FALSE; #ifndef ZSNES_FX SuperFX.nRomBanks = CalculatedSize >> 15; #endif - SA1.Executing = FALSE; + s7r.DataRomSize = 0; //// Parse ROM header and read ROM informatoin - CompanyId = -1; memset(ROMId, 0, 5); + memset(CompanyId, 0, 3); uint8 *RomHeader = ROM + 0x7FB0; if (ExtendedFormat == BIGFIRST) @@ -2282,66 +1721,73 @@ void CMemory::InitROM (void) //// detection codes are compatible with NSRT // DSP1/2/3/4 + Settings.DSP1Master = Settings.ForceDSP1; + DSP1.version = 0xff; + if (ROMType == 0x03) { if (ROMSpeed == 0x30) - Settings.DSP = 4; // DSP4 + DSP1.version = 3; // DSP4 else - Settings.DSP = 1; // DSP1 + DSP1.version = 0; // DSP1 } else if (ROMType == 0x05) { if (ROMSpeed == 0x20) - Settings.DSP = 2; // DSP2 + DSP1.version = 1; // DSP2 else if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2) - Settings.DSP = 3; // DSP3 + DSP1.version = 2; // DSP3 else - Settings.DSP = 1; // DSP1 + DSP1.version = 0; // DSP1 } - switch (Settings.DSP) + if (DSP1.version != 0xff) + Settings.DSP1Master = !Settings.ForceNoDSP1; + + switch (DSP1.version) { - case 1: // DSP1 + case 0: // DSP1 if (HiROM) { - DSP0.boundary = 0x7000; - DSP0.maptype = M_DSP1_HIROM; + DSP1.boundary = 0x7000; + DSP1.maptype = M_DSP1_HIROM; } else if (CalculatedSize > 0x100000) { - DSP0.boundary = 0x4000; - DSP0.maptype = M_DSP1_LOROM_L; + DSP1.boundary = 0x4000; + DSP1.maptype = M_DSP1_LOROM_L; } else { - DSP0.boundary = 0xc000; - DSP0.maptype = M_DSP1_LOROM_S; + DSP1.boundary = 0xc000; + DSP1.maptype = M_DSP1_LOROM_S; } SetDSP = &DSP1SetByte; GetDSP = &DSP1GetByte; break; - case 2: // DSP2 - DSP0.boundary = 0x10000; - DSP0.maptype = M_DSP2_LOROM; + case 1: // DSP2 + DSP1.boundary = 0x10000; + DSP1.maptype = M_DSP2_LOROM; SetDSP = &DSP2SetByte; GetDSP = &DSP2GetByte; break; - case 3: // DSP3 - DSP0.boundary = 0xc000; - DSP0.maptype = M_DSP3_LOROM; + case 2: // DSP3 + DSP1.boundary = 0xc000; + DSP1.maptype = M_DSP3_LOROM; SetDSP = &DSP3SetByte; GetDSP = &DSP3GetByte; + DSP3_Reset(); break; - case 4: // DSP4 - DSP0.boundary = 0xc000; - DSP0.maptype = M_DSP4_LOROM; + case 3: // DSP4 + DSP1.boundary = 0xc000; + DSP1.maptype = M_DSP4_LOROM; SetDSP = &DSP4SetByte; GetDSP = &DSP4GetByte; break; @@ -2352,6 +1798,11 @@ void CMemory::InitROM (void) break; } + Settings.SA1 = Settings.ForceSA1; + Settings.SuperFX = Settings.ForceSuperFX; + Settings.SDD1 = Settings.ForceSDD1; + Settings.C4 = Settings.ForceC4; + uint32 identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff); switch (identifier) @@ -2359,7 +1810,6 @@ void CMemory::InitROM (void) // SRTC case 0x5535: Settings.SRTC = TRUE; - S9xInitSRTC(); break; // SPC7110 @@ -2367,7 +1817,7 @@ void CMemory::InitROM (void) Settings.SPC7110RTC = TRUE; case 0xF53A: Settings.SPC7110 = TRUE; - S9xInitSPC7110(); + S9xSpc7110Init(); break; // OBC1 @@ -2378,7 +1828,7 @@ void CMemory::InitROM (void) // SA1 case 0x3423: case 0x3523: - Settings.SA1 = TRUE; + Settings.SA1 = !Settings.ForceNoSA1; break; // SuperFX @@ -2386,20 +1836,23 @@ void CMemory::InitROM (void) case 0x1420: case 0x1520: case 0x1A20: - Settings.SuperFX = TRUE; - #ifndef ZSNES_FX - S9xInitSuperFX(); - #endif - if (ROM[0x7FDA] == 0x33) - SRAMSize = ROM[0x7FBD]; - else - SRAMSize = 5; + Settings.SuperFX = !Settings.ForceNoSuperFX; + if (Settings.SuperFX) + { + if (ROM[0x7FDA] == 0x33) + SRAMSize = ROM[0x7FBD]; + else + SRAMSize = 5; + } + break; // SDD1 case 0x4332: case 0x4532: - Settings.SDD1 = TRUE; + Settings.SDD1 = !Settings.ForceNoSDD1; + if (Settings.SDD1) + S9xLoadSDD1Data(); break; // ST018 @@ -2432,7 +1885,7 @@ void CMemory::InitROM (void) // C4 case 0xF320: - Settings.C4 = TRUE; + Settings.C4 = !Settings.ForceNoC4; break; } @@ -2572,8 +2025,11 @@ void CMemory::InitROM (void) // checksum if (!isChecksumOK || ((uint32) CalculatedSize > (uint32) (((1 << (ROMSize - 7)) * 128) * 1024))) { - Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); - SET_UI_COLOR(255, 255, 0); + if (Settings.DisplayColor == 0xffff || Settings.DisplayColor != BUILD_PIXEL(31, 0, 0)) + { + Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); + SET_UI_COLOR(255, 255, 0); + } } if (Multi.cartType == 4) @@ -2598,19 +2054,16 @@ void CMemory::InitROM (void) Possible delays: { 12, 14, 16, 18, 20, 22, 24 } XXX: Snes9x can't emulate this timing :( so let's use the average value... */ Timings.DMACPUSync = 18; - /* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger - after the DMA completes (even if /NMI goes high again before the DMA - completes). In this case, there is a 24-30 cycle delay between the end of DMA - and the NMI handler, time enough for an instruction or two. */ - // Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition - Timings.NMIDMADelay = 24; - Timings.IRQPendCount = 0; + + IAPU.OneCycle = SNES_APU_ONE_CYCLE_SCALED; CPU.FastROMSpeed = 0; ResetSpeedMap(); IPPU.TotalEmulatedFrames = 0; + Settings.Shutdown = Settings.ShutdownMaster; + //// Hack games ApplyROMFixes(); @@ -2622,28 +2075,34 @@ void CMemory::InitROM (void) sprintf(displayName, "%s", SafeANK(ROMName)); sprintf(ROMName, "%s", Safe(ROMName)); sprintf(ROMId, "%s", Safe(ROMId)); + sprintf(CompanyId, "%s", Safe(CompanyId)); - sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X", + sprintf(String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s CRC32: %08X", displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"), - MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32); + MapType(), Size(), KartContents(), MapMode(), TVStandard(), StaticRAMSize(), ROMId, CompanyId, ROMCRC32); S9xMessage(S9X_INFO, S9X_ROM_INFO, String); - Settings.ForceLoROM = FALSE; - Settings.ForceHiROM = FALSE; - Settings.ForceHeader = FALSE; - Settings.ForceNoHeader = FALSE; - Settings.ForceInterleaved = FALSE; - Settings.ForceInterleaved2 = FALSE; - Settings.ForceInterleaveGD24 = FALSE; - Settings.ForceNotInterleaved = FALSE; - Settings.ForcePAL = FALSE; - Settings.ForceNTSC = FALSE; + // XXX: Please remove port specific codes +#ifdef __WIN32__ +#ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_ROM_INFO, MF_ENABLED); +#endif +#ifdef RTC_DEBUGGER + if (Settings.SPC7110RTC) + EnableMenuItem(GUI.hMenu, IDM_7110_RTC, MF_ENABLED); + else + EnableMenuItem(GUI.hMenu, IDM_7110_RTC, MF_GRAYED); +#endif +#endif - Settings.TakeScreenshot = FALSE; + Settings.ForceHiROM = Settings.ForceLoROM = FALSE; + Settings.ForceHeader = Settings.ForceNoHeader = FALSE; + Settings.ForceInterleaved = Settings.ForceNotInterleaved = Settings.ForceInterleaved2 = FALSE; +#ifndef NGC if (stopMovie) S9xMovieStop(TRUE); - +#endif if (PostRomInitFunc) PostRomInitFunc(); @@ -2836,7 +2295,7 @@ void CMemory::map_HiROMSRAM (void) void CMemory::map_DSP (void) { - switch (DSP0.maptype) + switch (DSP1.maptype) { case M_DSP1_LOROM_S: map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); @@ -2926,7 +2385,7 @@ void CMemory::Map_Initialize (void) void CMemory::Map_LoROMMap (void) { - printf("Map_LoROMMap\n"); + //printf("Map_LoROMMap\n"); map_System(); map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -2934,7 +2393,7 @@ void CMemory::Map_LoROMMap (void) map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); - if (Settings.DSP) + if (Settings.DSP1Master) map_DSP(); else if (Settings.C4) @@ -2954,7 +2413,7 @@ void CMemory::Map_LoROMMap (void) void CMemory::Map_NoMAD1LoROMMap (void) { - printf("Map_NoMAD1LoROMMap\n"); + //printf("Map_NoMAD1LoROMMap\n"); map_System(); map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -2973,7 +2432,7 @@ void CMemory::Map_NoMAD1LoROMMap (void) void CMemory::Map_JumboLoROMMap (void) { // XXX: Which game uses this? - printf("Map_JumboLoROMMap\n"); + //printf("Map_JumboLoROMMap\n"); map_System(); map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); @@ -2990,7 +2449,7 @@ void CMemory::Map_JumboLoROMMap (void) void CMemory::Map_ROM24MBSLoROMMap (void) { // PCB: BSC-1A5M-01, BSC-1A7M-10 - printf("Map_ROM24MBSLoROMMap\n"); + //printf("Map_ROM24MBSLoROMMap\n"); map_System(); map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0); @@ -3006,7 +2465,7 @@ void CMemory::Map_ROM24MBSLoROMMap (void) void CMemory::Map_SRAM512KLoROMMap (void) { - printf("Map_SRAM512KLoROMMap\n"); + //printf("Map_SRAM512KLoROMMap\n"); map_System(); map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -3026,7 +2485,7 @@ void CMemory::Map_SRAM512KLoROMMap (void) void CMemory::Map_SufamiTurboLoROMMap (void) { - printf("Map_SufamiTurboLoROMMap\n"); + //printf("Map_SufamiTurboLoROMMap\n"); map_System(); map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); @@ -3056,7 +2515,7 @@ void CMemory::Map_SufamiTurboLoROMMap (void) void CMemory::Map_SufamiTurboPseudoLoROMMap (void) { // for combined images - printf("Map_SufamiTurboPseudoLoROMMap\n"); + //printf("Map_SufamiTurboPseudoLoROMMap\n"); map_System(); map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); @@ -3079,7 +2538,7 @@ void CMemory::Map_SufamiTurboPseudoLoROMMap (void) void CMemory::Map_SuperFXLoROMMap (void) { - printf("Map_SuperFXLoROMMap\n"); + //printf("Map_SuperFXLoROMMap\n"); map_System(); // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K @@ -3108,7 +2567,7 @@ void CMemory::Map_SuperFXLoROMMap (void) void CMemory::Map_SetaDSPLoROMMap (void) { - printf("Map_SetaDSPLoROMMap\n"); + //printf("Map_SetaDSPLoROMMap\n"); map_System(); map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -3126,7 +2585,7 @@ void CMemory::Map_SetaDSPLoROMMap (void) void CMemory::Map_SDD1LoROMMap (void) { - printf("Map_SDD1LoROMMap\n"); + //printf("Map_SDD1LoROMMap\n"); map_System(); map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -3144,7 +2603,7 @@ void CMemory::Map_SDD1LoROMMap (void) void CMemory::Map_SA1LoROMMap (void) { - printf("Map_SA1LoROMMap\n"); + //printf("Map_SA1LoROMMap\n"); map_System(); map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -3186,7 +2645,7 @@ void CMemory::Map_SA1LoROMMap (void) void CMemory::Map_HiROMMap (void) { - printf("Map_HiROMMap\n"); + //printf("Map_HiROMMap\n"); map_System(); map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); @@ -3194,7 +2653,7 @@ void CMemory::Map_HiROMMap (void) map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); - if (Settings.DSP) + if (Settings.DSP1Master) map_DSP(); map_HiROMSRAM(); @@ -3205,7 +2664,7 @@ void CMemory::Map_HiROMMap (void) void CMemory::Map_ExtendedHiROMMap (void) { - printf("Map_ExtendedHiROMMap\n"); + //printf("Map_ExtendedHiROMMap\n"); map_System(); map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); @@ -3221,7 +2680,7 @@ void CMemory::Map_ExtendedHiROMMap (void) void CMemory::Map_SameGameHiROMMap (void) { - printf("Map_SameGameHiROMMap\n"); + //printf("Map_SameGameHiROMMap\n"); map_System(); map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); @@ -3241,18 +2700,20 @@ void CMemory::Map_SameGameHiROMMap (void) void CMemory::Map_SPC7110HiROMMap (void) { - printf("Map_SPC7110HiROMMap\n"); + //printf("Map_SPC7110HiROMMap\n"); map_System(); - map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); - map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); - map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM); - map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize); - map_hirom_offset(0xc0, 0xcf, 0x0000, 0xffff, CalculatedSize, 0); map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM, MAP_TYPE_ROM); - map_WRAM(); + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); map_WriteProtectROM(); } @@ -3325,11 +2786,25 @@ void CMemory::Checksum_Calculate (void) // information +const char * CMemory::TVStandard (void) +{ + return (Settings.PAL ? "PAL" : "NTSC"); +} + const char * CMemory::MapType (void) { return (HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM"); } +const char * CMemory::MapMode (void) +{ + static char str[4]; + + sprintf(str, "%02x", ROMSpeed & ~0x10); + + return (str); +} + const char * CMemory::StaticRAMSize (void) { static char str[20]; @@ -3337,7 +2812,7 @@ const char * CMemory::StaticRAMSize (void) if (SRAMSize > 16) strcpy(str, "Corrupt"); else - sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024); + sprintf(str, "%dKB", (SRAMMask + 1) / 1024); return (str); } @@ -3368,8 +2843,8 @@ const char * CMemory::Revision (void) const char * CMemory::KartContents (void) { - static char str[64]; - static const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; + static char str[30]; + static char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; char chip[16]; @@ -3377,10 +2852,10 @@ const char * CMemory::KartContents (void) return ("ROM"); if (Settings.BS) - strcpy(chip, "+BS"); + strcpy(chip, "+BSX"); else if (Settings.SuperFX) - strcpy(chip, "+Super FX"); + strcpy(chip, "+SuperFX"); else if (Settings.SDD1) strcpy(chip, "+S-DD1"); @@ -3412,8 +2887,8 @@ const char * CMemory::KartContents (void) if (Settings.SETA == ST_018) strcpy(chip, "+ST-018"); else - if (Settings.DSP) - sprintf(chip, "+DSP-%d", Settings.DSP); + if (Settings.DSP1Master) + sprintf(chip, "+DSP%d", DSP1.version + 1); else strcpy(chip, ""); @@ -3422,81 +2897,6 @@ const char * CMemory::KartContents (void) return (str); } -const char * CMemory::Country (void) -{ - switch (ROMRegion) - { - case 0: return("Japan"); - case 1: return("USA and Canada"); - case 2: return("Oceania, Europe and Asia"); - case 3: return("Sweden"); - case 4: return("Finland"); - case 5: return("Denmark"); - case 6: return("France"); - case 7: return("Holland"); - case 8: return("Spain"); - case 9: return("Germany, Austria and Switzerland"); - case 10: return("Italy"); - case 11: return("Hong Kong and China"); - case 12: return("Indonesia"); - case 13: return("South Korea"); - default: return("Unknown"); - } -} - -const char * CMemory::PublishingCompany (void) -{ - if (CompanyId >= (int) (sizeof(nintendo_licensees) / sizeof(nintendo_licensees[0])) || CompanyId < 0) - return ("Unknown"); - - if (nintendo_licensees[CompanyId] == NULL) - return ("Unknown"); - - return (nintendo_licensees[CompanyId]); -} - -void CMemory::MakeRomInfoText (char *romtext) -{ - char temp[256]; - - romtext[0] = 0; - - sprintf(temp, " Cart Name: %s", ROMName); - strcat(romtext, temp); - sprintf(temp, "\n Game Code: %s", ROMId); - strcat(romtext, temp); - sprintf(temp, "\n Contents: %s", KartContents()); - strcat(romtext, temp); - sprintf(temp, "\n Map: %s", MapType()); - strcat(romtext, temp); - sprintf(temp, "\n Speed: 0x%02X (%s)", ROMSpeed, (ROMSpeed & 0x10) ? "FastROM" : "SlowROM"); - strcat(romtext, temp); - sprintf(temp, "\n Type: 0x%02X", ROMType); - strcat(romtext, temp); - sprintf(temp, "\n Size (calculated): %dMbits", CalculatedSize / 0x20000); - strcat(romtext, temp); - sprintf(temp, "\n Size (header): %s", Size()); - strcat(romtext, temp); - sprintf(temp, "\n SRAM size: %s", StaticRAMSize()); - strcat(romtext, temp); - sprintf(temp, "\nChecksum (calculated): 0x%04X", CalculatedChecksum); - strcat(romtext, temp); - sprintf(temp, "\n Checksum (header): 0x%04X", ROMChecksum); - strcat(romtext, temp); - sprintf(temp, "\n Complement (header): 0x%04X", ROMComplementChecksum); - strcat(romtext, temp); - sprintf(temp, "\n Video Output: %s", (ROMRegion > 12 || ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz"); - strcat(romtext, temp); - sprintf(temp, "\n Revision: %s", Revision()); - strcat(romtext, temp); - sprintf(temp, "\n Licensee: %s", PublishingCompany()); - strcat(romtext, temp); - sprintf(temp, "\n Region: %s", Country()); - strcat(romtext, temp); - sprintf(temp, "\n CRC32: 0x%08X", ROMCRC32); - strcat(romtext, temp); -} - // hack bool8 CMemory::match_na (const char *str) @@ -3521,8 +2921,10 @@ bool8 CMemory::match_id (const char *str) void CMemory::ApplyROMFixes (void) { - Settings.Shutdown = Settings.ShutdownMaster; - Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster; +#ifdef __W32_HEAP + if (_HEAPOK != _heapchk()) + MessageBox(GUI.hWnd, "CMemory::ApplyROMFixes", "Heap Corrupt", MB_OK); +#endif //// Warnings @@ -3548,128 +2950,82 @@ void CMemory::ApplyROMFixes (void) //// APU timing hacks :( - Timings.APUSpeedup = 0; - - if (!Settings.DisableGameSpecificHacks) + // This game cannot work well anyway + if (match_id("AVCJ")) // Rendering Ranger R2 { - if (match_id("AVCJ")) // Rendering Ranger R2 - Timings.APUSpeedup = 4; - - if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki - match_id("JG ") || // Illusion of Gaia - match_id("CQ ") || // Stunt Race FX - match_na("SOULBLADER - 1") || // Soul Blader - match_na("SOULBLAZER - 1 USA") || // Soul Blazer - match_na("SLAP STICK 1 JPN") || // Slap Stick - match_id("E9 ") || // Robotrek - match_nn("ACTRAISER") || // Actraiser - match_nn("ActRaiser-2") || // Actraiser 2 - match_id("AQT") || // Tenchi Souzou, Terranigma - match_id("ATV") || // Tales of Phantasia - match_id("ARF") || // Star Ocean - match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan - match_id("A4B") || // Super Bomberman 4 - match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban - match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban - match_id("APB") || // Super Bomberman - Panic Bomber W - match_na("DARK KINGDOM") || // Dark Kingdom - match_na("ZAN3 SFC") || // Zan III Spirits - match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai - match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta - match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase - match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing - match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen - match_na("MASTERS") || // Harukanaru Augusta 2 - Masters - match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider - match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou - match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7 - match_nn("SWORD WORLD SFC") || // Sword World SFC/2 - match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4 - match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master - match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5 - match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 - match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! - Timings.APUSpeedup = 1; + IAPU.OneCycle = (int32) (15.7 * (1 << SNES_APU_ACCURACY)); + //printf("APU OneCycle hack: %d\n", IAPU.OneCycle); } - S9xAPUTimingSetSpeedup(Timings.APUSpeedup); + // XXX: All Quintet games? + if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki + match_na("SOULBLAZER 1 GRM") || // Soulblazer (E) + match_id("JG ") || // Illusion of Gaia + match_id("CQ ")) // Stunt Race FX + { + IAPU.OneCycle = (int32) (13.0 * (1 << SNES_APU_ACCURACY)); + //printf("APU OneCycle hack: %d\n", IAPU.OneCycle); + } - //// Other timing hacks :( + if (match_na("SOULBLADER - 1") || // Soul Blader + match_na("SOULBLAZER - 1 USA") || // Soul Blazer + match_na("SLAP STICK 1 JPN") || // Slap Stick + match_id("E9 ") || // Robotrek + match_nn("ACTRAISER") || // Actraiser + match_nn("ActRaiser-2") || // Actraiser 2 + match_id("AQT") || // Tenchi Souzou, Terranigma + match_id("ATV") || // Tales of Phantasia + match_id("ARF") || // Star Ocean + match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan + match_id("A4B") || // Super Bomberman 4 + match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban + match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban + match_id("APB") || // Super Bomberman - Panic Bomber W + match_na("DARK KINGDOM") || // Dark Kingdom + match_na("ZAN3 SFC") || // Zan III Spirits + match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai + match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta + match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase + match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing + match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen + match_na("MASTERS") || // Harukanaru Augusta 2 - Masters + match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider + match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou + match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7 + match_nn("SWORD WORLD SFC") || // Sword World SFC/2 + match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4 + match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master + match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5 + match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 + match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! + { + IAPU.OneCycle = (int32) (15.0 * (1 << SNES_APU_ACCURACY)); + //printf("APU OneCycle hack: %d\n", IAPU.OneCycle); + } + + //// DMA/HDMA timing hacks :( Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; - if (!Settings.DisableGameSpecificHacks) + // The HC counter (CPU.Cycles for snes9x) passes over the WRAM refresh point (HC~536) + // while preparing to jump to the IRQ vector address. + // That is to say, the WRAM refresh point is passed over in S9xOpcode_IRQ(). + // Then, HDMA starts just after $210e is half updated, and it causes the flicker of the ground. + // IRQ timing is bad? HDMA timing is bad? else? + if (match_na("GUNDAMW ENDLESSDUEL")) // Shin Kidou Senki Gundam W - Endless Duel { - // The HC counter (CPU.Cycles for snes9x) passes over the WRAM refresh point (HC~536) - // while preparing to jump to the IRQ vector address. - // That is to say, the WRAM refresh point is passed over in S9xOpcode_IRQ(). - // Then, HDMA starts just after $210e is half updated, and it causes the flicker of the ground. - // IRQ timing is bad? HDMA timing is bad? else? - if (match_na("GUNDAMW ENDLESSDUEL")) // Shin Kidou Senki Gundam W - Endless Duel - { - Timings.HDMAStart -= 10; - Timings.HBlankStart -= 10; - printf("HDMA timing hack: %d\n", Timings.HDMAStart); - } - - // Due to Snes9x's very inaccurate timings, - // HDMA transfer to $210D-$2114 between the first and second writings to the same addresses. - if (match_na("POWER RANGERS FIGHT")) // Mighty Morphin Power Rangers - The Fighting Edition - { - Timings.HDMAStart -= 10; - Timings.HBlankStart -= 10; - printf("HDMA timing hack: %d\n", Timings.HDMAStart); - } - - if (match_na("SFX SUPERBUTOUDEN2")) // Dragon Ball Z - Super Butouden 2 - { - Timings.HDMAStart += 20; - Timings.HBlankStart += 20; - printf("HDMA timing hack: %d\n", Timings.HDMAStart); - } + Timings.HDMAStart -= 10; + Timings.HBlankStart -= 10; + //printf("HDMA timing hack: %d\n", Timings.HDMAStart); } - if (!Settings.DisableGameSpecificHacks) + // The delay to sync CPU and DMA which Snes9x cannot emulate. + // Some games need really severe delay timing... + if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix { - // The delay to sync CPU and DMA which Snes9x cannot emulate. - // Some games need really severe delay timing... - if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix - { - Timings.DMACPUSync = 20; - printf("DMA sync: %d\n", Timings.DMACPUSync); - } - } - - if (!Settings.DisableGameSpecificHacks) - { - // Opcode-based emulators cannot escape from "reading $4211/BPL" infinite loop... - // The true IRQ can be triggered inside an opcode. - if (match_na("TRAVERSE")) // Traverse - Starlight & Prairie - { - Timings.IRQPendCount = 1; - printf("IRQ count hack: %d\n", Timings.IRQPendCount); - } - - // An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0. - // If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further. - // If Snes9x jumps into the IRQ handler before escaping from the loop, - // Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank. - if (match_na("Aero the AcroBat 2")) - { - Timings.IRQPendCount = 2; - printf("IRQ count hack: %d\n", Timings.IRQPendCount); - } - } - - if (!Settings.DisableGameSpecificHacks) - { - // XXX: What's happening? - if (match_na("X-MEN")) // Spider-Man and the X-Men - { - Settings.BlockInvalidVRAMAccess = FALSE; - printf("Invalid VRAM access hack\n"); - } + Timings.DMACPUSync = 20; + //printf("DMA sync: %d\n", Timings.DMACPUSync); } //// CPU speed-ups (CPU_Shutdown()) @@ -3681,6 +3037,8 @@ void CMemory::ApplyROMFixes (void) match_na("PRIMAL RAGE") || // Primal Rage match_na("CLAY FIGHTER") || // Clay Fighter match_na("ClayFighter 2") || // Clay Fighter 2 + match_id("ARWJ") || // Super Mario RPG (J) + match_id("ARWE") || // Super Mario RPG (U) match_na("WeaponLord") || // Weapon Lord match_nn("WAR 2410") || // War 2410 match_id("ARF") || // Star Ocean @@ -3688,8 +3046,8 @@ void CMemory::ApplyROMFixes (void) match_nn("NHL") || match_nc("MADDEN")) { - if (Settings.Shutdown) - printf("Disabled CPU shutdown hack.\n"); + //if (Settings.Shutdown) + // printf("Disabled CPU shutdown hack.\n"); Settings.Shutdown = FALSE; } @@ -3908,563 +3266,408 @@ void CMemory::ApplyROMFixes (void) // Super Shougi 3 - Kitaihei (J) } - //// SRAM initial value + //// SRAM fixes - if (!Settings.DisableGameSpecificHacks) + if (match_na("HITOMI3")) { - if (match_na("HITOMI3")) - { - SRAMSize = 1; - SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1; - } - - // SRAM value fixes - if (match_na("SUPER DRIFT OUT") || // Super Drift Out - match_na("SATAN IS OUR FATHER!") || - match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu - SNESGameFixes.SRAMInitialValue = 0x00; - - // Additional game fixes by sanmaiwashi ... - // XXX: unnecessary? - if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari - SNESGameFixes.SRAMInitialValue = 0x6b; - - // others: BS and ST-01x games are 0x00. + SRAMSize = 1; + SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1; } - //// OAM hacks :( + // SRAM value fixes + if (match_na("SUPER DRIFT OUT") || // Super Drift Out + match_na("SATAN IS OUR FATHER!") || + match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu + SNESGameFixes.SRAMInitialValue = 0x00; - if (!Settings.DisableGameSpecificHacks) + // Additional game fixes by sanmaiwashi ... + // XXX: unnecessary? + if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari + SNESGameFixes.SRAMInitialValue = 0x6b; + + // others: BS and ST-01x games are 0x00. + + //// Specific game fixes + + // for ZSNES SuperFX: is it still necessary? + Settings.WinterGold = match_na("FX SKIING NINTENDO 96") || match_na("DIRT RACER"); + + // OAM hacks because we don't fully understand the behavior of the SNES. + // Totally wacky display in 2P mode... + // seems to need a disproven behavior, so we're definitely overlooking some other bug? + if (match_nn("UNIRACERS")) // Uniracers { - // OAM hacks because we don't fully understand the behavior of the SNES. - // Totally wacky display in 2P mode... - // seems to need a disproven behavior, so we're definitely overlooking some other bug? - if (match_nn("UNIRACERS")) // Uniracers - { - SNESGameFixes.Uniracers = TRUE; - printf("Applied Uniracers hack.\n"); - } + SNESGameFixes.Uniracers = TRUE; + //printf("Applied Uniracers hack.\n"); } + + /* + // XXX: What's this? + if (match_na("\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0") || // Super Famista + match_na("\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0 2") || // Super Famista 2 + match_na("GANBA LEAGUE")) // Hakunetsu Pro Yakyuu - Ganba League + SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE; + */ } - +#ifndef NGC // IPS +// Read variable size MSB int from a file static long ReadInt (Reader *r, unsigned nbytes) { - long v = 0; - - while (nbytes--) - { - int c = r->get_char(); + long v = 0; + while (nbytes--) + { + int c = r->get_char(); if (c == EOF) - return (-1); + return -1; v = (v << 8) | (c & 0xFF); - } - - return (v); -} - -static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size) -{ - const int32 IPS_EOF = 0x00454F46l; - int32 ofs; - char fname[6]; - - fname[5] = 0; - for (int i = 0; i < 5; i++) - { - int c = r->get_char(); - if (c == EOF) - return (0); - fname[i] = (char) c; - } - - if (strncmp(fname, "PATCH", 5)) - return (0); - - for (;;) - { - long len, rlen; - int rchar; - - ofs = ReadInt(r, 3); - if (ofs == -1) - return (0); - - if (ofs == IPS_EOF) - break; - - ofs -= offset; - - len = ReadInt(r, 2); - if (len == -1) - return (0); - - if (len) - { - if (ofs + len > CMemory::MAX_ROM_SIZE) - return (0); - - while (len--) - { - rchar = r->get_char(); - if (rchar == EOF) - return (0); - Memory.ROM[ofs++] = (uint8) rchar; - } - - if (ofs > rom_size) - rom_size = ofs; - } - else - { - rlen = ReadInt(r, 2); - if (rlen == -1) - return (0); - - rchar = r->get_char(); - if (rchar == EOF) - return (0); - - if (ofs + rlen > CMemory::MAX_ROM_SIZE) - return (0); - - while (rlen--) - Memory.ROM[ofs++] = (uint8) rchar; - - if (ofs > rom_size) - rom_size = ofs; - } - } - - ofs = ReadInt(r, 3); - if (ofs != -1 && ofs - offset < rom_size) - rom_size = ofs - offset; - - return (1); -} - -#ifdef UNZIP_SUPPORT -static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print) -{ - unz_file_info info; - int port, l = strlen(ext); - - if (restart) - port = unzGoToFirstFile(file); - else - port = unzGoToNextFile(file); - - while (port == UNZ_OK) - { - int len; - char name[132]; - - unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0); - len = strlen(name); - - if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK) - { - if (print) - printf("Using IPS patch %s", name); - - return (port); - } - - port = unzGoToNextFile(file); - } - - return (port); + } + return (v); } #endif +#define IPS_EOF 0x00454F46l + +#ifndef NGC +static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size) +{ + char fname[6]; + for(int i=0; i<5; i++){ + int c=r->get_char(); + if(c==EOF) return 0; + fname[i]=(char) c; + } + fname[5]=0; + if (strncmp (fname, "PATCH", 5) != 0) + { + return 0; + } + + int32 ofs; + + for (;;) + { + long len; + long rlen; + int rchar; + + ofs = ReadInt (r, 3); + if (ofs == -1) + goto err_eof; + + if (ofs == IPS_EOF) + break; + + ofs -= offset; + + len = ReadInt (r, 2); + if (len == -1) + goto err_eof; + + /* Apply patch block */ + if (len) + { + if (ofs + len > CMemory::MAX_ROM_SIZE) + goto err_eof; + + while (len--) + { + rchar = r->get_char(); + if (rchar == EOF) + goto err_eof; + Memory.ROM [ofs++] = (uint8) rchar; + } + if (ofs > rom_size) + rom_size = ofs; + } + else + { + rlen = ReadInt (r, 2); + if (rlen == -1) + goto err_eof; + + rchar = r->get_char(); + if (rchar == EOF) + goto err_eof; + + if (ofs + rlen > CMemory::MAX_ROM_SIZE) + goto err_eof; + + while (rlen--) + Memory.ROM [ofs++] = (uint8) rchar; + + if (ofs > rom_size) + rom_size = ofs; + } + } + + // Check if ROM image needs to be truncated + ofs = ReadInt (r, 3); + if (ofs != -1 && ofs - offset < rom_size) + { + // Need to truncate ROM image + rom_size = ofs - offset; + } + return 1; + +err_eof: + return 0; +} +#endif + +#ifndef NGC + +static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print) +{ + int port; + int l=strlen(ext); + + if(restart){ + port=unzGoToFirstFile(file); + } else { + port=unzGoToNextFile(file); + } + unz_file_info info; + while(port==UNZ_OK){ + char name[132]; + unzGetCurrentFileInfo(file, &info, name,128, NULL,0, NULL,0); + int len=strlen(name); + if(len>=l+1 && name[len-l-1]=='.' && strcasecmp(name+len-l, ext)==0 && + unzOpenCurrentFile(file)==UNZ_OK){ + if(print) printf("Using IPS patch %s", name); + return port; + } + port = unzGoToNextFile(file); + } + return port; +} +#endif + +#ifndef NGC + void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, int32 &rom_size) { - if (Settings.NoPatch) - return; + if(Settings.NoPatch) return; - STREAM patch_file = NULL; - uint32 i; - long offset = header ? 512 : 0; - int ret; - bool flag; - char dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1]; + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char name [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char ips [_MAX_EXT + 3]; + char fname [_MAX_PATH + 1]; + STREAM patch_file = NULL; + long offset = header ? 512 : 0; + int ret; + bool8 flag; + uint32 i; - _splitpath(rom_filename, drive, dir, name, ext); - _makepath(fname, drive, dir, name, "ips"); - - if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) - { - printf("Using IPS patch %s", fname); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - return; - } - else - printf(" failed!\n"); - } - - if (_MAX_EXT > 6) - { - i = 0; - flag = false; - - do - { - snprintf(ips, 8, "%03d.ips", i); - _makepath(fname, drive, dir, name, ips); - - if (!(patch_file = OPEN_STREAM(fname, "rb"))) - break; - - printf("Using IPS patch %s", fname); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - } while (++i < 1000); - - if (flag) - return; - } - - if (_MAX_EXT > 3) - { - i = 0; - flag = false; - - do - { - snprintf(ips, _MAX_EXT + 2, "ips%d", i); - if (strlen(ips) > _MAX_EXT) - break; - _makepath(fname, drive, dir, name, ips); - - if (!(patch_file = OPEN_STREAM(fname, "rb"))) - break; - - printf("Using IPS patch %s", fname); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - } while (++i != 0); - - if (flag) - return; - } - - if (_MAX_EXT > 2) - { - i = 0; - flag = false; - - do - { - snprintf(ips, 4, "ip%d", i); - _makepath(fname, drive, dir, name, ips); - - if (!(patch_file = OPEN_STREAM(fname, "rb"))) - break; - - printf("Using IPS patch %s", fname); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - } while (++i < 10); - - if (flag) - return; - } + _splitpath (rom_filename, drive, dir, name, ext); + _makepath (fname, drive, dir, name, "ips"); + if ((patch_file = OPEN_STREAM (fname, "rb"))) + { + printf ("Using IPS patch %s", fname); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + printf("!\n"); + return; + } else printf(" failed!\n"); + } + if(_MAX_EXT>6){ + i=0; + flag=0; + do { + snprintf(ips, 8, "%03d.ips", i); + _makepath(fname, drive, dir, name, ips); + if(!(patch_file = OPEN_STREAM (fname, "rb"))) break; + printf ("Using IPS patch %s", fname); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + } while(++i<1000); + if(flag) return; + } + if(_MAX_EXT>3){ + i=0; + flag=0; + do { + snprintf(ips, _MAX_EXT+2, "ips%d", i); + if(strlen(ips)>_MAX_EXT) break; + _makepath(fname, drive, dir, name, ips); + if(!(patch_file = OPEN_STREAM (fname, "rb"))) break; + printf ("Using IPS patch %s", fname); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + } while(++i!=0); + if(flag) return; + } + if(_MAX_EXT>2){ + i=0; + flag=0; + do { + snprintf(ips, 4, "ip%d", i); + _makepath(fname, drive, dir, name, ips); + if(!(patch_file = OPEN_STREAM (fname, "rb"))) break; + printf ("Using IPS patch %s", fname); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + } while(++i<10); + if(flag) return; + } #ifdef UNZIP_SUPPORT - if (strcasecmp(ext, "zip") == 0) - { - unzFile file = unzOpen(rom_filename); - if (file) - { - int port = unzFindExtension(file, "ips"); - while (port == UNZ_OK) - { - printf(" in %s", rom_filename); - - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); - unzCloseCurrentFile(file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - printf(" failed!\n"); - - port = unzFindExtension(file, "ips", false); - } - - if (!flag) - { - i = 0; - - do - { - snprintf(ips, 8, "%03d.ips", i); - - if (unzFindExtension(file, ips) != UNZ_OK) - break; - - printf(" in %s", rom_filename); - - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); - unzCloseCurrentFile(file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - - if (unzFindExtension(file, ips, false, false) == UNZ_OK) - printf("WARNING: Ignoring extra .%s files!\n", ips); - } while (++i < 1000); - } - - if (!flag) - { - i = 0; - - do - { - snprintf(ips, _MAX_EXT + 2, "ips%d", i); - if (strlen(ips) > _MAX_EXT) - break; - - if (unzFindExtension(file, ips) != UNZ_OK) - break; - - printf(" in %s", rom_filename); - - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); - unzCloseCurrentFile(file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - - if (unzFindExtension(file, ips, false, false) == UNZ_OK) - printf("WARNING: Ignoring extra .%s files!\n", ips); - } while (++i != 0); - } - - if (!flag) - { - i = 0; - - do - { - snprintf(ips, 4, "ip%d", i); - - if (unzFindExtension(file, ips) != UNZ_OK) - break; - - printf(" in %s", rom_filename); - - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); - unzCloseCurrentFile(file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - - if (unzFindExtension(file, ips, false, false) == UNZ_OK) - printf("WARNING: Ignoring extra .%s files!\n", ips); - } while (++i < 10); - } - - assert(unzClose(file) == UNZ_OK); - - if (flag) - return; - } - } + if (strcasecmp(ext, "zip")==0) { + unzFile file=unzOpen(rom_filename); + if(file!=NULL){ + int port=unzFindExtension(file, "ips"); + while(port==UNZ_OK){ + printf(" in %s", rom_filename); + ret=ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + if(ret){ + printf("!\n"); + flag=1; + } else printf (" failed!\n"); + port = unzFindExtension(file, "ips", false); + } + if(!flag){ + i=0; + do { + snprintf(ips, _MAX_EXT+2, "ips%d", i); + if(strlen(ips)>_MAX_EXT) break; + if(unzFindExtension(file, ips)!=UNZ_OK) break; + printf(" in %s", rom_filename); + ret=ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + if(unzFindExtension(file, ips, false, false)==UNZ_OK) printf("WARNING: Ignoring extra .%s files!\n", ips); + } while(++i!=0); + } + if(!flag){ + i=0; + do { + snprintf(ips, 4, "ip%d", i); + if(unzFindExtension(file, ips)!=UNZ_OK) break; + printf(" in %s", rom_filename); + ret=ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + if(unzFindExtension(file, ips, false, false)==UNZ_OK) printf("WARNING: Ignoring extra .%s files!\n", ips); + } while(++i<10); + } + assert(unzClose(file)==UNZ_OK); + if(flag) return; + } + } #endif - const char *n; - - n = S9xGetFilename(".ips", IPS_DIR); - - if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) - { - printf("Using IPS patch %s", n); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - return; - } - else - printf(" failed!\n"); - } - - if (_MAX_EXT > 6) - { - i = 0; - flag = false; - - do - { - snprintf(ips, 9, ".%03d.ips", i); - n = S9xGetFilename(ips, IPS_DIR); - - if (!(patch_file = OPEN_STREAM(n, "rb"))) - break; - - printf("Using IPS patch %s", n); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - } while (++i < 1000); - - if (flag) - return; - } - - if (_MAX_EXT > 3) - { - i = 0; - flag = false; - - do - { - snprintf(ips, _MAX_EXT + 3, ".ips%d", i); - if (strlen(ips) > _MAX_EXT + 1) - break; - n = S9xGetFilename(ips, IPS_DIR); - - if (!(patch_file = OPEN_STREAM(n, "rb"))) - break; - - printf("Using IPS patch %s", n); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - } while (++i != 0); - - if (flag) - return; - } - - if (_MAX_EXT > 2) - { - i = 0; - flag = false; - - do - { - snprintf(ips, 5, ".ip%d", i); - n = S9xGetFilename(ips, IPS_DIR); - - if (!(patch_file = OPEN_STREAM(n, "rb"))) - break; - - printf("Using IPS patch %s", n); - - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); - - if (ret) - { - printf("!\n"); - flag = true; - } - else - { - printf(" failed!\n"); - break; - } - } while (++i < 10); - - if (flag) - return; - } + const char *n; + n=S9xGetFilename(".ips", PATCH_DIR); + if((patch_file=OPEN_STREAM(n, "rb"))) { + printf("Using IPS patch %s", n); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + printf("!\n"); + return; + } else printf(" failed!\n"); + } + if(_MAX_EXT>6){ + i=0; + flag=0; + do { + snprintf(ips, 9, ".%03d.ips", i); + n=S9xGetFilename(ips, PATCH_DIR); + if(!(patch_file = OPEN_STREAM(n, "rb"))) break; + printf ("Using IPS patch %s", n); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + } while(++i<1000); + if(flag) return; + } + if(_MAX_EXT>3){ + i=0; + flag=0; + do { + snprintf(ips, _MAX_EXT+3, ".ips%d", i); + if(strlen(ips)>_MAX_EXT+1) break; + n=S9xGetFilename(ips, PATCH_DIR); + if(!(patch_file = OPEN_STREAM(n, "rb"))) break; + printf ("Using IPS patch %s", n); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + } while(++i!=0); + if(flag) return; + } + if(_MAX_EXT>2){ + i=0; + flag=0; + do { + snprintf(ips, 5, ".ip%d", i); + n=S9xGetFilename(ips, PATCH_DIR); + if(!(patch_file = OPEN_STREAM(n, "rb"))) break; + printf ("Using IPS patch %s", n); + ret=ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + if(ret){ + flag=1; + printf("!\n"); + } else { + printf(" failed!\n"); + break; + } + } while(++i<10); + if(flag) return; + } } +#endif +#undef INLINE +#define INLINE +#include "getset.h" diff --git a/source/snes9x/memmap.h b/source/snes9x/memmap.h index 224e6a3..09ca296 100644 --- a/source/snes9x/memmap.h +++ b/source/snes9x/memmap.h @@ -159,19 +159,26 @@ **********************************************************************************/ -#ifndef _MEMMAP_H_ -#define _MEMMAP_H_ -#define MEMMAP_BLOCK_SIZE (0x1000) -#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) -#define MEMMAP_SHIFT (12) -#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) +#ifndef _memmap_h_ +#define _memmap_h_ + +#include "snes9x.h" + +#define MEMMAP_BLOCK_SIZE (0x1000) +#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) +#define MEMMAP_SHIFT (12) +#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) +#define MEMMAP_MAX_SDD1_LOGGED_ENTRIES (0x10000 / 8) struct CMemory { enum - { MAX_ROM_SIZE = 0x800000 }; - +#ifdef HW_RVL + { MAX_ROM_SIZE = 0x800000 }; // Wii - lots of memory +#else + { MAX_ROM_SIZE = 0x500000 }; // GameCube - less memory to play with +#endif enum file_formats { FILE_ZIP, FILE_JMA, FILE_DEFAULT }; @@ -183,25 +190,26 @@ struct CMemory enum { - MAP_CPU, MAP_PPU, + MAP_CPU, MAP_LOROM_SRAM, MAP_LOROM_SRAM_B, MAP_HIROM_SRAM, MAP_DSP, - MAP_SA1RAM, + MAP_C4, MAP_BWRAM, MAP_BWRAM_BITMAP, MAP_BWRAM_BITMAP2, + MAP_SA1RAM, MAP_SPC7110_ROM, MAP_SPC7110_DRAM, MAP_RONLY_SRAM, - MAP_C4, MAP_OBC_RAM, MAP_SETA_DSP, MAP_SETA_RISC, MAP_BSX, MAP_NONE, + MAP_DEBUG, MAP_LAST }; @@ -215,7 +223,6 @@ struct CMemory uint8 *FillRAM; uint8 *BWRAM; uint8 *C4RAM; - uint8 *OBC1RAM; uint8 *BSRAM; uint8 *BIOSROM; @@ -226,11 +233,11 @@ struct CMemory uint8 MemorySpeed[MEMMAP_NUM_BLOCKS]; uint8 ExtendedFormat; - char ROMFilename[PATH_MAX + 1]; + char ROMFilename[_MAX_PATH + 1]; char ROMName[ROM_NAME_LEN]; char RawROMName[ROM_NAME_LEN]; char ROMId[5]; - int32 CompanyId; + char CompanyId[3]; uint8 ROMRegion; uint8 ROMSpeed; uint8 ROMType; @@ -247,11 +254,19 @@ struct CMemory uint32 CalculatedSize; uint32 CalculatedChecksum; + uint8 *SDD1Index; + uint8 *SDD1Data; + uint32 SDD1Entries; + uint32 SDD1LoggedDataCountPrev; + uint32 SDD1LoggedDataCount; + uint8 SDD1LoggedData[MEMMAP_MAX_SDD1_LOGGED_ENTRIES]; + // ports can assign this to perform some custom action upon loading a ROM (such as adjusting controls) - void (*PostRomInitFunc) (void); + void (*PostRomInitFunc) (); bool8 Init (void); void Deinit (void); + void FreeSDD1Data (void); int ScoreHiROM (bool8, int32 romoff = 0); int ScoreLoROM (bool8, int32 romoff = 0); @@ -261,11 +276,10 @@ struct CMemory bool8 LoadMultiCart (const char *, const char *); bool8 LoadSufamiTurbo (const char *, const char *); bool8 LoadSameGame (const char *, const char *); + bool8 LoadLastROM (void); bool8 LoadSRAM (const char *); bool8 SaveSRAM (const char *); void ClearSRAM (bool8 onlyNonSavedSRAM = 0); - bool8 LoadSRTC (void); - bool8 SaveSRTC (void); char * Safe (const char *); char * SafeANK (const char *); @@ -319,15 +333,13 @@ struct CMemory void ApplyROMFixes (void); void CheckForIPSPatch (const char *, bool8, int32 &); - void MakeRomInfoText (char *); - + const char * TVStandard (void); const char * MapType (void); + const char * MapMode (void); const char * StaticRAMSize (void); const char * Size (void); const char * Revision (void); const char * KartContents (void); - const char * Country (void); - const char * PublishingCompany (void); }; struct SMulti @@ -338,20 +350,21 @@ struct SMulti uint32 sramMaskA, sramMaskB; uint32 cartOffsetA, cartOffsetB; uint8 *sramA, *sramB; - char fileNameA[PATH_MAX + 1], fileNameB[PATH_MAX + 1]; + char fileNameA[_MAX_PATH + 1], fileNameB[_MAX_PATH + 1]; }; +START_EXTERN_C extern CMemory Memory; extern SMulti Multi; - #if defined(ZSNES_FX) || defined(ZSNES_C4) extern uint8 *ROM; extern uint8 *SRAM; extern uint8 *RegRAM; #endif +bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); +END_EXTERN_C void S9xAutoSaveSRAM (void); -bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); enum s9xwrap_t { @@ -366,6 +379,25 @@ enum s9xwriteorder_t WRITE_10 }; +#ifdef NO_INLINE_SET_GET + +uint8 S9xGetByte (uint32); +uint16 S9xGetWord (uint32, enum s9xwrap_t w = WRAP_NONE); +void S9xSetByte (uint8, uint32); +void S9xSetWord (uint16, uint32, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01); +void S9xSetPCBase (uint32); +uint8 * S9xGetMemPointer (uint32); +uint8 * GetBasePointer (uint32); + +START_EXTERN_C +extern uint8 OpenBus; +END_EXTERN_C + +#else + +#define INLINE inline #include "getset.h" -#endif +#endif // NO_INLINE_SET_GET + +#endif // _memmap_h_ diff --git a/source/snes9x/messages.h b/source/snes9x/messages.h index 1e6c565..eb55261 100644 --- a/source/snes9x/messages.h +++ b/source/snes9x/messages.h @@ -159,49 +159,49 @@ **********************************************************************************/ -#ifndef _MESSAGES_H_ -#define _MESSAGES_H_ -// Types of message sent to S9xMessage() -enum -{ - S9X_TRACE, - S9X_DEBUG, - S9X_WARNING, - S9X_INFO, - S9X_ERROR, - S9X_FATAL_ERROR + +#ifndef _messages_h_ +#define _messages_h_ + +/* Types of message sent to S9xMessage routine */ +enum { + S9X_TRACE, + S9X_DEBUG, + S9X_WARNING, + S9X_INFO, + S9X_ERROR, + S9X_FATAL_ERROR }; -// Individual message numbers -enum -{ - S9X_ROM_INFO, - S9X_HEADERS_INFO, - S9X_CONFIG_INFO, - S9X_ROM_CONFUSING_FORMAT_INFO, - S9X_ROM_INTERLEAVED_INFO, - S9X_SOUND_DEVICE_OPEN_FAILED, - S9X_APU_STOPPED, - S9X_USAGE, - S9X_GAME_GENIE_CODE_ERROR, - S9X_ACTION_REPLY_CODE_ERROR, - S9X_GOLD_FINGER_CODE_ERROR, - S9X_DEBUG_OUTPUT, - S9X_DMA_TRACE, - S9X_HDMA_TRACE, - S9X_WRONG_FORMAT, - S9X_WRONG_VERSION, - S9X_ROM_NOT_FOUND, - S9X_FREEZE_FILE_NOT_FOUND, - S9X_PPU_TRACE, - S9X_TRACE_DSP1, - S9X_FREEZE_ROM_NAME, - S9X_HEADER_WARNING, - S9X_NETPLAY_NOT_SERVER, - S9X_FREEZE_FILE_INFO, - S9X_TURBO_MODE, - S9X_SOUND_NOT_BUILT, +/* Individual message numbers */ +enum { + S9X_ROM_INFO, + S9X_HEADERS_INFO, + S9X_CONFIG_INFO, + S9X_ROM_CONFUSING_FORMAT_INFO, + S9X_ROM_INTERLEAVED_INFO, + S9X_SOUND_DEVICE_OPEN_FAILED, + S9X_APU_STOPPED, + S9X_USAGE, + S9X_GAME_GENIE_CODE_ERROR, + S9X_ACTION_REPLY_CODE_ERROR, + S9X_GOLD_FINGER_CODE_ERROR, + S9X_DEBUG_OUTPUT, + S9X_DMA_TRACE, + S9X_HDMA_TRACE, + S9X_WRONG_FORMAT, + S9X_WRONG_VERSION, + S9X_ROM_NOT_FOUND, + S9X_FREEZE_FILE_NOT_FOUND, + S9X_PPU_TRACE, + S9X_TRACE_DSP1, + S9X_FREEZE_ROM_NAME, + S9X_HEADER_WARNING, + S9X_NETPLAY_NOT_SERVER, + S9X_FREEZE_FILE_INFO, + S9X_TURBO_MODE, + S9X_SOUND_NOT_BUILT, S9X_MOVIE_INFO, S9X_WRONG_MOVIE_SNAPSHOT, S9X_NOT_A_MOVIE_SNAPSHOT, @@ -210,3 +210,4 @@ enum }; #endif + diff --git a/source/snes9x/missing.h b/source/snes9x/missing.h index 527cb90..ef7c8d8 100644 --- a/source/snes9x/missing.h +++ b/source/snes9x/missing.h @@ -159,82 +159,80 @@ **********************************************************************************/ -#ifdef DEBUGGER + #ifndef _MISSING_H_ #define _MISSING_H_ -struct MissingHDMA +struct HDMA { - uint8 used; - uint8 bbus_address; - uint8 abus_bank; - uint16 abus_address; - uint8 indirect_address; - uint8 force_table_address_write; - uint8 force_table_address_read; - uint8 line_count_write; - uint8 line_count_read; + uint8 used; + uint8 bbus_address; + uint8 abus_bank; + uint16 abus_address; + uint8 indirect_address; + uint8 force_table_address_write; + uint8 force_table_address_read; + uint8 line_count_write; + uint8 line_count_read; }; struct Missing { - struct MissingHDMA hdma[8]; - uint8 emulate6502; - uint8 decimal_mode; - uint8 mv_8bit_index; - uint8 mv_8bit_acc; - uint8 interlace; - uint8 lines_239; - uint8 pseudo_512; - uint8 modes[8]; - uint8 mode7_fx; - uint8 mode7_flip; - uint8 mode7_bgmode; - uint8 direct; - uint8 matrix_multiply; - uint8 oam_read; - uint8 vram_read; - uint8 cgram_read; - uint8 wram_read; - uint8 dma_read; - uint8 vram_inc; - uint8 vram_full_graphic_inc; - uint8 virq; - uint8 hirq; - uint16 virq_pos; - uint16 hirq_pos; - uint8 h_v_latch; - uint8 h_counter_read; - uint8 v_counter_read; - uint8 fast_rom; - uint8 window1[6]; - uint8 window2[6]; - uint8 sprite_priority_rotation; - uint8 subscreen; - uint8 subscreen_add; - uint8 subscreen_sub; - uint8 fixed_colour_add; - uint8 fixed_colour_sub; - uint8 mosaic; - uint8 sprite_double_height; - uint8 dma_channels; - uint8 dma_this_frame; - uint8 oam_address_read; - uint8 bg_offset_read; - uint8 matrix_read; - uint8 hdma_channels; - uint8 hdma_this_frame; - uint16 unknownppu_read; - uint16 unknownppu_write; - uint16 unknowncpu_read; - uint16 unknowncpu_write; - uint16 unknowndsp_read; - uint16 unknowndsp_write; + uint8 emulate6502; + uint8 decimal_mode; + uint8 mv_8bit_index; + uint8 mv_8bit_acc; + uint8 interlace; + uint8 lines_239; + uint8 pseudo_512; + struct HDMA hdma [8]; + uint8 modes [8]; + uint8 mode7_fx; + uint8 mode7_flip; + uint8 mode7_bgmode; + uint8 direct; + uint8 matrix_multiply; + uint8 oam_read; + uint8 vram_read; + uint8 cgram_read; + uint8 wram_read; + uint8 dma_read; + uint8 vram_inc; + uint8 vram_full_graphic_inc; + uint8 virq; + uint8 hirq; + uint16 virq_pos; + uint16 hirq_pos; + uint8 h_v_latch; + uint8 h_counter_read; + uint8 v_counter_read; + uint8 fast_rom; + uint8 window1 [6]; + uint8 window2 [6]; + uint8 sprite_priority_rotation; + uint8 subscreen; + uint8 subscreen_add; + uint8 subscreen_sub; + uint8 fixed_colour_add; + uint8 fixed_colour_sub; + uint8 mosaic; + uint8 sprite_double_height; + uint8 dma_channels; + uint8 dma_this_frame; + uint8 oam_address_read; + uint8 bg_offset_read; + uint8 matrix_read; + uint8 hdma_channels; + uint8 hdma_this_frame; + uint16 unknownppu_read; + uint16 unknownppu_write; + uint16 unknowncpu_read; + uint16 unknowncpu_write; + uint16 unknowndsp_read; + uint16 unknowndsp_write; }; -extern struct Missing missing; - +EXTERN_C struct Missing missing; #endif -#endif diff --git a/source/snes9x/movie.cpp b/source/snes9x/movie.cpp deleted file mode 100644 index 7a1383f..0000000 --- a/source/snes9x/movie.cpp +++ /dev/null @@ -1,1171 +0,0 @@ -/********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com) - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley, - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001-2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight, - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound DSP emulator code is derived from SNEeSe and OpenSPC: - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2007 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -**********************************************************************************/ - -// Input recording/playback code -// (c) Copyright 2004 blip - -#include -#include "snes9x.h" -#include "memmap.h" -#include "controls.h" -#include "snapshot.h" -#include "movie.h" -#include "language.h" -#ifdef NETPLAY_SUPPORT -#include "netplay.h" -#endif - -#ifdef __WIN32__ -#include -#ifndef W_OK -#define W_OK 2 -#endif -#define ftruncate chsize -#endif - -#define SMV_MAGIC 0x1a564d53 // SMV0x1a -#define SMV_VERSION 5 -#define SMV_HEADER_SIZE 64 -#define SMV_EXTRAROMINFO_SIZE 30 -#define BUFFER_GROWTH_SIZE 4096 - -enum MovieState -{ - MOVIE_STATE_NONE = 0, - MOVIE_STATE_PLAY, - MOVIE_STATE_RECORD -}; - -struct SMovie -{ - enum MovieState State; - - FILE *File; - char Filename[PATH_MAX + 1]; - char ROMName[23]; - uint32 ROMCRC32; - uint32 MovieId; - uint32 Version; - - uint32 SaveStateOffset; - uint32 ControllerDataOffset; - - uint8 ControllersMask; - uint8 Opts; - uint8 SyncFlags; - uint32 MaxFrame; - uint32 MaxSample; - uint32 CurrentFrame; - uint32 CurrentSample; - uint32 BytesPerSample; - uint32 RerecordCount; - bool8 ReadOnly; - uint8 PortType[2]; - int8 PortIDs[2][4]; - - uint8 *InputBuffer; - uint8 *InputBufferPtr; - uint32 InputBufferSize; -}; - -static struct SMovie Movie; - -static uint8 prevPortType[2]; -static int8 prevPortIDs[2][4]; -static bool8 prevMouseMaster, prevSuperScopeMaster, prevJustifierMaster, prevMultiPlayer5Master; - -static uint8 Read8 (uint8 *&); -static uint16 Read16 (uint8 *&); -static uint32 Read32 (uint8 *&); -static void Write8 (uint8, uint8 *&); -static void Write16 (uint16, uint8 *&); -static void Write32 (uint32, uint8 *&); -static void store_previous_settings (void); -static void restore_previous_settings (void); -static void store_movie_settings (void); -static void restore_movie_settings (void); -static int bytes_per_sample (void); -static void reserve_buffer_space (uint32); -static void reset_controllers (void); -static void read_frame_controller_data (bool); -static void write_frame_controller_data (void); -static void flush_movie (void); -static void truncate_movie (void); -static int read_movie_header (FILE *, SMovie *); -static int read_movie_extrarominfo (FILE *, SMovie *); -static void write_movie_header (FILE *, SMovie *); -static void write_movie_extrarominfo (FILE *, SMovie *); -static void change_state (MovieState); - -// HACK: reduce movie size by not storing changes that can only affect polled input in the movie for these types, -// because currently no port sets these types to polling -#define SKIPPED_POLLING_PORT_TYPE(x) (((x) == CTL_NONE) || ((x) == CTL_JOYPAD) || ((x) == CTL_MP5)) - -#ifndef max -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#endif - - -static uint8 Read8 (uint8 *&ptr) -{ - uint8 v = *ptr++; - return (v); -} - -static uint16 Read16 (uint8 *&ptr) -{ - uint16 v = READ_WORD(ptr); - ptr += 2; - return (v); -} - -static uint32 Read32 (uint8 *&ptr) -{ - uint32 v = READ_DWORD(ptr); - ptr += 4; - return (v); -} - -static void Write8 (uint8 v, uint8 *&ptr) -{ - *ptr++ = v; -} - -static void Write16 (uint16 v, uint8 *&ptr) -{ - WRITE_WORD(ptr, v); - ptr += 2; -} - -static void Write32 (uint32 v, uint8 *&ptr) -{ - WRITE_DWORD(ptr, v); - ptr += 4; -} - -static void store_previous_settings (void) -{ - for (int i = 0; i < 2; i++) - { - enum controllers pt; - S9xGetController(i, &pt, &prevPortIDs[i][0], &prevPortIDs[i][1], &prevPortIDs[i][2], &prevPortIDs[i][3]); - prevPortType[i] = (uint8) pt; - } - - prevMouseMaster = Settings.MouseMaster; - prevSuperScopeMaster = Settings.SuperScopeMaster; - prevJustifierMaster = Settings.JustifierMaster; - prevMultiPlayer5Master = Settings.MultiPlayer5Master; -} - -static void restore_previous_settings (void) -{ - Settings.MouseMaster = prevMouseMaster; - Settings.SuperScopeMaster = prevSuperScopeMaster; - Settings.JustifierMaster = prevJustifierMaster; - Settings.MultiPlayer5Master = prevMultiPlayer5Master; - - S9xSetController(0, (enum controllers) prevPortType[0], prevPortIDs[0][0], prevPortIDs[0][1], prevPortIDs[0][2], prevPortIDs[0][3]); - S9xSetController(1, (enum controllers) prevPortType[1], prevPortIDs[1][0], prevPortIDs[1][1], prevPortIDs[1][2], prevPortIDs[1][3]); -} - -static void store_movie_settings (void) -{ - for (int i = 0; i < 2; i++) - { - enum controllers pt; - S9xGetController(i, &pt, &Movie.PortIDs[i][0], &Movie.PortIDs[i][1], &Movie.PortIDs[i][2], &Movie.PortIDs[i][3]); - Movie.PortType[i] = (uint8) pt; - } -} - -static void restore_movie_settings (void) -{ - Settings.MouseMaster = (Movie.PortType[0] == CTL_MOUSE || Movie.PortType[1] == CTL_MOUSE); - Settings.SuperScopeMaster = (Movie.PortType[0] == CTL_SUPERSCOPE || Movie.PortType[1] == CTL_SUPERSCOPE); - Settings.JustifierMaster = (Movie.PortType[0] == CTL_JUSTIFIER || Movie.PortType[1] == CTL_JUSTIFIER); - Settings.MultiPlayer5Master = (Movie.PortType[0] == CTL_MP5 || Movie.PortType[1] == CTL_MP5); - - S9xSetController(0, (enum controllers) Movie.PortType[0], Movie.PortIDs[0][0], Movie.PortIDs[0][1], Movie.PortIDs[0][2], Movie.PortIDs[0][3]); - S9xSetController(1, (enum controllers) Movie.PortType[1], Movie.PortIDs[1][0], Movie.PortIDs[1][1], Movie.PortIDs[1][2], Movie.PortIDs[1][3]); -} - -static int bytes_per_sample (void) -{ - int num_controllers = 0; - - for (int i = 0; i < 8; i++) - { - if (Movie.ControllersMask & (1 << i)) - num_controllers++; - } - - int bytes = CONTROLLER_DATA_SIZE * num_controllers; - - for (int p = 0; p < 2; p++) - { - if (Movie.PortType[p] == CTL_MOUSE) - bytes += MOUSE_DATA_SIZE; - else - if (Movie.PortType[p] == CTL_SUPERSCOPE) - bytes += SCOPE_DATA_SIZE; - else - if (Movie.PortType[p] == CTL_JUSTIFIER) - bytes += JUSTIFIER_DATA_SIZE; - } - - return (bytes); -} - -static void reserve_buffer_space (uint32 space_needed) -{ - if (space_needed > Movie.InputBufferSize) - { - uint32 ptr_offset = Movie.InputBufferPtr - Movie.InputBuffer; - uint32 alloc_chunks = space_needed / BUFFER_GROWTH_SIZE; - - Movie.InputBufferSize = BUFFER_GROWTH_SIZE * (alloc_chunks + 1); - Movie.InputBuffer = (uint8 *) realloc(Movie.InputBuffer, Movie.InputBufferSize); - Movie.InputBufferPtr = Movie.InputBuffer + ptr_offset; - } -} - -static void reset_controllers (void) -{ - for (int i = 0; i < 8; i++) - MovieSetJoypad(i, 0); - - uint8 clearedMouse[MOUSE_DATA_SIZE]; - ZeroMemory(clearedMouse, MOUSE_DATA_SIZE); - clearedMouse[4] = 1; - - uint8 clearedScope[SCOPE_DATA_SIZE]; - ZeroMemory(clearedScope, SCOPE_DATA_SIZE); - - uint8 clearedJustifier[JUSTIFIER_DATA_SIZE]; - ZeroMemory(clearedJustifier, JUSTIFIER_DATA_SIZE); - - for (int p = 0; p < 2; p++) - { - MovieSetMouse(p, clearedMouse, true); - MovieSetScope(p, clearedScope); - MovieSetJustifier(p, clearedJustifier); - } -} - -static void read_frame_controller_data (bool addFrame) -{ - // reset code check - if (Movie.InputBufferPtr[0] == 0xff) - { - bool reset = true; - for (int i = 1; i < (int) Movie.BytesPerSample; i++) - { - if (Movie.InputBufferPtr[i] != 0xff) - { - reset = false; - break; - } - } - - if (reset) - { - Movie.InputBufferPtr += Movie.BytesPerSample; - S9xSoftReset(); - return; - } - } - - for (int i = 0; i < 8; i++) - { - if (Movie.ControllersMask & (1 << i)) - MovieSetJoypad(i, Read16(Movie.InputBufferPtr)); - else - MovieSetJoypad(i, 0); // pretend the controller is disconnected - } - - for (int p = 0; p < 2; p++) - { - if (Movie.PortType[p] == CTL_MOUSE) - { - uint8 buf[MOUSE_DATA_SIZE]; - memcpy(buf, Movie.InputBufferPtr, MOUSE_DATA_SIZE); - Movie.InputBufferPtr += MOUSE_DATA_SIZE; - MovieSetMouse(p, buf, !addFrame); - } - else - if (Movie.PortType[p] == CTL_SUPERSCOPE) - { - uint8 buf[SCOPE_DATA_SIZE]; - memcpy(buf, Movie.InputBufferPtr, SCOPE_DATA_SIZE); - Movie.InputBufferPtr += SCOPE_DATA_SIZE; - MovieSetScope(p, buf); - } - else - if (Movie.PortType[p] == CTL_JUSTIFIER) - { - uint8 buf[JUSTIFIER_DATA_SIZE]; - memcpy(buf, Movie.InputBufferPtr, JUSTIFIER_DATA_SIZE); - Movie.InputBufferPtr += JUSTIFIER_DATA_SIZE; - MovieSetJustifier(p, buf); - } - } -} - -static void write_frame_controller_data (void) -{ - reserve_buffer_space((uint32) (Movie.InputBufferPtr + Movie.BytesPerSample - Movie.InputBuffer)); - - for (int i = 0; i < 8; i++) - { - if (Movie.ControllersMask & (1 << i)) - Write16(MovieGetJoypad(i), Movie.InputBufferPtr); - else - MovieSetJoypad(i, 0); // pretend the controller is disconnected - } - - for (int p = 0; p < 2; p++) - { - if (Movie.PortType[p] == CTL_MOUSE) - { - uint8 buf[MOUSE_DATA_SIZE]; - MovieGetMouse(p, buf); - memcpy(Movie.InputBufferPtr, buf, MOUSE_DATA_SIZE); - Movie.InputBufferPtr += MOUSE_DATA_SIZE; - } - else - if (Movie.PortType[p] == CTL_SUPERSCOPE) - { - uint8 buf[SCOPE_DATA_SIZE]; - MovieGetScope(p, buf); - memcpy(Movie.InputBufferPtr, buf, SCOPE_DATA_SIZE); - Movie.InputBufferPtr += SCOPE_DATA_SIZE; - } - else - if (Movie.PortType[p] == CTL_JUSTIFIER) - { - uint8 buf[JUSTIFIER_DATA_SIZE]; - MovieGetJustifier(p, buf); - memcpy(Movie.InputBufferPtr, buf, JUSTIFIER_DATA_SIZE); - Movie.InputBufferPtr += JUSTIFIER_DATA_SIZE; - } - } -} - -static void flush_movie (void) -{ - if (!Movie.File) - return; - - fseek(Movie.File, 0, SEEK_SET); - write_movie_header(Movie.File, &Movie); - fseek(Movie.File, Movie.ControllerDataOffset, SEEK_SET); - fwrite(Movie.InputBuffer, 1, Movie.BytesPerSample * (Movie.MaxSample + 1), Movie.File); -} - -static void truncate_movie (void) -{ - if (!Movie.File || !Settings.MovieTruncate) - return; - - if (Movie.SaveStateOffset > Movie.ControllerDataOffset) - return; - - ftruncate(fileno(Movie.File), Movie.ControllerDataOffset + Movie.BytesPerSample * (Movie.MaxSample + 1)); -} - -static int read_movie_header (FILE *fd, SMovie *movie) -{ - uint32 value; - uint8 buf[SMV_HEADER_SIZE], *ptr = buf; - - if (fread(buf, 1, SMV_HEADER_SIZE, fd) != SMV_HEADER_SIZE) - return (WRONG_FORMAT); - - value = Read32(ptr); - if (value != SMV_MAGIC) - return (WRONG_FORMAT); - - value = Read32(ptr); - if(value > SMV_VERSION || value < 4) - return (WRONG_VERSION); - - movie->Version = value; - movie->MovieId = Read32(ptr); - movie->RerecordCount = Read32(ptr); - movie->MaxFrame = Read32(ptr); - movie->ControllersMask = Read8(ptr); - movie->Opts = Read8(ptr); - ptr++; - movie->SyncFlags = Read8(ptr); - movie->SaveStateOffset = Read32(ptr); - movie->ControllerDataOffset = Read32(ptr); - movie->MaxSample = Read32(ptr); - movie->PortType[0] = Read8(ptr); - movie->PortType[1] = Read8(ptr); - for (int p = 0; p < 2; p++) - { - for (int i = 0; i < 4; i++) - movie->PortIDs[p][i] = Read8(ptr); - } - - if (movie->MaxSample < movie->MaxFrame) - movie->MaxSample = movie->MaxFrame; - - return (SUCCESS); -} - -static int read_movie_extrarominfo (FILE *fd, SMovie *movie) -{ - uint8 buf[SMV_EXTRAROMINFO_SIZE], *ptr = buf; - - fseek(fd, movie->SaveStateOffset - SMV_EXTRAROMINFO_SIZE, SEEK_SET); - - if (fread(buf, 1, SMV_EXTRAROMINFO_SIZE, fd) != SMV_EXTRAROMINFO_SIZE) - return (WRONG_FORMAT); - - ptr += 3; // zero bytes - movie->ROMCRC32 = Read32(ptr); - strncpy(movie->ROMName, (char *) ptr, 23); - - return (SUCCESS); -} - -static void write_movie_header (FILE *fd, SMovie *movie) -{ - uint8 buf[SMV_HEADER_SIZE], *ptr = buf; - - ZeroMemory(buf, sizeof(buf)); - - Write32(SMV_MAGIC, ptr); - Write32(SMV_VERSION, ptr); - Write32(movie->MovieId, ptr); - Write32(movie->RerecordCount, ptr); - Write32(movie->MaxFrame, ptr); - Write8(movie->ControllersMask, ptr); - Write8(movie->Opts, ptr); - ptr++; - Write8(movie->SyncFlags, ptr); - Write32(movie->SaveStateOffset, ptr); - Write32(movie->ControllerDataOffset, ptr); - Write32(movie->MaxSample, ptr); - Write8(movie->PortType[0], ptr); - Write8(movie->PortType[1], ptr); - for (int p = 0; p < 2; p++) - { - for (int i = 0; i < 4; i++) - Write8(movie->PortIDs[p][i], ptr); - } - - fwrite(buf, 1, SMV_HEADER_SIZE, fd); -} - -static void write_movie_extrarominfo (FILE *fd, SMovie *movie) -{ - uint8 buf[SMV_EXTRAROMINFO_SIZE], *ptr = buf; - - Write8(0, ptr); - Write8(0, ptr); - Write8(0, ptr); - Write32(movie->ROMCRC32, ptr); - strncpy((char *) ptr, movie->ROMName, 23); - - fwrite(buf, 1, SMV_EXTRAROMINFO_SIZE, fd); -} - -static void change_state (MovieState new_state) -{ - if (new_state == Movie.State) - return; - - if (Movie.State == MOVIE_STATE_RECORD) - flush_movie(); - - if (new_state == MOVIE_STATE_NONE) - { - truncate_movie(); - fclose(Movie.File); - Movie.File = NULL; - - if (S9xMoviePlaying() || S9xMovieRecording()) - restore_previous_settings(); - } - - Movie.State = new_state; -} - -void S9xMovieFreeze (uint8 **buf, uint32 *size) -{ - if (!S9xMovieActive()) - return; - - uint32 size_needed; - uint8 *ptr; - - size_needed = sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample); - size_needed += (uint32) (Movie.BytesPerSample * (Movie.MaxSample + 1)); - *size = size_needed; - - *buf = new uint8[size_needed]; - ptr = *buf; - if (!ptr) - return; - - Write32(Movie.MovieId, ptr); - Write32(Movie.CurrentFrame, ptr); - Write32(Movie.MaxFrame, ptr); - Write32(Movie.CurrentSample, ptr); - Write32(Movie.MaxSample, ptr); - - memcpy(ptr, Movie.InputBuffer, Movie.BytesPerSample * (Movie.MaxSample + 1)); -} - -int S9xMovieUnfreeze (uint8 *buf, uint32 size) -{ - if (!S9xMovieActive()) - return (FILE_NOT_FOUND); - - if (size < sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample)) - return (WRONG_FORMAT); - - uint8 *ptr = buf; - - uint32 movie_id = Read32(ptr); - uint32 current_frame = Read32(ptr); - uint32 max_frame = Read32(ptr); - uint32 current_sample = Read32(ptr); - uint32 max_sample = Read32(ptr); - uint32 space_needed = (Movie.BytesPerSample * (max_sample + 1)); - - if (current_frame > max_frame || current_sample > max_sample || space_needed > size) - return (WRONG_MOVIE_SNAPSHOT); - - if (Settings.WrongMovieStateProtection) - if (movie_id != Movie.MovieId) - if (max_frame < Movie.MaxFrame || max_sample < Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) - return (WRONG_MOVIE_SNAPSHOT); - - if (!Movie.ReadOnly) - { - change_state(MOVIE_STATE_RECORD); - - Movie.CurrentFrame = current_frame; - Movie.MaxFrame = max_frame; - Movie.CurrentSample = current_sample; - Movie.MaxSample = max_sample; - Movie.RerecordCount++; - - store_movie_settings(); - - reserve_buffer_space(space_needed); - memcpy(Movie.InputBuffer, ptr, space_needed); - - flush_movie(); - fseek(Movie.File, Movie.ControllerDataOffset + (Movie.BytesPerSample * (Movie.CurrentSample + 1)), SEEK_SET); - } - else - { - if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) - return (SNAPSHOT_INCONSISTENT); - - change_state(MOVIE_STATE_PLAY); - - Movie.CurrentFrame = current_frame; - Movie.CurrentSample = current_sample; - } - - Movie.InputBufferPtr = Movie.InputBuffer + (Movie.BytesPerSample * Movie.CurrentSample); - read_frame_controller_data(true); - - return (SUCCESS); -} - -int S9xMovieOpen (const char *filename, bool8 read_only) -{ - FILE *fd; - STREAM stream; - int result; - int fn; - - if (!(fd = fopen(filename, "rb+"))) - { - if (!(fd = fopen(filename, "rb"))) - return (FILE_NOT_FOUND); - else - read_only = TRUE; - } - - change_state(MOVIE_STATE_NONE); - - result = read_movie_header(fd, &Movie); - if (result != SUCCESS) - { - fclose(fd); - return (result); - } - - read_movie_extrarominfo(fd, &Movie); - - fn = dup(fileno(fd)); - fclose(fd); - - store_previous_settings(); - restore_movie_settings(); - - lseek(fn, Movie.SaveStateOffset, SEEK_SET); - stream = REOPEN_STREAM(fn, "rb"); - if (!stream) - return (FILE_NOT_FOUND); - - if (Movie.Opts & MOVIE_OPT_FROM_RESET) - { - S9xReset(); - reset_controllers(); - result = (READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT; - } - else - result = S9xUnfreezeFromStream(stream); - - CLOSE_STREAM(stream); - - if (result != SUCCESS) - return (result); - - if (!(fd = fopen(filename, "rb+"))) - { - if (!(fd = fopen(filename, "rb"))) - return (FILE_NOT_FOUND); - else - read_only = TRUE; - } - - if (fseek(fd, Movie.ControllerDataOffset, SEEK_SET)) - return (WRONG_FORMAT); - - Movie.File = fd; - Movie.BytesPerSample = bytes_per_sample(); - Movie.InputBufferPtr = Movie.InputBuffer; - reserve_buffer_space(Movie.BytesPerSample * (Movie.MaxSample + 1)); - fread(Movie.InputBufferPtr, 1, Movie.BytesPerSample * (Movie.MaxSample + 1), fd); - - // read "baseline" controller data - if (Movie.MaxSample && Movie.MaxFrame) - read_frame_controller_data(true); - - Movie.CurrentFrame = 0; - Movie.CurrentSample = 0; - Movie.ReadOnly = read_only; - strncpy(Movie.Filename, filename, PATH_MAX + 1); - Movie.Filename[PATH_MAX] = 0; - - change_state(MOVIE_STATE_PLAY); - - S9xUpdateFrameCounter(-1); - - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY); - - return (SUCCESS); -} - -int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, const wchar_t *metadata, int metadata_length) -{ - FILE *fd; - STREAM stream; - int fn; - - if (controllers_mask == 0) - return (WRONG_FORMAT); - - if (!(fd = fopen(filename, "wb"))) - return (FILE_NOT_FOUND); - - if (metadata_length > MOVIE_MAX_METADATA) - metadata_length = MOVIE_MAX_METADATA; - - change_state(MOVIE_STATE_NONE); - - store_previous_settings(); - store_movie_settings(); - - Movie.MovieId = (uint32) time(NULL); - Movie.RerecordCount = 0; - Movie.MaxFrame = 0; - Movie.MaxSample = 0; - Movie.SaveStateOffset = SMV_HEADER_SIZE + (sizeof(uint16) * metadata_length) + SMV_EXTRAROMINFO_SIZE; - Movie.ControllerDataOffset = 0; - Movie.ControllersMask = controllers_mask; - Movie.Opts = opts; - Movie.SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO; - - write_movie_header(fd, &Movie); - - // convert wchar_t metadata string/array to a uint16 array - // XXX: UTF-8 is much better... - if (metadata_length > 0) - { - uint8 meta_buf[sizeof(uint16) * MOVIE_MAX_METADATA]; - for (int i = 0; i < metadata_length; i++) - { - uint16 c = (uint16) metadata[i]; - meta_buf[i * 2] = (uint8) (c & 0xff); - meta_buf[i * 2 + 1] = (uint8) ((c >> 8) & 0xff); - } - - fwrite(meta_buf, sizeof(uint16), metadata_length, fd); - } - - Movie.ROMCRC32 = Memory.ROMCRC32; - strncpy(Movie.ROMName, Memory.RawROMName, 23); - - write_movie_extrarominfo(fd, &Movie); - - fn = dup(fileno(fd)); - fclose(fd); - - stream = REOPEN_STREAM(fn, "ab"); - if (!stream) - return (FILE_NOT_FOUND); - - if (opts & MOVIE_OPT_FROM_RESET) - { - S9xReset(); - reset_controllers(); - WRITE_STREAM(Memory.SRAM, 0x20000, stream); - } - else - S9xFreezeToStream(stream); - - CLOSE_STREAM(stream); - - if (!(fd = fopen(filename, "rb+"))) - return (FILE_NOT_FOUND); - - fseek(fd, 0, SEEK_END); - Movie.ControllerDataOffset = (uint32) ftell(fd); - - // 16-byte align the controller input, for hex-editing friendliness if nothing else - while (Movie.ControllerDataOffset % 16) - { - fputc(0xcc, fd); // arbitrary - Movie.ControllerDataOffset++; - } - - // write "baseline" controller data - Movie.File = fd; - Movie.BytesPerSample = bytes_per_sample(); - Movie.InputBufferPtr = Movie.InputBuffer; - write_frame_controller_data(); - - Movie.CurrentFrame = 0; - Movie.CurrentSample = 0; - Movie.ReadOnly = false; - strncpy(Movie.Filename, filename, PATH_MAX + 1); - Movie.Filename[PATH_MAX] = 0; - - change_state(MOVIE_STATE_RECORD); - - S9xUpdateFrameCounter(-1); - - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_RECORD); - - return (SUCCESS); -} - -int S9xMovieGetInfo (const char *filename, struct MovieInfo *info) -{ - FILE *fd; - SMovie local_movie; - int metadata_length; - int result, i; - - flush_movie(); - - ZeroMemory(info, sizeof(*info)); - - if (!(fd = fopen(filename, "rb"))) - return (FILE_NOT_FOUND); - - result = read_movie_header(fd, &local_movie); - if (result != SUCCESS) - return (result); - - info->TimeCreated = (time_t) local_movie.MovieId; - info->Version = local_movie.Version; - info->Opts = local_movie.Opts; - info->SyncFlags = local_movie.SyncFlags; - info->ControllersMask = local_movie.ControllersMask; - info->RerecordCount = local_movie.RerecordCount; - info->LengthFrames = local_movie.MaxFrame; - info->LengthSamples = local_movie.MaxSample; - info->PortType[0] = local_movie.PortType[0]; - info->PortType[1] = local_movie.PortType[1]; - - if (local_movie.SaveStateOffset > SMV_HEADER_SIZE) - { - uint8 meta_buf[sizeof(uint16) * MOVIE_MAX_METADATA]; - int curRomInfoSize = (local_movie.SyncFlags & MOVIE_SYNC_HASROMINFO) ? SMV_EXTRAROMINFO_SIZE : 0; - - metadata_length = ((int) local_movie.SaveStateOffset - SMV_HEADER_SIZE - curRomInfoSize) / sizeof(uint16); - metadata_length = (metadata_length >= MOVIE_MAX_METADATA) ? MOVIE_MAX_METADATA - 1 : metadata_length; - metadata_length = (int) fread(meta_buf, sizeof(uint16), metadata_length, fd); - - for (i = 0; i < metadata_length; i++) - { - uint16 c = meta_buf[i * 2] | (meta_buf[i * 2 + 1] << 8); - info->Metadata[i] = (wchar_t) c; - } - - info->Metadata[i] = '\0'; - } - else - info->Metadata[0] = '\0'; - - read_movie_extrarominfo(fd, &local_movie); - - info->ROMCRC32 = local_movie.ROMCRC32; - strncpy(info->ROMName, local_movie.ROMName, 23); - - fclose(fd); - - if (access(filename, W_OK)) - info->ReadOnly = true; - - return (SUCCESS); -} - -void S9xMovieUpdate (bool addFrame) -{ - switch (Movie.State) - { - case MOVIE_STATE_PLAY: - { - if (Movie.CurrentFrame >= Movie.MaxFrame || Movie.CurrentSample >= Movie.MaxSample) - { - change_state(MOVIE_STATE_NONE); - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_END); - return; - } - else - { - if (addFrame) - S9xUpdateFrameCounter(); - else - if (SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) - return; - - read_frame_controller_data(addFrame); - Movie.CurrentSample++; - if (addFrame) - Movie.CurrentFrame++; - } - - break; - } - - case MOVIE_STATE_RECORD: - { - if (addFrame) - S9xUpdateFrameCounter(); - else - if (SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) - return; - - write_frame_controller_data(); - Movie.MaxSample = ++Movie.CurrentSample; - if (addFrame) - Movie.MaxFrame = ++Movie.CurrentFrame; - fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); - - break; - } - - default: - { - if (addFrame) - S9xUpdateFrameCounter(); - - break; - } - } -} - -void S9xMovieUpdateOnReset (void) -{ - if (Movie.State == MOVIE_STATE_RECORD) - { - reserve_buffer_space((uint32) (Movie.InputBufferPtr + Movie.BytesPerSample - Movie.InputBuffer)); - memset(Movie.InputBufferPtr, 0xFF, Movie.BytesPerSample); - Movie.InputBufferPtr += Movie.BytesPerSample; - Movie.MaxSample = ++Movie.CurrentSample; - Movie.MaxFrame = ++Movie.CurrentFrame; - fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); - } -} - -void S9xMovieInit (void) -{ - ZeroMemory(&Movie, sizeof(Movie)); - Movie.State = MOVIE_STATE_NONE; -} - -void S9xMovieStop (bool8 suppress_message) -{ - if (Movie.State != MOVIE_STATE_NONE) - { - change_state(MOVIE_STATE_NONE); - - if (!suppress_message) - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_STOP); - } -} - -void S9xMovieShutdown (void) -{ - if (S9xMovieActive()) - S9xMovieStop(TRUE); -} - -bool8 S9xMovieActive (void) -{ - return (Movie.State != MOVIE_STATE_NONE); -} - -bool8 S9xMoviePlaying (void) -{ - return (Movie.State == MOVIE_STATE_PLAY); -} - -bool8 S9xMovieRecording (void) -{ - return (Movie.State == MOVIE_STATE_RECORD); -} - -uint8 S9xMovieControllers (void) -{ - return (Movie.ControllersMask); -} - -bool8 S9xMovieReadOnly (void) -{ - if (!S9xMovieActive()) - return (FALSE); - return (Movie.ReadOnly); -} - -uint32 S9xMovieGetId (void) -{ - if (!S9xMovieActive()) - return (0); - return (Movie.MovieId); -} - -uint32 S9xMovieGetLength (void) -{ - if (!S9xMovieActive()) - return (0); - return (Movie.MaxFrame); -} - -uint32 S9xMovieGetFrameCounter (void) -{ - if (!S9xMovieActive()) - return (0); - return (Movie.CurrentFrame); -} - -void S9xMovieToggleRecState (void) -{ - Movie.ReadOnly = !Movie.ReadOnly; - - if (Movie.ReadOnly) - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read-only."); - else - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read+write."); -} - -void S9xMovieToggleFrameDisplay (void) -{ - Settings.DisplayMovieFrame = !Settings.DisplayMovieFrame; - S9xReRefresh(); -} - -void S9xUpdateFrameCounter (int offset) -{ - extern bool8 pad_read; - - offset++; - - if (!Settings.DisplayMovieFrame) - *GFX.FrameDisplayString = 0; - else - if (Movie.State == MOVIE_STATE_RECORD) - sprintf(GFX.FrameDisplayString, "Recording frame: %d%s", - max(0, (int) (Movie.CurrentFrame + offset)), pad_read || !Settings.MovieNotifyIgnored ? "" : " (ignored)"); - else - if (Movie.State == MOVIE_STATE_PLAY) - sprintf(GFX.FrameDisplayString, "Playing frame: %d / %d", - max(0, (int) (Movie.CurrentFrame + offset)), Movie.MaxFrame); -#ifdef NETPLAY_SUPPORT - else - if (Settings.NetPlay) - sprintf(GFX.FrameDisplayString, "%s frame: %d", Settings.NetPlayServer ? "Server" : "Client", - max(0, (int) (NetPlay.FrameCount + offset))); -#endif -} diff --git a/source/snes9x/movie.h b/source/snes9x/movie.h deleted file mode 100644 index 293aa7c..0000000 --- a/source/snes9x/movie.h +++ /dev/null @@ -1,241 +0,0 @@ -/********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com) - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley, - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001-2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight, - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound DSP emulator code is derived from SNEeSe and OpenSPC: - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2007 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -**********************************************************************************/ - -// Input recording/playback code -// (c) Copyright 2004 blip - - -#ifndef _MOVIE_H_ -#define _MOVIE_H_ - -#define MOVIE_OPT_FROM_SNAPSHOT 0 -#define MOVIE_OPT_FROM_RESET (1 << 0) -#define MOVIE_OPT_PAL (1 << 1) -#define MOVIE_OPT_NOSAVEDATA (1 << 2) -#define MOVIE_SYNC_DATA_EXISTS 0x01 -#define MOVIE_SYNC_OBSOLETE 0x02 -#define MOVIE_SYNC_LEFTRIGHT 0x04 -#define MOVIE_SYNC_VOLUMEENVX 0x08 -#define MOVIE_SYNC_FAKEMUTE 0x10 -#define MOVIE_SYNC_SYNCSOUND 0x20 -#define MOVIE_SYNC_HASROMINFO 0x40 -#define MOVIE_SYNC_NOCPUSHUTDOWN 0x80 -#define MOVIE_MAX_METADATA 512 - -#define CONTROLLER_DATA_SIZE 2 -#define MOUSE_DATA_SIZE 5 -#define SCOPE_DATA_SIZE 6 -#define JUSTIFIER_DATA_SIZE 11 - -struct MovieInfo -{ - time_t TimeCreated; - uint32 Version; - uint32 LengthFrames; - uint32 LengthSamples; - uint32 RerecordCount; - uint8 Opts; - uint8 ControllersMask; - uint8 SyncFlags; - bool8 ReadOnly; - uint8 PortType[2]; - wchar_t Metadata[MOVIE_MAX_METADATA]; - uint32 ROMCRC32; - char ROMName[23]; -}; - -// methods used by the user-interface code -int S9xMovieOpen (const char *, bool8); -int S9xMovieCreate (const char *, uint8, uint8, const wchar_t *, int); -int S9xMovieGetInfo (const char *, struct MovieInfo *); -void S9xMovieStop (bool8); -void S9xMovieToggleRecState (void); -void S9xMovieToggleFrameDisplay (void); -const char * S9xChooseMovieFilename (bool8); - -// methods used by the emulation -void S9xMovieInit (void); -void S9xMovieShutdown (void); -void S9xMovieUpdate (bool a = true); -void S9xMovieUpdateOnReset (void); -void S9xUpdateFrameCounter (int o = 0); -void S9xMovieFreeze (uint8 **, uint32 *); -int S9xMovieUnfreeze (uint8 *, uint32); - -// accessor functions -bool8 S9xMovieActive (void); -bool8 S9xMoviePlaying (void); -bool8 S9xMovieRecording (void); -bool8 S9xMovieReadOnly (void); -uint8 S9xMovieControllers (void); -uint32 S9xMovieGetId (void); -uint32 S9xMovieGetLength (void); -uint32 S9xMovieGetFrameCounter (void); - -uint16 MovieGetJoypad (int); -void MovieSetJoypad (int, uint16); -bool MovieGetMouse (int, uint8 d[MOUSE_DATA_SIZE]); -void MovieSetMouse (int, uint8 d[MOUSE_DATA_SIZE], bool); -bool MovieGetScope (int, uint8 d[SCOPE_DATA_SIZE]); -void MovieSetScope (int, uint8 d[SCOPE_DATA_SIZE]); -bool MovieGetJustifier (int, uint8 d[JUSTIFIER_DATA_SIZE]); -void MovieSetJustifier (int, uint8 d[JUSTIFIER_DATA_SIZE]); - -#endif diff --git a/source/snes9x/obc1.cpp b/source/snes9x/obc1.cpp index d4f86d6..edb8193 100644 --- a/source/snes9x/obc1.cpp +++ b/source/snes9x/obc1.cpp @@ -159,102 +159,124 @@ **********************************************************************************/ -#include "snes9x.h" + +#include #include "memmap.h" +#include "obc1.h" +static uint8 *OBC1_RAM = NULL; -uint8 S9xGetOBC1 (uint16 Address) +int OBC1_Address; +int OBC1_BasePtr; +int OBC1_Shift; + +extern "C" { - switch (Address) - { +uint8 GetOBC1 (uint16 Address) +{ + switch(Address) { case 0x7ff0: - return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)]); + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)]; case 0x7ff1: - return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1]); + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1]; case 0x7ff2: - return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2]); + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2]; case 0x7ff3: - return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3]); + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3]; case 0x7ff4: - return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]); + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; } - return (Memory.OBC1RAM[Address - 0x6000]); + return OBC1_RAM[Address & 0x1fff]; } -void S9xSetOBC1 (uint8 Byte, uint16 Address) +void SetOBC1 (uint8 Byte, uint16 Address) { - switch (Address) - { + switch(Address) { case 0x7ff0: - Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)] = Byte; + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)] = Byte; break; + } case 0x7ff1: - Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1] = Byte; + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1] = Byte; break; + } case 0x7ff2: - Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2] = Byte; + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2] = Byte; break; + } case 0x7ff3: - Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3] = Byte; + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3] = Byte; break; + } case 0x7ff4: { - uint8 Temp; - Temp = Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]; - Temp = (Temp & ~(3 << OBC1.shift)) | ((Byte & 3) << OBC1.shift); - Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200] = Temp; + unsigned char Temp; + + Temp = OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; + Temp = (Temp & ~(3 << OBC1_Shift)) | ((Byte & 3) << OBC1_Shift); + OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200] = Temp; break; } case 0x7ff5: + { if (Byte & 1) - OBC1.basePtr = 0x1800; + OBC1_BasePtr = 0x1800; else - OBC1.basePtr = 0x1c00; + OBC1_BasePtr = 0x1c00; + break; + } case 0x7ff6: - OBC1.address = Byte & 0x7f; - OBC1.shift = (Byte & 3) << 1; + { + OBC1_Address = Byte & 0x7f; + OBC1_Shift = (Byte & 3) << 1; break; + } } - Memory.OBC1RAM[Address - 0x6000] = Byte; -} - -void S9xResetOBC1 (void) -{ - for (int i = 0; i <= 0x1fff; i++) - Memory.OBC1RAM[i] = 0xff; - - if (Memory.OBC1RAM[0x1ff5] & 1) - OBC1.basePtr = 0x1800; - else - OBC1.basePtr = 0x1c00; - - OBC1.address = Memory.OBC1RAM[0x1ff6] & 0x7f; - OBC1.shift = (Memory.OBC1RAM[0x1ff6] & 3) << 1; + OBC1_RAM[Address & 0x1fff] = Byte; } uint8 * S9xGetBasePointerOBC1 (uint16 Address) { if (Address >= 0x7ff0 && Address <= 0x7ff6) return (NULL); - return (Memory.OBC1RAM - 0x6000); + return (OBC1_RAM - 0x6000); } uint8 * S9xGetMemPointerOBC1 (uint16 Address) { if (Address >= 0x7ff0 && Address <= 0x7ff6) return (NULL); - return (Memory.OBC1RAM + Address - 0x6000); + return (OBC1_RAM - 0x6000 + (Address & 0xffff)); +} + +void ResetOBC1() +{ + OBC1_RAM = &Memory.FillRAM[0x6000]; + + if (OBC1_RAM[0x1ff5] & 1) + OBC1_BasePtr = 0x1800; + else + OBC1_BasePtr = 0x1c00; + + OBC1_Address = OBC1_RAM[0x1ff6] & 0x7f; + OBC1_Shift = (OBC1_RAM[0x1ff6] & 3) << 1; +} + } diff --git a/source/snes9x/obc1.h b/source/snes9x/obc1.h index 0153183..9177693 100644 --- a/source/snes9x/obc1.h +++ b/source/snes9x/obc1.h @@ -159,22 +159,18 @@ **********************************************************************************/ + + #ifndef _OBC1_H_ #define _OBC1_H_ -struct SOBC1 -{ - uint16 address; - uint16 basePtr; - uint16 shift; -}; - -extern struct SOBC1 OBC1; - -void S9xSetOBC1 (uint8, uint16); -uint8 S9xGetOBC1 (uint16); -void S9xResetOBC1 (void); +START_EXTERN_C +uint8 GetOBC1 (uint16 Address); +void SetOBC1 (uint8 Byte, uint16 Address); uint8 * S9xGetBasePointerOBC1 (uint16); uint8 * S9xGetMemPointerOBC1 (uint16); +void ResetOBC1();//bool8 full); +END_EXTERN_C #endif + diff --git a/source/snes9x/pixform.h b/source/snes9x/pixform.h index fa58f19..bdda64c 100644 --- a/source/snes9x/pixform.h +++ b/source/snes9x/pixform.h @@ -159,6 +159,8 @@ **********************************************************************************/ + + #ifndef _PIXFORM_H_ #define _PIXFORM_H_ @@ -166,226 +168,229 @@ enum { RGB565, RGB555, BGR565, BGR555, GBR565, GBR555, RGB5551 }; -#define BUILD_PIXEL(R, G, B) ((*GFX.BuildPixel) (R, G, B)) -#define BUILD_PIXEL2(R, G, B) ((*GFX.BuildPixel2) (R, G, B)) -#define DECOMPOSE_PIXEL(PIX, R, G, B) ((*GFX.DecomposePixel) (PIX, R, G, B)) +#define BUILD_PIXEL(R,G,B) ((*GFX.BuildPixel) (R, G, B)) +#define BUILD_PIXEL2(R,G,B) ((*GFX.BuildPixel2) (R, G, B)) +#define DECOMPOSE_PIXEL(Pixel,R,G,B) ((*GFX.DecomposePixel) (Pixel, R,G,B)) -extern uint32 MAX_RED; -extern uint32 MAX_GREEN; -extern uint32 MAX_BLUE; -extern uint32 RED_LOW_BIT_MASK; -extern uint32 GREEN_LOW_BIT_MASK; -extern uint32 BLUE_LOW_BIT_MASK; -extern uint32 RED_HI_BIT_MASK; -extern uint32 GREEN_HI_BIT_MASK; -extern uint32 BLUE_HI_BIT_MASK; -extern uint32 FIRST_COLOR_MASK; -extern uint32 SECOND_COLOR_MASK; -extern uint32 THIRD_COLOR_MASK; -extern uint32 ALPHA_BITS_MASK; -extern uint32 GREEN_HI_BIT; -extern uint32 RGB_LOW_BITS_MASK; -extern uint32 RGB_HI_BITS_MASK; -extern uint32 RGB_HI_BITS_MASKx2; -extern uint32 RGB_REMOVE_LOW_BITS_MASK; -extern uint32 FIRST_THIRD_COLOR_MASK; -extern uint32 TWO_LOW_BITS_MASK; -extern uint32 HIGH_BITS_SHIFTED_TWO_MASK; -extern uint32 SPARE_RGB_BIT_MASK; +extern uint32 RED_LOW_BIT_MASK; +extern uint32 GREEN_LOW_BIT_MASK; +extern uint32 BLUE_LOW_BIT_MASK; +extern uint32 RED_HI_BIT_MASK; +extern uint32 GREEN_HI_BIT_MASK; +extern uint32 BLUE_HI_BIT_MASK; +extern uint32 MAX_RED; +extern uint32 MAX_GREEN; +extern uint32 MAX_BLUE; +extern uint32 SPARE_RGB_BIT_MASK; +extern uint32 GREEN_HI_BIT; +extern uint32 RGB_LOW_BITS_MASK; +extern uint32 RGB_HI_BITS_MASK; +extern uint32 RGB_HI_BITS_MASKx2; +extern uint32 RGB_REMOVE_LOW_BITS_MASK; +extern uint32 FIRST_COLOR_MASK; +extern uint32 SECOND_COLOR_MASK; +extern uint32 THIRD_COLOR_MASK; +extern uint32 ALPHA_BITS_MASK; +extern uint32 FIRST_THIRD_COLOR_MASK; +extern uint32 TWO_LOW_BITS_MASK; +extern uint32 HIGH_BITS_SHIFTED_TWO_MASK; #endif /* RGB565 format */ -#define BUILD_PIXEL_RGB565(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) (B)) -#define BUILD_PIXEL2_RGB565(R, G, B) (((int) (R) << 11) | ((int) (G) << 5) | (int) (B)) -#define DECOMPOSE_PIXEL_RGB565(PIX, R, G, B) { (R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = (PIX) & 0x1f; } -#define SPARE_RGB_BIT_MASK_RGB565 (1 << 5) +#define BUILD_PIXEL_RGB565(R,G,B) (((int) (R) << 11) | ((int) (G) << 6) | (int) (B)) +#define BUILD_PIXEL2_RGB565(R,G,B) (((int) (R) << 11) | ((int) (G) << 5) | (int) (B)) +#define DECOMPOSE_PIXEL_RGB565(PIX,R,G,B) {(R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB565 (1 << 5) -#define MAX_RED_RGB565 31 -#define MAX_GREEN_RGB565 63 -#define MAX_BLUE_RGB565 31 -#define RED_LOW_BIT_MASK_RGB565 0x0800 -#define GREEN_LOW_BIT_MASK_RGB565 0x0020 -#define BLUE_LOW_BIT_MASK_RGB565 0x0001 -#define RED_HI_BIT_MASK_RGB565 0x8000 -#define GREEN_HI_BIT_MASK_RGB565 0x0400 -#define BLUE_HI_BIT_MASK_RGB565 0x0010 -#define FIRST_COLOR_MASK_RGB565 0xF800 -#define SECOND_COLOR_MASK_RGB565 0x07E0 -#define THIRD_COLOR_MASK_RGB565 0x001F -#define ALPHA_BITS_MASK_RGB565 0x0000 +#define MAX_RED_RGB565 31 +#define MAX_GREEN_RGB565 63 +#define MAX_BLUE_RGB565 31 +#define RED_LOW_BIT_MASK_RGB565 0x0800 +#define GREEN_LOW_BIT_MASK_RGB565 0x0020 +#define BLUE_LOW_BIT_MASK_RGB565 0x0001 +#define RED_HI_BIT_MASK_RGB565 0x8000 +#define GREEN_HI_BIT_MASK_RGB565 0x0400 +#define BLUE_HI_BIT_MASK_RGB565 0x0010 +#define FIRST_COLOR_MASK_RGB565 0xF800 +#define SECOND_COLOR_MASK_RGB565 0x07E0 +#define THIRD_COLOR_MASK_RGB565 0x001F +#define ALPHA_BITS_MASK_RGB565 0x0000 /* RGB555 format */ -#define BUILD_PIXEL_RGB555(R, G, B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) -#define BUILD_PIXEL2_RGB555(R, G, B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) -#define DECOMPOSE_PIXEL_RGB555(PIX, R, G, B) { (R) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (B) = (PIX) & 0x1f; } -#define SPARE_RGB_BIT_MASK_RGB555 (1 << 15) +#define BUILD_PIXEL_RGB555(R,G,B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) +#define BUILD_PIXEL2_RGB555(R,G,B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) +#define DECOMPOSE_PIXEL_RGB555(PIX,R,G,B) {(R) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (B) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB555 (1 << 15) -#define MAX_RED_RGB555 31 -#define MAX_GREEN_RGB555 31 -#define MAX_BLUE_RGB555 31 -#define RED_LOW_BIT_MASK_RGB555 0x0400 -#define GREEN_LOW_BIT_MASK_RGB555 0x0020 -#define BLUE_LOW_BIT_MASK_RGB555 0x0001 -#define RED_HI_BIT_MASK_RGB555 0x4000 -#define GREEN_HI_BIT_MASK_RGB555 0x0200 -#define BLUE_HI_BIT_MASK_RGB555 0x0010 -#define FIRST_COLOR_MASK_RGB555 0x7C00 -#define SECOND_COLOR_MASK_RGB555 0x03E0 -#define THIRD_COLOR_MASK_RGB555 0x001F -#define ALPHA_BITS_MASK_RGB555 0x0000 +#define MAX_RED_RGB555 31 +#define MAX_GREEN_RGB555 31 +#define MAX_BLUE_RGB555 31 +#define RED_LOW_BIT_MASK_RGB555 0x0400 +#define GREEN_LOW_BIT_MASK_RGB555 0x0020 +#define BLUE_LOW_BIT_MASK_RGB555 0x0001 +#define RED_HI_BIT_MASK_RGB555 0x4000 +#define GREEN_HI_BIT_MASK_RGB555 0x0200 +#define BLUE_HI_BIT_MASK_RGB555 0x0010 +#define FIRST_COLOR_MASK_RGB555 0x7C00 +#define SECOND_COLOR_MASK_RGB555 0x03E0 +#define THIRD_COLOR_MASK_RGB555 0x001F +#define ALPHA_BITS_MASK_RGB555 0x0000 /* BGR565 format */ -#define BUILD_PIXEL_BGR565(R, G, B) (((int) (B) << 11) | ((int) (G) << 6) | (int) (R)) -#define BUILD_PIXEL2_BGR565(R, G, B) (((int) (B) << 11) | ((int) (G) << 5) | (int) (R)) -#define DECOMPOSE_PIXEL_BGR565(PIX, R, G, B) { (B) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } -#define SPARE_RGB_BIT_MASK_BGR565 (1 << 5) +#define BUILD_PIXEL_BGR565(R,G,B) (((int) (B) << 11) | ((int) (G) << 6) | (int) (R)) +#define BUILD_PIXEL2_BGR565(R,G,B) (((int) (B) << 11) | ((int) (G) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_BGR565(PIX,R,G,B) {(B) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_BGR565 (1 << 5) -#define MAX_RED_BGR565 31 -#define MAX_GREEN_BGR565 63 -#define MAX_BLUE_BGR565 31 -#define RED_LOW_BIT_MASK_BGR565 0x0001 -#define GREEN_LOW_BIT_MASK_BGR565 0x0040 -#define BLUE_LOW_BIT_MASK_BGR565 0x0800 -#define RED_HI_BIT_MASK_BGR565 0x0010 -#define GREEN_HI_BIT_MASK_BGR565 0x0400 -#define BLUE_HI_BIT_MASK_BGR565 0x8000 -#define FIRST_COLOR_MASK_BGR565 0xF800 -#define SECOND_COLOR_MASK_BGR565 0x07E0 -#define THIRD_COLOR_MASK_BGR565 0x001F -#define ALPHA_BITS_MASK_BGR565 0x0000 +#define MAX_RED_BGR565 31 +#define MAX_GREEN_BGR565 63 +#define MAX_BLUE_BGR565 31 +#define RED_LOW_BIT_MASK_BGR565 0x0001 +#define GREEN_LOW_BIT_MASK_BGR565 0x0040 +#define BLUE_LOW_BIT_MASK_BGR565 0x0800 +#define RED_HI_BIT_MASK_BGR565 0x0010 +#define GREEN_HI_BIT_MASK_BGR565 0x0400 +#define BLUE_HI_BIT_MASK_BGR565 0x8000 +#define FIRST_COLOR_MASK_BGR565 0xF800 +#define SECOND_COLOR_MASK_BGR565 0x07E0 +#define THIRD_COLOR_MASK_BGR565 0x001F +#define ALPHA_BITS_MASK_BGR565 0x0000 /* BGR555 format */ -#define BUILD_PIXEL_BGR555(R, G, B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) -#define BUILD_PIXEL2_BGR555(R, G, B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) -#define DECOMPOSE_PIXEL_BGR555(PIX, R, G, B) { (B) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } -#define SPARE_RGB_BIT_MASK_BGR555 (1 << 15) +#define BUILD_PIXEL_BGR555(R,G,B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) +#define BUILD_PIXEL2_BGR555(R,G,B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_BGR555(PIX,R,G,B) {(B) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_BGR555 (1 << 15) -#define MAX_RED_BGR555 31 -#define MAX_GREEN_BGR555 31 -#define MAX_BLUE_BGR555 31 -#define RED_LOW_BIT_MASK_BGR555 0x0001 -#define GREEN_LOW_BIT_MASK_BGR555 0x0020 -#define BLUE_LOW_BIT_MASK_BGR555 0x0400 -#define RED_HI_BIT_MASK_BGR555 0x0010 -#define GREEN_HI_BIT_MASK_BGR555 0x0200 -#define BLUE_HI_BIT_MASK_BGR555 0x4000 -#define FIRST_COLOR_MASK_BGR555 0x7C00 -#define SECOND_COLOR_MASK_BGR555 0x03E0 -#define THIRD_COLOR_MASK_BGR555 0x001F -#define ALPHA_BITS_MASK_BGR555 0x0000 +#define MAX_RED_BGR555 31 +#define MAX_GREEN_BGR555 31 +#define MAX_BLUE_BGR555 31 +#define RED_LOW_BIT_MASK_BGR555 0x0001 +#define GREEN_LOW_BIT_MASK_BGR555 0x0020 +#define BLUE_LOW_BIT_MASK_BGR555 0x0400 +#define RED_HI_BIT_MASK_BGR555 0x0010 +#define GREEN_HI_BIT_MASK_BGR555 0x0200 +#define BLUE_HI_BIT_MASK_BGR555 0x4000 +#define FIRST_COLOR_MASK_BGR555 0x7C00 +#define SECOND_COLOR_MASK_BGR555 0x03E0 +#define THIRD_COLOR_MASK_BGR555 0x001F +#define ALPHA_BITS_MASK_BGR555 0x0000 /* GBR565 format */ -#define BUILD_PIXEL_GBR565(R, G, B) (((int) (G) << 11) | ((int) (B) << 6) | (int) (R)) -#define BUILD_PIXEL2_GBR565(R, G, B) (((int) (G) << 11) | ((int) (B) << 5) | (int) (R)) -#define DECOMPOSE_PIXEL_GBR565(PIX, R, G, B) { (G) = (PIX) >> 11; (B) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } -#define SPARE_RGB_BIT_MASK_GBR565 (1 << 5) +#define BUILD_PIXEL_GBR565(R,G,B) (((int) (G) << 11) | ((int) (B) << 6) | (int) (R)) +#define BUILD_PIXEL2_GBR565(R,G,B) (((int) (G) << 11) | ((int) (B) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_GBR565(PIX,R,G,B) {(G) = (PIX) >> 11; (B) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_GBR565 (1 << 5) -#define MAX_RED_GBR565 31 -#define MAX_GREEN_GBR565 31 -#define MAX_BLUE_GBR565 63 -#define RED_LOW_BIT_MASK_GBR565 0x0001 -#define GREEN_LOW_BIT_MASK_GBR565 0x0800 -#define BLUE_LOW_BIT_MASK_GBR565 0x0040 -#define RED_HI_BIT_MASK_GBR565 0x0010 -#define GREEN_HI_BIT_MASK_GBR565 0x8000 -#define BLUE_HI_BIT_MASK_GBR565 0x0400 -#define FIRST_COLOR_MASK_GBR565 0xF800 -#define SECOND_COLOR_MASK_GBR565 0x07E0 -#define THIRD_COLOR_MASK_GBR565 0x001F -#define ALPHA_BITS_MASK_GBR565 0x0000 +#define MAX_RED_GBR565 31 +#define MAX_BLUE_GBR565 63 +#define MAX_GREEN_GBR565 31 +#define RED_LOW_BIT_MASK_GBR565 0x0001 +#define BLUE_LOW_BIT_MASK_GBR565 0x0040 +#define GREEN_LOW_BIT_MASK_GBR565 0x0800 +#define RED_HI_BIT_MASK_GBR565 0x0010 +#define BLUE_HI_BIT_MASK_GBR565 0x0400 +#define GREEN_HI_BIT_MASK_GBR565 0x8000 +#define FIRST_COLOR_MASK_GBR565 0xF800 +#define SECOND_COLOR_MASK_GBR565 0x07E0 +#define THIRD_COLOR_MASK_GBR565 0x001F +#define ALPHA_BITS_MASK_GBR565 0x0000 /* GBR555 format */ -#define BUILD_PIXEL_GBR555(R, G, B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) -#define BUILD_PIXEL2_GBR555(R, G, B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) -#define DECOMPOSE_PIXEL_GBR555(PIX, R, G, B) { (G) = (PIX) >> 10; (B) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } -#define SPARE_RGB_BIT_MASK_GBR555 (1 << 15) +#define BUILD_PIXEL_GBR555(R,G,B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) +#define BUILD_PIXEL2_GBR555(R,G,B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_GBR555(PIX,R,G,B) {(G) = (PIX) >> 10; (B) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_GBR555 (1 << 15) -#define MAX_RED_GBR555 31 -#define MAX_GREEN_GBR555 31 -#define MAX_BLUE_GBR555 31 -#define RED_LOW_BIT_MASK_GBR555 0x0001 -#define GREEN_LOW_BIT_MASK_GBR555 0x0400 -#define BLUE_LOW_BIT_MASK_GBR555 0x0020 -#define RED_HI_BIT_MASK_GBR555 0x0010 -#define GREEN_HI_BIT_MASK_GBR555 0x4000 -#define BLUE_HI_BIT_MASK_GBR555 0x0200 -#define FIRST_COLOR_MASK_GBR555 0x7C00 -#define SECOND_COLOR_MASK_GBR555 0x03E0 -#define THIRD_COLOR_MASK_GBR555 0x001F -#define ALPHA_BITS_MASK_GBR555 0x0000 +#define MAX_RED_GBR555 31 +#define MAX_BLUE_GBR555 31 +#define MAX_GREEN_GBR555 31 +#define RED_LOW_BIT_MASK_GBR555 0x0001 +#define BLUE_LOW_BIT_MASK_GBR555 0x0020 +#define GREEN_LOW_BIT_MASK_GBR555 0x0400 +#define RED_HI_BIT_MASK_GBR555 0x0010 +#define BLUE_HI_BIT_MASK_GBR555 0x0200 +#define GREEN_HI_BIT_MASK_GBR555 0x4000 +#define FIRST_COLOR_MASK_GBR555 0x7C00 +#define SECOND_COLOR_MASK_GBR555 0x03E0 +#define THIRD_COLOR_MASK_GBR555 0x001F +#define ALPHA_BITS_MASK_GBR555 0x0000 /* RGB5551 format */ -#define BUILD_PIXEL_RGB5551(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) -#define BUILD_PIXEL2_RGB5551(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) -#define DECOMPOSE_PIXEL_RGB5551(PIX, R, G, B) { (R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = ((PIX) >> 1) & 0x1f; } -#define SPARE_RGB_BIT_MASK_RGB5551 (1) +#define BUILD_PIXEL_RGB5551(R,G,B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) +#define BUILD_PIXEL2_RGB5551(R,G,B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) +#define DECOMPOSE_PIXEL_RGB5551(PIX,R,G,B) {(R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = ((PIX) >> 1) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB5551 (1) -#define MAX_RED_RGB5551 31 -#define MAX_GREEN_RGB5551 31 -#define MAX_BLUE_RGB5551 31 -#define RED_LOW_BIT_MASK_RGB5551 0x0800 -#define GREEN_LOW_BIT_MASK_RGB5551 0x0040 -#define BLUE_LOW_BIT_MASK_RGB5551 0x0002 -#define RED_HI_BIT_MASK_RGB5551 0x8000 -#define GREEN_HI_BIT_MASK_RGB5551 0x0400 -#define BLUE_HI_BIT_MASK_RGB5551 0x0020 -#define FIRST_COLOR_MASK_RGB5551 0xf800 -#define SECOND_COLOR_MASK_RGB5551 0x07c0 -#define THIRD_COLOR_MASK_RGB5551 0x003e -#define ALPHA_BITS_MASK_RGB5551 0x0001 +#define MAX_RED_RGB5551 31 +#define MAX_GREEN_RGB5551 31 +#define MAX_BLUE_RGB5551 31 +#define RED_LOW_BIT_MASK_RGB5551 0x0800 +#define GREEN_LOW_BIT_MASK_RGB5551 0x0040 +#define BLUE_LOW_BIT_MASK_RGB5551 0x0002 +#define RED_HI_BIT_MASK_RGB5551 0x8000 +#define GREEN_HI_BIT_MASK_RGB5551 0x0400 +#define BLUE_HI_BIT_MASK_RGB5551 0x0020 +#define FIRST_COLOR_MASK_RGB5551 0xf800 +#define SECOND_COLOR_MASK_RGB5551 0x07c0 +#define THIRD_COLOR_MASK_RGB5551 0x003e +#define ALPHA_BITS_MASK_RGB5551 0x0001 #ifndef GFX_MULTI_FORMAT +#define CONCAT(X,Y) X##Y -#define CONCAT(X, Y) X##Y +/* C pre-processor needs a two stage macro define to enable it to concat + * to macro names together to form the name of another macro. */ +#define BUILD_PIXEL_D(F,R,G,B) CONCAT(BUILD_PIXEL_,F) (R,G,B) +#define BUILD_PIXEL2_D(F,R,G,B) CONCAT(BUILD_PIXEL2_,F) (R,G,B) +#define DECOMPOSE_PIXEL_D(F,PIX,R,G,B) CONCAT(DECOMPOSE_PIXEL_,F) (PIX,R,G,B) -// C pre-processor needs a two stage macro define to enable it to concat -// to macro names together to form the name of another macro. -#define BUILD_PIXEL_D(F, R, G, B) CONCAT(BUILD_PIXEL_,F) (R, G, B) -#define BUILD_PIXEL2_D(F, R, G, B) CONCAT(BUILD_PIXEL2_,F) (R, G, B) -#define DECOMPOSE_PIXEL_D(F, PIX, R, G, B) CONCAT(DECOMPOSE_PIXEL_,F) (PIX, R, G, B) +#define BUILD_PIXEL(R,G,B) BUILD_PIXEL_D(PIXEL_FORMAT,R,G,B) +#define BUILD_PIXEL2(R,G,B) BUILD_PIXEL2_D(PIXEL_FORMAT,R,G,B) +#define DECOMPOSE_PIXEL(PIX,R,G,B) DECOMPOSE_PIXEL_D(PIXEL_FORMAT,PIX,R,G,B) -#define BUILD_PIXEL(R, G, B) BUILD_PIXEL_D(PIXEL_FORMAT, R, G, B) -#define BUILD_PIXEL2(R, G, B) BUILD_PIXEL2_D(PIXEL_FORMAT, R, G, B) -#define DECOMPOSE_PIXEL(PIX, R, G, B) DECOMPOSE_PIXEL_D(PIXEL_FORMAT, PIX, R, G, B) +#define MAX_RED_D(F) CONCAT(MAX_RED_,F) +#define MAX_BLUE_D(F) CONCAT(MAX_BLUE_,F) +#define MAX_GREEN_D(F) CONCAT(MAX_GREEN_,F) +#define RED_LOW_BIT_MASK_D(F) CONCAT(RED_LOW_BIT_MASK_,F) +#define BLUE_LOW_BIT_MASK_D(F) CONCAT(BLUE_LOW_BIT_MASK_,F) +#define GREEN_LOW_BIT_MASK_D(F) CONCAT(GREEN_LOW_BIT_MASK_,F) +#define RED_HI_BIT_MASK_D(F) CONCAT(RED_HI_BIT_MASK_,F) +#define BLUE_HI_BIT_MASK_D(F) CONCAT(BLUE_HI_BIT_MASK_,F) +#define GREEN_HI_BIT_MASK_D(F) CONCAT(GREEN_HI_BIT_MASK_,F) +#define FIRST_COLOR_MASK_D(F) CONCAT(FIRST_COLOR_MASK_,F) +#define SECOND_COLOR_MASK_D(F) CONCAT(SECOND_COLOR_MASK_,F) +#define THIRD_COLOR_MASK_D(F) CONCAT(THIRD_COLOR_MASK_,F) +#define ALPHA_BITS_MASK_D(F) CONCAT(ALPHA_BITS_MASK_,F) -#define MAX_RED_D(F) CONCAT(MAX_RED_, F) -#define MAX_GREEN_D(F) CONCAT(MAX_GREEN_, F) -#define MAX_BLUE_D(F) CONCAT(MAX_BLUE_, F) -#define RED_LOW_BIT_MASK_D(F) CONCAT(RED_LOW_BIT_MASK_, F) -#define GREEN_LOW_BIT_MASK_D(F) CONCAT(GREEN_LOW_BIT_MASK_, F) -#define BLUE_LOW_BIT_MASK_D(F) CONCAT(BLUE_LOW_BIT_MASK_, F) -#define RED_HI_BIT_MASK_D(F) CONCAT(RED_HI_BIT_MASK_, F) -#define GREEN_HI_BIT_MASK_D(F) CONCAT(GREEN_HI_BIT_MASK_, F) -#define BLUE_HI_BIT_MASK_D(F) CONCAT(BLUE_HI_BIT_MASK_, F) -#define FIRST_COLOR_MASK_D(F) CONCAT(FIRST_COLOR_MASK_, F) -#define SECOND_COLOR_MASK_D(F) CONCAT(SECOND_COLOR_MASK_, F) -#define THIRD_COLOR_MASK_D(F) CONCAT(THIRD_COLOR_MASK_, F) -#define ALPHA_BITS_MASK_D(F) CONCAT(ALPHA_BITS_MASK_, F) - -#define MAX_RED MAX_RED_D(PIXEL_FORMAT) -#define MAX_GREEN MAX_GREEN_D(PIXEL_FORMAT) -#define MAX_BLUE MAX_BLUE_D(PIXEL_FORMAT) -#define RED_LOW_BIT_MASK RED_LOW_BIT_MASK_D(PIXEL_FORMAT) -#define GREEN_LOW_BIT_MASK GREEN_LOW_BIT_MASK_D(PIXEL_FORMAT) -#define BLUE_LOW_BIT_MASK BLUE_LOW_BIT_MASK_D(PIXEL_FORMAT) -#define RED_HI_BIT_MASK RED_HI_BIT_MASK_D(PIXEL_FORMAT) -#define GREEN_HI_BIT_MASK GREEN_HI_BIT_MASK_D(PIXEL_FORMAT) -#define BLUE_HI_BIT_MASK BLUE_HI_BIT_MASK_D(PIXEL_FORMAT) -#define FIRST_COLOR_MASK FIRST_COLOR_MASK_D(PIXEL_FORMAT) -#define SECOND_COLOR_MASK SECOND_COLOR_MASK_D(PIXEL_FORMAT) -#define THIRD_COLOR_MASK THIRD_COLOR_MASK_D(PIXEL_FORMAT) -#define ALPHA_BITS_MASK ALPHA_BITS_MASK_D(PIXEL_FORMAT) - -#define GREEN_HI_BIT ((MAX_GREEN + 1) >> 1) -#define RGB_LOW_BITS_MASK (RED_LOW_BIT_MASK | GREEN_LOW_BIT_MASK | BLUE_LOW_BIT_MASK) -#define RGB_HI_BITS_MASK (RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) -#define RGB_HI_BITS_MASKx2 ((RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) << 1) -#define RGB_REMOVE_LOW_BITS_MASK (~RGB_LOW_BITS_MASK) -#define FIRST_THIRD_COLOR_MASK (FIRST_COLOR_MASK | THIRD_COLOR_MASK) -#define TWO_LOW_BITS_MASK (RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1)) -#define HIGH_BITS_SHIFTED_TWO_MASK (((FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & ~TWO_LOW_BITS_MASK ) >> 2) +#define MAX_RED MAX_RED_D(PIXEL_FORMAT) +#define MAX_BLUE MAX_BLUE_D(PIXEL_FORMAT) +#define MAX_GREEN MAX_GREEN_D(PIXEL_FORMAT) +#define RED_LOW_BIT_MASK RED_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define BLUE_LOW_BIT_MASK BLUE_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define GREEN_LOW_BIT_MASK GREEN_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define RED_HI_BIT_MASK RED_HI_BIT_MASK_D(PIXEL_FORMAT) +#define BLUE_HI_BIT_MASK BLUE_HI_BIT_MASK_D(PIXEL_FORMAT) +#define GREEN_HI_BIT_MASK GREEN_HI_BIT_MASK_D(PIXEL_FORMAT) +#define FIRST_COLOR_MASK FIRST_COLOR_MASK_D(PIXEL_FORMAT) +#define SECOND_COLOR_MASK SECOND_COLOR_MASK_D(PIXEL_FORMAT) +#define THIRD_COLOR_MASK THIRD_COLOR_MASK_D(PIXEL_FORMAT) +#define ALPHA_BITS_MASK ALPHA_BITS_MASK_D(PIXEL_FORMAT) +#define GREEN_HI_BIT ((MAX_GREEN + 1) >> 1) +#define RGB_LOW_BITS_MASK (RED_LOW_BIT_MASK | GREEN_LOW_BIT_MASK | \ + BLUE_LOW_BIT_MASK) +#define RGB_HI_BITS_MASK (RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | \ + BLUE_HI_BIT_MASK) +#define RGB_HI_BITS_MASKx2 ((RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | \ + BLUE_HI_BIT_MASK) << 1) +#define RGB_REMOVE_LOW_BITS_MASK (~RGB_LOW_BITS_MASK) +#define FIRST_THIRD_COLOR_MASK (FIRST_COLOR_MASK | THIRD_COLOR_MASK) +#define TWO_LOW_BITS_MASK (RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1)) +#define HIGH_BITS_SHIFTED_TWO_MASK (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \ + ~TWO_LOW_BITS_MASK ) >> 2) #endif #endif + diff --git a/source/snes9x/port.h b/source/snes9x/port.h index 98f6e95..ec23aba 100644 --- a/source/snes9x/port.h +++ b/source/snes9x/port.h @@ -159,142 +159,243 @@ **********************************************************************************/ + + #ifndef _PORT_H_ #define _PORT_H_ -#include -#include #include -#ifndef GEKKO -#include -#endif -#include + +#ifndef STORM +//#include #include -#ifdef HAVE_STRINGS_H +#else #include +#include #endif + +#ifndef ACCEPT_SIZE_T +#ifdef __WIN32__ +#define ACCEPT_SIZE_T int +#else +#define ACCEPT_SIZE_T unsigned int +#endif +#endif + #include -#ifdef __WIN32__ -#include -#endif - -#define CHECK_SOUND() +/* #define PIXEL_FORMAT RGB565 */ #define GFX_MULTI_FORMAT -#ifdef __WIN32__ -#define RIGHTSHIFT_IS_SAR -#define SNES_JOY_READ_CALLBACKS +#ifndef NOASM +//#define USE_X86_ASM #endif #ifdef __MACOSX__ -#undef GFX_MULTI_FORMAT -#define PIXEL_FORMAT RGB555 -#endif + + #ifdef _C + #undef _C + #endif + + #ifdef _D + #undef _D + #endif + + #define CHECK_SOUND() + #define PIXEL_FORMAT RGB555 + #undef GFX_MULTI_FORMAT + #undef USE_X86_ASM + #undef _MAX_PATH + + #define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) + void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); + +#endif /* __MACOSX__ */ #ifndef snes9x_types_defined #define snes9x_types_defined -typedef unsigned char bool8; + +typedef unsigned char bool8; + #ifdef HAVE_STDINT_H #include -typedef intptr_t pint; -typedef int8_t int8; -typedef uint8_t uint8; -typedef int16_t int16; -typedef uint16_t uint16; -typedef int32_t int32; -typedef uint32_t uint32; -typedef int64_t int64; -typedef uint64_t uint64; -#else // HAVE_STDINT_H + +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +typedef intptr_t pint; + +#else /* Don't have stdint.h */ + #ifdef PTR_NOT_INT -typedef long pint; -#else -typedef int pint; -#endif -#ifdef __WIN32__ -#ifdef __BORLANDC__ -#include -#else -typedef signed char int8; -typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; -#ifndef WSAAP -// winsock2.h typedefs int32 as well -typedef signed int int32; -#endif -typedef unsigned int uint32; -#endif -typedef signed __int64 int64; -typedef unsigned __int64 uint64; -#else // __WIN32__ -typedef signed char int8; -typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; -typedef signed int int32; -typedef unsigned int uint32; -#ifdef __GNUC__ -// long long is not part of ISO C++ +typedef long pint; +#else /* pointer is int */ +typedef int pint; +#endif /* PTR_NOT_INT */ + +/* FIXME: Refactor this by moving out the BORLAND part and unifying typedefs */ +#ifndef __WIN32__ +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed char int8; +typedef short int16; +typedef int int32; +typedef unsigned int uint32; +# ifdef __GNUC__ /* long long is not part of ISO C++ */ __extension__ +# endif +typedef long long int64; +typedef unsigned long long uint64; +#else /* __WIN32__ */ + +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH #endif -typedef long long int64; -typedef unsigned long long uint64; -#endif // __WIN32__ -#endif // HAVE_STDINT_H -#endif // snes9x_types_defined + +# ifdef __BORLANDC__ +# include +# else + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed char int8; +typedef short int16; + +# ifndef WSAAPI +/* winsock2.h typedefs int32 as well. */ +typedef long int32; + +# define PLAT_SOUND_BUFFER SoundBuffer +# define RIGHTSHIFT_IS_SAR +# endif + +# if defined(_MSC_VER) && (_MSC_VER == 1400) /* VC8.0 */ +/* temporary solution for fatal error C1063 (cl.exe 14.00.50727.762) */ +# ifdef RIGHTSHIFT_IS_SAR +# undef RIGHTSHIFT_IS_SAR +# endif /* RIGHTSHIFT_IS_SAR */ +# define RIGHTSHIFT_INT8_IS_SAR +# define RIGHTSHIFT_INT16_IS_SAR +# define RIGHTSHIFT_INT32_IS_SAR +# endif /* VC8.0 */ + +typedef unsigned int uint32; + +# endif /* __BORLANDC__ */ + +typedef __int64 int64; +typedef unsigned __int64 uint64; + +#endif /* __WIN32__ */ +#endif /* HAVE_STDINT_H */ +#endif /* snes9x_types_defined */ + + +#include "pixform.h" #ifndef TRUE -#define TRUE 1 +#define TRUE 1 #endif + #ifndef FALSE -#define FALSE 0 +#define FALSE 0 #endif -#define START_EXTERN_C extern "C" { -#define END_EXTERN_C } - -#ifndef __WIN32__ -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif -#define _MAX_DRIVE 1 -#define _MAX_DIR PATH_MAX -#define _MAX_FNAME PATH_MAX -#define _MAX_EXT PATH_MAX -#define _MAX_PATH PATH_MAX +#ifdef STORM +#define EXTERN_C +#define START_EXTERN_C +#define END_EXTERN_C #else -#ifndef PATH_MAX -#define PATH_MAX _MAX_PATH +#if defined(__cplusplus) || defined(c_plusplus) +#define EXTERN_C extern "C" +#define START_EXTERN_C extern "C" { +#define END_EXTERN_C } +#else +#define EXTERN_C extern +#define START_EXTERN_C +#define END_EXTERN_C #endif #endif #ifndef __WIN32__ -#define ZeroMemory(a, b) memset((a), 0, (b)) -void _splitpath (const char *, char *, char *, char *, char *); -void _makepath (char *, const char *, const char *, const char *, const char *); -#define S9xDisplayString DisplayStringFromBottom + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#define _MAX_DIR PATH_MAX +#define _MAX_DRIVE 1 +#define _MAX_FNAME PATH_MAX +#define _MAX_EXT PATH_MAX +#define _MAX_PATH PATH_MAX + +#define ZeroMemory(a,b) memset((a),0,(b)) + +void _makepath (char *path, const char *drive, const char *dir, + const char *fname, const char *ext); +void _splitpath (const char *path, char *drive, char *dir, char *fname, + char *ext); +#else /* __WIN32__ */ +#define strcasecmp stricmp +#define strncasecmp strnicmp + +#define SNES_JOY_READ_CALLBACKS + +#endif + +EXTERN_C void S9xGenerateSound (); +#ifdef __WIN32__ +EXTERN_C void S9xGenerateFrameSound (); +#endif + +#ifdef STORM +EXTERN_C int soundsignal; +EXTERN_C void MixSound(void); +/* Yes, CHECK_SOUND is getting defined correctly! */ +#define CHECK_SOUND if (Settings.APUEnabled) if(SetSignalPPC(0L, soundsignal) & soundsignal) MixSound #else -#define strcasecmp stricmp -#define strncasecmp strnicmp -#define S9xDisplayString S9xCustomDisplayString +#define CHECK_SOUND() #endif #ifdef __DJGPP -#define SLASH_STR "\\" -#define SLASH_CHAR '\\' +#define SLASH_STR "\\" +#define SLASH_CHAR '\\' #else -#define SLASH_STR "/" -#define SLASH_CHAR '/' +#define SLASH_STR "/" +#define SLASH_CHAR '/' #endif +/* Taken care of in signal.h on Linux. + * #ifdef __linux + * typedef void (*SignalHandler)(int); + * #define SIG_PF SignalHandler + * #endif + */ + +/* If including signal.h, do it before snes9.h and port.h to avoid clashes. */ #ifndef SIG_PF -#define SIG_PF void (*) (int) +#define SIG_PF void(*)(int) +#endif + +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__x86_64__) || defined(__WIN32__) || defined(__alpha__) +#define LSB_FIRST +#define FAST_LSB_WORD_ACCESS +#else +#define MSB_FIRST +#endif + +#ifdef __sun +#define TITLE "Snes9X: Solaris" #endif #ifdef __linux -#define TITLE "Snes9x: Linux" +#define TITLE "Snes9X: Linux" #define SYS_CONFIG_FILE "/etc/snes9x/snes9x.conf" #endif @@ -302,32 +403,41 @@ void _makepath (char *, const char *, const char *, const char *, const char *); #define TITLE "Snes9x" #endif -#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) -#define LSB_FIRST -#define FAST_LSB_WORD_ACCESS +#ifdef STORM +#define STATIC +#define strncasecmp strnicmp #else -#define MSB_FIRST +#define STATIC static #endif #ifdef FAST_LSB_WORD_ACCESS -#define READ_WORD(s) (*(uint16 *) (s)) -#define READ_3WORD(s) (*(uint32 *) (s) & 0x00ffffff) -#define READ_DWORD(s) (*(uint32 *) (s)) -#define WRITE_WORD(s, d) *(uint16 *) (s) = (d) -#define WRITE_3WORD(s, d) *(uint16 *) (s) = (uint16) (d), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) -#define WRITE_DWORD(s, d) *(uint32 *) (s) = (d) +#define READ_WORD(s) (*(uint16 *) (s)) +#define READ_3WORD(s) (0x00ffffff & *(uint32 *) (s)) +#define READ_DWORD(s) (*(uint32 *) (s)) +#define WRITE_WORD(s, d) (*(uint16 *) (s)) = (d) +#define WRITE_3WORD(s, d) *(uint16 *) (s) = (uint16)(d),\ + *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) +#define WRITE_DWORD(s, d) (*(uint32 *) (s)) = (d) #else -#define READ_WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8)) -#define READ_3WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16)) -#define READ_DWORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16) | (*((uint8 *) (s) + 3) << 24)) -#define WRITE_WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8) -#define WRITE_3WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) -#define WRITE_DWORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16), *((uint8 *) (s) + 3) = (uint8) ((d) >> 24) +#define READ_WORD(s) ( *(uint8 *) (s) |\ + (*((uint8 *) (s) + 1) << 8)) +#define READ_3WORD(s) ( *(uint8 *) (s) |\ + (*((uint8 *) (s) + 1) << 8) |\ + (*((uint8 *) (s) + 2) << 16)) +#define READ_DWORD(s) ( *(uint8 *) (s) |\ + (*((uint8 *) (s) + 1) << 8) |\ + (*((uint8 *) (s) + 2) << 16) |\ + (*((uint8 *) (s) + 3) << 24)) +#define WRITE_WORD(s, d) *(uint8 *) (s) = (d), \ + *((uint8 *) (s) + 1) = (d) >> 8 +#define WRITE_3WORD(s, d) *(uint8 *) (s) = (uint8) (d), \ + *((uint8 *) (s) + 1) = (uint8) ((d) >> 8),\ + *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) +#define WRITE_DWORD(s, d) *(uint8 *) (s) = (uint8) (d), \ + *((uint8 *) (s) + 1) = (uint8) ((d) >> 8),\ + *((uint8 *) (s) + 2) = (uint8) ((d) >> 16),\ + *((uint8 *) (s) + 3) = (uint8) ((d) >> 24) #endif -#define SWAP_WORD(s) (s) = (((s) & 0xff) << 8) | (((s) & 0xff00) >> 8) -#define SWAP_DWORD(s) (s) = (((s) & 0xff) << 24) | (((s) & 0xff00) << 8) | (((s) & 0xff0000) >> 8) | (((s) & 0xff000000) >> 24) - -#include "pixform.h" - #endif + diff --git a/source/snes9x/ppu.cpp b/source/snes9x/ppu.cpp index 738cfa2..edb9927 100644 --- a/source/snes9x/ppu.cpp +++ b/source/snes9x/ppu.cpp @@ -159,41 +159,57 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "missing.h" +#include "apu.h" #include "dma.h" -#include "apu/apu.h" -#include "fxemu.h" +#include "gfx.h" +#include "display.h" +#include "sa1.h" #include "sdd1.h" #include "srtc.h" +#include "spc7110.h" +#include "bsx.h" +//#include "movie.h" #include "controls.h" -#include "movie.h" -#include "display.h" #ifdef NETPLAY_SUPPORT #include "netplay.h" #endif -#ifdef DEBUGGER -#include "debug.h" -#include "missing.h" + +#ifndef ZSNES_FX +#include "fxemu.h" +#include "fxinst.h" +extern struct FxInit_s SuperFX; +#else +EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); +EXTERN_C uint8 S9xSuperFXReadReg (uint32); #endif -extern uint8 *HDMAMemPointers[8]; +uint32 justifiers=0xFFFF00AA; +uint8 in_bit=0; +extern uint8 *HDMAMemPointers [8]; static inline void S9xLatchCounters (bool force) { - if (force || (Memory.FillRAM[0x4213] & 0x80)) - { - // Latch h and v counters, like the gun - #ifdef DEBUGGER - missing.h_v_latch = 1; - #endif - #if 0 // #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; - #endif - - PPU.HVBeamCounterLatched = 1; - PPU.VBeamPosLatched = (uint16) CPU.V_Counter; + if (force || (Memory.FillRAM[0x4213] & 0x80)) + { + // Latch h and v counters, like the gun +#ifdef DEBUGGER + missing.h_v_latch = 1; +#endif +#if 0 +# ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +# endif +#endif + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) CPU.V_Counter; // From byuu: // All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long. @@ -203,7 +219,7 @@ static inline void S9xLatchCounters (bool force) // This makes the effective range of hscan_pos 0-339 at all times. int32 hc = CPU.Cycles; - if (Timings.H_Max == Timings.H_Max_Master) // 1364 + if (Timings.H_Max == Timings.H_Max_Master) // 1364 { if (hc >= 1292) hc -= (ONE_DOT_CYCLE / 2); @@ -213,31 +229,43 @@ static inline void S9xLatchCounters (bool force) PPU.HBeamPosLatched = (uint16) (hc / ONE_DOT_CYCLE); - Memory.FillRAM[0x213f] |= 0x40; - } + // Causes screen flicker for Yoshi's Island if uncommented + //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) - PPU.GunVLatch = 1000; + Memory.FillRAM [0x213F] |= 0x40; + + } + + if (CPU.V_Counter > PPU.GunVLatch || + (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) + { + PPU.GunVLatch = 1000; + } } static inline void S9xTryGunLatch (bool force) { - if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) + if (CPU.V_Counter > PPU.GunVLatch || + (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) { if (force || (Memory.FillRAM[0x4213] & 0x80)) { - #ifdef DEBUGGER + #ifdef DEBUGGER missing.h_v_latch = 1; - #endif - #if 0 // #ifdef CPU_SHUTDOWN + #endif + #if 0 + # ifdef CPU_SHUTDOWN CPU.WaitAddress = CPU.PCAtOpcodeStart; - #endif - + # endif + #endif PPU.HVBeamCounterLatched = 1; PPU.VBeamPosLatched = (uint16) PPU.GunVLatch; PPU.HBeamPosLatched = (uint16) PPU.GunHLatch; - Memory.FillRAM[0x213f] |= 0x40; + // Causes screen flicker for Yoshi's Island if uncommented + //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + Memory.FillRAM [0x213F] |= 0x40; } PPU.GunVLatch = 1000; @@ -249,10 +277,10 @@ void S9xCheckMissingHTimerPosition (int32 hc) if (PPU.HTimerPosition == hc) { if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_IRQ_SOURCE); + S9xSetIRQ(PPU_H_BEAM_IRQ_SOURCE); else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_IRQ_SOURCE); + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); } } @@ -273,10 +301,10 @@ void S9xCheckMissingHTimerRange (int32 hc_from, int32 range) if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) { if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_IRQ_SOURCE); + S9xSetIRQ(PPU_H_BEAM_IRQ_SOURCE); else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_IRQ_SOURCE); + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); } } @@ -284,9 +312,9 @@ void S9xUpdateHVTimerPosition (void) { if (PPU.HTimerEnabled) { - #ifdef DEBUGGER +#ifdef DEBUGGER missing.hirq_pos = PPU.IRQHBeamPos; - #endif +#endif if (PPU.IRQHBeamPos != 0) { // IRQ_read @@ -298,7 +326,6 @@ void S9xUpdateHVTimerPosition (void) if (PPU.IRQHBeamPos > 326) PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); } - PPU.HTimerPosition += 14; // /IRQ PPU.HTimerPosition += 4; @@ -424,1761 +451,2402 @@ void S9xUpdateHVTimerPosition (void) break; } } - -#ifdef DEBUGGER - S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition); -#endif } -void S9xFixColourBrightness (void) +void S9xFixColourBrightness () { - IPPU.XB = mul_brightness[PPU.Brightness]; - - for (int i = 0; i < 256; i++) - { - IPPU.Red[i] = IPPU.XB[(PPU.CGDATA[i]) & 0x1f]; - IPPU.Green[i] = IPPU.XB[(PPU.CGDATA[i] >> 5) & 0x1f]; - IPPU.Blue[i] = IPPU.XB[(PPU.CGDATA[i] >> 10) & 0x1f]; - IPPU.ScreenColors[i] = BUILD_PIXEL(IPPU.Red[i], IPPU.Green[i], IPPU.Blue[i]); - } + IPPU.XB = mul_brightness [PPU.Brightness]; + for (int i = 0; i < 256; i++) + { + IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; + IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; + IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; + IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i], + IPPU.Blue [i]); + } } +/******************************************************************************/ +/* S9xSetPPU() */ +/* This function sets a PPU Register to a specific byte */ +/******************************************************************************/ void S9xSetPPU (uint8 Byte, uint16 Address) { - // MAP_PPU: $2000-$3FFF +// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, Byte, Address); - if (CPU.InDMAorHDMA) + // Take care of DMA wrapping + if(CPU.InDMAorHDMA && Address>0x21ff) Address=0x2100+(Address&0xff); + + if (Address <= 0x219F) { - if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) + switch (Address) { - // S9xSetPPU() is called to write to DMA[].AAddress - if ((Address & 0xff00) == 0x2100) + case 0x2100: + // Brightness and screen blank bit + if (Byte != Memory.FillRAM [0x2100]) { - // Cannot access to Address Bus B ($2100-$21ff) via (H)DMA - return; + FLUSH_REDRAW (); + if (PPU.Brightness != (Byte & 0xF)) + { + IPPU.ColorsChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + PPU.Brightness = Byte & 0xF; + S9xFixColourBrightness (); + if (PPU.Brightness > IPPU.MaxBrightness) + IPPU.MaxBrightness = PPU.Brightness; + } + if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) + { + IPPU.ColorsChanged = TRUE; + PPU.ForcedBlanking = (Byte >> 7) & 1; + } + } + if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter==PPU.ScreenHeight+FIRST_VISIBLE_LINE){ + PPU.OAMAddr = PPU.SavedOAMAddr; + uint8 tmp = 0; + if(PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xFE) >> 1; + if((PPU.OAMFlip&1) || PPU.FirstSprite!=tmp){ + PPU.FirstSprite = tmp; + IPPU.OBJChanged = TRUE; + } + PPU.OAMFlip = 0; + } + break; + + case 0x2101: + // Sprite (OBJ) tile address + if (Byte != Memory.FillRAM [0x2101]) + { + FLUSH_REDRAW (); + PPU.OBJNameBase = (Byte & 3) << 14; + PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; + PPU.OBJSizeSelect = (Byte >> 5) & 7; + IPPU.OBJChanged = TRUE; + } + break; + + case 0x2102: + // Sprite write address (low) + PPU.OAMAddr = ((Memory.FillRAM[0x2103]&1)<<8) | Byte; + PPU.OAMFlip = 2; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + break; + + case 0x2103: + // Sprite register write address (high), sprite priority rotation + // bit. + PPU.OAMAddr = ((Byte&1)<<8) | Memory.FillRAM[0x2102]; + + PPU.OAMPriorityRotation=(Byte & 0x80)? 1 : 0; + if (PPU.OAMPriorityRotation) + { + if (PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + } else { + if (PPU.FirstSprite != 0) + { + PPU.FirstSprite = 0; + IPPU.OBJChanged = TRUE; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + } + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + break; + + case 0x2104: + // Sprite register write + REGISTER_2104(Byte); + break; + + case 0x2105: + // Screen mode (0 - 7), background tile sizes and background 3 + // priority + if (Byte != Memory.FillRAM [0x2105]) + { + FLUSH_REDRAW (); + PPU.BG[0].BGSize = (Byte >> 4) & 1; + PPU.BG[1].BGSize = (Byte >> 5) & 1; + PPU.BG[2].BGSize = (Byte >> 6) & 1; + PPU.BG[3].BGSize = (Byte >> 7) & 1; + PPU.BGMode = Byte & 7; + // BJ: BG3Priority only takes effect if BGMode==1 and the bit is set + PPU.BG3Priority = ((Byte & 0x0f) == 0x09); +#ifdef DEBUGGER + missing.modes[PPU.BGMode] = 1; +#endif + if(PPU.BGMode==5||PPU.BGMode==6) + IPPU.Interlace = Memory.FillRAM[0x2133]&1; + else + IPPU.Interlace = 0; + } + break; + + case 0x2106: + if (Byte != Memory.FillRAM [0x2106]) + { + // Mosaic pixel size and enable + FLUSH_REDRAW(); + PPU.MosaicStart=CPU.V_Counter; + if(PPU.MosaicStart>PPU.ScreenHeight) PPU.MosaicStart=0; +#ifdef DEBUGGER + if ((Byte & 0xf0) && (Byte & 0x0f)) + missing.mosaic = 1; +#endif + PPU.Mosaic = (Byte >> 4) + 1; + PPU.BGMosaic [0] = (Byte & 1); + PPU.BGMosaic [1] = (Byte & 2); + PPU.BGMosaic [2] = (Byte & 4); + PPU.BGMosaic [3] = (Byte & 8); + } + break; + case 0x2107: // [BG0SC] + if (Byte != Memory.FillRAM [0x2107]) + { + FLUSH_REDRAW (); + PPU.BG[0].SCSize = Byte & 3; + PPU.BG[0].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x2108: // [BG1SC] + if (Byte != Memory.FillRAM [0x2108]) + { + FLUSH_REDRAW (); + PPU.BG[1].SCSize = Byte & 3; + PPU.BG[1].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x2109: // [BG2SC] + if (Byte != Memory.FillRAM [0x2109]) + { + FLUSH_REDRAW (); + PPU.BG[2].SCSize = Byte & 3; + PPU.BG[2].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x210A: // [BG3SC] + if (Byte != Memory.FillRAM [0x210a]) + { + FLUSH_REDRAW (); + PPU.BG[3].SCSize = Byte & 3; + PPU.BG[3].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x210B: // [BG01NBA] + if (Byte != Memory.FillRAM [0x210b]) + { + FLUSH_REDRAW (); + PPU.BG[0].NameBase = (Byte & 7) << 12; + PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; + } + break; + + case 0x210C: // [BG23NBA] + if (Byte != Memory.FillRAM [0x210c]) + { + FLUSH_REDRAW (); + PPU.BG[2].NameBase = (Byte & 7) << 12; + PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; + } + break; + + + case 0x210D: + // Yes, the two formulas are supposed to be different. + PPU.BG[0].HOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[0].HOffset>>8)&7); + PPU.M7HOFS = (Byte<<8) | PPU.M7byte; + PPU.BGnxOFSbyte = Byte; + PPU.M7byte = Byte; + break; + + case 0x210E: + // Yes, the two formulas are supposed to be different. + PPU.BG[0].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.M7VOFS = (Byte<<8) | PPU.M7byte; + PPU.BGnxOFSbyte = Byte; + PPU.M7byte = Byte; + break; + + case 0x210F: + PPU.BG[1].HOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[1].HOffset>>8)&7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2110: + PPU.BG[1].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2111: + PPU.BG[2].HOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[2].HOffset>>8)&7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2112: + PPU.BG[2].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2113: + PPU.BG[3].HOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[3].HOffset>>8)&7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2114: + PPU.BG[3].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2115: + // VRAM byte/word access flag and increment + PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; + switch (Byte & 3) + { + case 0: + PPU.VMA.Increment = 1; + break; + case 1: + PPU.VMA.Increment = 32; + break; + case 2: + PPU.VMA.Increment = 128; + break; + case 3: + PPU.VMA.Increment = 128; + break; + } +#ifdef DEBUGGER + if ((Byte & 3) != 0) + missing.vram_inc = Byte & 3; +#endif + if (Byte & 0x0c) + { + static uint16 IncCount [4] = { 0, 32, 64, 128 }; + static uint16 Shift [4] = { 0, 5, 6, 7 }; +#ifdef DEBUGGER + missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2; +#endif +// PPU.VMA.Increment = 1; + uint8 i = (Byte & 0x0c) >> 2; + PPU.VMA.FullGraphicCount = IncCount [i]; + PPU.VMA.Mask1 = IncCount [i] * 8 - 1; + PPU.VMA.Shift = Shift [i]; } else + PPU.VMA.FullGraphicCount = 0; + break; + + case 0x2116: + // VRAM read/write address (low) + PPU.VMA.Address &= 0xFF00; + PPU.VMA.Address |= Byte; +#ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) { - // 0x2000-0x3FFF is connected to Address Bus A - // SA1, SuperFX and SRTC are mapped here - // I don't bother for now... + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); + } else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); +#else + IPPU.FirstVRAMRead = TRUE; +#endif + break; + + case 0x2117: + // VRAM read/write address (high) + PPU.VMA.Address &= 0x00FF; + PPU.VMA.Address |= Byte << 8; +#ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); + } else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); +#else + IPPU.FirstVRAMRead = TRUE; +#endif + break; + + case 0x2118: + // VRAM write data (low) +#ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; +#endif + REGISTER_2118(Byte); + break; + + case 0x2119: + // VRAM write data (high) +#ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; +#endif + REGISTER_2119(Byte); + break; + + case 0x211a: + // Mode 7 outside rotation area display mode and flipping + if (Byte != Memory.FillRAM [0x211a]) + { + FLUSH_REDRAW (); + PPU.Mode7Repeat = Byte >> 6; + if (PPU.Mode7Repeat == 1) + PPU.Mode7Repeat = 0; + PPU.Mode7VFlip = (Byte & 2) >> 1; + PPU.Mode7HFlip = Byte & 1; + } + break; + case 0x211b: + // Mode 7 matrix A (low & high) + PPU.MatrixA = PPU.M7byte | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + PPU.M7byte = Byte; + break; + case 0x211c: + // Mode 7 matrix B (low & high) + PPU.MatrixB = PPU.M7byte | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + PPU.M7byte = Byte; + break; + case 0x211d: + // Mode 7 matrix C (low & high) + PPU.MatrixC = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + case 0x211e: + // Mode 7 matrix D (low & high) + PPU.MatrixD = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + case 0x211f: + // Mode 7 centre of rotation X (low & high) + PPU.CentreX = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + case 0x2120: + // Mode 7 centre of rotation Y (low & high) + PPU.CentreY = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x2121: + // CG-RAM address + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = Byte; + break; + + case 0x2122: + REGISTER_2122(Byte); + break; + + case 0x2123: + // Window 1 and 2 enable for backgrounds 1 and 2 + if (Byte != Memory.FillRAM [0x2123]) + { + FLUSH_REDRAW (); + PPU.ClipWindow1Enable [0] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [1] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [0] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [1] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [0] = !(Byte & 0x01); + PPU.ClipWindow1Inside [1] = !(Byte & 0x10); + PPU.ClipWindow2Inside [0] = !(Byte & 0x04); + PPU.ClipWindow2Inside [1] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[1] = 1; + if (Byte & 0x20) + missing.window1[1] = 1; + if (Byte & 0x08) + missing.window2[0] = 1; + if (Byte & 0x02) + missing.window1[0] = 1; +#endif + } + break; + case 0x2124: + // Window 1 and 2 enable for backgrounds 3 and 4 + if (Byte != Memory.FillRAM [0x2124]) + { + FLUSH_REDRAW (); + PPU.ClipWindow1Enable [2] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [3] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [2] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [3] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [2] = !(Byte & 0x01); + PPU.ClipWindow1Inside [3] = !(Byte & 0x10); + PPU.ClipWindow2Inside [2] = !(Byte & 0x04); + PPU.ClipWindow2Inside [3] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[3] = 1; + if (Byte & 0x20) + missing.window1[3] = 1; + if (Byte & 0x08) + missing.window2[2] = 1; + if (Byte & 0x02) + missing.window1[2] = 1; +#endif + } + break; + case 0x2125: + // Window 1 and 2 enable for objects and colour window + if (Byte != Memory.FillRAM [0x2125]) + { + FLUSH_REDRAW (); + PPU.ClipWindow1Enable [4] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [5] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [4] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [5] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [4] = !(Byte & 0x01); + PPU.ClipWindow1Inside [5] = !(Byte & 0x10); + PPU.ClipWindow2Inside [4] = !(Byte & 0x04); + PPU.ClipWindow2Inside [5] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[5] = 1; + if (Byte & 0x20) + missing.window1[5] = 1; + if (Byte & 0x08) + missing.window2[4] = 1; + if (Byte & 0x02) + missing.window1[4] = 1; +#endif + } + break; + case 0x2126: + // Window 1 left position + if (Byte != Memory.FillRAM [0x2126]) + { + FLUSH_REDRAW (); + PPU.Window1Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2127: + // Window 1 right position + if (Byte != Memory.FillRAM [0x2127]) + { + FLUSH_REDRAW (); + PPU.Window1Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2128: + // Window 2 left position + if (Byte != Memory.FillRAM [0x2128]) + { + FLUSH_REDRAW (); + PPU.Window2Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2129: + // Window 2 right position + if (Byte != Memory.FillRAM [0x2129]) + { + FLUSH_REDRAW (); + PPU.Window2Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212a: + // Windows 1 & 2 overlap logic for backgrounds 1 - 4 + if (Byte != Memory.FillRAM [0x212a]) + { + FLUSH_REDRAW (); + PPU.ClipWindowOverlapLogic [0] = (Byte & 0x03); + PPU.ClipWindowOverlapLogic [1] = (Byte & 0x0c) >> 2; + PPU.ClipWindowOverlapLogic [2] = (Byte & 0x30) >> 4; + PPU.ClipWindowOverlapLogic [3] = (Byte & 0xc0) >> 6; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212b: + // Windows 1 & 2 overlap logic for objects and colour window + if (Byte != Memory.FillRAM [0x212b]) + { + FLUSH_REDRAW (); + PPU.ClipWindowOverlapLogic [4] = Byte & 0x03; + PPU.ClipWindowOverlapLogic [5] = (Byte & 0x0c) >> 2; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212c: + // Main screen designation (backgrounds 1 - 4 and objects) + if (Byte != Memory.FillRAM [0x212c]) + { + FLUSH_REDRAW (); + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; return; } - } - else - { - // S9xSetPPU() is called to read from $21xx - // Take care of DMA wrapping - if (Address > 0x21ff) - Address = 0x2100 + (Address & 0xff); - } - } + break; + case 0x212d: + // Sub-screen designation (backgrounds 1 - 4 and objects) + if (Byte != Memory.FillRAM [0x212d]) + { + FLUSH_REDRAW (); +#ifdef DEBUGGER + if (Byte & 0x1f) + missing.subscreen = 1; +#endif + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; + return; + } + break; + case 0x212e: + // Window mask designation for main screen ? + if (Byte != Memory.FillRAM [0x212e]) + { + FLUSH_REDRAW (); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212f: + // Window mask designation for sub-screen ? + if (Byte != Memory.FillRAM [0x212f]) + { + FLUSH_REDRAW (); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2130: + // Fixed colour addition or screen addition + if (Byte != Memory.FillRAM [0x2130]) + { + FLUSH_REDRAW (); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7)) + missing.direct = 1; +#endif + } + break; + case 0x2131: + // Colour addition or subtraction select + if (Byte != Memory.FillRAM[0x2131]) + { + FLUSH_REDRAW (); + // Backgrounds 1 - 4, objects and backdrop colour add/sub enable +#ifdef DEBUGGER + if (Byte & 0x80) + { + // Subtract + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_sub = 1; + else + missing.fixed_colour_sub = 1; + } + else + { + // Addition + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_add = 1; + else + missing.fixed_colour_add = 1; + } +#endif + Memory.FillRAM[0x2131] = Byte; + } + break; + case 0x2132: + if (Byte != Memory.FillRAM [0x2132]) + { + FLUSH_REDRAW (); + // Colour data for fixed colour addition/subtraction + if (Byte & 0x80) + PPU.FixedColourBlue = Byte & 0x1f; + if (Byte & 0x40) + PPU.FixedColourGreen = Byte & 0x1f; + if (Byte & 0x20) + PPU.FixedColourRed = Byte & 0x1f; + } + break; + case 0x2133: + // Screen settings + if (Byte != Memory.FillRAM [0x2133]) + { +#ifdef DEBUGGER + if (Byte & 0x40) + missing.mode7_bgmode = 1; + if (Byte & 0x08) + missing.pseudo_512 = 1; +#endif + if((Memory.FillRAM [0x2133] ^ Byte)&8) + { + FLUSH_REDRAW (); + IPPU.PseudoHires = Byte&8; + } + if (Byte & 0x04) + { + PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; + if(IPPU.DoubleHeightPixels) + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + else + IPPU.RenderedScreenHeight = PPU.ScreenHeight; +#ifdef DEBUGGER + missing.lines_239 = 1; +#endif + } + else PPU.ScreenHeight = SNES_HEIGHT; #ifdef DEBUGGER - if (CPU.InHDMA) - S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte); + if (Byte & 0x02) + missing.sprite_double_height = 1; + + if (Byte & 1) + missing.interlace = 1; #endif - - if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 - // write_port will run the APU until given clock before writing value - S9xAPUWritePort(Address & 3, Byte); - else - if (Address <= 0x2183) - { - switch (Address) - { - case 0x2100: // INIDISP - if (Byte != Memory.FillRAM[0x2100]) + if((Memory.FillRAM [0x2133] ^ Byte)&3) { - FLUSH_REDRAW(); - - if (PPU.Brightness != (Byte & 0xf)) - { - IPPU.ColorsChanged = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - PPU.Brightness = Byte & 0xf; - S9xFixColourBrightness(); - if (PPU.Brightness > IPPU.MaxBrightness) - IPPU.MaxBrightness = PPU.Brightness; - } - - if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) - { - IPPU.ColorsChanged = TRUE; - PPU.ForcedBlanking = (Byte >> 7) & 1; - } - } - - if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - PPU.OAMAddr = PPU.SavedOAMAddr; - - uint8 tmp = 0; - if (PPU.OAMPriorityRotation) - tmp = (PPU.OAMAddr & 0xfe) >> 1; - if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) - { - PPU.FirstSprite = tmp; + FLUSH_REDRAW (); + if((Memory.FillRAM [0x2133] ^ Byte)&2) IPPU.OBJChanged = TRUE; - } - - PPU.OAMFlip = 0; + if(PPU.BGMode==5 || PPU.BGMode==6) + IPPU.Interlace = Byte&1; + IPPU.InterlaceOBJ = Byte&2; } - break; - - case 0x2101: // OBSEL - if (Byte != Memory.FillRAM[0x2101]) - { - FLUSH_REDRAW(); - PPU.OBJNameBase = (Byte & 3) << 14; - PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; - PPU.OBJSizeSelect = (Byte >> 5) & 7; - IPPU.OBJChanged = TRUE; - } - - break; - - case 0x2102: // OAMADDL - PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte; - PPU.OAMFlip = 2; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; - IPPU.OBJChanged = TRUE; - #ifdef DEBUGGER - missing.sprite_priority_rotation = 1; - #endif - } - - break; - - case 0x2103: // OAMADDH - PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102]; - PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0; - if (PPU.OAMPriorityRotation) - { - if (PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; - IPPU.OBJChanged = TRUE; - #ifdef DEBUGGER - missing.sprite_priority_rotation = 1; - #endif - } - } - else - { - if (PPU.FirstSprite != 0) - { - PPU.FirstSprite = 0; - IPPU.OBJChanged = TRUE; - #ifdef DEBUGGER - missing.sprite_priority_rotation = 1; - #endif - } - } - - PPU.OAMFlip = 0; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - - break; - - case 0x2104: // OAMDATA - REGISTER_2104(Byte); - break; - - case 0x2105: // BGMODE - if (Byte != Memory.FillRAM[0x2105]) - { - FLUSH_REDRAW(); - PPU.BG[0].BGSize = (Byte >> 4) & 1; - PPU.BG[1].BGSize = (Byte >> 5) & 1; - PPU.BG[2].BGSize = (Byte >> 6) & 1; - PPU.BG[3].BGSize = (Byte >> 7) & 1; - PPU.BGMode = Byte & 7; - // BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set - PPU.BG3Priority = ((Byte & 0x0f) == 0x09); - if (PPU.BGMode == 5 || PPU.BGMode == 6) - IPPU.Interlace = Memory.FillRAM[0x2133] & 1; - else - IPPU.Interlace = 0; - #ifdef DEBUGGER - missing.modes[PPU.BGMode] = 1; - #endif - } - - break; - - case 0x2106: // MOSAIC - if (Byte != Memory.FillRAM[0x2106]) - { - FLUSH_REDRAW(); - PPU.MosaicStart = CPU.V_Counter; - if (PPU.MosaicStart > PPU.ScreenHeight) - PPU.MosaicStart = 0; - PPU.Mosaic = (Byte >> 4) + 1; - PPU.BGMosaic[0] = (Byte & 1); - PPU.BGMosaic[1] = (Byte & 2); - PPU.BGMosaic[2] = (Byte & 4); - PPU.BGMosaic[3] = (Byte & 8); - #ifdef DEBUGGER - if ((Byte & 0xf0) && (Byte & 0x0f)) - missing.mosaic = 1; - #endif - } - - break; - - case 0x2107: // BG1SC - if (Byte != Memory.FillRAM[0x2107]) - { - FLUSH_REDRAW(); - PPU.BG[0].SCSize = Byte & 3; - PPU.BG[0].SCBase = (Byte & 0x7c) << 8; - } - - break; - - case 0x2108: // BG2SC - if (Byte != Memory.FillRAM[0x2108]) - { - FLUSH_REDRAW(); - PPU.BG[1].SCSize = Byte & 3; - PPU.BG[1].SCBase = (Byte & 0x7c) << 8; - } - - break; - - case 0x2109: // BG3SC - if (Byte != Memory.FillRAM[0x2109]) - { - FLUSH_REDRAW(); - PPU.BG[2].SCSize = Byte & 3; - PPU.BG[2].SCBase = (Byte & 0x7c) << 8; - } - - break; - - case 0x210a: // BG4SC - if (Byte != Memory.FillRAM[0x210a]) - { - FLUSH_REDRAW(); - PPU.BG[3].SCSize = Byte & 3; - PPU.BG[3].SCBase = (Byte & 0x7c) << 8; - } - - break; - - case 0x210b: // BG12NBA - if (Byte != Memory.FillRAM[0x210b]) - { - FLUSH_REDRAW(); - PPU.BG[0].NameBase = (Byte & 7) << 12; - PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; - } - - break; - - case 0x210c: // BG34NBA - if (Byte != Memory.FillRAM[0x210c]) - { - FLUSH_REDRAW(); - PPU.BG[2].NameBase = (Byte & 7) << 12; - PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; - } - - break; - - case 0x210d: // BG1HOFS, M7HOFS - PPU.BG[0].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[0].HOffset >> 8) & 7); - PPU.M7HOFS = (Byte << 8) | PPU.M7byte; - PPU.BGnxOFSbyte = Byte; - PPU.M7byte = Byte; - break; - - case 0x210e: // BG1VOFS, M7VOFS - PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; - PPU.M7VOFS = (Byte << 8) | PPU.M7byte; - PPU.BGnxOFSbyte = Byte; - PPU.M7byte = Byte; - break; - - case 0x210f: // BG2HOFS - PPU.BG[1].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[1].HOffset >> 8) & 7); - PPU.BGnxOFSbyte = Byte; - break; - - case 0x2110: // BG2VOFS - PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - break; - - case 0x2111: // BG3HOFS - PPU.BG[2].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[2].HOffset >> 8) & 7); - PPU.BGnxOFSbyte = Byte; - break; - - case 0x2112: // BG3VOFS - PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - break; - - case 0x2113: // BG4HOFS - PPU.BG[3].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[3].HOffset >> 8) & 7); - PPU.BGnxOFSbyte = Byte; - break; - - case 0x2114: // BG4VOFS - PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - break; - - case 0x2115: // VMAIN - PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; - switch (Byte & 3) - { - case 0: PPU.VMA.Increment = 1; break; - case 1: PPU.VMA.Increment = 32; break; - case 2: PPU.VMA.Increment = 128; break; - case 3: PPU.VMA.Increment = 128; break; - } - - if (Byte & 0x0c) - { - static uint16 Shift[4] = { 0, 5, 6, 7 }; - static uint16 IncCount[4] = { 0, 32, 64, 128 }; - - uint8 i = (Byte & 0x0c) >> 2; - PPU.VMA.FullGraphicCount = IncCount[i]; - PPU.VMA.Mask1 = IncCount[i] * 8 - 1; - PPU.VMA.Shift = Shift[i]; - #ifdef DEBUGGER - missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2; - #endif - } - else - PPU.VMA.FullGraphicCount = 0; - #ifdef DEBUGGER - if (Byte & 3) - missing.vram_inc = Byte & 3; - #endif - break; - - case 0x2116: // VMADDL - PPU.VMA.Address &= 0xff00; - PPU.VMA.Address |= Byte; - #ifdef CORRECT_VRAM_READS - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); - } - else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); - #else - IPPU.FirstVRAMRead = TRUE; - #endif - break; - - case 0x2117: // VMADDH - PPU.VMA.Address &= 0x00ff; - PPU.VMA.Address |= Byte << 8; - #ifdef CORRECT_VRAM_READS - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); - } - else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); - #else - IPPU.FirstVRAMRead = TRUE; - #endif - break; - - case 0x2118: // VMDATAL - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif - REGISTER_2118(Byte); - break; - - case 0x2119: // VMDATAH - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif - REGISTER_2119(Byte); - break; - - case 0x211a: // M7SEL - if (Byte != Memory.FillRAM[0x211a]) - { - FLUSH_REDRAW(); - PPU.Mode7Repeat = Byte >> 6; - if (PPU.Mode7Repeat == 1) - PPU.Mode7Repeat = 0; - PPU.Mode7VFlip = (Byte & 2) >> 1; - PPU.Mode7HFlip = Byte & 1; - } - - break; - - case 0x211b: // M7A - PPU.MatrixA = PPU.M7byte | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - PPU.M7byte = Byte; - break; - - case 0x211c: // M7B - PPU.MatrixB = PPU.M7byte | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - PPU.M7byte = Byte; - break; - - case 0x211d: // M7C - PPU.MatrixC = PPU.M7byte | (Byte << 8); - PPU.M7byte = Byte; - break; - - case 0x211e: // M7D - PPU.MatrixD = PPU.M7byte | (Byte << 8); - PPU.M7byte = Byte; - break; - - case 0x211f: // M7X - PPU.CentreX = PPU.M7byte | (Byte << 8); - PPU.M7byte = Byte; - break; - - case 0x2120: // M7Y - PPU.CentreY = PPU.M7byte | (Byte << 8); - PPU.M7byte = Byte; - break; - - case 0x2121: // CGADD - PPU.CGFLIP = 0; - PPU.CGFLIPRead = 0; - PPU.CGADD = Byte; - break; - - case 0x2122: // CGDATA - REGISTER_2122(Byte); - break; - - case 0x2123: // W12SEL - if (Byte != Memory.FillRAM[0x2123]) - { - FLUSH_REDRAW(); - PPU.ClipWindow1Enable[0] = !!(Byte & 0x02); - PPU.ClipWindow1Enable[1] = !!(Byte & 0x20); - PPU.ClipWindow2Enable[0] = !!(Byte & 0x08); - PPU.ClipWindow2Enable[1] = !!(Byte & 0x80); - PPU.ClipWindow1Inside[0] = !(Byte & 0x01); - PPU.ClipWindow1Inside[1] = !(Byte & 0x10); - PPU.ClipWindow2Inside[0] = !(Byte & 0x04); - PPU.ClipWindow2Inside[1] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; - #ifdef DEBUGGER - if (Byte & 0x80) - missing.window2[1] = 1; - if (Byte & 0x20) - missing.window1[1] = 1; - if (Byte & 0x08) - missing.window2[0] = 1; - if (Byte & 0x02) - missing.window1[0] = 1; - #endif - } - - break; - - case 0x2124: // W34SEL - if (Byte != Memory.FillRAM[0x2124]) - { - FLUSH_REDRAW(); - PPU.ClipWindow1Enable[2] = !!(Byte & 0x02); - PPU.ClipWindow1Enable[3] = !!(Byte & 0x20); - PPU.ClipWindow2Enable[2] = !!(Byte & 0x08); - PPU.ClipWindow2Enable[3] = !!(Byte & 0x80); - PPU.ClipWindow1Inside[2] = !(Byte & 0x01); - PPU.ClipWindow1Inside[3] = !(Byte & 0x10); - PPU.ClipWindow2Inside[2] = !(Byte & 0x04); - PPU.ClipWindow2Inside[3] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; - #ifdef DEBUGGER - if (Byte & 0x80) - missing.window2[3] = 1; - if (Byte & 0x20) - missing.window1[3] = 1; - if (Byte & 0x08) - missing.window2[2] = 1; - if (Byte & 0x02) - missing.window1[2] = 1; - #endif - } - - break; - - case 0x2125: // WOBJSEL - if (Byte != Memory.FillRAM[0x2125]) - { - FLUSH_REDRAW(); - PPU.ClipWindow1Enable[4] = !!(Byte & 0x02); - PPU.ClipWindow1Enable[5] = !!(Byte & 0x20); - PPU.ClipWindow2Enable[4] = !!(Byte & 0x08); - PPU.ClipWindow2Enable[5] = !!(Byte & 0x80); - PPU.ClipWindow1Inside[4] = !(Byte & 0x01); - PPU.ClipWindow1Inside[5] = !(Byte & 0x10); - PPU.ClipWindow2Inside[4] = !(Byte & 0x04); - PPU.ClipWindow2Inside[5] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; - #ifdef DEBUGGER - if (Byte & 0x80) - missing.window2[5] = 1; - if (Byte & 0x20) - missing.window1[5] = 1; - if (Byte & 0x08) - missing.window2[4] = 1; - if (Byte & 0x02) - missing.window1[4] = 1; - #endif - } - - break; - - case 0x2126: // WH0 - if (Byte != Memory.FillRAM[0x2126]) - { - FLUSH_REDRAW(); - PPU.Window1Left = Byte; - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x2127: // WH1 - if (Byte != Memory.FillRAM[0x2127]) - { - FLUSH_REDRAW(); - PPU.Window1Right = Byte; - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x2128: // WH2 - if (Byte != Memory.FillRAM[0x2128]) - { - FLUSH_REDRAW(); - PPU.Window2Left = Byte; - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x2129: // WH3 - if (Byte != Memory.FillRAM[0x2129]) - { - FLUSH_REDRAW(); - PPU.Window2Right = Byte; - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x212a: // WBGLOG - if (Byte != Memory.FillRAM[0x212a]) - { - FLUSH_REDRAW(); - PPU.ClipWindowOverlapLogic[0] = (Byte & 0x03); - PPU.ClipWindowOverlapLogic[1] = (Byte & 0x0c) >> 2; - PPU.ClipWindowOverlapLogic[2] = (Byte & 0x30) >> 4; - PPU.ClipWindowOverlapLogic[3] = (Byte & 0xc0) >> 6; - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x212b: // WOBJLOG - if (Byte != Memory.FillRAM[0x212b]) - { - FLUSH_REDRAW(); - PPU.ClipWindowOverlapLogic[4] = (Byte & 0x03); - PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2; - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x212c: // TM - if (Byte != Memory.FillRAM[0x212c]) - { - FLUSH_REDRAW(); - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x212d: // TS - if (Byte != Memory.FillRAM[0x212d]) - { - FLUSH_REDRAW(); - PPU.RecomputeClipWindows = TRUE; - #ifdef DEBUGGER - if (Byte & 0x1f) - missing.subscreen = 1; - #endif - } - - break; - - case 0x212e: // TMW - if (Byte != Memory.FillRAM[0x212e]) - { - FLUSH_REDRAW(); - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x212f: // TSW - if (Byte != Memory.FillRAM[0x212f]) - { - FLUSH_REDRAW(); - PPU.RecomputeClipWindows = TRUE; - } - - break; - - case 0x2130: // CGWSEL - if (Byte != Memory.FillRAM[0x2130]) - { - FLUSH_REDRAW(); - PPU.RecomputeClipWindows = TRUE; - #ifdef DEBUGGER - if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7)) - missing.direct = 1; - #endif - } - - break; - - case 0x2131: // CGADSUB - if (Byte != Memory.FillRAM[0x2131]) - { - FLUSH_REDRAW(); - #ifdef DEBUGGER - if (Byte & 0x80) - { - if (Memory.FillRAM[0x2130] & 0x02) - missing.subscreen_sub = 1; - else - missing.fixed_colour_sub = 1; - } - else - { - if (Memory.FillRAM[0x2130] & 0x02) - missing.subscreen_add = 1; - else - missing.fixed_colour_add = 1; - } - #endif - } - - break; - - case 0x2132: // COLDATA - if (Byte != Memory.FillRAM[0x2132]) - { - FLUSH_REDRAW(); - if (Byte & 0x80) - PPU.FixedColourBlue = Byte & 0x1f; - if (Byte & 0x40) - PPU.FixedColourGreen = Byte & 0x1f; - if (Byte & 0x20) - PPU.FixedColourRed = Byte & 0x1f; - } - - break; - - case 0x2133: // SETINI - if (Byte != Memory.FillRAM[0x2133]) - { - if ((Memory.FillRAM[0x2133] ^ Byte) & 8) - { - FLUSH_REDRAW(); - IPPU.PseudoHires = Byte & 8; - } - - if (Byte & 0x04) - { - PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; - if (IPPU.DoubleHeightPixels) - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - else - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - #ifdef DEBUGGER - missing.lines_239 = 1; - #endif - } - else - PPU.ScreenHeight = SNES_HEIGHT; - - if ((Memory.FillRAM[0x2133] ^ Byte) & 3) - { - FLUSH_REDRAW(); - if ((Memory.FillRAM[0x2133] ^ Byte) & 2) - IPPU.OBJChanged = TRUE; - if (PPU.BGMode == 5 || PPU.BGMode == 6) - IPPU.Interlace = Byte & 1; - IPPU.InterlaceOBJ = Byte & 2; - } - #ifdef DEBUGGER - if (Byte & 0x40) - missing.mode7_bgmode = 1; - if (Byte & 0x08) - missing.pseudo_512 = 1; - if (Byte & 0x02) - missing.sprite_double_height = 1; - if (Byte & 0x01) - missing.interlace = 1; - #endif - } - - break; - - case 0x2134: // MPYL - case 0x2135: // MPYM - case 0x2136: // MPYH - case 0x2137: // SLHV - case 0x2138: // OAMDATAREAD - case 0x2139: // VMDATALREAD - case 0x213a: // VMDATAHREAD - case 0x213b: // CGDATAREAD - case 0x213c: // OPHCT - case 0x213d: // OPVCT - case 0x213e: // STAT77 - case 0x213f: // STAT78 - return; - - case 0x2180: // WMDATA - if (!CPU.InWRAMDMAorHDMA) - REGISTER_2180(Byte); - break; - - case 0x2181: // WMADDL - if (!CPU.InWRAMDMAorHDMA) - { - PPU.WRAM &= 0x1ff00; - PPU.WRAM |= Byte; - } - - break; - - case 0x2182: // WMADDM - if (!CPU.InWRAMDMAorHDMA) - { - PPU.WRAM &= 0x100ff; - PPU.WRAM |= Byte << 8; - } - - break; - - case 0x2183: // WMADDH - if (!CPU.InWRAMDMAorHDMA) - { - PPU.WRAM &= 0x0ffff; - PPU.WRAM |= Byte << 16; - PPU.WRAM &= 0x1ffff; - } - - break; - } - } - else - { - if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) - { - S9xSetSuperFX(Byte, Address); - return; - } - else - if (Settings.SA1 && Address >= 0x2200) - { - if (Address <= 0x23ff) - S9xSetSA1(Byte, Address); - else - Memory.FillRAM[Address] = Byte; - return; - } - else - if (Settings.BS && Address >= 0x2188 && Address <= 0x219f) - S9xSetBSXPPU(Byte, Address); - else - if (Settings.SRTC && Address == 0x2801) - S9xSetSRTC(Byte, Address); - #ifdef DEBUGGER - else - { - missing.unknownppu_write = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf(String, "Unknown register write: $%02X->$%04X\n", Byte, Address); - S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); } - } - #endif - } + break; + case 0x2134: + case 0x2135: + case 0x2136: + // Matrix 16bit x 8bit multiply result (read-only) + return; + case 0x2137: + // Software latch for horizontal and vertical timers (read-only) + return; + case 0x2138: + // OAM read data (read-only) + return; + case 0x2139: + case 0x213a: + // VRAM read data (read-only) + return; + case 0x213b: + // CG-RAM read data (read-only) + return; + case 0x213c: + case 0x213d: + // Horizontal and vertical (low/high) read counter (read-only) + return; + case 0x213e: + // PPU status (time over and range over) + return; + case 0x213f: + // NTSC/PAL select and field (read-only) + return; + case 0x2140: case 0x2141: case 0x2142: case 0x2143: + case 0x2144: case 0x2145: case 0x2146: case 0x2147: + case 0x2148: case 0x2149: case 0x214a: case 0x214b: + case 0x214c: case 0x214d: case 0x214e: case 0x214f: + case 0x2150: case 0x2151: case 0x2152: case 0x2153: + case 0x2154: case 0x2155: case 0x2156: case 0x2157: + case 0x2158: case 0x2159: case 0x215a: case 0x215b: + case 0x215c: case 0x215d: case 0x215e: case 0x215f: + case 0x2160: case 0x2161: case 0x2162: case 0x2163: + case 0x2164: case 0x2165: case 0x2166: case 0x2167: + case 0x2168: case 0x2169: case 0x216a: case 0x216b: + case 0x216c: case 0x216d: case 0x216e: case 0x216f: + case 0x2170: case 0x2171: case 0x2172: case 0x2173: + case 0x2174: case 0x2175: case 0x2176: case 0x2177: + case 0x2178: case 0x2179: case 0x217a: case 0x217b: + case 0x217c: case 0x217d: case 0x217e: case 0x217f: +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; +#endif + S9xAPUExecute(); + Memory.FillRAM [Address] = Byte; + IAPU.RAM [(Address & 3) + 0xf4] = Byte; + break; + case 0x2180: + if(!CPU.InWRAMDMAorHDMA){ + REGISTER_2180(Byte); + } + break; + case 0x2181: + if(!CPU.InWRAMDMAorHDMA){ + PPU.WRAM &= 0x1FF00; + PPU.WRAM |= Byte; + } + break; + case 0x2182: + if(!CPU.InWRAMDMAorHDMA){ + PPU.WRAM &= 0x100FF; + PPU.WRAM |= Byte << 8; + } + break; + case 0x2183: + if(!CPU.InWRAMDMAorHDMA){ + PPU.WRAM &= 0x0FFFF; + PPU.WRAM |= Byte << 16; + PPU.WRAM &= 0x1FFFF; + } + break; + + case 0x2188: + case 0x2189: + case 0x218a: + case 0x218b: + case 0x218c: + case 0x218d: + case 0x218e: + case 0x218f: + case 0x2190: + case 0x2191: + case 0x2192: + case 0x2193: + case 0x2194: + case 0x2195: + case 0x2196: + case 0x2197: + case 0x2198: + case 0x2199: + case 0x219a: + case 0x219b: + case 0x219c: + case 0x219d: + case 0x219e: + case 0x219f: + if (Settings.BS) + S9xSetBSXPPU(Byte, Address); + break; + } + } + else + { + if (Settings.SA1) + { + if (Address >= 0x2200 && Address <0x23ff) + S9xSetSA1 (Byte, Address); + else + Memory.FillRAM [Address] = Byte; + + return; + } + else + // Dai Kaijyu Monogatari II + if (Address == 0x2801 && Settings.SRTC) + S9xSetSRTC (Byte, Address); + else + if (Address < 0x3000 || Address >= 0x3000 + 768) + { +#ifdef DEBUGGER + missing.unknownppu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register write: $%02X->$%04X\n", + Byte, Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + } + else + { + if (!Settings.SuperFX) + { + return; + } + +#ifdef ZSNES_FX + Memory.FillRAM [Address] = Byte; + if (Address < 0x3040) + S9xSuperFXWriteReg (Byte, Address); +#else + switch (Address) + { + case 0x3030: + if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) + { + Memory.FillRAM [Address] = Byte; + // Go flag has been changed + if (Byte & FLG_G) + { + if (!SuperFX.oneLineDone) + { + S9xSuperFXExec (); + SuperFX.oneLineDone = TRUE; + } + } + else + FxFlushCache (); + } + else + Memory.FillRAM [Address] = Byte; + break; + + case 0x3031: + Memory.FillRAM [Address] = Byte; + break; + case 0x3033: + Memory.FillRAM [Address] = Byte; + break; + case 0x3034: + Memory.FillRAM [Address] = Byte & 0x7f; + break; + case 0x3036: + Memory.FillRAM [Address] = Byte & 0x7f; + break; + case 0x3037: + Memory.FillRAM [Address] = Byte; + break; + case 0x3038: + Memory.FillRAM [Address] = Byte; + fx_dirtySCBR(); + break; + case 0x3039: + Memory.FillRAM [Address] = Byte; + break; + case 0x303a: + Memory.FillRAM [Address] = Byte; + break; + case 0x303b: + break; + case 0x303c: + Memory.FillRAM [Address] = Byte; + fx_updateRamBank(Byte); + break; + case 0x303f: + Memory.FillRAM [Address] = Byte; + break; + case 0x301f: + Memory.FillRAM [Address] = Byte; + Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; + if (!SuperFX.oneLineDone) + { + S9xSuperFXExec (); + SuperFX.oneLineDone = TRUE; + } + return; + + default: + Memory.FillRAM[Address] = Byte; + if (Address >= 0x3100) + { + FxCacheWriteAccess (Address); + } + break; + } +#endif + return; + } + } Memory.FillRAM[Address] = Byte; + } +/******************************************************************************/ +/* S9xGetPPU() */ +/* This function retrieves a PPU Register */ +/******************************************************************************/ uint8 S9xGetPPU (uint16 Address) { - // MAP_PPU: $2000-$3FFF + uint8 byte = OpenBus; - if (Address < 0x2100) - return (OpenBus); + if(Address<0x2100)//not a real PPU reg + return OpenBus; //treat as unmapped memory returning last byte on the bus - if (CPU.InDMAorHDMA) - { - if (CPU.CurrentDMAorHDMAChannel >= 0 && !DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) - { - // S9xGetPPU() is called to read from DMA[].AAddress - if ((Address & 0xff00) == 0x2100) - // Cannot access to Address Bus B ($2100-$21FF) via (H)DMA - return (OpenBus); + // Take care of DMA wrapping + if(CPU.InDMAorHDMA && Address>0x21ff) Address=0x2100+(Address&0xff); + + if (Address <= 0x219F) + { + switch (Address) + { + case 0x2100: + case 0x2101: + case 0x2102: + case 0x2103: + #ifdef DEBUGGER + missing.oam_address_read = 1; + #endif + return OpenBus; + + case 0x2104: + case 0x2105: + case 0x2106: + return PPU.OpenBus1; + case 0x2107: + return OpenBus; + case 0x2108: + case 0x2109: + case 0x210a: + return PPU.OpenBus1; + case 0x210b: + case 0x210c: + case 0x210d: + case 0x210e: + case 0x210f: + case 0x2110: + case 0x2111: + case 0x2112: + case 0x2113: + missing.bg_offset_read = 1; + return OpenBus; + + case 0x2114: +#ifdef DEBUGGER + missing.bg_offset_read = 1; +#endif + case 0x2115: + case 0x2116: + return PPU.OpenBus1; + + case 0x2117: + return OpenBus; + + case 0x2118: + case 0x2119: + case 0x211a: + return PPU.OpenBus1; + + case 0x211b: + case 0x211c: + case 0x211d: + case 0x211e: + case 0x211f: + case 0x2120: +#ifdef DEBUGGER + missing.matrix_read = 1; +#endif + return OpenBus; + + case 0x2121: + case 0x2122: + case 0x2123: + return OpenBus; + + case 0x2124: + case 0x2125: + case 0x2126: + return PPU.OpenBus1; + + case 0x2127: + return OpenBus; + + case 0x2128: + case 0x2129: + case 0x212a: + return PPU.OpenBus1; + + case 0x212b: + case 0x212c: + case 0x212d: + case 0x212e: + case 0x212f: + case 0x2130: + case 0x2131: + case 0x2132: + case 0x2133: + return OpenBus; + + case 0x2134: + case 0x2135: + case 0x2136: + // 16bit x 8bit multiply read result. + if (PPU.Need16x8Mulitply) + { + int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8); + + Memory.FillRAM[0x2134] = (uint8) r; + Memory.FillRAM[0x2135] = (uint8)(r >> 8); + Memory.FillRAM[0x2136] = (uint8)(r >> 16); + PPU.Need16x8Mulitply = FALSE; + } +#ifdef DEBUGGER + missing.matrix_multiply = 1; +#endif + return (PPU.OpenBus1 = Memory.FillRAM[Address]); + case 0x2137: + S9xLatchCounters(0); + return OpenBus; + + case 0x2138: + // Read OAM (sprite) control data + if(PPU.OAMAddr&0x100){ + if (!(PPU.OAMFlip&1)) + { + byte = PPU.OAMData [(PPU.OAMAddr&0x10f) << 1]; + } else - // $2200-$3FFF are connected to Address Bus A - // SA1, SuperFX and SRTC are mapped here - // I don't bother for now... - return (OpenBus); + { + byte = PPU.OAMData [((PPU.OAMAddr&0x10f) << 1) + 1]; + PPU.OAMAddr=(PPU.OAMAddr+1)&0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + } + } else { + if (!(PPU.OAMFlip&1)) + { + byte = PPU.OAMData [PPU.OAMAddr << 1]; + } + else + { + byte = PPU.OAMData [(PPU.OAMAddr << 1) + 1]; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + } } - else + PPU.OAMFlip ^= 1; +#ifdef DEBUGGER + missing.oam_read = 1; +#endif + return (PPU.OpenBus1 = byte); + + case 0x2139: + // Read vram low byte +#ifdef DEBUGGER + missing.vram_read = 1; +#endif +#ifdef CORRECT_VRAM_READS + byte = IPPU.VRAMReadBuffer & 0xff; + if (!PPU.VMA.High) { - // S9xGetPPU() is called to write to $21xx - // Take care of DMA wrapping - if (Address > 0x21ff) - Address = 0x2100 + (Address & 0xff); + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); + } else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); + PPU.VMA.Address += PPU.VMA.Increment; } +#else + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[(PPU.VMA.Address << 1)&0xFFFF]; + else + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM [((address << 1) - 2) & 0xFFFF]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; + + if (!PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } +#endif + PPU.OpenBus1 = byte; + break; + case 0x213A: + // Read vram high byte +#ifdef DEBUGGER + missing.vram_read = 1; +#endif +#ifdef CORRECT_VRAM_READS + byte = (IPPU.VRAMReadBuffer>>8) & 0xff; + if (PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); + } else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); + PPU.VMA.Address += PPU.VMA.Increment; + } +#else + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; + else + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM [((address << 1) - 1) & 0xFFFF]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xFFFF]; + if (PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } +#endif + PPU.OpenBus1 = byte; + break; + + case 0x213B: + // Read palette data +#ifdef DEBUGGER + missing.cgram_read = 1; +#endif + if (PPU.CGFLIPRead) + byte = PPU.CGDATA [PPU.CGADD++] >> 8; + else + byte = PPU.CGDATA [PPU.CGADD] & 0xff; + + PPU.CGFLIPRead ^= 1; + return (PPU.OpenBus2 = byte); + + case 0x213C: + // Horizontal counter value 0-339 +#ifdef DEBUGGER + missing.h_counter_read = 1; +#endif + S9xTryGunLatch(false); + if (PPU.HBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01); + else + byte = (uint8)PPU.HBeamPosLatched; + PPU.OpenBus2 = byte; + PPU.HBeamFlip ^= 1; + break; + + case 0x213D: + // Vertical counter value 0-262 +#ifdef DEBUGGER + missing.v_counter_read = 1; +#endif + S9xTryGunLatch(false); + if (PPU.VBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01); + else + byte = (uint8)PPU.VBeamPosLatched; + PPU.OpenBus2 = byte; + PPU.VBeamFlip ^= 1; + break; + + case 0x213E: + // PPU time and range over flags + FLUSH_REDRAW (); + + //so far, 5c77 version is always 1. + return (PPU.OpenBus1 = (Model->_5C77 | PPU.RangeTimeOver)); + + case 0x213F: + // NTSC/PAL and which field flags + S9xTryGunLatch(false); + PPU.VBeamFlip = PPU.HBeamFlip = 0; + //neviksti found a 2 and a 3 here. SNEeSe uses a 3. + byte=((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0) | Model->_5C78) | (PPU.OpenBus2 & 0x20); + Memory.FillRAM[0x213f] &= ~0x40; + return byte; + + case 0x2140: case 0x2141: case 0x2142: case 0x2143: + case 0x2144: case 0x2145: case 0x2146: case 0x2147: + case 0x2148: case 0x2149: case 0x214a: case 0x214b: + case 0x214c: case 0x214d: case 0x214e: case 0x214f: + case 0x2150: case 0x2151: case 0x2152: case 0x2153: + case 0x2154: case 0x2155: case 0x2156: case 0x2157: + case 0x2158: case 0x2159: case 0x215a: case 0x215b: + case 0x215c: case 0x215d: case 0x215e: case 0x215f: + case 0x2160: case 0x2161: case 0x2162: case 0x2163: + case 0x2164: case 0x2165: case 0x2166: case 0x2167: + case 0x2168: case 0x2169: case 0x216a: case 0x216b: + case 0x216c: case 0x216d: case 0x216e: case 0x216f: + case 0x2170: case 0x2171: case 0x2172: case 0x2173: + case 0x2174: case 0x2175: case 0x2176: case 0x2177: + case 0x2178: case 0x2179: case 0x217a: case 0x217b: + case 0x217c: case 0x217d: case 0x217e: case 0x217f: +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; +#endif + S9xAPUExecute(); + if (Settings.APUEnabled) + { +#ifdef CPU_SHUTDOWN +// CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif +#if 0 + if (SNESGameFixes.APU_OutPorts_ReturnValueFix && + Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) + { + return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : + (rand() & 0xff)); + } +#endif + return (APU.OutPorts [Address & 3]); + } + + switch (Settings.SoundSkipMethod) + { + case 0: + case 1: + CPU.BranchSkip = TRUE; + break; + case 2: + break; + case 3: + CPU.BranchSkip = TRUE; + break; + } + if ((Address & 3) < 2) + { + int r = rand (); + if (r & 2) + { + if (r & 4) + return ((Address & 3) == 1 ? 0xaa : 0xbb); + else + return ((r >> 3) & 0xff); + } + } + else + { + int r = rand (); + if (r & 2) + return ((r >> 3) & 0xff); + } + return (Memory.FillRAM[Address]); + + case 0x2180: + // Read WRAM +#ifdef DEBUGGER + missing.wram_read = 1; +#endif + if(!CPU.InWRAMDMAorHDMA){ + byte = Memory.RAM [PPU.WRAM++]; + PPU.WRAM &= 0x1FFFF; + } else { + byte=OpenBus; + } + break; + case 0x2181: + case 0x2182: + case 0x2183: + case 0x2184: + case 0x2185: + case 0x2186: + case 0x2187: + return OpenBus; + + case 0x2188: + case 0x2189: + case 0x218a: + case 0x218b: + case 0x218c: + case 0x218d: + case 0x218e: + case 0x218f: + case 0x2190: + case 0x2191: + case 0x2192: + case 0x2193: + case 0x2194: + case 0x2195: + case 0x2196: + case 0x2197: + case 0x2198: + case 0x2199: + case 0x219a: + case 0x219b: + case 0x219c: + case 0x219d: + case 0x219e: + case 0x219f: + if (Settings.BS) + return S9xGetBSXPPU(Address); + else + return OpenBus; + + default: + return OpenBus; + } + } + else + { + if (Settings.SA1) + return (S9xGetSA1 (Address)); + + if (Address <= 0x2fff || Address >= 0x3000 + 768) + { + switch (Address) + { + case 0x21c2: + if(Model->_5C77 ==2) + return (0x20); + + // fprintf(stderr, "Read from $21c2!\n"); + return OpenBus; + case 0x21c3: + if(Model->_5C77 ==2) + return (0); + // fprintf(stderr, "Read from $21c3!\n"); + return OpenBus; + case 0x2800: + // For Dai Kaijyu Monogatari II + if (Settings.SRTC) + return (S9xGetSRTC (Address)); + /*FALL*/ + + default: +#ifdef DEBUGGER + missing.unknownppu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register read: $%04X\n", Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + return OpenBus; + } } - if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 - // read_port will run the APU until given APU time before reading value - return (S9xAPUReadPort(Address & 3)); + if (!Settings.SuperFX) + return OpenBus; +#ifdef ZSNES_FX + if (Address < 0x3040) + byte = S9xSuperFXReadReg (Address); else - if (Address <= 0x2183) - { - uint8 byte; + byte = Memory.FillRAM [Address]; - switch (Address) - { - case 0x2104: // OAMDATA - case 0x2105: // BGMODE - case 0x2106: // MOSAIC - case 0x2108: // BG2SC - case 0x2109: // BG3SC - case 0x210a: // BG4SC - case 0x2114: // BG4VOFS - case 0x2115: // VMAIN - case 0x2116: // VMADDL - case 0x2118: // VMDATAL - case 0x2119: // VMDATAH - case 0x211a: // M7SEL - case 0x2124: // W34SEL - case 0x2125: // WOBJSEL - case 0x2126: // WH0 - case 0x2128: // WH2 - case 0x2129: // WH3 - case 0x212a: // WBGLOG - return (PPU.OpenBus1); +#ifdef CPU_SHUTDOWN + if (Address == 0x3030) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; +#endif + if (Address == 0x3031) + CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); +#else + byte = Memory.FillRAM [Address]; - case 0x2134: // MPYL - case 0x2135: // MPYM - case 0x2136: // MPYH - if (PPU.Need16x8Mulitply) - { - int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8); - Memory.FillRAM[0x2134] = (uint8) r; - Memory.FillRAM[0x2135] = (uint8) (r >> 8); - Memory.FillRAM[0x2136] = (uint8) (r >> 16); - PPU.Need16x8Mulitply = FALSE; - } - #ifdef DEBUGGER - missing.matrix_multiply = 1; - #endif - return (PPU.OpenBus1 = Memory.FillRAM[Address]); - - case 0x2137: // SLHV - S9xLatchCounters(0); - return (OpenBus); - - case 0x2138: // OAMDATAREAD - if (PPU.OAMAddr & 0x100) - { - if (!(PPU.OAMFlip & 1)) - byte = PPU.OAMData[(PPU.OAMAddr & 0x10f) << 1]; - else - { - byte = PPU.OAMData[((PPU.OAMAddr & 0x10f) << 1) + 1]; - PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; - IPPU.OBJChanged = TRUE; - #ifdef DEBUGGER - missing.sprite_priority_rotation = 1; - #endif - } - } - } - else - { - if (!(PPU.OAMFlip & 1)) - byte = PPU.OAMData[PPU.OAMAddr << 1]; - else - { - byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1]; - ++PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; - IPPU.OBJChanged = TRUE; - #ifdef DEBUGGER - missing.sprite_priority_rotation = 1; - #endif - } - } - } - - PPU.OAMFlip ^= 1; - #ifdef DEBUGGER - missing.oam_read = 1; - #endif - return (PPU.OpenBus1 = byte); - - case 0x2139: // VMDATALREAD - #ifdef CORRECT_VRAM_READS - byte = IPPU.VRAMReadBuffer & 0xff; - if (!PPU.VMA.High) - { - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); - } - else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); - - PPU.VMA.Address += PPU.VMA.Increment; - } - #else - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM[((address << 1) - 2) & 0xffff]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; - - if (!PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } - #endif - #ifdef DEBUGGER - missing.vram_read = 1; - #endif - return (PPU.OpenBus1 = byte); - - case 0x213a: // VMDATAHREAD - #ifdef CORRECT_VRAM_READS - byte = (IPPU.VRAMReadBuffer >> 8) & 0xff; - if (PPU.VMA.High) - { - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); - } - else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); - - PPU.VMA.Address += PPU.VMA.Increment; - } - #else - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM[((address << 1) - 1) & 0xffff]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xffff]; - - if (PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } - #endif - #ifdef DEBUGGER - missing.vram_read = 1; - #endif - return (PPU.OpenBus1 = byte); - - case 0x213b: // CGDATAREAD - if (PPU.CGFLIPRead) - byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f); - else - byte = PPU.CGDATA[PPU.CGADD] & 0xff; - PPU.CGFLIPRead ^= 1; - #ifdef DEBUGGER - missing.cgram_read = 1; - #endif - return (PPU.OpenBus2 = byte); - - case 0x213c: // OPHCT - S9xTryGunLatch(false); - if (PPU.HBeamFlip) - byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01); - else - byte = (uint8) PPU.HBeamPosLatched; - PPU.HBeamFlip ^= 1; - #ifdef DEBUGGER - missing.h_counter_read = 1; - #endif - return (PPU.OpenBus2 = byte); - - case 0x213d: // OPVCT - S9xTryGunLatch(false); - if (PPU.VBeamFlip) - byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01); - else - byte = (uint8) PPU.VBeamPosLatched; - PPU.VBeamFlip ^= 1; - #ifdef DEBUGGER - missing.v_counter_read = 1; - #endif - return (PPU.OpenBus2 = byte); - - case 0x213e: // STAT77 - FLUSH_REDRAW(); - byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77; - return (PPU.OpenBus1 = byte); - - case 0x213f: // STAT78 - S9xTryGunLatch(false); - PPU.VBeamFlip = PPU.HBeamFlip = 0; - byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78; - Memory.FillRAM[0x213f] &= ~0x40; - return (PPU.OpenBus2 = byte); - - case 0x2180: // WMDATA - if (!CPU.InWRAMDMAorHDMA) - { - byte = Memory.RAM[PPU.WRAM++]; - PPU.WRAM &= 0x1ffff; - } - else - byte = OpenBus; - #ifdef DEBUGGER - missing.wram_read = 1; - #endif - return (byte); - - default: - return (OpenBus); - } +//if (Address != 0x3030 && Address != 0x3031) +//printf ("%04x\n", Address); +#ifdef CPU_SHUTDOWN + if (Address == 0x3030) + { + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; } else - { - if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) - return (S9xGetSuperFX(Address)); - else - if (Settings.SA1 && Address >= 0x2200) - return (S9xGetSA1(Address)); - else - if (Settings.BS && Address >= 0x2188 && Address <= 0x219f) - return (S9xGetBSXPPU(Address)); - else - if (Settings.SRTC && Address == 0x2800) - return (S9xGetSRTC(Address)); - else - switch (Address) - { - case 0x21c2: - if (Model->_5C77 == 2) - return (0x20); - return (OpenBus); - - case 0x21c3: - if (Model->_5C77 == 2) - return (0); - return (OpenBus); - - default: - return (OpenBus); - } +#endif + if (Address == 0x3031) + { + CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); + Memory.FillRAM [0x3031] = byte & 0x7f; } + return (byte); +#endif + } +// fprintf(stderr, "%03d: %02x from %04x\n", CPU.V_Counter, byte, Address); + return (byte); } -void S9xSetCPU (uint8 Byte, uint16 Address) +/******************************************************************************/ +/* S9xSetCPU() */ +/* This function sets a CPU/DMA Register to a specific byte */ +/******************************************************************************/ +void S9xSetCPU (uint8 byte, uint16 Address) { + int d; + bool8 pV; +// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, byte, Address); + if (Address < 0x4200) { - CPU.Cycles += ONE_CYCLE; // XSlow - + CPU.Cycles += ONE_CYCLE; switch (Address) { - case 0x4016: // JOYSER0 - S9xSetJoypadLatch(Byte & 1); - break; - - case 0x4017: // JOYSER1 - return; - - default: - break; - } - } - else - if ((Address & 0xff80) == 0x4300) - { - if (CPU.InDMAorHDMA) - return; - - int d = (Address >> 4) & 0x7; - - switch (Address & 0xf) - { - case 0x0: // 0x43x0: DMAPx - DMA[d].ReverseTransfer = (Byte & 0x80) ? TRUE : FALSE; - DMA[d].HDMAIndirectAddressing = (Byte & 0x40) ? TRUE : FALSE; - DMA[d].UnusedBit43x0 = (Byte & 0x20) ? TRUE : FALSE; - DMA[d].AAddressDecrement = (Byte & 0x10) ? TRUE : FALSE; - DMA[d].AAddressFixed = (Byte & 0x08) ? TRUE : FALSE; - DMA[d].TransferMode = (Byte & 7); - return; - - case 0x1: // 0x43x1: BBADx - DMA[d].BAddress = Byte; - return; - - case 0x2: // 0x43x2: A1TxL - DMA[d].AAddress &= 0xff00; - DMA[d].AAddress |= Byte; - return; - - case 0x3: // 0x43x3: A1TxH - DMA[d].AAddress &= 0xff; - DMA[d].AAddress |= Byte << 8; - return; - - case 0x4: // 0x43x4: A1Bx - DMA[d].ABank = Byte; - HDMAMemPointers[d] = NULL; - return; - - case 0x5: // 0x43x5: DASxL - DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00; - DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte; - HDMAMemPointers[d] = NULL; - return; - - case 0x6: // 0x43x6: DASxH - DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff; - DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte << 8; - HDMAMemPointers[d] = NULL; - return; - - case 0x7: // 0x43x7: DASBx - DMA[d].IndirectBank = Byte; - HDMAMemPointers[d] = NULL; - return; - - case 0x8: // 0x43x8: A2AxL - DMA[d].Address &= 0xff00; - DMA[d].Address |= Byte; - HDMAMemPointers[d] = NULL; - return; - - case 0x9: // 0x43x9: A2AxH - DMA[d].Address &= 0xff; - DMA[d].Address |= Byte << 8; - HDMAMemPointers[d] = NULL; - return; - - case 0xa: // 0x43xa: NLTRx - if (Byte & 0x7f) - { - DMA[d].LineCount = Byte & 0x7f; - DMA[d].Repeat = !(Byte & 0x80); - } - else - { - DMA[d].LineCount = 128; - DMA[d].Repeat = !!(Byte & 0x80); - } - - return; - - case 0xb: // 0x43xb: ????x - case 0xf: // 0x43xf: mirror of 0x43xb - DMA[d].UnknownByte = Byte; - return; - - default: - break; - } - } - else - { - uint16 pos; - - switch (Address) - { - case 0x4200: // NMITIMEN - if (Byte & 0x20) - { - PPU.VTimerEnabled = TRUE; - #ifdef DEBUGGER - missing.virq = 1; - missing.virq_pos = PPU.IRQVBeamPos; - #endif - } - else - PPU.VTimerEnabled = FALSE; - - if (Byte & 0x10) - { - PPU.HTimerEnabled = TRUE; - #ifdef DEBUGGER - missing.hirq = 1; - missing.hirq_pos = PPU.IRQHBeamPos; - #endif - } - else - PPU.HTimerEnabled = FALSE; - - S9xUpdateHVTimerPosition(); - - // The case that IRQ will trigger in an instruction such as STA $4200. - // FIXME: not true but good enough for Snes9x, I think. - S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles); - - if (!(Byte & 0x30)) - S9xClearIRQ(PPU_IRQ_SOURCE); - - // NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard. - if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && - (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80)) - { - // FIXME: triggered at HC+=6, checked just before the final CPU cycle, - // then, when to call S9xOpcode_NMI()? - CPU.Flags |= NMI_FLAG; - Timings.NMITriggerPos = CPU.Cycles + 6 + 6; - } - - break; - - case 0x4201: // WRIO - if ((Byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80) - S9xLatchCounters(1); - else - S9xTryGunLatch((Byte & 0x80) ? true : false); - Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = Byte; - break; - - case 0x4202: // WRMPYA - break; - - case 0x4203: // WRMPYB + case 0x4016: + S9xSetJoypadLatch(byte&1); + break; + case 0x4017: + break; + default: +#ifdef DEBUGGER + missing.unknowncpu_write = Address; + if (Settings.TraceUnknownRegisters) { - uint32 res = Memory.FillRAM[0x4202] * Byte; - // FIXME: The update occurs 8 machine cycles after $4203 is set. + sprintf (String, "Unknown register register write: $%02X->$%04X\n", + byte, Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + } + else + switch (Address) + { + case 0x4200: + // NMI, V & H IRQ and joypad reading enable flags + pV = PPU.VTimerEnabled; + + if (byte & 0x20) + { + PPU.VTimerEnabled = TRUE; +#ifdef DEBUGGER + missing.virq = 1; + missing.virq_pos = PPU.IRQVBeamPos; +#endif + } + else + PPU.VTimerEnabled = FALSE; + + if (byte & 0x10) + { + PPU.HTimerEnabled = TRUE; +#ifdef DEBUGGER + missing.hirq = 1; + missing.hirq_pos = PPU.IRQHBeamPos; +#endif + } + else + PPU.HTimerEnabled = FALSE; + + S9xUpdateHVTimerPosition(); + + // The case that IRQ will trigger in an instruction such as STA $4200 + // FIXME: not true but good enough for Snes9x, I think. + S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles); + + if (!(byte & 0x30)) + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + if ((byte & 0x80) && + !(Memory.FillRAM [0x4200] & 0x80) && + // NMI can trigger during VBlank as long as NMI_read ($4210) wasn't cleard. + // Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling + // NMIs again. The NMI routine crashes the CPU if it is called without the NMI + // pending flag being set...*/ + CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && (Memory.FillRAM [0x4210] & 0x80)) + { + // FIXME: triggered at HC=6, checked just before the final CPU cycle, + // then, when to call S9xOpcode_NMI()? + CPU.Flags |= NMI_FLAG; + Timings.NMITriggerPos = CPU.Cycles + 6 + 6; + } + break; + case 0x4201: + if((byte&0x80)==0 && (Memory.FillRAM[0x4213]&0x80)==0x80) + S9xLatchCounters(1); + else + S9xTryGunLatch((byte&0x80)?true:false); + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = byte; + break; + case 0x4202: + // Multiplier (for multply) + break; + case 0x4203: + { + // Multiplicand + uint32 res = Memory.FillRAM[0x4202] * byte; + Memory.FillRAM[0x4216] = (uint8) res; Memory.FillRAM[0x4217] = (uint8) (res >> 8); break; } - - case 0x4204: // WRDIVL - case 0x4205: // WRDIVH - break; - - case 0x4206: // WRDIVB + case 0x4204: + case 0x4205: + // Low and high muliplier (for divide) + break; + case 0x4206: { + // Divisor uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); - uint16 div = Byte ? a / Byte : 0xffff; - uint16 rem = Byte ? a % Byte : a; - // FIXME: The update occurs 16 machine cycles after $4206 is set. - Memory.FillRAM[0x4214] = (uint8) div; + uint16 div = byte ? a / byte : 0xffff; + uint16 rem = byte ? a % byte : a; + + Memory.FillRAM[0x4214] = (uint8)div; Memory.FillRAM[0x4215] = div >> 8; - Memory.FillRAM[0x4216] = (uint8) rem; + Memory.FillRAM[0x4216] = (uint8)rem; Memory.FillRAM[0x4217] = rem >> 8; break; } - case 0x4207: // HTIMEL - pos = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte; - if (PPU.IRQHBeamPos != pos) - S9xUpdateHVTimerPosition(); - #ifdef DEBUGGER - missing.hirq_pos = PPU.IRQHBeamPos; - #endif - break; + case 0x4207: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; - case 0x4208: // HTIMEH - pos = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8); - if (PPU.IRQHBeamPos != pos) - S9xUpdateHVTimerPosition(); - #ifdef DEBUGGER - missing.hirq_pos = PPU.IRQHBeamPos; - #endif - break; + if (PPU.IRQHBeamPos != d) + S9xUpdateHVTimerPosition(); - case 0x4209: // VTIMEL - pos = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte; - if (PPU.IRQVBeamPos != pos) - S9xUpdateHVTimerPosition(); - #ifdef DEBUGGER - missing.virq_pos = PPU.IRQVBeamPos; - #endif - break; + break; - case 0x420a: // VTIMEH - pos = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8); - if (PPU.IRQVBeamPos != pos) - S9xUpdateHVTimerPosition(); - #ifdef DEBUGGER - missing.virq_pos = PPU.IRQVBeamPos; - #endif - break; + case 0x4208: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); - case 0x420b: // MDMAEN - if (CPU.InDMAorHDMA) - return; - // XXX: Not quite right... - if (Byte) - CPU.Cycles += Timings.DMACPUSync; - if (Byte & 0x01) - S9xDoDMA(0); - if (Byte & 0x02) - S9xDoDMA(1); - if (Byte & 0x04) - S9xDoDMA(2); - if (Byte & 0x08) - S9xDoDMA(3); - if (Byte & 0x10) - S9xDoDMA(4); - if (Byte & 0x20) - S9xDoDMA(5); - if (Byte & 0x40) - S9xDoDMA(6); - if (Byte & 0x80) - S9xDoDMA(7); - #ifdef DEBUGGER - missing.dma_this_frame = Byte; - missing.dma_channels = Byte; - #endif - break; + if (PPU.IRQHBeamPos != d) + S9xUpdateHVTimerPosition(); - case 0x420c: // HDMAEN - if (CPU.InDMAorHDMA) - return; - if (Settings.DisableHDMA) - Byte = 0; - Memory.FillRAM[0x420c] = Byte; - // Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia - PPU.HDMA = Byte & ~PPU.HDMAEnded; - #ifdef DEBUGGER - missing.hdma_this_frame |= Byte; - missing.hdma_channels |= Byte; - #endif - break; + break; - case 0x420d: // MEMSEL - if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1)) + case 0x4209: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; +#ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; +#endif + if (PPU.IRQVBeamPos != d) + S9xUpdateHVTimerPosition(); + + break; + + case 0x420A: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); +#ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; +#endif + if (PPU.IRQVBeamPos != d) + S9xUpdateHVTimerPosition(); + + break; + + case 0x420B: + if(CPU.InDMAorHDMA) return; +#ifdef DEBUGGER + missing.dma_this_frame = byte; + missing.dma_channels = byte; +#endif + // XXX: Not quite right... + if (byte) CPU.Cycles += Timings.DMACPUSync; + if ((byte & 0x01) != 0) + S9xDoDMA (0); + if ((byte & 0x02) != 0) + S9xDoDMA (1); + if ((byte & 0x04) != 0) + S9xDoDMA (2); + if ((byte & 0x08) != 0) + S9xDoDMA (3); + if ((byte & 0x10) != 0) + S9xDoDMA (4); + if ((byte & 0x20) != 0) + S9xDoDMA (5); + if ((byte & 0x40) != 0) + S9xDoDMA (6); + if ((byte & 0x80) != 0) + S9xDoDMA (7); + break; + case 0x420C: + if(CPU.InDMAorHDMA) return; +#ifdef DEBUGGER + missing.hdma_this_frame |= byte; + missing.hdma_channels |= byte; +#endif + if (Settings.DisableHDMA) + byte = 0; + Memory.FillRAM[0x420c] = byte; + //printf("$%02x is written to $420c at HC:%d, V:%d, PPU.HDMA:$%02x, PPU.HDMAEnded:$%02x\n", byte, CPU.Cycles, CPU.V_Counter, PPU.HDMA, PPU.HDMAEnded); + // FIXME + // Yoshi's Island / Genjyu Ryodan, Mortal Kombat, Tales of Phantasia + PPU.HDMA = byte&~PPU.HDMAEnded; + break; + + case 0x420d: + // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) + if ((byte & 1) != (Memory.FillRAM [0x420d] & 1)) + { + if (byte & 1) { - if (Byte & 1) - { - CPU.FastROMSpeed = ONE_CYCLE; - #ifdef DEBUGGER - missing.fast_rom = 1; - #endif - } - else - CPU.FastROMSpeed = SLOW_ONE_CYCLE; - - Memory.FixROMSpeed(); + CPU.FastROMSpeed = ONE_CYCLE; +#ifdef DEBUGGER + missing.fast_rom = 1; +#endif } + else CPU.FastROMSpeed = SLOW_ONE_CYCLE; + Memory.FixROMSpeed (); + } + break; + + case 0x420e: + case 0x420f: + // --->>> Unknown + break; + case 0x4210: + // NMI ocurred flag (reset on read or write) + Memory.FillRAM[0x4210] = Model->_5A22; + return; + case 0x4211: + // IRQ ocurred flag (reset on read or write) + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + break; + case 0x4212: + // v-blank, h-blank and joypad being scanned flags (read-only) + case 0x4213: + // I/O Port (read-only) + case 0x4214: + case 0x4215: + // Quotent of divide (read-only) + case 0x4216: + case 0x4217: + // Multiply product (read-only) + return; + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + // Joypad values (read-only) + return; + + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + DMA[d].ReverseTransfer = (byte&0x80)?1:0; + DMA[d].HDMAIndirectAddressing = (byte&0x40)?1:0; + DMA[d].UnusedBit43x0 = (byte&0x20)?1:0; + DMA[d].AAddressDecrement = (byte&0x10)?1:0; + DMA[d].AAddressFixed = (byte&0x08)?1:0; + DMA[d].TransferMode = (byte & 7); + return; + + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + if(CPU.InDMAorHDMA) return; + DMA[((Address >> 4) & 0x7)].BAddress = byte; + return; + + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF00; + DMA[d].AAddress |= byte; + return; + + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF; + DMA[d].AAddress |= byte << 8; + return; + + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + if(CPU.InDMAorHDMA) return; + DMA[d=((Address >> 4) & 0x7)].ABank = byte; + HDMAMemPointers[d]=NULL; + return; + + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00; + DMA[d].DMACount_Or_HDMAIndirectAddress |= byte; + HDMAMemPointers[d]=NULL; + return; + + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff; + DMA[d].DMACount_Or_HDMAIndirectAddress |= byte << 8; + HDMAMemPointers[d]=NULL; + return; + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + if(CPU.InDMAorHDMA) return; + DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; + HDMAMemPointers[d]=NULL; + return; + + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 7; + DMA[d].Address &= 0xff00; + DMA[d].Address |= byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + DMA[d].Address &= 0xff; + DMA[d].Address |= byte << 8; + HDMAMemPointers[d] = NULL; + return; + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + if(CPU.InDMAorHDMA) return; + d = (Address >> 4) & 0x7; + if(byte&0x7f){ + DMA[d].LineCount = byte & 0x7f; + DMA[d].Repeat = !(byte & 0x80); + } else { + DMA[d].LineCount = 128; + DMA[d].Repeat = !!(byte & 0x80); + } + //printf("$%02x is written to $43%da at HC:%d, V:%d, PPU.HDMA:$%02x, PPU.HDMAEnded:$%02x\n", byte, d, CPU.Cycles, CPU.V_Counter, PPU.HDMA, PPU.HDMAEnded); + return; + + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + if(CPU.InDMAorHDMA) return; + DMA[((Address >> 4) & 0x7)].UnknownByte = byte; + return; + + //These registers are used by both the S-DD1 and the SPC7110 + case 0x4800: + case 0x4801: + case 0x4802: + case 0x4803: + if(Settings.SPC7110) + S9xSetSPC7110(byte, Address); + //printf ("%02x->%04x\n", byte, Address); + break; + + case 0x4804: + case 0x4805: + case 0x4806: + case 0x4807: + //printf ("%02x->%04x\n", byte, Address); + if(Settings.SPC7110) + S9xSetSPC7110(byte, Address); + else S9xSetSDD1MemoryMap (Address - 0x4804, byte & 7); + break; + + //these are used by the SPC7110 + case 0x4808: + case 0x4809: + case 0x480A: + case 0x480B: + case 0x480C: + case 0x4810: + case 0x4811: + case 0x4812: + case 0x4813: + case 0x4814: + case 0x4815: + case 0x4816: + case 0x4817: + case 0x4818: + case 0x481A: + case 0x4820: + case 0x4821: + case 0x4822: + case 0x4823: + case 0x4824: + case 0x4825: + case 0x4826: + case 0x4827: + case 0x4828: + case 0x4829: + case 0x482A: + case 0x482B: + case 0x482C: + case 0x482D: + case 0x482E: + case 0x482F: + case 0x4830: + case 0x4831: + case 0x4832: + case 0x4833: + case 0x4834: + case 0x4840: + case 0x4841: + case 0x4842: + if(Settings.SPC7110) + { + S9xSetSPC7110(byte, Address); break; + } - case 0x4210: // RDNMI - #if 0 - Memory.FillRAM[0x4210] = Model->_5A22; - #endif - return; - - case 0x4211: // TIMEUP - #if 0 - S9xClearIRQ(PPU_IRQ_SOURCE); - #endif - return; - - case 0x4212: // HVBJOY - case 0x4213: // RDIO - case 0x4214: // RDDIVL - case 0x4215: // RDDIVH - case 0x4216: // RDMPYL - case 0x4217: // RDMPYH - case 0x4218: // JOY1L - case 0x4219: // JOY1H - case 0x421a: // JOY2L - case 0x421b: // JOY2H - case 0x421c: // JOY3L - case 0x421d: // JOY3H - case 0x421e: // JOY4L - case 0x421f: // JOY4H - return; - - default: - if (Settings.SPC7110 && Address >= 0x4800) - S9xSetSPC7110(Byte, Address); - else - if (Settings.SDD1 && Address >= 0x4804 && Address <= 0x4807) - S9xSetSDD1MemoryMap(Address - 0x4804, Byte & 7); - break; + default: +#ifdef DEBUGGER + missing.unknowncpu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register write: $%02X->$%04X\n", + byte, Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; } - } - - Memory.FillRAM[Address] = Byte; + Memory.FillRAM [Address] = byte; } +/******************************************************************************/ +/* S9xGetCPU() */ +/* This function retrieves a CPU/DMA Register */ +/******************************************************************************/ uint8 S9xGetCPU (uint16 Address) { - if (Address < 0x4200) + int d; + uint8 byte; +// fprintf(stderr, "read from %04x\n", Address); + + if (Address < 0x4200) { - #ifdef SNES_JOY_READ_CALLBACKS - extern bool8 pad_read; - if (Address == 0x4016 || Address == 0x4017) + if(Address==0x4016 || Address==0x4017) { + extern bool8 pad_read; +#ifdef SNES_JOY_READ_CALLBACKS S9xOnSNESPadRead(); - pad_read = TRUE; +#endif + pad_read = true; } - #endif - - CPU.Cycles += ONE_CYCLE; // XSlow + CPU.Cycles += ONE_CYCLE; switch (Address) { - case 0x4016: // JOYSER0 - case 0x4017: // JOYSER1 - return (S9xReadJOYSERn(Address)); + case 0x4016: + case 0x4017: + return S9xReadJOYSERn(Address); + default: +#ifdef DEBUGGER + missing.unknowncpu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register read: $%04X\n", Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + return OpenBus; - default: - return (OpenBus); } +// return (Memory.FillRAM [Address]); } - else - if ((Address & 0xff80) == 0x4300) - { - if (CPU.InDMAorHDMA) - return (OpenBus); + else + switch (Address) + { + case 0x4200: + case 0x4201: + case 0x4202: + case 0x4203: + case 0x4204: + case 0x4205: + case 0x4206: + case 0x4207: + case 0x4208: + case 0x4209: + case 0x420a: + case 0x420b: + case 0x420c: + case 0x420d: + case 0x420e: + case 0x420f: + return OpenBus; - int d = (Address >> 4) & 0x7; + case 0x4210: +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; +#endif + byte = Memory.FillRAM[0x4210]; + Memory.FillRAM[0x4210] = Model->_5A22; + //SNEeSe returns 2 for 5A22 version. + return ((byte&0x80)|(OpenBus&0x70)|Model->_5A22); - switch (Address & 0xf) + case 0x4211: + byte = (CPU.IRQActive & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) ? 0x80 : 0; +// // Super Robot Wars Ex ROM bug requires this. +// Let's try without, now that we have Open Bus emulation? +// byte |= CPU.Cycles >= Timings.HBlankStart ? 0x40 : 0; + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + byte |= OpenBus&0x7f; + + return (byte); + + case 0x4212: + // V-blank, h-blank and joypads being read flags (read-only) +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; +#endif + return (REGISTER_4212()|(OpenBus&0x3E)); + + case 0x4213: + // I/O port input - returns 0 wherever $4201 is 0, and 1 elsewhere + // unless something else pulls it down (i.e. a gun) + return Memory.FillRAM[0x4213]; + + case 0x4214: + case 0x4215: + // Quotient of divide result + case 0x4216: + case 0x4217: + // Multiplcation result (for multiply) or remainder of + // divison. + return (Memory.FillRAM[Address]); + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + if(Memory.FillRAM[0x4200] & 1) { - case 0x0: // 0x43x0: DMAPx - return ((DMA[d].ReverseTransfer ? 0x80 : 0) | - (DMA[d].HDMAIndirectAddressing ? 0x40 : 0) | - (DMA[d].UnusedBit43x0 ? 0x20 : 0) | - (DMA[d].AAddressDecrement ? 0x10 : 0) | - (DMA[d].AAddressFixed ? 0x08 : 0) | - (DMA[d].TransferMode & 7)); - - case 0x1: // 0x43x1: BBADx - return (DMA[d].BAddress); - - case 0x2: // 0x43x2: A1TxL - return (DMA[d].AAddress & 0xff); - - case 0x3: // 0x43x3: A1TxH - return (DMA[d].AAddress >> 8); - - case 0x4: // 0x43x4: A1Bx - return (DMA[d].ABank); - - case 0x5: // 0x43x5: DASxL - return (DMA[d].DMACount_Or_HDMAIndirectAddress & 0xff); - - case 0x6: // 0x43x6: DASxH - return (DMA[d].DMACount_Or_HDMAIndirectAddress >> 8); - - case 0x7: // 0x43x7: DASBx - return (DMA[d].IndirectBank); - - case 0x8: // 0x43x8: A2AxL - return (DMA[d].Address & 0xff); - - case 0x9: // 0x43x9: A2AxH - return (DMA[d].Address >> 8); - - case 0xa: // 0x43xa: NLTRx - return (DMA[d].LineCount ^ (DMA[d].Repeat ? 0x00 : 0x80)); - - case 0xb: // 0x43xb: ????x - case 0xf: // 0x43xf: mirror of 0x43xb - return (DMA[d].UnknownByte); - - default: - return (OpenBus); + extern bool8 pad_read; +#ifdef SNES_JOY_READ_CALLBACKS + S9xOnSNESPadRead(); +#endif + pad_read = true; } - } - else + // Joypads 1-4 button and direction state. + return (Memory.FillRAM [Address]); + + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + if(CPU.InDMAorHDMA) return OpenBus; + d = (Address >> 4) & 0x7; + return ((DMA[d].ReverseTransfer?0x80:0x00) | + (DMA[d].HDMAIndirectAddressing?0x40:0x00) | + (DMA[d].UnusedBit43x0?0x20:0x00) | + (DMA[d].AAddressDecrement?0x10:0x00) | + (DMA[d].AAddressFixed?0x08:0x00) | + (DMA[d].TransferMode & 7)); + + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + if(CPU.InDMAorHDMA) return OpenBus; + return DMA[((Address >> 4) & 0x7)].BAddress; + + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + if(CPU.InDMAorHDMA) return OpenBus; + return (DMA[((Address >> 4) & 0x7)].AAddress & 0xFF); + + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + if(CPU.InDMAorHDMA) return OpenBus; + return (DMA[((Address >> 4) & 0x7)].AAddress >> 8); + + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + if(CPU.InDMAorHDMA) return OpenBus; + return DMA[((Address >> 4) & 0x7)].ABank; + + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + if(CPU.InDMAorHDMA) return OpenBus; + return (DMA[((Address >> 4) & 0x7)].DMACount_Or_HDMAIndirectAddress & 0xff); + + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + if(CPU.InDMAorHDMA) return OpenBus; + return (DMA[((Address >> 4) & 0x7)].DMACount_Or_HDMAIndirectAddress >> 8); + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + if(CPU.InDMAorHDMA) return OpenBus; + return DMA[((Address >> 4) & 0x7)].IndirectBank; + + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + if(CPU.InDMAorHDMA) return OpenBus; + return (DMA[((Address >> 4) & 0x7)].Address & 0xFF); + + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + if(CPU.InDMAorHDMA) return OpenBus; + return (DMA[((Address >> 4) & 0x7)].Address >> 8); + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + if(CPU.InDMAorHDMA) return OpenBus; + d = (Address >> 4) & 0x7; + return (DMA[d].LineCount ^ (DMA[d].Repeat?0x00:0x80)); + + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + if(CPU.InDMAorHDMA) return OpenBus; + return DMA[((Address >> 4) & 0x7)].UnknownByte; + + default: +#ifdef DEBUGGER + missing.unknowncpu_read = Address; + if (Settings.TraceUnknownRegisters) { - uint8 byte; - - switch (Address) - { - case 0x4210: // RDNMI - #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif - byte = Memory.FillRAM[0x4210]; - Memory.FillRAM[0x4210] = Model->_5A22; - return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22); - - case 0x4211: // TIMEUP - byte = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0; - S9xClearIRQ(PPU_IRQ_SOURCE); - return (byte | (OpenBus & 0x7f)); - - case 0x4212: // HVBJOY - #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif - return (REGISTER_4212() | (OpenBus & 0x3e)); - - case 0x4213: // RDIO - return (Memory.FillRAM[0x4213]); - - case 0x4214: // RDDIVL - case 0x4215: // RDDIVH - case 0x4216: // RDMPYL - case 0x4217: // RDMPYH - return (Memory.FillRAM[Address]); - - case 0x4218: // JOY1L - case 0x4219: // JOY1H - case 0x421a: // JOY2L - case 0x421b: // JOY2H - case 0x421c: // JOY3L - case 0x421d: // JOY3H - case 0x421e: // JOY4L - case 0x421f: // JOY4H - #ifdef SNES_JOY_READ_CALLBACKS - extern bool8 pad_read; - if (Memory.FillRAM[0x4200] & 1) - { - S9xOnSNESPadRead(); - pad_read = TRUE; - } - #endif - return (Memory.FillRAM[Address]); - - default: - if (Settings.SPC7110 && Address >= 0x4800) - return (S9xGetSPC7110(Address)); - if (Settings.SDD1 && Address >= 0x4800 && Address <= 0x4807) - return (Memory.FillRAM[Address]); - return (OpenBus); - } + sprintf (String, "Unknown register read: $%04X\n", Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); } + +#endif + + if(Address>= 0x4800&&Settings.SPC7110) + return S9xGetSPC7110(Address); + + if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) + { + return Memory.FillRAM[Address]; + } + + return OpenBus; + } } -void S9xResetPPU (void) +void S9xResetPPU () { - S9xSoftResetPPU(); - S9xControlsReset(); + S9xSoftResetPPU(); + S9xControlsReset(); + IPPU.PreviousLine = IPPU.CurrentLine = 0; PPU.M7HOFS = 0; PPU.M7VOFS = 0; PPU.M7byte = 0; } -void S9xSoftResetPPU (void) +void S9xSoftResetPPU () { - S9xControlsSoftReset(); - + S9xControlsSoftReset(); + PPU.BGMode = 0; + PPU.BG3Priority = 0; + PPU.Brightness = 0; PPU.VMA.High = 0; PPU.VMA.Increment = 1; PPU.VMA.Address = 0; PPU.VMA.FullGraphicCount = 0; PPU.VMA.Shift = 0; - PPU.WRAM = 0; - - for (int c = 0; c < 4; c++) + for (uint8 B = 0; B != 4; B++) { - PPU.BG[c].SCBase = 0; - PPU.BG[c].HOffset = 0; - PPU.BG[c].VOffset = 0; - PPU.BG[c].BGSize = 0; - PPU.BG[c].NameBase = 0; - PPU.BG[c].SCSize = 0; + PPU.BG[B].SCBase = 0; + PPU.BG[B].VOffset = 0; + PPU.BG[B].HOffset = 0; + PPU.BG[B].BGSize = 0; + PPU.BG[B].NameBase = 0; + PPU.BG[B].SCSize = 0; + + PPU.ClipCounts[B] = 0; + PPU.ClipWindowOverlapLogic [B] = CLIP_OR; + PPU.ClipWindow1Enable[B] = FALSE; + PPU.ClipWindow2Enable[B] = FALSE; + PPU.ClipWindow1Inside[B] = TRUE; + PPU.ClipWindow2Inside[B] = TRUE; } - PPU.BGMode = 0; - PPU.BG3Priority = 0; + PPU.ClipCounts[4] = 0; + PPU.ClipCounts[5] = 0; + PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; + PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; + PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; + PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; + PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; PPU.CGFLIP = 0; - PPU.CGFLIPRead = 0; - PPU.CGADD = 0; - - for (int c = 0; c < 256; c++) + int c; + for (c = 0; c < 256; c++) { - IPPU.Red[c] = (c & 7) << 2; - IPPU.Green[c] = ((c >> 3) & 7) << 2; - IPPU.Blue[c] = ((c >> 6) & 2) << 3; - PPU.CGDATA[c] = IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10); + IPPU.Red [c] = (c & 7) << 2; + IPPU.Green [c] = ((c >> 3) & 7) << 2; + IPPU.Blue [c] = ((c >> 6) & 2) << 3; + PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | + (IPPU.Blue [c] << 10); } - for (int c = 0; c < 128; c++) - { - PPU.OBJ[c].HPos = 0; - PPU.OBJ[c].VPos = 0; - PPU.OBJ[c].HFlip = 0; - PPU.OBJ[c].VFlip = 0; - PPU.OBJ[c].Name = 0; - PPU.OBJ[c].Priority = 0; - PPU.OBJ[c].Palette = 0; - PPU.OBJ[c].Size = 0; - } - - PPU.OBJThroughMain = FALSE; - PPU.OBJThroughSub = FALSE; - PPU.OBJAddition = FALSE; - PPU.OBJNameBase = 0; - PPU.OBJNameSelect = 0; - PPU.OBJSizeSelect = 0; - - PPU.OAMAddr = 0; - PPU.SavedOAMAddr = 0; - PPU.OAMPriorityRotation = 0; - PPU.OAMFlip = 0; - PPU.OAMReadFlip = 0; - PPU.OAMTileAddress = 0; - PPU.OAMWriteRegister = 0; - ZeroMemory(PPU.OAMData, 512 + 32); - PPU.FirstSprite = 0; PPU.LastSprite = 127; + for (int Sprite = 0; Sprite < 128; Sprite++) + { + PPU.OBJ[Sprite].HPos = 0; + PPU.OBJ[Sprite].VPos = 0; + PPU.OBJ[Sprite].VFlip = 0; + PPU.OBJ[Sprite].HFlip = 0; + PPU.OBJ[Sprite].Priority = 0; + PPU.OBJ[Sprite].Palette = 0; + PPU.OBJ[Sprite].Name = 0; + PPU.OBJ[Sprite].Size = 0; + } + PPU.OAMPriorityRotation = 0; + PPU.OAMWriteRegister = 0; PPU.RangeTimeOver = 0; + PPU.OpenBus1 = 0; + PPU.OpenBus2 = 0; - PPU.HTimerEnabled = FALSE; - PPU.VTimerEnabled = FALSE; - PPU.HTimerPosition = Timings.H_Max + 1; - PPU.VTimerPosition = Timings.V_Max + 1; - PPU.IRQHBeamPos = 0x1ff; + PPU.OAMFlip = 0; + PPU.OAMTileAddress = 0; + PPU.OAMAddr = 0; PPU.IRQVBeamPos = 0x1ff; + PPU.IRQHBeamPos = 0x1ff; + PPU.VBeamPosLatched = 0; + PPU.HBeamPosLatched = 0; PPU.HBeamFlip = 0; PPU.VBeamFlip = 0; - PPU.HBeamPosLatched = 0; - PPU.VBeamPosLatched = 0; - PPU.GunHLatch = 0; - PPU.GunVLatch = 1000; PPU.HVBeamCounterLatched = 0; + PPU.GunVLatch=1000; + PPU.GunHLatch=0; + PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; + PPU.CentreX = PPU.CentreY = 0; + PPU.CGADD = 0; + PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; + PPU.SavedOAMAddr = 0; + PPU.ScreenHeight = SNES_HEIGHT; + PPU.WRAM = 0; + PPU.ForcedBlanking = TRUE; + PPU.OBJThroughMain = FALSE; + PPU.OBJThroughSub = FALSE; + PPU.OBJSizeSelect = 0; + PPU.OBJNameSelect = 0; + PPU.OBJNameBase = 0; + PPU.OBJAddition = FALSE; + PPU.OAMReadFlip = 0; + PPU.BGnxOFSbyte = 0; + ZeroMemory (PPU.OAMData, 512 + 32); + + PPU.VTimerEnabled = FALSE; + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Timings.H_Max + 1; + PPU.VTimerPosition = Timings.V_Max + 1; + PPU.Mosaic = 0; + PPU.BGMosaic [0] = PPU.BGMosaic [1] = FALSE; + PPU.BGMosaic [2] = PPU.BGMosaic [3] = FALSE; PPU.Mode7HFlip = FALSE; PPU.Mode7VFlip = FALSE; PPU.Mode7Repeat = 0; - PPU.MatrixA = 0; - PPU.MatrixB = 0; - PPU.MatrixC = 0; - PPU.MatrixD = 0; - PPU.CentreX = 0; - PPU.CentreY = 0; - - PPU.Mosaic = 0; - PPU.BGMosaic[0] = FALSE; - PPU.BGMosaic[1] = FALSE; - PPU.BGMosaic[2] = FALSE; - PPU.BGMosaic[3] = FALSE; - PPU.Window1Left = 1; PPU.Window1Right = 0; PPU.Window2Left = 1; PPU.Window2Right = 0; PPU.RecomputeClipWindows = TRUE; - - for (int c = 0; c < 6; c++) - { - PPU.ClipCounts[c] = 0; - PPU.ClipWindowOverlapLogic[c] = CLIP_OR; - PPU.ClipWindow1Enable[c] = FALSE; - PPU.ClipWindow2Enable[c] = FALSE; - PPU.ClipWindow1Inside[c] = TRUE; - PPU.ClipWindow2Inside[c] = TRUE; - } - - PPU.ForcedBlanking = TRUE; - - PPU.FixedColourRed = 0; - PPU.FixedColourGreen = 0; - PPU.FixedColourBlue = 0; - PPU.Brightness = 0; - PPU.ScreenHeight = SNES_HEIGHT; - + PPU.CGFLIPRead = 0; PPU.Need16x8Mulitply = FALSE; - PPU.BGnxOFSbyte = 0; + IPPU.ColorsChanged = TRUE; PPU.HDMA = 0; PPU.HDMAEnded = 0; - - PPU.OpenBus1 = 0; - PPU.OpenBus2 = 0; - - for (int c = 0; c < 2; c++) - memset(&IPPU.Clip[c], 0, sizeof(struct ClipData)); - IPPU.ColorsChanged = TRUE; + IPPU.MaxBrightness = 0; + IPPU.LatchedBlanking = 0; IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; IPPU.DirectColourMapsNeedRebuild = TRUE; - ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; + ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_2BIT_EVEN], MAX_2BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_2BIT_ODD], MAX_2BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_4BIT_EVEN], MAX_4BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_4BIT_ODD], MAX_4BIT_TILES); #ifdef CORRECT_VRAM_READS IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? #else @@ -2188,30 +2856,197 @@ void S9xSoftResetPPU (void) IPPU.InterlaceOBJ = FALSE; IPPU.DoubleWidthPixels = FALSE; IPPU.DoubleHeightPixels = FALSE; - IPPU.CurrentLine = 0; - IPPU.PreviousLine = 0; - IPPU.XB = NULL; - for (int c = 0; c < 256; c++) - IPPU.ScreenColors[c] = c; - IPPU.MaxBrightness = 0; - IPPU.RenderThisFrame = TRUE; IPPU.RenderedScreenWidth = SNES_WIDTH; IPPU.RenderedScreenHeight = SNES_HEIGHT; - IPPU.FrameCount = 0; - IPPU.RenderedFramesCount = 0; - IPPU.DisplayedRenderedFrameCount = 0; - IPPU.SkippedFrames = 0; - IPPU.FrameSkip = 0; + IPPU.XB = NULL; + for (c = 0; c < 256; c++) + IPPU.ScreenColors [c] = c; + S9xFixColourBrightness (); + IPPU.PreviousLine = IPPU.CurrentLine = 0; - S9xFixColourBrightness(); + for (c = 0; c < 2; c++) + memset (&IPPU.Clip [c], 0, sizeof (struct ClipData)); - for (int c = 0; c < 0x8000; c += 0x100) - memset(&Memory.FillRAM[c], c >> 8, 0x100); - ZeroMemory(&Memory.FillRAM[0x2100], 0x100); - ZeroMemory(&Memory.FillRAM[0x4200], 0x100); - ZeroMemory(&Memory.FillRAM[0x4000], 0x100); + for (c = 0; c < 0x8000; c += 0x100) + memset (&Memory.FillRAM [c], c >> 8, 0x100); + + ZeroMemory (&Memory.FillRAM [0x2100], 0x100); + ZeroMemory (&Memory.FillRAM [0x4200], 0x100); + ZeroMemory (&Memory.FillRAM [0x4000], 0x100); // For BS Suttehakkun 2... - ZeroMemory(&Memory.FillRAM[0x1000], 0x1000); + ZeroMemory (&Memory.FillRAM [0x1000], 0x1000); - Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff; + Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; } + +#ifndef ZSNES_FX +void S9xSuperFXExec () +{ +#if 1 + if (Settings.SuperFX) + { + if ((Memory.FillRAM [0x3000 + GSU_SFR] & FLG_G) && + (Memory.FillRAM [0x3000 + GSU_SCMR] & 0x18) == 0x18) + { + FxEmulate ((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine); + int GSUStatus = Memory.FillRAM [0x3000 + GSU_SFR] | + (Memory.FillRAM [0x3000 + GSU_SFR + 1] << 8); + if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) + { + // Trigger a GSU IRQ. + S9xSetIRQ (GSU_IRQ_SOURCE); + } + } + } +#else + uint32 tmp = (Memory.FillRAM[0x3034] << 16) + *(uint16 *) &Memory.FillRAM [0x301e]; + +#if 0 + if (tmp == 0x018428) + { + *(uint16 *) &SRAM [0x0064] = 0xbc00; + *(uint16 *) &SRAM [0x002c] = 0x8000; + } +#endif + if (tmp == -1)//0x018428) //0x01bfc3) //0x09edaf) //-1) //0x57edaf) + { + while (Memory.FillRAM [0x3030] & 0x20) + { + int i; + int32 vError; + uint8 avReg[0x40]; + char tmp[128]; + uint8 vPipe; + uint8 vColr; + uint8 vPor; + + FxPipeString (tmp); + /* Make the string 32 chars long */ + if(strlen(tmp) < 32) { memset(&tmp[strlen(tmp)],' ',32-strlen(tmp)); tmp[32] = 0; } + + /* Copy registers (so we can see if any changed) */ + vColr = FxGetColorRegister(); + vPor = FxGetPlotOptionRegister(); + memcpy(avReg,SuperFX.pvRegisters,0x40); + + /* Print the pipe string */ + //printf(tmp); + + /* Execute the instruction in the pipe */ + vPipe = FxPipe(); + vError = FxEmulate(1); + + /* Check if any registers changed (and print them if they did) */ + for(i=0; i<16; i++) + { + uint32 a = 0; + uint32 r1 = ((uint32)avReg[i*2]) | (((uint32)avReg[(i*2)+1])<<8); + uint32 r2 = (uint32)(SuperFX.pvRegisters[i*2]) | (((uint32)SuperFX.pvRegisters[(i*2)+1])<<8); + if(i==15) + a = OPCODE_BYTES(vPipe); + //if(((r1+a)&0xffff) != r2) + // printf(" r%d=$%04x",i,r2); + } + { + /* Check SFR */ + uint32 r1 = ((uint32)avReg[0x30]) | (((uint32)avReg[0x31])<<8); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x30]) | (((uint32)SuperFX.pvRegisters[0x31])<<8); + /*if((r1&(1<<1)) != (r2&(1<<1))) + printf(" Z=%d",(uint32)(!!(r2&(1<<1)))); + if((r1&(1<<2)) != (r2&(1<<2))) + printf(" CY=%d",(uint32)(!!(r2&(1<<2)))); + if((r1&(1<<3)) != (r2&(1<<3))) + printf(" S=%d",(uint32)(!!(r2&(1<<3)))); + if((r1&(1<<4)) != (r2&(1<<4))) + printf(" OV=%d",(uint32)(!!(r2&(1<<4)))); + if((r1&(1<<5)) != (r2&(1<<5))) + printf(" G=%d",(uint32)(!!(r2&(1<<5)))); + if((r1&(1<<6)) != (r2&(1<<6))) + printf(" R=%d",(uint32)(!!(r2&(1<<6)))); + if((r1&(1<<8)) != (r2&(1<<8))) + printf(" ALT1=%d",(uint32)(!!(r2&(1<<8)))); + if((r1&(1<<9)) != (r2&(1<<9))) + printf(" ALT2=%d",(uint32)(!!(r2&(1<<9)))); + if((r1&(1<<10)) != (r2&(1<<10))) + printf(" IL=%d",(uint32)(!!(r2&(1<<10)))); + if((r1&(1<<11)) != (r2&(1<<11))) + printf(" IH=%d",(uint32)(!!(r2&(1<<11)))); + if((r1&(1<<12)) != (r2&(1<<12))) + printf(" B=%d",(uint32)(!!(r2&(1<<12)))); + if((r1&(1<<15)) != (r2&(1<<15))) + printf(" IRQ=%d",(uint32)(!!(r2&(1<<15))));*/ + } + { + /* Check PBR */ + uint32 r1 = ((uint32)avReg[0x34]); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x34]); + //if(r1 != r2) + // printf(" PBR=$%02x",r2); + } + { + /* Check ROMBR */ + uint32 r1 = ((uint32)avReg[0x36]); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x36]); + //if(r1 != r2) + // printf(" ROMBR=$%02x",r2); + } + { + /* Check RAMBR */ + uint32 r1 = ((uint32)avReg[0x3c]); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x3c]); + //if(r1 != r2) + // printf(" RAMBR=$%02x",r2); + } + { + /* Check CBR */ + uint32 r1 = ((uint32)avReg[0x3e]) | (((uint32)avReg[0x3f])<<8); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x3e]) | (((uint32)SuperFX.pvRegisters[0x3f])<<8); + //if(r1 != r2) + // printf(" CBR=$%04x",r2); + } + { + /* Check COLR */ + //if(vColr != FxGetColorRegister()) + // printf(" COLR=$%02x",FxGetColorRegister()); + } + { + /* Check POR */ + //if(vPor != FxGetPlotOptionRegister()) + // printf(" POR=$%02x",FxGetPlotOptionRegister()); + } + //printf ("\n"); + } + S9xExit (); + } + else + { + uint32 t = (Memory.FillRAM [0x3034] << 16) + + (Memory.FillRAM [0x301f] << 8) + + (Memory.FillRAM [0x301e] << 0); + +//printf ("%06x: %d\n", t, FxEmulate (2000000)); +// FxEmulate (2000000); + } +#if 0 + if (!(CPU.Flags & TRACE_FLAG)) + { + static int z = 1; + if (z == 0) + { + extern FILE *trace; + CPU.Flags |= TRACE_FLAG; + trace = fopen ("trace.log", "wb"); + } + else + z--; + } +#endif + Memory.FillRAM [0x3030] &= ~0x20; + if (Memory.FillRAM [0x3031] & 0x80) + { + S9xSetIRQ (GSU_IRQ_SOURCE); + } +#endif +} +#endif + diff --git a/source/snes9x/ppu.h b/source/snes9x/ppu.h index 02c0e89..35b6d45 100644 --- a/source/snes9x/ppu.h +++ b/source/snes9x/ppu.h @@ -159,578 +159,630 @@ **********************************************************************************/ + + #ifndef _PPU_H_ #define _PPU_H_ -#define FIRST_VISIBLE_LINE 1 +#define FIRST_VISIBLE_LINE 1 -#define TILE_2BIT 0 -#define TILE_4BIT 1 -#define TILE_8BIT 2 -#define TILE_2BIT_EVEN 3 -#define TILE_2BIT_ODD 4 -#define TILE_4BIT_EVEN 5 -#define TILE_4BIT_ODD 6 +extern uint8 GetBank; +extern uint16 SignExtend [2]; -#define MAX_2BIT_TILES 4096 -#define MAX_4BIT_TILES 2048 -#define MAX_8BIT_TILES 1024 +#define TILE_2BIT 0 +#define TILE_4BIT 1 +#define TILE_8BIT 2 +#define TILE_2BIT_EVEN 3 +#define TILE_2BIT_ODD 4 +#define TILE_4BIT_EVEN 5 +#define TILE_4BIT_ODD 6 -#define CLIP_OR 0 -#define CLIP_AND 1 -#define CLIP_XOR 2 -#define CLIP_XNOR 3 +#define MAX_2BIT_TILES 4096 +#define MAX_4BIT_TILES 2048 +#define MAX_8BIT_TILES 1024 -#define PPU_IRQ_SOURCE (1 << 1) +#define PPU_H_BEAM_IRQ_SOURCE (1 << 0) +#define PPU_V_BEAM_IRQ_SOURCE (1 << 1) #define GSU_IRQ_SOURCE (1 << 2) #define SA1_IRQ_SOURCE (1 << 7) #define SA1_DMA_IRQ_SOURCE (1 << 5) -struct ClipData -{ - uint8 Count; - uint8 DrawMode[6]; - uint16 Left[6]; - uint16 Right[6]; +struct ClipData { + uint8 Count; + uint8 DrawMode[6]; + uint16 Left[6]; + uint16 Right[6]; }; -struct InternalPPU -{ - struct ClipData Clip[2][6]; - bool8 ColorsChanged; - bool8 OBJChanged; - bool8 DirectColourMapsNeedRebuild; - uint8 *TileCache[7]; - uint8 *TileCached[7]; +struct InternalPPU { + bool8 ColorsChanged; + uint8 MaxBrightness; + bool8 LatchedBlanking; + bool8 OBJChanged; + bool8 RenderThisFrame; + bool8 DirectColourMapsNeedRebuild; + uint32 FrameCount; + uint32 RenderedFramesCount; + uint32 DisplayedRenderedFrameCount; + uint32 TotalEmulatedFrames; + uint32 SkippedFrames; + uint32 FrameSkip; + uint8 *TileCache [7]; + uint8 *TileCached [7]; #ifdef CORRECT_VRAM_READS - uint16 VRAMReadBuffer; + uint16 VRAMReadBuffer; #else - bool8 FirstVRAMRead; + bool8 FirstVRAMRead; #endif - bool8 Interlace; - bool8 InterlaceOBJ; - bool8 PseudoHires; - bool8 DoubleWidthPixels; - bool8 DoubleHeightPixels; - int CurrentLine; - int PreviousLine; - uint8 *XB; - uint32 Red[256]; - uint32 Green[256]; - uint32 Blue[256]; - uint16 ScreenColors[256]; - uint8 MaxBrightness; - bool8 RenderThisFrame; - int RenderedScreenWidth; - int RenderedScreenHeight; - uint32 FrameCount; - uint32 RenderedFramesCount; - uint32 DisplayedRenderedFrameCount; - uint32 TotalEmulatedFrames; - uint32 SkippedFrames; - uint32 FrameSkip; + bool8 Interlace; + bool8 InterlaceOBJ; + bool8 PseudoHires; + bool8 DoubleWidthPixels; + bool8 DoubleHeightPixels; + int RenderedScreenHeight; + int RenderedScreenWidth; + uint32 Red [256]; + uint32 Green [256]; + uint32 Blue [256]; + uint8 *XB; + uint16 ScreenColors [256]; + int PreviousLine; + int CurrentLine; + struct ClipData Clip[2][6]; }; struct SOBJ { - int16 HPos; - uint16 VPos; - uint8 HFlip; - uint8 VFlip; - uint16 Name; - uint8 Priority; - uint8 Palette; - uint8 Size; + int16 HPos; + uint16 VPos; + uint16 Name; + uint8 VFlip; + uint8 HFlip; + uint8 Priority; + uint8 Palette; + uint8 Size; }; -struct SPPU -{ - struct - { - bool8 High; - uint8 Increment; - uint16 Address; - uint16 Mask1; - uint16 FullGraphicCount; - uint16 Shift; - } VMA; +struct SPPU { + uint8 BGMode; + uint8 BG3Priority; + uint8 Brightness; - uint32 WRAM; + struct { + bool8 High; + uint8 Increment; + uint16 Address; + uint16 Mask1; + uint16 FullGraphicCount; + uint16 Shift; + } VMA; - struct - { - uint16 SCBase; - uint16 HOffset; - uint16 VOffset; - uint8 BGSize; - uint16 NameBase; - uint16 SCSize; - } BG[4]; + struct { + uint16 SCBase; + uint16 VOffset; + uint16 HOffset; + uint8 BGSize; + uint16 NameBase; + uint16 SCSize; + } BG [4]; - uint8 BGMode; - uint8 BG3Priority; + bool8 CGFLIP; + uint16 CGDATA [256]; + uint8 FirstSprite; + uint8 LastSprite; + struct SOBJ OBJ [128]; + uint8 OAMPriorityRotation; + uint16 OAMAddr; + uint8 RangeTimeOver; - bool8 CGFLIP; - uint8 CGFLIPRead; - uint8 CGADD; - uint16 CGDATA[256]; + uint8 OAMFlip; + uint16 OAMTileAddress; + uint16 IRQVBeamPos; + uint16 IRQHBeamPos; + uint16 VBeamPosLatched; + uint16 HBeamPosLatched; - struct SOBJ OBJ[128]; - bool8 OBJThroughMain; - bool8 OBJThroughSub; - bool8 OBJAddition; - uint16 OBJNameBase; - uint16 OBJNameSelect; - uint8 OBJSizeSelect; + uint8 HBeamFlip; + uint8 VBeamFlip; + uint8 HVBeamCounterLatched; - uint16 OAMAddr; - uint16 SavedOAMAddr; - uint8 OAMPriorityRotation; - uint8 OAMFlip; - uint8 OAMReadFlip; - uint16 OAMTileAddress; - uint16 OAMWriteRegister; - uint8 OAMData[512 + 32]; + short MatrixA; + short MatrixB; + short MatrixC; + short MatrixD; + short CentreX; + short CentreY; + short M7HOFS; + short M7VOFS; - uint8 FirstSprite; - uint8 LastSprite; - uint8 RangeTimeOver; + uint8 CGADD; + uint8 FixedColourRed; + uint8 FixedColourGreen; + uint8 FixedColourBlue; + uint16 SavedOAMAddr; + uint16 ScreenHeight; + uint32 WRAM; + bool8 ForcedBlanking; + bool8 OBJThroughMain; + bool8 OBJThroughSub; + uint8 OBJSizeSelect; + uint16 OBJNameBase; + bool8 OBJAddition; + uint8 OAMReadFlip; + uint8 OAMData [512 + 32]; + bool8 VTimerEnabled; + bool8 HTimerEnabled; + short HTimerPosition; + uint8 Mosaic; + uint8 MosaicStart; + bool8 BGMosaic [4]; + bool8 Mode7HFlip; + bool8 Mode7VFlip; + uint8 Mode7Repeat; + uint8 Window1Left; + uint8 Window1Right; + uint8 Window2Left; + uint8 Window2Right; + uint8 ClipCounts [6]; + uint8 ClipWindowOverlapLogic [6]; + uint8 ClipWindow1Enable [6]; + uint8 ClipWindow2Enable [6]; + bool8 ClipWindow1Inside [6]; + bool8 ClipWindow2Inside [6]; + bool8 RecomputeClipWindows; + uint8 CGFLIPRead; + uint16 OBJNameSelect; + bool8 Need16x8Mulitply; - bool8 HTimerEnabled; - bool8 VTimerEnabled; - short HTimerPosition; - short VTimerPosition; - uint16 IRQHBeamPos; - uint16 IRQVBeamPos; + uint16 OAMWriteRegister; + uint8 BGnxOFSbyte; + uint8 M7byte; + uint8 OpenBus1; + uint8 OpenBus2; + uint16 GunVLatch; + uint16 GunHLatch; + short VTimerPosition; - uint8 HBeamFlip; - uint8 VBeamFlip; - uint16 HBeamPosLatched; - uint16 VBeamPosLatched; - uint16 GunHLatch; - uint16 GunVLatch; - uint8 HVBeamCounterLatched; - - bool8 Mode7HFlip; - bool8 Mode7VFlip; - uint8 Mode7Repeat; - short MatrixA; - short MatrixB; - short MatrixC; - short MatrixD; - short CentreX; - short CentreY; - short M7HOFS; - short M7VOFS; - - uint8 Mosaic; - uint8 MosaicStart; - bool8 BGMosaic[4]; - - uint8 Window1Left; - uint8 Window1Right; - uint8 Window2Left; - uint8 Window2Right; - bool8 RecomputeClipWindows; - uint8 ClipCounts[6]; - uint8 ClipWindowOverlapLogic[6]; - uint8 ClipWindow1Enable[6]; - uint8 ClipWindow2Enable[6]; - bool8 ClipWindow1Inside[6]; - bool8 ClipWindow2Inside[6]; - - bool8 ForcedBlanking; - - uint8 FixedColourRed; - uint8 FixedColourGreen; - uint8 FixedColourBlue; - uint8 Brightness; - uint16 ScreenHeight; - - bool8 Need16x8Mulitply; - uint8 BGnxOFSbyte; - uint8 M7byte; - - uint8 HDMA; - uint8 HDMAEnded; - - uint8 OpenBus1; - uint8 OpenBus2; + uint8 HDMA; + uint8 HDMAEnded; }; -extern uint16 SignExtend[2]; -extern struct SPPU PPU; -extern struct InternalPPU IPPU; +#define CLIP_OR 0 +#define CLIP_AND 1 +#define CLIP_XOR 2 +#define CLIP_XNOR 3 + +struct SDMA { + /* $43x0 */ + bool8 ReverseTransfer; + bool8 HDMAIndirectAddressing; + bool8 UnusedBit43x0; + bool8 AAddressFixed; + bool8 AAddressDecrement; + uint8 TransferMode; + + /* $43x1 */ + uint8 BAddress; + + /* $43x2-4 */ + uint16 AAddress; + uint8 ABank; + + /* $43x5-6 */ + uint16 DMACount_Or_HDMAIndirectAddress; + + /* $43x7 */ + uint8 IndirectBank; + + /* $43x8-9 */ + uint16 Address; + + /* $43xA */ + uint8 Repeat; + uint8 LineCount; + + /* $43xB/F */ + uint8 UnknownByte; + + /* internal */ + uint8 DoTransfer; +}; +#define TransferBytes DMACount_Or_HDMAIndirectAddress +#define IndirectAddress DMACount_Or_HDMAIndirectAddress + +START_EXTERN_C +void S9xUpdateScreen (); +void S9xResetPPU (); +void S9xSoftResetPPU (); +void S9xFixColourBrightness (); +void S9xDoAutoJoypad (); +void S9xSuperFXExec (); + +void S9xSetPPU (uint8 Byte, uint16 Address); +uint8 S9xGetPPU (uint16 Address); +void S9xSetCPU (uint8 Byte, uint16 Address); +uint8 S9xGetCPU (uint16 Address); + +void S9xInitC4 (); +void S9xSetC4 (uint8 Byte, uint16 Address); +uint8 S9xGetC4 (uint16 Address); +void S9xSetC4RAM (uint8 Byte, uint16 Address); +uint8 S9xGetC4RAM (uint16 Address); +uint8 * S9xGetBasePointerC4 (uint16); +uint8 * S9xGetMemPointerC4 (uint16); -void S9xResetPPU (void); -void S9xSoftResetPPU (void); -void S9xSetPPU (uint8, uint16); -uint8 S9xGetPPU (uint16); -void S9xSetCPU (uint8, uint16); -uint8 S9xGetCPU (uint16); void S9xUpdateHVTimerPosition (void); void S9xCheckMissingHTimerPosition (int32); void S9xCheckMissingHTimerRange (int32, int32); void S9xCheckMissingHTimerHalt (int32, int32); -void S9xFixColourBrightness (void); -void S9xDoAutoJoypad (void); + +extern struct SPPU PPU; +extern struct SDMA DMA [8]; +extern struct InternalPPU IPPU; +END_EXTERN_C #include "gfx.h" #include "memmap.h" -typedef struct +typedef struct{ + uint8 _5C77; + uint8 _5C78; + uint8 _5A22; +} SnesModel; + +START_EXTERN_C +extern SnesModel* Model; +extern SnesModel M1SNES; +extern SnesModel M2SNES; +END_EXTERN_C + +#define MAX_5C77_VERSION 0x01 +#define MAX_5C78_VERSION 0x03 +#define MAX_5A22_VERSION 0x02 + +STATIC inline uint8 REGISTER_4212() { - uint8 _5C77; - uint8 _5C78; - uint8 _5A22; -} SnesModel; + GetBank = 0; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && + CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) + GetBank = 1; -extern SnesModel *Model; -extern SnesModel M1SNES; -extern SnesModel M2SNES; + GetBank |= ((CPU.Cycles < Timings.HBlankEnd) || (CPU.Cycles >= Timings.HBlankStart)) ? 0x40 : 0; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) + GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */ -#define MAX_5C77_VERSION 0x01 -#define MAX_5C78_VERSION 0x03 -#define MAX_5A22_VERSION 0x02 - -static inline void FLUSH_REDRAW (void) -{ - if (IPPU.PreviousLine != IPPU.CurrentLine) - S9xUpdateScreen(); + return (GetBank); } -static inline void REGISTER_2104 (uint8 Byte) +STATIC inline void FLUSH_REDRAW () { - if (PPU.OAMAddr & 0x100) - { - int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); - if (Byte != PPU.OAMData[addr]) - { - FLUSH_REDRAW(); - PPU.OAMData[addr] = Byte; - IPPU.OBJChanged = TRUE; + if (IPPU.PreviousLine != IPPU.CurrentLine) + S9xUpdateScreen (); +} - // X position high bit, and sprite size (x4) - struct SOBJ *pObj = &PPU.OBJ[(addr & 0x1f) * 4]; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 0) & 1]; - pObj++->Size = Byte & 2; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 2) & 1]; - pObj++->Size = Byte & 8; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 4) & 1]; - pObj++->Size = Byte & 32; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 6) & 1]; - pObj->Size = Byte & 128; - } +STATIC inline void REGISTER_2104 (uint8 byte) +{ + if (PPU.OAMAddr & 0x100) + { + int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); + if (byte != PPU.OAMData [addr]){ + FLUSH_REDRAW (); + PPU.OAMData [addr] = byte; + IPPU.OBJChanged = TRUE; - PPU.OAMFlip ^= 1; - if (!(PPU.OAMFlip & 1)) - { + // X position high bit, and sprite size (x4) + struct SOBJ *pObj = &PPU.OBJ [(addr & 0x1f) * 4]; + + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 0) & 1]; + pObj++->Size = byte & 2; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 2) & 1]; + pObj++->Size = byte & 8; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 4) & 1]; + pObj++->Size = byte & 32; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 6) & 1]; + pObj->Size = byte & 128; + } + PPU.OAMFlip ^= 1; + if(!(PPU.OAMFlip & 1)){ ++PPU.OAMAddr; PPU.OAMAddr &= 0x1ff; if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) { - PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; IPPU.OBJChanged = TRUE; } + } else { + if (PPU.OAMPriorityRotation && (PPU.OAMAddr&1)) IPPU.OBJChanged = TRUE; } - else - { - if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) - IPPU.OBJChanged = TRUE; - } - } - else - if (!(PPU.OAMFlip & 1)) - { - PPU.OAMWriteRegister &= 0xff00; - PPU.OAMWriteRegister |= Byte; - PPU.OAMFlip |= 1; - if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) - IPPU.OBJChanged = TRUE; - } - else - { - PPU.OAMWriteRegister &= 0x00ff; - uint8 lowbyte = (uint8) (PPU.OAMWriteRegister); - uint8 highbyte = Byte; - PPU.OAMWriteRegister |= Byte << 8; + } else if(!(PPU.OAMFlip & 1)){ + PPU.OAMWriteRegister &= 0xff00; + PPU.OAMWriteRegister |= byte; + PPU.OAMFlip |= 1; + if (PPU.OAMPriorityRotation && (PPU.OAMAddr&1)) IPPU.OBJChanged = TRUE; + } else { + PPU.OAMWriteRegister &= 0x00ff; + uint8 lowbyte = (uint8)(PPU.OAMWriteRegister); + uint8 highbyte = byte; + PPU.OAMWriteRegister |= byte << 8; - int addr = (PPU.OAMAddr << 1); - if (lowbyte != PPU.OAMData[addr] || highbyte != PPU.OAMData[addr + 1]) - { - FLUSH_REDRAW(); - PPU.OAMData[addr] = lowbyte; - PPU.OAMData[addr + 1] = highbyte; - IPPU.OBJChanged = TRUE; - if (addr & 2) - { - // Tile - PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff; - // priority, h and v flip. - PPU.OBJ[addr].Palette = (highbyte >> 1) & 7; - PPU.OBJ[addr].Priority = (highbyte >> 4) & 3; - PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1; - PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1; - } - else - { - // X position (low) - PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xff00; - PPU.OBJ[addr].HPos |= lowbyte; - // Sprite Y position - PPU.OBJ[addr].VPos = highbyte; - } - } + int addr = (PPU.OAMAddr << 1); - PPU.OAMFlip &= ~1; - ++PPU.OAMAddr; + if (lowbyte != PPU.OAMData [addr] || + highbyte != PPU.OAMData [addr+1]) + { + FLUSH_REDRAW (); + PPU.OAMData [addr] = lowbyte; + PPU.OAMData [addr+1] = highbyte; + IPPU.OBJChanged = TRUE; + if (addr & 2) + { + // Tile + PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff; + + // priority, h and v flip. + PPU.OBJ[addr].Palette = (highbyte >> 1) & 7; + PPU.OBJ[addr].Priority = (highbyte >> 4) & 3; + PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1; + PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1; + } + else + { + // X position (low) + PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xFF00; + PPU.OBJ[addr].HPos |= lowbyte; + + // Sprite Y position + PPU.OBJ[addr].VPos = highbyte; + } + } + PPU.OAMFlip &= ~1; + ++PPU.OAMAddr; if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) { - PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; IPPU.OBJChanged = TRUE; } - } + } + + Memory.FillRAM [0x2104] = byte; } // This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :( -#ifdef DEBUGGER -#define CHECK_INBLANK() \ - if (!PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ - { \ - printf("Invalid VRAM acess at (%04d, %04d) blank:%d\n", CPU.Cycles, CPU.V_Counter, PPU.ForcedBlanking); \ - if (Settings.BlockInvalidVRAMAccess) \ - return; \ - } -#else -#define CHECK_INBLANK() \ +#define CHECK_INBLANK \ +{ \ if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ - return; + { \ + return; \ + } \ +} \ + +STATIC inline void REGISTER_2118 (uint8 Byte) +{ + CHECK_INBLANK; + + uint32 address; + if (PPU.VMA.FullGraphicCount) + { + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + Memory.VRAM [address] = Byte; + } + else + { + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; + } + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + if (!PPU.VMA.High) + { +#ifdef DEBUGGER + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) + { + printf ("VRAM write byte: $%04X (%d,%d)\n", PPU.VMA.Address, + Memory.FillRAM[0x2115] & 3, + (Memory.FillRAM [0x2115] & 0x0c) >> 2); + } +#endif + PPU.VMA.Address += PPU.VMA.Increment; + } +// Memory.FillRAM [0x2118] = Byte; +} + +STATIC inline void REGISTER_2118_tile (uint8 Byte) +{ + CHECK_INBLANK; + + uint32 address; + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + Memory.VRAM [address] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2118] = Byte; +} + +STATIC inline void REGISTER_2118_linear (uint8 Byte) +{ + CHECK_INBLANK; + + uint32 address; + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2118] = Byte; +} + +STATIC inline void REGISTER_2119 (uint8 Byte) +{ + CHECK_INBLANK; + + uint32 address; + if (PPU.VMA.FullGraphicCount) + { + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF; + Memory.VRAM [address] = Byte; + } + else + { + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; + } + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + if (PPU.VMA.High) + { +#ifdef DEBUGGER + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) + { + printf ("VRAM write word: $%04X (%d,%d)\n", PPU.VMA.Address, + Memory.FillRAM[0x2115] & 3, + (Memory.FillRAM [0x2115] & 0x0c) >> 2); + } +#endif + PPU.VMA.Address += PPU.VMA.Increment; + } +// Memory.FillRAM [0x2119] = Byte; +} + +STATIC inline void REGISTER_2119_tile (uint8 Byte) +{ + CHECK_INBLANK; + + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + uint32 address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF; + Memory.VRAM [address] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2119] = Byte; +} + +STATIC inline void REGISTER_2119_linear (uint8 Byte) +{ + CHECK_INBLANK; + + uint32 address; + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_EVEN][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][address >> 4] = FALSE; + IPPU.TileCached [TILE_2BIT_ODD][((address >> 4)-1)&(MAX_2BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_EVEN][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][address >> 5] = FALSE; + IPPU.TileCached [TILE_4BIT_ODD][((address >> 5)-1)&(MAX_4BIT_TILES-1)] = FALSE; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2119] = Byte; +} + +STATIC inline void REGISTER_2122(uint8 Byte) +{ + // CG-RAM (palette) write + + if (PPU.CGFLIP) + { + if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) + { + FLUSH_REDRAW (); + PPU.CGDATA[PPU.CGADD] &= 0x00FF; + PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; + IPPU.ColorsChanged = TRUE; + IPPU.Blue [PPU.CGADD] = IPPU.XB [(Byte >> 2) & 0x1f]; + IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], + IPPU.Green [PPU.CGADD], + IPPU.Blue [PPU.CGADD]); + } + PPU.CGADD++; + } + else + { + if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) + { + FLUSH_REDRAW (); + PPU.CGDATA[PPU.CGADD] &= 0x7F00; + PPU.CGDATA[PPU.CGADD] |= Byte; + IPPU.ColorsChanged = TRUE; + IPPU.Red [PPU.CGADD] = IPPU.XB [Byte & 0x1f]; + IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], + IPPU.Green [PPU.CGADD], + IPPU.Blue [PPU.CGADD]); + } + } + PPU.CGFLIP ^= 1; +// Memory.FillRAM [0x2122] = Byte; +} + +STATIC inline void REGISTER_2180(uint8 Byte) +{ + Memory.RAM[PPU.WRAM++] = Byte; + PPU.WRAM &= 0x1FFFF; + Memory.FillRAM [0x2180] = Byte; +} + + #endif -static inline void REGISTER_2118 (uint8 Byte) -{ - CHECK_INBLANK(); - - uint32 address; - - if (PPU.VMA.FullGraphicCount) - { - uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; - address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; - Memory.VRAM[address] = Byte; - } - else - Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte; - - IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - - if (!PPU.VMA.High) - { - #ifdef DEBUGGER - if (Settings.TraceVRAM && !CPU.InDMAorHDMA) - printf("VRAM write byte: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2); - #endif - PPU.VMA.Address += PPU.VMA.Increment; - } -} - -static inline void REGISTER_2119 (uint8 Byte) -{ - CHECK_INBLANK(); - - uint32 address; - - if (PPU.VMA.FullGraphicCount) - { - uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; - address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff; - Memory.VRAM[address] = Byte; - } - else - Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte; - - IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - - if (PPU.VMA.High) - { - #ifdef DEBUGGER - if (Settings.TraceVRAM && !CPU.InDMAorHDMA) - printf("VRAM write word: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2); - #endif - PPU.VMA.Address += PPU.VMA.Increment; - } -} - -static inline void REGISTER_2118_tile (uint8 Byte) -{ - CHECK_INBLANK(); - - uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; - uint32 address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; - - Memory.VRAM[address] = Byte; - - IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - - if (!PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -} - -static inline void REGISTER_2119_tile (uint8 Byte) -{ - CHECK_INBLANK(); - - uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; - uint32 address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff; - - Memory.VRAM[address] = Byte; - - IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - - if (PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -} - -static inline void REGISTER_2118_linear (uint8 Byte) -{ - CHECK_INBLANK(); - - uint32 address; - - Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte; - - IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - - if (!PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -} - -static inline void REGISTER_2119_linear (uint8 Byte) -{ - CHECK_INBLANK(); - - uint32 address; - - Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte; - - IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; - IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; - IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; - - if (PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -} - -static inline void REGISTER_2122 (uint8 Byte) -{ - if (PPU.CGFLIP) - { - if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) - { - FLUSH_REDRAW(); - PPU.CGDATA[PPU.CGADD] &= 0x00ff; - PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; - IPPU.ColorsChanged = TRUE; - IPPU.Blue[PPU.CGADD] = IPPU.XB[(Byte >> 2) & 0x1f]; - IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; - IPPU.ScreenColors[PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]); - } - - PPU.CGADD++; - } - else - { - if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) - { - FLUSH_REDRAW(); - PPU.CGDATA[PPU.CGADD] &= 0x7f00; - PPU.CGDATA[PPU.CGADD] |= Byte; - IPPU.ColorsChanged = TRUE; - IPPU.Red[PPU.CGADD] = IPPU.XB[Byte & 0x1f]; - IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; - IPPU.ScreenColors[PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]); - } - } - - PPU.CGFLIP ^= 1; -} - -static inline void REGISTER_2180 (uint8 Byte) -{ - Memory.RAM[PPU.WRAM++] = Byte; - PPU.WRAM &= 0x1ffff; -} - -static inline uint8 REGISTER_4212 (void) -{ - uint8 byte = 0; - - if ((CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3)) - byte = 1; - if ((CPU.Cycles < Timings.HBlankEnd) || (CPU.Cycles >= Timings.HBlankStart)) - byte |= 0x40; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) - byte |= 0x80; - - return (byte); -} - -#endif diff --git a/source/snes9x/s9xdebug.cpp b/source/snes9x/s9xdebug.cpp new file mode 100644 index 0000000..384f490 --- /dev/null +++ b/source/snes9x/s9xdebug.cpp @@ -0,0 +1,2307 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#include +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "cpuops.h" + +#ifndef NGC +#include "cheats.h" +#endif + +#include "ppu.h" +#include "cpuexec.h" +#include "s9xdebug.h" +#include "missing.h" +#include "display.h" +#include "apu.h" +#include "sa1.h" +#include "spc7110.h" + +#ifdef DEBUGGER +static void WhatsMissing (); +static void WhatsUsed (); +EXTERN_C SDMA DMA[8]; +extern struct SCheatData Cheat; + +FILE *trace = NULL; +FILE *trace2 = NULL; +struct SBreakPoint S9xBreakpoint[6]; +struct SDebug +{ + struct + { + uint8 Bank; + uint16 Address; + } Dump; + struct + { + uint8 Bank; + uint16 Address; + } Unassemble; +} Debug = +{ + { + 0, 0 + }, + { + 0, 0 + } +}; +char *HelpMessage[] = { + "Command Help:", + "? - Shows this Command Help", + "r - Shows the Registers", + "i - Shows the interrupt vectors", + "t - Trace current instruction [Step-into]", + "T - Toggle CPU instruction tracing to trace.log", + "D - Toggle DMA tracing to stdout", + "H - Toggle H-DMA tracing to stdout", + "P - Toggle DSP tracing to stdout", + "U - Toggle unknown register read/write tracing", + "V - Toggle non-DMA V-RAM read/write tracing", + "R - Reset ROM.", + "p - Proceed to next instruction [Step-over]", + "s - Skip to next instruction [Skip]", + "S - dump sprite (OBJ) status", + "g [Address] - Go or Go to [Address]", + "u [Address] - Disassemble from PC or [Address]", + "d [Address] - Dump from PC or [Address]", + "bv [Number] - View Breakpoints or View Breakpoint [Number]", + "bs [Number] [Address] - Enable/Disable Breakpoint", + " [Enable example: BS #2 $02:8002]", + " [Disable example: BS #2]", + "c - Dump SNES colour palette", + "W - Show what SNES hardware features a ROM is using", + " which might not be implemented yet.", + "w - Show some SNES hardware features used so far in this frame", + "q - Quit emulator", + "", + "[Address] - $Bank:Address or $Address", + " [For example: $01:8123]", + "[Number] - #Number", + " [For example: #1]", + "a - Show Sound CPU status", + "A - Toggle sound CPU instruction tracing to aputrace.log", + "B - Toggle sound DSP register tracing", + "C - Dump sound sample addresses", + "ad [Address] - Dump sound CPU RAM from PC or [Address]", + "", NULL}; + +char *S9xMnemonics[256] = { + "BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", + "PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", + "BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", + "CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", + "JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", + "PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", + "BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", + "SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", + "RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR", + "PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", + "BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", + "CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR", + "RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", + "PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", + "BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", + "SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", + "BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", + "DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", + "BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", + "TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", + "LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", + "TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", + "BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", + "CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", + "CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", + "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", + "BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", + "CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", + "CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", + "INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", + "BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", + "SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC" +}; +int AddrModes[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 3, 10, 3, 19, 6, 6, 6, 12, 0, 1,24, 0, 14, 14, 14, 17, //0 + 4, 11, 9, 20, 6, 7, 7, 13, 0, 16,24, 0, 14, 15, 15, 18, //1 + 14, 10,17, 19, 6, 6, 6, 12, 0, 1,24, 0, 14, 14, 14, 17, //2 + 4, 11, 9, 20, 7, 7, 7, 13, 0, 16,24, 0, 15, 15, 15, 18, //3 + 0, 10, 3, 19, 25,6, 6, 12, 0, 1,24, 0, 14, 14, 14, 17, //4 + 4, 11, 9, 20, 25,7, 7, 13, 0, 16, 0, 0, 17, 15, 15, 18, //5 + 0, 10, 5, 19, 6, 6, 6, 12, 0, 1,24, 0, 21, 14, 14, 17, //6 + 4, 11, 9, 20, 7, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18, //7 + 4, 10, 5, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //8 + 4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 14, 15, 15, 18, //9 + 2, 10, 2, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //A + 4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 15, 15, 16, 18, //B + 2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //C + 4, 11, 9, 9,27, 7, 7, 13, 0, 16, 0, 0, 22, 15, 15, 18, //D + 2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //E + 4, 11, 9, 20,26, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 //F +}; + +uint8 S9xOPrint (char *Line, uint8 Bank, uint16 Address) +{ + uint8 S9xOpcode; + uint8 Operant[3]; + uint16 Word; + uint8 Byte; + uint8 Size = 0; + char SByte; + short SWord; + +#if 0 + sprintf (Line, "%04X%04X%04X%04X%02X%04X%c%c%c%c%c%c%c%c%c%03d%03d", + Registers.A.W, Registers.X.W, Registers.Y.W, + Registers.D.W, Registers.DB, Registers.S.W, + CheckEmulation () ? 'E' : 'e', + CheckNegative () ? 'N' : 'n', + CheckOverflow () ? 'V' : 'v', + CheckMemory () ? 'M' : 'm', + CheckIndex () ? 'X' : 'x', + CheckDecimal () ? 'D' : 'd', + CheckIRQ () ? 'I' : 'i', + CheckZero () ? 'Z' : 'z', + CheckCarry () ? 'C' : 'c', + CPU.Cycles, + CPU.V_Counter); + return (0); + +#else + int32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + + S9xOpcode = S9xGetByte ((Bank << 16) + Address); + sprintf (Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); + Operant[0] = S9xGetByte ((Bank << 16) + Address + 1); + Operant[1] = S9xGetByte ((Bank << 16) + Address + 2); + Operant[2] = S9xGetByte ((Bank << 16) + Address + 3); + + switch (AddrModes[S9xOpcode]) + { + case 0: + //Implied + sprintf (Line, "%s %s", Line, S9xMnemonics[S9xOpcode]); + Size = 1; + break; + case 1: + //Immediate[MemoryFlag] + if (!CheckFlag (MemoryFlag)) + { + //Accumulator 16 - Bit + sprintf (Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + //Accumulator 8 - Bit + sprintf (Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + break; + case 2: + //Immediate[IndexFlag] + if (!CheckFlag (IndexFlag)) + { + //X / Y 16 - Bit + sprintf (Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + //X / Y 8 - Bit + sprintf (Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + break; + case 3: + //Immediate[Always 8 - Bit] + if (1) + { + //Always 8 - Bit + sprintf (Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + break; + case 4: + //Relative + sprintf (Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + SByte = Operant[0]; + Word = Address; + Word += SByte; + Word += 2; + sprintf (Line, "%-32s[$%04X]", Line, Word); + Size = 2; + break; + case 5: + //Relative Long + sprintf (Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + SWord = (Operant[1] << 8) | Operant[0]; + Word = Address; + Word += SWord; + Word += 3; + sprintf (Line, "%-32s[$%04X]", Line, Word); + Size = 3; + break; + case 6: + //Direct + sprintf (Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 7: + //Direct indexed (with x) + sprintf (Line, "%s%02X %s $%02X,x", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word += Registers.X.W; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 8: + //Direct indexed (with y) + sprintf (Line, "%s%02X %s $%02X,y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word += Registers.Y.W; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 9: + //Direct Indirect + sprintf (Line, "%s%02X %s ($%02X)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + case 10: + //Direct Indexed Indirect + sprintf (Line, "%s%02X %s ($%02X,x)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word += Registers.X.W; + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + case 11: + //Direct Indirect Indexed + sprintf (Line, "%s%02X %s ($%02X),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word = S9xGetWord (Word); + Word += Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + case 12: + //Direct Indirect Long + sprintf (Line, "%s%02X %s [$%02X]", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Byte = S9xGetByte (Word + 2); + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + case 13: + //Direct Indirect Indexed Long + sprintf (Line, "%s%02X %s [$%02X],y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Byte = S9xGetByte (Word + 2); + Word = S9xGetWord (Word); + Word += Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + case 14: + //Absolute + sprintf (Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 3; + break; + case 15: + //Absolute Indexed (With X) + sprintf (Line, "%s%02X %02X %s $%02X%02X,x", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.X.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 3; + break; + case 16: + //Absolute Indexed (With Y) + sprintf (Line, "%s%02X %02X %s $%02X%02X,y", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 3; + break; + case 17: + //Absolute long + sprintf (Line, "%s%02X %02X %02X %s $%02X%02X%02X", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + case 18: + //Absolute Indexed long + sprintf (Line, "%s%02X %02X %02X %s $%02X%02X%02X,x", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.X.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + case 19: + //StackRelative + sprintf (Line, "%s%02X %s $%02X,s", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Registers.S.W; + Word += Operant[0]; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 20: + //Stack Relative Indirect Indexed + sprintf (Line, "%s%02X %s ($%02X,s),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Registers.S.W; + Word += Operant[0]; + Word = S9xGetWord (Word); + Word += Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + case 21: + //Absolute Indirect + sprintf (Line, "%s%02X %02X %s ($%02X%02X)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); + Size = 3; + break; + case 22: + //Absolute Indirect Long + sprintf (Line, "%s%02X %02X %s [$%02X%02X]", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Byte = S9xGetByte (Word + 2); + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 3; + break; + case 23: + //Absolute Indexed Indirect + sprintf (Line, "%s%02X %02X %s ($%02X%02X,x)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.X.W; + Word = S9xGetWord (ICPU.ShiftedPB + Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); + Size = 3; + break; + case 24: + //Implied accumulator + sprintf (Line, "%s %s A", Line, S9xMnemonics[S9xOpcode]); + Size = 1; + break; + case 25: + // MVN/MVP SRC DST + sprintf (Line, "%s%02X %02X %s %02X %02X", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], + Operant[1], Operant[0]); + Size = 3; + break; + case 26: + // PEA + sprintf (Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + break; + case 27: + // PEI Direct Indirect + sprintf (Line, "%s%02X %s ($%02X)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%04X]", Line, Word); + Size = 2; + break; + } +// XXX: + sprintf (Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%04d VC:%03d FC:%02d %02x", + Line, Registers.A.W, Registers.X.W, Registers.Y.W, + Registers.D.W, Registers.DB, Registers.S.W, + CheckEmulation () ? 'E' : 'e', + CheckNegative () ? 'N' : 'n', + CheckOverflow () ? 'V' : 'v', + CheckMemory () ? 'M' : 'm', + CheckIndex () ? 'X' : 'x', + CheckDecimal () ? 'D' : 'd', + CheckIRQ () ? 'I' : 'i', + CheckZero () ? 'Z' : 'z', + CheckCarry () ? 'C' : 'c', + Cycles, + CPU.V_Counter, + IPPU.FrameCount, + CPU.IRQActive); + + CPU.Cycles = Cycles; + CPU.WaitAddress = WaitAddress; + return Size; +#endif +} + +uint8 S9xSA1OPrint (char *Line, uint8 Bank, uint16 Address) +{ + uint8 S9xOpcode; + uint8 Operant[3]; + uint16 Word; + uint8 Byte; + uint8 Size = 0; + char SByte; + short SWord; + +#if 0 + sprintf (Line, "%04X%04X%04X%04X%02X%04X%c%c%c%c%c%c%c%c%c%03d%03d", + SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W, + SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W, + SA1CheckEmulation () ? 'E' : 'e', + SA1CheckNegative () ? 'N' : 'n', + SA1CheckOverflow () ? 'V' : 'v', + SA1CheckMemory () ? 'M' : 'm', + SA1CheckIndex () ? 'X' : 'x', + SA1CheckDecimal () ? 'D' : 'd', + SA1CheckIRQ () ? 'I' : 'i', + SA1CheckZero () ? 'Z' : 'z', + SA1CheckCarry () ? 'C' : 'c', + CPU.Cycles, + CPU.V_Counter); + return (0); + +#else + S9xOpcode = S9xSA1GetByte ((Bank << 16) + Address); + sprintf (Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); + Operant[0] = S9xSA1GetByte ((Bank << 16) + Address + 1); + Operant[1] = S9xSA1GetByte ((Bank << 16) + Address + 2); + Operant[2] = S9xSA1GetByte ((Bank << 16) + Address + 3); + + switch (AddrModes[S9xOpcode]) + { + case 0: + //Implied + sprintf (Line, "%s %s", Line, S9xMnemonics[S9xOpcode]); + Size = 1; + break; + case 1: + //Immediate[MemoryFlag] + if (!SA1CheckFlag (MemoryFlag)) + { + //Accumulator 16 - Bit + sprintf (Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + //Accumulator 8 - Bit + sprintf (Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + break; + case 2: + //Immediate[IndexFlag] + if (!SA1CheckFlag (IndexFlag)) + { + //X / Y 16 - Bit + sprintf (Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + //X / Y 8 - Bit + sprintf (Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + break; + case 3: + //Immediate[Always 8 - Bit] + if (1) + { + //Always 8 - Bit + sprintf (Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + break; + case 4: + //Relative + sprintf (Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + SByte = Operant[0]; + Word = Address; + Word += SByte; + Word += 2; + sprintf (Line, "%-32s[$%04X]", Line, Word); + Size = 2; + break; + case 5: + //Relative Long + sprintf (Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + SWord = (Operant[1] << 8) | Operant[0]; + Word = Address; + Word += SWord; + Word += 3; + sprintf (Line, "%-32s[$%04X]", Line, Word); + Size = 3; + break; + case 6: + //Direct + sprintf (Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 7: + //Direct indexed (with x) + sprintf (Line, "%s%02X %s $%02X,x", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word += SA1Registers.X.W; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 8: + //Direct indexed (with y) + sprintf (Line, "%s%02X %s $%02X,y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 9: + //Direct Indirect + sprintf (Line, "%s%02X %s ($%02X)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + case 10: + //Direct Indexed Indirect + sprintf (Line, "%s%02X %s ($%02X,x)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word += SA1Registers.X.W; + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + case 11: + //Direct Indirect Indexed + sprintf (Line, "%s%02X %s ($%02X),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word = S9xSA1GetWord (Word); + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + case 12: + //Direct Indirect Long + sprintf (Line, "%s%02X %s [$%02X]", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Byte = S9xSA1GetByte (Word + 2); + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + case 13: + //Direct Indirect Indexed Long + sprintf (Line, "%s%02X %s [$%02X],y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Byte = S9xSA1GetByte (Word + 2); + Word = S9xSA1GetWord (Word); + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + case 14: + //Absolute + sprintf (Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 3; + break; + case 15: + //Absolute Indexed (With X) + sprintf (Line, "%s%02X %02X %s $%02X%02X,x", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.X.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 3; + break; + case 16: + //Absolute Indexed (With Y) + sprintf (Line, "%s%02X %02X %s $%02X%02X,y", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 3; + break; + case 17: + //Absolute long + sprintf (Line, "%s%02X %02X %02X %s $%02X%02X%02X", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + case 18: + //Absolute Indexed long + sprintf (Line, "%s%02X %02X %02X %s $%02X%02X%02X,x", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.X.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + case 19: + //StackRelative + sprintf (Line, "%s%02X %s $%02X,s", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = SA1Registers.S.W; + Word += Operant[0]; + sprintf (Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + case 20: + //Stack Relative Indirect Indexed + sprintf (Line, "%s%02X %s ($%02X,s),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = SA1Registers.S.W; + Word += Operant[0]; + Word = S9xSA1GetWord (Word); + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + case 21: + //Absolute Indirect + sprintf (Line, "%s%02X %02X %s ($%02X%02X)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); + Size = 3; + break; + case 22: + //Absolute Indirect Long + sprintf (Line, "%s%02X %02X %s [$%02X%02X]", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Byte = S9xSA1GetByte (Word + 2); + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 3; + break; + case 23: + //Absolute Indexed Indirect + sprintf (Line, "%s%02X %02X %s ($%02X%02X,x)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.X.W; + Word = S9xSA1GetWord (SA1.ShiftedPB + Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); + Size = 3; + break; + case 24: + //Implied accumulator + sprintf (Line, "%s %s A", Line, S9xMnemonics[S9xOpcode]); + Size = 1; + break; + case 25: + // MVN/MVP SRC DST + sprintf (Line, "%s %s %02X %02X", Line, S9xMnemonics[S9xOpcode], + Operant[0], Operant[1]); + Size = 3; + break; + } + sprintf (Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%03ld VC:%03ld", + Line, SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W, + SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W, + SA1CheckEmulation () ? 'E' : 'e', + SA1CheckNegative () ? 'N' : 'n', + SA1CheckOverflow () ? 'V' : 'v', + SA1CheckMemory () ? 'M' : 'm', + SA1CheckIndex () ? 'X' : 'x', + SA1CheckDecimal () ? 'D' : 'd', + SA1CheckIRQ () ? 'I' : 'i', + SA1CheckZero () ? 'Z' : 'z', + SA1CheckCarry () ? 'C' : 'c', + CPU.Cycles, + CPU.V_Counter); + + return Size; +#endif +} + +/**********************************************************************************************/ +/* DPrint() */ +/* This function prints a line in the debug listbox and deletes upperlines if needed */ +/**********************************************************************************************/ +void DPrint (char *Line) +{ + printf ("%s\n", Line); +} +/**********************************************************************************************/ +/* GetNumber() */ +/* This function gets a number from a debug command */ +/**********************************************************************************************/ +int GetNumber (char *Line, uint16 * Number) +{ + int i; + if (sscanf (Line, " #%d", &i) == 1) + { + *Number = i; + return (1); + } + return (-1); +} +/**********************************************************************************************/ +/* GetStartAddress() */ +/* This function gets a starting address from a debug command */ +/**********************************************************************************************/ +short GetStartAddress (char *Line, uint8 *Bank, uint32 *Address) +{ + uint32 a, b; + if (sscanf (Line + 1, " $%x:%x", &b, &a) != 2) + return (-1); + *Bank = b; + *Address = a; + return (1); +} +/**********************************************************************************************/ +/* ProcessDebugCommand() */ +/* This function processes a debug command */ +/**********************************************************************************************/ +static void ProcessDebugCommand (char *Line) +{ + uint8 Bank = Registers.PB; + uint32 Address = Registers.PCw; + uint16 Hold; + uint16 Number; + char String [512]; + short ErrorCode; + + if (strcasecmp (Line, "cheat") == 0) + { + S9xStartCheatSearch (&Cheat); + printf ("Cheat Search Started\n"); + return; + } + if (strcasecmp (Line, "less") == 0) + { + S9xSearchForChange (&Cheat, S9X_LESS_THAN, S9X_8_BITS, FALSE, TRUE); + printf ("Recorded all values that have decreased\n"); + return; + } + if (strcasecmp (Line, "print") == 0) + { + printf ("Cheat search results:\n"); + S9xOutputCheatSearchResults (&Cheat); + return; + } + + if (strncasecmp (Line, "constant", 8) == 0) + { + uint32 Byte; + if (sscanf (&Line [8], "%x %x", &Address, &Byte) == 2) + S9xAddCheat (TRUE, TRUE, Address, Byte); + return; + } + + if (strncasecmp (Line, "dump", 4) == 0) + { + int Count; + if (sscanf (&Line [4], "%x %d", &Address, &Count) == 2) + { + sprintf (String, "%06x%05d.sd2", Address, Count); + FILE *fs = fopen (String, "wb"); + if (fs) + { + int i; + for (i = 0; i < Count; i++) + putc (S9xGetByte (Address + i), fs); + + fclose (fs); + } + else + printf ("Can't open %s for writing\n", String); + } + else + printf ("Usage: dump start_address_in_hex count_in_decimal\n"); + return; + } + if (Line[0] == 'i') + { + printf ("Vectors:\n"); + sprintf (String, " 8 Bit 16 Bit "); + DPrint (String); + sprintf (String, "ABT $00:%04X|$00:%04X", S9xGetWord (0xFFF8), S9xGetWord (0xFFE8)); + DPrint (String); + sprintf (String, "BRK $00:%04X|$00:%04X", S9xGetWord (0xFFFE), S9xGetWord (0xFFE6)); + DPrint (String); + sprintf (String, "COP $00:%04X|$00:%04X", S9xGetWord (0xFFF4), S9xGetWord (0xFFE4)); + DPrint (String); + sprintf (String, "IRQ $00:%04X|$00:%04X", S9xGetWord (0xFFFE), S9xGetWord (0xFFEE)); + DPrint (String); + sprintf (String, "NMI $00:%04X|$00:%04X", S9xGetWord (0xFFFA), S9xGetWord (0xFFEA)); + DPrint (String); + sprintf (String, "RES $00:%04X", S9xGetWord (0xFFFC)); + DPrint (String); + } + if (strncmp (Line, "ai", 2) == 0) + { + printf ("APU vectors:"); + for (int i = 0; i < 0x40; i += 2) + { + if (i % 16 == 0) + printf ("\n%04x ", 0xffc0 + i); + printf ("%04x ", APU.ExtraRAM [i]); + } + printf ("\n"); + } + if (Line[0] == 's') + { + Registers.PCw += S9xOPrint (String, Bank, Address); + Bank = Registers.PB; + Address = Registers.PCw; + Line[0] = 'r'; + } + if (Line[0] == 'z') + { + uint16 *p = (uint16 *) &Memory.VRAM [PPU.BG[2].SCBase << 1]; + for (int l = 0; l < 32; l++) + { + for (int c = 0; c < 32; c++, p++) + { + printf ("%04x,", *p++); + } + printf ("\n"); + } + } + if (*Line == 'c') + { + printf ("Colours:\n"); + for (int i = 0; i < 256; i++) + { + printf ("%02x%02x%02x ", PPU.CGDATA[i] & 0x1f, + (PPU.CGDATA[i] >> 5) & 0x1f, + (PPU.CGDATA[i] >> 10) & 0x1f); + } + printf ("\n"); + } + if (*Line == 'S') + { + int SmallWidth, LargeWidth; + int SmallHeight, LargeHeight; + switch ((Memory.FillRAM[0x2101] >> 5) & 7) + { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + default: + case 5: + SmallWidth = SmallHeight = 32; + LargeWidth = LargeHeight = 64; + break; + case 6: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = 32; LargeHeight = 64; + break; + case 7: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } + printf ("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n", + SmallWidth,SmallHeight, LargeWidth,LargeHeight, PPU.OAMAddr, + PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite); +// for (int p = 0; p < 4; p++) +// { +// int c = 0; +// int i; +// for (i = 0; GFX.OBJList [i] >= 0; i++) +// { +// if (PPU.OBJ[GFX.OBJList [i]].Priority == p) +// c++; +// } +// printf ("Priority %d: %03d, ", p, c); +// } +// printf ("\n"); + for (int i = 0; i < 128; i++) + { + printf ("X:%3d Y:%3d %c%c%d%c ", + PPU.OBJ[i].HPos, + PPU.OBJ[i].VPos, + PPU.OBJ[i].VFlip ? 'V' : 'v', + PPU.OBJ[i].HFlip ? 'H' : 'h', + PPU.OBJ[i].Priority, + PPU.OBJ[i].Size ? 'S' : 's'); + if (i % 4 == 3) + printf ("\n"); + } + } + if (*Line == 'T') + { + if (Line [1] == 'S') + { + SA1.Flags ^= TRACE_FLAG; + if (SA1.Flags & TRACE_FLAG) + { + printf ("SA1 CPU instruction tracing enabled.\n"); + if (trace2 == NULL) + trace2 = fopen ("trace_sa1.log", "wb"); + } + else + { + printf ("SA1 CPU instruction tracing disabled.\n"); + fclose (trace2); + trace2 = NULL; + } + } + else + { + CPU.Flags ^= TRACE_FLAG; + if (CPU.Flags & TRACE_FLAG) + { + printf ("CPU instruction tracing enabled.\n"); + if (trace == NULL) + trace = fopen ("trace.log", "wb"); + } + else + { + printf ("CPU instruction tracing disabled.\n"); + fclose (trace); + trace = NULL; + } + } + } + if (*Line == 'A') + { + APU.Flags ^= TRACE_FLAG; + + extern FILE *apu_trace; + if (APU.Flags & TRACE_FLAG) + { + if (apu_trace == NULL) + apu_trace = fopen ("aputrace.log", "wb"); + } + else + { + if (apu_trace) + { + fclose (apu_trace); + apu_trace = NULL; + } + } + + printf ("APU tracing %s\n", APU.Flags & TRACE_FLAG ? "enabled" : + "disabled"); + } + if (*Line == 'B') + { + Settings.TraceSoundDSP ^= 1; + printf ("Sound DSP register tracing %s\n", Settings.TraceSoundDSP ? + "enabled" : "disabled"); + + S9xOpenCloseSoundTracingFile (Settings.TraceSoundDSP); + } + + if (*Line == 'b') + S9xPrintAPUState (); + + if (*Line == 'C') + { + printf ("SPC700 sample addresses at 0x%04x:\n", APU.DSP [APU_DIR] << 8); + for (int i = 0; i < 256; i++) + { + uint8 *dir = IAPU.RAM + + (((APU.DSP [APU_DIR] << 8) + + i * 4) & 0xffff); + int addr = *dir + (*(dir + 1) << 8); + int addr2 = *(dir + 2) + (*(dir + 3) << 8); + printf ("%04X %04X;", addr, addr2); + if (i % 8 == 7) + printf ("\n"); + } + } + if (*Line == 'R') + { + S9xReset (); + printf ("SNES reset.\n"); + CPU.Flags |= DEBUG_MODE_FLAG; + } + if (strncmp (Line, "ad", 2) == 0) + { + uint32 Count = 16; + Address = 0; + if (sscanf (Line+2, "%x,%x", &Address, &Count) != 2) + { + if (sscanf (Line + 2, "%x", &Address) == 1) + Count = 16; + } + printf ("APU RAM dump:\n"); + for (uint32 l = 0; l < Count; l += 16) + { + printf ("%04X ", Address); + for (int i = 0; i < 16; i++) + printf ("%02X ", IAPU.RAM [Address++]); + printf ("\n"); + } + *Line = 0; + } + if (*Line == 'a') + { + printf ("APU in-ports: %02X %02X %02X %02X\n", + IAPU.RAM [0xF4], IAPU.RAM [0xF5], IAPU.RAM [0xF6], IAPU.RAM [0xF7]); + printf ("APU out-ports: %02X %02X %02X %02X\n", + APU.OutPorts [0], APU.OutPorts [1], APU.OutPorts [2], APU.OutPorts [3]); + printf ("ROM/RAM switch: %s\n", (IAPU.RAM [0xf1] & 0x80) ? "ROM" : "RAM"); + for (int i = 0; i < 3; i++) + if (APU.TimerEnabled [i]) + printf ("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n", + i, APU.Timer [i], IAPU.RAM [0xfd + i], APU.TimerTarget [i]); + } + if (*Line == 'P') + { + Settings.TraceDSP = !Settings.TraceDSP; + printf ("DSP tracing %s\n", Settings.TraceDSP ? "enabled" : "disabled"); + } + if (Line[0] == 'p') + { + S9xBreakpoint[5].Enabled = FALSE; + Address += S9xOPrint (String, Bank, Address); + if (strncmp (&String[18], "JMP", 3) != 0 && + strncmp (&String[18], "JML", 3) != 0 && + strncmp (&String[18], "RT", 2) != 0 && + strncmp (&String[18], "BRA", 3)) + { + S9xBreakpoint[5].Enabled = TRUE; + S9xBreakpoint[5].Bank = Bank; + S9xBreakpoint[5].Address = Address; + } + else + { + CPU.Flags |= SINGLE_STEP_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + } + if (Line[0] == 'b') + { + if (Line[1] == 's') + { + GetNumber (Line + 2, &Hold); + if (Hold > 4) + Hold = 0; + if (Hold < 5) + if (GetStartAddress (Line + 5, &Bank, &Address) == -1) + { + //Clear S9xBreakpoint + S9xBreakpoint[Hold].Enabled = FALSE; + } + else + { + //Set S9xBreakpoint + S9xBreakpoint[Hold].Enabled = TRUE; + S9xBreakpoint[Hold].Bank = Bank; + S9xBreakpoint[Hold].Address = Address; + CPU.Flags |= BREAK_FLAG; + } + Line = "bv"; + } + if (Line[1] == 'v') + { + Number = 0; + if (GetNumber (Line + 2, &Number) == -1 && + Number < 5) + { + //Show All Breakpoints + DPrint ("Breakpoints:"); + for (Number = 0; Number != 5; Number++) + { + if (S9xBreakpoint[Number].Enabled) + sprintf (String, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address); + else + sprintf (String, "%i @ Disabled", Number); + DPrint (String); + } + } + else + { + //Show selected S9xBreakpoint + DPrint ("Breakpoint:"); + if (S9xBreakpoint[Number].Enabled) + sprintf (String, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address); + else + sprintf (String, "%i @ Disabled", Number); + DPrint (String); + } + } + } + if (Line[0] == '?' || strcasecmp (Line, "help") == 0) + { + for (short Counter = 0; HelpMessage[Counter] != NULL; Counter++) + DPrint (HelpMessage[Counter]); + } + if (Line[0] == 't') + { + CPU.Flags |= SINGLE_STEP_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + if (Line[0] == 'f') + { + CPU.Flags |= FRAME_ADVANCE_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + // Render this frame + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + if (sscanf (&Line [1], "%u", &ICPU.FrameAdvanceCount) != 1) + ICPU.Frame = 0; + } + + if (Line[0] == 'g') + { + S9xBreakpoint[5].Enabled = FALSE; + int i; + bool8 found = FALSE; + for (i = 0; i < 5; i++) + { + if (S9xBreakpoint[i].Enabled) + { + found = TRUE; + if (S9xBreakpoint[i].Bank == Registers.PB && + S9xBreakpoint[i].Address == Registers.PCw) + { + S9xBreakpoint[i].Enabled = 2; + break; + } + } + } + if (!found) + CPU.Flags &= ~BREAK_FLAG; + ErrorCode = GetStartAddress (Line, &Bank, &Address); + if (ErrorCode == 1) + { + S9xBreakpoint[5].Enabled = TRUE; + S9xBreakpoint[5].Bank = Bank; + S9xBreakpoint[5].Address = Address; + CPU.Flags |= BREAK_FLAG; + } + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + if (*Line == 'D') + { + Settings.TraceDMA = !Settings.TraceDMA; + printf ("DMA tracing %s\n", Settings.TraceDMA ? "enabled" : "disabled"); + } + if (*Line == 'V') + { + Settings.TraceVRAM = !Settings.TraceVRAM; + printf ("Non-DMA VRAM write tracing %s\n", Settings.TraceVRAM ? "enabled" : "disabled"); + } + if (*Line == 'H') + { + Settings.TraceHDMA = !Settings.TraceHDMA; + printf ("H-DMA tracing %s\n", Settings.TraceHDMA ? "enabled" : "disabled"); + } + if (*Line == 'U') + { + Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters; + printf ("Unknown registers read/write tracing %s\n", + Settings.TraceUnknownRegisters ? "enabled" : "disabled"); + } + if (Line[0] == 'd') + { + int CLine; + int CByte; + int32 Cycles = CPU.Cycles; + uint8 MemoryByte; + + if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0) + { + Bank = Debug.Dump.Bank; + Address = Debug.Dump.Address; + } + ErrorCode = GetStartAddress (Line, &Bank, &Address); + for (CLine = 0; CLine != 10; CLine++) + { + sprintf (String, "$%02X:%04X", Bank, Address); + for (CByte = 0; CByte != 16; CByte++) + { + if (Address + CByte == 0x2140 || + Address + CByte == 0x2141 || + Address + CByte == 0x2142 || + Address + CByte == 0x2143 || + Address + CByte == 0x4210) + { + MemoryByte = 0; + } + else + { + MemoryByte = S9xGetByte ((Bank << 16) + Address + CByte); + } + sprintf (String, "%s %02X", String, MemoryByte); + } + sprintf (String, "%s-", String); + for (CByte = 0; CByte != 16; CByte++) + { + if (Address + CByte == 0x2140 || + Address + CByte == 0x2141 || + Address + CByte == 0x2142 || + Address + CByte == 0x2143 || + Address + CByte == 0x4210) + { + MemoryByte = 0; + } + else + { + MemoryByte = S9xGetByte ((Bank << 16) + Address + CByte); + } + if (MemoryByte < 32 || MemoryByte >= 127) + MemoryByte = '?'; + sprintf (String, "%s%c", String, MemoryByte); + } + Address += 16; + DPrint (String); + } + Debug.Dump.Bank = Bank; + Debug.Dump.Address = Address; + CPU.Cycles = Cycles; + } + + if (*Line == 'q') + S9xExit (); + if (*Line == 'W') + WhatsMissing (); + if (*Line == 'w') + WhatsUsed (); + if (Line[0] == 'r') + { +#if 0 + sprintf (String, + "A[%04X] X[%04X] Y[%04X] S[%04X] D[%04X] DB[%02X] P[%02X] F[%s %s %s %s %s %s %s %s / %s]", + Registers.A.W, + Registers.X.W, + Registers.Y.W, + Registers.S.W, + Registers.D.W, + Registers.DB, + Registers.PL, + (Registers.P.W & 128) != 0 ? "N" : "n", + (Registers.P.W & 64) != 0 ? "V" : "v", + (Registers.P.W & 32) != 0 ? "M" : "m", + (Registers.P.W & 16) != 0 ? "X" : "x", + (Registers.P.W & 8) != 0 ? "D" : "d", + (Registers.P.W & 4) != 0 ? "I" : "i", + (Registers.P.W & 2) != 0 ? "Z" : "z", + (Registers.P.W & 1) != 0 ? "C" : "c", + (Registers.P.W & 256) != 0 ? "E" : "e"); + DPrint (String); +#endif + S9xOPrint (String, Bank, Address); + DPrint (String); + } + if (Line[0] == 'u') + { + if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0) + { + Bank = Debug.Unassemble.Bank; + Address = Debug.Unassemble.Address; + } + ErrorCode = GetStartAddress (Line, &Bank, &Address); + for (short Counter = 0; Counter != 10; Counter++) + { + Address += S9xOPrint (String, Bank, Address); + DPrint (String); + } + Debug.Unassemble.Bank = Bank; + Debug.Unassemble.Address = Address; + } + DPrint (""); + return; +} +static void PrintWindow (uint8 * a) +{ + for (int i = 0; i < 6; i++) + if (a[i]) + switch (i) + { + case 0: + printf ("Background 0, "); + break; + case 1: + printf ("Background 1, "); + break; + case 2: + printf ("Background 2, "); + break; + case 3: + printf ("Background 3, "); + break; + case 4: + printf ("Objects, "); + break; + case 5: + printf ("Colour window, "); + break; + } +} +static char *ClipFn (int logic) +{ + switch (logic) + { + case CLIP_OR: + return ("OR"); + case CLIP_AND: + return ("AND"); + case CLIP_XOR: + return ("XOR"); + case CLIP_XNOR: + return ("XNOR"); + default: + return ("???"); + } +} + +static void WhatsUsed () +{ + printf ("V-line: %ld, H-Pos: %ld\n", CPU.V_Counter, CPU.Cycles); + printf ("Screen mode: %d, ", PPU.BGMode); + if (PPU.BGMode <= 1 && (Memory.FillRAM [0x2105] & 8)) + printf ("(BG#2 Priority)"); + + printf ("Brightness: %d", PPU.Brightness); + if (Memory.FillRAM[0x2100] & 0x80) + printf (" (screen blanked)"); + printf ("\n"); + if (Memory.FillRAM[0x2133] & 1) + printf ("Interlace, "); + if (Memory.FillRAM[0x2133] & 4) + printf ("240 line visible, "); + if (Memory.FillRAM[0x2133] & 8) + printf ("Pseudo 512 pixels horizontal resolution, "); + if (Memory.FillRAM[0x2133] & 0x40) + printf ("Mode 7 priority per pixel, "); + printf ("\n"); + if (PPU.BGMode == 7 && (Memory.FillRAM[0x211a] & 3)) + printf ("Mode 7 flipping, "); + if (PPU.BGMode == 7) + printf ("Mode 7 screen repeat: %d,", (Memory.FillRAM[0x211a] & 0xc0) >> 6); + if (Memory.FillRAM[0x2130] & 1) + printf ("32K colour mode, "); + if (PPU.BGMode == 7) + { + // Sign extend 13 bit values to 16 bit values... + if (PPU.CentreX & (1 << 12)) + PPU.CentreX |= 0xe000; + if (PPU.CentreY & (1 << 12)) + PPU.CentreY |= 0xe000; + + printf ("\nMatrix A: %.3f, B: %.3f, C: %.3f, D: %.3f, Centre X: %d Y:%d\n", + (double) PPU.MatrixA / 256, (double) PPU.MatrixB / 256, + (double) PPU.MatrixC / 256, (double) PPU.MatrixD / 256, + PPU.CentreX, PPU.CentreY); + } + if ((Memory.FillRAM[0x2106] & 0xf0) && (Memory.FillRAM[0x2106] & 0x0f)) + { + printf ("\nMosaic effect(%d) on ", PPU.Mosaic); + for (int i = 0; i < 4; i++) + if (Memory.FillRAM[0x2106] & (1 << i)) + printf ("BG%d,", i); + printf (","); + } + if (PPU.HVBeamCounterLatched) + printf ("V and H beam pos latched, "); + if (Memory.FillRAM[0x4200] & 0x20) + printf ("V-IRQ enabled at %d\n", PPU.IRQVBeamPos); + if (Memory.FillRAM[0x4200] & 0x10) + printf ("H-IRQ enabled at %d\n", PPU.IRQHBeamPos); + if (Memory.FillRAM[0x4200] & 0x80) + printf ("V-blank NMI enabled\n"); + int i; + for (i = 0; i < 8; i++) + { + if (missing.hdma_this_frame & (1 << i)) + { + printf ("H-DMA %d [%d] 0x%02X%04X->0x21%02X %s %s 0x%02X%04X %s addressing\n", + i, DMA[i].TransferMode, + DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, + DMA[i].AAddressDecrement ? "dec" : "inc", + DMA[i].Repeat ? "repeat" : "continue", + DMA[i].IndirectBank, DMA[i].IndirectAddress, + DMA[i].HDMAIndirectAddressing ? "indirect" : "absolute"); + } + } + for (i = 0; i < 8; i++) + { + if (missing.dma_this_frame & (1 << i)) + { + printf ("DMA %d %d 0x%02X%04X->0x21%02X Num: %d %s\n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, + DMA[i].BAddress, DMA[i].TransferBytes, + DMA[i].AAddressFixed ? "fixed" : + (DMA[i].AAddressDecrement ? "dec" : "inc")); + } + } + printf ("VRAM write address: 0x%04x(%s), Full Graphic: %d, Address inc: %d\n", + PPU.VMA.Address, + PPU.VMA.High ? "Byte" : "Word", + PPU.VMA.FullGraphicCount, PPU.VMA.Increment); + + for (i = 0; i < 4; i++) + { + printf ("BG%d: VOffset:%d, HOffset:%d, W:%d, H:%d, TS:%d, BA:0x%04x, TA:0x%04X\n", + i, PPU.BG[i].VOffset, PPU.BG[i].HOffset, + (PPU.BG[i].SCSize & 1) * 32 + 32, + (PPU.BG[i].SCSize & 2) * 16 + 32, + PPU.BG[i].BGSize * 8 + 8, + PPU.BG[i].SCBase, + PPU.BG[i].NameBase); + } + char *s = ""; + switch ((Memory.FillRAM [0x2130] & 0xc0) >> 6) + { + case 0: s = "always on"; break; + case 1: s = "inside"; break; + case 2: s = "outside"; break; + case 3: s = "always off"; break; + } + printf ("Main screen (%s): ", s); + for (i = 0; i < 5; i++) + if (Memory.FillRAM[0x212c] & (1 << i)) + switch (i) + { + case 0: + printf ("BG0,"); + break; + case 1: + printf ("BG1,"); + break; + case 2: + printf ("BG2,"); + break; + case 3: + printf ("BG3,"); + break; + case 4: + printf ("OBJ,"); + break; + } + + switch ((Memory.FillRAM [0x2130] & 0x30) >> 4) + { + case 0: s = "always on"; break; + case 1: s = "inside"; break; + case 2: s = "outside"; break; + case 3: s = "always off"; break; + } + + printf ("\nSub-screen (%s): ", s); + for (i = 0; i < 5; i++) + if (Memory.FillRAM[0x212d] & (1 << i)) + switch (i) + { + case 0: + printf ("BG0,"); + break; + case 1: + printf ("BG1,"); + break; + case 2: + printf ("BG2,"); + break; + case 3: + printf ("BG3,"); + break; + case 4: + printf ("OBJ,"); + break; + } + printf ("\n"); + if ((Memory.FillRAM[0x2131] & 0x3f)) + { + if (Memory.FillRAM[0x2131] & 0x80) + { + if (Memory.FillRAM[0x2130] & 0x02) + printf ("Subscreen subtract"); + else + printf ("Fixed colour subtract"); + } + else + { + if (Memory.FillRAM[0x2130] & 0x02) + printf ("Subscreen addition"); + else + printf ("Fixed colour addition"); + } + if (Memory.FillRAM [0x2131] & 0x40) + printf ("(half):"); + else + printf (":"); + + for (i = 0; i < 6; i++) + if (Memory.FillRAM[0x2131] & (1 << i)) + { + switch (i) + { + case 0: + printf ("BG0,"); + break; + case 1: + printf ("BG1,"); + break; + case 2: + printf ("BG2,"); + break; + case 3: + printf ("BG3,"); + break; + case 4: + printf ("OBJ,"); + break; + case 5: + printf ("BACK,"); + break; + } + } + printf ("\n"); + } + printf ("\nWindow 1 (%d, %d, %02x, %02x): ", PPU.Window1Left, + PPU.Window1Right, Memory.FillRAM [0x212e], Memory.FillRAM [0x212f]); + for (i = 0; i < 6; i++) + if (PPU.ClipWindow1Enable [i]) + switch (i) + { + case 0: + printf ("BG0(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[0])); + break; + case 1: + printf ("BG1(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[1])); + break; + case 2: + printf ("BG2(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[2])); + break; + case 3: + printf ("BG3(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[3])); + break; + case 4: + printf ("OBJ(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[4])); + break; + case 5: + printf ("COL(%s-%s)", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[5])); + break; + } + + printf ("\nWindow 2 (%d, %d): ", PPU.Window2Left, + PPU.Window2Right); + for (i = 0; i < 6; i++) + if (PPU.ClipWindow2Enable [i]) + switch (i) + { + case 0: + printf ("BG0(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 1: + printf ("BG1(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 2: + printf ("BG2(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 3: + printf ("BG3(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 4: + printf ("OBJ(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 5: + printf ("COL(%s)", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + } + + printf ("\nFixed colour: %02x%02x%02x\n", PPU.FixedColourRed, + PPU.FixedColourGreen, PPU.FixedColourBlue); +} + +static void WhatsMissing () +{ + printf ("Processor: "); + if (missing.emulate6502) + printf ("emulation mode, "); + if (missing.decimal_mode) + printf ("decimal mode,"); + if (missing.mv_8bit_index) + printf ("MVP/MVN with 8bit index registers and XH or YH > 0,"); + if (missing.mv_8bit_acc) + printf ("MVP/MVN with 8bit accumulator > 255"); + printf ("\nScreen modes used:"); + int i; + for (i = 0; i < 8; i++) + if (missing.modes[i]) + printf (" %d,", i); + printf ("\n"); + if (missing.interlace) + printf ("Interlace, "); + if (missing.pseudo_512) + printf ("Pseudo 512 pixels horizontal resolution, "); + if (missing.lines_239) + printf ("240 lines visible,"); + if (missing.sprite_double_height) + printf ("double-hight sprites,"); + printf ("\n"); + if (missing.mode7_fx) + printf ("Mode 7 rotation/scaling, "); + if (missing.matrix_read) + printf ("Mode 7 read matrix registers, "); + if (missing.mode7_flip) + printf ("Mode 7 flipping, "); + if (missing.mode7_bgmode) + printf ("Mode 7 priority per pixel, "); + if (missing.direct) + printf ("Direct 32000 colour mode"); + printf ("\n"); + if (missing.mosaic) + printf ("Mosaic effect, "); + if (missing.subscreen) + printf ("Subscreen enabled, "); + if (missing.subscreen_add) + printf ("Subscreen colour add, "); + if (missing.subscreen_sub) + printf ("Subscreen colour subtract, "); + if (missing.fixed_colour_add) + printf ("Fixed colour add, "); + if (missing.fixed_colour_sub) + printf ("Fixed colour subtract"); + printf ("\n"); + printf ("Window 1 enabled on:"); + PrintWindow (missing.window1); + printf ("\nWindow 2 enabled on:"); + PrintWindow (missing.window2); + printf ("\n"); + if (missing.bg_offset_read) + printf ("BG offset read, "); + if (missing.oam_address_read) + printf ("OAM address read,"); + if (missing.sprite_priority_rotation) + printf ("Sprite priority rotation, "); + if (missing.fast_rom) + printf ("Fast 3.58MHz ROM access enabled, "); + if (missing.matrix_multiply) + printf ("Matrix multiply 16bit by 8bit used"); + printf ("\n"); + if (missing.virq) + printf ("V-position IRQ used at line %d, ", missing.virq_pos); + if (missing.hirq) + printf ("H-position IRQ used at position %d, ", missing.hirq_pos); + printf ("\n"); + if (missing.h_v_latch) + printf ("H and V-Pos latched, "); + if (missing.h_counter_read) + printf ("H-Pos read, "); + if (missing.v_counter_read) + printf ("V-Pos read"); + printf ("\n"); + if (missing.oam_read) + printf ("OAM read, "); + if (missing.vram_read) + printf ("VRAM read, "); + if (missing.cgram_read) + printf ("CG-RAM read, "); + if (missing.wram_read) + printf ("WRAM read, "); + if (missing.dma_read) + printf ("DMA read,"); + if (missing.vram_inc) + printf ("VRAM inc: %d,", missing.vram_inc); + if (missing.vram_full_graphic_inc) + printf ("VRAM full graphic inc: %d,", missing.vram_full_graphic_inc); + printf ("\n"); + for (i = 0; i < 8; i++) + { + if (missing.hdma[i].used) + { + printf ("HDMA %d, 0x%02X%04X->0x21%02X %s ", i, + missing.hdma[i].abus_bank, missing.hdma[i].abus_address, + missing.hdma[i].bbus_address, + missing.hdma[i].indirect_address ? "indirect" : "absolute"); + if (missing.hdma[i].force_table_address_write) + printf ("Forced address write, "); + if (missing.hdma[i].force_table_address_read) + printf ("Current address read, "); + if (missing.hdma[i].line_count_write) + printf ("Line count write, "); + if (missing.hdma[i].line_count_read) + printf ("Line count read"); + printf ("\n"); + } + } + for (i = 0; i < 8; i++) + { + if (missing.dma_channels & (1 << i)) + { + printf ("DMA %d %d 0x%02X%04X->0x21%02X Num: %d %s\n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, + DMA[i].BAddress, DMA[i].TransferBytes, + DMA[i].AAddressFixed ? "fixed" : + (DMA[i].AAddressDecrement ? "dec" : "inc")); + } + } + if (missing.unknownppu_read) + printf ("Read from unknown PPU register: $%04X\n", missing.unknownppu_read); + if (missing.unknownppu_write) + printf ("Write to unknown PPU register: $%04X\n", missing.unknownppu_write); + if (missing.unknowncpu_read) + printf ("Read from unknown CPU register: $%04X\n", missing.unknowncpu_read); + if (missing.unknowncpu_write) + printf ("Write to unknown CPU register: $%04X\n", missing.unknowncpu_write); + if (missing.unknowndsp_read) + printf ("Read from unknown DSP register: $%04X\n", missing.unknowndsp_read); + if (missing.unknowndsp_write) + printf ("Write to unknown DSP register: $%04X\n", missing.unknowndsp_write); +} + +void S9xDoDebug () +{ + char Line[513]; + Debug.Dump.Bank = 0; + Debug.Dump.Address = 0; + Debug.Unassemble.Bank = 0; + Debug.Unassemble.Address = 0; + S9xTextMode (); + ProcessDebugCommand ("r"); + while (CPU.Flags & DEBUG_MODE_FLAG) + { + printf ("> "); + fflush (stdout); + fgets (Line, sizeof (Line) - 1, stdin); + Line [strlen (Line) - 1] = 0; + int32 Cycles = CPU.Cycles; + ProcessDebugCommand (Line); + CPU.Cycles = Cycles; + } + if (!(CPU.Flags & SINGLE_STEP_FLAG)) + S9xGraphicsMode (); +} + +void S9xTrace () +{ + if(!trace) + trace=fopen("trace.log", "a"); + char String [512]; + S9xOPrint (String, Registers.PB, Registers.PCw); + fprintf (trace, "%s\n", String); +} + +void S9xSA1Trace () +{ + char String [512]; + S9xSA1OPrint (String, SA1Registers.PB, SA1Registers.PCw); + fprintf (trace2, "%s\n", String); + fflush (trace2); +} + +void S9xTraceMessage (const char *s) +{ + if(s) + { + if (trace) + fprintf (trace, "%s\n", s); + else + if (trace2) + fprintf (trace2, "%s\n", s); + } +} + +extern "C" void TraceSA1 () +{ + SA1.Flags ^= TRACE_FLAG; + if (SA1.Flags & TRACE_FLAG) + { + printf ("SA1 CPU instruction tracing enabled.\n"); + if (trace2 == NULL) + trace2 = fopen ("trace_sa1.log", "wb"); + } + else + { + printf ("SA1 CPU instruction tracing disabled.\n"); + fclose (trace2); + trace2 = NULL; + } +} + +extern "C" void Trace () +{ + CPU.Flags ^= TRACE_FLAG; + if (CPU.Flags & TRACE_FLAG) + { + if (trace == NULL) + trace = fopen ("trace.log", "wb"); + printf ("CPU instruction tracing enabled.\n"); + } + else + { + printf ("CPU instruction tracing disabled.\n"); + fclose (trace); + trace = NULL; + } +} + +#endif + diff --git a/source/snes9x/logger.h b/source/snes9x/s9xdebug.h similarity index 92% rename from source/snes9x/logger.h rename to source/snes9x/s9xdebug.h index 7689d3a..289fd9d 100644 --- a/source/snes9x/logger.h +++ b/source/snes9x/s9xdebug.h @@ -159,12 +159,29 @@ **********************************************************************************/ -#ifndef _LOGGER_H_ -#define _LOGGER_H_ -void S9xResetLogger(void); -void S9xCloseLogger(void); -void S9xVideoLogger(void *, int, int, int, int); -void S9xAudioLogger(void *, int); +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +START_EXTERN_C +void S9xDoDebug (); +void S9xTrace (); +void S9xSA1Trace (); +void S9xTraceMessage (const char *); + +// Structures +struct SBreakPoint{ + bool8 Enabled; + uint8 Bank; + uint16 Address; +}; + +uint8 S9xOPrint( char *Line, uint8 Bank, uint16 Address); +uint8 S9xSA1OPrint( char *Line, uint8 Bank, uint16 Address); + +extern struct SBreakPoint S9xBreakpoint[ 6]; +extern char *S9xMnemonics[256]; +END_EXTERN_C #endif + diff --git a/source/snes9x/sa1.cpp b/source/snes9x/sa1.cpp index cc1c765..81d4163 100644 --- a/source/snes9x/sa1.cpp +++ b/source/snes9x/sa1.cpp @@ -159,936 +159,894 @@ **********************************************************************************/ + + #include "snes9x.h" -#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" -uint8 SA1OpenBus; +#include "sa1.h" -static void S9xSA1Reset (void); -static void S9xSA1SetBWRAMMemMap (uint8); -static void S9xSetSA1MemMap (uint32, uint8); -static void S9xSA1CharConv2 (void); -static void S9xSA1DMA (void); -static void S9xSA1ReadVariableLengthData (bool8, bool8); +uint8 SA1OpenBus; +static void S9xSA1CharConv2 (); +static void S9xSA1DMA (); +static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift); -void S9xSA1Init (void) +void S9xSA1Init () { - SA1.IRQActive = FALSE; - SA1.WaitingForInterrupt = FALSE; - SA1.Waiting = FALSE; - SA1.Flags = 0; - SA1.Executing = FALSE; - memset(&Memory.FillRAM[0x2200], 0, 0x200); - Memory.FillRAM[0x2200] = 0x20; - Memory.FillRAM[0x2220] = 0x00; - Memory.FillRAM[0x2221] = 0x01; - Memory.FillRAM[0x2222] = 0x02; - Memory.FillRAM[0x2223] = 0x03; - Memory.FillRAM[0x2228] = 0xff; - SA1.op1 = 0; - SA1.op2 = 0; - SA1.arithmetic_op = 0; - SA1.sum = 0; - SA1.overflow = FALSE; - SA1.S9xOpcodes = NULL; + SA1.NMIActive = FALSE; + SA1.IRQActive = FALSE; + SA1.WaitingForInterrupt = FALSE; + SA1.Waiting = FALSE; + SA1.Flags = 0; + SA1.Executing = FALSE; + memset (&Memory.FillRAM [0x2200], 0, 0x200); + Memory.FillRAM [0x2200] = 0x20; + Memory.FillRAM [0x2220] = 0x00; + Memory.FillRAM [0x2221] = 0x01; + Memory.FillRAM [0x2222] = 0x02; + Memory.FillRAM [0x2223] = 0x03; + Memory.FillRAM [0x2228] = 0xff; + SA1.op1 = 0; + SA1.op2 = 0; + SA1.arithmetic_op = 0; + SA1.sum = 0; + SA1.overflow = FALSE; + SA1.S9xOpcodes=NULL; } -static void S9xSA1Reset (void) +void S9xSA1Reset () { - SA1Registers.PBPC = 0; - SA1Registers.PB = 0; - SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8); - SA1Registers.D.W = 0; - SA1Registers.DB = 0; - SA1Registers.SH = 1; - SA1Registers.SL = 0xFF; - SA1Registers.XH = 0; - SA1Registers.YH = 0; - SA1Registers.P.W = 0; + SA1Registers.PBPC = 0; + SA1Registers.PB = 0; + SA1Registers.PCw = Memory.FillRAM [0x2203] | + (Memory.FillRAM [0x2204] << 8); + SA1Registers.D.W = 0; + SA1Registers.DB = 0; + SA1Registers.SH = 1; + SA1Registers.SL = 0xFF; + SA1Registers.XH = 0; + SA1Registers.YH = 0; + SA1Registers.P.W = 0; - SA1.ShiftedPB = 0; - SA1.ShiftedDB = 0; - SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); - SA1ClearFlags(Decimal); + SA1.ShiftedPB = 0; + SA1.ShiftedDB = 0; + SA1SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + SA1ClearFlags (Decimal); - SA1.WaitingForInterrupt = FALSE; - SA1.PCBase = NULL; - S9xSA1SetPCBase(SA1Registers.PBPC); - SA1.S9xOpcodes = S9xSA1OpcodesM1X1; - SA1.S9xOpLengths = S9xOpLengthsM1X1; + SA1.WaitingForInterrupt = FALSE; + SA1.PCBase = NULL; + S9xSA1SetPCBase (SA1Registers.PBPC); + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; - S9xSA1UnpackStatus(); - S9xSA1FixCycles(); - SA1.Executing = TRUE; - SA1.BWRAM = Memory.SRAM; - Memory.FillRAM[0x2225] = 0; + S9xSA1UnpackStatus(); + S9xSA1FixCycles (); + SA1.Executing = TRUE; + SA1.BWRAM = Memory.SRAM; + Memory.FillRAM [0x2225] = 0; } -static void S9xSA1SetBWRAMMemMap (uint8 val) +void S9xSA1SetBWRAMMemMap (uint8 val) { - if (val & 0x80) - { - for (int c = 0; c < 0x400; c += 16) - { - SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - } + int c; - SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; - } - else + if (val & 0x80) + { + for (c = 0; c < 0x400; c += 16) { - for (int c = 0; c < 0x400; c += 16) - { - SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; - SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; - SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; - SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; - } - - SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; + SA1.Map [c + 6] = SA1.Map [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.Map [c + 7] = SA1.Map [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.WriteMap [c + 6] = SA1.WriteMap [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.WriteMap [c + 7] = SA1.WriteMap [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; } + SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; + } + else + { + for (c = 0; c < 0x400; c += 16) + { + SA1.Map [c + 6] = SA1.Map [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; + SA1.Map [c + 7] = SA1.Map [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; + SA1.WriteMap [c + 6] = SA1.WriteMap [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; + SA1.WriteMap [c + 7] = SA1.WriteMap [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; + } + SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; + } } -void S9xSA1PostLoadState (void) +void S9xFixSA1AfterSnapshotLoad () { - SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; - SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; - - S9xSA1SetPCBase(SA1Registers.PBPC); - S9xSA1UnpackStatus(); - S9xSA1FixCycles(); - SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4; - Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000; - S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]); - - SA1.Waiting = (Memory.FillRAM[0x2200] & 0x60) != 0; - SA1.Executing = !SA1.Waiting; -} - -void S9xSA1ExecuteDuringSleep (void) -{ -#if 0 - if (SA1.Executing) - { - while (CPU.Cycles < CPU.NextEvent) - { - S9xSA1MainLoop(); - CPU.Cycles += TWO_CYCLES * 2; - } - } -#endif -} - -static void S9xSetSA1MemMap (uint32 which1, uint8 map) -{ - int start = which1 * 0x100 + 0xc00; - int start2 = which1 * 0x200; - - if (which1 >= 2) - start2 += 0x400; - - for (int c = 0; c < 0x100; c += 16) - { - uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; - for (int i = c; i < c + 16; i++) - Memory.Map[start + i] = SA1.Map[start + i] = block; - } - - for (int c = 0; c < 0x200; c += 16) - { - uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000]; - for (int i = c + 8; i < c + 16; i++) - Memory.Map[start2 + i] = SA1.Map[start2 + i] = block; - } -} - -uint8 S9xGetSA1 (uint32 address) -{ - switch (address) - { - case 0x2300: - return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); - - case 0x2301: - return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0)); - - case 0x2306: - return ((uint8) SA1.sum); - - case 0x2307: - return ((uint8) (SA1.sum >> 8)); - - case 0x2308: - return ((uint8) (SA1.sum >> 16)); - - case 0x2309: - return ((uint8) (SA1.sum >> 24)); - - case 0x230a: - return ((uint8) (SA1.sum >> 32)); - - case 0x230c: - return (Memory.FillRAM[0x230c]); - - case 0x230d: - { - uint8 byte = Memory.FillRAM[0x230d]; - - if (Memory.FillRAM[0x2258] & 0x80) - S9xSA1ReadVariableLengthData(TRUE, FALSE); - - return (byte); - } - - default: - printf("R: %04x\n", address); - break; - } - - return (Memory.FillRAM[address]); -} - -void S9xSetSA1 (uint8 byte, uint32 address) -{ - switch (address) - { - case 0x2200: - SA1.Waiting = (byte & 0x60) != 0; - //SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - - if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20)) - S9xSA1Reset(); - - if (byte & 0x80) - { - Memory.FillRAM[0x2301] |= 0x80; - if (Memory.FillRAM[0x220a] & 0x80) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - } - } - - if (byte & 0x10) - { - Memory.FillRAM[0x2301] |= 0x10; - #ifdef DEBUGGER - printf("###SA1 NMI\n"); - #endif - if (Memory.FillRAM[0x220a] & 0x10) - { - // - } - } - - break; - - case 0x2201: - if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80)) - S9xSetIRQ(SA1_IRQ_SOURCE); - - if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20)) - S9xSetIRQ(SA1_DMA_IRQ_SOURCE); - - break; - - case 0x2202: - if (byte & 0x80) - { - Memory.FillRAM[0x2300] &= ~0x80; - S9xClearIRQ(SA1_IRQ_SOURCE); - } - - if (byte & 0x20) - { - Memory.FillRAM[0x2300] &= ~0x20; - S9xClearIRQ(SA1_DMA_IRQ_SOURCE); - } - - break; - - case 0x2203: - //printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8)); - break; - - case 0x2204: - //printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]); - break; - - case 0x2205: - //printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8)); - break; - - case 0x2206: - //printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]); - break; - - case 0x2207: - //printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8)); - break; - - case 0x2208: - //printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]); - break; - - case 0x2209: - Memory.FillRAM[0x2209] = byte; - - if (byte & 0x80) - Memory.FillRAM[0x2300] |= 0x80; - - if (byte & Memory.FillRAM[0x2201] & 0x80) - S9xSetIRQ(SA1_IRQ_SOURCE); - - break; - - case 0x220a: - if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= TIMER_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10)) - { - #ifdef DEBUGGER - printf("###SA1 NMI\n"); - #endif - } - - break; - - case 0x220b: - if (byte & 0x80) - { - SA1.IRQActive &= ~SNES_IRQ_SOURCE; - Memory.FillRAM[0x2301] &= ~0x80; - } - - if (byte & 0x40) - { - SA1.IRQActive &= ~TIMER_IRQ_SOURCE; - Memory.FillRAM[0x2301] &= ~0x40; - } - - if (byte & 0x20) - { - SA1.IRQActive &= ~DMA_IRQ_SOURCE; - Memory.FillRAM[0x2301] &= ~0x20; - } - - if (byte & 0x10) // Clear NMI - Memory.FillRAM[0x2301] &= ~0x10; - - if (!SA1.IRQActive) - SA1.Flags &= ~IRQ_FLAG; - - break; - - case 0x220c: - //printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8)); - break; - - case 0x220d: - //printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]); - break; - - case 0x220e: - //printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8)); - break; - - case 0x220f: - //printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]); - break; - - case 0x2210: - #if 0 - printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); - printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); - printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); - #endif - break; - - case 0x2211: - //printf("Timer reset\n"); - break; - - case 0x2212: - //printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8)); - break; - - case 0x2213: - //printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]); - break; - - case 0x2214: - //printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8)); - break; - - case 0x2215: - //printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]); - break; - - case 0x2220: - case 0x2221: - case 0x2222: - case 0x2223: - //printf("MMC: %02x\n", byte); - S9xSetSA1MemMap(address - 0x2220, byte); - break; - - case 0x2224: - //printf("BWRAM image SNES %02x -> 0x6000\n", byte); - Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; - break; - - case 0x2225: - //printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]); - if (byte != Memory.FillRAM[0x2225]) - S9xSA1SetBWRAMMemMap(byte); - break; - - case 0x2226: - //printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2227: - //printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2228: - //printf("BW-RAM write protect area %02x\n", byte); - break; - - case 0x2229: - //printf("I-RAM SNES write protect area %02x\n", byte); - break; - - case 0x222a: - //printf("I-RAM SA1 write protect area %02x\n", byte); - break; - - case 0x2230: - #if 0 - printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); - printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); - printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); - printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); - printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); - printf("DMA source %s\n", DMAsource[byte & 3]); - #endif - break; - - case 0x2231: - if (byte & 0x80) - SA1.in_char_dma = FALSE; - #if 0 - printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); - printf("DMA colour mode %d\n", byte & 3); - printf("virtual VRAM width %d\n", (byte >> 2) & 7); - #endif - break; - - case 0x2232: - case 0x2233: - case 0x2234: - Memory.FillRAM[address] = byte; - #if 0 - printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16)); - #endif - break; - - case 0x2235: - Memory.FillRAM[0x2235] = byte; - break; - - case 0x2236: - Memory.FillRAM[0x2236] = byte; - - if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM - S9xSA1DMA(); - else - if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) - { - Memory.FillRAM[0x2300] |= 0x20; - if (Memory.FillRAM[0x2201] & 0x20) - S9xSetIRQ(SA1_DMA_IRQ_SOURCE); - SA1.in_char_dma = TRUE; - } - - break; - - case 0x2237: - Memory.FillRAM[0x2237] = byte; - - if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM - S9xSA1DMA(); - #if 0 - printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16)); - #endif - break; - - case 0x2238: - case 0x2239: - Memory.FillRAM[address] = byte; - #if 0 - printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8)); - #endif - break; - - case 0x223f: - //printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); - SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; - break; - - case 0x2240: - case 0x2241: - case 0x2242: - case 0x2243: - case 0x2244: - case 0x2245: - case 0x2246: - case 0x2247: - case 0x2248: - case 0x2249: - case 0x224a: - case 0x224b: - case 0x224c: - case 0x224d: - case 0x224e: - #if 0 - if (!(SA1.Flags & TRACE_FLAG)) - { - TraceSA1(); - Trace(); - } - #endif - Memory.FillRAM[address] = byte; - break; - - case 0x224f: - Memory.FillRAM[0x224f] = byte; - - if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled - { - memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16); - SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; - if ((SA1.in_char_dma & 3) == 0) - S9xSA1CharConv2(); - } - - break; - - case 0x2250: - if (byte & 2) - SA1.sum = 0; - SA1.arithmetic_op = byte & 3; - break; - - case 0x2251: - SA1.op1 = (SA1.op1 & 0xff00) | byte; - break; - - case 0x2252: - SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); - break; - - case 0x2253: - SA1.op2 = (SA1.op2 & 0xff00) | byte; - break; - - case 0x2254: - SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); - - switch (SA1.arithmetic_op) - { - case 0: // multiply - SA1.sum = SA1.op1 * SA1.op2; - break; - - case 1: // divide - if (SA1.op2 == 0) - SA1.sum = SA1.op1 << 16; - else - SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); - break; - - case 2: // cumulative sum - default: - SA1.sum += SA1.op1 * SA1.op2; - if (SA1.sum & ((int64) 0xffffff << 32)) - SA1.overflow = TRUE; - break; - } - - break; - - case 0x2258: // Variable bit-field length/auto inc/start. - Memory.FillRAM[0x2258] = byte; - S9xSA1ReadVariableLengthData(TRUE, FALSE); - return; - - case 0x2259: // Variable bit-field start address - case 0x225a: - case 0x225b: - Memory.FillRAM[address] = byte; - // XXX: ??? - SA1.variable_bit_pos = 0; - S9xSA1ReadVariableLengthData(FALSE, TRUE); - return; - - default: - //printf("W: %02x->%04x\n", byte, address); - break; - } - - if (address >= 0x2200 && address <= 0x22ff) - Memory.FillRAM[address] = byte; -} - -static void S9xSA1CharConv2 (void) -{ - uint32 dest = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8); - uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; - int depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; - int bytes_per_char = 8 * depth; - uint8 *p = &Memory.FillRAM[0x3000] + dest + offset * bytes_per_char; - uint8 *q = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; - - switch (depth) - { - case 2: - case 4: - break; - - case 8: - for (int l = 0; l < 8; l++, q += 8) - { - for (int b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - - p += 2; - } - - break; - } -} - -static void S9xSA1DMA (void) -{ - uint32 src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16); - uint32 dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16); - uint32 len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8); - uint8 *s, *d; - - switch (Memory.FillRAM[0x2230] & 3) - { - case 0: // ROM - s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)]; - if (s >= (uint8 *) CMemory::MAP_LAST) - s += (src & 0xffff); - else - s = Memory.ROM + (src & 0xffff); - break; - - case 1: // BW-RAM - src &= Memory.SRAMMask; - len &= Memory.SRAMMask; - s = Memory.SRAM + src; - break; - - default: - case 2: - src &= 0x3ff; - len &= 0x3ff; - s = &Memory.FillRAM[0x3000] + src; - break; - } - - if (Memory.FillRAM[0x2230] & 4) - { - dst &= Memory.SRAMMask; - len &= Memory.SRAMMask; - d = Memory.SRAM + dst; - } - else - { - dst &= 0x3ff; - len &= 0x3ff; - d = &Memory.FillRAM[0x3000] + dst; - } - - memmove(d, s, len); - Memory.FillRAM[0x2301] |= 0x20; - - if (Memory.FillRAM[0x220a] & 0x20) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } -} - -static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) -{ - uint32 addr = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16); - uint8 shift = Memory.FillRAM[0x2258] & 15; - - if (no_shift) - shift = 0; - else - if (shift == 0) - shift = 16; - - uint8 s = shift + SA1.variable_bit_pos; - - if (s >= 16) - { - addr += (s >> 4) << 1; - s &= 15; - } - - uint32 data = S9xSA1GetWord(addr) | (S9xSA1GetWord(addr + 2) << 16); - - data >>= s; - Memory.FillRAM[0x230c] = (uint8) data; - Memory.FillRAM[0x230d] = (uint8) (data >> 8); - - if (inc) - { - SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; - Memory.FillRAM[0x2259] = (uint8) addr; - Memory.FillRAM[0x225a] = (uint8) (addr >> 8); - Memory.FillRAM[0x225b] = (uint8) (addr >> 16); - } + SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; + SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; + + S9xSA1SetPCBase (SA1Registers.PBPC); + S9xSA1UnpackStatus (); + S9xSA1FixCycles (); + SA1.VirtualBitmapFormat = (Memory.FillRAM [0x223f] & 0x80) ? 2 : 4; + Memory.BWRAM = Memory.SRAM + (Memory.FillRAM [0x2224] & 7) * 0x2000; + S9xSA1SetBWRAMMemMap (Memory.FillRAM [0x2225]); + + SA1.Waiting = (Memory.FillRAM [0x2200] & 0x60) != 0; + SA1.Executing = !SA1.Waiting; } uint8 S9xSA1GetByte (uint32 address) { - uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + uint8 *GetAddress = SA1.Map [(address&0xffffff) >> MEMMAP_SHIFT]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (*(GetAddress + (address & 0xffff))); - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (*(GetAddress + (address & 0xffff))); + switch ((pint) GetAddress) + { + case CMemory::MAP_PPU: + return (S9xGetSA1 (address & 0xffff)); + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + return (*(Memory.SRAM + (address & 0xffff))); + case CMemory::MAP_BWRAM: + return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + return ((Memory.SRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((Memory.SRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + return ((SA1.BWRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((SA1.BWRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); - switch ((pint) GetAddress) - { - case CMemory::MAP_PPU: - return (S9xGetSA1(address & 0xffff)); - - case CMemory::MAP_LOROM_SRAM: - case CMemory::MAP_SA1RAM: - return (*(Memory.SRAM + (address & 0xffff))); - - case CMemory::MAP_BWRAM: - return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); - - case CMemory::MAP_BWRAM_BITMAP: - address -= 0x600000; - if (SA1.VirtualBitmapFormat == 2) - return ((Memory.SRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); - else - return ((Memory.SRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); - - case CMemory::MAP_BWRAM_BITMAP2: - address = (address & 0xffff) - 0x6000; - if (SA1.VirtualBitmapFormat == 2) - return ((SA1.BWRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); - else - return ((SA1.BWRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); - - default: - return (SA1OpenBus); - } + case CMemory::MAP_DEBUG: + default: +#ifdef DEBUGGER +// printf ("R(B) %06x\n", address); +#endif + return SA1OpenBus; + } } uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) { - PC_t a; - - SA1OpenBus = S9xSA1GetByte(address); - - switch (w) - { - case WRAP_PAGE: - a.xPBPC = address; - a.B.xPCl++; - return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); - - case WRAP_BANK: - a.xPBPC = address; - a.W.xPC++; - return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); - - case WRAP_NONE: - default: - return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8)); - } + SA1OpenBus = S9xSA1GetByte (address); + switch(w){ + case WRAP_PAGE: + { + PC_t a; + a.xPBPC = address; + a.B.xPCl++; + return (SA1OpenBus | (S9xSA1GetByte (a.xPBPC) << 8)); + } + case WRAP_BANK: + { + PC_t a; + a.xPBPC = address; + a.W.xPC++; + return (SA1OpenBus | (S9xSA1GetByte (a.xPBPC) << 8)); + } + case WRAP_NONE: + default: + return (SA1OpenBus | (S9xSA1GetByte (address + 1) << 8)); + } } void S9xSA1SetByte (uint8 byte, uint32 address) { - uint8 *SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT]; + uint8 *Setaddress = SA1.WriteMap [(address&0xffffff) >> MEMMAP_SHIFT]; - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + if (Setaddress >= (uint8 *) CMemory::MAP_LAST) + { + *(Setaddress + (address & 0xffff)) = byte; + return; + } + + switch ((pint) Setaddress) + { + case CMemory::MAP_PPU: + S9xSetSA1 (byte, address & 0xffff); + return; + case CMemory::MAP_SA1RAM: + case CMemory::MAP_LOROM_SRAM: + *(Memory.SRAM + (address & 0xffff)) = byte; + return; + case CMemory::MAP_BWRAM: + *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; + return; + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) { - *(SetAddress + (address & 0xffff)) = byte; - return; + uint8 *ptr = &Memory.SRAM [(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); } - - switch ((pint) SetAddress) + else { - case CMemory::MAP_PPU: - S9xSetSA1(byte, address & 0xffff); - return; - - case CMemory::MAP_LOROM_SRAM: - case CMemory::MAP_SA1RAM: - *(Memory.SRAM + (address & 0xffff)) = byte; - return; - - case CMemory::MAP_BWRAM: - *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; - return; - - case CMemory::MAP_BWRAM_BITMAP: - address -= 0x600000; - if (SA1.VirtualBitmapFormat == 2) - { - uint8 *ptr = &Memory.SRAM[(address >> 2) & 0xffff]; - *ptr &= ~(3 << ((address & 3) << 1)); - *ptr |= (byte & 3) << ((address & 3) << 1); - } - else - { - uint8 *ptr = &Memory.SRAM[(address >> 1) & 0xffff]; - *ptr &= ~(15 << ((address & 1) << 2)); - *ptr |= (byte & 15) << ((address & 1) << 2); - } - - return; - - case CMemory::MAP_BWRAM_BITMAP2: - address = (address & 0xffff) - 0x6000; - if (SA1.VirtualBitmapFormat == 2) - { - uint8 *ptr = &SA1.BWRAM[(address >> 2) & 0xffff]; - *ptr &= ~(3 << ((address & 3) << 1)); - *ptr |= (byte & 3) << ((address & 3) << 1); - } - else - { - uint8 *ptr = &SA1.BWRAM[(address >> 1) & 0xffff]; - *ptr &= ~(15 << ((address & 1) << 2)); - *ptr |= (byte & 15) << ((address & 1) << 2); - } - - return; - - default: - return; + uint8 *ptr = &Memory.SRAM [(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); } + break; + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &SA1.BWRAM [(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &SA1.BWRAM [(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + default: + return; + } } void S9xSA1SetWord (uint16 Word, uint32 address, enum s9xwrap_t w, enum s9xwriteorder_t o) { - PC_t a; - - if (!o) - S9xSA1SetByte((uint8) Word, address); - - switch (w) - { - case WRAP_PAGE: - a.xPBPC = address; - a.B.xPCl++; - S9xSA1SetByte(Word >> 8, a.xPBPC); - break; - - case WRAP_BANK: - a.xPBPC = address; - a.W.xPC++; - S9xSA1SetByte(Word >> 8, a.xPBPC); - break; - - case WRAP_NONE: - default: - S9xSA1SetByte(Word >> 8, address + 1); - break; - } - - if (o) - S9xSA1SetByte((uint8) Word, address); + if(!o) S9xSA1SetByte ((uint8) Word, address); + switch(w){ + case WRAP_PAGE: + { + PC_t a; + a.xPBPC = address; + a.B.xPCl++; + S9xSA1SetByte (Word>>8, a.xPBPC); + } + case WRAP_BANK: + { + PC_t a; + a.xPBPC = address; + a.W.xPC++; + S9xSA1SetByte (Word>>8, a.xPBPC); + } + case WRAP_NONE: + default: + S9xSA1SetByte (Word>>8, address+1); + } + if(o) S9xSA1SetByte ((uint8) Word, address); } void S9xSA1SetPCBase (uint32 address) { - SA1Registers.PBPC = address & 0xffffff; - SA1.ShiftedPB = address & 0xff0000; + SA1Registers.PBPC = address&0xffffff; + SA1.ShiftedPB = address&0xff0000; - uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + uint8 *GetAddress = SA1.Map [(address&0xffffff) >> MEMMAP_SHIFT]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + SA1.PCBase = GetAddress; + return; + } - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - SA1.PCBase = GetAddress; - return; - } + switch ((pint) GetAddress) + { + case CMemory::MAP_SA1RAM: + SA1.PCBase = Memory.SRAM; + return; - switch ((pint) GetAddress) - { - case CMemory::MAP_LOROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - SA1.PCBase = NULL; - else - SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff); - return; + case CMemory::MAP_LOROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK){ + SA1.PCBase = NULL; + } else { + SA1.PCBase = (Memory.SRAM + ((((address&0xFF0000)>>1)|(address&0x7FFF)) & Memory.SRAMMask)) - (address&0xffff); + } + return; - case CMemory::MAP_HIROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - SA1.PCBase = NULL; - else - SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff); - return; + case CMemory::MAP_BWRAM: + SA1.PCBase = SA1.BWRAM - 0x6000 - (address&0x8000); + return; - case CMemory::MAP_BWRAM: - SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000); - return; + case CMemory::MAP_HIROM_SRAM: + if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK){ + SA1.PCBase = NULL; + } else { + SA1.PCBase = (Memory.SRAM + (((address&0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address&0xffff); + } + return; - case CMemory::MAP_SA1RAM: - SA1.PCBase = Memory.SRAM; - return; + case CMemory::MAP_DEBUG: +#ifdef DEBUGGER + printf ("SBP %06x\n", address); +#endif - default: - SA1.PCBase = NULL; - return; - } + default: + case CMemory::MAP_NONE: + SA1.PCBase = NULL; + return; + } } + +void S9xSA1ExecuteDuringSleep () +{ +#if 0 + if (SA1.Executing) + { + while (CPU.Cycles < CPU.NextEvent) + { + S9xSA1MainLoop (); + CPU.Cycles += TWO_CYCLES * 2; + } + } +#endif +} + +void S9xSetSA1MemMap (uint32 which1, uint8 map) +{ + int c; + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; + + if (which1 >= 2) + start2 += 0x400; + + for (c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 12)]; + int i; + + for (i = c; i < c + 16; i++) + Memory.Map [start + i] = SA1.Map [start + i] = block; + } + + for (c = 0; c < 0x200; c += 16) + { + uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 11) - 0x8000]; + int i; + + for (i = c + 8; i < c + 16; i++) + Memory.Map [start2 + i] = SA1.Map [start2 + i] = block; + } +} + +uint8 S9xGetSA1 (uint32 address) +{ +// printf ("R: %04x\n", address); + switch (address) + { + case 0x2300: + return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | + (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); + case 0x2301: + return ((Memory.FillRAM [0x2200] & 0xf) | + (Memory.FillRAM [0x2301] & 0xf0)); + case 0x2306: + return ((uint8) SA1.sum); + case 0x2307: + return ((uint8) (SA1.sum >> 8)); + case 0x2308: + return ((uint8) (SA1.sum >> 16)); + case 0x2309: + return ((uint8) (SA1.sum >> 24)); + case 0x230a: + return ((uint8) (SA1.sum >> 32)); + case 0x230c: + return (Memory.FillRAM [0x230c]); + case 0x230d: + { + uint8 byte = Memory.FillRAM [0x230d]; + + if (Memory.FillRAM [0x2258] & 0x80) + { + S9xSA1ReadVariableLengthData (TRUE, FALSE); + } + return (byte); + } + default: + printf ("R: %04x\n", address); + break; + } + return (Memory.FillRAM [address]); +} + +void S9xSetSA1 (uint8 byte, uint32 address) +{ +//printf ("W: %02x -> %04x\n", byte, address); + switch (address) + { + case 0x2200: + SA1.Waiting = (byte & 0x60) != 0; +// SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + + if (!(byte & 0x20) && (Memory.FillRAM [0x2200] & 0x20)) + { + S9xSA1Reset (); + } + if (byte & 0x80) + { + Memory.FillRAM [0x2301] |= 0x80; + if (Memory.FillRAM [0x220a] & 0x80) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + } + } + if (byte & 0x10) + { + Memory.FillRAM [0x2301] |= 0x10; +#ifdef DEBUGGER + printf ("###SA1 NMI\n"); +#endif + if (Memory.FillRAM [0x220a] & 0x10) + { + } + } + break; + + case 0x2201: + if (((byte ^ Memory.FillRAM [0x2201]) & 0x80) && + (Memory.FillRAM [0x2300] & byte & 0x80)) + { + S9xSetIRQ (SA1_IRQ_SOURCE); + } + if (((byte ^ Memory.FillRAM [0x2201]) & 0x20) && + (Memory.FillRAM [0x2300] & byte & 0x20)) + { + S9xSetIRQ (SA1_DMA_IRQ_SOURCE); + } + break; + case 0x2202: + if (byte & 0x80) + { + Memory.FillRAM [0x2300] &= ~0x80; + S9xClearIRQ (SA1_IRQ_SOURCE); + } + if (byte & 0x20) + { + Memory.FillRAM [0x2300] &= ~0x20; + S9xClearIRQ (SA1_DMA_IRQ_SOURCE); + } + break; + case 0x2203: +// printf ("SA1 reset vector: %04x\n", byte | (Memory.FillRAM [0x2204] << 8)); + break; + case 0x2204: +// printf ("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM [0x2203]); + break; + + case 0x2205: +// printf ("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM [0x2206] << 8)); + break; + case 0x2206: +// printf ("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM [0x2205]); + break; + + case 0x2207: +// printf ("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM [0x2208] << 8)); + break; + case 0x2208: +// printf ("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM [0x2207]); + break; + + case 0x2209: + Memory.FillRAM [0x2209] = byte; + if (byte & 0x80) + Memory.FillRAM [0x2300] |= 0x80; + + if (byte & Memory.FillRAM [0x2201] & 0x80) + { + S9xSetIRQ (SA1_IRQ_SOURCE); + } + break; + case 0x220a: + if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && + (Memory.FillRAM [0x2301] & byte & 0x80)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && + (Memory.FillRAM [0x2301] & byte & 0x40)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= TIMER_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && + (Memory.FillRAM [0x2301] & byte & 0x20)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x10) && + (Memory.FillRAM [0x2301] & byte & 0x10)) + { +#ifdef DEBUGGER + printf ("###SA1 NMI\n"); +#endif + } + break; + case 0x220b: + if (byte & 0x80) + { + SA1.IRQActive &= ~SNES_IRQ_SOURCE; + Memory.FillRAM [0x2301] &= ~0x80; + } + if (byte & 0x40) + { + SA1.IRQActive &= ~TIMER_IRQ_SOURCE; + Memory.FillRAM [0x2301] &= ~0x40; + } + if (byte & 0x20) + { + SA1.IRQActive &= ~DMA_IRQ_SOURCE; + Memory.FillRAM [0x2301] &= ~0x20; + } + if (byte & 0x10) + { + // Clear NMI + Memory.FillRAM [0x2301] &= ~0x10; + } + if (!SA1.IRQActive) + SA1.Flags &= ~IRQ_FLAG; + break; + case 0x220c: +// printf ("SNES NMI vector: %04x\n", byte | (Memory.FillRAM [0x220d] << 8)); + break; + case 0x220d: +// printf ("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM [0x220c]); + break; + + case 0x220e: +// printf ("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM [0x220f] << 8)); + break; + case 0x220f: +// printf ("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM [0x220e]); + break; + + case 0x2210: +#if 0 + printf ("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); + printf ("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); + printf ("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); +#endif + break; + case 0x2211: +// printf ("Timer reset\n"); + break; + case 0x2212: +// printf ("H-Timer %04x\n", byte | (Memory.FillRAM [0x2213] << 8)); + break; + case 0x2213: +// printf ("H-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2212]); + break; + case 0x2214: +// printf ("V-Timer %04x\n", byte | (Memory.FillRAM [0x2215] << 8)); + break; + case 0x2215: +// printf ("V-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2214]); + break; + case 0x2220: + case 0x2221: + case 0x2222: + case 0x2223: + S9xSetSA1MemMap (address - 0x2220, byte); +// printf ("MMC: %02x\n", byte); + break; + case 0x2224: +// printf ("BWRAM image SNES %02x -> 0x6000\n", byte); + Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; + break; + case 0x2225: +// printf ("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM [address]); + if (byte != Memory.FillRAM [address]) + S9xSA1SetBWRAMMemMap (byte); + break; + case 0x2226: +// printf ("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + case 0x2227: +// printf ("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + + case 0x2228: +// printf ("BW-RAM write protect area %02x\n", byte); + break; + case 0x2229: +// printf ("I-RAM SNES write protect area %02x\n", byte); + break; + case 0x222a: +// printf ("I-RAM SA1 write protect area %02x\n", byte); + break; + case 0x2230: +#if 0 + printf ("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); + printf ("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); + printf ("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); + printf ("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); + printf ("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); + printf ("DMA source %s\n", DMAsource [byte & 3]); +#endif + break; + case 0x2231: + if (byte & 0x80) + SA1.in_char_dma = FALSE; +#if 0 + printf ("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); + printf ("DMA colour mode %d\n", byte & 3); + printf ("virtual VRAM width %d\n", (byte >> 2) & 7); +#endif + break; + case 0x2232: + case 0x2233: + case 0x2234: + Memory.FillRAM [address] = byte; +#if 0 + printf ("DMA source start %06x\n", + Memory.FillRAM [0x2232] | (Memory.FillRAM [0x2233] << 8) | + (Memory.FillRAM [0x2234] << 16)); +#endif + break; + case 0x2235: + Memory.FillRAM [address] = byte; + break; + case 0x2236: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xa4) == 0x80) + { + // Normal DMA to I-RAM + S9xSA1DMA (); + } + else + if ((Memory.FillRAM [0x2230] & 0xb0) == 0xb0) + { + Memory.FillRAM [0x2300] |= 0x20; + if (Memory.FillRAM [0x2201] & 0x20) + S9xSetIRQ (SA1_DMA_IRQ_SOURCE); + SA1.in_char_dma = TRUE; + } + break; + case 0x2237: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xa4) == 0x84) + { + // Normal DMA to BW-RAM + S9xSA1DMA (); + } +#if 0 + printf ("DMA dest address %06x\n", + Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8) | + (Memory.FillRAM [0x2237] << 16)); +#endif + break; + case 0x2238: + case 0x2239: + Memory.FillRAM [address] = byte; +#if 0 + printf ("DMA length %04x\n", + Memory.FillRAM [0x2238] | (Memory.FillRAM [0x2239] << 8)); +#endif + break; + case 0x223f: + SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; + //printf ("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); + break; + + case 0x2240: case 0x2241: case 0x2242: case 0x2243: + case 0x2244: case 0x2245: case 0x2246: case 0x2247: + case 0x2248: case 0x2249: case 0x224a: case 0x224b: + case 0x224c: case 0x224d: case 0x224e: +#if 0 + if (!(SA1.Flags & TRACE_FLAG)) + { + TraceSA1 (); + Trace (); + } +#endif + Memory.FillRAM [address] = byte; + break; + + case 0x224f: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) + { + // Char conversion 2 DMA enabled + memmove (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, + &Memory.FillRAM [0x2240], 16); + SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; + if ((SA1.in_char_dma & 3) == 0) + { + S9xSA1CharConv2 (); + } + } + break; + case 0x2250: + if (byte & 2) + SA1.sum = 0; + SA1.arithmetic_op = byte & 3; + break; + + case 0x2251: + SA1.op1 = (SA1.op1 & 0xff00) | byte; + break; + case 0x2252: + SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); + break; + case 0x2253: + SA1.op2 = (SA1.op2 & 0xff00) | byte; + break; + case 0x2254: + SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); + switch (SA1.arithmetic_op) + { + case 0: // multiply + SA1.sum = SA1.op1 * SA1.op2; + break; + case 1: // divide + if (SA1.op2 == 0) + SA1.sum = SA1.op1 << 16; + else + { + SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | + ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); + } + break; + case 2: + default: // cumulative sum + SA1.sum += SA1.op1 * SA1.op2; + if (SA1.sum & ((int64) 0xffffff << 32)) + SA1.overflow = TRUE; + break; + } + break; + case 0x2258: // Variable bit-field length/auto inc/start. + Memory.FillRAM [0x2258] = byte; + S9xSA1ReadVariableLengthData (TRUE, FALSE); + return; + case 0x2259: + case 0x225a: + case 0x225b: // Variable bit-field start address + Memory.FillRAM [address] = byte; + // XXX: ??? + SA1.variable_bit_pos = 0; + S9xSA1ReadVariableLengthData (FALSE, TRUE); + return; + default: +// printf ("W: %02x->%04x\n", byte, address); + break; + } + if (address >= 0x2200 && address <= 0x22ff) + Memory.FillRAM [address] = byte; +} + +static void S9xSA1CharConv2 () +{ + uint32 dest = Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8); + uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; + int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : + (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; + int bytes_per_char = 8 * depth; + uint8 *p = &Memory.FillRAM [0x3000] + dest + offset * bytes_per_char; + uint8 *q = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; + + switch (depth) + { + case 2: + break; + case 4: + break; + case 8: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + p += 2; + } + break; + } +} + +static void S9xSA1DMA () +{ + uint32 src = Memory.FillRAM [0x2232] | + (Memory.FillRAM [0x2233] << 8) | + (Memory.FillRAM [0x2234] << 16); + uint32 dst = Memory.FillRAM [0x2235] | + (Memory.FillRAM [0x2236] << 8) | + (Memory.FillRAM [0x2237] << 16); + uint32 len = Memory.FillRAM [0x2238] | + (Memory.FillRAM [0x2239] << 8); + + uint8 *s; + uint8 *d; + + switch (Memory.FillRAM [0x2230] & 3) + { + case 0: // ROM + s = SA1.Map [((src&0xffffff) >> MEMMAP_SHIFT)]; + if (s >= (uint8 *) CMemory::MAP_LAST) + s += (src & 0xffff); + else + s = Memory.ROM + (src & 0xffff); + break; + case 1: // BW-RAM + src &= Memory.SRAMMask; + len &= Memory.SRAMMask; + s = Memory.SRAM + src; + break; + default: + case 2: + src &= 0x3ff; + len &= 0x3ff; + s = &Memory.FillRAM [0x3000] + src; + break; + } + + if (Memory.FillRAM [0x2230] & 4) + { + dst &= Memory.SRAMMask; + len &= Memory.SRAMMask; + d = Memory.SRAM + dst; + } + else + { + dst &= 0x3ff; + len &= 0x3ff; + d = &Memory.FillRAM [0x3000] + dst; + } + memmove (d, s, len); + Memory.FillRAM [0x2301] |= 0x20; + + if (Memory.FillRAM [0x220a] & 0x20) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } +} + +void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) +{ + uint32 addr = Memory.FillRAM [0x2259] | + (Memory.FillRAM [0x225a] << 8) | + (Memory.FillRAM [0x225b] << 16); + uint8 shift = Memory.FillRAM [0x2258] & 15; + + if (no_shift) + shift = 0; + else + if (shift == 0) + shift = 16; + + uint8 s = shift + SA1.variable_bit_pos; + + if (s >= 16) + { + addr += (s >> 4) << 1; + s &= 15; + } + uint32 data = S9xSA1GetWord (addr) | + (S9xSA1GetWord (addr + 2) << 16); + + data >>= s; + Memory.FillRAM [0x230c] = (uint8) data; + Memory.FillRAM [0x230d] = (uint8) (data >> 8); + if (inc) + { + SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; + Memory.FillRAM [0x2259] = (uint8) addr; + Memory.FillRAM [0x225a] = (uint8) (addr >> 8); + Memory.FillRAM [0x225b] = (uint8) (addr >> 16); + } +} + diff --git a/source/snes9x/sa1.h b/source/snes9x/sa1.h index 5890cab..96e1194 100644 --- a/source/snes9x/sa1.h +++ b/source/snes9x/sa1.h @@ -159,149 +159,150 @@ **********************************************************************************/ -#ifndef _SA1_H_ -#define _SA1_H_ -struct SSA1Registers -{ - uint8 DB; - pair P; - pair A; - pair D; - pair S; - pair X; - pair Y; - PC_t PC; + +#ifndef _sa1_h_ +#define _sa1_h_ + +#include "memmap.h" + +struct SSA1Registers { + uint8 DB; + pair P; + pair A; + pair D; + pair S; + pair X; + pair Y; + PC_t PC; }; -struct SSA1 -{ - struct SOpcodes *S9xOpcodes; - uint8 *S9xOpLengths; - uint8 _Carry; - uint8 _Zero; - uint8 _Negative; - uint8 _Overflow; - bool8 CPUExecuting; - uint32 ShiftedPB; - uint32 ShiftedDB; - - uint32 Flags; - uint8 *PCBase; - bool8 IRQActive; - bool8 Waiting; - bool8 WaitingForInterrupt; - uint32 WaitAddress; - uint32 WaitCounter; - uint32 PBPCAtOpcodeStart; - uint8 *WaitByteAddress1; - uint8 *WaitByteAddress2; - - uint8 *Map[MEMMAP_NUM_BLOCKS]; - uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; - uint8 *BWRAM; - - bool8 Executing; - bool8 overflow; - bool8 in_char_dma; - int16 op1; - int16 op2; - int32 arithmetic_op; - int64 sum; - uint8 VirtualBitmapFormat; - uint8 variable_bit_pos; +struct SSA1 { + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + uint32 Flags; + bool8 Executing; + bool8 NMIActive; + bool8 IRQActive; + bool8 WaitingForInterrupt; + bool8 Waiting; +// uint8 WhichEvent; + uint8 *PCBase; + uint8 *BWRAM; + uint32 PBPCAtOpcodeStart; + uint32 WaitAddress; + uint32 WaitCounter; + uint8 *WaitByteAddress1; + uint8 *WaitByteAddress2; +// int32 Cycles; +// int32 NextEvent; +// int32 V_Counter; + uint8 *Map [MEMMAP_NUM_BLOCKS]; + uint8 *WriteMap [MEMMAP_NUM_BLOCKS]; + int16 op1; + int16 op2; + int32 arithmetic_op; + int64 sum; + bool8 overflow; + uint8 VirtualBitmapFormat; + bool8 in_char_dma; + uint8 variable_bit_pos; }; -#define SA1CheckCarry() (SA1._Carry) -#define SA1CheckZero() (SA1._Zero == 0) -#define SA1CheckIRQ() (SA1Registers.PL & IRQ) -#define SA1CheckDecimal() (SA1Registers.PL & Decimal) -#define SA1CheckIndex() (SA1Registers.PL & IndexFlag) -#define SA1CheckMemory() (SA1Registers.PL & MemoryFlag) -#define SA1CheckOverflow() (SA1._Overflow) -#define SA1CheckNegative() (SA1._Negative & 0x80) -#define SA1CheckEmulation() (SA1Registers.P.W & Emulation) +#define SA1CheckZero() (SA1._Zero == 0) +#define SA1CheckCarry() (SA1._Carry) +#define SA1CheckIRQ() (SA1Registers.PL & IRQ) +#define SA1CheckDecimal() (SA1Registers.PL & Decimal) +#define SA1CheckIndex() (SA1Registers.PL & IndexFlag) +#define SA1CheckMemory() (SA1Registers.PL & MemoryFlag) +#define SA1CheckOverflow() (SA1._Overflow) +#define SA1CheckNegative() (SA1._Negative & 0x80) +#define SA1CheckEmulation() (SA1Registers.P.W & Emulation) -#define SA1SetFlags(f) (SA1Registers.P.W |= (f)) -#define SA1ClearFlags(f) (SA1Registers.P.W &= ~(f)) -#define SA1CheckFlag(f) (SA1Registers.PL & (f)) +#define SA1ClearFlags(f) (SA1Registers.P.W &= ~(f)) +#define SA1SetFlags(f) (SA1Registers.P.W |= (f)) +#define SA1CheckFlag(f) (SA1Registers.PL & (f)) -extern struct SSA1Registers SA1Registers; -extern struct SSA1 SA1; -extern uint8 SA1OpenBus; -extern struct SOpcodes S9xSA1OpcodesM1X1[256]; -extern struct SOpcodes S9xSA1OpcodesM1X0[256]; -extern struct SOpcodes S9xSA1OpcodesM0X1[256]; -extern struct SOpcodes S9xSA1OpcodesM0X0[256]; -extern uint8 S9xOpLengthsM1X1[256]; -extern uint8 S9xOpLengthsM1X0[256]; -extern uint8 S9xOpLengthsM0X1[256]; -extern uint8 S9xOpLengthsM0X0[256]; +START_EXTERN_C uint8 S9xSA1GetByte (uint32); +uint16 S9xSA1GetWord (uint32, enum s9xwrap_t w=WRAP_NONE); void S9xSA1SetByte (uint8, uint32); -uint16 S9xSA1GetWord (uint32, enum s9xwrap_t w = WRAP_NONE); -void S9xSA1SetWord (uint16, uint32, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01); +void S9xSA1SetWord (uint16, uint32, enum s9xwrap_t w=WRAP_NONE, enum s9xwriteorder_t o=WRITE_01); void S9xSA1SetPCBase (uint32); uint8 S9xGetSA1 (uint32); void S9xSetSA1 (uint8, uint32); -void S9xSA1Init (void); -void S9xSA1MainLoop (void); -void S9xSA1ExecuteDuringSleep (void); -void S9xSA1PostLoadState (void); -#define SNES_IRQ_SOURCE (1 << 7) -#define TIMER_IRQ_SOURCE (1 << 6) -#define DMA_IRQ_SOURCE (1 << 5) +extern struct SOpcodes S9xSA1OpcodesM1X1 [256]; +extern struct SOpcodes S9xSA1OpcodesM1X0 [256]; +extern struct SOpcodes S9xSA1OpcodesM0X1 [256]; +extern struct SOpcodes S9xSA1OpcodesM0X0 [256]; +extern uint8 S9xOpLengthsM1X1 [256]; +extern uint8 S9xOpLengthsM1X0 [256]; +extern uint8 S9xOpLengthsM0X1 [256]; +extern uint8 S9xOpLengthsM0X0 [256]; +extern struct SSA1Registers SA1Registers; +extern struct SSA1 SA1; +extern uint8 SA1OpenBus; -static inline void S9xSA1UnpackStatus (void) +void S9xSA1MainLoop (); +void S9xSA1Init (); +void S9xFixSA1AfterSnapshotLoad (); +void S9xSA1ExecuteDuringSleep (); +END_EXTERN_C + +#define SNES_IRQ_SOURCE (1 << 7) +#define TIMER_IRQ_SOURCE (1 << 6) +#define DMA_IRQ_SOURCE (1 << 5) + +STATIC inline void S9xSA1UnpackStatus() { - SA1._Zero = (SA1Registers.PL & Zero) == 0; - SA1._Negative = (SA1Registers.PL & Negative); - SA1._Carry = (SA1Registers.PL & Carry); - SA1._Overflow = (SA1Registers.PL & Overflow) >> 6; + SA1._Zero = (SA1Registers.PL & Zero) == 0; + SA1._Negative = (SA1Registers.PL & Negative); + SA1._Carry = (SA1Registers.PL & Carry); + SA1._Overflow = (SA1Registers.PL & Overflow) >> 6; } -static inline void S9xSA1PackStatus (void) +STATIC inline void S9xSA1PackStatus() { - SA1Registers.PL &= ~(Zero | Negative | Carry | Overflow); - SA1Registers.PL |= SA1._Carry | ((SA1._Zero == 0) << 1) | (SA1._Negative & 0x80) | (SA1._Overflow << 6); + SA1Registers.PL &= ~(Zero | Negative | Carry | Overflow); + SA1Registers.PL |= SA1._Carry | ((SA1._Zero == 0) << 1) | + (SA1._Negative & 0x80) | (SA1._Overflow << 6); } -static inline void S9xSA1FixCycles (void) +STATIC inline void S9xSA1FixCycles () { - if (SA1CheckEmulation()) - { - SA1.S9xOpcodes = S9xSA1OpcodesM1X1; - SA1.S9xOpLengths = S9xOpLengthsM1X1; - } - else - if (SA1CheckMemory()) - { - if (SA1CheckIndex()) - { - SA1.S9xOpcodes = S9xSA1OpcodesM1X1; - SA1.S9xOpLengths = S9xOpLengthsM1X1; - } - else - { - SA1.S9xOpcodes = S9xSA1OpcodesM1X0; - SA1.S9xOpLengths = S9xOpLengthsM1X0; - } - } - else - { - if (SA1CheckIndex()) - { - SA1.S9xOpcodes = S9xSA1OpcodesM0X1; - SA1.S9xOpLengths = S9xOpLengthsM0X1; - } - else - { - SA1.S9xOpcodes = S9xSA1OpcodesM0X0; - SA1.S9xOpLengths = S9xOpLengthsM0X0; - } - } + if (SA1CheckEmulation ()) { + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + } else + if (SA1CheckMemory ()) + { + if (SA1CheckIndex ()){ + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + } else { + SA1.S9xOpcodes = S9xSA1OpcodesM1X0; + SA1.S9xOpLengths = S9xOpLengthsM1X0; + } + } + else + { + if (SA1CheckIndex ()){ + SA1.S9xOpcodes = S9xSA1OpcodesM0X1; + SA1.S9xOpLengths = S9xOpLengthsM0X1; + } else { + SA1.S9xOpcodes = S9xSA1OpcodesM0X0; + SA1.S9xOpLengths = S9xOpLengthsM0X0; + } + } } - #endif + diff --git a/source/snes9x/sa1cpu.cpp b/source/snes9x/sa1cpu.cpp index 9bcae88..0183c2e 100644 --- a/source/snes9x/sa1cpu.cpp +++ b/source/snes9x/sa1cpu.cpp @@ -159,125 +159,120 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" -#define CPU SA1 -#define ICPU SA1 -#define Registers SA1Registers -#define OpenBus SA1OpenBus -#define S9xGetByte S9xSA1GetByte -#define S9xGetWord S9xSA1GetWord -#define S9xSetByte S9xSA1SetByte -#define S9xSetWord S9xSA1SetWord -#define S9xSetPCBase S9xSA1SetPCBase -#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 -#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 -#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 -#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 -#define S9xOpcodesE1 S9xSA1OpcodesE1 -#define S9xOpcodesSlow S9xSA1OpcodesSlow -#define S9xOpcode_IRQ S9xSA1Opcode_IRQ -#define S9xOpcode_NMI S9xSA1Opcode_NMI -#define S9xUnpackStatus S9xSA1UnpackStatus -#define S9xPackStatus S9xSA1PackStatus -#define S9xFixCycles S9xSA1FixCycles -#define Immediate8 SA1Immediate8 -#define Immediate16 SA1Immediate16 -#define Relative SA1Relative -#define RelativeLong SA1RelativeLong -#define Absolute SA1Absolute -#define AbsoluteLong SA1AbsoluteLong -#define AbsoluteIndirect SA1AbsoluteIndirect -#define AbsoluteIndirectLong SA1AbsoluteIndirectLong -#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect -#define Direct SA1Direct -#define DirectIndirectIndexed SA1DirectIndirectIndexed -#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong -#define DirectIndexedIndirect SA1DirectIndexedIndirect -#define DirectIndexedX SA1DirectIndexedX -#define DirectIndexedY SA1DirectIndexedY -#define AbsoluteIndexedX SA1AbsoluteIndexedX -#define AbsoluteIndexedY SA1AbsoluteIndexedY -#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX -#define DirectIndirect SA1DirectIndirect -#define DirectIndirectLong SA1DirectIndirectLong -#define StackRelative SA1StackRelative -#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed +#include "sa1.h" + +#define CPU SA1 +#define ICPU SA1 +#define Registers SA1Registers +#define OpenBus SA1OpenBus +#define S9xGetByte S9xSA1GetByte +#define S9xGetWord S9xSA1GetWord +#define S9xSetByte S9xSA1SetByte +#define S9xSetWord S9xSA1SetWord +#define S9xSetPCBase S9xSA1SetPCBase +#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 +#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 +#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 +#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 +#define S9xOpcodesE1 S9xSA1OpcodesE1 +#define S9xOpcodesSlow S9xSA1OpcodesSlow +#define S9xOpcode_IRQ S9xSA1Opcode_IRQ +#define S9xOpcode_NMI S9xSA1Opcode_NMI +#define S9xUnpackStatus S9xSA1UnpackStatus +#define S9xPackStatus S9xSA1PackStatus +#define S9xFixCycles S9xSA1FixCycles +#define Immediate8 SA1Immediate8 +#define Immediate16 SA1Immediate16 +#define Relative SA1Relative +#define RelativeLong SA1RelativeLong +#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect +#define AbsoluteIndirectLong SA1AbsoluteIndirectLong +#define AbsoluteIndirect SA1AbsoluteIndirect +#define Absolute SA1Absolute +#define AbsoluteLong SA1AbsoluteLong +#define Direct SA1Direct +#define DirectIndirectIndexed SA1DirectIndirectIndexed +#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong +#define DirectIndexedIndirect SA1DirectIndexedIndirect +#define DirectIndexedX SA1DirectIndexedX +#define DirectIndexedY SA1DirectIndexedY +#define AbsoluteIndexedX SA1AbsoluteIndexedX +#define AbsoluteIndexedY SA1AbsoluteIndexedY +#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX +#define DirectIndirect SA1DirectIndirect +#define DirectIndirectLong SA1DirectIndirectLong +#define StackRelative SA1StackRelative +#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed //#undef CPU_SHUTDOWN #define SA1_OPCODES #include "cpuops.cpp" - -void S9xSA1MainLoop (void) +void S9xSA1MainLoop () { -#if 0 - if (SA1.Flags & NMI_FLAG) - { - SA1.Flags &= ~NMI_FLAG; - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; - } + int i; - S9xSA1Opcode_NMI(); +#if 0 + if (SA1.Flags & NMI_FLAG) + { + SA1.Flags &= ~NMI_FLAG; + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; } + S9xSA1Opcode_NMI (); + } +#endif + if (SA1.Flags & IRQ_FLAG) + { + if (SA1.IRQActive) + { + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + if (!SA1CheckFlag (IRQ)) + S9xSA1Opcode_IRQ (); + } + else + SA1.Flags &= ~IRQ_FLAG; + } + for (i = 0; i < 3 && SA1.Executing; i++) + { +#ifdef DEBUGGER + if (SA1.Flags & TRACE_FLAG){ S9xSA1Trace(); } +#endif +#ifdef CPU_SHUTDOWN + SA1.PBPCAtOpcodeStart = SA1Registers.PBPC; #endif - if (SA1.Flags & IRQ_FLAG) - { - if (SA1.IRQActive) - { - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; - } - - if (!SA1CheckFlag(IRQ)) - S9xSA1Opcode_IRQ(); - } - else - SA1.Flags &= ~IRQ_FLAG; - } - - for (int i = 0; i < 3 && SA1.Executing; i++) - { - #ifdef DEBUGGER - if (SA1.Flags & TRACE_FLAG) - S9xSA1Trace(); - #endif - - #ifdef CPU_SHUTDOWN - SA1.PBPCAtOpcodeStart = SA1Registers.PBPC; - #endif - - register uint8 Op; - register struct SOpcodes *Opcodes; - - if (SA1.PCBase) - { - SA1OpenBus = Op = SA1.PCBase[Registers.PCw]; - Opcodes = SA1.S9xOpcodes; - } - else - { - Op = S9xSA1GetByte(Registers.PBPC); - Opcodes = S9xOpcodesSlow; - } - - if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) - { - uint32 oldPC = SA1Registers.PBPC; - S9xSA1SetPCBase(SA1Registers.PBPC); - SA1Registers.PBPC = oldPC; - Opcodes = S9xSA1OpcodesSlow; - } - - Registers.PCw++; - (*Opcodes[Op].S9xOpcode)(); - } + register uint8 Op; + register struct SOpcodes *Opcodes; + if(SA1.PCBase){ + SA1OpenBus = Op = SA1.PCBase[Registers.PCw]; + Opcodes = SA1.S9xOpcodes; + } else { + Op = S9xSA1GetByte(Registers.PBPC); + Opcodes = S9xOpcodesSlow; + } + if((SA1Registers.PCw&MEMMAP_MASK)+SA1.S9xOpLengths[Op]>=MEMMAP_BLOCK_SIZE){ + uint32 oldPC = SA1Registers.PBPC; + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1Registers.PBPC = oldPC; + Opcodes = S9xSA1OpcodesSlow; + } + Registers.PCw++; + (*Opcodes[Op].S9xOpcode) (); + } } + diff --git a/source/snes9x/sar.h b/source/snes9x/sar.h index acea063..140dfeb 100644 --- a/source/snes9x/sar.h +++ b/source/snes9x/sar.h @@ -159,49 +159,54 @@ **********************************************************************************/ + + #ifndef _SAR_H_ #define _SAR_H_ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include "port.h" + +#ifndef snes9x_types_defined +#include "9xtypes.h" +#endif + #ifdef RIGHTSHIFT_IS_SAR -#define SAR(b, n) ((b) >> (n)) +#define SAR(b, n) ((b)>>(n)) #else -static inline int8 SAR (const int8 b, const int n) -{ +static inline int8 SAR(const int8 b, const int n){ #ifndef RIGHTSHIFT_int8_IS_SAR - if (b < 0) - return ((b >> n) | (-1 << (8 - n))); + if(b<0) return (b>>n)|(-1<<(8-n)); #endif - return (b >> n); + return b>>n; } -static inline int16 SAR (const int16 b, const int n) -{ +static inline int16 SAR(const int16 b, const int n){ #ifndef RIGHTSHIFT_int16_IS_SAR - if (b < 0) - return ((b >> n) | (-1 << (16 - n))); + if(b<0) return (b>>n)|(-1<<(16-n)); #endif - return (b >> n); + return b>>n; } -static inline int32 SAR (const int32 b, const int n) -{ +static inline int32 SAR(const int32 b, const int n){ #ifndef RIGHTSHIFT_int32_IS_SAR - if (b < 0) - return ((b >> n) | (-1 << (32 - n))); + if(b<0) return (b>>n)|(-1<<(32-n)); #endif - return (b >> n); + return b>>n; } -static inline int64 SAR (const int64 b, const int n) -{ +static inline int64 SAR(const int64 b, const int n){ #ifndef RIGHTSHIFT_int64_IS_SAR - if (b < 0) - return ((b >> n) | (-1 << (64 - n))); + if(b<0) return (b>>n)|(-1<<(64-n)); #endif - return (b >> n); + return b>>n; } #endif #endif + diff --git a/source/snes9x/screenshot.cpp b/source/snes9x/screenshot.cpp deleted file mode 100644 index a09c661..0000000 --- a/source/snes9x/screenshot.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com) - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley, - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001-2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight, - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound DSP emulator code is derived from SNEeSe and OpenSPC: - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2007 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -**********************************************************************************/ - - -#ifdef HAVE_LIBPNG -#include -#endif -#include "snes9x.h" -#include "memmap.h" -#include "display.h" -#include "screenshot.h" - - -bool8 S9xDoScreenshot (int width, int height) -{ - Settings.TakeScreenshot = FALSE; - -#ifdef HAVE_LIBPNG - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - png_color_8 sig_bit; - int imgwidth, imgheight; - const char *fname; - - fname = S9xGetFilenameInc(".png", SCREENSHOT_DIR); - - fp = fopen(fname, "wb"); - if (!fp) - { - S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); - return (FALSE); - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - { - fclose(fp); - unlink(fname); - S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); - return (FALSE); - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_write_struct(&png_ptr, (png_infopp) NULL); - fclose(fp); - unlink(fname); - S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); - return (FALSE); - } - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); - unlink(fname); - S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); - return (FALSE); - } - - imgwidth = width; - imgheight = height; - - if (Settings.StretchScreenshots == 1) - { - if (width > SNES_WIDTH && height <= SNES_HEIGHT_EXTENDED) - imgheight = height << 1; - } - else - if (Settings.StretchScreenshots == 2) - { - if (width <= SNES_WIDTH) - imgwidth = width << 1; - if (height <= SNES_HEIGHT_EXTENDED) - imgheight = height << 1; - } - - png_init_io(png_ptr, fp); - - png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - sig_bit.red = 5; - sig_bit.green = 5; - sig_bit.blue = 5; - png_set_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, &sig_bit); - - png_write_info(png_ptr, info_ptr); - - png_set_packing(png_ptr); - - png_byte *row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; - uint16 *screen = GFX.Screen; - - for (int y = 0; y < height; y++, screen += GFX.RealPPL) - { - png_byte *rowpix = row_pointer; - - for (int x = 0; x < width; x++) - { - uint32 r, g, b; - - DECOMPOSE_PIXEL(screen[x], r, g, b); - - *(rowpix++) = r; - *(rowpix++) = g; - *(rowpix++) = b; - - if (imgwidth != width) - { - *(rowpix++) = r; - *(rowpix++) = g; - *(rowpix++) = b; - } - } - - png_write_row(png_ptr, row_pointer); - if (imgheight != height) - png_write_row(png_ptr, row_pointer); - } - - delete [] row_pointer; - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - - fclose(fp); - - fprintf(stderr, "%s saved.\n", fname); - - const char *base = S9xBasename(fname); - sprintf(String, "Saved screenshot %s", base); - S9xMessage(S9X_INFO, 0, String); - - return (TRUE); -#else - fprintf(stderr, "Screenshot support not available (libpng was not found at build time).\n"); - return (FALSE); -#endif -} diff --git a/source/snes9x/screenshot.h b/source/snes9x/screenshot.h index 4db3061..1665a3c 100644 --- a/source/snes9x/screenshot.h +++ b/source/snes9x/screenshot.h @@ -159,9 +159,12 @@ **********************************************************************************/ -#ifndef _SCREENSHOT_H_ -#define _SCREENSHOT_H_ -bool8 S9xDoScreenshot (int, int); + +#ifndef SCREENSHOT_H +#define SCREENSHOT_H + +bool8 S9xDoScreenshot(int width, int height); #endif + diff --git a/source/snes9x/sdd1.cpp b/source/snes9x/sdd1.cpp index 994f2cc..ae5206f 100644 --- a/source/snes9x/sdd1.cpp +++ b/source/snes9x/sdd1.cpp @@ -159,37 +159,97 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" +#include "ppu.h" #include "sdd1.h" #include "display.h" +#ifdef __linux +#include +#endif void S9xSetSDD1MemoryMap (uint32 bank, uint32 value) { - bank = 0xc00 + bank * 0x100; - value = value * 1024 * 1024; + bank = 0xc00 + bank * 0x100; + value = value * 1024 * 1024; - for (int c = 0; c < 0x100; c += 16) - { - uint8 *block = &Memory.ROM[value + (c << 12)]; - for (int i = c; i < c + 16; i++) - Memory.Map[i + bank] = block; - } + int c; + + for (c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM [value + (c << 12)]; + int i; + + for (i = c; i < c + 16; i++) + Memory.Map [i + bank] = block; + } } -void S9xResetSDD1 (void) +void S9xResetSDD1 () { - memset(&Memory.FillRAM[0x4800], 0, 4); - for (int i = 0; i < 4; i++) - { - Memory.FillRAM[0x4804 + i] = i; - S9xSetSDD1MemoryMap(i, i); - } + memset (&Memory.FillRAM [0x4800], 0, 4); + for (int i = 0; i < 4; i++) + { + Memory.FillRAM [0x4804 + i] = i; + S9xSetSDD1MemoryMap (i, i); + } } -void S9xSDD1PostLoadState (void) +void S9xSDD1PostLoadState () { - for (int i = 0; i < 4; i++) - S9xSetSDD1MemoryMap(i, Memory.FillRAM[0x4804 + i]); + for (int i = 0; i < 4; i++) + S9xSetSDD1MemoryMap (i, Memory.FillRAM [0x4804 + i]); } + +static int S9xCompareSDD1LoggedDataEntries (const void *p1, const void *p2) +{ + uint8 *b1 = (uint8 *) p1; + uint8 *b2 = (uint8 *) p2; + uint32 a1 = (*b1 << 16) + (*(b1 + 1) << 8) + *(b1 + 2); + uint32 a2 = (*b2 << 16) + (*(b2 + 1) << 8) + *(b2 + 2); + + return (a1 - a2); +} + +void S9xSDD1SaveLoggedData () +{ + if (Memory.SDD1LoggedDataCount != Memory.SDD1LoggedDataCountPrev) + { + qsort (Memory.SDD1LoggedData, Memory.SDD1LoggedDataCount, 8, + S9xCompareSDD1LoggedDataEntries); + + FILE *fs = fopen (S9xGetFilename (".dat", PATCH_DIR), "wb"); + + if (fs) + { + fwrite (Memory.SDD1LoggedData, 8, + Memory.SDD1LoggedDataCount, fs); + fclose (fs); +#if defined(__linux) + chown (S9xGetFilename (".dat", PATCH_DIR), getuid (), getgid ()); +#endif + } + Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount; + } +} + +void S9xSDD1LoadLoggedData () +{ + FILE *fs = fopen (S9xGetFilename (".dat", PATCH_DIR), "rb"); + + Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0; + + if (fs) + { + int c = fread (Memory.SDD1LoggedData, 8, + MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs); + + if (c != EOF) + Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c; + fclose (fs); + } +} + diff --git a/source/snes9x/sdd1.h b/source/snes9x/sdd1.h index afb6107..c03c343 100644 --- a/source/snes9x/sdd1.h +++ b/source/snes9x/sdd1.h @@ -159,11 +159,14 @@ **********************************************************************************/ + + #ifndef _SDD1_H_ #define _SDD1_H_ - -void S9xSetSDD1MemoryMap (uint32, uint32); -void S9xResetSDD1 (void); -void S9xSDD1PostLoadState (void); - +void S9xSetSDD1MemoryMap (uint32 bank, uint32 value); +void S9xResetSDD1 (); +void S9xSDD1PostLoadState (); +void S9xSDD1SaveLoggedData (); +void S9xSDD1LoadLoggedData (); #endif + diff --git a/source/snes9x/sdd1emu.cpp b/source/snes9x/sdd1emu.cpp index 29ba5f4..4104137 100644 --- a/source/snes9x/sdd1emu.cpp +++ b/source/snes9x/sdd1emu.cpp @@ -158,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + /* S-DD1 decompressor * * Based on code and documentation by Andreas Naive, who deserves a great deal @@ -172,7 +174,7 @@ * S-DD1 issue in the past. */ - +#include #include "port.h" #include "sdd1emu.h" @@ -388,7 +390,6 @@ void SDD1_decompress(uint8 *out, uint8 *in, int len){ } } -#if 0 static uint8 cur_plane; static uint8 num_bits; static uint8 next_byte; @@ -484,4 +485,4 @@ uint8 SDD1_get_byte(void){ return 0; } } -#endif + diff --git a/source/snes9x/sdd1emu.h b/source/snes9x/sdd1emu.h index e6d56b5..86c03e9 100644 --- a/source/snes9x/sdd1emu.h +++ b/source/snes9x/sdd1emu.h @@ -159,9 +159,20 @@ **********************************************************************************/ -#ifndef _SDD1EMU_H_ -#define _SDD1EMU_H_ -void SDD1_decompress (uint8 *, uint8 *, int); +#ifndef SDD1EMU_H +#define SDD1EMU_H + +/* for START_EXTERN_C/END_EXTERN_C */ +#include "port.h" + +START_EXTERN_C + +void SDD1_decompress(uint8 *out, uint8 *in, int output_length); + +void SDD1_init(uint8 *in); +uint8 SDD1_get_byte(void); + +END_EXTERN_C #endif diff --git a/source/snes9x/seta.cpp b/source/snes9x/seta.cpp index 62ad645..ca3bfba 100644 --- a/source/snes9x/seta.cpp +++ b/source/snes9x/seta.cpp @@ -159,19 +159,21 @@ **********************************************************************************/ -#include "snes9x.h" + #include "seta.h" -uint8 (*GetSETA) (uint32) = &S9xGetST010; -void (*SetSETA) (uint32, uint8) = &S9xSetST010; +void (*SetSETA)(uint32, uint8)=&S9xSetST010; +uint8 (*GetSETA)(uint32)=&S9xGetST010; - -uint8 S9xGetSetaDSP (uint32 Address) +extern "C"{ +uint8 S9xGetSetaDSP(uint32 Address) { - return (GetSETA(Address)); + return GetSETA(Address); } -void S9xSetSetaDSP (uint8 Byte, uint32 Address) +void S9xSetSetaDSP(uint8 Byte, uint32 Address) { - SetSETA (Address, Byte); + SetSETA(Address, Byte); } +} + diff --git a/source/snes9x/seta.h b/source/snes9x/seta.h index 9af7c36..0c49170 100644 --- a/source/snes9x/seta.h +++ b/source/snes9x/seta.h @@ -159,64 +159,72 @@ **********************************************************************************/ -#ifndef _SETA_H_ -#define _SETA_H_ -#define ST_010 0x01 -#define ST_011 0x02 -#define ST_018 0x03 -struct SST010 +#ifndef NO_SETA +#ifndef _seta_h +#define _seta_h + +#include "port.h" + +#define ST_010 0x01 +#define ST_011 0x02 +#define ST_018 0x03 + + +extern "C" { - uint8 input_params[16]; - uint8 output_params[16]; - uint8 op_reg; - uint8 execute; - bool8 control_enable; -}; +uint8 S9xGetSetaDSP(uint32 Address); +void S9xSetSetaDSP(uint8 byte,uint32 Address); +uint8 S9xGetST018(uint32 Address); +void S9xSetST018(uint8 Byte, uint32 Address); -struct SST011 +uint8 S9xGetST010(uint32 Address); +void S9xSetST010(uint32 Address, uint8 Byte); +uint8 S9xGetST011(uint32 Address); +void S9xSetST011(uint32 Address, uint8 Byte); +} + +extern void (*SetSETA)(uint32, uint8); +extern uint8 (*GetSETA)(uint32); + +typedef struct SETA_ST010_STRUCT { - bool8 waiting4command; - uint8 status; - uint8 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters[512]; - uint8 output[512]; -}; + uint8 input_params[16]; + uint8 output_params[16]; + uint8 op_reg; + uint8 execute; + bool8 control_enable; +} ST010_Regs; -struct SST018 +typedef struct SETA_ST011_STRUCT { - bool8 waiting4command; - uint8 status; - uint8 part_command; - uint8 pass; - uint32 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters[512]; - uint8 output[512]; -}; + bool8 waiting4command; + uint8 status; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters [512]; + uint8 output [512]; +} ST011_Regs; -extern struct SST010 ST010; -extern struct SST011 ST011; -extern struct SST018 ST018; - -uint8 S9xGetST010 (uint32); -void S9xSetST010 (uint32, uint8); -uint8 S9xGetST011 (uint32); -void S9xSetST011 (uint32, uint8); -uint8 S9xGetST018 (uint32); -void S9xSetST018 (uint8, uint32); -uint8 S9xGetSetaDSP (uint32); -void S9xSetSetaDSP (uint8, uint32); - -extern uint8 (*GetSETA) (uint32); -extern void (*SetSETA) (uint32, uint8); +typedef struct SETA_ST018_STRUCT +{ + bool8 waiting4command; + uint8 status; + uint8 part_command; + uint8 pass; + uint32 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters [512]; + uint8 output [512]; +} ST018_Regs; #endif +#endif + diff --git a/source/snes9x/seta010.cpp b/source/snes9x/seta010.cpp index b4288c1..e28225a 100644 --- a/source/snes9x/seta010.cpp +++ b/source/snes9x/seta010.cpp @@ -159,13 +159,61 @@ **********************************************************************************/ -#include -#include "snes9x.h" -#include "memmap.h" -#include "seta.h" -static const int16 ST010_SinTable[256] = +#include "seta.h" +#include "memmap.h" + +// Mode 7 scaling constants for all raster lines +const int16 ST010_M7Scale[176] = { + 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, + 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, + 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, + 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, + 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, + 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, + 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, + 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, + 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, + 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, + 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, + 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, + 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, + 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, + 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, + 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, + 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, + 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, + 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, + 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, + 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, + 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b +}; + +// H-DMA hack +bool seta_hack; + +//temporary Op04 requirement +#include + +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif + +ST010_Regs ST010; + +uint8 S9xGetST010(uint32 Address) { + if(!(Address&0x80000)) + return 0x80; + + if((Address&0xFFF)==0x20) + return ST010.op_reg; + if ((Address&0xFFF)==0x21) + return ST010.execute; + return Memory.SRAM[Address&Memory.SRAMMask]; +} + +const int16 ST010_SinTable[256] = { 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, 0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, @@ -197,194 +245,155 @@ static const int16 ST010_SinTable[256] = -0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3, -0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de, -0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b, - -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324 -}; + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; -static const uint8 ST010_ArcTan[32][32] = -{ +const unsigned char ST010_ArcTan[32][32] = { { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, { 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf }, + 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf}, { 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd }, + 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd}, { 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8, - 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc }, + 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc}, { 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5, - 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb }, + 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb}, { 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, - 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9 }, + 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9}, { 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8 }, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8}, { 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae, - 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7 }, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7}, { 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac, - 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5 }, + 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5}, { 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa, - 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4 }, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4}, { 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8, - 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3 }, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3}, { 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6, - 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2 }, + 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2}, { 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1 }, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1}, { 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3, - 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0 }, + 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0}, { 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1, - 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf }, + 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf}, { 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0, - 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae }, + 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae}, { 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad }, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad}, { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d, - 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac }, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac}, { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c, - 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab }, + 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab}, { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b, - 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa }, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa}, { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a, - 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9 }, + 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9}, { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99, - 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8 }, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8}, { 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98, - 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7 }, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7}, { 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6 }, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6}, { 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5 }, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5}, { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4 }, + 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4}, { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95, - 0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4 }, + 0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4}, { 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95, - 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3 }, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3}, { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2 }, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2}, { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1 }, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1}, { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1 }, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1}, { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, - 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 } -}; + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0}}; -// Mode 7 scaling constants for all raster lines -static const int16 ST010_M7Scale[176] = +short ST010_Sin(short Theta) { - 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, - 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, - 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, - 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, - 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, - 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, - 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, - 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, - 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, - 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, - 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, - 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, - 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, - 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, - 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, - 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, - 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, - 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, - 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, - 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, - 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, - 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b -}; - -#ifndef PI -#define PI 3.1415926535897932384626433832795 -#endif - -#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] - - -static int16 ST010_Sin (int16 Theta) -{ - return (ST010_SinTable[(Theta >> 8) & 0xff]); + return ST010_SinTable[(Theta >> 8) & 0xff]; } -static int16 ST010_Cos (int16 Theta) +short ST010_Cos(short Theta) { - return (ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]); + return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]; } -static void ST010_OP01 (int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &Quadrant, int16 &Theta) +void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) { - if ((x0 < 0) && (y0 < 0)) + if ((x0 < 0) && (y0 < 0)) { x1 = -x0; y1 = -y0; Quadrant = -0x8000; } - else - if (x0 < 0) + else if (x0 < 0) { - x1 = y0; + x1 = y0; y1 = -x0; Quadrant = -0x4000; } - else - if (y0 < 0) + else if (y0 < 0) { x1 = -y0; - y1 = x0; - Quadrant = 0x4000; + y1 = x0; + Quadrant = 0x4000; } else { - x1 = x0; - y1 = y0; - Quadrant = 0x0000; + x1 = x0; + y1 = y0; + Quadrant = 0x0000; } - while ((x1 > 0x1f) || (y1 > 0x1f)) + while ((x1 > 0x1f) || (y1 > 0x1f)) { - if (x1 > 1) - x1 >>= 1; - if (y1 > 1) - y1 >>= 1; + if (x1 > 1) x1 >>= 1; + if (y1 > 1) y1 >>= 1; } - if (y1 == 0) - Quadrant += 0x4000; + if (y1 == 0) Quadrant += 0x4000; Theta = (ST010_ArcTan[y1][x1] << 8) ^ Quadrant; } -static void ST010_Scale (int16 Multiplier, int16 X0, int16 Y0, int32 &X1, int32 &Y1) +void ST010_Scale(short Multiplier, short X0, short Y0, int &X1, int &Y1) { X1 = X0 * Multiplier << 1; Y1 = Y0 * Multiplier << 1; } -static void ST010_Multiply (int16 Multiplicand, int16 Multiplier, int32 &Product) +void ST010_Multiply(short Multiplicand, short Multiplier, int &Product) { Product = Multiplicand * Multiplier << 1; } -static void ST010_Rotate (int16 Theta, int16 X0, int16 Y0, int16 &X1, int16 &Y1) +void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1) { X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); } -static void ST010_SortDrivers (uint16 Positions, uint16 Places[32], uint16 Drivers[32]) +void SETA_Distance(short Y0, short X0, short &Distance) { - bool Sorted; - uint16 Temp; + if (X0 < 0) X0 = -X0; + if (Y0 < 0) Y0 = -Y0; + Distance = ((X0 * 0x7af0) + 0x4000) >> 15; +} + +void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) +{ + bool Sorted; + uint16 Temp; if (Positions > 1) - { - do - { + do { Sorted = true; - for (int i = 0; i < Positions - 1; i++) - { if (Places[i] < Places[i + 1]) { Temp = Places[i + 1]; @@ -397,82 +406,49 @@ static void ST010_SortDrivers (uint16 Positions, uint16 Places[32], uint16 Drive Sorted = false; } - } - Positions--; - } - while (!Sorted); - } + } while (!Sorted); } -/* -static void SETA_Distance (int16 Y0, int16 X0, int16 &Distance) +#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] + +void S9xSetST010(uint32 Address, uint8 Byte) { - if (X0 < 0) - X0 = -X0; - if (Y0 < 0) - Y0 = -Y0; - - Distance = ((X0 * 0x7af0) + 0x4000) >> 15; -} -*/ - -uint8 S9xGetST010 (uint32 Address) -{ - if (!(Address & 0x80000)) - return (0x80); - - if ((Address & 0xFFF) == 0x20) - return (ST010.op_reg); - - if ((Address & 0xFFF) == 0x21) - return (ST010.execute); - - return (Memory.SRAM[Address & Memory.SRAMMask]); -} - -void S9xSetST010 (uint32 Address, uint8 Byte) -{ - if (!(Address & 0x80000)) + if(!(Address&0x80000)) { - ST010.control_enable = TRUE; + ST010.control_enable=TRUE; return; } + //printf("Write %06X:%02X\n", Address, Byte); -#ifdef DEBUGGER - printf("Write %06X:%02X\n", Address, Byte); -#endif + if((Address &0xFFF) ==0x20 && ST010.control_enable) + ST010.op_reg=Byte; + if((Address &0xFFF) ==0x21 && ST010.control_enable) + ST010.execute=Byte; + else Memory.SRAM[Address&Memory.SRAMMask]=Byte; - if ((Address & 0xFFF) == 0x20 && ST010.control_enable) - ST010.op_reg = Byte; - - if ((Address & 0xFFF) == 0x21 && ST010.control_enable) - ST010.execute = Byte; - else - Memory.SRAM[Address & Memory.SRAMMask] = Byte; - - if (ST010.execute & 0x80) + if(ST010.execute&0x80) { - switch (ST010.op_reg) + switch(ST010.op_reg) { - // Sorts Driver Placements - // - // Input - // 0x0024-0x0025 : Positions - // 0x0040-0x007f : Places - // 0x0080-0x00ff : Drivers - // Output - // 0x0040-0x007f : Places - // 0x0080-0x00ff : Drivers - // - case 0x02: + // Sorts Driver Placements + // + // Input + // 0x0024-0x0025 : Positions + // 0x0040-0x007f : Places + // 0x0080-0x00ff : Drivers + // Output + // 0x0040-0x007f : Places + // 0x0080-0x00ff : Drivers + // + case 0x02: { - #ifdef FAST_LSB_WORD_ACCESS - ST010_SortDrivers(*(uint16 *) (Memory.SRAM + 0x0024), (uint16 *) (Memory.SRAM + 0x0040), (uint16 *) (Memory.SRAM + 0x0080)); - #else - uint16 Places[32]; - uint16 Positions = ST010_WORD(0x0024); - int Pos, Offset; +#ifdef FAST_LSB_WORD_ACCESS + ST010_SortDrivers(*(uint16*)(Memory.SRAM + 0x0024), (uint16*) (Memory.SRAM + 0x0040), (uint16*) (Memory.SRAM + 0x0080)); +#else + uint16 Places[32]; + uint16 Positions = ST010_WORD(0x0024); + int Pos, Offset; Offset = 0; @@ -482,113 +458,114 @@ void S9xSetST010 (uint32 Address, uint8 Byte) Offset += 2; } - ST010_SortDrivers(Positions, Places, (uint16 *) (Memory.SRAM + 0x0080)); + ST010_SortDrivers(Positions, Places, (uint16*) (Memory.SRAM + 0x0080)); Offset = 0; for (Pos = 0; Pos < Positions; Pos++) { - Memory.SRAM[0x0040 + Offset] = (uint8) (Places[Pos]); - Memory.SRAM[0x0041 + Offset] = (uint8) (Places[Pos] >> 8); + Memory.SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); + Memory.SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); Offset += 2; } - #endif +#endif break; + } - // Two Dimensional Coordinate Scale - // - // Input - // 0x0000-0x0001 : X0 (signed) - // 0x0002-0x0003 : Y0 (signed) - // 0x0004-0x0005 : Multiplier (signed) - // Output - // 0x0010-0x0013 : X1 (signed) - // 0x0014-0x0017 : Y1 (signed) - // - case 0x03: + // Two Dimensional Coordinate Scale + // + // Input + // 0x0000-0x0001 : X0 (signed) + // 0x0002-0x0003 : Y0 (signed) + // 0x0004-0x0005 : Multiplier (signed) + // Output + // 0x0010-0x0013 : X1 (signed) + // 0x0014-0x0017 : Y1 (signed) + // + case 0x03: { - #ifdef FAST_LSB_WORD_ACCESS - ST010_Scale(*(int16 *) &Memory.SRAM[0x0004], *(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010], (int32 &) Memory.SRAM[0x0014]); - #else - int32 x1, y1; +#ifdef FAST_LSB_WORD_ACCESS + ST010_Scale(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]); +#else + int x1, y1; ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); - Memory.SRAM[0x0010] = (uint8) (x1); - Memory.SRAM[0x0011] = (uint8) (x1 >> 8); - Memory.SRAM[0x0012] = (uint8) (x1 >> 16); - Memory.SRAM[0x0013] = (uint8) (x1 >> 24); - Memory.SRAM[0x0014] = (uint8) (y1); - Memory.SRAM[0x0015] = (uint8) (y1 >> 8); - Memory.SRAM[0x0016] = (uint8) (y1 >> 16); - Memory.SRAM[0x0017] = (uint8) (y1 >> 24); - #endif + Memory.SRAM[0x0010]=(uint8)(x1); + Memory.SRAM[0x0011]=(uint8)(x1 >> 8); + Memory.SRAM[0x0012]=(uint8)(x1 >> 16); + Memory.SRAM[0x0013]=(uint8)(x1 >> 24); + Memory.SRAM[0x0014]=(uint8)(y1); + Memory.SRAM[0x0015]=(uint8)(y1 >> 8); + Memory.SRAM[0x0016]=(uint8)(y1 >> 16); + Memory.SRAM[0x0017]=(uint8)(y1 >> 24); +#endif break; } - // 16-bit Multiplication - // - // Input - // 0x0000-0x0001 : Multiplcand (signed) - // 0x0002-0x0003 : Multiplier (signed) - // Output - // 0x0010-0x0013 : Product (signed) - // - case 0x06: + // 16-bit Multiplication + // + // Input + // 0x0000-0x0001 : Multiplcand (signed) + // 0x0002-0x0003 : Multiplier (signed) + // Output + // 0x0010-0x0013 : Product (signed) + // + case 0x06: { - #ifdef FAST_LSB_WORD_ACCESS - ST010_Multiply(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010]); - #else - int32 Product; +#ifdef FAST_LSB_WORD_ACCESS + ST010_Multiply(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], (int&) Memory.SRAM[0x0010]); +#else + int Product; ST010_Multiply(ST010_WORD(0x0000), ST010_WORD(0x0002), Product); - Memory.SRAM[0x0010] = (uint8) (Product); - Memory.SRAM[0x0011] = (uint8) (Product >> 8); - Memory.SRAM[0x0012] = (uint8) (Product >> 16); - Memory.SRAM[0x0013] = (uint8) (Product >> 24); - #endif + Memory.SRAM[0x0010]=(uint8)(Product); + Memory.SRAM[0x0011]=(uint8)(Product >> 8); + Memory.SRAM[0x0012]=(uint8)(Product >> 16); + Memory.SRAM[0x0013]=(uint8)(Product >> 24); +#endif break; } - // Mode 7 Raster Data Calculation - // - // Input - // 0x0000-0x0001 : Angle (signed) - // Output - // 0x00f0-0x024f : Mode 7 Matrix A - // 0x0250-0x03af : Mode 7 Matrix B - // 0x03b0-0x050f : Mode 7 Matrix C - // 0x0510-0x066f : Mode 7 Matrix D - // - case 0x07: + // Mode 7 Raster Data Calculation + // + // Input + // 0x0000-0x0001 : Angle (signed) + // Output + // 0x00f0-0x024f : Mode 7 Matrix A + // 0x0250-0x03af : Mode 7 Matrix B + // 0x03b0-0x050f : Mode 7 Matrix C + // 0x0510-0x066f : Mode 7 Matrix D + // + case 0x07: { - int16 data; - int32 offset = 0; - int16 Theta = ST010_WORD(0x0000); + int16 data; + int32 offset = 0; + int16 Theta = ST010_WORD(0x0000); for (int32 line = 0; line < 176; line++) { // Calculate Mode 7 Matrix A/D data data = ST010_M7Scale[line] * ST010_Cos(Theta) >> 15; - Memory.SRAM[0x00f0 + offset] = (uint8) (data); - Memory.SRAM[0x00f1 + offset] = (uint8) (data >> 8); - Memory.SRAM[0x0510 + offset] = (uint8) (data); - Memory.SRAM[0x0511 + offset] = (uint8) (data >> 8); + Memory.SRAM[0x00f0 + offset]=(uint8)(data); + Memory.SRAM[0x00f1 + offset]=(uint8)(data >> 8); + Memory.SRAM[0x0510 + offset]=(uint8)(data); + Memory.SRAM[0x0511 + offset]=(uint8)(data >> 8); // Calculate Mode 7 Matrix B/C data data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15; - Memory.SRAM[0x0250 + offset] = (uint8) (data); - Memory.SRAM[0x0251 + offset] = (uint8) (data >> 8); + Memory.SRAM[0x0250 + offset]=(uint8)(data); + Memory.SRAM[0x0251 + offset]=(uint8)(data >> 8); - if (data) - data = ~data; + if (data) data = ~data; - Memory.SRAM[0x03b0 + offset] = (uint8) (data); - Memory.SRAM[0x03b1 + offset] = (uint8) (data >> 8); + Memory.SRAM[0x03b0 + offset]=(uint8)(data); + Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8); offset += 2; } @@ -600,156 +577,162 @@ void S9xSetST010 (uint32 Address, uint8 Byte) break; } - // Two dimensional Coordinate Rotation - // - // Input - // 0x0000-0x0001 : X0 (signed) - // 0x0002-0x0003 : Y0 (signed) - // 0x0004-0x0005 : Angle (signed) - // Output - // 0x0010-0x0011 : X1 (signed) - // 0x0012-0x0013 : Y1 (signed) - // - case 0x08: + // Two dimensional Coordinate Rotation + // + // Input + // 0x0000-0x0001 : X0 (signed) + // 0x0002-0x0003 : Y0 (signed) + // 0x0004-0x0005 : Angle (signed) + // Output + // 0x0010-0x0011 : X1 (signed) + // 0x0012-0x0013 : Y1 (signed) + // + case 0x08: { - #ifdef FAST_LSB_WORD_ACCESS - ST010_Rotate(*(int16 *) &Memory.SRAM[0x0004], *(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0010], (int16 &) Memory.SRAM[0x0012]); - #else - int16 x1, y1; +#ifdef FAST_LSB_WORD_ACCESS + ST010_Rotate(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]); +#else + short x1, y1; ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); - Memory.SRAM[0x0010] = (uint8) (x1); - Memory.SRAM[0x0011] = (uint8) (x1 >> 8); - Memory.SRAM[0x0012] = (uint8) (y1); - Memory.SRAM[0x0013] = (uint8) (y1 >> 8); - #endif + Memory.SRAM[0x0010]=(uint8)(x1); + Memory.SRAM[0x0011]=(uint8)(x1 >> 8); + Memory.SRAM[0x0012]=(uint8)(y1); + Memory.SRAM[0x0013]=(uint8)(y1 >> 8); +#endif break; } - // Input - // 0x0000-0x0001 : DX (signed) - // 0x0002-0x0003 : DY (signed) - // Output - // 0x0010-0x0011 : Angle (signed) - // - case 0x01: + // Input + // 0x0000-0x0001 : DX (signed) + // 0x0002-0x0003 : DY (signed) + // Output + // 0x0010-0x0011 : Angle (signed) + // + case 0x01: { Memory.SRAM[0x0006] = Memory.SRAM[0x0002]; Memory.SRAM[0x0007] = Memory.SRAM[0x0003]; - #ifdef FAST_LSB_WORD_ACCESS - ST010_OP01(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0000], (int16 &) Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0004], (int16 &) Memory.SRAM[0x0010]); - #else - int16 x1, y1, Quadrant, Theta; +#ifdef FAST_LSB_WORD_ACCESS + ST010_OP01(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0000], (short&) Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0004], (short&) Memory.SRAM[0x0010]); +#else + short x1, y1, Quadrant, Theta; ST010_OP01(ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1, Quadrant, Theta); - Memory.SRAM[0x0000] = (uint8) (x1); - Memory.SRAM[0x0001] = (uint8) (x1 >> 8); - Memory.SRAM[0x0002] = (uint8) (y1); - Memory.SRAM[0x0003] = (uint8) (y1 >> 8); - Memory.SRAM[0x0004] = (uint8) (Quadrant); - Memory.SRAM[0x0005] = (uint8) (Quadrant >> 8); - Memory.SRAM[0x0010] = (uint8) (Theta); - Memory.SRAM[0x0011] = (uint8) (Theta >> 8); - #endif + Memory.SRAM[0x0000]=(uint8)(x1); + Memory.SRAM[0x0001]=(uint8)(x1 >> 8); + Memory.SRAM[0x0002]=(uint8)(y1); + Memory.SRAM[0x0003]=(uint8)(y1 >> 8); + Memory.SRAM[0x0004]=(uint8)(Quadrant); + Memory.SRAM[0x0005]=(uint8)(Quadrant >> 8); + Memory.SRAM[0x0010]=(uint8)(Theta); + Memory.SRAM[0x0011]=(uint8)(Theta >> 8); +#endif + break; + } + + // calculate the vector length of (x,y) + case 0x04: + { + int16 square, x,y; +#ifdef FAST_LSB_WORD_ACCESS + x=*((int16*)Memory.SRAM); + y=*((int16*)&Memory.SRAM[2]); +#else + x=Memory.SRAM[0]|(Memory.SRAM[1]<<8); + y=Memory.SRAM[2]|(Memory.SRAM[3]<<8); +#endif + square=(int16)sqrt((double)(y*y+x*x)); + //SETA_Distance( x,y,square ); + +#ifdef FAST_LSB_WORD_ACCESS + *((int16*)&Memory.SRAM[0x10])=square; +#else + Memory.SRAM[0x10]=(uint8)(square); + Memory.SRAM[0x11]=(uint8)(square>>8); +#endif break; } - // calculate the vector length of (x, y) - case 0x04: + // calculate AI orientation based on specific guidelines + case 0x05: { - int16 square, x, y; - #ifdef FAST_LSB_WORD_ACCESS - x = *((int16 *) Memory.SRAM); - y = *((int16 *) &Memory.SRAM[2]); - #else - x = Memory.SRAM[0] | (Memory.SRAM[1] << 8); - y = Memory.SRAM[2] | (Memory.SRAM[3] << 8); - #endif - square = (int16) sqrt((double) (y * y + x * x)); - //SETA_Distance(x, y, square); + int dx,dy; + int16 a1,b1,c1; + uint16 o1; - #ifdef FAST_LSB_WORD_ACCESS - *((int16 *) &Memory.SRAM[0x10]) = square; - #else - Memory.SRAM[0x10] = (uint8) (square); - Memory.SRAM[0x11] = (uint8) (square >> 8); - #endif - break; - } + bool wrap=false; - // calculate AI orientation based on specific guidelines - case 0x05: - { - int32 dx, dy; - int16 a1, b1, c1; - uint16 o1; - bool wrap = false; - - // target (x, y) coordinates - int16 ypos_max = ST010_WORD(0x00C0); - int16 xpos_max = ST010_WORD(0x00C2); + // target (x,y) coordinates + int16 ypos_max = ST010_WORD(0x00C0); + int16 xpos_max = ST010_WORD(0x00C2); // current coordinates and direction - int32 ypos = Memory.SRAM[0xC4] | (Memory.SRAM[0xC5] << 8) | (Memory.SRAM[0xC6] << 16) | (Memory.SRAM[0xC7] << 24); - int32 xpos = Memory.SRAM[0xC8] | (Memory.SRAM[0xC9] << 8) | (Memory.SRAM[0xCA] << 16) | (Memory.SRAM[0xCB] << 24); - uint16 rot = Memory.SRAM[0xCC] | (Memory.SRAM[0xCD] << 8); + int32 ypos = Memory.SRAM[0xC4]|(Memory.SRAM[0xC5]<<8)|(Memory.SRAM[0xC6]<<16)|(Memory.SRAM[0xC7]<<24); + int32 xpos = Memory.SRAM[0xC8]|(Memory.SRAM[0xC9]<<8)|(Memory.SRAM[0xCA]<<16)|(Memory.SRAM[0xCB]<<24); + uint16 rot = Memory.SRAM[0xCC]|(Memory.SRAM[0xCD]<<8); // physics - uint16 speed = ST010_WORD(0x00D4); - uint16 accel = ST010_WORD(0x00D6); - uint16 speed_max = ST010_WORD(0x00D8); + uint16 speed = ST010_WORD(0x00D4); + uint16 accel = ST010_WORD(0x00D6); + uint16 speed_max = ST010_WORD(0x00D8); // special condition acknowledgment - int16 system = ST010_WORD(0x00DA); - int16 flags = ST010_WORD(0x00DC); + int16 system = ST010_WORD(0x00DA); + int16 flags = ST010_WORD(0x00DC); // new target coordinates - int16 ypos_new = ST010_WORD(0x00DE); - int16 xpos_new = ST010_WORD(0x00E0); + int16 ypos_new = ST010_WORD(0x00DE); + int16 xpos_new = ST010_WORD(0x00E0); // mask upper bit xpos_new &= 0x7FFF; // get the current distance - dx = xpos_max - (xpos >> 16); - dy = ypos_max - (ypos >> 16); + dx = xpos_max-(xpos>>16); + dy = ypos_max-(ypos>>16); // quirk: clear and move in9 - Memory.SRAM[0xD2] = 0xFF; - Memory.SRAM[0xD3] = 0xFF; - Memory.SRAM[0xDA] = 0; - Memory.SRAM[0xDB] = 0; + Memory.SRAM[0xD2]=0xFF; + Memory.SRAM[0xD3]=0xFF; + Memory.SRAM[0xDA]=0; + Memory.SRAM[0xDB]=0; // grab the target angle - ST010_OP01(dy, dx, a1, b1, c1, (int16 &) o1); + ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1); // check for wrapping - //if ((o1 < 0x6000 && rot > 0xA000) || (rot < 0x6000 && o1 > 0xA000)) - //if (o1 < rot) - if (abs(o1 - rot) > 0x8000) + //if((o1<0x6000 && rot>0xA000) || + // (rot<0x6000 && o1>0xA000)) + //if(o10x8000) { - o1 += 0x8000; - rot += 0x8000; - wrap = true; + o1+=0x8000; + rot+=0x8000; + wrap=true; } - //o1 = 0x0000; - //rot = 0xFF00; + //o1=0x0000; + //rot=0xFF00; - uint16 old_speed; + uint16 old_speed; old_speed = speed; // special case - if (abs(o1 - rot) == 0x8000) - speed = 0x100; - // slow down for sharp curves - else - if (abs(o1 - rot) >= 0x1000) + if(abs(o1-rot)==0x8000) { - uint32 slow = abs(o1 - rot); + speed = 0x100; + } + // slow down for sharp curves + else if(abs(o1-rot)>=0x1000) + { + uint32 slow = abs(o1-rot); slow >>= 4; // scaling speed -= slow; } @@ -757,7 +740,7 @@ void S9xSetST010 (uint32 Address, uint8 Byte) else { speed += accel; - if (speed > speed_max) + if(speed > speed_max) { // clip speed speed = speed_max; @@ -765,40 +748,35 @@ void S9xSetST010 (uint32 Address, uint8 Byte) } // prevent negative/positive overflow - if (abs(old_speed - speed) > 0x8000) - { - if (old_speed < speed) - speed = 0; - else - speed = 0xff00; + if(abs(old_speed-speed)>0x8000) { + if(old_speed rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) + if( (o1>rot && (o1-rot)>0x80) || + (o1=0x80) ) { - if (o1 < rot) - rot -= 0x280; - else - if (o1 > rot) - rot += 0x280; + if(o1rot) rot+=0x280; } // turn off wrapping - if (wrap) - rot -= 0x8000; + if(wrap) rot-=0x8000; // now check the distances (store for later) - dx = (xpos_max << 16) - xpos; - dy = (ypos_max << 16) - ypos; - dx >>= 16; - dy >>= 16; + dx = (xpos_max<<16)-xpos; + dy = (ypos_max<<16)-ypos; + dx>>=16; + dy>>=16; // if we're in so many units of the target, signal it - if ((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) + if( ( system && (dy<=6 && dy>=-8) && (dx<=126 && dx>=-128)) || + (!system && (dx<=6 && dx>=-8) && (dy<=126 && dy>=-128)) ) { // announce our new destination and flag it - xpos_max = xpos_new & 0x7FFF; + xpos_max = xpos_new&0x7FFF; ypos_max = ypos_new; flags |= 0x08; } @@ -811,37 +789,36 @@ void S9xSetST010 (uint32 Address, uint8 Byte) xpos &= 0x1FFFFFFF; ypos &= 0x1FFFFFFF; - Memory.SRAM[0x00C0] = (uint8) (ypos_max); - Memory.SRAM[0x00C1] = (uint8) (ypos_max >> 8); - Memory.SRAM[0x00C2] = (uint8) (xpos_max); - Memory.SRAM[0x00C3] = (uint8) (xpos_max >> 8); - Memory.SRAM[0x00C4] = (uint8) (ypos); - Memory.SRAM[0x00C5] = (uint8) (ypos >> 8); - Memory.SRAM[0x00C6] = (uint8) (ypos >> 16); - Memory.SRAM[0x00C7] = (uint8) (ypos >> 24); - Memory.SRAM[0x00C8] = (uint8) (xpos); - Memory.SRAM[0x00C9] = (uint8) (xpos >> 8); - Memory.SRAM[0x00CA] = (uint8) (xpos >> 16); - Memory.SRAM[0x00CB] = (uint8) (xpos >> 24); - Memory.SRAM[0x00CC] = (uint8) (rot); - Memory.SRAM[0x00CD] = (uint8) (rot >> 8); - Memory.SRAM[0x00D4] = (uint8) (speed); - Memory.SRAM[0x00D5] = (uint8) (speed >> 8); - Memory.SRAM[0x00DC] = (uint8) (flags); - Memory.SRAM[0x00DD] = (uint8) (flags >> 8); + Memory.SRAM[0x00C0]=(uint8)(ypos_max); + Memory.SRAM[0x00C1]=(uint8)(ypos_max >> 8); + Memory.SRAM[0x00C2]=(uint8)(xpos_max); + Memory.SRAM[0x00C3]=(uint8)(xpos_max >> 8); + Memory.SRAM[0x00C4]=(uint8)(ypos); + Memory.SRAM[0x00C5]=(uint8)(ypos >> 8); + Memory.SRAM[0x00C6]=(uint8)(ypos >> 16); + Memory.SRAM[0x00C7]=(uint8)(ypos >> 24); + Memory.SRAM[0x00C8]=(uint8)(xpos); + Memory.SRAM[0x00C9]=(uint8)(xpos >> 8); + Memory.SRAM[0x00CA]=(uint8)(xpos >> 16); + Memory.SRAM[0x00CB]=(uint8)(xpos >> 24); + Memory.SRAM[0x00CC]=(uint8)(rot); + Memory.SRAM[0x00CD]=(uint8)(rot >> 8); + Memory.SRAM[0x00D4]=(uint8)(speed); + Memory.SRAM[0x00D5]=(uint8)(speed >> 8); + Memory.SRAM[0x00DC]=(uint8)(flags); + Memory.SRAM[0x00DD]=(uint8)(flags >> 8); break; } - default: - #ifdef DEBUGGER - printf("Unknown Op\n"); - #endif - break; + default: + //printf("Unknown Op\n"); + break; } // lower signal: op processed - ST010.op_reg = 0; - ST010.execute = 0; + ST010.op_reg=0; + ST010.execute=0; } } + diff --git a/source/snes9x/seta011.cpp b/source/snes9x/seta011.cpp index 8dceb1b..9995283 100644 --- a/source/snes9x/seta011.cpp +++ b/source/snes9x/seta011.cpp @@ -159,135 +159,148 @@ **********************************************************************************/ -#include "snes9x.h" -#include "memmap.h" + +#include #include "seta.h" +#include "memmap.h" -static uint8 board[9][9]; // shougi playboard -static int line = 0; // line counter +ST011_Regs ST011; +// shougi playboard +uint8 board[9][9]; -uint8 S9xGetST011 (uint32 Address) +// debug +static int line = 0; + +uint8 S9xGetST011(uint32 Address) { - uint8 t; - uint16 address = (uint16) Address & 0xFFFF; + uint8 t; + uint16 address = (uint16) Address & 0xFFFF; + // line counter line++; // status check if (address == 0x01) - t = 0xFF; + { + t = 0xFF; + } + // read directly from s-ram else - t = Memory.SRAM[address]; // read directly from s-ram + { + t = Memory.SRAM[address]; + } -#ifdef DEBUGGER - if (address < 0x150) - printf("ST011 R: %06X %02X\n", Address, t); -#endif + // debug +// if(address<0x150) +// printf( "ST011 R: %06X %02X\n", Address, t); - return (t); + return t; } -void S9xSetST011 (uint32 Address, uint8 Byte) +void S9xSetST011(uint32 Address, uint8 Byte) { - static bool reset = false; - uint16 address = (uint16) Address & 0xFFFF; + uint16 address = (uint16) Address & 0xFFFF; + static bool reset = false; + // debug line++; - if (!reset) + if(!reset) { // bootup values ST011.waiting4command = true; reset = true; } -#ifdef DEBUGGER - if (address < 0x150) - printf("ST011 W: %06X %02X\n", Address, Byte); -#endif + // debug +// if(address<0x150) +// printf( "ST011 W: %06X %02X\n", Address, Byte ); - Memory.SRAM[address] = Byte; + Memory.SRAM[address]=Byte; // op commands/data goes through this address - if (address == 0x00) + if(address==0x00) { // check for new commands if (ST011.waiting4command) { ST011.waiting4command = false; - ST011.command = Byte; - ST011.in_index = 0; - ST011.out_index = 0; - - switch (ST011.command) + ST011.command = Byte; + ST011.in_index = 0; + ST011.out_index = 0; + switch(ST011.command) { - case 0x01: ST011.in_count = 12 * 10 + 8; break; - case 0x02: ST011.in_count = 4; break; - case 0x04: ST011.in_count = 0; break; - case 0x05: ST011.in_count = 0; break; - case 0x06: ST011.in_count = 0; break; - case 0x07: ST011.in_count = 0; break; - case 0x0E: ST011.in_count = 0; break; - default: ST011.waiting4command = true; break; + case 0x01: ST011.in_count = 12*10+8; break; + case 0x02: ST011.in_count = 4; break; + case 0x04: ST011.in_count = 0; break; + case 0x05: ST011.in_count = 0; break; + case 0x06: ST011.in_count = 0; break; + case 0x07: ST011.in_count = 0; break; + case 0x0E: ST011.in_count = 0; break; + default: ST011.waiting4command=true; break; } } else { - ST011.parameters[ST011.in_index] = Byte; + ST011.parameters [ST011.in_index] = Byte; ST011.in_index++; } } - if (ST011.in_count == ST011.in_index) + if (ST011.in_count==ST011.in_index) { - // actually execute the command + // Actually execute the command ST011.waiting4command = true; - ST011.out_index = 0; - + ST011.out_index = 0; switch (ST011.command) { - // unknown: download playboard - case 0x01: + // unknown: download playboard + case 0x01: + { // 9x9 board data: top to bottom, left to right // Values represent piece types and ownership - for (int lcv = 0; lcv < 9; lcv++) - memcpy(board[lcv], ST011.parameters + lcv * 10, 9 * 1); - break; + for( int lcv=0; lcv<9; lcv++ ) + memcpy( board[lcv], ST011.parameters+lcv*10, 9*1 ); + } + break; - // unknown - case 0x02: - break; + // unknown + case 0x02: break; - // unknown - case 0x04: + // unknown + case 0x04: + { // outputs Memory.SRAM[0x12C] = 0x00; //Memory.SRAM[0x12D] = 0x00; Memory.SRAM[0x12E] = 0x00; - break; + } + break; - // unknown - case 0x05: + // unknown + case 0x05: + { // outputs Memory.SRAM[0x12C] = 0x00; //Memory.SRAM[0x12D] = 0x00; Memory.SRAM[0x12E] = 0x00; - break; + } + break; - // unknown - case 0x06: - break; + // unknown + case 0x06: break; + case 0x07: break; - case 0x07: - break; - - // unknown - case 0x0E: + // unknown + case 0x0E: + { // outputs Memory.SRAM[0x12C] = 0x00; Memory.SRAM[0x12D] = 0x00; - break; + } + break; } } } + diff --git a/source/snes9x/seta018.cpp b/source/snes9x/seta018.cpp index 3b3f306..8dc6bff 100644 --- a/source/snes9x/seta018.cpp +++ b/source/snes9x/seta018.cpp @@ -159,17 +159,19 @@ **********************************************************************************/ -#include "snes9x.h" -#include "memmap.h" + #include "seta.h" +#include "memmap.h" -static int line; // line counter +ST018_Regs ST018; +static int line; // line counter -uint8 S9xGetST018 (uint32 Address) +extern "C"{ +uint8 S9xGetST018(uint32 Address) { - uint8 t = 0; - uint16 address = (uint16) Address & 0xFFFF; + uint8 t = 0; + uint16 address = (uint16) Address & 0xFFFF; line++; @@ -179,34 +181,29 @@ uint8 S9xGetST018 (uint32 Address) { if (ST018.out_count) { - t = (uint8) ST018.output[ST018.out_index]; + t = (uint8) ST018.output [ST018.out_index]; ST018.out_index++; - if (ST018.out_count == ST018.out_index) - ST018.out_count = 0; + if (ST018.out_count==ST018.out_index) + ST018.out_count=0; } else t = 0x81; } // status register - else - if (address == 0x3800) + else if (address == 0x3800) t = ST018.status; -#ifdef DEBUGGER - printf("ST018 R: %06X %02X\n", Address, t); -#endif + //printf( "ST018 R: %06X %02X\n", Address, t); - return (t); + return t; } -void S9xSetST018 (uint8 Byte, uint32 Address) +void S9xSetST018(uint8 Byte, uint32 Address) { - static bool reset = false; - uint16 address = (uint16) Address & 0xFFFF; + uint16 address = (uint16) Address&0xFFFF; + static bool reset = false; -#ifdef DEBUGGER - printf("ST018 W: %06X %02X\n", Address, Byte); -#endif + //printf( "ST018 W: %06X %02X\n", Address, Byte ); line++; @@ -214,38 +211,36 @@ void S9xSetST018 (uint8 Byte, uint32 Address) { // bootup values ST018.waiting4command = true; - ST018.part_command = 0; + ST018.part_command = 0; reset = true; } - Memory.SRAM[address] = Byte; + Memory.SRAM[address]=Byte; // default status for now ST018.status = 0x00; // op data goes through this address - if (address == 0x3804) + if (address==0x3804) { // check for new commands: 3 bytes length - if (ST018.waiting4command && ST018.part_command == 2) + if(ST018.waiting4command && ST018.part_command==2) { ST018.waiting4command = false; - ST018.in_index = 0; - ST018.out_index = 0; - ST018.part_command = 0; // 3-byte commands - ST018.pass = 0; // data streams into the chip ST018.command <<= 8; ST018.command |= Byte; - - switch (ST018.command & 0xFFFFFF) + ST018.in_index = 0; + ST018.out_index = 0; + ST018.part_command = 0; // 3-byte commands + ST018.pass = 0; // data streams into the chip + switch(ST018.command & 0xFFFFFF) { - case 0x0100: ST018.in_count = 0; break; - case 0xFF00: ST018.in_count = 0; break; - default: ST018.waiting4command = true; break; + case 0x0100: ST018.in_count = 0; break; + case 0xFF00: ST018.in_count = 0; break; + default: ST018.waiting4command = true; break; } } - else - if (ST018.waiting4command) + else if(ST018.waiting4command) { // 3-byte commands ST018.part_command++; @@ -254,84 +249,80 @@ void S9xSetST018 (uint8 Byte, uint32 Address) } } // extra parameters - else - if (address == 0x3802) + else if (address==0x3802) { ST018.parameters[ST018.in_index] = Byte; ST018.in_index++; } - if (ST018.in_count == ST018.in_index) + if (ST018.in_count==ST018.in_index) { - // qctually execute the command + // Actually execute the command ST018.waiting4command = true; - ST018.in_index = 0; - ST018.out_index = 0; - + ST018.in_index = 0; + ST018.out_index = 0; switch (ST018.command) { - // hardware check? - case 0x0100: - ST018.waiting4command = false; - ST018.pass++; + // hardware check? + case 0x0100: + ST018.waiting4command = false; + ST018.pass++; + if (ST018.pass==1) + { + ST018.in_count = 1; + ST018.out_count = 2; - if (ST018.pass == 1) - { - ST018.in_count = 1; - ST018.out_count = 2; + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; - // Overload's research - ST018.output[0x00] = 0x81; - ST018.output[0x01] = 0x81; - } - else - { - //ST018.in_count = 1; - ST018.out_count = 3; + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; - // no reason to change this - //ST018.output[0x00] = 0x81; - //ST018.output[0x01] = 0x81; - ST018.output[0x02] = 0x81; + // done processing requests + if (ST018.pass==3) + ST018.waiting4command = true; + } + break; - // done processing requests - if (ST018.pass == 3) - ST018.waiting4command = true; - } + // unknown: feels like a security detection + // format identical to 0x0100 + case 0xFF00: + ST018.waiting4command = false; + ST018.pass++; + if (ST018.pass==1) + { + ST018.in_count = 1; + ST018.out_count = 2; - break; + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; - // unknown: feels like a security detection - // format identical to 0x0100 - case 0xFF00: - ST018.waiting4command = false; - ST018.pass++; + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; - if (ST018.pass == 1) - { - ST018.in_count = 1; - ST018.out_count = 2; - - // Overload's research - ST018.output[0x00] = 0x81; - ST018.output[0x01] = 0x81; - } - else - { - //ST018.in_count = 1; - ST018.out_count = 3; - - // no reason to change this - //ST018.output[0x00] = 0x81; - //ST018.output[0x01] = 0x81; - ST018.output[0x02] = 0x81; - - // done processing requests - if (ST018.pass == 3) - ST018.waiting4command = true; - } - - break; + // done processing requests + if (ST018.pass==3) + ST018.waiting4command = true; + } + break; } } } +} + diff --git a/source/snes9x/snapshot.cpp b/source/snes9x/snapshot.cpp index c75a39e..2eee373 100644 --- a/source/snes9x/snapshot.cpp +++ b/source/snes9x/snapshot.cpp @@ -159,1800 +159,1689 @@ **********************************************************************************/ -#include -#include "snes9x.h" -#include "memmap.h" -#include "dma.h" -#include "apu/apu.h" -#include "fxinst.h" -#include "fxemu.h" -#include "sdd1.h" -#include "srtc.h" -#include "snapshot.h" -#include "controls.h" -#include "movie.h" -#include "display.h" -#include "language.h" -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include +#include +#include + +#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) +#include +#include +#include #endif -typedef struct -{ - int offset; - int offset2; - int size; - int type; - uint16 debuted_in; - uint16 deleted_in; - const char *name; -} FreezeData; +#include "snapshot.h" +#ifndef NGC +#include "snaporig.h" +#endif +#include "memmap.h" +#include "snes9x.h" +#include "65c816.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "apu.h" +#include "soundux.h" +#include "sa1.h" +#include "bsx.h" +#include "srtc.h" +#include "sdd1.h" +#include "spc7110.h" +//#include "movie.h" +#include "controls.h" +#include "dsp1.h" +#include "c4.h" +#ifndef ZSNES_FX + #include "fxinst.h" +#endif +#include "language.h" -enum -{ - INT_V, - uint8_ARRAY_V, - uint16_ARRAY_V, - uint32_ARRAY_V, - uint8_INDIR_ARRAY_V, - uint16_INDIR_ARRAY_V, - uint32_INDIR_ARRAY_V, - POINTER_V +#ifdef NGC +#include "freeze.h" +#include "gccore.h" +#endif + +//you would think everyone would have these +//since they're so useful. +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +extern uint8 *SRAM; + +#ifdef ZSNES_FX +START_EXTERN_C +void S9xSuperFXPreSaveState (); +void S9xSuperFXPostSaveState (); +void S9xSuperFXPostLoadState (); +END_EXTERN_C +#endif + +void S9xResetSaveTimer(bool8 dontsave){ + static time_t t=-1; + + if(!dontsave && t!=-1 && time(NULL)-t>300){{ +#ifndef NGC + char def [PATH_MAX]; + char filename [PATH_MAX]; + char drive [_MAX_DRIVE]; + char dir [_MAX_DIR]; + char ext [_MAX_EXT]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + sprintf(filename, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), + SLASH_STR, def, _MAX_EXT-1, "oops"); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, "Auto-saving 'oops' savestate"); + Snapshot(filename); +#endif + }} + t=time(NULL); +} + +bool8 S9xUnfreezeZSNES (const char *filename); + +typedef struct { + int offset; + int offset2; + int size; + int type; + uint16 debuted_in, deleted_in; + const char* name; +} FreezeData; + +enum { + INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V, uint8_INDIR_ARRAY_V, uint16_INDIR_ARRAY_V, uint32_INDIR_ARRAY_V, POINTER_V }; -#define COUNT(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) -#define Offset(field, structure) ((int) (((char *) (&(((structure) NULL)->field))) - ((char *) NULL))) -#define OFFSET(f) Offset(f, STRUCT *) -#define DUMMY(f) Offset(f, struct Obsolete *) -#define DELETED(f) (-1) +static struct Obsolete { + uint8 SPPU_Joypad1ButtonReadPos; + uint8 SPPU_Joypad2ButtonReadPos; + uint8 SPPU_Joypad3ButtonReadPos; + uint8 SPPU_MouseSpeed[2]; + uint8 SAPU_Flags; +} Obsolete; -#define INT_ENTRY(save_version_introduced, field) \ -{ \ - OFFSET(field), \ - 0, \ - sizeof(((STRUCT *) NULL)->field), \ - INT_V, \ - save_version_introduced, \ - 9999, \ - #field \ -} +#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) +#define SIZE_TO_ARRAY_TYPE(s) ((s)==1 ? uint8_ARRAY_V : ((s)==2 ? uint16_ARRAY_V : uint32_ARRAY_V)) -#define ARRAY_ENTRY(save_version_introduced, field, count, elemType) \ -{ \ - OFFSET(field), \ - 0, \ - count, \ - elemType, \ - save_version_introduced, \ - 9999, \ - #field \ -} - -#define POINTER_ENTRY(save_version_introduced, field, relativeToField) \ -{ \ - OFFSET(field), \ - OFFSET(relativeToField), \ - 4, \ - POINTER_V, \ - save_version_introduced, \ - 9999, \ - #field \ -} - -#define OBSOLETE_INT_ENTRY(save_version_introduced, save_version_removed, field) \ -{ \ - DUMMY(field), \ - 0, \ - sizeof(((struct Obsolete *) NULL)->field), \ - INT_V, \ - save_version_introduced, \ - save_version_removed, \ - #field \ -} - -#define OBSOLETE_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) \ -{ \ - DUMMY(field), \ - 0, \ - count, \ - elemType, \ - save_version_introduced, \ - save_version_removed, \ - #field \ -} - -#define OBSOLETE_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) \ -{ \ - DUMMY(field), \ - DUMMY(relativeToField), \ - 4, \ - POINTER_V, \ - save_version_introduced, \ - save_version_removed, \ - #field \ -} - -#define DELETED_INT_ENTRY(save_version_introduced, save_version_removed, field, size) \ -{ \ - DELETED(field), \ - 0, \ - size, \ - INT_V, \ - save_version_introduced, \ - save_version_removed, \ - #field \ -} - -#define DELETED_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) \ -{ \ - DELETED(field), \ - 0, \ - count, \ - elemType, \ - save_version_introduced, \ - save_version_removed, \ - #field \ -} - -#define DELETED_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) \ -{ \ - DELETED(field), \ - DELETED(relativeToField), \ - 4, \ - POINTER_V, \ - save_version_introduced, \ - save_version_removed, \ - #field \ -} - -struct SDMASnapshot -{ - struct SDMA dma[8]; -}; +#define Offset(field,structure) \ +((int) (((char *) (&(((structure)NULL)->field))) - ((char *) NULL))) +#define DUMMY(f) Offset(f,struct Obsolete *) +#define DELETED(f) (-1) +#define OFFSET(f) Offset(f, STRUCT *) +//#define ARRAY_ENTRY(save_version_introduced, field) {OFFSET(field), COUNT(((STRUCT*)NULL)->field), SIZE_TO_ARRAY_TYPE(sizeof(((STRUCT*)NULL)->field)), save_version_introduced, 9999} +#define INT_ENTRY(save_version_introduced, field) {OFFSET(field),0, sizeof(((STRUCT*)NULL)->field), INT_V, save_version_introduced, 9999, #field} +#define ARRAY_ENTRY(save_version_introduced, field, count, elemType) {OFFSET(field),0, count, elemType, save_version_introduced, 9999, #field} +#define POINTER_ENTRY(save_version_introduced, field, relativeToField) {OFFSET(field),OFFSET(relativeToField), 4, POINTER_V, save_version_introduced, 9999, #field} // size=4 -> (field - relativeToField) must fit in 4 bytes +#define OBSOLETE_INT_ENTRY(save_version_introduced, save_version_removed, field) {DUMMY(field),0, sizeof(((struct Obsolete*)NULL)->field), INT_V, save_version_introduced, save_version_removed, #field} +#define OBSOLETE_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) {DUMMY(field),0, count, elemType, save_version_introduced, save_version_removed, #field} +#define OBSOLETE_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) {DUMMY(field),DUMMY(relativeToField), 4, POINTER_V, save_version_introduced, save_version_removed, #field} // size=4 -> (field - relativeToField) must fit in 4 bytes +#define DELETED_INT_ENTRY(save_version_introduced, save_version_removed, field, size) {DELETED(field),0, size, INT_V, save_version_introduced, save_version_removed, #field} +#define DELETED_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) {DELETED(field),0, count, elemType, save_version_introduced, save_version_removed, #field} +#define DELETED_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) {DELETED(field),DELETED(relativeToField), 4, POINTER_V, save_version_introduced, save_version_removed, #field} // size=4 -> (field - relativeToField) must fit in 4 bytes struct SnapshotMovieInfo { uint32 MovieInputDataSize; }; -struct SnapshotScreenshotInfo -{ - uint16 Width; - uint16 Height; - uint8 Interlaced; - uint8 Data[MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3]; -}; - -static struct Obsolete -{ - uint8 reserved; -} Obsolete; - -#define STRUCT struct SCPUState - -static FreezeData SnapCPU[] = -{ - INT_ENTRY(6, Cycles), - INT_ENTRY(6, PrevCycles), - INT_ENTRY(6, V_Counter), - INT_ENTRY(6, Flags), - INT_ENTRY(6, IRQActive), - INT_ENTRY(6, IRQPending), - INT_ENTRY(6, MemSpeed), - INT_ENTRY(6, MemSpeedx2), - INT_ENTRY(6, FastROMSpeed), - INT_ENTRY(6, InDMA), - INT_ENTRY(6, InHDMA), - INT_ENTRY(6, InDMAorHDMA), - INT_ENTRY(6, InWRAMDMAorHDMA), - INT_ENTRY(6, HDMARanInDMA), - INT_ENTRY(6, WhichEvent), - INT_ENTRY(6, NextEvent), - INT_ENTRY(6, WaitingForInterrupt), - INT_ENTRY(6, WaitAddress), - INT_ENTRY(6, WaitCounter), - INT_ENTRY(6, PBPCAtOpcodeStart) -}; - #undef STRUCT -#define STRUCT struct SRegisters +#define STRUCT struct SnapshotMovieInfo -static FreezeData SnapRegisters[] = -{ - INT_ENTRY(6, PB), - INT_ENTRY(6, DB), - INT_ENTRY(6, P.W), - INT_ENTRY(6, A.W), - INT_ENTRY(6, D.W), - INT_ENTRY(6, S.W), - INT_ENTRY(6, X.W), - INT_ENTRY(6, Y.W), - INT_ENTRY(6, PCw) +#ifndef NGC + static FreezeData SnapMovie [] = { + INT_ENTRY(1, MovieInputDataSize), }; - -#undef STRUCT -#define STRUCT struct SPPU - -static FreezeData SnapPPU[] = -{ - INT_ENTRY(6, VMA.High), - INT_ENTRY(6, VMA.Increment), - INT_ENTRY(6, VMA.Address), - INT_ENTRY(6, VMA.Mask1), - INT_ENTRY(6, VMA.FullGraphicCount), - INT_ENTRY(6, VMA.Shift), - INT_ENTRY(6, WRAM), -#define O(N) \ - INT_ENTRY(6, BG[N].SCBase), \ - INT_ENTRY(6, BG[N].HOffset), \ - INT_ENTRY(6, BG[N].VOffset), \ - INT_ENTRY(6, BG[N].BGSize), \ - INT_ENTRY(6, BG[N].NameBase), \ - INT_ENTRY(6, BG[N].SCSize) - O(0), O(1), O(2), O(3), -#undef O - INT_ENTRY(6, BGMode), - INT_ENTRY(6, BG3Priority), - INT_ENTRY(6, CGFLIP), - INT_ENTRY(6, CGFLIPRead), - INT_ENTRY(6, CGADD), - ARRAY_ENTRY(6, CGDATA, 256, uint16_ARRAY_V), -#define O(N) \ - INT_ENTRY(6, OBJ[N].HPos), \ - INT_ENTRY(6, OBJ[N].VPos), \ - INT_ENTRY(6, OBJ[N].HFlip), \ - INT_ENTRY(6, OBJ[N].VFlip), \ - INT_ENTRY(6, OBJ[N].Name), \ - INT_ENTRY(6, OBJ[N].Priority), \ - INT_ENTRY(6, OBJ[N].Palette), \ - INT_ENTRY(6, OBJ[N].Size) - O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), - O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), - O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), - O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), - O( 32), O( 33), O( 34), O( 35), O( 36), O( 37), O( 38), O( 39), - O( 40), O( 41), O( 42), O( 43), O( 44), O( 45), O( 46), O( 47), - O( 48), O( 49), O( 50), O( 51), O( 52), O( 53), O( 54), O( 55), - O( 56), O( 57), O( 58), O( 59), O( 60), O( 61), O( 62), O( 63), - O( 64), O( 65), O( 66), O( 67), O( 68), O( 69), O( 70), O( 71), - O( 72), O( 73), O( 74), O( 75), O( 76), O( 77), O( 78), O( 79), - O( 80), O( 81), O( 82), O( 83), O( 84), O( 85), O( 86), O( 87), - O( 88), O( 89), O( 90), O( 91), O( 92), O( 93), O( 94), O( 95), - O( 96), O( 97), O( 98), O( 99), O(100), O(101), O(102), O(103), - O(104), O(105), O(106), O(107), O(108), O(109), O(110), O(111), - O(112), O(113), O(114), O(115), O(116), O(117), O(118), O(119), - O(120), O(121), O(122), O(123), O(124), O(125), O(126), O(127), -#undef O - INT_ENTRY(6, OBJThroughMain), - INT_ENTRY(6, OBJThroughSub), - INT_ENTRY(6, OBJAddition), - INT_ENTRY(6, OBJNameBase), - INT_ENTRY(6, OBJNameSelect), - INT_ENTRY(6, OBJSizeSelect), - INT_ENTRY(6, OAMAddr), - INT_ENTRY(6, SavedOAMAddr), - INT_ENTRY(6, OAMPriorityRotation), - INT_ENTRY(6, OAMFlip), - INT_ENTRY(6, OAMReadFlip), - INT_ENTRY(6, OAMTileAddress), - INT_ENTRY(6, OAMWriteRegister), - ARRAY_ENTRY(6, OAMData, 512 + 32, uint8_ARRAY_V), - INT_ENTRY(6, FirstSprite), - INT_ENTRY(6, LastSprite), - INT_ENTRY(6, HTimerEnabled), - INT_ENTRY(6, VTimerEnabled), - INT_ENTRY(6, HTimerPosition), - INT_ENTRY(6, VTimerPosition), - INT_ENTRY(6, IRQHBeamPos), - INT_ENTRY(6, IRQVBeamPos), - INT_ENTRY(6, HBeamFlip), - INT_ENTRY(6, VBeamFlip), - INT_ENTRY(6, HBeamPosLatched), - INT_ENTRY(6, VBeamPosLatched), - INT_ENTRY(6, GunHLatch), - INT_ENTRY(6, GunVLatch), - INT_ENTRY(6, HVBeamCounterLatched), - INT_ENTRY(6, Mode7HFlip), - INT_ENTRY(6, Mode7VFlip), - INT_ENTRY(6, Mode7Repeat), - INT_ENTRY(6, MatrixA), - INT_ENTRY(6, MatrixB), - INT_ENTRY(6, MatrixC), - INT_ENTRY(6, MatrixD), - INT_ENTRY(6, CentreX), - INT_ENTRY(6, CentreY), - INT_ENTRY(6, M7HOFS), - INT_ENTRY(6, M7VOFS), - INT_ENTRY(6, Mosaic), - INT_ENTRY(6, MosaicStart), - ARRAY_ENTRY(6, BGMosaic, 4, uint8_ARRAY_V), - INT_ENTRY(6, Window1Left), - INT_ENTRY(6, Window1Right), - INT_ENTRY(6, Window2Left), - INT_ENTRY(6, Window2Right), - INT_ENTRY(6, RecomputeClipWindows), -#define O(N) \ - INT_ENTRY(6, ClipCounts[N]), \ - INT_ENTRY(6, ClipWindowOverlapLogic[N]), \ - INT_ENTRY(6, ClipWindow1Enable[N]), \ - INT_ENTRY(6, ClipWindow2Enable[N]), \ - INT_ENTRY(6, ClipWindow1Inside[N]), \ - INT_ENTRY(6, ClipWindow2Inside[N]) - O(0), O(1), O(2), O(3), O(4), O(5), -#undef O - INT_ENTRY(6, ForcedBlanking), - INT_ENTRY(6, FixedColourRed), - INT_ENTRY(6, FixedColourGreen), - INT_ENTRY(6, FixedColourBlue), - INT_ENTRY(6, Brightness), - INT_ENTRY(6, ScreenHeight), - INT_ENTRY(6, Need16x8Mulitply), - INT_ENTRY(6, BGnxOFSbyte), - INT_ENTRY(6, M7byte), - INT_ENTRY(6, HDMA), - INT_ENTRY(6, HDMAEnded), - INT_ENTRY(6, OpenBus1), - INT_ENTRY(6, OpenBus2) -}; - -#undef STRUCT -#define STRUCT struct SDMASnapshot - -static FreezeData SnapDMA[] = -{ -#define O(N) \ - INT_ENTRY(6, dma[N].ReverseTransfer), \ - INT_ENTRY(6, dma[N].HDMAIndirectAddressing), \ - INT_ENTRY(6, dma[N].UnusedBit43x0), \ - INT_ENTRY(6, dma[N].AAddressFixed), \ - INT_ENTRY(6, dma[N].AAddressDecrement), \ - INT_ENTRY(6, dma[N].TransferMode), \ - INT_ENTRY(6, dma[N].BAddress), \ - INT_ENTRY(6, dma[N].AAddress), \ - INT_ENTRY(6, dma[N].ABank), \ - INT_ENTRY(6, dma[N].DMACount_Or_HDMAIndirectAddress), \ - INT_ENTRY(6, dma[N].IndirectBank), \ - INT_ENTRY(6, dma[N].Address), \ - INT_ENTRY(6, dma[N].Repeat), \ - INT_ENTRY(6, dma[N].LineCount), \ - INT_ENTRY(6, dma[N].UnknownByte), \ - INT_ENTRY(6, dma[N].DoTransfer) - O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) -#undef O -}; - -#undef STRUCT -#define STRUCT struct SControlSnapshot - -static FreezeData SnapControls[] = -{ - INT_ENTRY(6, ver), - ARRAY_ENTRY(6, port1_read_idx, 2, uint8_ARRAY_V), - ARRAY_ENTRY(6, dummy1, 4, uint8_ARRAY_V), - ARRAY_ENTRY(6, port2_read_idx, 2, uint8_ARRAY_V), - ARRAY_ENTRY(6, dummy2, 4, uint8_ARRAY_V), - ARRAY_ENTRY(6, mouse_speed, 2, uint8_ARRAY_V), - INT_ENTRY(6, justifier_select), - ARRAY_ENTRY(6, dummy3, 8, uint8_ARRAY_V), - INT_ENTRY(6, pad_read), - INT_ENTRY(6, pad_read_last), - ARRAY_ENTRY(6, internal, 60, uint8_ARRAY_V) -}; - -#undef STRUCT -#define STRUCT struct STimings - -static FreezeData SnapTimings[] = -{ - INT_ENTRY(6, H_Max_Master), - INT_ENTRY(6, H_Max), - INT_ENTRY(6, V_Max_Master), - INT_ENTRY(6, V_Max), - INT_ENTRY(6, HBlankStart), - INT_ENTRY(6, HBlankEnd), - INT_ENTRY(6, HDMAInit), - INT_ENTRY(6, HDMAStart), - INT_ENTRY(6, NMITriggerPos), - INT_ENTRY(6, WRAMRefreshPos), - INT_ENTRY(6, RenderPos), - INT_ENTRY(6, InterlaceField), - INT_ENTRY(6, DMACPUSync), - INT_ENTRY(6, NMIDMADelay), - INT_ENTRY(6, IRQPendCount), - INT_ENTRY(6, APUSpeedup) -}; - -#ifndef ZSNES_FX - -#undef STRUCT -#define STRUCT struct FxRegs_s - -static FreezeData SnapFX[] = -{ - ARRAY_ENTRY(6, avReg, 16, uint32_ARRAY_V), - INT_ENTRY(6, vColorReg), - INT_ENTRY(6, vPlotOptionReg), - INT_ENTRY(6, vStatusReg), - INT_ENTRY(6, vPrgBankReg), - INT_ENTRY(6, vRomBankReg), - INT_ENTRY(6, vRamBankReg), - INT_ENTRY(6, vCacheBaseReg), - INT_ENTRY(6, vCacheFlags), - INT_ENTRY(6, vLastRamAdr), - POINTER_ENTRY(6, pvDreg, avReg), - POINTER_ENTRY(6, pvSreg, avReg), - INT_ENTRY(6, vRomBuffer), - INT_ENTRY(6, vPipe), - INT_ENTRY(6, vPipeAdr), - INT_ENTRY(6, vSign), - INT_ENTRY(6, vZero), - INT_ENTRY(6, vCarry), - INT_ENTRY(6, vOverflow), - INT_ENTRY(6, vErrorCode), - INT_ENTRY(6, vIllegalAddress), - INT_ENTRY(6, bBreakPoint), - INT_ENTRY(6, vBreakPoint), - INT_ENTRY(6, vStepPoint), - INT_ENTRY(6, nRamBanks), - INT_ENTRY(6, nRomBanks), - INT_ENTRY(6, vMode), - INT_ENTRY(6, vPrevMode), - POINTER_ENTRY(6, pvScreenBase, pvRam), -#define O(N) \ - POINTER_ENTRY(6, apvScreen[N], pvRam) - O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), - O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), - O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), - O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), -#undef O - ARRAY_ENTRY(6, x, 32, uint32_ARRAY_V), - INT_ENTRY(6, vScreenHeight), - INT_ENTRY(6, vScreenRealHeight), - INT_ENTRY(6, vPrevScreenHeight), - INT_ENTRY(6, vScreenSize), - POINTER_ENTRY(6, pvRamBank, apvRamBank), - POINTER_ENTRY(6, pvRomBank, apvRomBank), - POINTER_ENTRY(6, pvPrgBank, apvRomBank), -#define O(N) \ - POINTER_ENTRY(6, apvRamBank[N], pvRam) - O(0), O(1), O(2), O(3), -#undef O - INT_ENTRY(6, bCacheActive), - POINTER_ENTRY(6, pvCache, pvRegisters), - ARRAY_ENTRY(6, avCacheBackup, 512, uint8_ARRAY_V), - INT_ENTRY(6, vCounter), - INT_ENTRY(6, vInstCount), - INT_ENTRY(6, vSCBRDirty) -}; - #endif #undef STRUCT -#define STRUCT struct SSA1 +#define STRUCT struct SCPUState -static FreezeData SnapSA1[] = -{ - INT_ENTRY(6, CPUExecuting), - INT_ENTRY(6, ShiftedPB), - INT_ENTRY(6, ShiftedDB), - INT_ENTRY(6, Flags), - INT_ENTRY(6, IRQActive), - INT_ENTRY(6, Waiting), - INT_ENTRY(6, WaitingForInterrupt), - INT_ENTRY(6, WaitAddress), - INT_ENTRY(6, WaitCounter), - INT_ENTRY(6, PBPCAtOpcodeStart), - INT_ENTRY(6, Executing), - INT_ENTRY(6, overflow), - INT_ENTRY(6, in_char_dma), - INT_ENTRY(6, op1), - INT_ENTRY(6, op2), - INT_ENTRY(6, arithmetic_op), - INT_ENTRY(6, sum), - INT_ENTRY(6, VirtualBitmapFormat), - INT_ENTRY(6, variable_bit_pos) +static FreezeData SnapCPU [] = { + INT_ENTRY(1, Flags), + INT_ENTRY(1, BranchSkip), + DELETED_INT_ENTRY(1,4, NMIActive,1), + INT_ENTRY(1, IRQActive), + INT_ENTRY(1, WaitingForInterrupt), + INT_ENTRY(1, WhichEvent), + INT_ENTRY(1, Cycles), + INT_ENTRY(1, NextEvent), + INT_ENTRY(1, V_Counter), + INT_ENTRY(1, MemSpeed), + INT_ENTRY(1, MemSpeedx2), + INT_ENTRY(1, FastROMSpeed), + // not sure if the following are necessary + INT_ENTRY(3, InDMAorHDMA), + INT_ENTRY(3, InWRAMDMAorHDMA), + INT_ENTRY(3, PBPCAtOpcodeStart), + INT_ENTRY(3, WaitAddress), + INT_ENTRY(3, WaitCounter), + DELETED_INT_ENTRY(3,4, AutoSaveTimer,4), + DELETED_INT_ENTRY(3,4, SRAMModified,1), + DELETED_INT_ENTRY(3,4, BRKTriggered,1), + INT_ENTRY(3, TriedInterleavedMode2), // deprecated + INT_ENTRY(4, IRQPending), // essential + INT_ENTRY(4, InDMA), + INT_ENTRY(4, InHDMA), + INT_ENTRY(4, HDMARanInDMA), + INT_ENTRY(4, PrevCycles), }; #undef STRUCT -#define STRUCT struct SSA1Registers +#define STRUCT struct SRegisters -static FreezeData SnapSA1Registers[] = -{ - INT_ENTRY(6, PB), - INT_ENTRY(6, DB), - INT_ENTRY(6, P.W), - INT_ENTRY(6, A.W), - INT_ENTRY(6, D.W), - INT_ENTRY(6, S.W), - INT_ENTRY(6, X.W), - INT_ENTRY(6, Y.W), - INT_ENTRY(6, PCw) +static FreezeData SnapRegisters [] = { + INT_ENTRY(1, PB), + INT_ENTRY(1, DB), + INT_ENTRY(1, P.W), + INT_ENTRY(1, A.W), + INT_ENTRY(1, D.W), + INT_ENTRY(1, S.W), + INT_ENTRY(1, X.W), + INT_ENTRY(1, Y.W), + INT_ENTRY(1, PCw), }; #undef STRUCT -#define STRUCT struct SDSP1 +#define STRUCT struct SPPU -static FreezeData SnapDSP1[] = -{ - INT_ENTRY(6, waiting4command), - INT_ENTRY(6, first_parameter), - INT_ENTRY(6, command), - INT_ENTRY(6, in_count), - INT_ENTRY(6, in_index), - INT_ENTRY(6, out_count), - INT_ENTRY(6, out_index), - ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), - ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), - INT_ENTRY(6, CentreX), - INT_ENTRY(6, CentreY), - INT_ENTRY(6, VOffset), - INT_ENTRY(6, VPlane_C), - INT_ENTRY(6, VPlane_E), - INT_ENTRY(6, SinAas), - INT_ENTRY(6, CosAas), - INT_ENTRY(6, SinAzs), - INT_ENTRY(6, CosAzs), - INT_ENTRY(6, SinAZS), - INT_ENTRY(6, CosAZS), - INT_ENTRY(6, SecAZS_C1), - INT_ENTRY(6, SecAZS_E1), - INT_ENTRY(6, SecAZS_C2), - INT_ENTRY(6, SecAZS_E2), - INT_ENTRY(6, Nx), - INT_ENTRY(6, Ny), - INT_ENTRY(6, Nz), - INT_ENTRY(6, Gx), - INT_ENTRY(6, Gy), - INT_ENTRY(6, Gz), - INT_ENTRY(6, C_Les), - INT_ENTRY(6, E_Les), - INT_ENTRY(6, G_Les), +static FreezeData SnapPPU [] = { + INT_ENTRY(1, BGMode), + INT_ENTRY(1, BG3Priority), + INT_ENTRY(1, Brightness), + INT_ENTRY(1, VMA.High), + INT_ENTRY(1, VMA.Increment), + INT_ENTRY(1, VMA.Address), + INT_ENTRY(1, VMA.Mask1), + INT_ENTRY(1, VMA.FullGraphicCount), + INT_ENTRY(1, VMA.Shift), + INT_ENTRY(1, BG[0].SCBase), + INT_ENTRY(1, BG[0].VOffset), + INT_ENTRY(1, BG[0].HOffset), + INT_ENTRY(1, BG[0].BGSize), + INT_ENTRY(1, BG[0].NameBase), + INT_ENTRY(1, BG[0].SCSize), + + INT_ENTRY(1, BG[1].SCBase), + INT_ENTRY(1, BG[1].VOffset), + INT_ENTRY(1, BG[1].HOffset), + INT_ENTRY(1, BG[1].BGSize), + INT_ENTRY(1, BG[1].NameBase), + INT_ENTRY(1, BG[1].SCSize), + + INT_ENTRY(1, BG[2].SCBase), + INT_ENTRY(1, BG[2].VOffset), + INT_ENTRY(1, BG[2].HOffset), + INT_ENTRY(1, BG[2].BGSize), + INT_ENTRY(1, BG[2].NameBase), + INT_ENTRY(1, BG[2].SCSize), + + INT_ENTRY(1, BG[3].SCBase), + INT_ENTRY(1, BG[3].VOffset), + INT_ENTRY(1, BG[3].HOffset), + INT_ENTRY(1, BG[3].BGSize), + INT_ENTRY(1, BG[3].NameBase), + INT_ENTRY(1, BG[3].SCSize), + + INT_ENTRY(1, CGFLIP), + ARRAY_ENTRY(1, CGDATA, 256, uint16_ARRAY_V), + INT_ENTRY(1, FirstSprite), + INT_ENTRY(3, LastSprite), #define O(N) \ - ARRAY_ENTRY(6, matrixA[N], 3, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, matrixB[N], 3, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, matrixC[N], 3, uint16_ARRAY_V) - O(0), O(1), O(2), + INT_ENTRY(1, OBJ[N].HPos), \ + INT_ENTRY(1, OBJ[N].VPos), \ + INT_ENTRY(1, OBJ[N].Name), \ + INT_ENTRY(1, OBJ[N].VFlip), \ + INT_ENTRY(1, OBJ[N].HFlip), \ + INT_ENTRY(1, OBJ[N].Priority), \ + INT_ENTRY(1, OBJ[N].Palette), \ + INT_ENTRY(1, OBJ[N].Size) + + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), + O( 32), O( 33), O( 34), O( 35), O( 36), O( 37), O( 38), O( 39), + O( 40), O( 41), O( 42), O( 43), O( 44), O( 45), O( 46), O( 47), + O( 48), O( 49), O( 50), O( 51), O( 52), O( 53), O( 54), O( 55), + O( 56), O( 57), O( 58), O( 59), O( 60), O( 61), O( 62), O( 63), + O( 64), O( 65), O( 66), O( 67), O( 68), O( 69), O( 70), O( 71), + O( 72), O( 73), O( 74), O( 75), O( 76), O( 77), O( 78), O( 79), + O( 80), O( 81), O( 82), O( 83), O( 84), O( 85), O( 86), O( 87), + O( 88), O( 89), O( 90), O( 91), O( 92), O( 93), O( 94), O( 95), + O( 96), O( 97), O( 98), O( 99), O(100), O(101), O(102), O(103), + O(104), O(105), O(106), O(107), O(108), O(109), O(110), O(111), + O(112), O(113), O(114), O(115), O(116), O(117), O(118), O(119), + O(120), O(121), O(122), O(123), O(124), O(125), O(126), O(127), #undef O - INT_ENTRY(6, Op00Multiplicand), - INT_ENTRY(6, Op00Multiplier), - INT_ENTRY(6, Op00Result), - INT_ENTRY(6, Op20Multiplicand), - INT_ENTRY(6, Op20Multiplier), - INT_ENTRY(6, Op20Result), - INT_ENTRY(6, Op10Coefficient), - INT_ENTRY(6, Op10Exponent), - INT_ENTRY(6, Op10CoefficientR), - INT_ENTRY(6, Op10ExponentR), - INT_ENTRY(6, Op04Angle), - INT_ENTRY(6, Op04Radius), - INT_ENTRY(6, Op04Sin), - INT_ENTRY(6, Op04Cos), - INT_ENTRY(6, Op0CA), - INT_ENTRY(6, Op0CX1), - INT_ENTRY(6, Op0CY1), - INT_ENTRY(6, Op0CX2), - INT_ENTRY(6, Op0CY2), - INT_ENTRY(6, Op02FX), - INT_ENTRY(6, Op02FY), - INT_ENTRY(6, Op02FZ), - INT_ENTRY(6, Op02LFE), - INT_ENTRY(6, Op02LES), - INT_ENTRY(6, Op02AAS), - INT_ENTRY(6, Op02AZS), - INT_ENTRY(6, Op02VOF), - INT_ENTRY(6, Op02VVA), - INT_ENTRY(6, Op02CX), - INT_ENTRY(6, Op02CY), - INT_ENTRY(6, Op0AVS), - INT_ENTRY(6, Op0AA), - INT_ENTRY(6, Op0AB), - INT_ENTRY(6, Op0AC), - INT_ENTRY(6, Op0AD), - INT_ENTRY(6, Op06X), - INT_ENTRY(6, Op06Y), - INT_ENTRY(6, Op06Z), - INT_ENTRY(6, Op06H), - INT_ENTRY(6, Op06V), - INT_ENTRY(6, Op06M), - INT_ENTRY(6, Op01m), - INT_ENTRY(6, Op01Zr), - INT_ENTRY(6, Op01Xr), - INT_ENTRY(6, Op01Yr), - INT_ENTRY(6, Op11m), - INT_ENTRY(6, Op11Zr), - INT_ENTRY(6, Op11Xr), - INT_ENTRY(6, Op11Yr), - INT_ENTRY(6, Op21m), - INT_ENTRY(6, Op21Zr), - INT_ENTRY(6, Op21Xr), - INT_ENTRY(6, Op21Yr), - INT_ENTRY(6, Op0DX), - INT_ENTRY(6, Op0DY), - INT_ENTRY(6, Op0DZ), - INT_ENTRY(6, Op0DF), - INT_ENTRY(6, Op0DL), - INT_ENTRY(6, Op0DU), - INT_ENTRY(6, Op1DX), - INT_ENTRY(6, Op1DY), - INT_ENTRY(6, Op1DZ), - INT_ENTRY(6, Op1DF), - INT_ENTRY(6, Op1DL), - INT_ENTRY(6, Op1DU), - INT_ENTRY(6, Op2DX), - INT_ENTRY(6, Op2DY), - INT_ENTRY(6, Op2DZ), - INT_ENTRY(6, Op2DF), - INT_ENTRY(6, Op2DL), - INT_ENTRY(6, Op2DU), - INT_ENTRY(6, Op03F), - INT_ENTRY(6, Op03L), - INT_ENTRY(6, Op03U), - INT_ENTRY(6, Op03X), - INT_ENTRY(6, Op03Y), - INT_ENTRY(6, Op03Z), - INT_ENTRY(6, Op13F), - INT_ENTRY(6, Op13L), - INT_ENTRY(6, Op13U), - INT_ENTRY(6, Op13X), - INT_ENTRY(6, Op13Y), - INT_ENTRY(6, Op13Z), - INT_ENTRY(6, Op23F), - INT_ENTRY(6, Op23L), - INT_ENTRY(6, Op23U), - INT_ENTRY(6, Op23X), - INT_ENTRY(6, Op23Y), - INT_ENTRY(6, Op23Z), - INT_ENTRY(6, Op14Zr), - INT_ENTRY(6, Op14Xr), - INT_ENTRY(6, Op14Yr), - INT_ENTRY(6, Op14U), - INT_ENTRY(6, Op14F), - INT_ENTRY(6, Op14L), - INT_ENTRY(6, Op14Zrr), - INT_ENTRY(6, Op14Xrr), - INT_ENTRY(6, Op14Yrr), - INT_ENTRY(6, Op0EH), - INT_ENTRY(6, Op0EV), - INT_ENTRY(6, Op0EX), - INT_ENTRY(6, Op0EY), - INT_ENTRY(6, Op0BX), - INT_ENTRY(6, Op0BY), - INT_ENTRY(6, Op0BZ), - INT_ENTRY(6, Op0BS), - INT_ENTRY(6, Op1BX), - INT_ENTRY(6, Op1BY), - INT_ENTRY(6, Op1BZ), - INT_ENTRY(6, Op1BS), - INT_ENTRY(6, Op2BX), - INT_ENTRY(6, Op2BY), - INT_ENTRY(6, Op2BZ), - INT_ENTRY(6, Op2BS), - INT_ENTRY(6, Op28X), - INT_ENTRY(6, Op28Y), - INT_ENTRY(6, Op28Z), - INT_ENTRY(6, Op28R), - INT_ENTRY(6, Op1CX), - INT_ENTRY(6, Op1CY), - INT_ENTRY(6, Op1CZ), - INT_ENTRY(6, Op1CXBR), - INT_ENTRY(6, Op1CYBR), - INT_ENTRY(6, Op1CZBR), - INT_ENTRY(6, Op1CXAR), - INT_ENTRY(6, Op1CYAR), - INT_ENTRY(6, Op1CZAR), - INT_ENTRY(6, Op1CX1), - INT_ENTRY(6, Op1CY1), - INT_ENTRY(6, Op1CZ1), - INT_ENTRY(6, Op1CX2), - INT_ENTRY(6, Op1CY2), - INT_ENTRY(6, Op1CZ2), - INT_ENTRY(6, Op0FRamsize), - INT_ENTRY(6, Op0FPass), - INT_ENTRY(6, Op2FUnknown), - INT_ENTRY(6, Op2FSize), - INT_ENTRY(6, Op08X), - INT_ENTRY(6, Op08Y), - INT_ENTRY(6, Op08Z), - INT_ENTRY(6, Op08Ll), - INT_ENTRY(6, Op08Lh), - INT_ENTRY(6, Op18X), - INT_ENTRY(6, Op18Y), - INT_ENTRY(6, Op18Z), - INT_ENTRY(6, Op18R), - INT_ENTRY(6, Op18D), - INT_ENTRY(6, Op38X), - INT_ENTRY(6, Op38Y), - INT_ENTRY(6, Op38Z), - INT_ENTRY(6, Op38R), - INT_ENTRY(6, Op38D) -}; - -#undef STRUCT -#define STRUCT struct SDSP2 - -static FreezeData SnapDSP2[] = -{ - INT_ENTRY(6, waiting4command), - INT_ENTRY(6, command), - INT_ENTRY(6, in_count), - INT_ENTRY(6, in_index), - INT_ENTRY(6, out_count), - INT_ENTRY(6, out_index), - ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), - ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), - INT_ENTRY(6, Op05HasLen), - INT_ENTRY(6, Op05Len), - INT_ENTRY(6, Op05Transparent), - INT_ENTRY(6, Op06HasLen), - INT_ENTRY(6, Op06Len), - INT_ENTRY(6, Op09Word1), - INT_ENTRY(6, Op09Word2), - INT_ENTRY(6, Op0DHasLen), - INT_ENTRY(6, Op0DOutLen), - INT_ENTRY(6, Op0DInLen) -}; - -#undef STRUCT -#define STRUCT struct SDSP4 - -static FreezeData SnapDSP4[] = -{ - INT_ENTRY(6, waiting4command), - INT_ENTRY(6, half_command), - INT_ENTRY(6, command), - INT_ENTRY(6, in_count), - INT_ENTRY(6, in_index), - INT_ENTRY(6, out_count), - INT_ENTRY(6, out_index), - ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), - ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), - INT_ENTRY(6, byte), - INT_ENTRY(6, address), - INT_ENTRY(6, Logic), - INT_ENTRY(6, lcv), - INT_ENTRY(6, distance), - INT_ENTRY(6, raster), - INT_ENTRY(6, segments), - INT_ENTRY(6, world_x), - INT_ENTRY(6, world_y), - INT_ENTRY(6, world_dx), - INT_ENTRY(6, world_dy), - INT_ENTRY(6, world_ddx), - INT_ENTRY(6, world_ddy), - INT_ENTRY(6, world_xenv), - INT_ENTRY(6, world_yofs), - INT_ENTRY(6, view_x1), - INT_ENTRY(6, view_y1), - INT_ENTRY(6, view_x2), - INT_ENTRY(6, view_y2), - INT_ENTRY(6, view_dx), - INT_ENTRY(6, view_dy), - INT_ENTRY(6, view_xofs1), - INT_ENTRY(6, view_yofs1), - INT_ENTRY(6, view_xofs2), - INT_ENTRY(6, view_yofs2), - INT_ENTRY(6, view_yofsenv), - INT_ENTRY(6, view_turnoff_x), - INT_ENTRY(6, view_turnoff_dx), - INT_ENTRY(6, viewport_cx), - INT_ENTRY(6, viewport_cy), - INT_ENTRY(6, viewport_left), - INT_ENTRY(6, viewport_right), - INT_ENTRY(6, viewport_top), - INT_ENTRY(6, viewport_bottom), - INT_ENTRY(6, sprite_x), - INT_ENTRY(6, sprite_y), - INT_ENTRY(6, sprite_attr), - INT_ENTRY(6, sprite_size), - INT_ENTRY(6, sprite_clipy), - INT_ENTRY(6, sprite_count), + INT_ENTRY(1, OAMPriorityRotation), + INT_ENTRY(1, OAMAddr), + INT_ENTRY(1, OAMFlip), + INT_ENTRY(1, OAMTileAddress), + INT_ENTRY(1, IRQVBeamPos), + INT_ENTRY(1, IRQHBeamPos), + INT_ENTRY(1, VBeamPosLatched), + INT_ENTRY(1, HBeamPosLatched), + INT_ENTRY(1, HBeamFlip), + INT_ENTRY(1, VBeamFlip), + INT_ENTRY(1, HVBeamCounterLatched), + INT_ENTRY(1, MatrixA), + INT_ENTRY(1, MatrixB), + INT_ENTRY(1, MatrixC), + INT_ENTRY(1, MatrixD), + INT_ENTRY(1, CentreX), + INT_ENTRY(1, CentreY), + INT_ENTRY(2, M7HOFS), + INT_ENTRY(2, M7VOFS), + OBSOLETE_INT_ENTRY(1,2, SPPU_Joypad1ButtonReadPos), + OBSOLETE_INT_ENTRY(1,2, SPPU_Joypad2ButtonReadPos), + OBSOLETE_INT_ENTRY(1,2, SPPU_Joypad3ButtonReadPos), + INT_ENTRY(1, CGADD), + INT_ENTRY(1, FixedColourRed), + INT_ENTRY(1, FixedColourGreen), + INT_ENTRY(1, FixedColourBlue), + INT_ENTRY(1, SavedOAMAddr), + INT_ENTRY(1, ScreenHeight), + INT_ENTRY(1, WRAM), + DELETED_INT_ENTRY(3,3, BG_Forced,1), + INT_ENTRY(1, ForcedBlanking), + INT_ENTRY(3, OBJThroughMain), + INT_ENTRY(3, OBJThroughSub), + INT_ENTRY(1, OBJNameSelect), + INT_ENTRY(1, OBJSizeSelect), + INT_ENTRY(1, OBJNameBase), + INT_ENTRY(3, OBJAddition), + INT_ENTRY(1, OAMReadFlip), + INT_ENTRY(1, VTimerEnabled), + INT_ENTRY(1, HTimerEnabled), + INT_ENTRY(1, HTimerPosition), + INT_ENTRY(1, Mosaic), + INT_ENTRY(3, MosaicStart), + INT_ENTRY(1, Mode7HFlip), + INT_ENTRY(1, Mode7VFlip), + INT_ENTRY(1, Mode7Repeat), + INT_ENTRY(1, Window1Left), + INT_ENTRY(1, Window1Right), + INT_ENTRY(1, Window2Left), + INT_ENTRY(1, Window2Right), #define O(N) \ - ARRAY_ENTRY(6, poly_clipLf[N], 2, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, poly_clipRt[N], 2, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, poly_ptr[N], 2, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, poly_raster[N], 2, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, poly_top[N], 2, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, poly_bottom[N], 2, uint16_ARRAY_V), \ - ARRAY_ENTRY(6, poly_cx[N], 2, uint16_ARRAY_V) - O(0), O(1), + INT_ENTRY(3, ClipCounts[N]), \ + INT_ENTRY(1, ClipWindowOverlapLogic[N]), \ + INT_ENTRY(1, ClipWindow1Enable[N]), \ + INT_ENTRY(1, ClipWindow2Enable[N]), \ + INT_ENTRY(1, ClipWindow1Inside[N]), \ + INT_ENTRY(1, ClipWindow2Inside[N]) + + O(0), O(1), O(2), O(3), O(4), O(5), #undef O - ARRAY_ENTRY(6, poly_start, 2, uint16_ARRAY_V), - ARRAY_ENTRY(6, poly_plane, 2, uint16_ARRAY_V), - ARRAY_ENTRY(6, OAM_attr, 16, uint16_ARRAY_V), - INT_ENTRY(6, OAM_index), - INT_ENTRY(6, OAM_bits), - INT_ENTRY(6, OAM_RowMax), - ARRAY_ENTRY(6, OAM_Row, 32, uint16_ARRAY_V) + INT_ENTRY(3, RecomputeClipWindows), + INT_ENTRY(1, CGFLIPRead), + INT_ENTRY(1, Need16x8Mulitply), + ARRAY_ENTRY(1, BGMosaic, 4, uint8_ARRAY_V), + ARRAY_ENTRY(1, OAMData, 512 + 32, uint8_ARRAY_V), + INT_ENTRY(1, Need16x8Mulitply), + OBSOLETE_ARRAY_ENTRY(1,2, SPPU_MouseSpeed, 2, uint8_ARRAY_V), + INT_ENTRY(2, OAMWriteRegister), + INT_ENTRY(2, BGnxOFSbyte), + INT_ENTRY(2, M7byte), + INT_ENTRY(2, OpenBus1), + INT_ENTRY(2, OpenBus2), + INT_ENTRY(3, GunVLatch), + INT_ENTRY(3, GunHLatch), + INT_ENTRY(2, VTimerPosition), + + INT_ENTRY(5, HDMA), + INT_ENTRY(5, HDMAEnded), }; #undef STRUCT -#define STRUCT struct SST010 +#define STRUCT struct SDMA -static FreezeData SnapST010[] = -{ - ARRAY_ENTRY(6, input_params, 16, uint8_ARRAY_V), - ARRAY_ENTRY(6, output_params, 16, uint8_ARRAY_V), - INT_ENTRY(6, op_reg), - INT_ENTRY(6, execute), - INT_ENTRY(6, control_enable) -}; - -#undef STRUCT -#define STRUCT struct SOBC1 - -static FreezeData SnapOBC1[] = -{ - INT_ENTRY(6, address), - INT_ENTRY(6, basePtr), - INT_ENTRY(6, shift) -}; - -#undef STRUCT -#define STRUCT struct SSPC7110Snapshot - -static FreezeData SnapSPC7110Snap[] = -{ - INT_ENTRY(6, r4801), - INT_ENTRY(6, r4802), - INT_ENTRY(6, r4803), - INT_ENTRY(6, r4804), - INT_ENTRY(6, r4805), - INT_ENTRY(6, r4806), - INT_ENTRY(6, r4807), - INT_ENTRY(6, r4808), - INT_ENTRY(6, r4809), - INT_ENTRY(6, r480a), - INT_ENTRY(6, r480b), - INT_ENTRY(6, r480c), - INT_ENTRY(6, r4811), - INT_ENTRY(6, r4812), - INT_ENTRY(6, r4813), - INT_ENTRY(6, r4814), - INT_ENTRY(6, r4815), - INT_ENTRY(6, r4816), - INT_ENTRY(6, r4817), - INT_ENTRY(6, r4818), - INT_ENTRY(6, r481x), - INT_ENTRY(6, r4814_latch), - INT_ENTRY(6, r4815_latch), - INT_ENTRY(6, r4820), - INT_ENTRY(6, r4821), - INT_ENTRY(6, r4822), - INT_ENTRY(6, r4823), - INT_ENTRY(6, r4824), - INT_ENTRY(6, r4825), - INT_ENTRY(6, r4826), - INT_ENTRY(6, r4827), - INT_ENTRY(6, r4828), - INT_ENTRY(6, r4829), - INT_ENTRY(6, r482a), - INT_ENTRY(6, r482b), - INT_ENTRY(6, r482c), - INT_ENTRY(6, r482d), - INT_ENTRY(6, r482e), - INT_ENTRY(6, r482f), - INT_ENTRY(6, r4830), - INT_ENTRY(6, r4831), - INT_ENTRY(6, r4832), - INT_ENTRY(6, r4833), - INT_ENTRY(6, r4834), - INT_ENTRY(6, dx_offset), - INT_ENTRY(6, ex_offset), - INT_ENTRY(6, fx_offset), - INT_ENTRY(6, r4840), - INT_ENTRY(6, r4841), - INT_ENTRY(6, r4842), - INT_ENTRY(6, rtc_state), - INT_ENTRY(6, rtc_mode), - INT_ENTRY(6, rtc_index), - INT_ENTRY(6, decomp_mode), - INT_ENTRY(6, decomp_offset), - ARRAY_ENTRY(6, decomp_buffer, SPC7110_DECOMP_BUFFER_SIZE, uint8_ARRAY_V), - INT_ENTRY(6, decomp_buffer_rdoffset), - INT_ENTRY(6, decomp_buffer_wroffset), - INT_ENTRY(6, decomp_buffer_length), +static FreezeData SnapDMA [] = { #define O(N) \ - INT_ENTRY(6, context[N].index), \ - INT_ENTRY(6, context[N].invert) - O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), - O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), - O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), - O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31) + {OFFSET (ReverseTransfer) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "ReverseTransfer"}, \ + {OFFSET (AAddressFixed) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "AAddressFixed"}, \ + {OFFSET (AAddressDecrement) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "AAddressDecrement"}, \ + {OFFSET (TransferMode) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "TransferMode"}, \ + {OFFSET (ABank) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "ABank"}, \ + {OFFSET (AAddress) + N * sizeof (struct SDMA),0, 2, INT_V, 1, 9999, "AAddress"}, \ + {OFFSET (Address) + N * sizeof (struct SDMA),0, 2, INT_V, 1, 9999, "Address"}, \ + {OFFSET (BAddress) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "BAddress"}, \ + {DELETED (TransferBytes),0, 2, INT_V, 1, 2, "TransferBytes"}, \ + {OFFSET (HDMAIndirectAddressing) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "HDMAIndirectAddressing"}, \ + {OFFSET (DMACount_Or_HDMAIndirectAddress) + N * sizeof (struct SDMA),0, 2, INT_V, 1, 9999, "DMACount_Or_HDMAIndirectAddress"}, \ + {OFFSET (IndirectBank) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "IndirectBank"}, \ + {OFFSET (Repeat) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "Repeat"}, \ + {OFFSET (LineCount) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "LineCount"}, \ + {OFFSET (DoTransfer) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "DoTransfer"}, \ + {OFFSET (UnknownByte) + N * sizeof (struct SDMA),0, 1, INT_V, 2, 9999, "UnknownByte"}, \ + {OFFSET (UnusedBit43x0) + N * sizeof (struct SDMA),0, 1, INT_V, 2, 9999, "UnusedBit43x0"} + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) #undef O }; #undef STRUCT -#define STRUCT struct SSRTCSnapshot +#define STRUCT struct SAPU -static FreezeData SnapSRTCSnap[] = -{ - INT_ENTRY(6, rtc_mode), - INT_ENTRY(6, rtc_index) +static FreezeData SnapAPU [] = { + INT_ENTRY(1, OldCycles), + INT_ENTRY(1, ShowROM), + OBSOLETE_INT_ENTRY(1,2, SAPU_Flags), + INT_ENTRY(2, Flags), + INT_ENTRY(1, KeyedChannels), + ARRAY_ENTRY(1, OutPorts, 4, uint8_ARRAY_V), + ARRAY_ENTRY(1, DSP, 0x80, uint8_ARRAY_V), + ARRAY_ENTRY(1, ExtraRAM, 64, uint8_ARRAY_V), + ARRAY_ENTRY(1, Timer, 3, uint16_ARRAY_V), + ARRAY_ENTRY(1, TimerTarget, 3, uint16_ARRAY_V), + ARRAY_ENTRY(1, TimerEnabled, 3, uint8_ARRAY_V), + ARRAY_ENTRY(1, TimerValueWritten, 3, uint8_ARRAY_V), + INT_ENTRY(4, Cycles), + INT_ENTRY(5, NextAPUTimerPos), + INT_ENTRY(5, APUTimerCounter), }; #undef STRUCT -#define STRUCT struct SBSX +#define STRUCT struct SAPURegisters -static FreezeData SnapBSX[] = -{ - INT_ENTRY(6, dirty), - INT_ENTRY(6, dirty2), - INT_ENTRY(6, bootup), - INT_ENTRY(6, flash_enable), - INT_ENTRY(6, write_enable), - INT_ENTRY(6, read_enable), - INT_ENTRY(6, flash_command), - INT_ENTRY(6, old_write), - INT_ENTRY(6, new_write), - INT_ENTRY(6, out_index), - ARRAY_ENTRY(6, output, 32, uint8_ARRAY_V), - ARRAY_ENTRY(6, PPU, 32, uint8_ARRAY_V), - ARRAY_ENTRY(6, MMC, 16, uint8_ARRAY_V), - ARRAY_ENTRY(6, prevMMC, 16, uint8_ARRAY_V), - ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V) +static FreezeData SnapAPURegisters [] = { + INT_ENTRY(1, P), + INT_ENTRY(1, YA.W), + INT_ENTRY(1, X), + INT_ENTRY(1, S), + INT_ENTRY(1, PC), }; #undef STRUCT -#define STRUCT struct SnapshotScreenshotInfo +#define STRUCT SSoundData -static FreezeData SnapScreenshot[] = -{ - INT_ENTRY(6, Width), - INT_ENTRY(6, Height), - INT_ENTRY(6, Interlaced), - ARRAY_ENTRY(6, Data, MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3, uint8_ARRAY_V) +static FreezeData SnapSoundData [] = { + INT_ENTRY(1, master_volume_left), + INT_ENTRY(1, master_volume_right), + INT_ENTRY(1, echo_volume_left), + INT_ENTRY(1, echo_volume_right), + INT_ENTRY(1, echo_enable), + INT_ENTRY(1, echo_feedback), + INT_ENTRY(1, echo_ptr), + INT_ENTRY(1, echo_buffer_size), + INT_ENTRY(1, echo_write_enabled), + INT_ENTRY(1, echo_channel_enable), + INT_ENTRY(1, pitch_mod), + ARRAY_ENTRY(1, dummy, 3, uint32_ARRAY_V), +#define O(N) \ + INT_ENTRY(1, channels [N].state), \ + INT_ENTRY(1, channels [N].type), \ + INT_ENTRY(1, channels [N].volume_left), \ + INT_ENTRY(1, channels [N].volume_right), \ + INT_ENTRY(1, channels [N].hertz), \ + INT_ENTRY(1, channels [N].count), \ + INT_ENTRY(1, channels [N].loop), \ + INT_ENTRY(1, channels [N].envx), \ + INT_ENTRY(1, channels [N].left_vol_level), \ + INT_ENTRY(1, channels [N].right_vol_level), \ + INT_ENTRY(1, channels [N].envx_target), \ + INT_ENTRY(1, channels [N].env_error), \ + INT_ENTRY(1, channels [N].erate), \ + INT_ENTRY(1, channels [N].direction), \ + INT_ENTRY(1, channels [N].attack_rate), \ + INT_ENTRY(1, channels [N].decay_rate), \ + INT_ENTRY(1, channels [N].sustain_rate), \ + INT_ENTRY(1, channels [N].release_rate), \ + INT_ENTRY(1, channels [N].sustain_level), \ + INT_ENTRY(1, channels [N].sample), \ + ARRAY_ENTRY(1, channels [N].decoded, 16, uint16_ARRAY_V), \ + ARRAY_ENTRY(1, channels [N].previous16, 2, uint16_ARRAY_V), \ + INT_ENTRY(1, channels [N].sample_number), \ + INT_ENTRY(1, channels [N].last_block), \ + INT_ENTRY(1, channels [N].needs_decode), \ + INT_ENTRY(1, channels [N].block_pointer), \ + INT_ENTRY(1, channels [N].sample_pointer), \ + INT_ENTRY(1, channels [N].mode) + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7), +#undef O + INT_ENTRY(2, noise_rate), +#define O(N) \ + INT_ENTRY(2, channels [N].out_sample), \ + INT_ENTRY(2, channels [N].xenvx), \ + INT_ENTRY(2, channels [N].xenvx_target), \ + INT_ENTRY(2, channels [N].xenv_count), \ + INT_ENTRY(2, channels [N].xenv_rate), \ + INT_ENTRY(2, channels [N].xattack_rate), \ + INT_ENTRY(2, channels [N].xdecay_rate), \ + INT_ENTRY(2, channels [N].xsustain_rate), \ + INT_ENTRY(2, channels [N].xsustain_level) + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7), +#undef O + INT_ENTRY(4, noise_count), + INT_ENTRY(4, no_filter), + INT_ENTRY(4, echo_volume[0]), + INT_ENTRY(4, echo_volume[1]), + INT_ENTRY(4, master_volume[0]), + INT_ENTRY(4, master_volume[1]), }; #undef STRUCT -#define STRUCT struct SnapshotMovieInfo +#define STRUCT struct SSA1Registers -static FreezeData SnapMovie[] = -{ - INT_ENTRY(6, MovieInputDataSize) +static FreezeData SnapSA1Registers [] = { + INT_ENTRY(1, PB), + INT_ENTRY(1, DB), + INT_ENTRY(1, P.W), + INT_ENTRY(1, A.W), + INT_ENTRY(1, D.W), + INT_ENTRY(1, S.W), + INT_ENTRY(1, X.W), + INT_ENTRY(1, Y.W), + INT_ENTRY(1, PCw), }; -static int UnfreezeBlock (STREAM, const char *, uint8 *, int); -static int UnfreezeBlockCopy (STREAM, const char *, uint8 **, int); -static int UnfreezeStruct (STREAM, const char *, void *, FreezeData *, int, int); -static int UnfreezeStructCopy (STREAM, const char *, uint8 **, FreezeData *, int, int); -static void UnfreezeStructFromCopy (void *, FreezeData *, int, uint8 *, int); -static void FreezeBlock (STREAM, const char *, uint8 *, int); -static void FreezeStruct (STREAM, const char *, void *, FreezeData *, int); +#undef STRUCT +#define STRUCT struct SSA1 + +static FreezeData SnapSA1 [] = { + INT_ENTRY(1, Flags), + INT_ENTRY(1, NMIActive), + INT_ENTRY(1, IRQActive), + INT_ENTRY(1, WaitingForInterrupt), + INT_ENTRY(1, op1), + INT_ENTRY(1, op2), + INT_ENTRY(1, arithmetic_op), + INT_ENTRY(1, sum), + INT_ENTRY(1, overflow), + // not sure if the following are necessary, but better safe than sorry + INT_ENTRY(3, CPUExecuting), + INT_ENTRY(3, ShiftedPB), + INT_ENTRY(3, ShiftedDB), + INT_ENTRY(3, Executing), + INT_ENTRY(3, Waiting), + INT_ENTRY(3, PBPCAtOpcodeStart), + INT_ENTRY(3, WaitAddress), + INT_ENTRY(3, WaitCounter), + INT_ENTRY(3, VirtualBitmapFormat), + INT_ENTRY(3, in_char_dma), + INT_ENTRY(3, variable_bit_pos), +}; + +#undef STRUCT +#define STRUCT struct SDSP1 + +static FreezeData SnapDSP1 [] = { + INT_ENTRY(3, version), + INT_ENTRY(3, waiting4command), + INT_ENTRY(3, first_parameter), + INT_ENTRY(3, command), + INT_ENTRY(3, in_count), + INT_ENTRY(3, in_index), + INT_ENTRY(3, out_count), + INT_ENTRY(3, out_index), + ARRAY_ENTRY(3, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(3, output, 512, uint8_ARRAY_V), + ARRAY_ENTRY(4, temp_save_data, sizeof(DSP1.temp_save_data), uint8_ARRAY_V), +}; + +#undef STRUCT +#define STRUCT struct SPC7110EmuVars + +static FreezeData SnapSPC7110 [] = { + INT_ENTRY(1, reg4800), + INT_ENTRY(1, reg4801), + INT_ENTRY(1, reg4802), + INT_ENTRY(1, reg4803), + INT_ENTRY(1, reg4804), + INT_ENTRY(1, reg4805), + INT_ENTRY(1, reg4806), + INT_ENTRY(1, reg4807), + INT_ENTRY(1, reg4808), + INT_ENTRY(1, reg4809), + INT_ENTRY(1, reg480A), + INT_ENTRY(1, reg480B), + INT_ENTRY(1, reg480C), + INT_ENTRY(1, reg4811), + INT_ENTRY(1, reg4812), + INT_ENTRY(1, reg4813), + INT_ENTRY(1, reg4814), + INT_ENTRY(1, reg4815), + INT_ENTRY(1, reg4816), + INT_ENTRY(1, reg4817), + INT_ENTRY(1, reg4818), + INT_ENTRY(1, reg4820), + INT_ENTRY(1, reg4821), + INT_ENTRY(1, reg4822), + INT_ENTRY(1, reg4823), + INT_ENTRY(1, reg4824), + INT_ENTRY(1, reg4825), + INT_ENTRY(1, reg4826), + INT_ENTRY(1, reg4827), + INT_ENTRY(1, reg4828), + INT_ENTRY(1, reg4829), + INT_ENTRY(1, reg482A), + INT_ENTRY(1, reg482B), + INT_ENTRY(1, reg482C), + INT_ENTRY(1, reg482D), + INT_ENTRY(1, reg482E), + INT_ENTRY(1, reg482F), + INT_ENTRY(1, reg4830), + INT_ENTRY(1, reg4831), + INT_ENTRY(1, reg4832), + INT_ENTRY(1, reg4833), + INT_ENTRY(1, reg4834), + INT_ENTRY(1, reg4840), + INT_ENTRY(1, reg4841), + INT_ENTRY(1, reg4842), + INT_ENTRY(1, AlignBy), + INT_ENTRY(1, written), + INT_ENTRY(1, offset_add), + INT_ENTRY(1, DataRomOffset), + INT_ENTRY(1, DataRomSize), + INT_ENTRY(1, bank50Internal), + ARRAY_ENTRY(1, bank50, 0x10000, uint8_ARRAY_V), +}; + +#undef STRUCT +#define STRUCT struct SPC7110RTC + +static FreezeData SnapS7RTC [] = { + ARRAY_ENTRY(1, reg, 16, uint8_ARRAY_V), + INT_ENTRY(1, index), + INT_ENTRY(1, control), + INT_ENTRY(1, init), + INT_ENTRY(1, last_used), +}; + +#undef STRUCT +#define STRUCT struct SControlSnapshot + +static FreezeData SnapControls [] = { + INT_ENTRY(2, ver), + ARRAY_ENTRY(2, port1_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(2, dummy1, 4, uint8_ARRAY_V), + ARRAY_ENTRY(2, port2_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(2, dummy2, 4, uint8_ARRAY_V), + ARRAY_ENTRY(2, mouse_speed, 2, uint8_ARRAY_V), + INT_ENTRY(2, justifier_select), + ARRAY_ENTRY(2, dummy3, 8, uint8_ARRAY_V), + INT_ENTRY(4, pad_read), + INT_ENTRY(4, pad_read_last), + ARRAY_ENTRY(3, internal, 60, uint8_ARRAY_V), // yes, we need to save this! +}; + +#undef STRUCT +#define STRUCT struct STimings + +static FreezeData SnapTimings [] = { + INT_ENTRY(2, H_Max_Master), + INT_ENTRY(2, H_Max), + INT_ENTRY(2, V_Max_Master), + INT_ENTRY(2, V_Max), + INT_ENTRY(2, HBlankStart), + INT_ENTRY(2, HBlankEnd), + INT_ENTRY(2, HDMAInit), + INT_ENTRY(2, HDMAStart), + INT_ENTRY(2, NMITriggerPos), + INT_ENTRY(2, WRAMRefreshPos), + INT_ENTRY(2, RenderPos), + INT_ENTRY(2, InterlaceField), + INT_ENTRY(4, DMACPUSync), +}; + +#undef STRUCT +#define STRUCT struct SBSX + +static FreezeData SnapBSX [] = { + INT_ENTRY(2, dirty), + INT_ENTRY(2, dirty2), + INT_ENTRY(2, bootup), + INT_ENTRY(2, flash_enable), + INT_ENTRY(2, write_enable), + INT_ENTRY(2, read_enable), + INT_ENTRY(2, flash_command), + INT_ENTRY(2, old_write), + INT_ENTRY(2, new_write), + INT_ENTRY(2, out_index), + ARRAY_ENTRY(2, output, 32, uint8_ARRAY_V), + ARRAY_ENTRY(2, PPU, 32, uint8_ARRAY_V), + ARRAY_ENTRY(2, MMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(2, prevMMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(2, test2192, 32, uint8_ARRAY_V), +}; + +// deleted blocks +static FreezeData SnapIPPU [] = { + DELETED_ARRAY_ENTRY(3,4, Junk, 2, uint32_ARRAY_V), +}; +static FreezeData SnapGFX [] = { + DELETED_ARRAY_ENTRY(3,4, Junk, 22+256+MAX_SNES_WIDTH*MAX_SNES_HEIGHT*2, uint8_ARRAY_V), +}; -void S9xResetSaveTimer (bool8 dontsave) +#ifndef NGC +struct SnapshotScreenshotInfo { - static time_t t = -1; + uint16 Width; + uint16 Height; + uint8 Data [MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3]; + uint8 Interlaced; +}; - if (!Settings.DontSaveOopsSnapshot && !dontsave && t != -1 && time(NULL) - t > 300) - { - char filename[PATH_MAX + 1]; - char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; +#undef STRUCT +#define STRUCT struct SnapshotScreenshotInfo - _splitpath(Memory.ROMFilename, drive, dir, def, ext); - sprintf(filename, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops"); - S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, SAVE_INFO_OOPS); - S9xFreezeGame(filename); - } +static FreezeData SnapScreenshot [] = { + INT_ENTRY(4, Width), + INT_ENTRY(4, Height), + ARRAY_ENTRY(4, Data, MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3, uint8_ARRAY_V), + INT_ENTRY(4, Interlaced), // needed in case interlacing was on before loading a state where it is off +}; +#endif - t = time(NULL); +#ifndef ZSNES_FX + extern struct FxRegs_s GSU; + + #undef STRUCT + #define STRUCT struct FxRegs_s + + // TODO: figure out which of these are completely unnecessary. Many of them are necessary. + static FreezeData SnapFX [] = { + INT_ENTRY(4, vColorReg), + INT_ENTRY(4, vPlotOptionReg), + INT_ENTRY(4, vStatusReg), + INT_ENTRY(4, vPrgBankReg), + INT_ENTRY(4, vRomBankReg), + INT_ENTRY(4, vRamBankReg), + INT_ENTRY(4, vCacheBaseReg), + INT_ENTRY(4, vCacheFlags), + INT_ENTRY(4, vLastRamAdr), + INT_ENTRY(4, vPipeAdr), + INT_ENTRY(4, vSign), + INT_ENTRY(4, vZero), + INT_ENTRY(4, vCarry), + INT_ENTRY(4, vOverflow), + INT_ENTRY(4, vErrorCode), + INT_ENTRY(4, vIllegalAddress), + INT_ENTRY(4, vBreakPoint), + INT_ENTRY(4, vStepPoint), + INT_ENTRY(4, nRamBanks), + INT_ENTRY(4, nRomBanks), + INT_ENTRY(4, vMode), + INT_ENTRY(4, vPrevMode), + INT_ENTRY(4, vScreenHeight), + INT_ENTRY(4, vScreenRealHeight), + INT_ENTRY(4, vPrevScreenHeight), + INT_ENTRY(4, vScreenSize), + INT_ENTRY(4, vCounter), + INT_ENTRY(4, vInstCount), + INT_ENTRY(4, vSCBRDirty), + INT_ENTRY(4, vRomBuffer), + INT_ENTRY(4, vPipe), + INT_ENTRY(4, bCacheActive), + INT_ENTRY(4, bBreakPoint), + ARRAY_ENTRY(4, avCacheBackup, 512, uint8_ARRAY_V), + ARRAY_ENTRY(4, avReg, 16, uint32_ARRAY_V), + ARRAY_ENTRY(4, x, 32, uint32_ARRAY_V), + POINTER_ENTRY(4, pvScreenBase, pvRam), + POINTER_ENTRY(4, pvPrgBank, apvRomBank), + POINTER_ENTRY(4, pvDreg, avReg), + POINTER_ENTRY(4, pvSreg, avReg), +#define O(N) POINTER_ENTRY(4, apvScreen[N], pvRam) + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), +#undef O + POINTER_ENTRY(4, pvRamBank, apvRamBank), + POINTER_ENTRY(4, pvRomBank, apvRomBank), + POINTER_ENTRY(4, pvCache, pvRegisters), + POINTER_ENTRY(4, apvRamBank[0], pvRam), + POINTER_ENTRY(4, apvRamBank[1], pvRam), + POINTER_ENTRY(4, apvRamBank[2], pvRam), + POINTER_ENTRY(4, apvRamBank[3], pvRam), +// uint8 * apvRomBank[256]; // probably OK to not save it, because it only changes in FxReset +// uint8 * pvRegisters; // can't save, but no need +// uint8 * pvRam; // can't save, but no need +// uint8 * pvRom; // can't save, but no need +// void (*pfPlot)(); // can't save, so we set it after loading +// void (*pfRpix)(); // can't save, so we set it after loading + }; +#endif + + +static char ROMFilename [_MAX_PATH]; +//static char SnapshotFilename [_MAX_PATH]; + +void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, + int num_fields); +void FreezeBlock (STREAM stream, char *name, uint8 *block, int size); + +#ifdef NGC +extern void NGCFreezeBlock (char *name, uint8 *block, int size); +extern int NGCUnFreezeBlock( char *name, uint8 *block, int size ); +extern int GetMem( char *buffer, int len ); +#endif + +int UnfreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, + int num_fields, int version); +int UnfreezeBlock (STREAM stream, char *name, uint8 *block, int size); + +int UnfreezeStructCopy (STREAM stream, char *name, uint8** block, FreezeData *fields, int num_fields, int version); + +void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uint8* block, int version); + +int UnfreezeBlockCopy (STREAM stream, char *name, uint8** block, int size); + +bool8 Snapshot (const char *filename) +{ + return (S9xFreezeGame (filename)); } bool8 S9xFreezeGame (const char *filename) { - STREAM stream = NULL; + STREAM stream = NULL; - if (S9xOpenSnapshotFile(filename, FALSE, &stream)) +#ifndef NGC + if (S9xOpenSnapshotFile (filename, FALSE, &stream)) +#endif { - S9xFreezeToStream(stream); - S9xCloseSnapshotFile(stream); + S9xPrepareSoundForSnapshotSave (FALSE); - S9xResetSaveTimer(TRUE); + S9xFreezeToStream (stream); +#ifndef NGC + S9xCloseSnapshotFile (stream); +#endif + S9xPrepareSoundForSnapshotSave (TRUE); - const char *base = S9xBasename(filename); - if (S9xMovieActive()) - sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base); + S9xResetSaveTimer (TRUE); + +#ifndef NGC + if(S9xMovieActive()) + { + const char * name = S9xBasename (filename); + if(name && strlen(name) > 3) + name += strlen(name) - 3; + else + name = filename; + sprintf(String, MOVIE_INFO_SNAPSHOT " %s", name); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + GFX.InfoStringTimeout /= 4; + } else - sprintf(String, SAVE_INFO_SNAPSHOT " %s", base); - - S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); - + { + sprintf(String, SAVE_INFO_SNAPSHOT " %s", S9xBasename (filename)); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + } +#endif return (TRUE); - } + } + return (FALSE); +} - return (FALSE); +bool8 S9xLoadSnapshot (const char *filename) +{ + return (S9xUnfreezeGame (filename)); } bool8 S9xUnfreezeGame (const char *filename) { - STREAM stream = NULL; - char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + char def [PATH_MAX + 1 ]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1 ]; + char ext [_MAX_EXT + 1 ] ; - const char *base = S9xBasename(filename); + _splitpath (filename, drive, dir, def, ext); + S9xResetSaveTimer (!strcmp(ext, "oops") || !strcmp(ext, "oop")); - _splitpath(filename, drive, dir, def, ext); - S9xResetSaveTimer(!strcmp(ext, "oops") || !strcmp(ext, "oop") || !strcmp(ext, ".oops") || !strcmp(ext, ".oop")); + ZeroMemory (&Obsolete, sizeof(Obsolete)); - if (S9xOpenSnapshotFile(filename, TRUE, &stream)) +#ifndef NGC + /*** As the GC never had snapshots - there won't be + any original ones -;) ***/ + if (S9xLoadOrigSnapshot (filename)) + return (TRUE); + + if (S9xUnfreezeZSNES (filename)) + return (TRUE); +#endif + + STREAM snapshot = NULL; +#ifndef NGC + if (S9xOpenSnapshotFile (filename, TRUE, &snapshot)) +#endif { - int result; - - result = S9xUnfreezeFromStream(stream); - S9xCloseSnapshotFile(stream); - - if (result != SUCCESS) + int result; + if ((result = S9xUnfreezeFromStream (snapshot)) != SUCCESS) { switch (result) { - case WRONG_FORMAT: - S9xMessage(S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); - break; - - case WRONG_VERSION: - S9xMessage(S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); - break; - - case WRONG_MOVIE_SNAPSHOT: - S9xMessage(S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); - break; - - case NOT_A_MOVIE_SNAPSHOT: - S9xMessage(S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); - break; - - case SNAPSHOT_INCONSISTENT: - S9xMessage(S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); - break; - - case FILE_NOT_FOUND: - default: - sprintf(String, SAVE_ERR_ROM_NOT_FOUND, base); - S9xMessage(S9X_ERROR, S9X_ROM_NOT_FOUND, String); - break; + case WRONG_FORMAT: + S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); + break; + case WRONG_VERSION: + S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); + break; + case WRONG_MOVIE_SNAPSHOT: + S9xMessage (S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); + break; + case NOT_A_MOVIE_SNAPSHOT: + S9xMessage (S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); + break; + case SNAPSHOT_INCONSISTENT: + S9xMessage (S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); + break; + default: + case FILE_NOT_FOUND: + sprintf (String, SAVE_ERR_ROM_NOT_FOUND, ROMFilename); + S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); + break; } - +#ifndef NGC + S9xCloseSnapshotFile (snapshot); +#endif return (FALSE); } - if (S9xMovieActive()) +#ifndef NGC + if(S9xMovieActive()) { - if (S9xMovieReadOnly()) - sprintf(String, MOVIE_INFO_REWIND " %s", base); + const char * name = S9xBasename (filename); + if(name && strlen(name) > 3) + name += strlen(name) - 3; else - sprintf(String, MOVIE_INFO_RERECORD " %s", base); + name = filename; + if(S9xMovieReadOnly()) + sprintf(String, MOVIE_INFO_REWIND " %s", name); + else + sprintf(String, MOVIE_INFO_RERECORD " %s", name); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + GFX.InfoStringTimeout /= 4; } else - sprintf(String, SAVE_INFO_LOAD " %s", base); - - S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + { + sprintf(String, SAVE_INFO_LOAD " %s", S9xBasename (filename)); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + } + S9xCloseSnapshotFile (snapshot); +#endif return (TRUE); + } + +#ifndef NGC + // failed; error message: + { + char name [PATH_MAX]; + strcpy(name, S9xBasename (filename)); + int len = strlen(name); + if(len > 3 && name[len-3] == 'z' && name[len-2] == 's') + name[len-3] = name[len-2] = '0'; + sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, name); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); } - sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base); - S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); - - return (FALSE); + return (FALSE); +#endif } +bool diagnostic_freezing = false; +//#define DIAGNOSTIC_FREEZING_SUPPORT + void S9xFreezeToStream (STREAM stream) { - char buffer[1024]; - - S9xSetSoundMute(TRUE); + char buffer [1024]; + int i; + S9xSetSoundMute (TRUE); #ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPreSaveState(); + if (Settings.SuperFX) + S9xSuperFXPreSaveState (); #endif - sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); - WRITE_STREAM(buffer, strlen(buffer), stream); + S9xUpdateRTC(); + S9xSRTCPreSaveState (); - sprintf(buffer, "NAM:%06d:%s%c", (int) strlen(Memory.ROMFilename) + 1, Memory.ROMFilename, 0); - WRITE_STREAM(buffer, strlen(buffer) + 1, stream); + for (i = 0; i < 8; i++) + { + SoundData.channels [i].previous16 [0] = (int16) SoundData.channels [i].previous [0]; + SoundData.channels [i].previous16 [1] = (int16) SoundData.channels [i].previous [1]; + } + sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, diagnostic_freezing ? 9999 : SNAPSHOT_VERSION); + WRITE_STREAM (buffer, strlen (buffer), stream); + sprintf (buffer, "NAM:%06d:%s%c", (int)strlen (Memory.ROMFilename) + 1, + Memory.ROMFilename, 0); + WRITE_STREAM (buffer, strlen (buffer) + 1, stream); + FreezeStruct (stream, "CPU", &CPU, SnapCPU, COUNT (SnapCPU)); + FreezeStruct (stream, "REG", &Registers, SnapRegisters, COUNT (SnapRegisters)); + FreezeStruct (stream, "PPU", &PPU, SnapPPU, COUNT (SnapPPU)); + FreezeStruct (stream, "DMA", DMA, SnapDMA, COUNT (SnapDMA)); - FreezeStruct(stream, "CPU", &CPU, SnapCPU, COUNT(SnapCPU)); + // RAM and VRAM + FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); + FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); + FreezeBlock (stream, "SRA", Memory.SRAM, 0x20000); + FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); + if (Settings.APUEnabled) + { + // APU + FreezeStruct (stream, "APU", &APU, SnapAPU, COUNT (SnapAPU)); + FreezeStruct (stream, "ARE", &APURegisters, SnapAPURegisters, + COUNT (SnapAPURegisters)); + FreezeBlock (stream, "ARA", IAPU.RAM, 0x10000); + FreezeStruct (stream, "SOU", &SoundData, SnapSoundData, + COUNT (SnapSoundData)); + } - FreezeStruct(stream, "REG", &Registers, SnapRegisters, COUNT(SnapRegisters)); + // Controls + struct SControlSnapshot ctl_snap; + S9xControlPreSave(&ctl_snap); + FreezeStruct (stream, "CTL", &ctl_snap, SnapControls, COUNT (SnapControls)); - FreezeStruct(stream, "PPU", &PPU, SnapPPU, COUNT(SnapPPU)); + // Timings + FreezeStruct (stream, "TIM", &Timings, SnapTimings, COUNT (SnapTimings)); - struct SDMASnapshot dma_snap; - for (int d = 0; d < 8; d++) - dma_snap.dma[d] = DMA[d]; - FreezeStruct(stream, "DMA", &dma_snap, SnapDMA, COUNT(SnapDMA)); + // Special chips + if (Settings.SA1) + { + S9xSA1PackStatus (); + FreezeStruct (stream, "SA1", &SA1, SnapSA1, COUNT (SnapSA1)); + FreezeStruct (stream, "SAR", &SA1Registers, SnapSA1Registers, + COUNT (SnapSA1Registers)); + } - FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); + if (Settings.SPC7110) + { + FreezeStruct (stream, "SP7", &s7r, SnapSPC7110, COUNT (SnapSPC7110)); + } - FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); + if (Settings.SPC7110RTC) + { + FreezeStruct (stream, "RTC", &rtc_f9, SnapS7RTC, COUNT (SnapS7RTC)); + } - FreezeBlock (stream, "SRA", Memory.SRAM, 0x20000); + // BS + if (Settings.BS) + { + FreezeStruct (stream, "BSX", &BSX, SnapBSX, COUNT (SnapBSX)); + } - FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); +#ifndef NGC + if (S9xMovieActive ()) + { + uint8* movie_freeze_buf; + uint32 movie_freeze_size; - uint8 soundsnapshot[SPC_SAVE_STATE_BLOCK_SIZE]; - S9xAPUSaveState(soundsnapshot); - FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + S9xMovieFreeze(&movie_freeze_buf, &movie_freeze_size); + if(movie_freeze_buf) + { + struct SnapshotMovieInfo mi; + mi.MovieInputDataSize = movie_freeze_size; + FreezeStruct (stream, "MOV", &mi, SnapMovie, COUNT (SnapMovie)); + FreezeBlock (stream, "MID", movie_freeze_buf, movie_freeze_size); + delete [] movie_freeze_buf; + } + } +#endif - struct SControlSnapshot ctl_snap; - S9xControlPreSaveState(&ctl_snap); - FreezeStruct(stream, "CTL", &ctl_snap, SnapControls, COUNT(SnapControls)); + // DSP1 chip + if(Settings.DSP1Master) + { + S9xPreSaveDSP1(); + FreezeStruct (stream, "DSP", &DSP1, SnapDSP1, COUNT (SnapDSP1)); + } - FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings)); + if (Settings.C4) + { +#ifdef ZSNES_C4 + extern uint8 *C4Ram; + if (C4Ram) + FreezeBlock (stream, "CX4", C4Ram, 8192); +#else + FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); +#endif + } #ifndef ZSNES_FX if (Settings.SuperFX) - FreezeStruct(stream, "SFX", &GSU, SnapFX, COUNT(SnapFX)); + FreezeStruct (stream, "SFX", &GSU, SnapFX, COUNT (SnapFX)); #endif - if (Settings.SA1) +#ifndef NGC + if(Settings.SnapshotScreenshots) { - S9xSA1PackStatus(); - FreezeStruct(stream, "SA1", &SA1, SnapSA1, COUNT(SnapSA1)); - FreezeStruct(stream, "SAR", &SA1Registers, SnapSA1Registers, COUNT(SnapSA1Registers)); - } - - if (Settings.DSP == 1) - FreezeStruct(stream, "DP1", &DSP1, SnapDSP1, COUNT(SnapDSP1)); - - if (Settings.DSP == 2) - FreezeStruct(stream, "DP2", &DSP2, SnapDSP2, COUNT(SnapDSP2)); - - if (Settings.DSP == 4) - FreezeStruct(stream, "DP4", &DSP4, SnapDSP4, COUNT(SnapDSP4)); - - if (Settings.C4) -#ifndef ZSNES_C4 - FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); -#else - FreezeBlock (stream, "CX4", C4Ram, 8192); -#endif - - if (Settings.SETA == ST_010) - FreezeStruct(stream, "ST0", &ST010, SnapST010, COUNT(SnapST010)); - - if (Settings.OBC1) - { - FreezeStruct(stream, "OBC", &OBC1, SnapOBC1, COUNT(SnapOBC1)); - FreezeBlock (stream, "OBM", Memory.OBC1RAM, 8192); - } - - if (Settings.SPC7110) - { - S9xSPC7110PreSaveState(); - FreezeStruct(stream, "S71", &s7snap, SnapSPC7110Snap, COUNT(SnapSPC7110Snap)); - } - - if (Settings.SRTC) - { - S9xSRTCPreSaveState(); - FreezeStruct(stream, "SRT", &srtcsnap, SnapSRTCSnap, COUNT(SnapSRTCSnap)); - } - - if (Settings.SRTC || Settings.SPC7110RTC) - FreezeBlock (stream, "CLK", RTCData.reg, 20); - - if (Settings.BS) - FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX)); - - if (Settings.SnapshotScreenshots) - { - SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; - - ssi->Width = min(IPPU.RenderedScreenWidth, MAX_SNES_WIDTH); + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + ssi->Width = min(IPPU.RenderedScreenWidth, MAX_SNES_WIDTH); ssi->Height = min(IPPU.RenderedScreenHeight, MAX_SNES_HEIGHT); ssi->Interlaced = GFX.DoInterlace; - uint8 *rowpix = ssi->Data; - uint16 *screen = GFX.Screen; - - for (int y = 0; y < ssi->Height; y++, screen += GFX.RealPPL) - { - for (int x = 0; x < ssi->Width; x++) - { - uint32 r, g, b; - + uint8 *rowpix=ssi->Data; + uint16 *screen=GFX.Screen; + for(int y=0; yHeight; y++, screen+=GFX.RealPPL){ + for(int x=0; xWidth; x++){ + uint32 r, g, b; DECOMPOSE_PIXEL(screen[x], r, g, b); - *(rowpix++) = r; + *(rowpix++) = r; // save pixel as 15-bits-in-3-bytes, for simplicity *(rowpix++) = g; *(rowpix++) = b; } } - memset(rowpix, 0, sizeof(ssi->Data) + ssi->Data - rowpix); - FreezeStruct(stream, "SHO", ssi, SnapScreenshot, COUNT(SnapScreenshot)); - + FreezeStruct (stream, "SHO", ssi, SnapScreenshot, COUNT (SnapScreenshot)); delete ssi; } - - if (S9xMovieActive()) - { - uint8 *movie_freeze_buf; - uint32 movie_freeze_size; - - S9xMovieFreeze(&movie_freeze_buf, &movie_freeze_size); - if (movie_freeze_buf) - { - struct SnapshotMovieInfo mi; - - mi.MovieInputDataSize = movie_freeze_size; - FreezeStruct(stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie)); - FreezeBlock (stream, "MID", movie_freeze_buf, movie_freeze_size); - - delete [] movie_freeze_buf; - } - } - -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostSaveState(); #endif - S9xSetSoundMute(FALSE); + S9xSetSoundMute (FALSE); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostSaveState (); +#endif } +bool unfreezing_from_stream = false; + int S9xUnfreezeFromStream (STREAM stream) { - int result = SUCCESS; - int version, len; - char buffer[PATH_MAX + 1]; - - printf("unfreezing ...\n"); + char buffer [_MAX_PATH + 1]; + char rom_filename [_MAX_PATH + 1]; + int result; - len = strlen(SNAPSHOT_MAGIC) + 1 + 4 + 1; - if (READ_STREAM(buffer, len, stream) != len) + int version; + int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; +#ifdef NGC + GetMem(buffer, len); +#else + if (READ_STREAM (buffer, len, stream) != len) return (WRONG_FORMAT); - - if (strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0) +#endif + if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) return (WRONG_FORMAT); - - version = atoi(&buffer[strlen(SNAPSHOT_MAGIC) + 1]); - if (version > SNAPSHOT_VERSION) + if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) return (WRONG_VERSION); - result = UnfreezeBlock(stream, "NAM", (uint8 *) buffer, PATH_MAX); - if (result != SUCCESS) + if ((result = UnfreezeBlock (stream, "NAM", (uint8 *) rom_filename, _MAX_PATH)) != SUCCESS) return (result); - - printf("unfreezing 2...\n"); - uint8 *local_cpu = NULL; - uint8 *local_registers = NULL; - uint8 *local_ppu = NULL; - uint8 *local_dma = NULL; - uint8 *local_vram = NULL; - uint8 *local_ram = NULL; - uint8 *local_sram = NULL; - uint8 *local_fillram = NULL; - uint8 *local_apu_sound = NULL; - uint8 *local_control_data = NULL; - uint8 *local_timing_data = NULL; - uint8 *local_superfx = NULL; - uint8 *local_sa1 = NULL; - uint8 *local_sa1_registers = NULL; - uint8 *local_dsp1 = NULL; - uint8 *local_dsp2 = NULL; - uint8 *local_dsp4 = NULL; - uint8 *local_cx4_data = NULL; - uint8 *local_st010 = NULL; - uint8 *local_obc1 = NULL; - uint8 *local_obc1_data = NULL; - uint8 *local_spc7110 = NULL; - uint8 *local_srtc = NULL; - uint8 *local_rtc_data = NULL; - uint8 *local_bsx_data = NULL; - uint8 *local_screenshot = NULL; - uint8 *local_movie_data = NULL; + unfreezing_from_stream = true; + +#ifndef NGC + if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && + strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) + { + S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, + "Current loaded ROM image doesn't match that required by freeze-game file."); + } +#endif + +// ## begin load ## + uint8* local_cpu = NULL; + uint8* local_registers = NULL; + uint8* local_ppu = NULL; + uint8* local_dma = NULL; + uint8* local_vram = NULL; + uint8* local_ram = NULL; + uint8* local_sram = NULL; + uint8* local_fillram = NULL; + uint8* local_apu = NULL; + uint8* local_apu_registers = NULL; + uint8* local_apu_ram = NULL; + uint8* local_apu_sounddata = NULL; + uint8* local_sa1 = NULL; + uint8* local_sa1_registers = NULL; + uint8* local_spc = NULL; + uint8* local_spc_rtc = NULL; + uint8* local_movie_data = NULL; + uint8* local_control_data = NULL; + uint8* local_timing_data = NULL; + uint8* local_bsx_data = NULL; + uint8* local_dsp1 = NULL; + uint8* local_cx4_data = NULL; + uint8* local_superfx = NULL; + uint8* local_screenshot = NULL; + uint8* local_dummy[2] = {NULL,NULL}; do { - result = UnfreezeStructCopy(stream, "CPU", &local_cpu, SnapCPU, COUNT(SnapCPU), version); - if (result != SUCCESS) + if ((result = UnfreezeStructCopy (stream, "CPU", &local_cpu, SnapCPU, COUNT (SnapCPU), version)) != SUCCESS) break; - - result = UnfreezeStructCopy(stream, "REG", &local_registers, SnapRegisters, COUNT(SnapRegisters), version); - if (result != SUCCESS) + if ((result = UnfreezeStructCopy (stream, "REG", &local_registers, SnapRegisters, COUNT (SnapRegisters), version)) != SUCCESS) break; - - result = UnfreezeStructCopy(stream, "PPU", &local_ppu, SnapPPU, COUNT(SnapPPU), version); - if (result != SUCCESS) + if ((result = UnfreezeStructCopy (stream, "PPU", &local_ppu, SnapPPU, COUNT (SnapPPU), version)) != SUCCESS) break; - - result = UnfreezeStructCopy(stream, "DMA", &local_dma, SnapDMA, COUNT(SnapDMA), version); - if (result != SUCCESS) + if ((result = UnfreezeStructCopy (stream, "DMA", &local_dma, SnapDMA, COUNT (SnapDMA), version)) != SUCCESS) break; - - result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000); - if (result != SUCCESS) + if ((result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000)) != SUCCESS) break; - - result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000); - if (result != SUCCESS) + if ((result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000)) != SUCCESS) break; - - result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000); - if (result != SUCCESS) + if ((result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000)) != SUCCESS) break; - - result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000); - if (result != SUCCESS) + if ((result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000)) != SUCCESS) break; - - result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); - if (result != SUCCESS) - break; - - result = UnfreezeStructCopy(stream, "CTL", &local_control_data, SnapControls, COUNT(SnapControls), version); - if (result != SUCCESS) - break; - - result = UnfreezeStructCopy(stream, "TIM", &local_timing_data, SnapTimings, COUNT(SnapTimings), version); - if (result != SUCCESS) - break; - - #ifndef ZSNES_FX - result = UnfreezeStructCopy(stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version); - if (result != SUCCESS && Settings.SuperFX) - break; - #endif - - result = UnfreezeStructCopy(stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1), version); - if (result != SUCCESS && Settings.SA1) - break; - - result = UnfreezeStructCopy(stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT(SnapSA1Registers), version); - if (result != SUCCESS && Settings.SA1) - break; - - result = UnfreezeStructCopy(stream, "DP1", &local_dsp1, SnapDSP1, COUNT(SnapDSP1), version); - if (result != SUCCESS && Settings.DSP == 1) - break; - - result = UnfreezeStructCopy(stream, "DP2", &local_dsp2, SnapDSP2, COUNT(SnapDSP2), version); - if (result != SUCCESS && Settings.DSP == 2) - break; - - result = UnfreezeStructCopy(stream, "DP4", &local_dsp4, SnapDSP4, COUNT(SnapDSP4), version); - if (result != SUCCESS && Settings.DSP == 4) - break; - - result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192); - if (result != SUCCESS && Settings.C4) - break; - - result = UnfreezeStructCopy(stream, "ST0", &local_st010, SnapST010, COUNT(SnapST010), version); - if (result != SUCCESS && Settings.SETA == ST_010) - break; - - result = UnfreezeStructCopy(stream, "OBC", &local_obc1, SnapOBC1, COUNT(SnapOBC1), version); - if (result != SUCCESS && Settings.OBC1) - break; - - result = UnfreezeBlockCopy (stream, "OBM", &local_obc1_data, 8192); - if (result != SUCCESS && Settings.OBC1) - break; - - result = UnfreezeStructCopy(stream, "S71", &local_spc7110, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), version); - if (result != SUCCESS && Settings.SPC7110) - break; - - result = UnfreezeStructCopy(stream, "SRT", &local_srtc, SnapSRTCSnap, COUNT(SnapSRTCSnap), version); - if (result != SUCCESS && Settings.SRTC) - break; - - result = UnfreezeBlockCopy (stream, "CLK", &local_rtc_data, 20); - if (result != SUCCESS && (Settings.SRTC || Settings.SPC7110RTC)) - break; - - result = UnfreezeStructCopy(stream, "BSX", &local_bsx_data, SnapBSX, COUNT(SnapBSX), version); - if (result != SUCCESS && Settings.BS) - break; - - result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); - - SnapshotMovieInfo mi; - - result = UnfreezeStruct(stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie), version); - if (result != SUCCESS) + if (UnfreezeStructCopy (stream, "APU", &local_apu, SnapAPU, COUNT (SnapAPU), version) == SUCCESS) { - if (S9xMovieActive()) - { - result = NOT_A_MOVIE_SNAPSHOT; + if ((result = UnfreezeStructCopy (stream, "ARE", &local_apu_registers, SnapAPURegisters, COUNT (SnapAPURegisters), version)) != SUCCESS) + break; + if ((result = UnfreezeBlockCopy (stream, "ARA", &local_apu_ram, 0x10000)) != SUCCESS) + break; + if ((result = UnfreezeStructCopy (stream, "SOU", &local_apu_sounddata, SnapSoundData, COUNT (SnapSoundData), version)) != SUCCESS) break; - } } - else + if ((result = UnfreezeStructCopy (stream, "CTL", &local_control_data, SnapControls, COUNT (SnapControls), version)) != SUCCESS && version>1) + break; + + if ((result = UnfreezeStructCopy (stream, "TIM", &local_timing_data, SnapTimings, COUNT (SnapTimings), version)) != SUCCESS && version>1) + break; + + if ((result = UnfreezeStructCopy (stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1), version)) == SUCCESS) { - result = UnfreezeBlockCopy(stream, "MID", &local_movie_data, mi.MovieInputDataSize); - if (result != SUCCESS) + if ((result = UnfreezeStructCopy (stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT (SnapSA1Registers), version)) != SUCCESS) + break; + } + else if (Settings.SA1) + break; + + if ((result = UnfreezeStructCopy (stream, "SP7", &local_spc, SnapSPC7110, COUNT(SnapSPC7110), version)) != SUCCESS) + if (Settings.SPC7110) + break; + + if ((result = UnfreezeStructCopy (stream, "RTC", &local_spc_rtc, SnapS7RTC, COUNT (SnapS7RTC), version)) != SUCCESS) + if (Settings.SPC7110RTC) + break; + + if ((result = UnfreezeStructCopy (stream, "BSX", &local_bsx_data, SnapBSX, COUNT (SnapBSX), version)) != SUCCESS) + if (Settings.BS) + break; + +#ifndef NGC + // movie + { + SnapshotMovieInfo mi; + if ((result = UnfreezeStruct (stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie), version)) != SUCCESS) { - if (S9xMovieActive()) + if (S9xMovieActive ()) { result = NOT_A_MOVIE_SNAPSHOT; break; } - } + } else { - if (S9xMovieActive()) - { - result = S9xMovieUnfreeze(local_movie_data, mi.MovieInputDataSize); - if (result != SUCCESS) - break; + if ((result = UnfreezeBlockCopy (stream, "MID", &local_movie_data, mi.MovieInputDataSize)) != SUCCESS) + { + if (S9xMovieActive ()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } + + if (S9xMovieActive ()) + { + result = S9xMovieUnfreeze(local_movie_data, mi.MovieInputDataSize); + if(result != SUCCESS) + break; + } } } +#endif + if ((result = UnfreezeStructCopy (stream, "DSP", &local_dsp1, SnapDSP1, COUNT(SnapDSP1), version)) != SUCCESS) + if(Settings.DSP1Master) + break; - result = SUCCESS; - } while (false); + if ((result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192)) != SUCCESS) + if(Settings.C4) + break; + +#ifndef ZSNES_FX + if ((result = UnfreezeStructCopy (stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version)) != SUCCESS) +// if (Settings.SuperFX) +// break; // what if the savestate was made with ZSNES_FX on? + {} +#endif + + UnfreezeStructCopy (stream, "IPU", &local_dummy[0], SnapIPPU, COUNT(SnapIPPU), version); // obsolete + UnfreezeStructCopy (stream, "GFX", &local_dummy[1], SnapGFX, COUNT(SnapGFX), version); // obsolete + +#ifndef NGC + UnfreezeStructCopy (stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); +#endif + result=SUCCESS; + + } while(false); +// ## end load ## if (result == SUCCESS) { - printf("unfreezing 3...\n"); - - uint32 old_flags = CPU.Flags; + uint32 old_flags = CPU.Flags; uint32 sa1_old_flags = SA1.Flags; + S9xReset (); + S9xSetSoundMute (TRUE); - S9xSetSoundMute(TRUE); + UnfreezeStructFromCopy (&CPU, SnapCPU, COUNT (SnapCPU), local_cpu, version); + UnfreezeStructFromCopy (&Registers, SnapRegisters, COUNT (SnapRegisters), local_registers, version); + UnfreezeStructFromCopy (&PPU, SnapPPU, COUNT (SnapPPU), local_ppu, version); + UnfreezeStructFromCopy (DMA, SnapDMA, COUNT (SnapDMA), local_dma, version); + memcpy (Memory.VRAM, local_vram, 0x10000); + memcpy (Memory.RAM, local_ram, 0x20000); + memcpy (Memory.SRAM, local_sram, 0x20000); + memcpy (Memory.FillRAM, local_fillram, 0x8000); + if(local_apu) + { + UnfreezeStructFromCopy (&APU, SnapAPU, COUNT (SnapAPU), local_apu, version); + UnfreezeStructFromCopy (&APURegisters, SnapAPURegisters, COUNT (SnapAPURegisters), local_apu_registers, version); + memcpy (IAPU.RAM, local_apu_ram, 0x10000); + UnfreezeStructFromCopy (&SoundData, SnapSoundData, COUNT (SnapSoundData), local_apu_sounddata, version); + } + if(local_sa1) + { + UnfreezeStructFromCopy (&SA1, SnapSA1, COUNT (SnapSA1), local_sa1, version); + UnfreezeStructFromCopy (&SA1Registers, SnapSA1Registers, COUNT (SnapSA1Registers), local_sa1_registers, version); + } + if(local_spc) + { + UnfreezeStructFromCopy (&s7r, SnapSPC7110, COUNT (SnapSPC7110), local_spc, version); + } + if(local_spc_rtc) + { + UnfreezeStructFromCopy (&rtc_f9, SnapS7RTC, COUNT (SnapS7RTC), local_spc_rtc, version); + } - S9xReset(); + struct SControlSnapshot ctl_snap; + if(local_control_data) { + UnfreezeStructFromCopy (&ctl_snap, SnapControls, COUNT (SnapControls), local_control_data, version); + } else { + // Must be an old snes9x savestate + ZeroMemory(&ctl_snap, sizeof(ctl_snap)); + ctl_snap.ver=0; + ctl_snap.port1_read_idx[0]=Obsolete.SPPU_Joypad1ButtonReadPos; + ctl_snap.port2_read_idx[0]=Obsolete.SPPU_Joypad2ButtonReadPos; + ctl_snap.port2_read_idx[1]=Obsolete.SPPU_Joypad3ButtonReadPos; + // Old snes9x used MouseSpeed[0] for both mice. Weird. + ctl_snap.mouse_speed[0]=ctl_snap.mouse_speed[1]=Obsolete.SPPU_MouseSpeed[0]; + ctl_snap.justifier_select=0; + } + S9xControlPostLoad(&ctl_snap); - UnfreezeStructFromCopy(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version); + if(local_movie_data) // restore last displayed pad_read status + { + extern bool8 pad_read, pad_read_last; + bool8 pad_read_temp = pad_read; + pad_read = pad_read_last; + //S9xUpdateFrameCounter (-1); + pad_read = pad_read_temp; + } - UnfreezeStructFromCopy(&Registers, SnapRegisters, COUNT(SnapRegisters), local_registers, version); - - UnfreezeStructFromCopy(&PPU, SnapPPU, COUNT(SnapPPU), local_ppu, version); - - struct SDMASnapshot dma_snap; - UnfreezeStructFromCopy(&dma_snap, SnapDMA, COUNT(SnapDMA), local_dma, version); - - memcpy(Memory.VRAM, local_vram, 0x10000); - - memcpy(Memory.RAM, local_ram, 0x20000); - - memcpy(Memory.SRAM, local_sram, 0x20000); - - memcpy(Memory.FillRAM, local_fillram, 0x8000); - - S9xAPULoadState(local_apu_sound); - - struct SControlSnapshot ctl_snap; - UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version); - - UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version); - - #ifndef ZSNES_FX - if (local_superfx) - UnfreezeStructFromCopy(&GSU, SnapFX, COUNT(SnapFX), local_superfx, version); - #endif - - if (local_sa1) - UnfreezeStructFromCopy(&SA1, SnapSA1, COUNT(SnapSA1), local_sa1, version); - - if (local_sa1_registers) - UnfreezeStructFromCopy(&SA1Registers, SnapSA1Registers, COUNT(SnapSA1Registers), local_sa1_registers, version); - - if (local_dsp1) - UnfreezeStructFromCopy(&DSP1, SnapDSP1, COUNT(SnapDSP1), local_dsp1, version); - - if (local_dsp2) - UnfreezeStructFromCopy(&DSP2, SnapDSP2, COUNT(SnapDSP2), local_dsp2, version); - - if (local_dsp4) - UnfreezeStructFromCopy(&DSP4, SnapDSP4, COUNT(SnapDSP4), local_dsp4, version); - - if (local_cx4_data) - #ifndef ZSNES_C4 - memcpy(Memory.C4RAM, local_cx4_data, 8192); - #else - memcpy(C4Ram, local_cx4_data, 8192); - #endif - - if (local_st010) - UnfreezeStructFromCopy(&ST010, SnapST010, COUNT(SnapST010), local_st010, version); - - if (local_obc1) - UnfreezeStructFromCopy(&OBC1, SnapOBC1, COUNT(SnapOBC1), local_obc1, version); - - if (local_obc1_data) - memcpy(Memory.OBC1RAM, local_obc1_data, 8192); - - if (local_spc7110) - UnfreezeStructFromCopy(&s7snap, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), local_spc7110, version); - - if (local_srtc) - UnfreezeStructFromCopy(&srtcsnap, SnapSRTCSnap, COUNT(SnapSRTCSnap), local_srtc, version); - - if (local_rtc_data) - memcpy(RTCData.reg, local_rtc_data, 20); + if (local_timing_data) + UnfreezeStructFromCopy (&Timings, SnapTimings, COUNT (SnapTimings), local_timing_data, version); + else // Must be an old snes9x savestate + { + S9xUpdateHVTimerPosition(); + } if (local_bsx_data) - UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); + UnfreezeStructFromCopy (&BSX, SnapBSX, COUNT (SnapBSX), local_bsx_data, version); - CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); - ICPU.ShiftedPB = Registers.PB << 16; - ICPU.ShiftedDB = Registers.DB << 16; - S9xSetPCBase(Registers.PBPC); - S9xUnpackStatus(); - S9xFixCycles(); - Memory.FixROMSpeed(); + if(local_dsp1) + { + UnfreezeStructFromCopy (&DSP1, SnapDSP1, COUNT (SnapDSP1), local_dsp1, version); + S9xPostLoadDSP1(); + } - for (int d = 0; d < 8; d++) - DMA[d] = dma_snap.dma[d]; + if (local_cx4_data) + { +#ifdef ZSNES_C4 + extern uint8 *C4Ram; + if (C4Ram) + memcpy(C4Ram, local_cx4_data, 8192); +#else + memcpy(Memory.C4RAM, local_cx4_data, 8192); +#endif + } + +#ifndef ZSNES_FX + if(local_superfx) + { + UnfreezeStructFromCopy (&GSU, SnapFX, COUNT (SnapFX), local_superfx, version); + GSU.pfPlot = fx_apfPlotTable[GSU.vMode]; + GSU.pfRpix = fx_apfPlotTable[GSU.vMode + 5]; + } +#endif +#ifndef NGC + if(GFX.Screen) + if(local_screenshot) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + UnfreezeStructFromCopy (ssi, SnapScreenshot, COUNT (SnapScreenshot), local_screenshot, version); + IPPU.RenderedScreenWidth = min(ssi->Width, IMAGE_WIDTH); + IPPU.RenderedScreenHeight = min(ssi->Height, IMAGE_HEIGHT); + const bool scaleDownX = IPPU.RenderedScreenWidth < ssi->Width; + const bool scaleDownY = IPPU.RenderedScreenHeight < ssi->Height && ssi->Height > SNES_HEIGHT_EXTENDED; + GFX.DoInterlace = Settings.SupportHiRes ? ssi->Interlaced : 0; + + uint8 *rowpix=ssi->Data; + uint16 *screen=GFX.Screen; + for(int y=0; y>1; + g = (g + *(rowpix++))>>1; + b = (b + *(rowpix++))>>1; + if(x+x+1 >= ssi->Width) + break; + } + screen[x] = BUILD_PIXEL(r, g, b); + } + if(scaleDownY) + { + rowpix += 3*ssi->Width; + if(y+y+1 >= ssi->Height) + break; + } + } + + // black out what we might have missed + for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32)(IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL*2); + delete ssi; + } + else + { + // couldn't load graphics, so black out the screen instead + for (uint32 y = 0; y < (uint32)(IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL*2); + } +#endif + Memory.FixROMSpeed (); + CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | + SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); + + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; CPU.InDMA = CPU.InHDMA = FALSE; CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = FALSE; CPU.HDMARanInDMA = 0; + S9xFixColourBrightness (); + IPPU.RenderThisFrame = TRUE; // was FALSE, but for most games it's more useful to see that frame - S9xFixColourBrightness(); - IPPU.ColorsChanged = TRUE; - IPPU.OBJChanged = TRUE; - IPPU.RenderThisFrame = TRUE; + if (local_apu) + { + if (APU.OldCycles != -99999999) + { + // Must be <= v1.5 savestate + //printf("Older APU Cycles found.\n"); + APU.Cycles = (APU.OldCycles << SNES_APU_ACCURACY); + APU.OldCycles = -99999999; + } + + S9xSetSoundMute (FALSE); + IAPU.PC = IAPU.RAM + APURegisters.PC; + S9xAPUUnpackStatus (); + IAPU.APUExecuting = TRUE; + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + Settings.APUEnabled = TRUE; + } + else + { + Settings.APUEnabled = FALSE; + IAPU.APUExecuting = FALSE; + S9xSetSoundMute (TRUE); + } + + if (local_sa1) + { + S9xFixSA1AfterSnapshotLoad (); + SA1.Flags |= sa1_old_flags & (TRACE_FLAG); + } + + if (local_spc_rtc) + { + S9xUpdateRTC(); + } + + if (local_bsx_data) + S9xFixBSXAfterSnapshotLoad(); + + S9xFixSoundAfterSnapshotLoad (version); uint8 hdma_byte = Memory.FillRAM[0x420c]; S9xSetCPU(hdma_byte, 0x420c); - S9xControlPostLoadState(&ctl_snap); - - printf("unfreezing 4...\n"); + if(version<2){ + for(int d=0; d<8; d++){ + DMA[d].UnknownByte = Memory.FillRAM[0x430b+(d<<4)]; + DMA[d].UnusedBit43x0 = (Memory.FillRAM[0x4300+(d<<4)]&0x20)?1:0; + } + PPU.M7HOFS = PPU.BG[0].HOffset; + PPU.M7VOFS = PPU.BG[0].VOffset; + if(!Memory.FillRAM[0x4213]){ + // most likely an old savestate + Memory.FillRAM[0x4213]=Memory.FillRAM[0x4201]; + if(!Memory.FillRAM[0x4213]) + Memory.FillRAM[0x4213]=Memory.FillRAM[0x4201]=0xFF; + } + if(local_apu) APU.Flags = Obsolete.SAPU_Flags; - #ifndef ZSNES_FX - if (local_superfx) - { - GSU.pfPlot = fx_PlotTable[GSU.vMode]; - GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; + // FIXME: assuming the old savesate was made outside S9xMainLoop(). + // In this case, V=0 and HDMA was already initialized. + CPU.WhichEvent = HC_HDMA_INIT_EVENT; + CPU.NextEvent = Timings.HDMAInit; + S9xReschedule(); + } - // Sanity check for 64-bit register offset problem - if (GSU.pvSreg < &GSU.avReg[0] || GSU.pvSreg >= ((uint32 *) &GSU.avReg[0]) + 16) - GSU.pvSreg = &GSU.avReg[0]; + ICPU.ShiftedPB = Registers.PB << 16; + ICPU.ShiftedDB = Registers.DB << 16; + S9xSetPCBase (Registers.PBPC); + S9xUnpackStatus (); + S9xFixCycles (); +// S9xReschedule (); // <-- this causes desync when recording or playing movies - if (GSU.pvDreg < &GSU.avReg[0] || GSU.pvDreg >= ((uint32 *) &GSU.avReg[0]) + 16) - GSU.pvDreg = &GSU.avReg[0]; - } - #else +#ifdef ZSNES_FX if (Settings.SuperFX) - S9xSuperFXPostLoadState(); - #endif - - if (local_sa1 && local_sa1_registers) - { - SA1.Flags |= sa1_old_flags & TRACE_FLAG; - S9xSA1PostLoadState(); - } + S9xSuperFXPostLoadState (); +#endif + S9xSRTCPostLoadState (); if (Settings.SDD1) - S9xSDD1PostLoadState(); + S9xSDD1PostLoadState (); - if (local_spc7110) - S9xSPC7110PostLoadState(version); - - if (local_srtc) - S9xSRTCPostLoadState(version); - - if (local_bsx_data) - S9xBSXPostLoadState(); - - if (local_movie_data) + if (version < 5) { - // restore last displayed pad_read status - extern bool8 pad_read, pad_read_last; - bool8 pad_read_temp = pad_read; - - pad_read = pad_read_last; - S9xUpdateFrameCounter(-1); - pad_read = pad_read_temp; + // This is not correct, it causes desyncs frequently. + // So they have been stored in a snapshot since ver.5. + APU.NextAPUTimerPos = (CPU.Cycles << SNES_APU_ACCURACY); + APU.APUTimerCounter = 0; } - - if (local_screenshot) - { - SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; - - UnfreezeStructFromCopy(ssi, SnapScreenshot, COUNT(SnapScreenshot), local_screenshot, version); - - IPPU.RenderedScreenWidth = min(ssi->Width, IMAGE_WIDTH); - IPPU.RenderedScreenHeight = min(ssi->Height, IMAGE_HEIGHT); - const bool8 scaleDownX = IPPU.RenderedScreenWidth < ssi->Width; - const bool8 scaleDownY = IPPU.RenderedScreenHeight < ssi->Height && ssi->Height > SNES_HEIGHT_EXTENDED; - GFX.DoInterlace = Settings.SupportHiRes ? ssi->Interlaced : 0; - - printf("unfreezing 5...\n"); - - uint8 *rowpix = ssi->Data; - uint16 *screen = GFX.Screen; - - for (int y = 0; y < IPPU.RenderedScreenHeight; y++, screen += GFX.RealPPL) - { - for (int x = 0; x < IPPU.RenderedScreenWidth; x++) - { - uint32 r, g, b; - - r = *(rowpix++); - g = *(rowpix++); - b = *(rowpix++); - - if (scaleDownX) - { - r = (r + *(rowpix++)) >> 1; - g = (g + *(rowpix++)) >> 1; - b = (b + *(rowpix++)) >> 1; - - if (x + x + 1 >= ssi->Width) - break; - } - - screen[x] = BUILD_PIXEL(r, g, b); - } - - if (scaleDownY) - { - rowpix += 3 * ssi->Width; - if (y + y + 1 >= ssi->Height) - break; - } - } - - printf("unfreezing 6...\n"); - - // black out what we might have missed - for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32) (IMAGE_HEIGHT); y++) - memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); - - delete ssi; - - printf("unfreezing 7...\n"); - } - else - { - printf("unfreezing 8...\n"); - // couldn't load graphics, so black out the screen instead - for (uint32 y = 0; y < (uint32) (IMAGE_HEIGHT); y++) - memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); - } - - S9xSetSoundMute(FALSE); - printf("unfreezing 9...\n"); } - printf("unfreezing 10...\n"); - if (local_cpu) delete [] local_cpu; - if (local_registers) delete [] local_registers; - if (local_ppu) delete [] local_ppu; - if (local_dma) delete [] local_dma; - if (local_vram) delete [] local_vram; - if (local_ram) delete [] local_ram; - if (local_sram) delete [] local_sram; - if (local_fillram) delete [] local_fillram; - if (local_apu_sound) delete [] local_apu_sound; - if (local_control_data) delete [] local_control_data; - if (local_timing_data) delete [] local_timing_data; - if (local_superfx) delete [] local_superfx; - if (local_sa1) delete [] local_sa1; - if (local_sa1_registers) delete [] local_sa1_registers; - if (local_dsp1) delete [] local_dsp1; - if (local_dsp2) delete [] local_dsp2; - if (local_dsp4) delete [] local_dsp4; - if (local_cx4_data) delete [] local_cx4_data; - if (local_st010) delete [] local_st010; - if (local_obc1) delete [] local_obc1; - if (local_obc1_data) delete [] local_obc1_data; - if (local_spc7110) delete [] local_spc7110; - if (local_srtc) delete [] local_srtc; - if (local_rtc_data) delete [] local_rtc_data; - if (local_bsx_data) delete [] local_bsx_data; - if (local_screenshot) delete [] local_screenshot; - if (local_movie_data) delete [] local_movie_data; - printf("unfreezing 11...\n"); + + if (local_cpu) delete [] local_cpu; + if (local_registers) delete [] local_registers; + if (local_ppu) delete [] local_ppu; + if (local_dma) delete [] local_dma; + if (local_vram) delete [] local_vram; + if (local_ram) delete [] local_ram; + if (local_sram) delete [] local_sram; + if (local_fillram) delete [] local_fillram; + if (local_apu) delete [] local_apu; + if (local_apu_registers) delete [] local_apu_registers; + if (local_apu_ram) delete [] local_apu_ram; + if (local_apu_sounddata) delete [] local_apu_sounddata; + if (local_sa1) delete [] local_sa1; + if (local_sa1_registers) delete [] local_sa1_registers; + if (local_spc) delete [] local_spc; + if (local_spc_rtc) delete [] local_spc_rtc; + if (local_movie_data) delete [] local_movie_data; + if (local_control_data) delete [] local_control_data; + if (local_timing_data) delete [] local_timing_data; + if (local_bsx_data) delete [] local_bsx_data; + if (local_dsp1) delete [] local_dsp1; + if (local_cx4_data) delete [] local_cx4_data; + if (local_superfx) delete [] local_superfx; + if (local_screenshot) delete [] local_screenshot; + for(int i=0; i<2; i++) + if (local_dummy[i]) delete [] local_dummy[i]; + + unfreezing_from_stream = false; + return (result); } -static int FreezeSize (int size, int type) + +/*****************************************************************/ + +int FreezeSize (int size, int type) { - switch (type) - { - case uint32_ARRAY_V: - case uint32_INDIR_ARRAY_V: - return (size * 4); - - case uint16_ARRAY_V: - case uint16_INDIR_ARRAY_V: - return (size * 2); - - default: - return (size); - } + switch (type) + { + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + return (size * 2); + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + return (size * 4); + default: + return (size); + } } -static void FreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields) +void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, + int num_fields) { - int len = 0; - int i, j; + // Work out the size of the required block + int len = 0; + int i; + int j; - for (i = 0; i < num_fields; i++) - { - if (SNAPSHOT_VERSION < fields[i].debuted_in) + for (i = 0; i < num_fields; i++) + { + if(fields[i].debuted_in > SNAPSHOT_VERSION) { - fprintf(stderr, "%s[%p]: field has bad debuted_in value %d, > %d.", name, (void *) fields, fields[i].debuted_in, SNAPSHOT_VERSION); + fprintf(stderr, "%s[%p]: field has bad debuted_in value %d, > %d.", name, (void *)fields, fields[i].debuted_in, SNAPSHOT_VERSION); continue; } - if (SNAPSHOT_VERSION < fields[i].deleted_in) - len += FreezeSize(fields[i].size, fields[i].type); - } + if (SNAPSHOT_VERSION= fields[i].deleted_in || SNAPSHOT_VERSION < fields[i].debuted_in) - continue; + uint8 *block = new uint8 [len]; + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; - addr = (uint8 *) base + fields[i].offset; + // Build the block ready to be streamed out + for (i = 0; i < num_fields; i++) + { + if (SNAPSHOT_VERSION>=fields[i].deleted_in) continue; + if (SNAPSHOT_VERSION> 8); - *ptr++ = (uint8) word; - break; - - case 4: - dword = *((uint32 *) (addr)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - break; - - case 8: - qword = *((int64 *) (addr)); - *ptr++ = (uint8) (qword >> 56); - *ptr++ = (uint8) (qword >> 48); - *ptr++ = (uint8) (qword >> 40); - *ptr++ = (uint8) (qword >> 32); - *ptr++ = (uint8) (qword >> 24); - *ptr++ = (uint8) (qword >> 16); - *ptr++ = (uint8) (qword >> 8); - *ptr++ = (uint8) qword; - break; - } - + case INT_V: + case POINTER_V: + switch (fields[i].size) + { + case 1: + *ptr++ = *(addr); break; - - case uint8_ARRAY_V: + case 2: + word = *((uint16 *) (addr)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + break; + case 4: + dword = *((uint32 *) (addr)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + break; + case 8: + qword = *((int64 *) (addr)); + *ptr++ = (uint8) (qword >> 56); + *ptr++ = (uint8) (qword >> 48); + *ptr++ = (uint8) (qword >> 40); + *ptr++ = (uint8) (qword >> 32); + *ptr++ = (uint8) (qword >> 24); + *ptr++ = (uint8) (qword >> 16); + *ptr++ = (uint8) (qword >> 8); + *ptr++ = (uint8) qword; + break; + } + break; + case uint8_ARRAY_V: case uint8_INDIR_ARRAY_V: - memmove(ptr, addr, fields[i].size); + memmove (ptr, addr, fields[i].size); ptr += fields[i].size; - break; - case uint16_ARRAY_V: case uint16_INDIR_ARRAY_V: for (j = 0; j < fields[i].size; j++) @@ -1961,321 +1850,876 @@ static void FreezeStruct (STREAM stream, const char *name, void *base, FreezeDat *ptr++ = (uint8) (word >> 8); *ptr++ = (uint8) word; } - break; - case uint32_ARRAY_V: case uint32_INDIR_ARRAY_V: for (j = 0; j < fields[i].size; j++) { dword = *((uint32 *) (addr + j * 4)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - } - - break; - } - } - - FreezeBlock(stream, name, block, len); - delete [] block; + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + } + break; + } + } + //fprintf(stderr, "%s: Wrote %d bytes\n", name, ptr-block); +#ifndef NGC + FreezeBlock (stream, name, block, len); +#else + NGCFreezeBlock(name, block, len); +#endif + delete[] block; } -static void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +void FreezeBlock (STREAM stream, char *name, uint8 *block, int size) { - char buffer[20]; + char buffer [512]; - // check if it fits in 6 digits. (letting it go over and using strlen isn't safe) - if (size <= 999999) - sprintf(buffer, "%s:%06d:", name, size); - else + if(size <= 999999) // check if it fits in 6 digits. (letting it go over and using strlen isn't safe) + sprintf (buffer, "%s:%06d:", name, size); + else + { + // to make it fit, pack it in the bytes instead of as digits + sprintf (buffer, "%s:------:", name); + buffer[6] = (unsigned char)((unsigned)size >> 24); + buffer[7] = (unsigned char)((unsigned)size >> 16); + buffer[8] = (unsigned char)((unsigned)size >> 8); + buffer[9] = (unsigned char)((unsigned)size >> 0); + } + buffer[11] = 0; + + WRITE_STREAM (buffer, 11, stream); + WRITE_STREAM (block, size, stream); + +} + +#ifdef NGC +void NGCFreezeStruct() +{ + STREAM s = NULL; + + FreezeStruct (s,"CPU", &CPU, SnapCPU, COUNT (SnapCPU)); + FreezeStruct (s,"REG", &Registers, SnapRegisters, COUNT (SnapRegisters)); + FreezeStruct (s,"PPU", &PPU, SnapPPU, COUNT (SnapPPU)); + FreezeStruct (s,"DMA", DMA, SnapDMA, COUNT (SnapDMA)); + + // RAM and VRAM + NGCFreezeBlock ("VRA", Memory.VRAM, 0x10000); + NGCFreezeBlock ("RAM", Memory.RAM, 0x20000); + NGCFreezeBlock ("SRA", Memory.SRAM, 0x20000); + NGCFreezeBlock ("FIL", Memory.FillRAM, 0x8000); + + if (Settings.APUEnabled) + { + // APU + FreezeStruct (s,"APU", &APU, SnapAPU, COUNT (SnapAPU)); + FreezeStruct (s,"ARE", &APURegisters, SnapAPURegisters, + COUNT (SnapAPURegisters)); + NGCFreezeBlock ("ARA", IAPU.RAM, 0x10000); + FreezeStruct (s,"SOU", &SoundData, SnapSoundData, + COUNT (SnapSoundData)); + } + + // Controls + struct SControlSnapshot ctl_snap; + S9xControlPreSave(&ctl_snap); + FreezeStruct (s,"CTL", &ctl_snap, SnapControls, COUNT (SnapControls)); + + // Timings + FreezeStruct (s,"TIM", &Timings, SnapTimings, COUNT (SnapTimings)); + + // Special chips + if (Settings.SA1) + { + S9xSA1PackStatus (); + FreezeStruct (s,"SA1", &SA1, SnapSA1, COUNT (SnapSA1)); + FreezeStruct (s,"SAR", &SA1Registers, SnapSA1Registers, + COUNT (SnapSA1Registers)); + } + + if (Settings.SPC7110) + { + FreezeStruct (s,"SP7", &s7r, SnapSPC7110, COUNT (SnapSPC7110)); + } + + if (Settings.SPC7110RTC) + { + FreezeStruct (s,"RTC", &rtc_f9, SnapS7RTC, COUNT (SnapS7RTC)); + } + + // BS + if (Settings.BS) { - // to make it fit, pack it in the bytes instead of as digits - sprintf(buffer, "%s:------:", name); - buffer[6] = (unsigned char) ((unsigned) size >> 24); - buffer[7] = (unsigned char) ((unsigned) size >> 16); - buffer[8] = (unsigned char) ((unsigned) size >> 8); - buffer[9] = (unsigned char) ((unsigned) size >> 0); + FreezeStruct (s,"BSX", &BSX, SnapBSX, COUNT (SnapBSX)); } - buffer[11] = 0; + // DSP1 chip + if(Settings.DSP1Master) + { + S9xPreSaveDSP1(); + FreezeStruct (s, "DSP", &DSP1, SnapDSP1, COUNT (SnapDSP1)); + } - WRITE_STREAM(buffer, 11, stream); - WRITE_STREAM(block, size, stream); + if (Settings.C4) + { +#ifdef ZSNES_C4 + extern uint8 *C4Ram; + if (C4Ram) + NGCFreezeBlock ("CX4", C4Ram, 8192); +#else + NGCFreezeBlock ("CX4", Memory.C4RAM, 8192); +#endif + } + +#ifndef ZSNES_FX + if (Settings.SuperFX) + FreezeStruct (s, "SFX", &GSU, SnapFX, COUNT (SnapFX)); +#endif } -static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size) -{ - char buffer[20]; - int len = 0, rem = 0; - long rewind = FIND_STREAM(stream); +#endif - size_t l = READ_STREAM(buffer, 11, stream); +/*****************************************************************/ + +int UnfreezeBlock (STREAM stream, char *name, uint8 *block, int size) +{ +#ifndef NGC + char buffer [20]; + int len = 0; + int rem = 0; + long rewind = FIND_STREAM(stream); + + size_t l = READ_STREAM (buffer, 11, stream); buffer[l] = 0; - - if (l != 11 || strncmp(buffer, name, 3) != 0 || buffer[3] != ':') - { - err: + if (l != 11 + || strncmp (buffer, name, 3) != 0 + || buffer[3] != ':') + { + err: fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer); - REVERT_STREAM(stream, FIND_STREAM(stream) - l, 0); + REVERT_STREAM(stream, FIND_STREAM(stream)-l, 0); return (WRONG_FORMAT); - } + } - if (buffer[4] == '-') - { - len = (((unsigned char) buffer[6]) << 24) - | (((unsigned char) buffer[7]) << 16) - | (((unsigned char) buffer[8]) << 8) - | (((unsigned char) buffer[9]) << 0); - } - else - len = atoi(buffer + 4); + if(buffer[4] == '-') + { + len = (((unsigned char)buffer[6]) << 24) + | (((unsigned char)buffer[7]) << 16) + | (((unsigned char)buffer[8]) << 8) + | (((unsigned char)buffer[9]) << 0); + } + else + { + len = atoi(buffer+4); + } + if(len <= 0) goto err; - if (len <= 0) - goto err; + if (len > size) + { + rem = len - size; + len = size; + } + ZeroMemory (block, size); + if (READ_STREAM (block, len, stream) != len) + { + REVERT_STREAM(stream, rewind, 0); + return (WRONG_FORMAT); + } + if (rem) + { + char *junk = new char [rem]; + len = READ_STREAM (junk, rem, stream); + delete [] junk; + if (len != rem) + { + REVERT_STREAM(stream, rewind, 0); + return (WRONG_FORMAT); + } + } - if (len > size) - { - rem = len - size; - len = size; - } - - ZeroMemory(block, size); - - if (READ_STREAM(block, len, stream) != len) - { - REVERT_STREAM(stream, rewind, 0); - return (WRONG_FORMAT); - } - - if (rem) - { - char *junk = new char[rem]; - len = READ_STREAM(junk, rem, stream); - delete [] junk; - if (len != rem) - { - REVERT_STREAM(stream, rewind, 0); - return (WRONG_FORMAT); - } - } - - return (SUCCESS); + return (SUCCESS); +#else + return NGCUnFreezeBlock(name, block, size); +#endif } -static int UnfreezeBlockCopy (STREAM stream, const char *name, uint8 **block, int size) +int UnfreezeBlockCopy (STREAM stream, char *name, uint8** block, int size) { - int result; + *block = new uint8 [size]; + int result; - *block = new uint8[size]; + if ((result = UnfreezeBlock (stream, name, *block, size)) != SUCCESS) + { + delete [] (*block); + *block = NULL; + return (result); + } - result = UnfreezeBlock(stream, name, *block, size); - if (result != SUCCESS) - { - delete [] (*block); - *block = NULL; - return (result); - } - - return (SUCCESS); + return (result); } -static int UnfreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields, int version) +int UnfreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, + int num_fields, int version) { - int result; - uint8 *block = NULL; + uint8 *block = NULL; + int result; - result = UnfreezeStructCopy(stream, name, &block, fields, num_fields, version); - if (result != SUCCESS) - { - if (block != NULL) - delete [] block; - return (result); - } - - UnfreezeStructFromCopy(base, fields, num_fields, block, version); - delete [] block; - - return (SUCCESS); + result = UnfreezeStructCopy (stream, name, &block, fields, num_fields, version); + if (result != SUCCESS) + { + if (block!=NULL) delete [] block; + return result; + } + UnfreezeStructFromCopy (base, fields, num_fields, block, version); + delete [] block; + return SUCCESS; } -static int UnfreezeStructCopy (STREAM stream, const char *name, uint8 **block, FreezeData *fields, int num_fields, int version) +int UnfreezeStructCopy (STREAM stream, char *name, uint8** block, FreezeData *fields, int num_fields, int version) { - int len = 0; + // Work out the size of the required block + int len = 0; + int i; - for (int i = 0; i < num_fields; i++) - { - if (version >= fields[i].debuted_in && version < fields[i].deleted_in) - len += FreezeSize(fields[i].size, fields[i].type); - } + for (i = 0; i < num_fields; i++) + { + if (version>=fields[i].debuted_in && version= fields[i].deleted_in) - continue; + // Unpack the block of data into a C structure + for (i = 0; i < num_fields; i++) + { + if (version=fields[i].deleted_in) continue; + base = (SNAPSHOT_VERSION>=fields[i].deleted_in)?((void *)&Obsolete):sbase; - base = (SNAPSHOT_VERSION >= fields[i].deleted_in) ? ((void *) &Obsolete) : sbase; - addr = (uint8 *) base + fields[i].offset; + uint8 *addr = (uint8 *) base + fields[i].offset; + // determine real address of indirect-type fields + // (where the structure contains a pointer to an array rather than the array itself) if (fields[i].type == uint8_INDIR_ARRAY_V || fields[i].type == uint16_INDIR_ARRAY_V || fields[i].type == uint32_INDIR_ARRAY_V) - addr = (uint8 *) (*((pint *) addr)); + addr = (uint8 *)(*((pint*)addr)); - switch (fields[i].type) + switch (fields[i].type) + { + case INT_V: + case POINTER_V: + switch (fields[i].size) + { + case 1: + if(fields[i].offset<0){ ptr++; break; } + *(addr) = *ptr++; + break; + case 2: + if(fields[i].offset<0){ ptr+=2; break; } + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) (addr)) = word; + break; + case 4: + if(fields[i].offset<0){ ptr+=4; break; } + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) (addr)) = dword; + break; + case 8: + if(fields[i].offset<0){ ptr+=8; break; } + qword = (int64) *ptr++ << 56; + qword |= (int64) *ptr++ << 48; + qword |= (int64) *ptr++ << 40; + qword |= (int64) *ptr++ << 32; + qword |= (int64) *ptr++ << 24; + qword |= (int64) *ptr++ << 16; + qword |= (int64) *ptr++ << 8; + qword |= (int64) *ptr++; + *((int64 *) (addr)) = qword; + break; + default: + assert(0); + break; + } + break; + case uint8_ARRAY_V: + case uint8_INDIR_ARRAY_V: + if(fields[i].offset>=0) + memmove (addr, ptr, fields[i].size); + ptr += fields[i].size; + break; + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + if(fields[i].offset<0){ ptr+=fields[i].size*2; break; } + for (j = 0; j < fields[i].size; j++) + { + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) (addr + j * 2)) = word; + } + break; + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + if(fields[i].offset<0){ ptr+=fields[i].size*4; break; } + for (j = 0; j < fields[i].size; j++) + { + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) (addr + j * 4)) = dword; + } + break; + } + + // convert pointer-type saves from relative to absolute pointers + if(fields[i].type == POINTER_V) { - case INT_V: - case POINTER_V: - switch (fields[i].size) - { - case 1: - if (fields[i].offset < 0) - { - ptr++; - break; - } - - *(addr) = *ptr++; - break; - - case 2: - if (fields[i].offset < 0) - { - ptr += 2; - break; - } - - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) (addr)) = word; - break; - - case 4: - if (fields[i].offset < 0) - { - ptr += 4; - break; - } - - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) (addr)) = dword; - break; - - case 8: - if (fields[i].offset < 0) - { - ptr += 8; - break; - } - - qword = (int64) *ptr++ << 56; - qword |= (int64) *ptr++ << 48; - qword |= (int64) *ptr++ << 40; - qword |= (int64) *ptr++ << 32; - qword |= (int64) *ptr++ << 24; - qword |= (int64) *ptr++ << 16; - qword |= (int64) *ptr++ << 8; - qword |= (int64) *ptr++; - *((int64 *) (addr)) = qword; - break; - - default: - assert(0); - break; - } - - break; - - case uint8_ARRAY_V: - case uint8_INDIR_ARRAY_V: - if (fields[i].offset >= 0) - memmove(addr, ptr, fields[i].size); - ptr += fields[i].size; - - break; - - case uint16_ARRAY_V: - case uint16_INDIR_ARRAY_V: - if (fields[i].offset < 0) - { - ptr += fields[i].size * 2; - break; - } - - for (j = 0; j < fields[i].size; j++) - { - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) (addr + j * 2)) = word; - } - - break; - - case uint32_ARRAY_V: - case uint32_INDIR_ARRAY_V: - if (fields[i].offset < 0) - { - ptr += fields[i].size * 4; - break; - } - - for (j = 0; j < fields[i].size; j++) - { - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) (addr + j * 4)) = dword; - } - - break; - } - - if (fields[i].type == POINTER_V) - { - relativeAddr = (int) *((pint *) ((uint8 *) base + fields[i].offset)); - uint8 *relativeTo = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset2)); - *((pint *) (addr)) = (pint) (relativeTo + relativeAddr); + int relativeAddr = (int)*((pint*)((uint8 *) base + fields[i].offset)); + uint8* relativeTo = (uint8*)*((pint*)((uint8 *) base + fields[i].offset2)); + *((pint *) (addr)) = (pint)(relativeTo + relativeAddr); } } + //fprintf(stderr, "%p: Unfroze %d bytes\n", fields, ptr-block); } + +/*****************************************************************/ + +extern uint8 spc_dump_dsp[0x100]; + bool8 S9xSPCDump (const char *filename) { - FILE *fs; - uint8 buf[SNES_SPC::spc_file_size]; + static uint8 header [] = { + 'S', 'N', 'E', 'S', '-', 'S', 'P', 'C', '7', '0', '0', ' ', + 'S', 'o', 'u', 'n', 'd', ' ', 'F', 'i', 'l', 'e', ' ', + 'D', 'a', 't', 'a', ' ', 'v', '0', '.', '3', '0', 26, 26, 26 + }; + static uint8 version = { + 0x1e + }; - fs = fopen(filename, "wb"); - if (!fs) + FILE *fs; + + if (!(fs = fopen (filename, "wb"))) return (FALSE); - S9xSetSoundMute(TRUE); + S9xSetSoundMute (TRUE); - spc_core->init_header(buf); - spc_core->save_spc(buf); + // The SPC file format: + // 0000: header: 'SNES-SPC700 Sound File Data v0.30',26,26,26 + // 0036: version: $1e + // 0037: SPC700 PC: + // 0039: SPC700 A: + // 0040: SPC700 X: + // 0041: SPC700 Y: + // 0042: SPC700 P: + // 0043: SPC700 S: + // 0044: Reserved: 0, 0, 0, 0 + // 0048: Title of game: 32 bytes + // 0000: Song name: 32 bytes + // 0000: Name of dumper: 32 bytes + // 0000: Comments: 32 bytes + // 0000: Date of SPC dump: 4 bytes + // 0000: Fade out time in milliseconds: 4 bytes + // 0000: Fade out length in milliseconds: 2 bytes + // 0000: Default channel enables: 1 bytes + // 0000: Emulator used to dump .SPC files: 1 byte, 1 == ZSNES + // 0000: Reserved: 36 bytes + // 0256: SPC700 RAM: 64K + // ----: DSP Registers: 256 bytes - fwrite(buf, SNES_SPC::spc_file_size, 1, fs); - - fclose(fs); - - S9xSetSoundMute(FALSE); - - return (TRUE); + if (fwrite (header, sizeof (header), 1, fs) != 1 || + fputc (version, fs) == EOF || + fseek (fs, 37, SEEK_SET) == EOF || + fputc (APURegisters.PC & 0xff, fs) == EOF || + fputc (APURegisters.PC >> 8, fs) == EOF || + fputc (APURegisters.YA.B.A, fs) == EOF || + fputc (APURegisters.X, fs) == EOF || + fputc (APURegisters.YA.B.Y, fs) == EOF || + fputc (APURegisters.P, fs) == EOF || + fputc (APURegisters.S, fs) == EOF || + fseek (fs, 256, SEEK_SET) == EOF || + fwrite (IAPU.RAM, 0x10000, 1, fs) != 1 || + fwrite (spc_dump_dsp, 1, 256, fs) != 256 || + fwrite (APU.ExtraRAM, 64, 1, fs) != 1 || + fclose (fs) < 0) + { + S9xSetSoundMute (FALSE); + return (FALSE); + } + S9xSetSoundMute (FALSE); + return (TRUE); } + +bool8 S9xUnfreezeZSNES (const char *filename) +{ + FILE *fs; + uint8 t [4000]; + + if (!(fs = fopen (filename, "rb"))) + return (FALSE); + + if (fread (t, 64, 1, fs) == 1 && + strncmp ((char *) t, "ZSNES Save State File V0.6", 26) == 0) + { + S9xReset (); + S9xSetSoundMute (TRUE); + + // 28 Curr cycle + CPU.V_Counter = READ_WORD (&t[29]); + // 33 instrset + Settings.APUEnabled = t[36]; + + // 34 bcycpl cycles per scanline + // 35 cycphb cyclers per hblank + + Registers.A.W = READ_WORD (&t[41]); + Registers.DB = t[43]; + Registers.PB = t[44]; + Registers.S.W = READ_WORD (&t[45]); + Registers.D.W = READ_WORD (&t[47]); + Registers.X.W = READ_WORD (&t[49]); + Registers.Y.W = READ_WORD (&t[51]); + Registers.P.W = READ_WORD (&t[53]); + Registers.PCw = READ_WORD (&t[55]); + + fread (t, 1, 8, fs); + fread (t, 1, 3019, fs); + S9xSetCPU (t[2], 0x4200); + Memory.FillRAM [0x4210] = t[3]; + PPU.IRQVBeamPos = READ_WORD (&t[4]); + PPU.IRQHBeamPos = READ_WORD (&t[2527]); + PPU.Brightness = t[6]; + PPU.ForcedBlanking = t[8] >> 7; + + int i; + for (i = 0; i < 544; i++) + S9xSetPPU (t[0464 + i], 0x2104); + + PPU.OBJNameBase = READ_WORD (&t[9]); + PPU.OBJNameSelect = READ_WORD (&t[13]) - PPU.OBJNameBase; + switch (t[18]) + { + case 4: + if (t[17] == 1) + PPU.OBJSizeSelect = 0; + else + PPU.OBJSizeSelect = 6; + break; + case 16: + if (t[17] == 1) + PPU.OBJSizeSelect = 1; + else + PPU.OBJSizeSelect = 3; + break; + default: + case 64: + if (t[17] == 1) + PPU.OBJSizeSelect = 2; + else + if (t[17] == 4) + PPU.OBJSizeSelect = 4; + else + PPU.OBJSizeSelect = 5; + break; + } + PPU.OAMAddr = READ_WORD (&t[25]); + PPU.SavedOAMAddr = READ_WORD (&t[27]); + PPU.FirstSprite = t[29]; + PPU.BGMode = t[30]; + PPU.BG3Priority = t[31]; + PPU.BG[0].BGSize = (t[32] >> 0) & 1; + PPU.BG[1].BGSize = (t[32] >> 1) & 1; + PPU.BG[2].BGSize = (t[32] >> 2) & 1; + PPU.BG[3].BGSize = (t[32] >> 3) & 1; + PPU.Mosaic = t[33] + 1; + PPU.BGMosaic [0] = (t[34] & 1) != 0; + PPU.BGMosaic [1] = (t[34] & 2) != 0; + PPU.BGMosaic [2] = (t[34] & 4) != 0; + PPU.BGMosaic [3] = (t[34] & 8) != 0; + PPU.BG [0].SCBase = READ_WORD (&t[35]) >> 1; + PPU.BG [1].SCBase = READ_WORD (&t[37]) >> 1; + PPU.BG [2].SCBase = READ_WORD (&t[39]) >> 1; + PPU.BG [3].SCBase = READ_WORD (&t[41]) >> 1; + PPU.BG [0].SCSize = t[67]; + PPU.BG [1].SCSize = t[68]; + PPU.BG [2].SCSize = t[69]; + PPU.BG [3].SCSize = t[70]; + PPU.BG[0].NameBase = READ_WORD (&t[71]) >> 1; + PPU.BG[1].NameBase = READ_WORD (&t[73]) >> 1; + PPU.BG[2].NameBase = READ_WORD (&t[75]) >> 1; + PPU.BG[3].NameBase = READ_WORD (&t[77]) >> 1; + PPU.BG[0].HOffset = READ_WORD (&t[79]); + PPU.BG[1].HOffset = READ_WORD (&t[81]); + PPU.BG[2].HOffset = READ_WORD (&t[83]); + PPU.BG[3].HOffset = READ_WORD (&t[85]); + PPU.BG[0].VOffset = READ_WORD (&t[89]); + PPU.BG[1].VOffset = READ_WORD (&t[91]); + PPU.BG[2].VOffset = READ_WORD (&t[93]); + PPU.BG[3].VOffset = READ_WORD (&t[95]); + PPU.VMA.Increment = READ_WORD (&t[97]) >> 1; + PPU.VMA.High = t[99]; +#ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = t[100]; +#endif + S9xSetPPU (t[2512], 0x2115); + PPU.VMA.Address = READ_DWORD (&t[101]); + for (i = 0; i < 512; i++) + S9xSetPPU (t[1488 + i], 0x2122); + + PPU.CGADD = (uint8) READ_WORD (&t[105]); + Memory.FillRAM [0x212c] = t[108]; + Memory.FillRAM [0x212d] = t[109]; + PPU.ScreenHeight = READ_WORD (&t[111]); + Memory.FillRAM [0x2133] = t[2526]; + Memory.FillRAM [0x4202] = t[113]; + Memory.FillRAM [0x4204] = t[114]; + Memory.FillRAM [0x4205] = t[115]; + Memory.FillRAM [0x4214] = t[116]; + Memory.FillRAM [0x4215] = t[117]; + Memory.FillRAM [0x4216] = t[118]; + Memory.FillRAM [0x4217] = t[119]; + PPU.VBeamPosLatched = READ_WORD (&t[122]); + PPU.HBeamPosLatched = READ_WORD (&t[120]); + PPU.Window1Left = t[127]; + PPU.Window1Right = t[128]; + PPU.Window2Left = t[129]; + PPU.Window2Right = t[130]; + S9xSetPPU (t[131] | (t[132] << 4), 0x2123); + S9xSetPPU (t[133] | (t[134] << 4), 0x2124); + S9xSetPPU (t[135] | (t[136] << 4), 0x2125); + S9xSetPPU (t[137], 0x212a); + S9xSetPPU (t[138], 0x212b); + S9xSetPPU (t[139], 0x212e); + S9xSetPPU (t[140], 0x212f); + S9xSetPPU (t[141], 0x211a); + PPU.MatrixA = READ_WORD (&t[142]); + PPU.MatrixB = READ_WORD (&t[144]); + PPU.MatrixC = READ_WORD (&t[146]); + PPU.MatrixD = READ_WORD (&t[148]); + PPU.CentreX = READ_WORD (&t[150]); + PPU.CentreY = READ_WORD (&t[152]); + PPU.M7HOFS = PPU.BG[0].HOffset; + PPU.M7VOFS = PPU.BG[0].VOffset; + // JoyAPos t[154] + // JoyBPos t[155] + Memory.FillRAM [0x2134] = t[156]; // Matrix mult + Memory.FillRAM [0x2135] = t[157]; // Matrix mult + Memory.FillRAM [0x2136] = t[158]; // Matrix mult + PPU.WRAM = READ_DWORD (&t[161]); + + for (i = 0; i < 128; i++) + S9xSetCPU (t[165 + i], 0x4300 + i); + + if (t[294]) + CPU.IRQActive |= PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE; + + S9xSetCPU (t[296], 0x420c); + // hdmadata t[297] + 8 * 19 + PPU.FixedColourRed = t[450]; + PPU.FixedColourGreen = t[451]; + PPU.FixedColourBlue = t[452]; + S9xSetPPU (t[454], 0x2130); + S9xSetPPU (t[455], 0x2131); + // vraminctype ... + + fread (Memory.RAM, 1, 128 * 1024, fs); + fread (Memory.VRAM, 1, 64 * 1024, fs); + + if (Settings.APUEnabled) + { + // SNES SPC700 RAM (64K) + fread (IAPU.RAM, 1, 64 * 1024, fs); + + // Junk 16 bytes + fread (t, 1, 16, fs); + + // SNES SPC700 state and internal ZSNES SPC700 emulation state + fread (t, 1, 304, fs); + + APURegisters.PC = READ_DWORD (&t[0]); + APURegisters.YA.B.A = t[4]; + APURegisters.X = t[8]; + APURegisters.YA.B.Y = t[12]; + APURegisters.P = t[16]; + APURegisters.S = t[24]; + + APU.Cycles = READ_DWORD (&t[32]) << SNES_APU_ACCURACY; + APU.ShowROM = (IAPU.RAM [0xf1] & 0x80) != 0; + APU.OutPorts [0] = t[36]; + APU.OutPorts [1] = t[37]; + APU.OutPorts [2] = t[38]; + APU.OutPorts [3] = t[39]; + + APU.TimerEnabled [0] = (t[40] & 1) != 0; + APU.TimerEnabled [1] = (t[40] & 2) != 0; + APU.TimerEnabled [2] = (t[40] & 4) != 0; + S9xSetAPUTimer (0xfa, t[41]); + S9xSetAPUTimer (0xfb, t[42]); + S9xSetAPUTimer (0xfc, t[43]); + APU.Timer [0] = t[44]; + APU.Timer [1] = t[45]; + APU.Timer [2] = t[46]; + + memmove (APU.ExtraRAM, &t[48], 64); + + // Internal ZSNES sound DSP state + fread (t, 1, 1068, fs); + + // SNES sound DSP register values + fread (t, 1, 256, fs); + + uint8 saved = IAPU.RAM [0xf2]; + + for (i = 0; i < 128; i++) + { + switch (i) + { + case APU_KON: + case APU_KOFF: + break; + case APU_FLG: + t[i] &= ~APU_SOFT_RESET; + default: + IAPU.RAM [0xf2] = i; + S9xSetAPUDSP (t[i]); + break; + } + } + IAPU.RAM [0xf2] = APU_KON; + S9xSetAPUDSP (t[APU_KON]); + IAPU.RAM [0xf2] = saved; + + S9xSetSoundMute (FALSE); + IAPU.PC = IAPU.RAM + APURegisters.PC; + S9xAPUUnpackStatus (); + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + Settings.APUEnabled = TRUE; + IAPU.APUExecuting = TRUE; + } + else + { + Settings.APUEnabled = FALSE; + IAPU.APUExecuting = FALSE; + S9xSetSoundMute (TRUE); + } + + if (Settings.SuperFX) + { + fread (Memory.SRAM, 1, 64 * 1024, fs); + fseek (fs, 64 * 1024, SEEK_CUR); + fread (Memory.FillRAM + 0x7000, 1, 692, fs); + } + if (Settings.SA1) + { + fread (t, 1, 2741, fs); + S9xSetSA1 (t[4], 0x2200); // Control + S9xSetSA1 (t[12], 0x2203); // ResetV low + S9xSetSA1 (t[13], 0x2204); // ResetV hi + S9xSetSA1 (t[14], 0x2205); // NMI low + S9xSetSA1 (t[15], 0x2206); // NMI hi + S9xSetSA1 (t[16], 0x2207); // IRQ low + S9xSetSA1 (t[17], 0x2208); // IRQ hi + S9xSetSA1 (((READ_DWORD (&t[28]) - (4096*1024-0x6000))) >> 13, 0x2224); + S9xSetSA1 (t[36], 0x2201); + S9xSetSA1 (t[41], 0x2209); + + SA1Registers.A.W = READ_DWORD (&t[592]); + SA1Registers.X.W = READ_DWORD (&t[596]); + SA1Registers.Y.W = READ_DWORD (&t[600]); + SA1Registers.D.W = READ_DWORD (&t[604]); + SA1Registers.DB = t[608]; + SA1Registers.PB = t[612]; + SA1Registers.S.W = READ_DWORD (&t[616]); + SA1Registers.PCw = READ_DWORD (&t[636]); + SA1Registers.P.W = t[620] | (t[624] << 8); + + memmove (&Memory.FillRAM [0x3000], t + 692, 2 * 1024); + + fread (Memory.SRAM, 1, 64 * 1024, fs); + fseek (fs, 64 * 1024, SEEK_CUR); + S9xFixSA1AfterSnapshotLoad (); + } + if(Settings.SPC7110) + { + uint32 temp; + fread(&s7r.bank50, 1,0x10000, fs); + + //NEWSYM SPCMultA, dd 0 4820-23 + fread(&temp, 1, 4, fs); + + s7r.reg4820=temp&(0x0FF); + s7r.reg4821=(temp>>8)&(0x0FF); + s7r.reg4822=(temp>>16)&(0x0FF); + s7r.reg4823=(temp>>24)&(0x0FF); + + //NEWSYM SPCMultB, dd 0 4824-5 + fread(&temp, 1,4,fs); + s7r.reg4824=temp&(0x0FF); + s7r.reg4825=(temp>>8)&(0x0FF); + + + //NEWSYM SPCDivEnd, dd 0 4826-7 + fread(&temp, 1,4,fs); + s7r.reg4826=temp&(0x0FF); + s7r.reg4827=(temp>>8)&(0x0FF); + + //NEWSYM SPCMulRes, dd 0 4828-B + fread(&temp, 1, 4, fs); + + s7r.reg4828=temp&(0x0FF); + s7r.reg4829=(temp>>8)&(0x0FF); + s7r.reg482A=(temp>>16)&(0x0FF); + s7r.reg482B=(temp>>24)&(0x0FF); + + //NEWSYM SPCDivRes, dd 0 482C-D + fread(&temp, 1,4,fs); + s7r.reg482C=temp&(0x0FF); + s7r.reg482D=(temp>>8)&(0x0FF); + + //NEWSYM SPC7110BankA, dd 020100h 4831-3 + fread(&temp, 1, 4, fs); + + s7r.reg4831=temp&(0x0FF); + s7r.reg4832=(temp>>8)&(0x0FF); + s7r.reg4833=(temp>>16)&(0x0FF); + + //NEWSYM SPC7110RTCStat, dd 0 4840,init,command, index + fread(&temp, 1, 4, fs); + + s7r.reg4840=temp&(0x0FF); + +//NEWSYM SPC7110RTC, db 00,00,00,00,00,00,01,00,01,00,00,00,00,00,0Fh,00 +fread(&temp, 1, 4, fs); +if(Settings.SPC7110RTC) +{ + rtc_f9.reg[0]=temp&(0x0FF); + rtc_f9.reg[1]=(temp>>8)&(0x0FF); + rtc_f9.reg[2]=(temp>>16)&(0x0FF); + rtc_f9.reg[3]=(temp>>24)&(0x0FF); +} +fread(&temp, 1, 4, fs); +if(Settings.SPC7110RTC) +{ + rtc_f9.reg[4]=temp&(0x0FF); + rtc_f9.reg[5]=(temp>>8)&(0x0FF); + rtc_f9.reg[6]=(temp>>16)&(0x0FF); + rtc_f9.reg[7]=(temp>>24)&(0x0FF); +} +fread(&temp, 1, 4, fs); +if(Settings.SPC7110RTC) +{ + rtc_f9.reg[8]=temp&(0x0FF); + rtc_f9.reg[9]=(temp>>8)&(0x0FF); + rtc_f9.reg[10]=(temp>>16)&(0x0FF); + rtc_f9.reg[11]=(temp>>24)&(0x0FF); +} +fread(&temp, 1, 4, fs); +if(Settings.SPC7110RTC) +{ + rtc_f9.reg[12]=temp&(0x0FF); + rtc_f9.reg[13]=(temp>>8)&(0x0FF); + rtc_f9.reg[14]=(temp>>16)&(0x0FF); + rtc_f9.reg[15]=(temp>>24)&(0x0FF); +} +//NEWSYM SPC7110RTCB, db 00,00,00,00,00,00,01,00,01,00,00,00,00,01,0Fh,06 +fread(&temp, 1, 4, fs); +fread(&temp, 1, 4, fs); +fread(&temp, 1, 4, fs); +fread(&temp, 1, 4, fs); + +//NEWSYM SPCROMPtr, dd 0 4811-4813 + fread(&temp, 1, 4, fs); + + s7r.reg4811=temp&(0x0FF); + s7r.reg4812=(temp>>8)&(0x0FF); + s7r.reg4813=(temp>>16)&(0x0FF); +//NEWSYM SPCROMtoI, dd SPCROMPtr + fread(&temp, 1, 4, fs); +//NEWSYM SPCROMAdj, dd 0 4814-5 + fread(&temp, 1, 4, fs); + s7r.reg4814=temp&(0x0FF); + s7r.reg4815=(temp>>8)&(0x0FF); +//NEWSYM SPCROMInc, dd 0 4816-7 + fread(&temp, 1, 4, fs); + s7r.reg4816=temp&(0x0FF); + s7r.reg4817=(temp>>8)&(0x0FF); +//NEWSYM SPCROMCom, dd 0 4818 +fread(&temp, 1, 4, fs); + + s7r.reg4818=temp&(0x0FF); +//NEWSYM SPCCompPtr, dd 0 4801-4804 (+b50i) if"manual" + fread(&temp, 1, 4, fs); + + //do table check + + s7r.reg4801=temp&(0x0FF); + s7r.reg4802=(temp>>8)&(0x0FF); + s7r.reg4803=(temp>>16)&(0x0FF); + s7r.reg4804=(temp>>24)&(0x0FF); +///NEWSYM SPCDecmPtr, dd 0 4805-6 +b50i + fread(&temp, 1, 4, fs); + s7r.reg4805=temp&(0x0FF); + s7r.reg4806=(temp>>8)&(0x0FF); +//NEWSYM SPCCompCounter, dd 0 4809-A + fread(&temp, 1, 4, fs); + s7r.reg4809=temp&(0x0FF); + s7r.reg480A=(temp>>8)&(0x0FF); +//NEWSYM SPCCompCommand, dd 0 480B +fread(&temp, 1, 4, fs); + + s7r.reg480B=temp&(0x0FF); +//NEWSYM SPCCheckFix, dd 0 written(if 1, then set writtne to max value!) +fread(&temp, 1, 4, fs); +(temp&(0x0FF))?s7r.written=0x1F:s7r.written=0x00; +//NEWSYM SPCSignedVal, dd 0 482E +fread(&temp, 1, 4, fs); + + s7r.reg482E=temp&(0x0FF); + + } + fclose (fs); + + Memory.FixROMSpeed (); + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = FALSE; + S9xFixColourBrightness (); + IPPU.RenderThisFrame = FALSE; + + S9xFixSoundAfterSnapshotLoad (1); + ICPU.ShiftedPB = Registers.PB << 16; + ICPU.ShiftedDB = Registers.DB << 16; + S9xSetPCBase (Registers.PBPC); + S9xUnpackStatus (); + S9xFixCycles (); + S9xReschedule (); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostLoadState (); +#endif + return (TRUE); + } + fclose (fs); + return (FALSE); +} + diff --git a/source/snes9x/snapshot.h b/source/snes9x/snapshot.h index 74b2dfe..05ad989 100644 --- a/source/snes9x/snapshot.h +++ b/source/snes9x/snapshot.h @@ -159,25 +159,34 @@ **********************************************************************************/ + #ifndef _SNAPSHOT_H_ #define _SNAPSHOT_H_ -#define SNAPSHOT_MAGIC "#!s9xsnp" -#define SNAPSHOT_VERSION 6 +#include +#include "snes9x.h" -#define SUCCESS 1 -#define WRONG_FORMAT (-1) -#define WRONG_VERSION (-2) -#define FILE_NOT_FOUND (-3) -#define WRONG_MOVIE_SNAPSHOT (-4) -#define NOT_A_MOVIE_SNAPSHOT (-5) -#define SNAPSHOT_INCONSISTENT (-6) +#define SNAPSHOT_MAGIC "#!snes9x" +#define SNAPSHOT_VERSION 5 -void S9xResetSaveTimer (bool8); -bool8 S9xFreezeGame (const char *); -bool8 S9xUnfreezeGame (const char *); +#define SUCCESS 1 +#define WRONG_FORMAT (-1) +#define WRONG_VERSION (-2) +#define FILE_NOT_FOUND (-3) +#define WRONG_MOVIE_SNAPSHOT (-4) +#define NOT_A_MOVIE_SNAPSHOT (-5) +#define SNAPSHOT_INCONSISTENT (-6) + +START_EXTERN_C +void S9xResetSaveTimer(bool8 dontsave); +bool8 S9xFreezeGame (const char *filename); +bool8 S9xUnfreezeGame (const char *filename); +bool8 Snapshot (const char *filename); +bool8 S9xLoadSnapshot (const char *filename); +bool8 S9xSPCDump (const char *filename); void S9xFreezeToStream (STREAM); -int S9xUnfreezeFromStream (STREAM); -bool8 S9xSPCDump (const char *); +int S9xUnfreezeFromStream (STREAM); +END_EXTERN_C #endif + diff --git a/source/snes9x/snes9x.cpp b/source/snes9x/snes9x.cpp new file mode 100644 index 0000000..440d75d --- /dev/null +++ b/source/snes9x/snes9x.cpp @@ -0,0 +1,1264 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "display.h" + +#ifndef NGC +#include "cheats.h" +#endif + +#include "controls.h" + +#ifndef NGC +#include "netplay.h" +#include "logger.h" +#endif +#include "gfx.h" + +#ifdef DEBUGGER +extern FILE *trace; +#endif + +static char *rom_filename=NULL; + +void S9xUsage () +{ + S9xMessage (S9X_INFO, S9X_USAGE, "snes9x: S9xUsage: snes9x \n"); + S9xMessage (S9X_INFO, S9X_USAGE, "Where can be:"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + /* SOUND OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-sound or -so Enable digital sound output"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nosound or -ns Disable digital sound output"); + S9xMessage(S9X_INFO, S9X_USAGE, "-soundskip or -sk <0-3> Sound CPU skip-waiting method"); +#ifdef SHOW_OBSOLETE_OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-ratio or -ra Ratio of 65c816 to SPC700 instructions (ignored)"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-soundquality, -sq, or -r Set sound playback quality"); +#ifndef __MSDOS__ + S9xMessage (S9X_INFO, S9X_USAGE, "\ + 0 - off, 1 - 8192, 2 - 11025, 3 - 16000,\n\ + 4 - 22050, 5 - 32000 (default), 6 - 44100,\n\ + 7 - 48000"); +#else + S9xMessage (S9X_INFO, S9X_USAGE, "\ + 0 - off, 1 - 8192, 2 - 11025, 3 - 16500,\n\ + 4 - 22050 (default), 5 - 29300, 6 - 36600,\n\ + 7 - 44000"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-altsampledecode or -alt Use alternate sample decoder"); + S9xMessage(S9X_INFO, S9X_USAGE, "-stereo or -st Enable stereo sound output (implies -sound)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-mono Enable monaural sound output (implies -sound)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-soundsync or -sy Enable sound sync to CPU at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-soundsync2 or -sy2 Alternate method to sync sound"); +#ifdef USE_THREADS + S9xMessage(S9X_INFO, S9X_USAGE, "-threadsound or -ts Use a separate thread to output sound"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-nois Turn off interpolated sound"); + S9xMessage(S9X_INFO, S9X_USAGE, "-echo or -e Enable DSP echo effects at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-noecho or -ne Disable DSP echo effects at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-envx or -ex Enable volume envelope height reading"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nosamplecaching, -nsc, or -nc Disable sample caching"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nomastervolume or -nmv Disable master volume setting"); + S9xMessage(S9X_INFO, S9X_USAGE, "-fix 'Fix' sound frequencies"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + /* FEATURE OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-conf Use specified conf file (after standard files)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nostdconf Do not load the standard config files"); + S9xMessage(S9X_INFO, S9X_USAGE, "-hdma or -ha Enable HDMA emulation at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nohdma or -nh Disable HDMA emulation at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-transparency or -tr Enable transparency effects"); + S9xMessage(S9X_INFO, S9X_USAGE, "-notransparency or -nt Disable transparency effects at start"); + S9xMessage(S9X_INFO, S9X_USAGE, "-windows Enable graphic window effects"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nowindows or -nw Disable graphic window effects"); +#ifdef SHOW_OBSOLETE_OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-layering or -L Enable BG Layering Hack at startup (ignored)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nolayering or -nl Disable BG Layering Hack at startup (ignored)"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-im7 Enable Mode 7 interpolation effects"); + S9xMessage(S9X_INFO, S9X_USAGE, "-displayframerate or -dfr Display the frame rate counter"); + S9xMessage(S9X_INFO, S9X_USAGE, "-aidoshm Run in AIDO mode, with specified SHM ID"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + /* DISPLAY OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-hires or -hi Enable support for hi-res and interlace modes"); +#ifdef SHOW_OBSOLETE_OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-16 or -sixteen Enable 16-bit rendering"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-frameskip or -f Screen update frame skip rate"); + S9xMessage(S9X_INFO, S9X_USAGE, "-frametime or -ft Milliseconds per frame for frameskip auto-adjust"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + /* ROM OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-hirom, -hr, or -fh Force Hi-ROM memory map"); + S9xMessage(S9X_INFO, S9X_USAGE, "-lorom, -lr, or -fl Force Lo-ROM memory map"); + S9xMessage(S9X_INFO, S9X_USAGE, "-bs Use BS Satellite System ROM mapping"); + S9xMessage(S9X_INFO, S9X_USAGE, "-bsxbootup Boot up BS games from BS-X"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nointerleave or -ni ROM image is not in interleaved format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-interleaved or -i ROM image is in interleaved format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-interleaved2 or -i2 ROM image is in interleaved 2 format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-interleavedgd24 or -gd24 ROM image is in interleaved gd24 format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-header, -he, or -hd Force the detection of a ROM image header"); + S9xMessage(S9X_INFO, S9X_USAGE, "-noheader or -nhd Force the detection of no ROM image header"); + S9xMessage(S9X_INFO, S9X_USAGE, "-ntsc or -n Force NTSC timing (60 frames/sec)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-pal or -p Force PAL timing (50 frames/sec)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-superfx or -sfx Force detection of the SuperFX chip"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nosuperfx or -nosfx Force detection of no SuperFX chip"); + S9xMessage(S9X_INFO, S9X_USAGE, "-dsp1 Force detection of the DSP-1 chip"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nodsp1 Force detection of no DSP-1 chip"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + /* Multi ROMs OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-multi Enable multi cartridge system"); + S9xMessage(S9X_INFO, S9X_USAGE, "-carta ROM in slot A. Use with -multi"); + S9xMessage(S9X_INFO, S9X_USAGE, "-cartb ROM in slot B. Use with -multi"); + + /* OPTIONS FOR DEBUGGING USE */ + S9xMessage(S9X_INFO, S9X_USAGE, "-hdmahacks or -h <1-199> Changes HDMA transfer timing"); + S9xMessage(S9X_INFO, S9X_USAGE, "-speedhacks or -sh Enable speed hacks"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nospeedhacks or -nsh Disable speed hacks"); + S9xMessage(S9X_INFO, S9X_USAGE, "-invalidvramaccess Allow invalid VRAM access"); +#ifdef DEBUGGER + S9xMessage(S9X_INFO, S9X_USAGE, "-debug or -d Set the Debugger flag at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-trace or -t Begin CPU instruction tracing at startup"); + S9xMessage(S9X_INFO, S9X_USAGE, "-noirq Disable processor IRQ (for debugging)"); + S9xMessage(S9X_INFO, S9X_USAGE, "--selftest Run self tests and exit"); +#ifdef DEBUG_MAXCOUNT + S9xMessage(S9X_INFO, S9X_USAGE, "-maxcount Only run through N cycles of the main loop"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, ""); +#endif + + /* PATCH/CHEAT OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-nopatch Do not apply any available IPS patches"); + S9xMessage(S9X_INFO, S9X_USAGE, "-cheat Apply saved cheats"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nocheat Do not apply saved cheats"); + S9xMessage(S9X_INFO, S9X_USAGE, "-gamegenie or -gg Supply a Game Genie code"); + S9xMessage(S9X_INFO, S9X_USAGE, "-actionreplay or -ar Supply a Pro-Action Reply code"); + S9xMessage(S9X_INFO, S9X_USAGE, "-goldfinger or -gf Supply a Gold Finger code"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + /* CONTROLLER OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-nomp5 Disable emulation of the Multiplayer 5 adapter"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nomouse Disable emulation of the SNES mouse"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nosuperscope Disable emulation of the Superscope"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nojustifier Disable emulation of the Konami Justifier"); + S9xMessage(S9X_INFO, S9X_USAGE, "-port# Specify which controller to emulate in port 1/2"); + S9xMessage(S9X_INFO, S9X_USAGE, " Controllers: none No controller"); + S9xMessage(S9X_INFO, S9X_USAGE, " pad# Joypad number 1-8"); + S9xMessage(S9X_INFO, S9X_USAGE, " mouse# Mouse number 1-2"); + S9xMessage(S9X_INFO, S9X_USAGE, " superscope Superscope (not useful with -port1)"); + S9xMessage(S9X_INFO, S9X_USAGE, " justifier Blue Justifier (not useful with -port1)"); + S9xMessage(S9X_INFO, S9X_USAGE, " one-justifier ditto"); + S9xMessage(S9X_INFO, S9X_USAGE, " two-justifiers Blue & Pink Justifiers"); + S9xMessage(S9X_INFO, S9X_USAGE, " mp5:#### MP5 with the 4 named pads (1-8 or n)"); + + S9xMessage(S9X_INFO, S9X_USAGE, ""); + +#ifdef NETPLAY_SUPPORT + /* NETPLAY OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-net Enable netplay"); + S9xMessage(S9X_INFO, S9X_USAGE, "-port or -po Use port for netplay"); + S9xMessage(S9X_INFO, S9X_USAGE, "-server or -srv Use the specified server for netplay"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); +#endif + +#ifdef STORM + /* "STORM" OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-nosecondjoy Set secondjoy=0"); + S9xMessage(S9X_INFO, S9X_USAGE, "-showfps Set dofps=1"); + S9xMessage(S9X_INFO, S9X_USAGE, "-hicolor Set hicolor=1"); + S9xMessage(S9X_INFO, S9X_USAGE, "-minimal Turn off "Keyboard with exception of ESC""); + S9xMessage(S9X_INFO, S9X_USAGE, "-ahiunit Set AHI Unit to "); + S9xMessage(S9X_INFO, S9X_USAGE, ""); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, " DeHackEd's commands:"); + S9xMessage(S9X_INFO, S9X_USAGE, "-dumpstreams Save audio/video data to disk"); + S9xMessage(S9X_INFO, S9X_USAGE, "-mute Don't output audio to sound card, use with above."); + S9xMessage(S9X_INFO, S9X_USAGE, "-upanddown Override protection from pressing"); + S9xMessage(S9X_INFO, S9X_USAGE, " left+right or up+down together"); + S9xMessage(S9X_INFO, S9X_USAGE, "-autodemo Start emulator playing a movie"); + S9xMessage(S9X_INFO, S9X_USAGE, "-maxframes Stop emulator after playing specified"); + S9xMessage(S9X_INFO, S9X_USAGE, " number of frames. Requires -dumpstreams"); + S9xMessage(S9X_INFO, S9X_USAGE, "-oldturbo Turbo button renders all frames, but slower"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); +#ifndef NGC + S9xExtraUsage(); +#endif + + S9xMessage (S9X_INFO, S9X_USAGE, "\ +\nROM image needs to be in Super MagiCom (*.smc), Super FamiCom (*.sfc),\n\ +*.fig, or split (*.1, *.2, or sf32527a, sf32527b, etc) format and can be\n\ +compressed with zip, gzip, JMA, or compress.\n"); + + exit (1); +} + +#ifdef STORM +extern int dofps; +extern int hicolor; +extern int secondjoy; +extern int minimal; +int prelude=0; +extern int unit; +#endif + +#ifndef NGC +static bool parse_controller_spec(int port, const char *arg){ + if(!strcasecmp(arg, "none")) { + S9xSetController(port, CTL_NONE, 0, 0, 0, 0); + } else if(!strncasecmp(arg, "pad", 3) && + arg[3]>='1' && arg[3]<='8' && + arg[4]=='\0'){ + S9xSetController(port, CTL_JOYPAD, arg[3]-'1', 0, 0, 0); + } else if(!strncasecmp(arg, "mouse", 5) && + arg[5]>='1' && arg[5]<='2' && + arg[6]=='\0'){ + S9xSetController(port, CTL_MOUSE, arg[5]-'1', 0, 0, 0); + } else if(!strcasecmp(arg, "superscope")) { + S9xSetController(port, CTL_SUPERSCOPE, 0, 0, 0, 0); + } else if(!strcasecmp(arg, "justifier") || + !strcasecmp(arg, "one-justifier")) { + S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0); + } else if(!strcasecmp(arg, "two-justifiers")) { + S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0); + } else if(!strncasecmp(arg, "mp5:", 4) && + ((arg[4]>='1' && arg[4]<='8') || arg[4]=='n') && + ((arg[5]>='1' && arg[5]<='8') || arg[5]=='n') && + ((arg[6]>='1' && arg[6]<='8') || arg[6]=='n') && + ((arg[7]>='1' && arg[7]<='8') || arg[7]=='n') && + arg[8]=='\0'){ + S9xSetController(port, CTL_MP5, + (arg[4]=='n')?-1:arg[4]-'1', + (arg[5]=='n')?-1:arg[5]-'1', + (arg[6]=='n')?-1:arg[6]-'1', + (arg[7]=='n')?-1:arg[7]-'1'); + } else { + return false; + } + return true; +} + +#endif + +char *S9xParseArgs (char **argv, int argc) +{ + +#ifndef NGC + // Nintendo Gamecube has NO COMMAND LINE ARGUMENTS -;) ***/ + for (int i = 1; i < argc; i++) + { + if (*argv[i] == '-') + { + if (strcasecmp (argv [i], "--selftest") == 0) + { + // FIXME: Probable missuse of S9X_USAGE + // FIXME: Actual tests. But at least this checks for coredumps. + S9xMessage (S9X_INFO, S9X_USAGE, "Running selftest ..."); + S9xMessage (S9X_INFO, S9X_USAGE, "snes9x started:\t[OK]"); + S9xMessage (S9X_INFO, S9X_USAGE, "All tests ok."); + exit(0); + } + if (strcasecmp (argv [i], "-so") == 0 || + strcasecmp (argv [i], "-sound") == 0) + { + Settings.NextAPUEnabled = TRUE; + } + else if (strcasecmp (argv [i], "-ns") == 0 || + strcasecmp (argv [i], "-nosound") == 0) + { + Settings.NextAPUEnabled = FALSE; + } + else if (strcasecmp (argv [i], "-soundskip") == 0 || + strcasecmp (argv [i], "-sk") == 0) + { + if (i + 1 < argc) + Settings.SoundSkipMethod = atoi (argv [++i]); + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-ra") == 0 || + strcasecmp (argv [i], "-ratio") == 0) + { + if ((i + 1) < argc) + { + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-h") == 0 || + strcasecmp (argv [i], "-hdmahacks") == 0) + { + if (i + 1 < argc) + { + int p = atoi (argv [++i]); + if (p > 0 && p < 200) + Settings.HDMATimingHack = p; + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-nh") == 0 || + strcasecmp (argv [i], "-nohdma") == 0) + { + Settings.DisableHDMA = TRUE; + } + else if (strcasecmp (argv [i], "-ha") == 0 || + strcasecmp (argv [i], "-hdma") == 0) + { + Settings.DisableHDMA = FALSE; + } + else if (strcasecmp (argv [i], "-nsh") == 0 || + strcasecmp (argv [i], "-nospeedhacks") == 0) + { + Settings.ShutdownMaster = FALSE; + } + else if (strcasecmp (argv [i], "-sh") == 0 || + strcasecmp (argv [i], "-speedhacks") == 0) + { + Settings.ShutdownMaster = TRUE; + } + else if (strcasecmp (argv [i], "-invalidvramaccess") == 0) + { + Settings.BlockInvalidVRAMAccess = FALSE; + } + else if (strcasecmp (argv [i], "-p") == 0 || + strcasecmp (argv [i], "-pal") == 0) + { + Settings.ForcePAL = TRUE; + } + else if (strcasecmp (argv [i], "-n") == 0 || + strcasecmp (argv [i], "-ntsc") == 0) + { + Settings.ForceNTSC = TRUE; + } + else if (strcasecmp (argv [i], "-f") == 0 || + strcasecmp (argv [i], "-frameskip") == 0) + { + if (i + 1 < argc) + Settings.SkipFrames = atoi (argv [++i]) + 1; + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-fh") == 0 || + strcasecmp (argv [i], "-hr") == 0 || + strcasecmp (argv [i], "-hirom") == 0) + Settings.ForceHiROM = TRUE; + else if (strcasecmp (argv [i], "-fl") == 0 || + strcasecmp (argv [i], "-lr") == 0 || + strcasecmp (argv [i], "-lorom") == 0) + Settings.ForceLoROM = TRUE; + else if (strcasecmp (argv [i], "-hd") == 0 || + strcasecmp (argv [i], "-header") == 0 || + strcasecmp (argv [i], "-he") == 0) + { + Settings.ForceHeader = TRUE; + } + else if (strcasecmp (argv [i], "-nhd") == 0 || + strcasecmp (argv [i], "-noheader") == 0) + { + Settings.ForceNoHeader = TRUE; + } + else if (strcasecmp (argv [i], "-bs") == 0) + { + Settings.BS = TRUE; + } + else if (strcasecmp (argv [i], "-bsxbootup") == 0) + { + Settings.BSXBootup = TRUE; + } +#ifdef DEBUGGER + else if (strcasecmp (argv [i], "-d") == 0 || + strcasecmp (argv [i], "-debug") == 0) + { + CPU.Flags |= DEBUG_MODE_FLAG; + } + else if (strcasecmp (argv [i], "-t") == 0 || + strcasecmp (argv [i], "-trace") == 0) + { + if(!trace) trace = fopen ("trace.log", "wb"); + CPU.Flags |= TRACE_FLAG; + } +#endif + else if (strcasecmp (argv [i], "-L") == 0 || + strcasecmp (argv [i], "-layering") == 0) + Settings.BGLayering = TRUE; + else if (strcasecmp (argv [i], "-nl") == 0 || + strcasecmp (argv [i], "-nolayering") == 0) + Settings.BGLayering = FALSE; + else if (strcasecmp (argv [i], "-tr") == 0 || + strcasecmp (argv [i], "-transparency") == 0) + { + Settings.ForceTransparency = TRUE; + Settings.ForceNoTransparency = FALSE; + } + else if (strcasecmp (argv [i], "-nt") == 0 || + strcasecmp (argv [i], "-notransparency") == 0) + { + Settings.ForceNoTransparency = TRUE; + Settings.ForceTransparency = FALSE; + } + else if (strcasecmp (argv [i], "-hi") == 0 || + strcasecmp (argv [i], "-hires") == 0) + { + Settings.SupportHiRes = TRUE; + } + else if (strcasecmp (argv [i], "-16") == 0 || + strcasecmp (argv [i], "-sixteen") == 0) + { + } + else if (strcasecmp (argv [i], "-displayframerate") == 0 || + strcasecmp (argv [i], "-dfr") == 0) + { + Settings.DisplayFrameRate = TRUE; + } + else if (strcasecmp (argv [i], "-nomessagesinimage") == 0) + Settings.AutoDisplayMessages = FALSE; + else if (strcasecmp (argv [i], "-i") == 0 || + strcasecmp (argv [i], "-interleaved") == 0) + Settings.ForceInterleaved = TRUE; + else if (strcasecmp (argv [i], "-i2") == 0 || + strcasecmp (argv [i], "-interleaved2") == 0) + Settings.ForceInterleaved2=TRUE; + else if (strcasecmp (argv [i], "-gd24") == 0 || + strcasecmp (argv [i], "-interleavedgd24") == 0) + Settings.ForceInterleaveGD24 = TRUE; + else if (strcasecmp (argv [i], "-ni") == 0 || + strcasecmp (argv [i], "-nointerleave") == 0) + Settings.ForceNotInterleaved = TRUE; + else if (strcasecmp (argv [i], "-noirq") == 0) + Settings.DisableIRQ = TRUE; + else if (strcasecmp (argv [i], "-nw") == 0 || + strcasecmp (argv [i], "-nowindows") == 0) + { + Settings.DisableGraphicWindows = TRUE; + } + else if (strcasecmp (argv [i], "-nopatch") == 0) + { + Settings.NoPatch=TRUE; + } + else if (strcasecmp (argv [i], "-nocheat") == 0) + { + Settings.ApplyCheats=FALSE; + } + else if (strcasecmp (argv [i], "-cheat") == 0) + { + Settings.ApplyCheats=TRUE; + } + else if (strcasecmp (argv [i], "-windows") == 0) + { + Settings.DisableGraphicWindows = FALSE; + } + else if (strcasecmp (argv [i], "-aidoshm") == 0) + { + if (i + 1 < argc) + { + Settings.AIDOShmId = atoi (argv [++i]); + fprintf(stderr, "Snes9X running in AIDO mode. shmid: %d\n", + Settings.AIDOShmId); + } else + S9xUsage (); + } +#ifdef DEBUG_MAXCOUNT + else if (strcasecmp (argv [i], "-maxcount") == 0) + { + if (i + 1 < argc) + { + Settings.MaxCount = atol (argv [++i]); + fprintf(stderr, "Running for a maximum of %d loops.\n", + Settings.MaxCount); + } else + S9xUsage (); + } +#endif + else if (strcasecmp (argv [i], "-im7") == 0) + { + Settings.Mode7Interpolate = TRUE; + } + else if (strcasecmp (argv [i], "-gg") == 0 || + strcasecmp (argv [i], "-gamegenie") == 0) + { + if (i + 1 < argc) + { + uint32 address; + uint8 byte; + const char *error; + if ((error = S9xGameGenieToRaw (argv [++i], address, byte)) == NULL) + S9xAddCheat (TRUE, FALSE, address, byte); + else + S9xMessage (S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, + error); + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-ar") == 0 || + strcasecmp (argv [i], "-actionreplay") == 0) + { + if (i + 1 < argc) + { + uint32 address; + uint8 byte; + const char *error; + if ((error = S9xProActionReplayToRaw (argv [++i], address, byte)) == NULL) + S9xAddCheat (TRUE, FALSE, address, byte); + else + S9xMessage (S9X_ERROR, S9X_ACTION_REPLY_CODE_ERROR, + error); + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-gf") == 0 || + strcasecmp (argv [i], "-goldfinger") == 0) + { + if (i + 1 < argc) + { + uint32 address; + uint8 bytes [3]; + bool8 sram; + uint8 num_bytes; + const char *error; + if ((error = S9xGoldFingerToRaw (argv [++i], address, sram, + num_bytes, bytes)) == NULL) + { + for (int c = 0; c < num_bytes; c++) + S9xAddCheat (TRUE, FALSE, address + c, bytes [c]); + } + else + S9xMessage (S9X_ERROR, S9X_GOLD_FINGER_CODE_ERROR, + error); + } + else + S9xUsage (); + } + else if (strcasecmp (argv[i], "-ft") == 0 || + strcasecmp (argv [i], "-frametime") == 0) + { + if (i + 1 < argc) + { + double ft; + if (sscanf (argv [++i], "%lf", &ft) == 1) + { + Settings.FrameTimePAL = (int32) ft; + Settings.FrameTimeNTSC = (int32) ft; + } + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-e") == 0 || + strcasecmp (argv [i], "-echo") == 0) + Settings.DisableSoundEcho = FALSE; + else if (strcasecmp (argv [i], "-ne") == 0 || + strcasecmp (argv [i], "-noecho") == 0) + Settings.DisableSoundEcho = TRUE; + else if (strcasecmp (argv [i], "-r") == 0 || + strcasecmp (argv [i], "-soundquality") == 0 || + strcasecmp (argv [i], "-sq") == 0) + { + if (i + 1 < argc) + Settings.SoundPlaybackRate = atoi (argv [++i]) & 7; + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-stereo") == 0 || + strcasecmp (argv [i], "-st") == 0) + { + Settings.Stereo = TRUE; + Settings.APUEnabled = TRUE; + Settings.NextAPUEnabled = TRUE; + } + else if (strcasecmp (argv [i], "-mono") == 0) + { + Settings.Stereo = FALSE; + Settings.NextAPUEnabled = TRUE; + } + else if (strcasecmp (argv [i], "-envx") == 0 || + strcasecmp (argv [i], "-ex") == 0) + { + Settings.SoundEnvelopeHeightReading = TRUE; + } + else if (strcasecmp (argv [i], "-nosamplecaching") == 0 || + strcasecmp (argv [i], "-nsc") == 0 || + strcasecmp (argv [i], "-nc") == 0) + { + Settings.DisableSampleCaching = TRUE; + } + else if (strcasecmp (argv [i], "-nomastervolume") == 0 || + strcasecmp (argv [i], "-nmv") == 0) + { + Settings.DisableMasterVolume = TRUE; + } + else if (strcasecmp (argv [i], "-soundsync") == 0 || + strcasecmp (argv [i], "-sy") == 0) + { + Settings.SoundSync = TRUE; + Settings.SoundEnvelopeHeightReading = TRUE; + Settings.InterpolatedSound = TRUE; + } + else if (strcasecmp (argv [i], "-soundsync2") == 0 || + strcasecmp (argv [i], "-sy2") == 0) + { + Settings.SoundSync = 2; + Settings.SoundEnvelopeHeightReading = TRUE; + Settings.InterpolatedSound = TRUE; + } + else if (strcasecmp (argv [i], "-nois") == 0) + { + Settings.InterpolatedSound = FALSE; + } +#ifdef USE_THREADS + else if (strcasecmp (argv [i], "-threadsound") == 0 || + strcasecmp (argv [i], "-ts") == 0) + { + Settings.ThreadSound = TRUE; + } +#endif + else if (strcasecmp (argv [i], "-alt") == 0 || + strcasecmp (argv [i], "-altsampledecode") == 0) + { + Settings.AltSampleDecode = 1; + } + else if (strcasecmp (argv [i], "-fix") == 0) + { + Settings.FixFrequency = 1; + } + else if (strcasecmp (argv [i], "-nosuperfx") == 0 || + strcasecmp (argv [i], "-nosfx") == 0) + Settings.ForceNoSuperFX = TRUE; + else if (strcasecmp (argv [i], "-superfx") == 0 || + strcasecmp (argv [i], "-sfx") == 0) + Settings.ForceSuperFX = TRUE; + else if (strcasecmp (argv [i], "-dsp1") == 0) + Settings.ForceDSP1 = TRUE; + else if (strcasecmp (argv [i], "-nodsp1") == 0) + Settings.ForceNoDSP1 = TRUE; + else if (strcasecmp (argv [i], "-nomp5") == 0) + Settings.MultiPlayer5Master = FALSE; + else if (strcasecmp (argv [i], "-nomouse") == 0) + Settings.MouseMaster = FALSE; + else if (strcasecmp (argv [i], "-nosuperscope") == 0) + Settings.SuperScopeMaster = FALSE; + else if (strcasecmp (argv [i], "-nojustifier") == 0) + Settings.JustifierMaster = FALSE; + else if (strcasecmp (argv[i], "-port1") == 0 || + strcasecmp (argv[i], "-port2") == 0) + { + if (i + 1 < argc) + { + i++; + if(!parse_controller_spec(argv[i-1][5]-'1', argv[i])) + S9xUsage (); + } + else + S9xUsage (); + } +#ifdef NETPLAY_SUPPORT + else if (strcasecmp (argv [i], "-port") == 0 || + strcasecmp (argv [i], "-po") == 0) + { + if (i + 1 < argc) + { + Settings.NetPlay = TRUE; + Settings.Port = -atoi (argv [++i]); + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-server") == 0 || + strcasecmp (argv [i], "-srv") == 0) + { + if (i + 1 < argc) + { + Settings.NetPlay = TRUE; + strncpy (Settings.ServerName, argv [++i], 127); + Settings.ServerName [127] = 0; + } + else + S9xUsage (); + } + else if (strcasecmp (argv [i], "-net") == 0) + { + Settings.NetPlay = TRUE; + } +#endif +#ifdef STORM + else if (strcasecmp(argv[i],"-nosecondjoy")==0){secondjoy=0;} + else if (strcasecmp(argv[i],"-showfps")==0){dofps=1;} + else if (strcasecmp(argv[i],"-hicolor")==0){hicolor=1;} + else if (strcasecmp(argv[i],"-minimal")==0){minimal=1;printf("Keyboard with exception of ESC switched off!\n");} + else if (strcasecmp(argv[i],"-ahiunit")==0) + { + if (i+1=argc) S9xUsage(); + // Else do nothing, S9xLoadConfigFiles() handled it + } + else if (strcasecmp (argv [i], "-nostdconf") == 0) + { + // Do nothing, S9xLoadConfigFiles() handled it + } + else if (strcasecmp (argv [i], "-version") == 0) + { + printf("Snes9X " VERSION "\n"); + exit(0); + } + else if (strcasecmp (argv [i], "-help") == 0) + { + S9xUsage(); + } + else if (strcasecmp (argv [i], "-multi") == 0) + { + Settings.Multi = TRUE; + } + else if (strcasecmp (argv [i], "-carta") == 0) + { + if (i + 1 < argc) + { + strncpy (Settings.CartAName, argv [++i], _MAX_PATH); + } + } + else if (strcasecmp (argv [i], "-cartb") == 0) + { + if (i + 1 < argc) + { + strncpy (Settings.CartBName, argv [++i], _MAX_PATH); + } + } + + else + S9xParseArg (argv, i, argc); + } + else + rom_filename = argv [i]; + } + + S9xVerifyControllers(); + +#endif + + return (rom_filename); +} + +#ifndef NGC +void S9xParseCheatsFile (const char *rom_filename) +{ + FILE *f; + char dir [_MAX_DIR]; + char drive [_MAX_DRIVE]; + char name [_MAX_FNAME]; + char ext [_MAX_EXT]; + char fname [_MAX_PATH]; + char buf [80]; + uint32 address; + uint8 byte; + uint8 bytes [3]; + bool8 sram; + uint8 num_bytes; + const char *error; + char *p; + + _splitpath (rom_filename, drive, dir, name, ext); + _makepath (fname, drive, dir, name, "pat"); + + if ((f = fopen(fname, "r")) != NULL) + { + while(fgets(buf, 80, f) != NULL) + { + if ((p = strrchr (buf, '\n')) != NULL) + *p = '\0'; + if (((error = S9xGameGenieToRaw (buf, address, byte)) == NULL) || + ((error = S9xProActionReplayToRaw (buf, address, byte)) == NULL)) + { + S9xAddCheat (TRUE, FALSE, address, byte); + } + else + if ((error = S9xGoldFingerToRaw (buf, address, sram, + num_bytes, bytes)) == NULL) + { + for (int c = 0; c < num_bytes; c++) + S9xAddCheat (TRUE, FALSE, address + c, bytes [c]); + } + else + S9xMessage (S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, error); + } + fclose(f); + } +} + +#endif + +#ifndef NGC +#include "conffile.h" +#include "crosshairs.h" + +static void parse_crosshair_spec(enum crosscontrols ctl, const char *spec){ + int idx=-1, i; + const char *fg=NULL, *bg=NULL, *s=spec; + + if(s[0]=='"'){ + s++; + for(i=0; s[i]!='\0'; i++){ + if(s[i]=='"' && s[i-1]!='\\') break; + } + idx=31-ctl; + std::string fname(s, i); + if(!S9xLoadCrosshairFile(idx, fname.c_str())) return; + s+=i+1; + } else { + if(isdigit(*s)){ idx=*s-'0'; s++; } + if(isdigit(*s)){ idx=idx*10+*s-'0'; s++; } + if(idx>31){ + fprintf(stderr, "Invalid crosshair spec '%s'\n", spec); + return; + } + } + + while(*s!='\0' && isspace(*s)){ s++; } + if(*s!='\0'){ + fg=s; + while(isalnum(*s)){ s++; } + if(*s!='/' || !isalnum(s[1])){ + fprintf(stderr, "Invalid crosshair spec '%s'\n", spec); + return; + } + bg=++s; + while(isalnum(*s)){ s++; } + if(*s!='\0'){ + fprintf(stderr, "Invalid crosshair spec '%s'\n", spec); + return; + } + } + + S9xSetControllerCrosshair(ctl, idx, fg, bg); +} + +static bool try_load(const char *fname, ConfigFile &conf){ + STREAM fp; + if((fp=OPEN_STREAM(fname, "r"))!=NULL){ + fprintf(stdout, "Reading config file %s\n", fname); + conf.LoadFile(new fReader(fp)); + CLOSE_STREAM(fp); + return true; + } + return false; +} + +void S9xLoadConfigFiles(char **argv, int argc){ + int i; + bool skip=false; + + for(i=0; i0 && i<200) Settings.HDMATimingHack = i; + Settings.DisableHDMA=conf.GetBool("Settings::DisableHDMA", false); + Settings.ShutdownMaster=conf.GetBool("Settings::SpeedHacks", false); + Settings.BlockInvalidVRAMAccess=conf.GetBool("Settings::BlockInvalidVRAMAccess", true); + Settings.ForcePAL=conf.GetBool("ROM::PAL", false); + Settings.ForceNTSC=conf.GetBool("ROM::NTSC", false); + if(!strcasecmp(conf.GetString("Settings::FrameSkip", "Auto"),"Auto")){ + Settings.SkipFrames=AUTO_FRAMERATE; + } else { + Settings.SkipFrames=conf.GetUInt("Settings::FrameSkip", 0)+1; + } + Settings.TurboSkipFrames=conf.GetUInt("Settings::TurboFrameSkip", 15); + Settings.TurboMode=conf.GetBool("Settings::TurboMode",false); + Settings.StretchScreenshots=conf.GetInt("Settings::StretchScreenshots",1); + Settings.InitialInfoStringTimeout=conf.GetInt("Settings::MessageDisplayTime",120); + Settings.AutoSaveDelay=conf.GetUInt("Settings::AutoSaveDelay", 30); + Settings.ForceHiROM=conf.GetBool("ROM::HiROM", false); + Settings.ForceLoROM=conf.GetBool("ROM::LoROM", false); + if(conf.Exists("ROM::Header")){ + Settings.ForceHeader=conf.GetBool("ROM::Header"); + Settings.ForceNoHeader=!Settings.ForceHeader; + } + Settings.BS=conf.GetBool("ROM::BS", false); +#ifdef DEBUGGER + if(conf.GetBool("DEBUG::Debugger", false)) CPU.Flags |= DEBUG_MODE_FLAG; + if(conf.GetBool("DEBUG::Trace", false)){ + if(!trace) trace = fopen ("trace.log", "wb"); + CPU.Flags |= TRACE_FLAG; + } +#endif + Settings.BGLayering=conf.GetBool("Settings::BGLayeringHack", false); + if(conf.Exists("Display::Transparency")){ + Settings.ForceTransparency=conf.GetBool("Display::Transparency", true); + Settings.ForceNoTransparency=!Settings.ForceTransparency; + } + Settings.SupportHiRes=conf.GetBool("Display::HiRes", true); + Settings.DisplayFrameRate=conf.GetBool("Display::FrameRate", false); + if(conf.Exists("Display::DisplayInput")) + Settings.DisplayPressedKeys=conf.GetBool("Display::DisplayInput", false)?1:0; +// GFX.FrameDisplay=conf.GetBool("Display::DisplayFrameCount", false); + GFX.FrameDisplay=TRUE; + Settings.AutoDisplayMessages=conf.GetBool("Display::MessagesInImage", true); + if(conf.Exists("ROM::Interleaved")){ + Settings.ForceInterleaved=conf.GetBool("ROM::Interleaved", false); + Settings.ForceNotInterleaved=!Settings.ForceInterleaved; + } + Settings.ForceInterleaved2=conf.GetBool("ROM::Interleaved2", false); + Settings.ForceInterleaveGD24=conf.GetBool("ROM::InterleaveGD24", false); + Settings.DisableIRQ=conf.GetBool("CPU::DisableIRQ", false); + Settings.DisableGraphicWindows=!conf.GetBool("Display::GraphicWindows", true); + Settings.NoPatch=!conf.GetBool("ROM::Patch", true); + Settings.ApplyCheats=conf.GetBool("ROM::Cheat", true); +#ifdef DEBUG_MAXCOUNT + if(conf.Exists("DEBUG::MaxCount")){ + Settings.MaxCount = conf.GetUInt("DEBUG::MaxCount", 1); + fprintf(stderr, "Running for a maximum of %d loops.\n", Settings.MaxCount); + } +#endif + Settings.Mode7Interpolate=conf.GetBool("Display::Mode7Interpolate", false); + Settings.FrameTimePAL=conf.GetUInt("Settings::PALFrameTime", 20000); + Settings.FrameTimeNTSC=conf.GetUInt("Settings::NTSCFrameTime", 16667); + if(conf.Exists("Settings::FrameTime")){ + double ft; + if (sscanf(conf.GetString("Settings::FrameTime"), "%lf", &ft) == 1) + { + Settings.FrameTimePAL = (int32) ft; + Settings.FrameTimeNTSC = (int32) ft; + } + } + Settings.FrameTime = Settings.FrameTimeNTSC; + Settings.DisableSoundEcho=!conf.GetBool("Sound::Echo", true); + Settings.SoundPlaybackRate=conf.GetUInt("Sound::Rate", Settings.SoundPlaybackRate) & 7; + Settings.SoundBufferSize=conf.GetUInt("Sound::BufferSize", Settings.SoundBufferSize); + if(conf.Exists("Sound::Stereo")){ + Settings.Stereo = conf.GetBool("Sound::Stereo"); + Settings.APUEnabled = TRUE; + Settings.NextAPUEnabled = TRUE; + } + if(conf.Exists("Sound::Mono")){ + Settings.Stereo = !conf.GetBool("Sound::Mono"); + Settings.NextAPUEnabled = TRUE; + } + Settings.SoundEnvelopeHeightReading=conf.GetBool("Sound::EnvelopeHeightReading"); + Settings.DisableSampleCaching=!conf.GetBool("Sound::SampleCaching"); + Settings.DisableMasterVolume=!conf.GetBool("Sound::MasterVolume"); + Settings.InterpolatedSound=conf.GetBool("Sound::Interpolate", true); + if(conf.Exists("Sound::Sync")){ + Settings.SoundSync=conf.GetInt("Sound::Sync", 1); + if(Settings.SoundSync>2) Settings.SoundSync=1; + Settings.SoundEnvelopeHeightReading = TRUE; + Settings.InterpolatedSound = TRUE; + } +#ifdef USE_THREADS + Settings.ThreadSound=conf.GetBool("Sound::ThreadSound", false); +#endif + if(conf.Exists("Sound::AltDecode")){ + Settings.AltSampleDecode=conf.GetInt("Sound::AltDecode", 1); + } + if(conf.Exists("Sound::FixFrequency")){ + Settings.FixFrequency=conf.GetInt("Sound::FixFrequency", 1); + } + if(conf.Exists("ROM::SuperFX")){ + Settings.ForceSuperFX=conf.GetBool("ROM::SuperFX"); + Settings.ForceNoSuperFX=!Settings.ForceSuperFX; + } + if(conf.Exists("ROM::DSP1")){ + Settings.ForceDSP1=conf.GetBool("ROM::DSP1"); + Settings.ForceNoDSP1=!Settings.ForceDSP1; + } + Settings.MultiPlayer5Master=conf.GetBool("Controls::MP5Master", true); + Settings.MouseMaster=conf.GetBool("Controls::MouseMaster", true); + Settings.SuperScopeMaster=conf.GetBool("Controls::SuperscopeMaster", true); + Settings.JustifierMaster=conf.GetBool("Controls::JustifierMaster", true); + if(conf.Exists("Controls::Port1")){ + parse_controller_spec(0, conf.GetString("Controls::Port1")); + } + if(conf.Exists("Controls::Port2")){ + parse_controller_spec(1, conf.GetString("Controls::Port2")); + } + if(conf.Exists("Controls::Mouse1Crosshair")){ + parse_crosshair_spec(X_MOUSE1, conf.GetString("Controls::Mouse1Crosshair")); + } + if(conf.Exists("Controls::Mouse2Crosshair")){ + parse_crosshair_spec(X_MOUSE2, conf.GetString("Controls::Mouse2Crosshair")); + } + if(conf.Exists("Controls::SuperscopeCrosshair")){ + parse_crosshair_spec(X_SUPERSCOPE, conf.GetString("Controls::SuperscopeCrosshair")); + } + if(conf.Exists("Controls::Justifier1Crosshair")){ + parse_crosshair_spec(X_JUSTIFIER1, conf.GetString("Controls::Justifier1Crosshair")); + } + if(conf.Exists("Controls::Justifier2Crosshair")){ + parse_crosshair_spec(X_JUSTIFIER2, conf.GetString("Controls::Justifier2Crosshair")); + } +#ifdef NETPLAY_SUPPORT + Settings.Port = NP_DEFAULT_PORT; + if(conf.Exists("Netplay::Port")){ + Settings.NetPlay = TRUE; + Settings.Port = -(int)conf.GetUInt("Netplay::Port"); + } + Settings.ServerName[0]='\0'; + if(conf.Exists("Netplay::Server")){ + Settings.NetPlay = TRUE; + conf.GetString("Netplay::Server", Settings.ServerName, 128); + } + Settings.NetPlay=conf.GetBool("Netplay::Enable"); +#endif +#ifdef STORM + secondjoy=conf.GetBool("STORM::EnableSecondJoy",true)?1:0; + dofps=conf.GetBool("STORM::ShowFPS",false)?1:0; + hicolor=conf.GetBool("STORM::HiColor",false)?1:0; + if((minimal=conf.GetBool("STORM::Minimal")?1:0)){ + printf("Keyboard with exception of ESC switched off!\n"); + } + if(conf.Exists("STORM::AHIunit")){ + unit=conf.GetInt("STORM::AHIunit",0); + fprintf(stderr,"AHI Unit set to: Unit %i\n",unit); + } +#endif + Settings.JoystickEnabled=conf.GetBool("Controls::Joystick", Settings.JoystickEnabled); + Settings.UpAndDown=conf.GetBool("Controls::AllowLeftRight", false); + Settings.SnapshotScreenshots=conf.GetBool("Settings::SnapshotScreenshots", true); + Settings.MovieTruncate=conf.GetBool("Settings::MovieTruncateAtEnd", false); + Settings.MovieNotifyIgnored=conf.GetBool("Settings::MovieNotifyIgnored", false); + Settings.DisplayWatchedAddresses=conf.GetBool("Settings::DisplayWatchedAddresses", false); + Settings.WrongMovieStateProtection=conf.GetBool("Settings::WrongMovieStateProtection", true); + rom_filename=conf.GetStringDup("ROM::Filename", NULL); + + S9xParsePortConfig(conf, 1); + S9xVerifyControllers(); +} + +#endif /*** Nintendo Gamecube Exclusion ***/ diff --git a/source/snes9x/snes9x.h b/source/snes9x/snes9x.h index c34195f..18d3e0e 100644 --- a/source/snes9x/snes9x.h +++ b/source/snes9x/snes9x.h @@ -159,42 +159,62 @@ **********************************************************************************/ + #ifndef _SNES9X_H_ #define _SNES9X_H_ -#ifndef VERSION -#define VERSION "1.52" +#define VERSION "1.51" + +#include +#include + +#ifdef __WIN32__ +#include +#ifdef ZLIB +#include #endif +#endif + +//#include "language.h" // files should include this as needed, no need to recompile practically everything when it changes #include "port.h" #include "65c816.h" #include "messages.h" -#ifdef ZLIB -#include -#define STREAM gzFile -#define READ_STREAM(p, l, s) gzread(s, p, l) -#define WRITE_STREAM(p, l, s) gzwrite(s, p, l) -#define GETS_STREAM(p, l, s) gzgets(s, p, l) -#define GETC_STREAM(s) gzgetc(s) -#define OPEN_STREAM(f, m) gzopen(f, m) -#define REOPEN_STREAM(f, m) gzdopen(f, m) -#define FIND_STREAM(f) gztell(f) -#define REVERT_STREAM(f, o, s) gzseek(f, o, s) -#define CLOSE_STREAM(s) gzclose(s) -#else -#define STREAM FILE * -#define READ_STREAM(p, l, s) fread(p, 1, l, s) -#define WRITE_STREAM(p, l, s) fwrite(p, 1, l, s) -#define GETS_STREAM(p, l, s) fgets(p, l, s) -#define GETC_STREAM(s) fgetc(s) -#define OPEN_STREAM(f, m) fopen(f, m) -#define REOPEN_STREAM(f, m) fdopen(f, m) -#define FIND_STREAM(f) ftell(f) -#define REVERT_STREAM(f, o, s) fseek(f, o, s) -#define CLOSE_STREAM(s) fclose(s) +#if defined(USE_GLIDE) && !defined(GFX_MULTI_FORMAT) +#define GFX_MULTI_FORMAT #endif +#define ROM_NAME_LEN 23 + +#ifdef ZLIB +#ifndef __WIN32__ +#include +#endif +#define STREAM gzFile +#define READ_STREAM(p,l,s) gzread (s,p,l) +#define WRITE_STREAM(p,l,s) gzwrite (s,p,l) +#define GETS_STREAM(p,l,s) gzgets(s,p,l) +#define GETC_STREAM(s) gzgetc(s) +#define OPEN_STREAM(f,m) gzopen (f,m) +#define REOPEN_STREAM(f,m) gzdopen (f,m) +#define FIND_STREAM(f) gztell(f) +#define REVERT_STREAM(f,o,s) gzseek(f,o,s) +#define CLOSE_STREAM(s) gzclose (s) +#else +#define STREAM FILE * +#define READ_STREAM(p,l,s) fread (p,1,l,s) +#define WRITE_STREAM(p,l,s) fwrite (p,1,l,s) +#define GETS_STREAM(p,l,s) fgets(p,l,s) +#define GETC_STREAM(s) fgetc(s) +#define OPEN_STREAM(f,m) fopen (f,m) +#define REOPEN_STREAM(f,m) fdopen (f,m) +#define FIND_STREAM(f) ftell(f) +#define REVERT_STREAM(f,o,s) fseek(f,o,s) +#define CLOSE_STREAM(s) fclose (s) +#endif + + #define SNES_WIDTH 256 #define SNES_HEIGHT 224 #define SNES_HEIGHT_EXTENDED 239 @@ -228,62 +248,88 @@ #define SNES_HDMA_INIT_HC 20 // FIXME: not true #define SNES_RENDER_START_HC (48 * ONE_DOT_CYCLE) // FIXME: Snes9x renders a line at a time. -#define SNES_TR_MASK (1 << 4) -#define SNES_TL_MASK (1 << 5) -#define SNES_X_MASK (1 << 6) -#define SNES_A_MASK (1 << 7) -#define SNES_RIGHT_MASK (1 << 8) -#define SNES_LEFT_MASK (1 << 9) -#define SNES_DOWN_MASK (1 << 10) -#define SNES_UP_MASK (1 << 11) -#define SNES_START_MASK (1 << 12) -#define SNES_SELECT_MASK (1 << 13) +#define SNES_APU_CLOCK 1024000.0 // 1026900.0? +#define SNES_APU_ACCURACY 10 +#define SNES_APU_ONE_CYCLE_SCALED ((int32) (NTSC_MASTER_CLOCK / SNES_APU_CLOCK * (1 << SNES_APU_ACCURACY))) +#define SNES_APUTIMER2_CYCLE_SCALED ((int32) (NTSC_MASTER_CLOCK / 64000.0 * (1 << SNES_APU_ACCURACY))) + + +#define AUTO_FRAMERATE 200 + +#define SNES_TR_MASK (1 << 4) +#define SNES_TL_MASK (1 << 5) +#define SNES_X_MASK (1 << 6) +#define SNES_A_MASK (1 << 7) +#define SNES_RIGHT_MASK (1 << 8) +#define SNES_LEFT_MASK (1 << 9) +#define SNES_DOWN_MASK (1 << 10) +#define SNES_UP_MASK (1 << 11) +#define SNES_START_MASK (1 << 12) +#define SNES_SELECT_MASK (1 << 13) #define SNES_Y_MASK (1 << 14) #define SNES_B_MASK (1 << 15) -#define DEBUG_MODE_FLAG (1 << 0) // debugger -#define TRACE_FLAG (1 << 1) // debugger -#define SINGLE_STEP_FLAG (1 << 2) // debugger -#define BREAK_FLAG (1 << 3) // debugger -#define NMI_FLAG (1 << 7) // CPU -#define IRQ_FLAG (1 << 11) // CPU -#define SCAN_KEYS_FLAG (1 << 4) // CPU -#define HALTED_FLAG (1 << 12) // APU -#define FRAME_ADVANCE_FLAG (1 << 9) +#define DEBUG_MODE_FLAG (1 << 0) +#define TRACE_FLAG (1 << 1) +#define SINGLE_STEP_FLAG (1 << 2) +#define BREAK_FLAG (1 << 3) +#define SCAN_KEYS_FLAG (1 << 4) +#define SAVE_SNAPSHOT_FLAG (1 << 5) +#define DELAYED_NMI_FLAG (1 << 6) +#define NMI_FLAG (1 << 7) +#define PROCESS_SOUND_FLAG (1 << 8) +#define FRAME_ADVANCE_FLAG (1 << 9) +#define DELAYED_NMI_FLAG2 (1 << 10) +#define IRQ_FLAG (1 << 11) +#define HALTED_FLAG (1 << 12) -#define ROM_NAME_LEN 23 -#define AUTO_FRAMERATE 200 - -struct SCPUState -{ - int32 Cycles; - int32 PrevCycles; - int32 V_Counter; +struct SCPUState{ uint32 Flags; - uint8 *PCBase; + bool8 BranchSkip; + bool8 NMIActive; bool8 IRQActive; - int32 IRQPending; + bool8 WaitingForInterrupt; + bool8 InDMAorHDMA; + bool8 InWRAMDMAorHDMA; + uint8 WhichEvent; + uint8 *PCBase; + uint32 PBPCAtOpcodeStart; + uint32 WaitAddress; + uint32 WaitCounter; + int32 Cycles; + int32 NextEvent; + int32 V_Counter; int32 MemSpeed; int32 MemSpeedx2; int32 FastROMSpeed; - bool8 InDMA; - bool8 InHDMA; - bool8 InDMAorHDMA; - bool8 InWRAMDMAorHDMA; - uint8 HDMARanInDMA; - int32 CurrentDMAorHDMAChannel; - uint8 WhichEvent; - int32 NextEvent; - bool8 WaitingForInterrupt; - uint32 WaitAddress; - uint32 WaitCounter; - uint32 PBPCAtOpcodeStart; uint32 AutoSaveTimer; bool8 SRAMModified; + bool8 BRKTriggered; + bool8 TriedInterleavedMode2; + int32 IRQPending; + bool8 InDMA; + bool8 InHDMA; + uint8 HDMARanInDMA; + int32 PrevCycles; }; -enum -{ +struct STimings { + int32 H_Max_Master; + int32 H_Max; + int32 V_Max_Master; + int32 V_Max; + int32 HBlankStart; + int32 HBlankEnd; + int32 HDMAInit; + int32 HDMAStart; + int32 NMITriggerPos; + int32 WRAMRefreshPos; + int32 RenderPos; + bool8 InterlaceField; + int32 DMACPUSync; +}; + +enum { HC_HBLANK_START_EVENT = 1, HC_IRQ_1_3_EVENT = 2, HC_HDMA_START_EVENT = 3, @@ -298,164 +344,187 @@ enum HC_IRQ_A_1_EVENT = 12 }; -struct STimings -{ - int32 H_Max_Master; - int32 H_Max; - int32 V_Max_Master; - int32 V_Max; - int32 HBlankStart; - int32 HBlankEnd; - int32 HDMAInit; - int32 HDMAStart; - int32 NMITriggerPos; - int32 WRAMRefreshPos; - int32 RenderPos; - bool8 InterlaceField; - int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly. - int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly. - int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode. - int32 APUSpeedup; -}; +struct SSettings{ + /* CPU options */ + bool8 APUEnabled; + bool8 Shutdown; + uint8 SoundSkipMethod; + int32 HDMATimingHack; + bool8 DisableIRQ; + bool8 Paused; + bool8 ForcedPause; + bool8 StopEmulation; + bool8 FrameAdvance; -struct SSettings -{ - bool8 TraceDMA; - bool8 TraceHDMA; - bool8 TraceVRAM; - bool8 TraceUnknownRegisters; - bool8 TraceDSP; - bool8 TraceHCEvent; + /* Tracing options */ + bool8 TraceDMA; + bool8 TraceHDMA; + bool8 TraceVRAM; + bool8 TraceUnknownRegisters; + bool8 TraceDSP; - bool8 SuperFX; - uint8 DSP; - bool8 SA1; - bool8 C4; - bool8 SDD1; - bool8 SPC7110; - bool8 SPC7110RTC; - bool8 OBC1; - uint8 SETA; - bool8 SRTC; - bool8 BS; - bool8 BSXItself; - bool8 BSXBootup; - bool8 MouseMaster; - bool8 SuperScopeMaster; - bool8 JustifierMaster; - bool8 MultiPlayer5Master; + /* Joystick options */ + bool8 JoystickEnabled; - bool8 ForceLoROM; - bool8 ForceHiROM; - bool8 ForceHeader; - bool8 ForceNoHeader; - bool8 ForceInterleaved; - bool8 ForceInterleaved2; - bool8 ForceInterleaveGD24; - bool8 ForceNotInterleaved; - bool8 ForcePAL; - bool8 ForceNTSC; - bool8 PAL; - uint32 FrameTimePAL; - uint32 FrameTimeNTSC; - uint32 FrameTime; + /* ROM timing options (see also H_Max above) */ + bool8 ForcePAL; + bool8 ForceNTSC; + bool8 PAL; + uint32 FrameTimePAL; + uint32 FrameTimeNTSC; + uint32 FrameTime; + uint32 SkipFrames; - bool8 SoundSync; - bool8 SixteenBitSound; - uint32 SoundPlaybackRate; - uint32 SoundInputRate; - bool8 Stereo; - bool8 ReverseStereo; - bool8 Mute; + /* ROM image options */ + bool8 ForceLoROM; + bool8 ForceHiROM; + bool8 ForceHeader; + bool8 ForceNoHeader; + bool8 ForceInterleaved; + bool8 ForceInterleaved2; + bool8 ForceNotInterleaved; - bool8 SupportHiRes; - bool8 Transparency; - uint8 BG_Forced; - bool8 DisableGraphicWindows; + /* Peripherial options */ + bool8 ForceSuperFX; + bool8 ForceNoSuperFX; + bool8 ForceDSP1; + bool8 ForceNoDSP1; + bool8 ForceSA1; + bool8 ForceNoSA1; + bool8 ForceC4; + bool8 ForceNoC4; + bool8 ForceSDD1; + bool8 ForceNoSDD1; + bool8 SRTC; - bool8 DisplayFrameRate; - bool8 DisplayWatchedAddresses; - bool8 DisplayPressedKeys; - bool8 DisplayMovieFrame; - bool8 AutoDisplayMessages; - uint32 InitialInfoStringTimeout; - uint16 DisplayColor; + bool8 ShutdownMaster; + bool8 MultiPlayer5Master; + bool8 SuperScopeMaster; + bool8 MouseMaster; + bool8 JustifierMaster; + bool8 SuperFX; + bool8 DSP1Master; + bool8 SA1; + bool8 C4; + bool8 SDD1; + bool8 SPC7110; + bool8 SPC7110RTC; + bool8 OBC1; + /* Sound options */ + uint32 SoundPlaybackRate; + bool8 TraceSoundDSP; + bool8 Stereo; + bool8 ReverseStereo; + bool8 SixteenBitSound; + int SoundBufferSize; + int SoundMixInterval; + bool8 SoundEnvelopeHeightReading; + bool8 DisableSoundEcho; + bool8 DisableSampleCaching; + bool8 DisableMasterVolume; + bool8 SoundSync; + bool8 FakeMuteFix; + bool8 InterpolatedSound; + bool8 ThreadSound; + bool8 Mute; + bool8 NextAPUEnabled; + uint8 AltSampleDecode; + bool8 FixFrequency; - bool8 Multi; - char CartAName[PATH_MAX + 1]; - char CartBName[PATH_MAX + 1]; + /* Graphics options */ + bool8 Transparency; + bool8 SupportHiRes; + bool8 Mode7Interpolate; // no longer used? + bool8 AutoDisplayMessages; + uint8 BG_Forced; + bool8 SnapshotScreenshots; + uint32 InitialInfoStringTimeout; // Messages normally display for this many frames - bool8 DisableGameSpecificHacks; - bool8 ShutdownMaster; - bool8 Shutdown; - bool8 BlockInvalidVRAMAccessMaster; - bool8 BlockInvalidVRAMAccess; - bool8 DisableIRQ; - bool8 DisableHDMA; - int32 HDMATimingHack; + /* SNES graphics options */ + bool8 BGLayering; + bool8 DisableGraphicWindows; + bool8 ForceTransparency; + bool8 ForceNoTransparency; + bool8 DisableHDMA; + bool8 DisplayFrameRate; + bool8 DisableRangeTimeOver; /* XXX: unused */ + bool8 DisplayWatchedAddresses; - bool8 ForcedPause; - bool8 Paused; - bool8 StopEmulation; + /* Multi ROMs */ + bool8 Multi; + char CartAName[_MAX_PATH + 1]; + char CartBName[_MAX_PATH + 1]; - uint32 SkipFrames; - uint32 TurboSkipFrames; - uint32 AutoMaxSkipFrames; - bool8 TurboMode; - uint32 HighSpeedSeek; - bool8 FrameAdvance; + /* Others */ + bool8 NetPlay; + bool8 NetPlayServer; + char ServerName [128]; + int Port; + bool8 GlideEnable; + bool8 OpenGLEnable; + int32 AutoSaveDelay; /* Time in seconds before S-RAM auto-saved if modified. */ + bool8 ApplyCheats; + bool8 TurboMode; + bool8 OldTurbo; + bool8 UpAndDown; + uint8 DisplayPressedKeys; // The value indicates how to do it. + uint32 HighSpeedSeek; + uint32 TurboSkipFrames; + uint32 AutoMaxSkipFrames; + bool8 MovieTruncate; + bool8 MovieNotifyIgnored; + bool8 WrongMovieStateProtection; - bool8 NetPlay; - bool8 NetPlayServer; - char ServerName[128]; - int Port; - - bool8 MovieTruncate; - bool8 MovieNotifyIgnored; - bool8 WrongMovieStateProtection; - bool8 DumpStreams; - int DumpStreamsMaxFrames; - - bool8 TakeScreenshot; - int8 StretchScreenshots; - bool8 SnapshotScreenshots; - - bool8 ApplyCheats; - bool8 NoPatch; - int32 AutoSaveDelay; - bool8 DontSaveOopsSnapshot; - bool8 UpAndDown; - - bool8 OpenGLEnable; +/* Fixes for individual games */ + bool8 WinterGold; + bool8 BS; /* Japanese Satellite System games. */ + bool8 BSXItself; + bool8 BSXBootup; + uint8 APURAMInitialValue; + bool8 SampleCatchup; + int8 SETA; + bool8 BlockInvalidVRAMAccess; + bool8 TakeScreenshot; + int8 StretchScreenshots; + uint16 DisplayColor; + int SoundDriver; + int AIDOShmId; + bool8 SDD1Pack; + bool8 NoPatch; + bool8 ForceInterleaveGD24; }; struct SSNESGameFixes { - uint8 SRAMInitialValue; - uint8 Uniracers; + uint8 APU_OutPorts_ReturnValueFix; + uint8 SRAMInitialValue; + uint8 Uniracers; }; -enum -{ - PAUSE_NETPLAY_CONNECT = (1 << 0), - PAUSE_TOGGLE_FULL_SCREEN = (1 << 1), - PAUSE_EXIT = (1 << 2), - PAUSE_MENU = (1 << 3), - PAUSE_INACTIVE_WINDOW = (1 << 4), - PAUSE_WINDOW_ICONISED = (1 << 5), - PAUSE_RESTORE_GUI = (1 << 6), - PAUSE_FREEZE_FILE = (1 << 7) +START_EXTERN_C +extern struct SSettings Settings; +extern struct SCPUState CPU; +extern struct STimings Timings; +extern struct SSNESGameFixes SNESGameFixes; +extern char String [513]; + +void S9xExit (); +void S9xMessage (int type, int number, const char *message); +void S9xLoadSDD1Data (); +END_EXTERN_C + +enum { + PAUSE_NETPLAY_CONNECT = (1 << 0), + PAUSE_TOGGLE_FULL_SCREEN = (1 << 1), + PAUSE_EXIT = (1 << 2), + PAUSE_MENU = (1 << 3), + PAUSE_INACTIVE_WINDOW = (1 << 4), + PAUSE_WINDOW_ICONISED = (1 << 5), + PAUSE_RESTORE_GUI = (1 << 6), + PAUSE_FREEZE_FILE = (1 << 7) }; - -void S9xSetPause(uint32); -void S9xClearPause(uint32); -void S9xExit(void); -void S9xMessage(int, int, const char *); - -extern struct SSettings Settings; -extern struct SCPUState CPU; -extern struct STimings Timings; -extern struct SSNESGameFixes SNESGameFixes; -extern char String[513]; +void S9xSetPause (uint32 mask); +void S9xClearPause (uint32 mask); #endif + diff --git a/source/snes9x/soundux.cpp b/source/snes9x/soundux.cpp new file mode 100644 index 0000000..3247e91 --- /dev/null +++ b/source/snes9x/soundux.cpp @@ -0,0 +1,2442 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#ifdef __DJGPP__ +#include +#undef TRUE +#endif + +#include +#include "snes9x.h" +#include "apu.h" +#include "memmap.h" +#include "soundux.h" + +// gaussian table by libopenspc and SNEeSe +static const int32 gauss[512] = +{ + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, + 0x001, 0x001, 0x001, 0x002, 0x002, 0x002, 0x002, 0x002, + 0x002, 0x002, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004, + 0x004, 0x004, 0x004, 0x004, 0x005, 0x005, 0x005, 0x005, + 0x006, 0x006, 0x006, 0x006, 0x007, 0x007, 0x007, 0x008, + 0x008, 0x008, 0x009, 0x009, 0x009, 0x00A, 0x00A, 0x00A, + 0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00D, 0x00D, 0x00E, + 0x00E, 0x00F, 0x00F, 0x00F, 0x010, 0x010, 0x011, 0x011, + 0x012, 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x016, + 0x017, 0x017, 0x018, 0x018, 0x019, 0x01A, 0x01B, 0x01B, + 0x01C, 0x01D, 0x01D, 0x01E, 0x01F, 0x020, 0x020, 0x021, + 0x022, 0x023, 0x024, 0x024, 0x025, 0x026, 0x027, 0x028, + 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030, + 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038, + 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x040, 0x041, 0x042, + 0x043, 0x045, 0x046, 0x047, 0x049, 0x04A, 0x04C, 0x04D, + 0x04E, 0x050, 0x051, 0x053, 0x054, 0x056, 0x057, 0x059, + 0x05A, 0x05C, 0x05E, 0x05F, 0x061, 0x063, 0x064, 0x066, + 0x068, 0x06A, 0x06B, 0x06D, 0x06F, 0x071, 0x073, 0x075, + 0x076, 0x078, 0x07A, 0x07C, 0x07E, 0x080, 0x082, 0x084, + 0x086, 0x089, 0x08B, 0x08D, 0x08F, 0x091, 0x093, 0x096, + 0x098, 0x09A, 0x09C, 0x09F, 0x0A1, 0x0A3, 0x0A6, 0x0A8, + 0x0AB, 0x0AD, 0x0AF, 0x0B2, 0x0B4, 0x0B7, 0x0BA, 0x0BC, + 0x0BF, 0x0C1, 0x0C4, 0x0C7, 0x0C9, 0x0CC, 0x0CF, 0x0D2, + 0x0D4, 0x0D7, 0x0DA, 0x0DD, 0x0E0, 0x0E3, 0x0E6, 0x0E9, + 0x0EC, 0x0EF, 0x0F2, 0x0F5, 0x0F8, 0x0FB, 0x0FE, 0x101, + 0x104, 0x107, 0x10B, 0x10E, 0x111, 0x114, 0x118, 0x11B, + 0x11E, 0x122, 0x125, 0x129, 0x12C, 0x130, 0x133, 0x137, + 0x13A, 0x13E, 0x141, 0x145, 0x148, 0x14C, 0x150, 0x153, + 0x157, 0x15B, 0x15F, 0x162, 0x166, 0x16A, 0x16E, 0x172, + 0x176, 0x17A, 0x17D, 0x181, 0x185, 0x189, 0x18D, 0x191, + 0x195, 0x19A, 0x19E, 0x1A2, 0x1A6, 0x1AA, 0x1AE, 0x1B2, + 0x1B7, 0x1BB, 0x1BF, 0x1C3, 0x1C8, 0x1CC, 0x1D0, 0x1D5, + 0x1D9, 0x1DD, 0x1E2, 0x1E6, 0x1EB, 0x1EF, 0x1F3, 0x1F8, + 0x1FC, 0x201, 0x205, 0x20A, 0x20F, 0x213, 0x218, 0x21C, + 0x221, 0x226, 0x22A, 0x22F, 0x233, 0x238, 0x23D, 0x241, + 0x246, 0x24B, 0x250, 0x254, 0x259, 0x25E, 0x263, 0x267, + 0x26C, 0x271, 0x276, 0x27B, 0x280, 0x284, 0x289, 0x28E, + 0x293, 0x298, 0x29D, 0x2A2, 0x2A6, 0x2AB, 0x2B0, 0x2B5, + 0x2BA, 0x2BF, 0x2C4, 0x2C9, 0x2CE, 0x2D3, 0x2D8, 0x2DC, + 0x2E1, 0x2E6, 0x2EB, 0x2F0, 0x2F5, 0x2FA, 0x2FF, 0x304, + 0x309, 0x30E, 0x313, 0x318, 0x31D, 0x322, 0x326, 0x32B, + 0x330, 0x335, 0x33A, 0x33F, 0x344, 0x349, 0x34E, 0x353, + 0x357, 0x35C, 0x361, 0x366, 0x36B, 0x370, 0x374, 0x379, + 0x37E, 0x383, 0x388, 0x38C, 0x391, 0x396, 0x39B, 0x39F, + 0x3A4, 0x3A9, 0x3AD, 0x3B2, 0x3B7, 0x3BB, 0x3C0, 0x3C5, + 0x3C9, 0x3CE, 0x3D2, 0x3D7, 0x3DC, 0x3E0, 0x3E5, 0x3E9, + 0x3ED, 0x3F2, 0x3F6, 0x3FB, 0x3FF, 0x403, 0x408, 0x40C, + 0x410, 0x415, 0x419, 0x41D, 0x421, 0x425, 0x42A, 0x42E, + 0x432, 0x436, 0x43A, 0x43E, 0x442, 0x446, 0x44A, 0x44E, + 0x452, 0x455, 0x459, 0x45D, 0x461, 0x465, 0x468, 0x46C, + 0x470, 0x473, 0x477, 0x47A, 0x47E, 0x481, 0x485, 0x488, + 0x48C, 0x48F, 0x492, 0x496, 0x499, 0x49C, 0x49F, 0x4A2, + 0x4A6, 0x4A9, 0x4AC, 0x4AF, 0x4B2, 0x4B5, 0x4B7, 0x4BA, + 0x4BD, 0x4C0, 0x4C3, 0x4C5, 0x4C8, 0x4CB, 0x4CD, 0x4D0, + 0x4D2, 0x4D5, 0x4D7, 0x4D9, 0x4DC, 0x4DE, 0x4E0, 0x4E3, + 0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF, 0x4F1, 0x4F3, + 0x4F5, 0x4F6, 0x4F8, 0x4FA, 0x4FB, 0x4FD, 0x4FF, 0x500, + 0x502, 0x503, 0x504, 0x506, 0x507, 0x508, 0x50A, 0x50B, + 0x50C, 0x50D, 0x50E, 0x50F, 0x510, 0x511, 0x511, 0x512, + 0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517, + 0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519 +}; + +//static const int32 *G1 = &gauss[256], *G2 = &gauss[512], +// *G3 = &gauss[255], *G4 = &gauss[-1]; + +#define G1(n) gauss[256 + (n)] +#define G2(n) gauss[512 + (n)] +#define G3(n) gauss[255 + (n)] +#define G4(n) gauss[ -1 + (n)] + +// envelope/noise table by libopenspc and SNEeSe +int32 env_counter_table[32] = +{ + 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C, + 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180, + 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00, + 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800 +}; + +static int32 env_counter_max; +static const int32 env_counter_max_master = 0x7800; + +static int rand_seed = 1; + +extern int32 Loop[16]; +extern int32 Echo[24000]; +extern int32 FilterTaps[8]; +extern int32 MixBuffer[SOUND_BUFFER_SIZE]; +extern int32 EchoBuffer[SOUND_BUFFER_SIZE]; +extern int32 DummyEchoBuffer[SOUND_BUFFER_SIZE]; +extern uint32 FIRIndex; + +// For backward compatibility ------------------------------ +static uint32 OldAttackRate[16] = +{ + 4100, 2600, 1500, 1000, 640, 380, 260, 160, + 96, 64, 40, 24, 16, 10, 6, 1 +}; + +static uint32 OldDecayRate[8] = +{ + 1200, 740, 440, 290, 180, 110, 74, 37 +}; + +static uint32 OldSustainRate[32] = +{ + ~0, 38000, 28000, 24000, 19000, 14000, 12000, 9400, + 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500, + 1200, 880, 740, 590, 440, 370, 290, 220, + 180, 150, 110, 92, 74, 55, 37, 18 +}; + +static int OldNoiseFreq[32] = +{ + 0, 16, 21, 25, 31, 42, 50, 63, + 84, 100, 125, 167, 200, 250, 333, 400, + 500, 667, 800, 1000, 1300, 1600, 2000, 2700, + 3200, 4000, 5300, 6400, 8000, 10700, 16000, 32000 +}; +// --------------------------------------------------------- + +#define FIXED_POINT 0x10000UL +#define FIXED_POINT_SHIFT 16 + +#undef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define CLIP16(v) \ + if ((v) < -32768) \ + (v) = -32768; \ + else \ + if ((v) > 32767) \ + (v) = 32767 + +#define CLIP8(v) \ + if ((v) < -128) \ + (v) = -128; \ + else \ + if ((v) > 127) \ + (v) = 127 + +void S9xAPUSetEndOfSample (int i, Channel *); +void S9xAPUSetEndX (int); +void S9xSetEnvRate (Channel *, int32, int32); +void MixStereo (int); +void MixMono (int); + +static void S9xSetSoundFrequency (int, int); +static void S9xConvertSoundOldValues (); +static void DecodeBlock (Channel *); +static void AltDecodeBlock (Channel *); +static void AltDecodeBlock2 (Channel *); +STATIC inline uint8 *S9xGetSampleAddress (int); + +EXTERN_C void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); +EXTERN_C void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); + +static bool8 DoFakeMute = FALSE; + +STATIC inline uint8 *S9xGetSampleAddress (int sample_number) +{ + uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xFFFF); + return (IAPU.RAM + addr); +} + +void S9xAPUSetEndOfSample (int i, Channel *ch) +{ + ch->state = SOUND_SILENT; + ch->mode = MODE_NONE; + ch->out_sample = 0; + ch->xenvx = 0; + if(!DoFakeMute) { + APU.DSP[APU_ENDX] |= 1 << i; + APU.DSP[APU_KON] &= ~(1 << i); + APU.DSP[APU_KOFF] &= ~(1 << i); + APU.KeyedChannels &= ~(1 << i); + } +} + +#ifdef __DJGPP +END_OF_FUNCTION (S9xAPUSetEndOfSample) +#endif + +void S9xAPUSetEndX (int i) +{ + if(!DoFakeMute) { + APU.DSP[APU_ENDX] |= 1 << i; + } +} + +#ifdef __DJGPP +END_OF_FUNCTION (S9xAPUSetEndX) +#endif + +void S9xSetEnvRate (Channel *ch, int32 rate_count, int32 xtarget) +{ + ch->xenvx_target = xtarget; + ch->xenv_rate = rate_count; +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xSetEnvRate); +#endif + +void S9xSetEnvelopeRate (int channel, int32 rate_count, int32 xtarget) +{ + S9xSetEnvRate (&SoundData.channels[channel], rate_count, xtarget); +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xSetEnvelopeRate); +#endif + +void S9xSetSoundVolume (int channel, short volume_left, short volume_right) +{ + Channel *ch = &SoundData.channels[channel]; + + if (so.stereo_switch + 1) + { + volume_left = ((so.stereo_switch & ( 1 << channel)) ? volume_left : 0); + volume_right = ((so.stereo_switch & (256 << channel)) ? volume_right : 0); + } + + if (!so.stereo) + volume_left = (ABS(volume_right) + ABS(volume_left)) >> 1; + + ch->volume_left = volume_left; + ch->volume_right = volume_right; +} + +void S9xSetMasterVolume (short volume_left, short volume_right) +{ + if (Settings.DisableMasterVolume) + { + SoundData.master_volume_left = 127; + SoundData.master_volume_right = 127; + SoundData.master_volume[0] = SoundData.master_volume[1] = 127; + } + else + { + if (!so.stereo) + volume_left = (ABS(volume_right) + ABS(volume_left)) >> 1; + + SoundData.master_volume_left = volume_left; + SoundData.master_volume_right = volume_right; + SoundData.master_volume[Settings.ReverseStereo] = volume_left; + SoundData.master_volume[1 ^ Settings.ReverseStereo] = volume_right; + } +} + +void S9xSetEchoVolume (short volume_left, short volume_right) +{ + if (!so.stereo) + volume_left = (ABS(volume_right) + ABS(volume_left)) >> 1; + + SoundData.echo_volume_left = volume_left; + SoundData.echo_volume_right = volume_right; + SoundData.echo_volume[Settings.ReverseStereo] = volume_left; + SoundData.echo_volume[1 ^ Settings.ReverseStereo] = volume_right; +} + +void S9xSetEchoEnable (uint8 byte) +{ +#if 0 + SoundData.echo_channel_enable = byte; + if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho) + byte = 0; + if (byte && !SoundData.echo_enable) + { + memset (Loop, 0, sizeof (Loop)); + memset (Echo, 0, sizeof (Echo)); + } +#endif + SoundData.echo_enable = byte; + for (int i = 0; i < NUM_CHANNELS; i++) + { + if (byte & (1 << i)) + SoundData.channels[i].echo_buf_ptr = EchoBuffer; + else + SoundData.channels[i].echo_buf_ptr = DummyEchoBuffer; + } +} + +void S9xSetEchoFeedback (int feedback) +{ + SoundData.echo_feedback = feedback; +} + +void S9xSetEchoDelay (unsigned int delay) +{ + SoundData.echo_buffer_size = (delay << 10) * so.playback_rate / 32000; + if (!so.stereo) + SoundData.echo_buffer_size >>= 1; + if (SoundData.echo_buffer_size) + SoundData.echo_ptr %= SoundData.echo_buffer_size; + else + SoundData.echo_ptr = 0; +} + +void S9xSetEchoWriteEnable (uint8 byte) +{ + SoundData.echo_write_enabled = byte; + //printf("Echo write enable: %d\n", byte); +} + +void S9xSetFrequencyModulationEnable (uint8 byte) +{ + SoundData.pitch_mod = byte & ~1; +} + +void S9xSetSoundKeyOff (int channel) +{ + Channel *ch = &SoundData.channels[channel]; + + if (ch->state != SOUND_SILENT) + { + ch->state = SOUND_RELEASE; + ch->mode = MODE_RELEASE; + S9xSetEnvRate (ch, env_counter_max, 0); + } +} + +void S9xPrepareSoundForSnapshotSave (bool8 restore) +{ + static uint32 temp_hertz[NUM_CHANNELS]; + + int i, j; + + if (!restore) + { + for (i = 0; i < NUM_CHANNELS; i++) + { + Channel *ch = &SoundData.channels[i]; + + ch->count = 0; + ch->envx = ch->xenvx >> 4; + ch->envx_target = ch->xenvx_target >> 4; + ch->direction = 0; + ch-> left_vol_level = (ch->xenvx * ch->volume_left ) >> 11; + ch->right_vol_level = (ch->xenvx * ch->volume_right) >> 11; + ch->release_rate = 8; + ch->sustain_level = ch->xsustain_level >> 8; + + if (env_counter_max < ch->xenv_count) + ch->env_error = 0; + else + ch->env_error = (uint32) + ((double) FIXED_POINT / env_counter_max * (env_counter_max - ch->xenv_count)); + + if (ch->xenv_rate < 0) + ch->erate = 0; + else + ch->erate = (uint32) + ((double) FIXED_POINT / env_counter_max * ch->xenv_rate); + + for (j = 0; j < 32; j++) + if (env_counter_table[j] == ch->xattack_rate) + break; + ch->attack_rate = OldAttackRate[(unsigned) (((j - 1) >> 1) & 0xF)]; + + for (j = 0; j < 32; j++) + if (env_counter_table[j] == ch->xdecay_rate) + break; + ch->decay_rate = OldDecayRate[(unsigned) (((j - 0x10) >> 1) & 0x7)]; + + for (j = 0; j < 32; j++) + if (env_counter_table[j] == ch->xsustain_rate) + break; + ch->sustain_rate = OldSustainRate[(unsigned) (j & 0x1F)]; + } + + for (j = 0; j < 32; j++) + if (env_counter_table[j] == SoundData.noise_rate) + break; + + for (i = 0; i < NUM_CHANNELS; i++) + { + Channel *ch = &SoundData.channels[i]; + + temp_hertz[i] = ch->hertz; + if (ch->type == SOUND_NOISE) + ch->hertz = OldNoiseFreq[(unsigned) (j & 0x1F)]; + } + } + else + { + for (i = 0; i < NUM_CHANNELS; i++) + { + Channel *ch = &SoundData.channels[i]; + + ch->hertz = temp_hertz[i]; + } + } +} + +static void S9xConvertSoundOldValues () +{ + int i, j; + int old_noise_freq = 0; + + for (i = 0; i < NUM_CHANNELS; i++) + { + Channel *ch = &SoundData.channels[i]; + + ch->xenvx = ch->envx << 4; + ch->xenvx_target = ch->envx_target << 4; + ch->out_sample = ((ch->sample * ch->xenvx) >> 11) & ~1; + ch->xsustain_level = ch->sustain_level << 8; + + ch->xenv_rate = (int32) ((double) ch->erate * env_counter_max / FIXED_POINT); + ch->xenv_count = env_counter_max - + (int32) ((double) ch->env_error * env_counter_max / FIXED_POINT); + + for (j = 0; j < 16; j++) + if (OldAttackRate[j] == ch->attack_rate) + break; + ch->xattack_rate = env_counter_table[(unsigned) (((j << 1) + 1) & 0x1F)]; + + for (j = 0; j < 8; j++) + if (OldDecayRate[j] == ch->decay_rate) + break; + ch->xdecay_rate = env_counter_table[(unsigned) (((j << 1) + 0x10) & 0x1F)]; + + for (j = 0; j < 32; j++) + if (OldSustainRate[j] == ch->sustain_rate) + break; + ch->xsustain_rate = env_counter_table[(unsigned) (j & 0x1F)]; + + if (ch->type == SOUND_NOISE) + { + old_noise_freq = ch->hertz; + ch->hertz = 32000; + } + } + + if (old_noise_freq) + { + for (j = 0; j < 32; j++) + if (OldNoiseFreq[j] == old_noise_freq) + break; + SoundData.noise_rate = env_counter_table[(unsigned) (j & 0x1F)]; + } + else + SoundData.noise_rate = 0; +} + +void S9xFixSoundAfterSnapshotLoad (int version) +{ + S9xSetEchoEnable (APU.DSP[APU_EON]); + S9xSetEchoWriteEnable (!(APU.DSP[APU_FLG] & APU_ECHO_DISABLED)); + S9xSetEchoDelay (APU.DSP[APU_EDL] & 0xF); + S9xSetEchoFeedback ((signed char) APU.DSP[APU_EFB]); + + S9xSetFilterCoefficient (0, (signed char) APU.DSP[APU_C0]); + S9xSetFilterCoefficient (1, (signed char) APU.DSP[APU_C1]); + S9xSetFilterCoefficient (2, (signed char) APU.DSP[APU_C2]); + S9xSetFilterCoefficient (3, (signed char) APU.DSP[APU_C3]); + S9xSetFilterCoefficient (4, (signed char) APU.DSP[APU_C4]); + S9xSetFilterCoefficient (5, (signed char) APU.DSP[APU_C5]); + S9xSetFilterCoefficient (6, (signed char) APU.DSP[APU_C6]); + S9xSetFilterCoefficient (7, (signed char) APU.DSP[APU_C7]); + + if (version < 2) + S9xConvertSoundOldValues (); + + for (int i = 0; i < NUM_CHANNELS; i++) + { + S9xSetSoundFrequency (i, SoundData.channels[i].hertz); + SoundData.channels[i].needs_decode = TRUE; + SoundData.channels[i].nb_index = 0; + SoundData.channels[i].nb_sample[0] = 0; + SoundData.channels[i].nb_sample[1] = 0; + SoundData.channels[i].nb_sample[2] = 0; + SoundData.channels[i].nb_sample[3] = 0; + SoundData.channels[i].xsmp_count = 0; + SoundData.channels[i].previous[0] = (int32) SoundData.channels[i].previous16[0]; + SoundData.channels[i].previous[1] = (int32) SoundData.channels[i].previous16[1]; + } + + SoundData.noise_count = 0; + + SoundData.master_volume[Settings.ReverseStereo] = SoundData.master_volume_left; + SoundData.master_volume[1 ^ Settings.ReverseStereo] = SoundData.master_volume_right; + SoundData.echo_volume[Settings.ReverseStereo] = SoundData.echo_volume_left; + SoundData.echo_volume[1 ^ Settings.ReverseStereo] = SoundData.echo_volume_right; +} + +void S9xSetFilterCoefficient (int tap, int value) +{ + FilterTaps[tap & 7] = value; + SoundData.no_filter = + FilterTaps[0] == 127 && + FilterTaps[1] == 0 && + FilterTaps[2] == 0 && + FilterTaps[3] == 0 && + FilterTaps[4] == 0 && + FilterTaps[5] == 0 && + FilterTaps[6] == 0 && + FilterTaps[7] == 0; +} + +void S9xSetSoundADSR (int channel, int ar, int dr, int sr, int sl) +{ + Channel *ch = &SoundData.channels[channel]; + + ch->xattack_rate = env_counter_table[(ar << 1) + 1]; + ch->xdecay_rate = env_counter_table[(dr << 1) + 0x10]; + ch->xsustain_rate = env_counter_table[sr]; + ch->xsustain_level = (ENV_RANGE >> 3) * (sl + 1); + + switch (ch->state) + { + case SOUND_ATTACK: + S9xSetEnvRate (ch, ch->xattack_rate, ENV_MAX); + break; + + case SOUND_DECAY: + S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); + break; + + case SOUND_SUSTAIN: + S9xSetEnvRate (ch, ch->xsustain_rate, 0); + break; + } +} + +void S9xSetEnvelopeHeight (int channel, int32 xlevel) +{ + Channel *ch = &SoundData.channels[channel]; + + ch->xenvx = ch->xenvx_target = xlevel; + ch->xenv_rate = 0; + if (xlevel == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) + S9xAPUSetEndOfSample (channel, ch); +} + +uint8 S9xGetEnvelopeHeight (int channel) +{ + if (Settings.SoundEnvelopeHeightReading) + return ((SoundData.channels[channel].xenvx >> ENV_SHIFT) & 0x7F); + else + return (0); +} + +static void S9xSetSoundFrequency (int channel, int hertz) +{ + if (so.playback_rate) + SoundData.channels[channel].frequency = (uint32) + ((int64) (hertz << (FIXED_POINT_SHIFT - 15)) * 32000 / so.playback_rate); + if (Settings.FixFrequency) + SoundData.channels[channel].frequency = (uint32) + (SoundData.channels[channel].frequency * so.pitch_mul); +} + +void S9xSetSoundHertz (int channel, int hertz) +{ + SoundData.channels[channel].hertz = hertz; + S9xSetSoundFrequency (channel, hertz); +} + +void S9xSetSoundType (int channel, int type_of_sound) +{ + SoundData.channels[channel].type = type_of_sound; +} + +bool8 S9xSetSoundMute (bool8 mute) +{ + bool8 old = so.mute_sound; + so.mute_sound = mute; + return (old); +} + +static void AltDecodeBlock (Channel *ch) +{ + if (ch->block_pointer > 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + memset ((void *) ch->decoded, 0, sizeof (int16) * 16); + return; + } + + signed char *compressed = (signed char *) &IAPU.RAM[ch->block_pointer]; + + unsigned char filter = *compressed; + ch->last_block = filter & 1; + ch->loop = (filter & 2) != 0; + + signed short *raw = ch->block = ch->decoded; + +#if (defined (USE_X86_ASM) && (defined (__i386__) || defined (__i486__) || \ + defined (__i586__) || defined (__WIN32__) || defined (__DJGPP))) + if (Settings.AltSampleDecode == 1) + DecodeBlockAsm (compressed, raw, &ch->previous[0], &ch->previous[1]); + else + DecodeBlockAsm2 (compressed, raw, &ch->previous[0], &ch->previous[1]); +#else + int32 out; + unsigned char shift; + signed char sample1, sample2; + uint32 i; + + compressed++; + + int32 prev0 = ch->previous[0]; + int32 prev1 = ch->previous[1]; + shift = filter >> 4; + + switch ((filter >> 2) & 3) + { + case 0: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + *raw++ = ((int32) sample1 << shift); + *raw++ = ((int32) sample2 << shift); + } + prev1 = *(raw - 2); + prev0 = *(raw - 1); + break; + + case 1: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + prev0 = (int16) prev0; + *raw++ = prev1 = ((int32) sample1 << shift) + prev0 - (prev0 >> 4); + prev1 = (int16) prev1; + *raw++ = prev0 = ((int32) sample2 << shift) + prev1 - (prev1 >> 4); + } + break; + + case 2: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + + out = (sample1 << shift) - prev1 + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + (prev0 >> 4); + + out = (sample2 << shift) - prev1 + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + (prev0 >> 4); + } + break; + + case 3: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + out = (sample1 << shift); + + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + (prev0 >> 4) - (prev1 >> 6); + + out = (sample2 << shift); + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + (prev0 >> 4) - (prev1 >> 6); + } + break; + } + + ch->previous[0] = prev0; + ch->previous[1] = prev1; +#endif + ch->block_pointer += 9; +} + +static void AltDecodeBlock2 (Channel *ch) +{ + int32 out; + unsigned char filter; + unsigned char shift; + signed char sample1, sample2; + uint32 i; + + if (ch->block_pointer > 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + memset ((void *) ch->decoded, 0, sizeof (int16) * 16); + return; + } + + signed char *compressed = (signed char *) &IAPU.RAM[ch->block_pointer]; + + filter = *compressed; + ch->last_block = filter & 1; + ch->loop = (filter & 2) != 0; + + compressed++; + signed short *raw = ch->block = ch->decoded; + + shift = filter >> 4; + int32 prev0 = ch->previous[0]; + int32 prev1 = ch->previous[1]; + + if(shift > 12) + shift -= 4; + + switch ((filter >> 2) & 3) + { + case 0: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + + out = (int32) (sample1 << shift); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16) out; + + out = (int32) (sample2 << shift); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16) out; + } + break; + + case 1: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + out = (int32) (sample1 << shift); + out += (int32) ((double) prev0 * 15/16); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16) out; + + out = (int32) (sample2 << shift); + out += (int32) ((double) prev0 * 15/16); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16) out; + } + break; + + case 2: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + + out = ((sample1 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; + + prev1 = prev0; + prev0 = (int16) out; + *raw++ = (int16) out; + + out = ((sample2 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; + + prev1 = prev0; + prev0 = (int16) out; + *raw++ = (int16) out; + } + break; + + case 3: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + out = (int32) (sample1 << shift); + out += (int32) ((double) prev0 * 115/64 - (double) prev1 * 13/16); + + prev1 = prev0; + prev0 = out; + + CLIP16(out); + *raw++ = (int16) out; + + out = (int32) (sample2 << shift); + out += (int32) ((double) prev0 * 115/64 - (double) prev1 * 13/16); + + prev1 = prev0; + prev0 = out; + + CLIP16(out); + *raw++ = (int16) out; + } + break; + } + + ch->previous[0] = prev0; + ch->previous[1] = prev1; + + ch->block_pointer += 9; +} + +static void DecodeBlock (Channel *ch) +{ + int32 out; + unsigned char filter; + unsigned char shift; + signed char sample1, sample2; + bool invalid_header; + + if (Settings.AltSampleDecode) + { + if (Settings.AltSampleDecode < 3) + AltDecodeBlock (ch); + else + AltDecodeBlock2 (ch); + return; + } + + if (ch->block_pointer > 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + return; + } + + signed char *compressed = (signed char *) &IAPU.RAM[ch->block_pointer]; + + filter = *compressed; + ch->last_block = filter & 1; + ch->loop = (filter & 2) != 0; + + compressed++; + signed short *raw = ch->block = ch->decoded; + + // Seperate out the header parts used for decoding + + shift = filter >> 4; + + // Header validity check: if range(shift) is over 12, ignore + // all bits of the data for that block except for the sign bit of each + invalid_header = !(shift < 0xD); + + filter &= 0x0C; + + int32 prev0 = ch->previous[0]; + int32 prev1 = ch->previous[1]; + + for (uint32 i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + sample1 >>= 4; + + for (int nybblesmp = 0; nybblesmp < 2; nybblesmp++) + { + out = (nybblesmp ? sample2 : sample1); + if (!invalid_header) + out = (out << shift) >> 1; + else + out &= ~0x7FF; + + switch (filter) + { + case 0x00: + // Method0 -[Smp] + break; + + case 0x04: + // Method1 -[Delta]+[Smp-1](15/16) + out += prev0 >> 1; + out += (-prev0) >> 5; + break; + + case 0x08: + // Method2 -[Delta]+[Smp-1](61/32)-[Smp-2](15/16) + out += prev0; + out += (-(prev0 + (prev0 >> 1))) >> 5; + out -= prev1 >> 1; + out += prev1 >> 5; + break; + + case 0x0C: + // Method3 -[Delta]+[Smp-1](115/64)-[Smp-2](13/16) + out += prev0; + out += (-(prev0 + (prev0 << 2) + (prev0 << 3))) >> 7; + out -= prev1 >> 1; + out += (prev1 + (prev1 >> 1)) >> 4; + break; + } + + CLIP16(out); + + prev1 = (signed short) prev0; + prev0 = *raw++ = (signed short) (out << 1); + } + } + + ch->previous[0] = prev0; + ch->previous[1] = prev1; + + ch->block_pointer += 9; +} + +void MixStereo (int sample_count) +{ + DoFakeMute=Settings.FakeMuteFix; + + static int32 noise_cache[256]; + static int32 wave[SOUND_BUFFER_SIZE]; + + int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; + + int32 noise_index = 0; + int32 noise_count = 0; + + if (APU.DSP[APU_NON]) + { + noise_count = SoundData.noise_count; + + for (uint32 I = 0; I < (uint32) sample_count; I += 2) + { + noise_count -= SoundData.noise_rate; + while (noise_count <= 0) + { + rand_seed = rand_seed * 48828125 + 1; + noise_cache[noise_index] = rand_seed; + noise_index = (noise_index + 1) & 0xFF; + noise_count += env_counter_max; + } + } + } + + for (uint32 J = 0; J < NUM_CHANNELS; J++) + { + Channel *ch = &SoundData.channels[J]; + uint32 freq = ch->frequency; + + bool8 last_block = FALSE; + + if (ch->type == SOUND_NOISE) + { + noise_index = 0; + noise_count = SoundData.noise_count; + } + + if (ch->state == SOUND_SILENT || last_block || !(so.sound_switch & (1 << J))) + continue; + + bool8 mod1 = pitch_mod & (1 << J); + bool8 mod2 = pitch_mod & (1 << (J + 1)); + + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = 0; + } + + for (uint32 I = 0; I < (uint32) sample_count; I += 2) + { + switch (ch->state) + { + case SOUND_ATTACK: + if (ch->xenv_rate == env_counter_max_master) + ch->xenvx += (ENV_RANGE >> 1); // FIXME + else + { + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx += (ENV_RANGE >> 6); // 1/64 + ch->xenv_count += env_counter_max; + } + } + + if (ch->xenvx > ENV_MAX) + { + ch->xenvx = ENV_MAX; + + if (ch->xsustain_level != ENV_RANGE) + { + ch->state = SOUND_DECAY; + S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); + } + else + { + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->xsustain_rate, 0); + } + } + + break; + + case SOUND_DECAY: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= ch->xenvx_target) + { + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + else + { + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->xsustain_rate, 0); + } + } + + break; + + case SOUND_SUSTAIN: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + + break; + + case SOUND_RELEASE: + ch->xenv_count -= env_counter_max; + while (ch->xenv_count <= 0) + { + ch->xenvx -= (ENV_RANGE >> 8); // 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + + break; + + case SOUND_INCREASE_LINEAR: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx += (ENV_RANGE >> 6); // 1/64 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx > ENV_MAX) + { + ch->xenvx = ENV_MAX; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, 0); + } + + break; + + case SOUND_INCREASE_BENT_LINE: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + if (ch->xenvx >= ((ENV_RANGE * 3) >> 2)) // 0x600 + ch->xenvx += (ENV_RANGE >> 8); // 1/256 + else + ch->xenvx += (ENV_RANGE >> 6); // 1/64 + + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx > ENV_MAX) + { + ch->xenvx = ENV_MAX; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, 0); + } + + break; + + case SOUND_DECREASE_LINEAR: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= (ENV_RANGE >> 6); // 1/64 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + + break; + + case SOUND_DECREASE_EXPONENTIAL: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + + break; + + case SOUND_GAIN: + S9xSetEnvRate (ch, 0, 0); + + break; + } + + ch->xsmp_count += mod1 ? (((int64) freq * (32768 + wave[I >> 1])) >> 15) : freq; + + while (ch->xsmp_count >= 0) + { + ch->xsmp_count -= FIXED_POINT; + ch->nb_sample[ch->nb_index] = ch->sample; + ch->nb_index = (ch->nb_index + 1) & 3; + + ch->sample_pointer++; + if (ch->sample_pointer == SOUND_DECODE_LENGTH) + { + ch->sample_pointer = 0; + + if (ch->last_block) + { + S9xAPUSetEndX (J); + if (!ch->loop) + { + ch->xenvx = 0; + last_block = TRUE; + //S9xAPUSetEndOfSample (J, ch); + while (ch->xsmp_count >= 0) + { + ch->xsmp_count -= FIXED_POINT; + ch->nb_sample[ch->nb_index] = 0; + ch->nb_index = (ch->nb_index + 1) & 3; + } + + break; + } + else + { + ch->last_block = FALSE; + uint8 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = READ_WORD(dir + 2); // loop pointer + } + } + + DecodeBlock (ch); + } + + ch->sample = ch->block[ch->sample_pointer]; + } + + int32 outx, d; + + if (ch->type == SOUND_SAMPLE) + { + if (Settings.InterpolatedSound) + { + // 4-point gaussian interpolation + d = ch->xsmp_count >> (FIXED_POINT_SHIFT - 8); + outx = ((G4(-d) * ch->nb_sample[ ch->nb_index ]) >> 11) & ~1; + outx += ((G3(-d) * ch->nb_sample[(ch->nb_index + 1) & 3]) >> 11) & ~1; + outx += ((G2( d) * ch->nb_sample[(ch->nb_index + 2) & 3]) >> 11) & ~1; + outx = ((outx & 0xFFFF) ^ 0x8000) - 0x8000; + outx += ((G1( d) * ch->nb_sample[(ch->nb_index + 3) & 3]) >> 11) & ~1; + CLIP16(outx); + } + else + outx = ch->sample; + } + else // SAMPLE_NOISE + { + noise_count -= SoundData.noise_rate; + while (noise_count <= 0) + { + noise_count += env_counter_max; + noise_index = (noise_index + 1) & 0xFF; + } + + outx = noise_cache[noise_index] >> 16; + } + + outx = ((outx * ch->xenvx) >> 11) & ~1; + ch->out_sample = outx; + + if (mod2) + wave[I >> 1] = outx; + + int32 VL, VR; + + VL = (outx * ch->volume_left ) >> 7; + VR = (outx * ch->volume_right) >> 7; + + MixBuffer[I ^ Settings.ReverseStereo ] += VL; + MixBuffer[I + (1 ^ Settings.ReverseStereo)] += VR; + ch->echo_buf_ptr[I ^ Settings.ReverseStereo ] += VL; + ch->echo_buf_ptr[I + (1 ^ Settings.ReverseStereo)] += VR; + } + + stereo_exit: ; + } + DoFakeMute=FALSE; + + if (APU.DSP[APU_NON]) + SoundData.noise_count = noise_count; +} + +#ifdef __DJGPP +END_OF_FUNCTION(MixStereo); +#endif + +void MixMono (int sample_count) +{ + DoFakeMute=Settings.FakeMuteFix; + + static int32 noise_cache[256]; + static int32 wave[SOUND_BUFFER_SIZE]; + + int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; + + int32 noise_index = 0; + int32 noise_count = 0; + + if (APU.DSP[APU_NON]) + { + noise_count = SoundData.noise_count; + + for (uint32 I = 0; I < (uint32) sample_count; I++) + { + noise_count -= SoundData.noise_rate; + while (noise_count <= 0) + { + rand_seed = rand_seed * 48828125 + 1; + noise_cache[noise_index] = rand_seed; + noise_index = (noise_index + 1) & 0xFF; + noise_count += env_counter_max; + } + } + } + + for (uint32 J = 0; J < NUM_CHANNELS; J++) + { + Channel *ch = &SoundData.channels[J]; + uint32 freq = ch->frequency; + + bool8 last_block = FALSE; + + if (ch->type == SOUND_NOISE) + { + noise_index = 0; + noise_count = SoundData.noise_count; + } + + if (ch->state == SOUND_SILENT || last_block || !(so.sound_switch & (1 << J))) + continue; + + bool8 mod1 = pitch_mod & (1 << J); + bool8 mod2 = pitch_mod & (1 << (J + 1)); + + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = 0; + } + + for (uint32 I = 0; I < (uint32) sample_count; I++) + { + switch (ch->state) + { + case SOUND_ATTACK: + if (ch->xenv_rate == env_counter_max_master) + ch->xenvx += (ENV_RANGE >> 1); // FIXME + else + { + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx += (ENV_RANGE >> 6); // 1/64 + ch->xenv_count += env_counter_max; + } + } + + if (ch->xenvx > ENV_MAX) + { + ch->xenvx = ENV_MAX; + + if (ch->xsustain_level != ENV_RANGE) + { + ch->state = SOUND_DECAY; + S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); + } + else + { + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->xsustain_rate, 0); + } + } + + break; + + case SOUND_DECAY: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= ch->xenvx_target) + { + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + else + { + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->xsustain_rate, 0); + } + } + + break; + + case SOUND_SUSTAIN: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + + break; + + case SOUND_RELEASE: + ch->xenv_count -= env_counter_max; + while (ch->xenv_count <= 0) + { + ch->xenvx -= (ENV_RANGE >> 8); // 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + + break; + + case SOUND_INCREASE_LINEAR: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx += (ENV_RANGE >> 6); // 1/64 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx > ENV_MAX) + { + ch->xenvx = ENV_MAX; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, 0); + } + + break; + + case SOUND_INCREASE_BENT_LINE: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + if (ch->xenvx >= ((ENV_RANGE * 3) >> 2)) // 0x600 + ch->xenvx += (ENV_RANGE >> 8); // 1/256 + else + ch->xenvx += (ENV_RANGE >> 6); // 1/64 + + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx > ENV_MAX) + { + ch->xenvx = ENV_MAX; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, 0); + } + + break; + + case SOUND_DECREASE_LINEAR: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= (ENV_RANGE >> 6); // 1/64 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + + break; + + case SOUND_DECREASE_EXPONENTIAL: + ch->xenv_count -= ch->xenv_rate; + while (ch->xenv_count <= 0) + { + ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 + ch->xenv_count += env_counter_max; + } + + if (ch->xenvx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + + break; + + case SOUND_GAIN: + S9xSetEnvRate (ch, 0, 0); + + break; + } + + ch->xsmp_count += mod1 ? (((int64) freq * (32768 + wave[I])) >> 15) : freq; + + while (ch->xsmp_count >= 0) + { + ch->xsmp_count -= FIXED_POINT; + ch->nb_sample[ch->nb_index] = ch->sample; + ch->nb_index = (ch->nb_index + 1) & 3; + + ch->sample_pointer++; + if (ch->sample_pointer == SOUND_DECODE_LENGTH) + { + ch->sample_pointer = 0; + + if (ch->last_block) + { + S9xAPUSetEndX (J); + if (!ch->loop) + { + ch->xenvx = 0; + last_block = TRUE; + //S9xAPUSetEndOfSample (J, ch); + while (ch->xsmp_count >= 0) + { + ch->xsmp_count -= FIXED_POINT; + ch->nb_sample[ch->nb_index] = 0; + ch->nb_index = (ch->nb_index + 1) & 3; + } + + break; + } + else + { + ch->last_block = FALSE; + uint8 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = READ_WORD(dir + 2); // loop pointer + } + } + + DecodeBlock (ch); + } + + ch->sample = ch->block[ch->sample_pointer]; + } + + int32 outx, d; + + if (ch->type == SOUND_SAMPLE) + { + if (Settings.InterpolatedSound) + { + // 4-point gaussian interpolation + d = ch->xsmp_count >> (FIXED_POINT_SHIFT - 8); + outx = ((G4(-d) * ch->nb_sample[ ch->nb_index ]) >> 11) & ~1; + outx += ((G3(-d) * ch->nb_sample[(ch->nb_index + 1) & 3]) >> 11) & ~1; + outx += ((G2( d) * ch->nb_sample[(ch->nb_index + 2) & 3]) >> 11) & ~1; + outx = ((outx & 0xFFFF) ^ 0x8000) - 0x8000; + outx += ((G1( d) * ch->nb_sample[(ch->nb_index + 3) & 3]) >> 11) & ~1; + CLIP16(outx); + } + else + outx = ch->sample; + } + else // SAMPLE_NOISE + { + noise_count -= SoundData.noise_rate; + while (noise_count <= 0) + { + noise_count += env_counter_max; + noise_index = (noise_index + 1) & 0xFF; + } + + outx = noise_cache[noise_index] >> 16; + } + + outx = ((outx * ch->xenvx) >> 11) & ~1; + ch->out_sample = outx; + + if (mod2) + wave[I] = outx; + + int32 V; + + V = (outx * ch->volume_left ) >> 7; + + MixBuffer[I] += V; + ch->echo_buf_ptr[I] += V; + } + + mono_exit: ; + } + DoFakeMute=FALSE; + + if (APU.DSP[APU_NON]) + SoundData.noise_count = noise_count; +} + +#ifdef __DJGPP +END_OF_FUNCTION(MixMono); +#endif + +#ifdef __sun +extern uint8 int2ulaw (int); +#endif + +// For backwards compatibility with older port specific code +void S9xMixSamplesO (uint8 *buffer, int sample_count, int byte_offset) +{ + S9xMixSamples (buffer+byte_offset, sample_count); +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xMixSamplesO); +#endif + +void S9xMixSamples (uint8 *buffer, int sample_count) +{ + int I, J; + + if (!so.mute_sound) + { + memset (MixBuffer, 0, sample_count * sizeof (MixBuffer[0])); + if (!Settings.DisableSoundEcho) + memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer[0])); + + if (so.stereo) + MixStereo (sample_count); + else + MixMono (sample_count); + } + + /* Mix and convert waveforms */ + if (so.sixteen_bit) + { + // 16-bit sound + if (so.mute_sound) + memset (buffer, 0, sample_count << 1); + else + { + if (!Settings.DisableSoundEcho) + { + if (so.stereo) + { + // 16-bit stereo sound with echo enabled ... + if (SoundData.no_filter) + { + // ... but no filter defined. + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 15] = E; + E = (E * 127) >> 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + + E * SoundData.echo_volume[J & 1]) >> 7; + CLIP16(I); + ((int16 *) buffer) [J] = I; + } + } + else + { + // ... with filter defined. + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 15] = E; + E = E * FilterTaps[0]; + E += Loop[(FIRIndex - 2) & 15] * FilterTaps[1]; + E += Loop[(FIRIndex - 4) & 15] * FilterTaps[2]; + E += Loop[(FIRIndex - 6) & 15] * FilterTaps[3]; + E += Loop[(FIRIndex - 8) & 15] * FilterTaps[4]; + E += Loop[(FIRIndex - 10) & 15] * FilterTaps[5]; + E += Loop[(FIRIndex - 12) & 15] * FilterTaps[6]; + E += Loop[(FIRIndex - 14) & 15] * FilterTaps[7]; + E >>= 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + + E * SoundData.echo_volume[J & 1]) >> 7; + CLIP16(I); + ((int16 *) buffer) [J] = I; + } + } + } + else + { + // 16-bit mono sound with echo enabled... + if (SoundData.no_filter) + { + // ... no filter defined + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 7] = E; + E = (E * 127) >> 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[0] + + E * SoundData.echo_volume[0]) >> 7; + CLIP16(I); + ((int16 *) buffer) [J] = I; + } + } + else + { + // ... with filter defined + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 7] = E; + E = E * FilterTaps[0]; + E += Loop[(FIRIndex - 1) & 7] * FilterTaps[1]; + E += Loop[(FIRIndex - 2) & 7] * FilterTaps[2]; + E += Loop[(FIRIndex - 3) & 7] * FilterTaps[3]; + E += Loop[(FIRIndex - 4) & 7] * FilterTaps[4]; + E += Loop[(FIRIndex - 5) & 7] * FilterTaps[5]; + E += Loop[(FIRIndex - 6) & 7] * FilterTaps[6]; + E += Loop[(FIRIndex - 7) & 7] * FilterTaps[7]; + E >>= 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[0] + + E * SoundData.echo_volume[0]) >> 7; + CLIP16(I); + ((int16 *) buffer) [J] = I; + } + } + } + } + else + { + // 16-bit mono or stereo sound, no echo + for (J = 0; J < sample_count; J++) + { + I = (MixBuffer[J] * SoundData.master_volume[J & 1]) >> 7; + CLIP16(I); + ((int16 *) buffer) [J] = I; + } + } + } + } + else + { + // 8-bit sound + if (so.mute_sound) + memset (buffer, 128, sample_count); + else + #ifdef __sun + if (so.encoded) + { + for (J = 0; J < sample_count; J++) + { + I = (MixBuffer[J] * SoundData.master_volume[0]) >> 7; + CLIP16(I); + buffer[J] = int2ulaw (I); + } + } + else + #endif + { + if (!Settings.DisableSoundEcho) + { + if (so.stereo) + { + // 8-bit stereo sound with echo enabled... + if (SoundData.no_filter) + { + // ... but no filter + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 15] = E; + E = (E * 127) >> 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + + E * SoundData.echo_volume[J & 1]) >> 15; + CLIP8(I); + buffer[J] = I + 128; + } + } + else + { + // ... with filter + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 15] = E; + E = E * FilterTaps[0]; + E += Loop[(FIRIndex - 2) & 15] * FilterTaps[1]; + E += Loop[(FIRIndex - 4) & 15] * FilterTaps[2]; + E += Loop[(FIRIndex - 6) & 15] * FilterTaps[3]; + E += Loop[(FIRIndex - 8) & 15] * FilterTaps[4]; + E += Loop[(FIRIndex - 10) & 15] * FilterTaps[5]; + E += Loop[(FIRIndex - 12) & 15] * FilterTaps[6]; + E += Loop[(FIRIndex - 14) & 15] * FilterTaps[7]; + E >>= 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + + E * SoundData.echo_volume[J & 1]) >> 15; + CLIP8(I); + buffer[J] = I + 128; + } + } + } + else + { + // 8-bit mono sound with echo enabled... + if (SoundData.no_filter) + { + // ... but no filter. + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 7] = E; + E = (E * 127) >> 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[0] + + E * SoundData.echo_volume[0]) >> 15; + CLIP8(I); + buffer[J] = I + 128; + } + } + else + { + // ... with filter. + for (J = 0; J < sample_count; J++) + { + int E = Echo[SoundData.echo_ptr]; + + Loop[FIRIndex & 7] = E; + E = E * FilterTaps[0]; + E += Loop[(FIRIndex - 1) & 7] * FilterTaps[1]; + E += Loop[(FIRIndex - 2) & 7] * FilterTaps[2]; + E += Loop[(FIRIndex - 3) & 7] * FilterTaps[3]; + E += Loop[(FIRIndex - 4) & 7] * FilterTaps[4]; + E += Loop[(FIRIndex - 5) & 7] * FilterTaps[5]; + E += Loop[(FIRIndex - 6) & 7] * FilterTaps[6]; + E += Loop[(FIRIndex - 7) & 7] * FilterTaps[7]; + E >>= 7; + FIRIndex++; + + if (SoundData.echo_write_enabled) + { + I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); + CLIP16(I); + Echo[SoundData.echo_ptr] = I; + } + else // FIXME: Snes9x's echo buffer is not in APU_RAM + Echo[SoundData.echo_ptr] = 0; + + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * SoundData.master_volume[0] + + E * SoundData.echo_volume[0]) >> 15; + CLIP8(I); + buffer[J] = I + 128; + } + } + } + } + else + { + // 8-bit mono or stereo sound, no echo + for (J = 0; J < sample_count; J++) + { + I = (MixBuffer[J] * SoundData.master_volume[J & 1]) >> 15; + CLIP8(I); + buffer[J] = I + 128; + } + } + } + } +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xMixSamples); +#endif + +void S9xResetSound (bool8 full) +{ + for (int i = 0; i < NUM_CHANNELS; i++) + { + SoundData.channels[i].state = SOUND_SILENT; + SoundData.channels[i].mode = MODE_NONE; + SoundData.channels[i].type = SOUND_SAMPLE; + SoundData.channels[i].volume_left = 0; + SoundData.channels[i].volume_right = 0; + SoundData.channels[i].hertz = 0; + SoundData.channels[i].loop = FALSE; + SoundData.channels[i].xsmp_count = 0; + SoundData.channels[i].xenvx = 0; + SoundData.channels[i].xenvx_target = 0; + SoundData.channels[i].xenv_count = 0; + SoundData.channels[i].xenv_rate = 0; + SoundData.channels[i].xattack_rate = 0; + SoundData.channels[i].xdecay_rate = 0; + SoundData.channels[i].xsustain_rate = 0; + SoundData.channels[i].xsustain_level = 0; + if(full) + { + SoundData.channels[i].out_sample = 0; + SoundData.channels[i].block_pointer = 0; + SoundData.channels[i].sample_pointer = 0; + SoundData.channels[i].sample = 0; + SoundData.channels[i].sample_number = 0; + SoundData.channels[i].last_block = 0; + for(int j = 0 ; j < 2 ; j++) SoundData.channels[i].previous[j] = 0; + for(int j = 0 ; j < 2 ; j++) SoundData.channels[i].previous16[j] = 0; + for(int j = 0 ; j < 16 ; j++) SoundData.channels[i].decoded[j] = 0; + } + } + + FilterTaps [0] = 127; + FilterTaps [1] = 0; + FilterTaps [2] = 0; + FilterTaps [3] = 0; + FilterTaps [4] = 0; + FilterTaps [5] = 0; + FilterTaps [6] = 0; + FilterTaps [7] = 0; + + rand_seed = 1; + + so.mute_sound = TRUE; + so.noise_gen = 1; + so.sound_switch = 255; + so.stereo_switch = ~0; + so.samples_mixed_so_far = 0; + so.play_position = 0; + so.err_counter = 0; + + if (full) + { + SoundData.echo_volume_left = 0; + SoundData.echo_volume_right = 0; + SoundData.echo_enable = 0; + SoundData.echo_write_enabled = 0; + SoundData.pitch_mod = 0; + SoundData.dummy[0] = 0; + SoundData.dummy[1] = 0; + SoundData.dummy[2] = 0; + SoundData.echo_volume[0] = 0; + SoundData.echo_volume[1] = 0; + SoundData.noise_count = 0; + SoundData.noise_rate = 0; + memset (Loop, 0, sizeof (Loop)); + memset (Echo, 0, sizeof (Echo)); + } + + // At least Super Bomberman 2 requires the defaule master volume is not zero. +#if 1 + SoundData.master_volume_left = 127; + SoundData.master_volume_right = 127; + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; +#else + SoundData.master_volume_left = 0; + SoundData.master_volume_right = 0; + SoundData.master_volume [0] = SoundData.master_volume [1] = 0; +#endif + SoundData.no_filter = TRUE; + SoundData.echo_ptr = 0; + SoundData.echo_feedback = 0; + SoundData.echo_buffer_size = 1; + + if (so.playback_rate) + so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME * so.playback_rate); + else + so.err_rate = 0; +} + +void S9xSetPlaybackRate (uint32 playback_rate) +{ + if (playback_rate > 48000) + playback_rate = 48000; + + so.playback_rate = playback_rate; + so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME * so.playback_rate); + + memset (Loop, 0, sizeof (Loop)); + memset (Echo, 0, sizeof (Echo)); + S9xSetEchoDelay (APU.DSP[APU_EDL] & 0xF); + + for (int i = 0; i < NUM_CHANNELS; i++) + S9xSetSoundFrequency (i, SoundData.channels[i].hertz); + + env_counter_max = env_counter_max_master * playback_rate / 32000; + SoundData.noise_count = env_counter_max; +} + +bool8 S9xInitSound (int mode, bool8 stereo, int buffer_size) +{ + so.sound_fd = -1; + so.sound_switch = 255; + so.stereo_switch = ~0; + + so.playback_rate = 0; + so.buffer_size = 0; + so.stereo = stereo; + so.sixteen_bit = Settings.SixteenBitSound; + so.encoded = FALSE; + so.pitch_mul = 0.985; // XXX: necessary for most cards in linux...? + + S9xResetSound (TRUE); + + if (!(mode & 7)) + return (1); + + S9xSetSoundMute (TRUE); + if (!S9xOpenSoundDevice (mode, stereo, buffer_size)) + { + #ifdef NOSOUND + S9xMessage (S9X_WARNING, S9X_SOUND_NOT_BUILT, + "No sound support compiled in"); + #else + S9xMessage (S9X_ERROR, S9X_SOUND_DEVICE_OPEN_FAILED, + "Sound device open failed"); + #endif + return (0); + } + + return (1); +} + +bool8 S9xSetSoundMode (int channel, int mode) +{ + Channel *ch = &SoundData.channels[channel]; + + switch (mode) + { + case MODE_RELEASE: + if (ch->mode != MODE_NONE) + { + ch->mode = MODE_RELEASE; + return (TRUE); + } + break; + + case MODE_DECREASE_LINEAR: + case MODE_DECREASE_EXPONENTIAL: + case MODE_GAIN: + if (ch->mode != MODE_RELEASE) + { + ch->mode = mode; + if (ch->state != SOUND_SILENT) + ch->state = mode; + + return (TRUE); + } + break; + + case MODE_INCREASE_LINEAR: + case MODE_INCREASE_BENT_LINE: + if (ch->mode != MODE_RELEASE) + { + ch->mode = mode; + if (ch->state != SOUND_SILENT) + ch->state = mode; + + return (TRUE); + } + break; + + case MODE_ADSR: + if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR) + { + ch->mode = mode; + return (TRUE); + } + } + + return (FALSE); +} + +void S9xSetSoundControl (int sound_switch) +{ + so.sound_switch = sound_switch; +} + +void S9xPlaySample (int channel) +{ + Channel *ch = &SoundData.channels[channel]; + + ch->state = SOUND_SILENT; + ch->mode = MODE_NONE; + ch->xenvx = 0; + + S9xFixEnvelope (channel, + APU.DSP[APU_GAIN + (channel << 4)], + APU.DSP[APU_ADSR1 + (channel << 4)], + APU.DSP[APU_ADSR2 + (channel << 4)]); + + ch->sample_number = APU.DSP[APU_SRCN + channel * 0x10]; + if (APU.DSP[APU_NON] & (1 << channel)) + ch->type = SOUND_NOISE; + else + ch->type = SOUND_SAMPLE; + + S9xSetSoundFrequency (channel, ch->hertz); + ch->loop = FALSE; + ch->needs_decode = TRUE; + ch->last_block = FALSE; + ch->previous[0] = ch->previous[1] = 0; + uint8 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = READ_WORD (dir); + ch->sample_pointer = 0; + ch->xenv_count = env_counter_max; + ch->xsmp_count = 3 * FIXED_POINT; // since gaussian interpolation uses 4 points + ch->nb_sample[0] = 0; + ch->nb_sample[1] = 0; + ch->nb_sample[2] = 0; + ch->nb_sample[3] = 0; + ch->nb_index = 0; + + switch (ch->mode) + { + case MODE_ADSR: // FIXME: rapid attack + #if 0 + ch->state = SOUND_ATTACK; + ch->xenvx = 0; + S9xSetEnvRate (ch, ch->xattack_rate, ENV_MAX); + break; + #else + if (ch->xattack_rate == env_counter_max_master) + { + ch->xenvx = ENV_MAX; + if (ch->xsustain_level == ENV_RANGE) + { + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->xsustain_rate, 0); + } + else + { + ch->state = SOUND_DECAY; + S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); + } + } + else + { + ch->state = SOUND_ATTACK; + ch->xenvx = 0; + S9xSetEnvRate (ch, ch->xattack_rate, ENV_MAX); + } + + break; + #endif + + case MODE_GAIN: + ch->state = SOUND_GAIN; + break; + + case MODE_INCREASE_LINEAR: + ch->state = SOUND_INCREASE_LINEAR; + break; + + case MODE_INCREASE_BENT_LINE: + ch->state = SOUND_INCREASE_BENT_LINE; + break; + + case MODE_DECREASE_LINEAR: + ch->state = SOUND_DECREASE_LINEAR; + break; + + case MODE_DECREASE_EXPONENTIAL: + ch->state = SOUND_DECREASE_EXPONENTIAL; + break; + + default: + break; + } + + S9xFixEnvelope (channel, + APU.DSP[APU_GAIN + (channel << 4)], + APU.DSP[APU_ADSR1 + (channel << 4)], + APU.DSP[APU_ADSR2 + (channel << 4)]); +} diff --git a/source/snes9x/soundux.h b/source/snes9x/soundux.h new file mode 100644 index 0000000..1357061 --- /dev/null +++ b/source/snes9x/soundux.h @@ -0,0 +1,352 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#ifndef _SOUND_H_ +#define _SOUND_H_ + +enum +{ + SOUND_SAMPLE = 0, + SOUND_NOISE +}; + +enum +{ + SOUND_SILENT, + SOUND_ATTACK, + SOUND_DECAY, + SOUND_SUSTAIN, + SOUND_RELEASE, + SOUND_GAIN, + SOUND_INCREASE_LINEAR, + SOUND_INCREASE_BENT_LINE, + SOUND_DECREASE_LINEAR, + SOUND_DECREASE_EXPONENTIAL +}; + +enum +{ + MODE_NONE = SOUND_SILENT, + MODE_ADSR, + MODE_RELEASE = SOUND_RELEASE, + MODE_GAIN, + MODE_INCREASE_LINEAR, + MODE_INCREASE_BENT_LINE, + MODE_DECREASE_LINEAR, + MODE_DECREASE_EXPONENTIAL +}; + +#define NUM_CHANNELS 8 +#define SOUND_DECODE_LENGTH 16 +#define SOUND_BUFFER_SIZE (1024 * 16) +#define MAX_BUFFER_SIZE SOUND_BUFFER_SIZE +#define SOUND_BUFFER_SIZE_MASK (SOUND_BUFFER_SIZE - 1) + +#define ENV_RANGE 0x800 +#define ENV_MAX 0x7FF +#define ENV_SHIFT 4 + +#ifdef __sgi +#include +#endif /* __sgi */ + +typedef struct { + int sound_fd; // ** port specific + int sound_switch; // channel on/off + int playback_rate; // 32000Hz is recommended + int buffer_size; // ** port specific + int noise_gen; // ** unused + bool8 mute_sound; // mute + int stereo; // stereo or mono + bool8 sixteen_bit; // 16bit or 8bit sample + bool8 encoded; // ** port specific +#ifdef __sun + int last_eof; // ** port specific +#endif +#ifdef __sgi + ALport al_port; // ** port specific +#endif /* __sgi */ + int32 samples_mixed_so_far; // ** port specific + int32 play_position; // ** port specific + uint32 err_counter; // ** port specific + uint32 err_rate; // ** port specific + + uint16 stereo_switch; // stereo channel on/off + double pitch_mul; // used with Settings.FixFrequency +} SoundStatus; + +EXTERN_C volatile SoundStatus so; + +typedef struct { + int32 state; // ADSR/GAIN/RELEASE/SILENT + int32 type; // sample or noise + short volume_left; // VOL(L) + short volume_right; // VOL(R) + uint32 hertz; // ((P(H) << 8) + P(L)) * 8 + uint32 frequency; // normalized pitch + uint32 count; // ** unused + bool8 loop; // loop flag in BRR header + int32 envx; // ** unused + short left_vol_level; // ** unused + short right_vol_level; // ** unused + short envx_target; // ** unused + uint32 env_error; // ** unused + uint32 erate; // ** unused + int32 direction; // ** unused + uint32 attack_rate; // ** unused + uint32 decay_rate; // ** unused + uint32 sustain_rate; // ** unused + uint32 release_rate; // ** unused + uint32 sustain_level; // ** unused + signed short sample; // signed 16 bit sample + signed short decoded[16]; // decoded 16 samples + signed short previous16[2]; + signed short *block; + uint16 sample_number; // SRCN + bool8 last_block; // end flag in BRR header + bool8 needs_decode; // true when BRR block will be decoded + uint32 block_pointer; // currect block + uint32 sample_pointer; // pointer in a block + int32 *echo_buf_ptr; // EchoBuffer[] or DummyEchoBuffer[] + int32 mode; // ADSR/GAIN/RELEASE/SILENT + int32 envxx; // ** unused + signed short next_sample; // ** unused + int32 interpolate; // ** unused + int32 previous[2]; // last two nybbles for BRR decode + uint32 dummy[8]; // Just incase they are needed in the future, + // for snapshot compatibility. + + int32 nb_index; // index of cached samples + int16 nb_sample[4]; // cached samples for interpolation + int16 out_sample; // OUTX << 4 + int32 xenvx; // ENVX << 4 + int32 xenvx_target; // ENVX target << 4 + int32 xenv_count; // counter for envelope timing + int32 xenv_rate; // envelope timing from env_counter_table + int32 xsmp_count; // counter for pitch + int32 xattack_rate; // envelope timing from env_counter_table + int32 xdecay_rate; // envelope timing from env_counter_table + int32 xsustain_rate; // envelope timing from env_counter_table + int32 xsustain_level; // (128 / 8 * (SR + 1)) << 4 +} Channel; + +typedef struct +{ + short master_volume_left; // MVOL(L) + short master_volume_right; // MVOL(R) + short echo_volume_left; // EVOL(L) + short echo_volume_right; // EVOL(R) + int32 echo_enable; // EON + int32 echo_feedback; // EFB + int32 echo_ptr; // index of Echo[] + int32 echo_buffer_size; // num of echo samples + int32 echo_write_enabled; // ECEN + int32 echo_channel_enable; // ** unused + int32 pitch_mod; // PMOD + uint32 dummy[3]; // Just incase they are needed in the future, + // for snapshot compatibility. + Channel channels[NUM_CHANNELS]; + bool8 no_filter; // true when simple echo + int32 master_volume[2]; + int32 echo_volume[2]; + int32 noise_hertz; // ** unused + + int32 noise_count; // counter for noise frequency + int32 noise_rate; // noise frequency from env_counter_table +} SSoundData; + +EXTERN_C SSoundData SoundData; + + +void S9xSetEnvelopeRate (int channel, int32 rate_count, int32 xtarget); +void S9xSetSoundVolume (int channel, short volume_left, short volume_right); +void S9xSetMasterVolume (short volume_left, short volume_right); +void S9xSetEchoVolume (short volume_left, short volume_right); +void S9xSetEchoEnable (uint8 byte); +void S9xSetEchoFeedback (int echo_feedback); +void S9xSetEchoDelay (unsigned int byte); +void S9xSetEchoWriteEnable (uint8 byte); +void S9xSetFrequencyModulationEnable (uint8 byte); +void S9xSetSoundKeyOff (int channel); +void S9xPrepareSoundForSnapshotSave (bool8 restore); +void S9xFixSoundAfterSnapshotLoad (int version); +void S9xSetFilterCoefficient (int tap, int value); +void S9xSetSoundADSR (int channel, int ar, int dr, int sr, int sl); +void S9xSetEnvelopeHeight (int channel, int32 xlevel); +uint8 S9xGetEnvelopeHeight (int channel); +void S9xSetSoundHertz (int channel, int hertz); +void S9xSetSoundType (int channel, int type_of_sound); +bool8 S9xSetSoundMute (bool8 mute); +void S9xResetSound (bool8 full); +void S9xSetPlaybackRate (uint32 playback_rate); +bool8 S9xSetSoundMode (int channel, int mode); +void S9xSetSoundControl (int sound_switch); +void S9xPlaySample (int channel); + +void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2); +bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size); + +EXTERN_C void S9xMixSamples (uint8 *buffer, int sample_count); +EXTERN_C void S9xMixSamplesO (uint8 *buffer, int sample_count, int byte_offset); + +#endif diff --git a/source/snes9x/spc700.cpp b/source/snes9x/spc700.cpp new file mode 100644 index 0000000..abbf360 --- /dev/null +++ b/source/snes9x/spc700.cpp @@ -0,0 +1,2650 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + +#include "snes9x.h" +#include "spc700.h" +#include "memmap.h" +#include "display.h" +#include "cpuexec.h" +#include "apu.h" + +// SPC700/Sound DSP chips have a 24.57MHz crystal on their PCB. + +#ifdef NO_INLINE_SET_GET +uint8 S9xAPUGetByteZ (uint8 address); +uint8 S9xAPUGetByte (uint32 address); +void S9xAPUSetByteZ (uint8, uint8 address); +void S9xAPUSetByte (uint8, uint32 address); + +#else +#undef INLINE +#define INLINE inline +#include "apumem.h" +#endif + +START_EXTERN_C +// XXX: FIXME: Rewrite APU core to not use global variables +uint8 Work8; +uint16 Work16; +uint32 Work32; +int8 Int8; +int16 Int16; +int32 Int32; +uint8 W1; +uint8 W2; + +END_EXTERN_C + +#define OP1 (*(IAPU.PC + 1)) +#define OP2 (*(IAPU.PC + 2)) + +#ifdef SPC700_SHUTDOWN +#define APUShutdown() \ +if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ +{ \ + if (IAPU.WaitCounter == 0) \ + { \ + if (!ICPU.CPUExecuting) \ + S9xAPUExecute(); \ + else \ + IAPU.APUExecuting = FALSE; \ + } \ + else \ + if (IAPU.WaitCounter >= 2) \ + IAPU.WaitCounter = 1; \ + else \ + IAPU.WaitCounter--; \ +} +#else +#define APUShutdown() +#endif + +#define APUSetZN8(b)\ + IAPU._Zero = (b); + +#define APUSetZN16(w)\ + IAPU._Zero = ((w) != 0) | ((w) >> 8); + +void WARN (char *s) +{ + char buffer[100]; + +#ifdef DEBUGGER + S9xAPUOPrint (buffer, IAPU.PC - IAPU.RAM); +#endif + + sprintf (String, "Sound CPU executing %s at %04X\n%s\n", s, (uint32) (IAPU.PC - IAPU.RAM), buffer); + S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String); +} + +void STOP (char *s) +{ + WARN(s); + APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; + IAPU.APUExecuting = FALSE; + Settings.APUEnabled = FALSE; // re-enabled on next APU reset +#ifdef DEBUGGER + CPU.Flags |= DEBUG_MODE_FLAG; +#else + S9xExit (); +#endif +} + +#define TCALL(n)\ +{\ + PushW (IAPU.PC - IAPU.RAM + 1); \ + IAPU.PC = IAPU.RAM + S9xAPUGetByte(0xffc0 + ((15 - n) << 1)) + \ + (S9xAPUGetByte(0xffc1 + ((15 - n) << 1)) << 8); \ +} + +#define SBC(a,b)\ +Int16 = (short) (a) - (short) (b) + (short) (APUCheckCarry ()) - 1;\ +IAPU._Carry = Int16 >= 0;\ +if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8) Int16) & 0x80))\ + APUSetOverflow ();\ +else \ + APUClearOverflow (); \ +APUSetHalfCarry ();\ +if(((a) ^ (b) ^ (uint8) Int16) & 0x10)\ + APUClearHalfCarry ();\ +(a) = (uint8) Int16;\ +APUSetZN8 ((uint8) Int16); + +#define ADC(a,b)\ +Work16 = (a) + (b) + APUCheckCarry();\ +IAPU._Carry = Work16 >= 0x100; \ +if (~((a) ^ (b)) & ((b) ^ (uint8) Work16) & 0x80)\ + APUSetOverflow ();\ +else \ + APUClearOverflow (); \ +APUClearHalfCarry ();\ +if(((a) ^ (b) ^ (uint8) Work16) & 0x10)\ + APUSetHalfCarry ();\ +(a) = (uint8) Work16;\ +APUSetZN8 ((uint8) Work16); + +#define CMP(a,b)\ +Int16 = (short) (a) - (short) (b);\ +IAPU._Carry = Int16 >= 0;\ +APUSetZN8 ((uint8) Int16); + +#define ASL(b)\ + IAPU._Carry = ((b) & 0x80) != 0; \ + (b) <<= 1;\ + APUSetZN8 (b); +#define LSR(b)\ + IAPU._Carry = (b) & 1;\ + (b) >>= 1;\ + APUSetZN8 (b); +#define ROL(b)\ + Work16 = ((b) << 1) | APUCheckCarry (); \ + IAPU._Carry = Work16 >= 0x100; \ + (b) = (uint8) Work16; \ + APUSetZN8 (b); +#define ROR(b)\ + Work16 = (b) | ((uint16) APUCheckCarry () << 8); \ + IAPU._Carry = (uint8) Work16 & 1; \ + Work16 >>= 1; \ + (b) = (uint8) Work16; \ + APUSetZN8 (b); + +#define Push(b)\ + *(IAPU.RAM + 0x100 + APURegisters.S) = b;\ + APURegisters.S--; + +#define Pop(b)\ + APURegisters.S++;\ + (b) = *(IAPU.RAM + 0x100 + APURegisters.S); + +#ifdef FAST_LSB_WORD_ACCESS +#define PushW(w)\ + if(APURegisters.S==0){ \ + *(IAPU.RAM + 0x1ff) = (w);\ + *(IAPU.RAM + 0x100) = ((w) >> 8);\ + } else { \ + *(uint16 *) (IAPU.RAM + 0xff + APURegisters.S) = (w);\ + } \ + APURegisters.S -= 2; +#define PopW(w)\ + APURegisters.S += 2;\ + if(APURegisters.S==0){ \ + (w) = *(IAPU.RAM + 0x1ff) | (*(IAPU.RAM + 0x100)<<8);\ + } else { \ + (w) = *(uint16 *) (IAPU.RAM + 0xff + APURegisters.S); \ + } +#else +#define PushW(w)\ + *(IAPU.RAM + 0x100 + APURegisters.S--) = ((w) >> 8);\ + *(IAPU.RAM + 0x100 + APURegisters.S--) = (w); +#define PopW(w)\ + APURegisters.S += 2;\ + if(APURegisters.S==0){ \ + (w) = *(IAPU.RAM + 0x1ff) | (*(IAPU.RAM + 0x100)<<8);\ + } else { \ + (w) = *(IAPU.RAM + 0xff + APURegisters.S) + (*(IAPU.RAM + 0x100 + APURegisters.S) << 8); \ + } +#endif + +#define Relative()\ + Int8 = OP1;\ + Int16 = (int32) (IAPU.PC + 2 - IAPU.RAM) + Int8; + +#define Relative2()\ + Int8 = OP2;\ + Int16 = (int32) (IAPU.PC + 3 - IAPU.RAM) + Int8; + +#ifdef FAST_LSB_WORD_ACCESS +#define IndexedXIndirect()\ + IAPU.Address = *(uint16 *) (IAPU.DirectPage + ((OP1 + APURegisters.X) & 0xff)); + +#define Absolute()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1); + +#define AbsoluteX()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1) + APURegisters.X; + +#define AbsoluteY()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1) + APURegisters.YA.B.Y; + +#define MemBit()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1);\ + IAPU.Bit = (uint8)(IAPU.Address >> 13);\ + IAPU.Address &= 0x1fff; + +#define IndirectIndexedY()\ + IAPU.Address = *(uint16 *) (IAPU.DirectPage + OP1) + APURegisters.YA.B.Y; +#else +#define IndexedXIndirect()\ + IAPU.Address = *(IAPU.DirectPage + ((OP1 + APURegisters.X) & 0xff)) + \ + (*(IAPU.DirectPage + ((OP1 + APURegisters.X + 1) & 0xff)) << 8); +#define Absolute()\ + IAPU.Address = OP1 + (OP2 << 8); + +#define AbsoluteX()\ + IAPU.Address = OP1 + (OP2 << 8) + APURegisters.X; + +#define AbsoluteY()\ + IAPU.Address = OP1 + (OP2 << 8) + APURegisters.YA.B.Y; + +#define MemBit()\ + IAPU.Address = OP1 + (OP2 << 8);\ + IAPU.Bit = (int8) (IAPU.Address >> 13);\ + IAPU.Address &= 0x1fff; + +#define IndirectIndexedY()\ + IAPU.Address = *(IAPU.DirectPage + OP1) + \ + (*(IAPU.DirectPage + OP1 + 1) << 8) + \ + APURegisters.YA.B.Y; +#endif + +void Apu00 () +{ +// NOP + IAPU.PC++; +} + +void Apu01 () { TCALL (0) } + +void Apu11 () { TCALL (1) } + +void Apu21 () { TCALL (2) } + +void Apu31 () { TCALL (3) } + +void Apu41 () { TCALL (4) } + +void Apu51 () { TCALL (5) } + +void Apu61 () { TCALL (6) } + +void Apu71 () { TCALL (7) } + +void Apu81 () { TCALL (8) } + +void Apu91 () { TCALL (9) } + +void ApuA1 () { TCALL (10) } + +void ApuB1 () { TCALL (11) } + +void ApuC1 () { TCALL (12) } + +void ApuD1 () { TCALL (13) } + +void ApuE1 () { TCALL (14) } + +void ApuF1 () { TCALL (15) } + +void Apu3F () // CALL absolute +{ + Absolute (); + // 0xB6f for Star Fox 2 + PushW (IAPU.PC + 3 - IAPU.RAM); + IAPU.PC = IAPU.RAM + IAPU.Address; +} + +void Apu4F () // PCALL $XX +{ + Work8 = OP1; + PushW (IAPU.PC + 2 - IAPU.RAM); + IAPU.PC = IAPU.RAM + 0xff00 + Work8; +} + +#define SET(b) \ +S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1 ) | (1 << (b))), OP1); \ +IAPU.PC += 2 + +void Apu02 () +{ + SET (0); +} + +void Apu22 () +{ + SET (1); +} + +void Apu42 () +{ + SET (2); +} + +void Apu62 () +{ + SET (3); +} + +void Apu82 () +{ + SET (4); +} + +void ApuA2 () +{ + SET (5); +} + +void ApuC2 () +{ + SET (6); +} + +void ApuE2 () +{ + SET (7); +} + +#define CLR(b) \ +S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1) & ~(1 << (b))), OP1); \ +IAPU.PC += 2; + +void Apu12 () +{ + CLR (0); +} + +void Apu32 () +{ + CLR (1); +} + +void Apu52 () +{ + CLR (2); +} + +void Apu72 () +{ + CLR (3); +} + +void Apu92 () +{ + CLR (4); +} + +void ApuB2 () +{ + CLR (5); +} + +void ApuD2 () +{ + CLR (6); +} + +void ApuF2 () +{ + CLR (7); +} + +#define BBS(b) \ +Work8 = OP1; \ +Relative2 (); \ +if (S9xAPUGetByteZ (Work8) & (1 << (b))) \ +{ \ + IAPU.PC = IAPU.RAM + (uint16) Int16; \ + APU.Cycles += IAPU.TwoCycles; \ +} \ +else \ + IAPU.PC += 3 + +void Apu03 () +{ + BBS (0); +} + +void Apu23 () +{ + BBS (1); +} + +void Apu43 () +{ + BBS (2); +} + +void Apu63 () +{ + BBS (3); +} + +void Apu83 () +{ + BBS (4); +} + +void ApuA3 () +{ + BBS (5); +} + +void ApuC3 () +{ + BBS (6); +} + +void ApuE3 () +{ + BBS (7); +} + +#define BBC(b) \ +Work8 = OP1; \ +Relative2 (); \ +if (!(S9xAPUGetByteZ (Work8) & (1 << (b)))) \ +{ \ + IAPU.PC = IAPU.RAM + (uint16) Int16; \ + APU.Cycles += IAPU.TwoCycles; \ +} \ +else \ + IAPU.PC += 3 + +void Apu13 () +{ + BBC (0); +} + +void Apu33 () +{ + BBC (1); +} + +void Apu53 () +{ + BBC (2); +} + +void Apu73 () +{ + BBC (3); +} + +void Apu93 () +{ + BBC (4); +} + +void ApuB3 () +{ + BBC (5); +} + +void ApuD3 () +{ + BBC (6); +} + +void ApuF3 () +{ + BBC (7); +} + +void Apu04 () +{ +// OR A,dp + APURegisters.YA.B.A |= S9xAPUGetByteZ (OP1); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu05 () +{ +// OR A,abs + Absolute (); + APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu06 () +{ +// OR A,(X) + APURegisters.YA.B.A |= S9xAPUGetByteZ (APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu07 () +{ +// OR A,(dp+X) + IndexedXIndirect (); + APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu08 () +{ +// OR A,#00 + APURegisters.YA.B.A |= OP1; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu09 () +{ +// OR dp(dest),dp(src) + Work8 = S9xAPUGetByteZ (OP1); + Work8 |= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu14 () +{ +// OR A,dp+X + APURegisters.YA.B.A |= S9xAPUGetByteZ (OP1 + APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu15 () +{ +// OR A,abs+X + AbsoluteX (); + APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu16 () +{ +// OR A,abs+Y + AbsoluteY (); + APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu17 () +{ +// OR A,(dp)+Y + IndirectIndexedY (); + APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu18 () +{ +// OR dp,#00 + Work8 = OP1; + Work8 |= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu19 () +{ +// OR (X),(Y) + Work8 = S9xAPUGetByteZ (APURegisters.X) | S9xAPUGetByteZ (APURegisters.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, APURegisters.X); + IAPU.PC++; +} + +void Apu0A () +{ +// OR1 C,membit + MemBit (); + if (!APUCheckCarry ()) + { + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUSetCarry (); + } + IAPU.PC += 3; +} + +void Apu2A () +{ +// OR1 C,not membit + MemBit (); + if (!APUCheckCarry ()) + { + if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) + APUSetCarry (); + } + IAPU.PC += 3; +} + +void Apu4A () +{ +// AND1 C,membit + MemBit (); + if (APUCheckCarry ()) + { + if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) + APUClearCarry (); + } + IAPU.PC += 3; +} + +void Apu6A () +{ +// AND1 C, not membit + MemBit (); + if (APUCheckCarry ()) + { + if ((S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) + APUClearCarry (); + } + IAPU.PC += 3; +} + +void Apu8A () +{ +// EOR1 C, membit + MemBit (); + if (APUCheckCarry ()) + { + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUClearCarry (); + } + else + { + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUSetCarry (); + } + IAPU.PC += 3; +} + +void ApuAA () +{ +// MOV1 C,membit + MemBit (); + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUSetCarry (); + else + APUClearCarry (); + IAPU.PC += 3; +} + +void ApuCA () +{ +// MOV1 membit,C + MemBit (); + if (APUCheckCarry ()) + { + S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) | (1 << IAPU.Bit), IAPU.Address); + } + else + { + S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) & ~(1 << IAPU.Bit), IAPU.Address); + } + IAPU.PC += 3; +} + +void ApuEA () +{ +// NOT1 membit + MemBit (); + S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) ^ (1 << IAPU.Bit), IAPU.Address); + IAPU.PC += 3; +} + +void Apu0B () +{ +// ASL dp + Work8 = S9xAPUGetByteZ (OP1); + ASL (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu0C () +{ +// ASL abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + ASL (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu1B () +{ +// ASL dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + ASL (Work8); + S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); + IAPU.PC += 2; +} + +void Apu1C () +{ +// ASL A + ASL (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu0D () +{ +// PUSH PSW + S9xAPUPackStatus (); + Push (APURegisters.P); + IAPU.PC++; +} + +void Apu2D () +{ +// PUSH A + Push (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu4D () +{ +// PUSH X + Push (APURegisters.X); + IAPU.PC++; +} + +void Apu6D () +{ +// PUSH Y + Push (APURegisters.YA.B.Y); + IAPU.PC++; +} + +void Apu8E () +{ +// POP PSW + Pop (APURegisters.P); + S9xAPUUnpackStatus (); + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + IAPU.PC++; +} + +void ApuAE () +{ +// POP A + Pop (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuCE () +{ +// POP X + Pop (APURegisters.X); + IAPU.PC++; +} + +void ApuEE () +{ +// POP Y + Pop (APURegisters.YA.B.Y); + IAPU.PC++; +} + +void Apu0E () +{ +// TSET1 abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + S9xAPUSetByte (Work8 | APURegisters.YA.B.A, IAPU.Address); + Work8 = APURegisters.YA.B.A - Work8; + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu4E () +{ +// TCLR1 abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + S9xAPUSetByte (Work8 & ~APURegisters.YA.B.A, IAPU.Address); + Work8 = APURegisters.YA.B.A - Work8; + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu0F () +{ +// BRK + +#if 0 + STOP ("BRK"); +#else + PushW (IAPU.PC + 1 - IAPU.RAM); + S9xAPUPackStatus (); + Push (APURegisters.P); + APUSetBreak (); + APUClearInterrupt (); + IAPU.PC = IAPU.RAM + S9xAPUGetByte(0xffde) + (S9xAPUGetByte(0xffdf)<<8); +#endif +} + +void ApuEF () +{ +// SLEEP + if(!(APU.Flags & HALTED_FLAG)) WARN("SLEEP"); + APU.Flags |= HALTED_FLAG; + APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; + IAPU.APUExecuting = FALSE; +} + +void ApuFF () +{ +// STOP + if(!(APU.Flags & HALTED_FLAG)) WARN("STOP"); + APU.Flags |= HALTED_FLAG; + APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; + IAPU.APUExecuting = FALSE; + Settings.APUEnabled = FALSE; // re-enabled on next APU reset +} + +void Apu10 () +{ +// BPL + Relative (); + if (!APUCheckNegative ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void Apu30 () +{ +// BMI + Relative (); + if (APUCheckNegative ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void Apu90 () +{ +// BCC + Relative (); + if (!APUCheckCarry ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void ApuB0 () +{ +// BCS + Relative (); + if (APUCheckCarry ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void ApuD0 () +{ +// BNE + Relative (); + if (!APUCheckZero ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void ApuF0 () +{ +// BEQ + Relative (); + if (APUCheckZero ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void Apu50 () +{ +// BVC + Relative (); + if (!APUCheckOverflow ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu70 () +{ +// BVS + Relative (); + if (APUCheckOverflow ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu2F () +{ +// BRA + Relative (); + IAPU.PC = IAPU.RAM + (uint16) Int16; +} + +void Apu80 () +{ +// SETC + APUSetCarry (); + IAPU.PC++; +} + +void ApuED () +{ +// NOTC + IAPU._Carry ^= 1; + IAPU.PC++; +} + +void Apu40 () +{ +// SETP + APUSetDirectPage (); + IAPU.DirectPage = IAPU.RAM + 0x100; + IAPU.PC++; +} + +void Apu1A () +{ +// DECW dp + Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Work16--; + S9xAPUSetByteZ ((uint8) Work16, OP1); + S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); + APUSetZN16 (Work16); + IAPU.PC += 2; +} + +void Apu5A () +{ +// CMPW YA,dp + Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Int32 = (int32) APURegisters.YA.W - (int32) Work16; + IAPU._Carry = Int32 >= 0; + APUSetZN16 ((uint16) Int32); + IAPU.PC += 2; +} + +void Apu3A () +{ +// INCW dp + Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Work16++; + S9xAPUSetByteZ ((uint8) Work16, OP1); + S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); + APUSetZN16 (Work16); + IAPU.PC += 2; +} + +void Apu7A () +{ +// ADDW YA,dp + Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Work32 = (uint32) APURegisters.YA.W + Work16; + IAPU._Carry = Work32 >= 0x10000; + if (~(APURegisters.YA.W ^ Work16) & (Work16 ^ (uint16) Work32) & 0x8000) + APUSetOverflow (); + else + APUClearOverflow (); + APUClearHalfCarry (); + if((APURegisters.YA.W ^ Work16 ^ (uint16) Work32) & 0x1000) + APUSetHalfCarry (); + APURegisters.YA.W = (uint16) Work32; + APUSetZN16 (APURegisters.YA.W); + IAPU.PC += 2; +} + +void Apu9A () +{ +// SUBW YA,dp + Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Int32 = (int32) APURegisters.YA.W - (int32) Work16; + APUClearHalfCarry (); + IAPU._Carry = Int32 >= 0; + if (((APURegisters.YA.W ^ Work16) & 0x8000) && + ((APURegisters.YA.W ^ (uint16) Int32) & 0x8000)) + APUSetOverflow (); + else + APUClearOverflow (); + APUSetHalfCarry (); + if((APURegisters.YA.W ^ Work16 ^ (uint16) Int32) & 0x1000) + APUClearHalfCarry (); + APURegisters.YA.W = (uint16) Int32; + APUSetZN16 (APURegisters.YA.W); + IAPU.PC += 2; +} + +void ApuBA () +{ +// MOVW YA,dp + APURegisters.YA.B.A = S9xAPUGetByteZ (OP1); + APURegisters.YA.B.Y = S9xAPUGetByteZ (OP1 + 1); + APUSetZN16 (APURegisters.YA.W); + IAPU.PC += 2; +} + +void ApuDA () +{ +// MOVW dp,YA + S9xAPUSetByteZ (APURegisters.YA.B.A, OP1); + S9xAPUSetByteZ (APURegisters.YA.B.Y, OP1 + 1); + IAPU.PC += 2; +} + +void Apu64 () +{ +// CMP A,dp + Work8 = S9xAPUGetByteZ (OP1); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu65 () +{ +// CMP A,abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu66 () +{ +// CMP A,(X) + Work8 = S9xAPUGetByteZ (APURegisters.X); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC++; +} + +void Apu67 () +{ +// CMP A,(dp+X) + IndexedXIndirect (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu68 () +{ +// CMP A,#00 + Work8 = OP1; + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu69 () +{ +// CMP dp(dest), dp(src) + W1 = S9xAPUGetByteZ (OP1); + Work8 = S9xAPUGetByteZ (OP2); + CMP (Work8, W1); + IAPU.PC += 3; +} + +void Apu74 () +{ +// CMP A, dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu75 () +{ +// CMP A,abs+X + AbsoluteX (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu76 () +{ +// CMP A, abs+Y + AbsoluteY (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu77 () +{ +// CMP A,(dp)+Y + IndirectIndexedY (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu78 () +{ +// CMP dp,#00 + Work8 = OP1; + W1 = S9xAPUGetByteZ (OP2); + CMP (W1, Work8); + IAPU.PC += 3; +} + +void Apu79 () +{ +// CMP (X),(Y) + W1 = S9xAPUGetByteZ (APURegisters.X); + Work8 = S9xAPUGetByteZ (APURegisters.YA.B.Y); + CMP (W1, Work8); + IAPU.PC++; +} + +void Apu1E () +{ +// CMP X,abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.X, Work8); + IAPU.PC += 3; +} + +void Apu3E () +{ +// CMP X,dp + Work8 = S9xAPUGetByteZ (OP1); + CMP (APURegisters.X, Work8); + IAPU.PC += 2; +} + +void ApuC8 () +{ +// CMP X,#00 + CMP (APURegisters.X, OP1); + IAPU.PC += 2; +} + +void Apu5E () +{ +// CMP Y,abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + CMP (APURegisters.YA.B.Y, Work8); + IAPU.PC += 3; +} + +void Apu7E () +{ +// CMP Y,dp + Work8 = S9xAPUGetByteZ (OP1); + CMP (APURegisters.YA.B.Y, Work8); + IAPU.PC += 2; +} + +void ApuAD () +{ +// CMP Y,#00 + Work8 = OP1; + CMP (APURegisters.YA.B.Y, Work8); + IAPU.PC += 2; +} + +void Apu1F () +{ +// JMP (abs+X) + Absolute (); + IAPU.PC = IAPU.RAM + S9xAPUGetByte (IAPU.Address + APURegisters.X) + + (S9xAPUGetByte (IAPU.Address + APURegisters.X + 1) << 8); +} + +void Apu5F () +{ +// JMP abs + Absolute (); + IAPU.PC = IAPU.RAM + IAPU.Address; +} + +void Apu20 () +{ +// CLRP + APUClearDirectPage (); + IAPU.DirectPage = IAPU.RAM; + IAPU.PC++; +} + +void Apu60 () +{ +// CLRC + APUClearCarry (); + IAPU.PC++; +} + +void ApuE0 () +{ +// CLRV + APUClearHalfCarry (); + APUClearOverflow (); + IAPU.PC++; +} + +void Apu24 () +{ +// AND A,dp + APURegisters.YA.B.A &= S9xAPUGetByteZ (OP1); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu25 () +{ +// AND A,abs + Absolute (); + APURegisters.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu26 () +{ +// AND A,(X) + APURegisters.YA.B.A &= S9xAPUGetByteZ (APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu27 () +{ +// AND A,(dp+X) + IndexedXIndirect (); + APURegisters.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu28 () +{ +// AND A,#00 + APURegisters.YA.B.A &= OP1; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu29 () +{ +// AND dp(dest),dp(src) + Work8 = S9xAPUGetByteZ (OP1); + Work8 &= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu34 () +{ +// AND A,dp+X + APURegisters.YA.B.A &= S9xAPUGetByteZ (OP1 + APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu35 () +{ +// AND A,abs+X + AbsoluteX (); + APURegisters.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu36 () +{ +// AND A,abs+Y + AbsoluteY (); + APURegisters.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu37 () +{ +// AND A,(dp)+Y + IndirectIndexedY (); + APURegisters.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu38 () +{ +// AND dp,#00 + Work8 = OP1; + Work8 &= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu39 () +{ +// AND (X),(Y) + Work8 = S9xAPUGetByteZ (APURegisters.X) & S9xAPUGetByteZ (APURegisters.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, APURegisters.X); + IAPU.PC++; +} + +void Apu2B () +{ +// ROL dp + Work8 = S9xAPUGetByteZ (OP1); + ROL (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu2C () +{ +// ROL abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + ROL (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu3B () +{ +// ROL dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + ROL (Work8); + S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); + IAPU.PC += 2; +} + +void Apu3C () +{ +// ROL A + ROL (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu2E () +{ +// CBNE dp,rel + Work8 = OP1; + Relative2 (); + + if (S9xAPUGetByteZ (Work8) != APURegisters.YA.B.A) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 3; +} + +void ApuDE () +{ +// CBNE dp+X,rel + Work8 = OP1 + APURegisters.X; + Relative2 (); + + if (S9xAPUGetByteZ (Work8) != APURegisters.YA.B.A) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 3; +} + +void Apu3D () +{ +// INC X + APURegisters.X++; + APUSetZN8 (APURegisters.X); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuFC () +{ +// INC Y + APURegisters.YA.B.Y++; + APUSetZN8 (APURegisters.YA.B.Y); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu1D () +{ +// DEC X + APURegisters.X--; + APUSetZN8 (APURegisters.X); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuDC () +{ +// DEC Y + APURegisters.YA.B.Y--; + APUSetZN8 (APURegisters.YA.B.Y); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuAB () +{ +// INC dp + Work8 = S9xAPUGetByteZ (OP1) + 1; + S9xAPUSetByteZ (Work8, OP1); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void ApuAC () +{ +// INC abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address) + 1; + S9xAPUSetByte (Work8, IAPU.Address); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 3; +} + +void ApuBB () +{ +// INC dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X) + 1; + S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void ApuBC () +{ +// INC A + APURegisters.YA.B.A++; + APUSetZN8 (APURegisters.YA.B.A); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu8B () +{ +// DEC dp + Work8 = S9xAPUGetByteZ (OP1) - 1; + S9xAPUSetByteZ (Work8, OP1); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void Apu8C () +{ +// DEC abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address) - 1; + S9xAPUSetByte (Work8, IAPU.Address); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 3; +} + +void Apu9B () +{ +// DEC dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X) - 1; + S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void Apu9C () +{ +// DEC A + APURegisters.YA.B.A--; + APUSetZN8 (APURegisters.YA.B.A); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu44 () +{ +// EOR A,dp + APURegisters.YA.B.A ^= S9xAPUGetByteZ (OP1); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu45 () +{ +// EOR A,abs + Absolute (); + APURegisters.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu46 () +{ +// EOR A,(X) + APURegisters.YA.B.A ^= S9xAPUGetByteZ (APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu47 () +{ +// EOR A,(dp+X) + IndexedXIndirect (); + APURegisters.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu48 () +{ +// EOR A,#00 + APURegisters.YA.B.A ^= OP1; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu49 () +{ +// EOR dp(dest),dp(src) + Work8 = S9xAPUGetByteZ (OP1); + Work8 ^= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu54 () +{ +// EOR A,dp+X + APURegisters.YA.B.A ^= S9xAPUGetByteZ (OP1 + APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu55 () +{ +// EOR A,abs+X + AbsoluteX (); + APURegisters.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu56 () +{ +// EOR A,abs+Y + AbsoluteY (); + APURegisters.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void Apu57 () +{ +// EOR A,(dp)+Y + IndirectIndexedY (); + APURegisters.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void Apu58 () +{ +// EOR dp,#00 + Work8 = OP1; + Work8 ^= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu59 () +{ +// EOR (X),(Y) + Work8 = S9xAPUGetByteZ (APURegisters.X) ^ S9xAPUGetByteZ (APURegisters.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, APURegisters.X); + IAPU.PC++; +} + +void Apu4B () +{ +// LSR dp + Work8 = S9xAPUGetByteZ (OP1); + LSR (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu4C () +{ +// LSR abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + LSR (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu5B () +{ +// LSR dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + LSR (Work8); + S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); + IAPU.PC += 2; +} + +void Apu5C () +{ +// LSR A + LSR (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu7D () +{ +// MOV A,X + APURegisters.YA.B.A = APURegisters.X; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuDD () +{ +// MOV A,Y + APURegisters.YA.B.A = APURegisters.YA.B.Y; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu5D () +{ +// MOV X,A + APURegisters.X = APURegisters.YA.B.A; + APUSetZN8 (APURegisters.X); + IAPU.PC++; +} + +void ApuFD () +{ +// MOV Y,A + APURegisters.YA.B.Y = APURegisters.YA.B.A; + APUSetZN8 (APURegisters.YA.B.Y); + IAPU.PC++; +} + +void Apu9D () +{ +//MOV X,SP + APURegisters.X = APURegisters.S; + APUSetZN8 (APURegisters.X); + IAPU.PC++; +} + +void ApuBD () +{ +// MOV SP,X + APURegisters.S = APURegisters.X; + IAPU.PC++; +} + +void Apu6B () +{ +// ROR dp + Work8 = S9xAPUGetByteZ (OP1); + ROR (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu6C () +{ +// ROR abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + ROR (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu7B () +{ +// ROR dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + ROR (Work8); + S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); + IAPU.PC += 2; +} + +void Apu7C () +{ +// ROR A + ROR (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu6E () +{ +// DBNZ dp,rel + Work8 = OP1; + Relative2 (); + W1 = S9xAPUGetByteZ (Work8) - 1; + S9xAPUSetByteZ (W1, Work8); + if (W1 != 0) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 3; +} + +void ApuFE () +{ +// DBNZ Y,rel + Relative (); + APURegisters.YA.B.Y--; + if (APURegisters.YA.B.Y != 0) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu6F () +{ +// RET + PopW (APURegisters.PC); + IAPU.PC = IAPU.RAM + APURegisters.PC; +} + +void Apu7F () +{ +// RETI + // STOP ("RETI"); + Pop (APURegisters.P); + S9xAPUUnpackStatus (); + PopW (APURegisters.PC); + IAPU.PC = IAPU.RAM + APURegisters.PC; +} + +void Apu84 () +{ +// ADC A,dp + Work8 = S9xAPUGetByteZ (OP1); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu85 () +{ +// ADC A, abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu86 () +{ +// ADC A,(X) + Work8 = S9xAPUGetByteZ (APURegisters.X); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC++; +} + +void Apu87 () +{ +// ADC A,(dp+X) + IndexedXIndirect (); + Work8 = S9xAPUGetByte (IAPU.Address); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu88 () +{ +// ADC A,#00 + Work8 = OP1; + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu89 () +{ +// ADC dp(dest),dp(src) + Work8 = S9xAPUGetByteZ (OP1); + W1 = S9xAPUGetByteZ (OP2); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void Apu94 () +{ +// ADC A,dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu95 () +{ +// ADC A, abs+X + AbsoluteX (); + Work8 = S9xAPUGetByte (IAPU.Address); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu96 () +{ +// ADC A, abs+Y + AbsoluteY (); + Work8 = S9xAPUGetByte (IAPU.Address); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu97 () +{ +// ADC A, (dp)+Y + IndirectIndexedY (); + Work8 = S9xAPUGetByte (IAPU.Address); + ADC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu98 () +{ +// ADC dp,#00 + Work8 = OP1; + W1 = S9xAPUGetByteZ (OP2); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void Apu99 () +{ +// ADC (X),(Y) + W1 = S9xAPUGetByteZ (APURegisters.X); + Work8 = S9xAPUGetByteZ (APURegisters.YA.B.Y); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, APURegisters.X); + IAPU.PC++; +} + +void Apu8D () +{ +// MOV Y,#00 + APURegisters.YA.B.Y = OP1; + APUSetZN8 (APURegisters.YA.B.Y); + IAPU.PC += 2; +} + +void Apu8F () +{ +// MOV dp,#00 + Work8 = OP1; + S9xAPUSetByteZ (Work8, OP2); + IAPU.PC += 3; +} + +void Apu9E () +{ +// DIV YA,X + if((APURegisters.X&0xf)<=(APURegisters.YA.B.Y&0x0f)){ + APUSetHalfCarry(); + } else { + APUClearHalfCarry(); + } + uint32 yva, x, i; + yva = APURegisters.YA.W; + x = APURegisters.X << 9; + for(i=0; i<9; i++){ + yva<<=1; if(yva&0x20000) yva=(yva&0x1ffff)|1; + if(yva>=x) yva^=1; + if(yva&1) yva=(yva-x)&0x1ffff; + } + if(yva&0x100){ + APUSetOverflow(); + } else { + APUClearOverflow(); + } + APURegisters.YA.B.Y = (yva>>9)&0xff; + APURegisters.YA.B.A = yva&0xff; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void Apu9F () +{ +// XCN A + APURegisters.YA.B.A = (APURegisters.YA.B.A >> 4) | (APURegisters.YA.B.A << 4); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuA4 () +{ +// SBC A, dp + Work8 = S9xAPUGetByteZ (OP1); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA5 () +{ +// SBC A, abs + Absolute (); + Work8 = S9xAPUGetByte (IAPU.Address); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuA6 () +{ +// SBC A, (X) + Work8 = S9xAPUGetByteZ (APURegisters.X); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC++; +} + +void ApuA7 () +{ +// SBC A,(dp+X) + IndexedXIndirect (); + Work8 = S9xAPUGetByte (IAPU.Address); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA8 () +{ +// SBC A,#00 + Work8 = OP1; + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA9 () +{ +// SBC dp(dest), dp(src) + Work8 = S9xAPUGetByteZ (OP1); + W1 = S9xAPUGetByteZ (OP2); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void ApuB4 () +{ +// SBC A, dp+X + Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuB5 () +{ +// SBC A,abs+X + AbsoluteX (); + Work8 = S9xAPUGetByte (IAPU.Address); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuB6 () +{ +// SBC A,abs+Y + AbsoluteY (); + Work8 = S9xAPUGetByte (IAPU.Address); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuB7 () +{ +// SBC A,(dp)+Y + IndirectIndexedY (); + Work8 = S9xAPUGetByte (IAPU.Address); + SBC (APURegisters.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuB8 () +{ +// SBC dp,#00 + Work8 = OP1; + W1 = S9xAPUGetByteZ (OP2); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void ApuB9 () +{ +// SBC (X),(Y) + W1 = S9xAPUGetByteZ (APURegisters.X); + Work8 = S9xAPUGetByteZ (APURegisters.YA.B.Y); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, APURegisters.X); + IAPU.PC++; +} + +void ApuAF () +{ +// MOV (X)+, A + S9xAPUSetByteZ (APURegisters.YA.B.A, APURegisters.X++); + IAPU.PC++; +} + +void ApuBE () +{ +// DAS + if (APURegisters.YA.B.A > 0x99 || !IAPU._Carry) { + APURegisters.YA.B.A -= 0x60; + APUClearCarry (); + } + else { APUSetCarry (); } + if ((APURegisters.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry()) + { + APURegisters.YA.B.A -= 6; + } + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuBF () +{ +// MOV A,(X)+ + APURegisters.YA.B.A = S9xAPUGetByteZ (APURegisters.X++); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuC0 () +{ +// DI + APUClearInterrupt (); + IAPU.PC++; +} + +void ApuA0 () +{ +// EI + APUSetInterrupt (); + IAPU.PC++; +} + +void ApuC4 () +{ +// MOV dp,A + S9xAPUSetByteZ (APURegisters.YA.B.A, OP1); + IAPU.PC += 2; +} + +void ApuC5 () +{ +// MOV abs,A + Absolute (); + S9xAPUSetByte (APURegisters.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuC6 () +{ +// MOV (X), A + S9xAPUSetByteZ (APURegisters.YA.B.A, APURegisters.X); + IAPU.PC++; +} + +void ApuC7 () +{ +// MOV (dp+X),A + IndexedXIndirect (); + S9xAPUSetByte (APURegisters.YA.B.A, IAPU.Address); + IAPU.PC += 2; +} + +void ApuC9 () +{ +// MOV abs,X + Absolute (); + S9xAPUSetByte (APURegisters.X, IAPU.Address); + IAPU.PC += 3; +} + +void ApuCB () +{ +// MOV dp,Y + S9xAPUSetByteZ (APURegisters.YA.B.Y, OP1); + IAPU.PC += 2; +} + +void ApuCC () +{ +// MOV abs,Y + Absolute (); + S9xAPUSetByte (APURegisters.YA.B.Y, IAPU.Address); + IAPU.PC += 3; +} + +void ApuCD () +{ +// MOV X,#00 + APURegisters.X = OP1; + APUSetZN8 (APURegisters.X); + IAPU.PC += 2; +} + +void ApuCF () +{ +// MUL YA + APURegisters.YA.W = (uint16) APURegisters.YA.B.A * APURegisters.YA.B.Y; + APUSetZN8 (APURegisters.YA.B.Y); + IAPU.PC++; +} + +void ApuD4 () +{ +// MOV dp+X, A + S9xAPUSetByteZ (APURegisters.YA.B.A, OP1 + APURegisters.X); + IAPU.PC += 2; +} + +void ApuD5 () +{ +// MOV abs+X,A + AbsoluteX (); + S9xAPUSetByte (APURegisters.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuD6 () +{ +// MOV abs+Y,A + AbsoluteY (); + S9xAPUSetByte (APURegisters.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuD7 () +{ +// MOV (dp)+Y,A + IndirectIndexedY (); + S9xAPUSetByte (APURegisters.YA.B.A, IAPU.Address); + IAPU.PC += 2; +} + +void ApuD8 () +{ +// MOV dp,X + S9xAPUSetByteZ (APURegisters.X, OP1); + IAPU.PC += 2; +} + +void ApuD9 () +{ +// MOV dp+Y,X + S9xAPUSetByteZ (APURegisters.X, OP1 + APURegisters.YA.B.Y); + IAPU.PC += 2; +} + +void ApuDB () +{ +// MOV dp+X,Y + S9xAPUSetByteZ (APURegisters.YA.B.Y, OP1 + APURegisters.X); + IAPU.PC += 2; +} + +void ApuDF () +{ +// DAA + if (APURegisters.YA.B.A > 0x99 || IAPU._Carry) + { + APURegisters.YA.B.A += 0x60; + APUSetCarry (); + } + else { APUClearCarry (); } + if ((APURegisters.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry()) + { + APURegisters.YA.B.A += 6; + //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc... + } + //else { APUClearHalfCarry (); } ditto as above + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuE4 () +{ +// MOV A, dp + APURegisters.YA.B.A = S9xAPUGetByteZ (OP1); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void ApuE5 () +{ +// MOV A,abs + Absolute (); + APURegisters.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void ApuE6 () +{ +// MOV A,(X) + APURegisters.YA.B.A = S9xAPUGetByteZ (APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC++; +} + +void ApuE7 () +{ +// MOV A,(dp+X) + IndexedXIndirect (); + APURegisters.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void ApuE8 () +{ +// MOV A,#00 + APURegisters.YA.B.A = OP1; + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void ApuE9 () +{ +// MOV X, abs + Absolute (); + APURegisters.X = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.X); + IAPU.PC += 3; +} + +void ApuEB () +{ +// MOV Y,dp + APURegisters.YA.B.Y = S9xAPUGetByteZ (OP1); + APUSetZN8 (APURegisters.YA.B.Y); + IAPU.PC += 2; +} + +void ApuEC () +{ +// MOV Y,abs + Absolute (); + APURegisters.YA.B.Y = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.Y); + IAPU.PC += 3; +} + +void ApuF4 () +{ +// MOV A, dp+X + APURegisters.YA.B.A = S9xAPUGetByteZ (OP1 + APURegisters.X); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void ApuF5 () +{ +// MOV A, abs+X + AbsoluteX (); + APURegisters.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void ApuF6 () +{ +// MOV A, abs+Y + AbsoluteY (); + APURegisters.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 3; +} + +void ApuF7 () +{ +// MOV A, (dp)+Y + IndirectIndexedY (); + APURegisters.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (APURegisters.YA.B.A); + IAPU.PC += 2; +} + +void ApuF8 () +{ +// MOV X,dp + APURegisters.X = S9xAPUGetByteZ (OP1); + APUSetZN8 (APURegisters.X); + IAPU.PC += 2; +} + +void ApuF9 () +{ +// MOV X,dp+Y + APURegisters.X = S9xAPUGetByteZ (OP1 + APURegisters.YA.B.Y); + APUSetZN8 (APURegisters.X); + IAPU.PC += 2; +} + +void ApuFA () +{ +// MOV dp(dest),dp(src) + S9xAPUSetByteZ (S9xAPUGetByteZ (OP1), OP2); + IAPU.PC += 3; +} + +void ApuFB () +{ +// MOV Y,dp+X + APURegisters.YA.B.Y = S9xAPUGetByteZ (OP1 + APURegisters.X); + APUSetZN8 (APURegisters.YA.B.Y); + IAPU.PC += 2; +} + +#ifdef NO_INLINE_SET_GET +#undef INLINE +#define INLINE +#include "apumem.h" +#endif + +void (*S9xApuOpcodes[256]) (void) = +{ + Apu00, Apu01, Apu02, Apu03, Apu04, Apu05, Apu06, Apu07, + Apu08, Apu09, Apu0A, Apu0B, Apu0C, Apu0D, Apu0E, Apu0F, + Apu10, Apu11, Apu12, Apu13, Apu14, Apu15, Apu16, Apu17, + Apu18, Apu19, Apu1A, Apu1B, Apu1C, Apu1D, Apu1E, Apu1F, + Apu20, Apu21, Apu22, Apu23, Apu24, Apu25, Apu26, Apu27, + Apu28, Apu29, Apu2A, Apu2B, Apu2C, Apu2D, Apu2E, Apu2F, + Apu30, Apu31, Apu32, Apu33, Apu34, Apu35, Apu36, Apu37, + Apu38, Apu39, Apu3A, Apu3B, Apu3C, Apu3D, Apu3E, Apu3F, + Apu40, Apu41, Apu42, Apu43, Apu44, Apu45, Apu46, Apu47, + Apu48, Apu49, Apu4A, Apu4B, Apu4C, Apu4D, Apu4E, Apu4F, + Apu50, Apu51, Apu52, Apu53, Apu54, Apu55, Apu56, Apu57, + Apu58, Apu59, Apu5A, Apu5B, Apu5C, Apu5D, Apu5E, Apu5F, + Apu60, Apu61, Apu62, Apu63, Apu64, Apu65, Apu66, Apu67, + Apu68, Apu69, Apu6A, Apu6B, Apu6C, Apu6D, Apu6E, Apu6F, + Apu70, Apu71, Apu72, Apu73, Apu74, Apu75, Apu76, Apu77, + Apu78, Apu79, Apu7A, Apu7B, Apu7C, Apu7D, Apu7E, Apu7F, + Apu80, Apu81, Apu82, Apu83, Apu84, Apu85, Apu86, Apu87, + Apu88, Apu89, Apu8A, Apu8B, Apu8C, Apu8D, Apu8E, Apu8F, + Apu90, Apu91, Apu92, Apu93, Apu94, Apu95, Apu96, Apu97, + Apu98, Apu99, Apu9A, Apu9B, Apu9C, Apu9D, Apu9E, Apu9F, + ApuA0, ApuA1, ApuA2, ApuA3, ApuA4, ApuA5, ApuA6, ApuA7, + ApuA8, ApuA9, ApuAA, ApuAB, ApuAC, ApuAD, ApuAE, ApuAF, + ApuB0, ApuB1, ApuB2, ApuB3, ApuB4, ApuB5, ApuB6, ApuB7, + ApuB8, ApuB9, ApuBA, ApuBB, ApuBC, ApuBD, ApuBE, ApuBF, + ApuC0, ApuC1, ApuC2, ApuC3, ApuC4, ApuC5, ApuC6, ApuC7, + ApuC8, ApuC9, ApuCA, ApuCB, ApuCC, ApuCD, ApuCE, ApuCF, + ApuD0, ApuD1, ApuD2, ApuD3, ApuD4, ApuD5, ApuD6, ApuD7, + ApuD8, ApuD9, ApuDA, ApuDB, ApuDC, ApuDD, ApuDE, ApuDF, + ApuE0, ApuE1, ApuE2, ApuE3, ApuE4, ApuE5, ApuE6, ApuE7, + ApuE8, ApuE9, ApuEA, ApuEB, ApuEC, ApuED, ApuEE, ApuEF, + ApuF0, ApuF1, ApuF2, ApuF3, ApuF4, ApuF5, ApuF6, ApuF7, + ApuF8, ApuF9, ApuFA, ApuFB, ApuFC, ApuFD, ApuFE, ApuFF +}; + diff --git a/source/snes9x/logger.cpp b/source/snes9x/spc700.h similarity index 74% rename from source/snes9x/logger.cpp rename to source/snes9x/spc700.h index 4c75c5e..fb29bb7 100644 --- a/source/snes9x/logger.cpp +++ b/source/snes9x/spc700.h @@ -159,89 +159,79 @@ **********************************************************************************/ -#include "snes9x.h" -#include "movie.h" -#include "logger.h" -static int resetno = 0; -static int framecounter = 0; -static FILE *video = NULL; -static FILE *audio = NULL; +#ifndef _SPC700_H_ +#define _SPC700_H_ +#define Carry 1 +#define Zero 2 +#define Interrupt 4 +#define HalfCarry 8 +#define BreakFlag 16 +#define DirectPageFlag 32 +#define Overflow 64 +#define Negative 128 -void S9xResetLogger (void) +#define APUClearCarry() (IAPU._Carry = 0) +#define APUSetCarry() (IAPU._Carry = 1) +#define APUSetInterrupt() (APURegisters.P |= Interrupt) +#define APUClearInterrupt() (APURegisters.P &= ~Interrupt) +#define APUSetHalfCarry() (APURegisters.P |= HalfCarry) +#define APUClearHalfCarry() (APURegisters.P &= ~HalfCarry) +#define APUSetBreak() (APURegisters.P |= BreakFlag) +#define APUClearBreak() (APURegisters.P &= ~BreakFlag) +#define APUSetDirectPage() (APURegisters.P |= DirectPageFlag) +#define APUClearDirectPage() (APURegisters.P &= ~DirectPageFlag) +#define APUSetOverflow() (IAPU._Overflow = 1) +#define APUClearOverflow() (IAPU._Overflow = 0) + +#define APUCheckZero() (IAPU._Zero == 0) +#define APUCheckCarry() (IAPU._Carry) +#define APUCheckInterrupt() (APURegisters.P & Interrupt) +#define APUCheckHalfCarry() (APURegisters.P & HalfCarry) +#define APUCheckBreak() (APURegisters.P & BreakFlag) +#define APUCheckDirectPage() (APURegisters.P & DirectPageFlag) +#define APUCheckOverflow() (IAPU._Overflow) +#define APUCheckNegative() (IAPU._Zero & 0x80) + +#define APUClearFlags(f) (APURegisters.P &= ~(f)) +#define APUSetFlags(f) (APURegisters.P |= (f)) +#define APUCheckFlag(f) (APURegisters.P & (f)) + +typedef union { - if (!Settings.DumpStreams) - return; +#ifdef LSB_FIRST + struct { uint8 A, Y; } B; +#else + struct { uint8 Y, A; } B; +#endif + uint16 W; +} YAndA; - char buffer[128]; +struct SAPURegisters{ + uint8 P; + YAndA YA; + uint8 X; + uint8 S; + uint16 PC; +}; - S9xCloseLogger(); - framecounter = 0; +EXTERN_C struct SAPURegisters APURegisters; - sprintf(buffer, "videostream%d.dat", resetno); - video = fopen(buffer, "wb"); - if (!video) - { - printf("Opening %s failed. Logging cancelled.\n", buffer); - return; - } - - sprintf(buffer, "audiostream%d.dat", resetno); - audio = fopen(buffer, "wb"); - if (!audio) - { - printf("Opening %s failed. Logging cancelled.\n", buffer); - fclose(video); - return; - } - - resetno++; +#ifdef DEBUGGER +#define APU_EXECUTE1() \ +{ \ + if (APU.Flags & TRACE_FLAG) \ + S9xTraceAPU (); \ + APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ + (*S9xApuOpcodes[*IAPU.PC]) (); \ } - -void S9xCloseLogger (void) -{ - if (video) - { - fclose(video); - video = NULL; - } - - if (audio) - { - fclose(audio); - audio = NULL; - } -} - -void S9xVideoLogger (void *pixels, int width, int height, int depth, int bytes_per_line) -{ - int fc = S9xMovieGetFrameCounter(); - if (fc > 0) - framecounter = fc; - else - framecounter++; - - if (video) - { - char *data = (char *) pixels; - - for (int i = 0; i < height; i++) - fwrite(data + i * bytes_per_line, depth, width, video); - fflush(video); - fflush(audio); - - if (Settings.DumpStreamsMaxFrames > 0 && framecounter >= Settings.DumpStreamsMaxFrames) - { - printf("Logging ended.\n"); - S9xCloseLogger(); - } - - } +#else +#define APU_EXECUTE1() \ +{ \ + APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ + (*S9xApuOpcodes[*IAPU.PC]) (); \ } +#endif -void S9xAudioLogger (void *samples, int length) -{ - if (audio) - fwrite(samples, 1, length, audio); -} +#endif diff --git a/source/snes9x/spc7110.cpp b/source/snes9x/spc7110.cpp index 2e19c0c..36b4747 100644 --- a/source/snes9x/spc7110.cpp +++ b/source/snes9x/spc7110.cpp @@ -158,60 +158,2201 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ -/***** - * SPC7110 emulator - version 0.03 (2008-08-10) - * Copyright (c) 2008, byuu and neviksti - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * The software is provided "as is" and the author disclaims all warranties - * with regard to this software including all implied warranties of - * merchantibility and fitness, in no event shall the author be liable for - * any special, direct, indirect, or consequential damages or any damages - * whatsoever resulting from loss of use, data or profits, whether in an - * action of contract, negligence or other tortious action, arising out of - * or in connection with the use or performance of this software. - *****/ -#include -#include "snes9x.h" +//#define SPC7110_DEBUG + +#include "spc7110.h" #include "memmap.h" -#include "srtc.h" +#include +#include + +//Windows includes +#ifdef __WIN32__ +#ifndef _XBOX // chdir and getcwd not supported on Xbox hardware +#include "win32/wsnes9x.h" // FIXME: shouldn't be necessary +#include +#define chdir _chdir +#define getcwd _getcwd +#endif +#undef PATH_MAX +//zinx suggested this, for *nix compatibility +#define PATH_MAX MAX_PATH +#else // Unix +#include +#include +#ifdef __MACOSX__ +const char * S9xGetSPC7110Directory(void); +#endif +#endif #include "display.h" -#define memory_cartrom_size() Memory.CalculatedSize -#define memory_cartrom_read(a) Memory.ROM[(a)] -#define memory_cartrtc_read(a) RTCData.reg[(a)] -#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } -#define cartridge_info_spc7110rtc Settings.SPC7110RTC -#define cpu_regs_mdr OpenBus +#ifndef NGC +extern "C" char *osd_GetPackDir(); +#endif +//really not needed, but usually MS adds the _ to POSIX functions, +//while *nix doesn't, so this was to "un-M$" the function. +#define splitpath _splitpath -#define _SPC7110EMU_CPP_ +//not much headroom, but FEOEZ has 41 tables, I think, and SPL4 has 38. +#define MAX_TABLES 48 -#include -#include "port.h" +//default to using 5 megs of RAM for method 3 caching. +uint16 cacheMegs=5; -#include "spc7110emu.h" -#include "spc7110emu.cpp" - -SPC7110 s7emu; +//using function pointers to initialize cache management +void (*CleanUp7110)(void)=NULL; +void (*LoadUp7110)(char*)=&SPC7110Load; +void (*Copy7110)(void)=NULL; static void SetSPC7110SRAMMap (uint8); - -void S9xInitSPC7110 (void) +//size and offset of the pack data +//offset and size of reads from pack +typedef struct SPC7110DecompressionLocationStruct { - s7emu.power(); - memset(RTCData.reg, 0, 20); + uint32 offset; + uint32 size; + uint16 used_offset; + uint16 used_len; +} Data7110; + +//this maps an index.bin table to the decompression pack +typedef struct SPC7110DecompressionIndexStruct +{ + int table; + bool is_file; + Data7110 location[256]; +} Index7110; + +//this contains all the data for the decompression pack. +typedef struct SPC7110DecompressionPackStructure +{ + uint8* binfiles[MAX_TABLES]; + Index7110 tableEnts[MAX_TABLES]; + int last_table; + int idx; + uint8 last_idx; + uint16 last_offset; +} Pack7110; + + +char pfold[9]; //hack variable for log naming (each game makes a different log) +Pack7110* decompack=NULL; //decompression pack uses a fair chunk of RAM, so dynalloc it. +SPC7110Regs s7r; //SPC7110 registers, about 33KB +S7RTC rtc_f9; //FEOEZ (and Shounen Jump no SHou) RTC +void S9xUpdateRTC (); //S-RTC function hacked to work with the RTC + +//Emulate power on state +void S9xSpc7110Init() +{ + s7r.DataRomOffset=0x00100000;//handy constant! + s7r.DataRomSize=Memory.CalculatedSize-s7r.DataRomOffset; + s7r.reg4800=0; + s7r.reg4801=0; + s7r.reg4802=0; + s7r.reg4803=0; + s7r.reg4804=0; + s7r.reg4805=0; + s7r.reg4806=0; + s7r.reg4807=0; + s7r.reg4808=0; + s7r.reg4809=0; + s7r.reg480A=0; + s7r.reg480B=0; + s7r.reg480C=0; + s7r.reg4811=0; + s7r.reg4812=0; + s7r.reg4813=0; + s7r.reg4814=0; + s7r.reg4815=0; + s7r.reg4816=0; + s7r.reg4817=0; + s7r.reg4818=0; + s7r.reg4820=0; + s7r.reg4821=0; + s7r.reg4822=0; + s7r.reg4823=0; + s7r.reg4824=0; + s7r.reg4825=0; + s7r.reg4826=0; + s7r.reg4827=0; + s7r.reg4828=0; + s7r.reg4829=0; + s7r.reg482A=0; + s7r.reg482B=0; + s7r.reg482C=0; + s7r.reg482D=0; + s7r.reg482E=0; + s7r.reg482F=0; + s7r.reg4830=0; + s7r.reg4831=0; + s7r.reg4832=1; + s7r.reg4833=2; + s7r.reg4834=0; + s7r.reg4840=0; + s7r.reg4841=0; + s7r.reg4842=0; + s7r.written=0; + s7r.offset_add=0; + s7r.AlignBy=1; + + #ifndef NGC + (*LoadUp7110)(osd_GetPackDir()); + #endif + + if(Settings.SPC7110RTC) + Settings.TurboMode=false; + + s7r.bank50Internal=0; + memset(s7r.bank50,0x00,DECOMP_BUFFER_SIZE); } -void S9xResetSPC7110 (void) + +//full cache decompression routine (memcpy) Method 1 +void MovePackData() { - s7emu.reset(); + //log the last entry + Data7110* log=&(decompack->tableEnts[decompack->idx].location[decompack->last_idx]); + if((log->used_len+log->used_offset)<(decompack->last_offset+(unsigned short)s7r.bank50Internal)) + { + log->used_len=s7r.bank50Internal; + log->used_offset=decompack->last_offset; + } + + //set up for next logging + decompack->last_offset=(s7r.reg4805)|(s7r.reg4806<<8); + + decompack->last_idx=s7r.reg4804; + + //start decompression + int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; + + //the table is a offset multiplier byte and a big-endian pointer + int j= 4*s7r.reg4804; + j+=s7r.DataRomOffset; + j+=table; + + //set proper offsetting. + if(s7r.reg480B==0) + s7r.AlignBy=0; + else + { + switch(Memory.ROM[j]) + { + case 0x03: + s7r.AlignBy=8; + break; + case 0x01: + s7r.AlignBy=2; + break; + case 0x02: + s7r.AlignBy=4; + break; + case 0x00: + default: + s7r.AlignBy=1; + break; + } + } + //note that we are still setting up for the next log. + decompack->last_offset*=s7r.AlignBy; + decompack->last_offset%=DECOMP_BUFFER_SIZE; + + //find the table + if(table!=decompack->last_table) + { + int i=0; + while(itableEnts[i].table!=table) + i++; + if(i==MAX_TABLES) + { +#ifdef _XBOX + FILE* fp=fopen("T:\\sp7err.out","a"); +#else +#ifdef __MACOSX__ + FILE* fp=fopen(S9xGetFilename(".out", DEFAULT_DIR), "a"); +#else + FILE* fp=fopen("sp7err.out","a"); +#endif +#endif + + fprintf(fp, "Table Entry %06X:%02X not found\n", table, s7r.reg4804); + fclose(fp); + return; + } + decompack->idx=i; + decompack->last_table=table; + } + + //copy data + if(decompack->binfiles[decompack->idx]) + { + memcpy(s7r.bank50, + &(decompack->binfiles[decompack->idx][decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset]), + decompack->tableEnts[decompack->idx].location[s7r.reg4804].size); + } +} + + +//this is similar to the last function, but it keeps the last 5 accessed files open, +// and reads the data directly. Method 2 +void ReadPackData() +{ + static int table_age_2; + static int table_age_3; + static int table_age_4; + static int table_age_5; + + int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; + + if(table==0) + { + table_age_2=table_age_3=table_age_4=table_age_5=MAX_TABLES; + return; + } + + if(table_age_2==0&&table_age_3==0&&table_age_4==0&&table_age_5==0) + table_age_2=table_age_3=table_age_4=table_age_5=MAX_TABLES; + Data7110* log=&(decompack->tableEnts[decompack->idx].location[decompack->last_idx]); + if((log->used_len+log->used_offset)<(decompack->last_offset+(unsigned short)s7r.bank50Internal)) + { + log->used_len=s7r.bank50Internal; + log->used_offset=decompack->last_offset; + } + + decompack->last_offset=(s7r.reg4805)|(s7r.reg4806<<8); + + decompack->last_idx=s7r.reg4804; + + int j= 4*s7r.reg4804; + j+=s7r.DataRomOffset; + j+=table; + + if(s7r.reg480B==0) + s7r.AlignBy=0; + else + { + switch(Memory.ROM[j]) + { + case 0x03: + s7r.AlignBy=8; + break; + case 0x01: + s7r.AlignBy=2; + break; + case 0x02: + s7r.AlignBy=4; + break; + case 0x00: + default: + s7r.AlignBy=1; + break; + } + } + decompack->last_offset*=s7r.AlignBy; + decompack->last_offset%=DECOMP_BUFFER_SIZE; + if(table!=decompack->last_table) + { + int i=0; + while(itableEnts[i].table!=table) + i++; + if(i==MAX_TABLES) + { + #ifdef __MACOSX__ + FILE* fp=fopen(S9xGetFilename(".out", DEFAULT_DIR), "a"); + #else + FILE* fp=fopen("sp7err.out","a"); + #endif + fprintf(fp, "Table Entry %06X:%02X not found\n", table, s7r.reg4804); + fclose(fp); + return; + } + if(i!= table_age_2 && i!= table_age_3 && i!= table_age_4 && i!= table_age_5) + { + if(table_age_5!=MAX_TABLES&&decompack->binfiles[table_age_5]) + { + fclose((FILE*)(decompack->binfiles[table_age_5])); + (decompack->binfiles[table_age_5])=NULL; + } + table_age_5=table_age_4; + table_age_4=table_age_3; + table_age_3=table_age_2; + table_age_2=decompack->idx; + + #ifdef __MACOSX__ + char name[PATH_MAX + 1], bfname[11]; + strcpy(name, S9xGetSPC7110Directory()); + sprintf(bfname, "%06X.bin", table); + strcat(name, bfname); + #else + char name[PATH_MAX]; + //open file + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + const char* patchDir = S9xGetDirectory (PATCH_DIR); + if (patchDir && strlen (patchDir)) + { + //splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy (name, patchDir); + strcat (name, "/"); + } + else + { + splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy(name, drive); + //strcat(filename, "\\"); + strcat(name, dir); + } + strcat(name, pfold); + char bfname[11]; + sprintf(bfname, "%06X.bin", table); + strcat(name, "/"); + strcat(name, bfname); + #endif + + decompack->binfiles[i]=(uint8*)fopen(name, "rb"); + } + else + { + //fix tables in this case + if(table_age_5==i) + { + table_age_5=table_age_4; + table_age_4=table_age_3; + table_age_3=table_age_2; + table_age_2=decompack->idx; + } + if(table_age_4==i) + { + table_age_4=table_age_3; + table_age_3=table_age_2; + table_age_2=decompack->idx; + } + if(table_age_3==i) + { + table_age_3=table_age_2; + table_age_2=decompack->idx; + } + if(table_age_2==i) + { + table_age_2=decompack->idx; + } + } + decompack->idx=i; + decompack->last_table=table; + } + //do read here. + if(decompack->binfiles[decompack->idx]) + { + fseek((FILE*)(decompack->binfiles[decompack->idx]), decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset, 0); + fread(s7r.bank50,1, (decompack->tableEnts[decompack->idx].location[s7r.reg4804].size), (FILE*)(decompack->binfiles[decompack->idx])); + } +} + +//Cache Method 3: some entries are cached, others are file handles. +//use is_file to distinguish. +void GetPackData() +{ + Data7110* log=&(decompack->tableEnts[decompack->idx].location[decompack->last_idx]); + if((log->used_len+log->used_offset)<(decompack->last_offset+(unsigned short)s7r.bank50Internal)) + { + log->used_len=s7r.bank50Internal; + log->used_offset=decompack->last_offset; + } + + decompack->last_offset=(s7r.reg4805)|(s7r.reg4806<<8); + + decompack->last_idx=s7r.reg4804; + int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; + + int j= 4*s7r.reg4804; + j+=s7r.DataRomOffset; + j+=table; + + if(s7r.reg480B==0) + s7r.AlignBy=0; + else + { + switch(Memory.ROM[j]) + { + case 0x03: + s7r.AlignBy=8; + break; + case 0x01: + s7r.AlignBy=2; + break; + case 0x02: + s7r.AlignBy=4; + break; + case 0x00: + default: + s7r.AlignBy=1; + break; + } + } + decompack->last_offset*=s7r.AlignBy; + decompack->last_offset%=DECOMP_BUFFER_SIZE; + if(table!=decompack->last_table) + { + int i=0; + while(itableEnts[i].table!=table) + i++; + if(i==MAX_TABLES) + { + #ifdef __MACOSX__ + FILE* fp=fopen(S9xGetFilename(".out", DEFAULT_DIR), "a"); + #else + FILE* fp=fopen("sp7err.out","a"); + #endif + fprintf(fp, "Table Entry %06X:%02X not found\n", table, s7r.reg4804); + fclose(fp); + return; + } + decompack->idx=i; + decompack->last_table=table; + } + if(decompack->binfiles[decompack->idx]) + { + if(decompack->tableEnts[decompack->idx].is_file) + { + fseek((FILE*)decompack->binfiles[decompack->idx], decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset, 0); + fread(s7r.bank50,1, (decompack->tableEnts[decompack->idx].location[s7r.reg4804].size), (FILE*)(decompack->binfiles[decompack->idx])); + } + else + { + memcpy(s7r.bank50, + &(decompack->binfiles[decompack->idx][decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset]), + decompack->tableEnts[decompack->idx].location[s7r.reg4804].size); + } + } +} + +extern "C"{ +//reads SPC7110 and RTC registers. +uint8 S9xGetSPC7110(uint16 Address) +{ +#ifdef SPC7110_DEBUG + printf("%04X read\n", Address); +#endif + switch (Address) + { + //decompressed data read port. decrements 4809-A (with wrap) + //4805-6 is the offset into the bank + //AlignBy is set (afaik) at decompression time, and is the offset multiplier + //bank50internal is an internal pointer to the actual byte to read. + //so you read from offset*multiplier + bank50internal + //the offset registers cannot be incremented due to the offset multiplier. + case 0x4800: + { + unsigned short count=s7r.reg4809|(s7r.reg480A<<8); + uint32 i, j; + j=(s7r.reg4805|(s7r.reg4806<<8)); + j*=s7r.AlignBy; + i=j; + if(count >0) + count--; + else count = 0xFFFF; + s7r.reg4809=0x00ff&count; + s7r.reg480A=(0xff00&count)>>8; + i+=s7r.bank50Internal; + i%=DECOMP_BUFFER_SIZE; + s7r.reg4800=s7r.bank50[i]; + + s7r.bank50Internal++; + s7r.bank50Internal%=DECOMP_BUFFER_SIZE; +#ifdef SPC7110_DEBUG + printf("Returned %02X\n", s7r.reg4800); +#endif + } + return s7r.reg4800; + //table register low + case 0x4801: return s7r.reg4801; + //table register middle + case 0x4802: return s7r.reg4802; + //table register high + case 0x4803: return s7r.reg4803; + //index of pointer in table (each entry is 4 bytes) + case 0x4804: return s7r.reg4804; + //offset register low + case 0x4805: return s7r.reg4805; + //offset register high + case 0x4806: return s7r.reg4806; + //DMA channel (not that I see this usually set, + //regardless of what channel DMA is on) + case 0x4807: return s7r.reg4807; + //C r/w option, unknown, defval:00 is what Dark Force says + //afaict, Snes9x doesn't use this at all. + case 0x4808: return s7r.reg4808; + //C-Length low + //counts down the number of bytes left to read from the decompression buffer. + //this is set by the ROM, and wraps on bounds. + case 0x4809: return s7r.reg4809; + //C Length high + case 0x480A: return s7r.reg480A; + //Offset enable. + //if this is zero, 4805-6 are useless. Emulated by setting AlignBy to 0 + case 0x480B: + return s7r.reg480B; + //decompression finished: just emulated by switching each read. + case 0x480C: + s7r.reg480C^=0x80; + return s7r.reg480C^0x80; + + //Data access port + //reads from the data ROM (anywhere over the first 8 mbits + //behavior is complex, will document later, + //possibly missing cases, because of the number of switches in play + case 0x4810: + if(s7r.written==0) + return 0; + if((s7r.written&0x07)==0x07) + { + uint32 i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; + i%=s7r.DataRomSize; + if(s7r.reg4818&0x02) + { + if(s7r.reg4818&0x08) + { + signed short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + i+=r4814; + r4814++; + s7r.reg4815=(uint8)(r4814>>8); + s7r.reg4814=(uint8)(r4814&0x00FF); + } + else + { + unsigned short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + i+=r4814; + if(r4814!=0xFFFF) + r4814++; + else r4814=0; + s7r.reg4815=(uint8)(r4814>>8); + s7r.reg4814=(uint8)(r4814&0x00FF); + + } + } + i+=s7r.DataRomOffset; + uint8 tmp=Memory.ROM[i]; + i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; + + if(s7r.reg4818&0x02) + { + } + else if(s7r.reg4818&0x01) + { + if(s7r.reg4818&0x04) + { + signed short inc; + inc=(s7r.reg4817<<8)|s7r.reg4816; + + if(!(s7r.reg4818&0x10)) + i+=inc; + else + { + if(s7r.reg4818&0x08) + { + signed short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + r4814+=inc; + s7r.reg4815=(r4814&0xFF00)>>8; + s7r.reg4814=r4814&0xFF; + } + else + { + unsigned short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + r4814+=inc; + s7r.reg4815=(r4814&0xFF00)>>8; + s7r.reg4814=r4814&0xFF; + + } + } + //is signed + } + else + { + uint16 inc; + inc=(s7r.reg4817<<8)|s7r.reg4816; + if(!(s7r.reg4818&0x10)) + i+=inc; + else + { + if(s7r.reg4818&0x08) + { + signed short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + r4814+=inc; + s7r.reg4815=(r4814&0xFF00)>>8; + s7r.reg4814=r4814&0xFF; + } + else + { + unsigned short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + r4814+=inc; + s7r.reg4815=(r4814&0xFF00)>>8; + s7r.reg4814=r4814&0xFF; + + } + } + } + } + else + { + if(!(s7r.reg4818&0x10)) + i+=1; + else + { + if(s7r.reg4818&0x08) + { + signed short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + r4814+=1; + s7r.reg4815=(r4814&0xFF00)>>8; + s7r.reg4814=r4814&0xFF; + } + else + { + unsigned short r4814; + r4814=(s7r.reg4815<<8)|s7r.reg4814; + r4814+=1; + s7r.reg4815=(r4814&0xFF00)>>8; + s7r.reg4814=r4814&0xFF; + + } + } + } + +#ifdef SPC7110_DEBUG + printf("Returned %02X\n", tmp); +#endif + + i%=s7r.DataRomSize; + s7r.reg4811=i&0x00FF; + s7r.reg4812=(i&0x00FF00)>>8; + s7r.reg4813=((i&0xFF0000)>>16); + return tmp; + } + else return 0; + //direct read address low + case 0x4811: return s7r.reg4811; + //direct read address middle + case 0x4812: return s7r.reg4812; + //direct read access high + case 0x4813: return s7r.reg4813; + //read adjust low + case 0x4814: return s7r.reg4814; + //read adjust high + case 0x4815: return s7r.reg4815; + //read increment low + case 0x4816: return s7r.reg4816; + //read increment high + case 0x4817: return s7r.reg4817; + //Data ROM command mode + //essentially, this controls the insane code of $4810 and $481A + case 0x4818: return s7r.reg4818; + //read after adjust port + //what this does, besides more nasty stuff like 4810, + //I don't know. Just assume it is a different implementation of $4810, + //if it helps your sanity + case 0x481A: + if(s7r.written==0x1F) + { + uint32 i=((s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811); + if(s7r.reg4818&0x08) + { + short adj; + adj=((short)(s7r.reg4815<<8))|s7r.reg4814; + i+=adj; + } + else + { + uint16 adj; + adj=(s7r.reg4815<<8)|s7r.reg4814; + i+=adj; + } + + i%=s7r.DataRomSize; + i+=s7r.DataRomOffset; + uint8 tmp=Memory.ROM[i]; + i=((s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811); + if(0x60==(s7r.reg4818&0x60)) + { + i=((s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811); + + if(!(s7r.reg4818&0x10)) + { + if(s7r.reg4818&0x08) + { + short adj; + adj=((short)(s7r.reg4815<<8))|s7r.reg4814; + i+=adj; + } + else + { + uint16 adj; + adj=(s7r.reg4815<<8)|s7r.reg4814; + i+=adj; + } + i%=s7r.DataRomSize; + s7r.reg4811=i&0x00FF; + s7r.reg4812=(i&0x00FF00)>>8; + s7r.reg4813=((i&0xFF0000)>>16); + } + else + { + if(s7r.reg4818&0x08) + { + short adj; + adj=((short)(s7r.reg4815<<8))|s7r.reg4814; + adj+=adj; + s7r.reg4815=(adj&0xFF00)>>8; + s7r.reg4814=adj&0xFF; + } + else + { + uint16 adj; + adj=(s7r.reg4815<<8)|s7r.reg4814; + adj+=adj; + s7r.reg4815=(adj&0xFF00)>>8; + s7r.reg4814=adj&0xFF; + } + } + } +#ifdef SPC7110_DEBUG + printf("Returned %02X\n", tmp); +#endif + return tmp; + } + else return 0; + + //multiplicand low or dividend lowest + case 0x4820: return s7r.reg4820; + //multiplicand high or divdend lower + case 0x4821: return s7r.reg4821; + //dividend higher + case 0x4822: return s7r.reg4822; + //dividend highest + case 0x4823: return s7r.reg4823; + //multiplier low + case 0x4824: return s7r.reg4824; + //multiplier high + case 0x4825: return s7r.reg4825; + //divisor low + case 0x4826: return s7r.reg4826; + //divisor high + case 0x4827: return s7r.reg4827; + + //result lowest + case 0x4828: + return s7r.reg4828; + //result lower + case 0x4829: + return s7r.reg4829; + //result higher + case 0x482A: + return s7r.reg482A; + //result highest + case 0x482B: + return s7r.reg482B; + //remainder (division) low + case 0x482C: return s7r.reg482C; + //remainder (division) high + case 0x482D: return s7r.reg482D; + //signed/unsigned + case 0x482E: return s7r.reg482E; + //finished flag, emulated as an on-read toggle. + case 0x482F: + if(s7r.reg482F) + { + s7r.reg482F=0; + return 0x80; + } + return 0; + break; + + //SRAM toggle + case 0x4830: + return s7r.reg4830; + //DX bank mapping + case 0x4831: + return s7r.reg4831; + //EX bank mapping + case 0x4832: + return s7r.reg4832; + //FX bank mapping + case 0x4833: + return s7r.reg4833; + //SRAM mapping? We have no clue! + case 0x4834: + return s7r.reg4834; +//RTC enable + case 0x4840: + if(!Settings.SPC7110RTC) + return Address>>8; + return s7r.reg4840; +//command/index/value of RTC (essentially, zero unless we're in read mode + case 0x4841: + if(!Settings.SPC7110RTC) + return Address>>8; + if(rtc_f9.init) + { + S9xUpdateRTC(); + uint8 tmp=rtc_f9.reg[rtc_f9.index]; + rtc_f9.index++; + rtc_f9.index%=0x10; +#ifdef SPC7110_DEBUG + printf("$4841 returned %02X\n", tmp); +#endif + return tmp; + } + else return 0; +//RTC done flag + case 0x4842: + if(!Settings.SPC7110RTC) + return Address>>8; + s7r.reg4842^=0x80; + return s7r.reg4842^0x80; + default: +#ifdef SPC7110_DEBUG + printf("Access to Reg %04X\n", Address); +#endif + return 0x00; + } +} +} +void S9xSetSPC7110 (uint8 data, uint16 Address) +{ +#ifdef SPC7110_DEBUG + printf("%04X written to, value %02X\n", Address, data); +#endif + switch(Address) + { +//Writes to $4800 are undefined. + + //table low, middle, and high. + case 0x4801: + s7r.reg4801=data; + break; + case 0x4802: + s7r.reg4802=data; + break; + case 0x4803: + s7r.reg4803=data; + break; + + //table index (4 byte entries, bigendian with a multiplier byte) + case 0x4804: + s7r.reg4804=data; + break; + + //offset low + case 0x4805: + s7r.reg4805=data; + break; + + //offset high, starts decompression + case 0x4806: + s7r.reg4806=data; + (*Copy7110)(); + s7r.bank50Internal=0; + s7r.reg480C&=0x7F; + break; + + //DMA channel register (Is it used??) + case 0x4807: + s7r.reg4807=data; + break; + + //C r/w? I have no idea. If you get weird values written here before a bug, + //The Dumper should probably be contacted about running a test. + case 0x4808: + s7r.reg4808=data; + break; + + //C-Length low + case 0x4809: + s7r.reg4809=data; + break; + //C-Length high + case 0x480A: + s7r.reg480A=data; + break; + + //Offset enable + case 0x480B: + { + s7r.reg480B=data; + int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; + + int j= 4*s7r.reg4804; + j+=s7r.DataRomOffset; + j+=table; + + if(s7r.reg480B==0) + s7r.AlignBy=0; + else + { + switch(Memory.ROM[j]) + { + case 0x03: + s7r.AlignBy=8; + break; + case 0x01: + s7r.AlignBy=2; + break; + case 0x02: + s7r.AlignBy=4; + break; + case 0x00: + default: + s7r.AlignBy=1; + break; + } + } +// s7r.decomp_set=true; + } + break; +//$4810 is probably read only. + + //Data port address low + case 0x4811: + s7r.reg4811=data; + s7r.written|=0x01; + break; + + //data port address middle + case 0x4812: + s7r.reg4812=data; + s7r.written|=0x02; + break; + + //data port address high + case 0x4813: + s7r.reg4813=data; + s7r.written|=0x04; + break; + + //data port adjust low (has a funky immediate increment mode) + case 0x4814: + s7r.reg4814=data; + if(s7r.reg4818&0x02) + { + if((s7r.reg4818&0x20)&&!(s7r.reg4818&0x40)) + { + s7r.offset_add|=0x01; + if(s7r.offset_add==3) + { + if(s7r.reg4818&0x10) + { + } + else + { + uint32 i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; + if(s7r.reg4818&0x08) + { + i+=(signed char)s7r.reg4814; + } + else + { + i+=s7r.reg4814; + } + i%=s7r.DataRomSize; + s7r.reg4811=i&0x00FF; + s7r.reg4812=(i&0x00FF00)>>8; + s7r.reg4813=((i&0xFF0000)>>16); + } + } + } + else if((s7r.reg4818&0x40)&&!(s7r.reg4818&0x20)) + { + s7r.offset_add|=0x01; + if(s7r.offset_add==3) + { + if(s7r.reg4818&0x10) + { + } + else + { + uint32 i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; + if(s7r.reg4818&0x08) + { + short adj; + adj=((short)(s7r.reg4815<<8))|s7r.reg4814; + i+=adj; + } + else + { + uint16 adj; + adj=(s7r.reg4815<<8)|s7r.reg4814; + i+=adj; + } + i%=s7r.DataRomSize; + s7r.reg4811=i&0x00FF; + s7r.reg4812=(i&0x00FF00)>>8; + s7r.reg4813=((i&0xFF0000)>>16); + } + } + + } + } + + s7r.written|=0x08; + break; + + //data port adjust high (has a funky immediate increment mode) + case 0x4815: + s7r.reg4815=data; + if(s7r.reg4818&0x02) + { + if(s7r.reg4818&0x20&&!(s7r.reg4818&0x40)) + { + s7r.offset_add|=0x02; + if(s7r.offset_add==3) + { + if(s7r.reg4818&0x10) + { + } + else + { + uint32 i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; + + if(s7r.reg4818&0x08) + { + i+=(signed char)s7r.reg4814; + } + else + { + i+=s7r.reg4814; + } + i%=s7r.DataRomSize; + s7r.reg4811=i&0x00FF; + s7r.reg4812=(i&0x00FF00)>>8; + s7r.reg4813=((i&0xFF0000)>>16); + } + } + } + else if(s7r.reg4818&0x40&&!(s7r.reg4818&0x20)) + { + s7r.offset_add|=0x02; + if(s7r.offset_add==3) + { + if(s7r.reg4818&0x10) + { + } + else + { + uint32 i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; + if(s7r.reg4818&0x08) + { + short adj; + adj=((short)(s7r.reg4815<<8))|s7r.reg4814; + i+=adj; + } + else + { + uint16 adj; + adj=(s7r.reg4815<<8)|s7r.reg4814; + i+=adj; + } + i%=s7r.DataRomSize; + s7r.reg4811=i&0x00FF; + s7r.reg4812=(i&0x00FF00)>>8; + s7r.reg4813=((i&0xFF0000)>>16); + } + } + } + } + s7r.written|=0x10; + break; + //data port increment low + case 0x4816: + s7r.reg4816=data; + break; + //data port increment high + case 0x4817: + s7r.reg4817=data; + break; + + //data port mode switches + //note that it starts inactive. + case 0x4818: + if((s7r.written&0x18)!=0x18) + break; + s7r.offset_add=0; + s7r.reg4818=data; + break; + + //multiplicand low or dividend lowest + case 0x4820: + s7r.reg4820=data; + break; + //multiplicand high or dividend lower + case 0x4821: + s7r.reg4821=data; + break; + //dividend higher + case 0x4822: + s7r.reg4822=data; + break; + //dividend highest + case 0x4823: + s7r.reg4823=data; + break; + //multiplier low + case 0x4824: + s7r.reg4824=data; + break; + //multiplier high (triggers operation) + case 0x4825: + s7r.reg4825=data; + if(s7r.reg482E&0x01) + { + int mul; + short m1=(short)((s7r.reg4824)|(s7r.reg4825<<8)); + short m2=(short)((s7r.reg4820)|(s7r.reg4821<<8)); + + mul=m1*m2; + s7r.reg4828=(uint8)(mul&0x000000FF); + s7r.reg4829=(uint8)((mul&0x0000FF00)>>8); + s7r.reg482A=(uint8)((mul&0x00FF0000)>>16); + s7r.reg482B=(uint8)((mul&0xFF000000)>>24); + } + else + { + uint32 mul; + uint16 m1=(uint16)((s7r.reg4824)|(s7r.reg4825<<8)); + uint16 m2=(uint16)((s7r.reg4820)|(s7r.reg4821<<8)); + + mul=m1*m2; + s7r.reg4828=(uint8)(mul&0x000000FF); + s7r.reg4829=(uint8)((mul&0x0000FF00)>>8); + s7r.reg482A=(uint8)((mul&0x00FF0000)>>16); + s7r.reg482B=(uint8)((mul&0xFF000000)>>24); + } + s7r.reg482F=0x80; + break; + //divisor low + case 0x4826: + s7r.reg4826=data; + break; + //divisor high (triggers operation) + case 0x4827: + s7r.reg4827=data; + if(s7r.reg482E&0x01) + { + int quotient; + short remainder; + int dividend=(int)(s7r.reg4820|(s7r.reg4821<<8)|(s7r.reg4822<<16)|(s7r.reg4823<<24)); + short divisor=(short)(s7r.reg4826|(s7r.reg4827<<8)); + if(divisor != 0) + { + quotient=(int)(dividend/divisor); + remainder=(short)(dividend%divisor); + } + else + { + quotient=0; + remainder=dividend&0x0000FFFF; + } + s7r.reg4828=(uint8)(quotient&0x000000FF); + s7r.reg4829=(uint8)((quotient&0x0000FF00)>>8); + s7r.reg482A=(uint8)((quotient&0x00FF0000)>>16); + s7r.reg482B=(uint8)((quotient&0xFF000000)>>24); + s7r.reg482C=(uint8)remainder&0x00FF; + s7r.reg482D=(uint8)((remainder&0xFF00)>>8); + } + else + { + uint32 quotient; + uint16 remainder; + uint32 dividend=(uint32)(s7r.reg4820|(s7r.reg4821<<8)|(s7r.reg4822<<16)|(s7r.reg4823<<24)); + uint16 divisor=(uint16)(s7r.reg4826|(s7r.reg4827<<8)); + if(divisor != 0) + { + quotient=(uint32)(dividend/divisor); + remainder=(uint16)(dividend%divisor); + } + else + { + quotient=0; + remainder=dividend&0x0000FFFF; + } + s7r.reg4828=(uint8)(quotient&0x000000FF); + s7r.reg4829=(uint8)((quotient&0x0000FF00)>>8); + s7r.reg482A=(uint8)((quotient&0x00FF0000)>>16); + s7r.reg482B=(uint8)((quotient&0xFF000000)>>24); + s7r.reg482C=(uint8)remainder&0x00FF; + s7r.reg482D=(uint8)((remainder&0xFF00)>>8); + } + s7r.reg482F=0x80; + break; + //result registers are possibly read-only + + //reset: writes here nuke the whole math unit + //Zero indicates unsigned math, resets with non-zero values turn on signed math + case 0x482E: + s7r.reg4820=s7r.reg4821=s7r.reg4822=s7r.reg4823=s7r.reg4824=s7r.reg4825=s7r.reg4826=s7r.reg4827=s7r.reg4828=s7r.reg4829=s7r.reg482A=s7r.reg482B=s7r.reg482C=s7r.reg482D=0; + s7r.reg482E=data; + break; + + //math status register possibly read only + + //SRAM toggle + case 0x4830: + SetSPC7110SRAMMap(data); + s7r.reg4830=data; + break; + //Bank DX mapping + case 0x4831: + s7r.reg4831=data; + break; + //Bank EX mapping + case 0x4832: + s7r.reg4832=data; + break; + //Bank FX mapping + case 0x4833: + s7r.reg4833=data; + break; + //S-RAM mapping? who knows? + case 0x4834: + s7r.reg4834=data; + break; + //RTC Toggle + case 0x4840: + if(0==data) + { + S9xUpdateRTC(); + // rtc_f9.init=false; + // rtc_f9.index=-1; + } + if(data&0x01) + { + s7r.reg4842=0x80; + //rtc_f9.last_used=time(NULL);//???? + rtc_f9.init=false; + rtc_f9.index=-1; + } + s7r.reg4840=data; + break; + //RTC init/command/index register + case 0x4841: + if(rtc_f9.init) + { + if(-1==rtc_f9.index) + { + rtc_f9.index=data&0x0F; + break; + } + if(rtc_f9.control==0x0C) + { + rtc_f9.index=data&0x0F; + s7r.reg4842=0x80; + rtc_f9.last_used=time(NULL); + } + else + { + + if(0x0D==rtc_f9.index) + { + if(data&0x08) + { + if(rtc_f9.reg[1]<3) + { + S9xUpdateRTC(); + rtc_f9.reg[0]=0; + rtc_f9.reg[1]=0; + rtc_f9.last_used=time(NULL); + } + else + { + S9xUpdateRTC(); + rtc_f9.reg[0]=0; + rtc_f9.reg[1]=0; + rtc_f9.last_used=time(NULL)-60; + S9xUpdateRTC(); + rtc_f9.last_used=time(NULL); + } + data&=0x07; + } + if(rtc_f9.reg[0x0D]&0x01) + { + if(!(data%2)) + { + rtc_f9.reg[rtc_f9.index&0x0F]=data; + rtc_f9.last_used=time(NULL)-1; + S9xUpdateRTC(); + rtc_f9.last_used=time(NULL); + } + } + } + if(0x0F==rtc_f9.index) + { + if(data&0x01&&!(rtc_f9.reg[0x0F]&0x01)) + { + S9xUpdateRTC(); + rtc_f9.reg[0]=0; + rtc_f9.reg[1]=0; + rtc_f9.last_used=time(NULL); + } + if(data&0x02&&!(rtc_f9.reg[0x0F]&0x02)) + { + S9xUpdateRTC(); + rtc_f9.last_used=time(NULL); + } + } + rtc_f9.reg[rtc_f9.index&0x0F]=data; + s7r.reg4842=0x80; + rtc_f9.index=(rtc_f9.index+1)%0x10; + } + } + else + { + if(data==0x03||data==0x0C) + { + rtc_f9.init=true; + rtc_f9.control=data; + rtc_f9.index=-1; + } + } + break; + //writes to RTC status register aren't expected to be meaningful + default: + Address-=0x4800; + break; + //16 BIT MULTIPLIER: ($FF00) high byte, defval:00 + } +} +extern "C"{ +//emulate the SPC7110's ability to remap banks Dx, Ex, and Fx. +uint8 S9xGetSPC7110Byte(uint32 Address) +{ + uint32 i; + switch((Address&0x00F00000)>>16) + { + case 0xD0: + i=s7r.reg4831*0x00100000; + break; + case 0xE0: + i=s7r.reg4832*0x00100000; + break; + case 0xF0: + i=s7r.reg4833*0x00100000; + break; + default:i=0; + } + i+=Address&0x000FFFFF; + i+=s7r.DataRomOffset; + return Memory.ROM[i]; +} +} +/**********************************************************************************************/ +/* S9xSRTCDaysInMonth() */ +/* Return the number of days in a specific month for a certain year */ +/* copied directly for RTC functionality, separated in case of incompatibilities */ +/**********************************************************************************************/ +int S9xRTCDaysInMonth( int month, int year ) +{ + int mdays; + + switch ( month ) + { + case 2: + if ( ( year % 4 == 0 ) ) // DKJM2 only uses 199x - 22xx + mdays = 29; + else + mdays = 28; + break; + + case 4: + case 6: + case 9: + case 11: + mdays = 30; + break; + + default: // months 1,3,5,7,8,10,12 + mdays = 31; + break; + } + + return mdays; +} + + +#define DAYTICKS (60*60*24) +#define HOURTICKS (60*60) +#define MINUTETICKS 60 + + +/**********************************************************************************************/ +/* S9xUpdateRTC() */ +/* Advance the RTC time */ +/**********************************************************************************************/ + +void S9xUpdateRTC () +{ + time_t cur_systime; + long time_diff; + + // Keep track of game time by computing the number of seconds that pass on the system + // clock and adding the same number of seconds to the RTC clock structure. + + if (rtc_f9.init && 0==(rtc_f9.reg[0x0D]&0x01) && 0==(rtc_f9.reg[0x0F]&0x03)) + { + cur_systime = time (NULL); + + // This method assumes one time_t clock tick is one second + // which should work on PCs and GNU systems. + // If your tick interval is different adjust the + // DAYTICK, HOURTICK, and MINUTETICK defines + + time_diff = (long) (cur_systime - rtc_f9.last_used); + rtc_f9.last_used = cur_systime; + + if ( time_diff > 0 ) + { + int seconds; + int minutes; + int hours; + int days; + int month; + int year; + int temp_days; + + int year_hundreds; + int year_tens; + int year_ones; + + + if ( time_diff > DAYTICKS ) + { + days = time_diff / DAYTICKS; + time_diff = time_diff - days * DAYTICKS; + } + else + { + days = 0; + } + + if ( time_diff > HOURTICKS ) + { + hours = time_diff / HOURTICKS; + time_diff = time_diff - hours * HOURTICKS; + } + else + { + hours = 0; + } + + if ( time_diff > MINUTETICKS ) + { + minutes = time_diff / MINUTETICKS; + time_diff = time_diff - minutes * MINUTETICKS; + } + else + { + minutes = 0; + } + + if ( time_diff > 0 ) + { + seconds = time_diff; + } + else + { + seconds = 0; + } + + + seconds += (rtc_f9.reg[1]*10 + rtc_f9.reg[0]); + if ( seconds >= 60 ) + { + seconds -= 60; + minutes += 1; + } + + minutes += (rtc_f9.reg[3]*10 + rtc_f9.reg[2]); + if ( minutes >= 60 ) + { + minutes -= 60; + hours += 1; + } + + hours += (rtc_f9.reg[5]*10 + rtc_f9.reg[4]); + if ( hours >= 24 ) + { + hours -= 24; + days += 1; + } + + year = rtc_f9.reg[11]*10 + rtc_f9.reg[10]; + year += ( 1900 ); + month = rtc_f9.reg[8]+10*rtc_f9.reg[9]; + rtc_f9.reg[12]+=days; + days += (rtc_f9.reg[7]*10 + rtc_f9.reg[6]); + if ( days > 0 ) + { + while ( days > (temp_days = S9xRTCDaysInMonth( month, year )) ) + { + days -= temp_days; + month += 1; + if ( month > 12 ) + { + year += 1; + month = 1; + } + } + } + + year_tens = year % 100; + year_ones = year_tens % 10; + year_tens /= 10; + year_hundreds = (year - 1000) / 100; + + rtc_f9.reg[0] = seconds % 10; + rtc_f9.reg[1] = seconds / 10; + rtc_f9.reg[2] = minutes % 10; + rtc_f9.reg[3] = minutes / 10; + rtc_f9.reg[4] = hours % 10; + rtc_f9.reg[5] = hours / 10; + rtc_f9.reg[6] = days % 10; + rtc_f9.reg[7] = days / 10; + rtc_f9.reg[8] = month%10; + rtc_f9.reg[9] = month /10; + rtc_f9.reg[10] = year_ones; + rtc_f9.reg[11] = year_tens; + rtc_f9.reg[12] %= 7; + return; + } + } +} +extern "C"{ + +//allows DMA from the ROM (is this even possible on the SPC7110? +uint8* Get7110BasePtr(uint32 Address) +{ + uint32 i; + switch((Address&0x00F00000)>>16) + { + case 0xD0: + i=s7r.reg4831*0x100000; + break; + case 0xE0: + i=s7r.reg4832*0x100000; + break; + case 0xF0: + i=s7r.reg4833*0x100000; + break; + default:i=0; + } + i+=Address&0x000F0000; + return &Memory.ROM[i]; +} +//end extern +} + +//loads the index into memory. +//index.bin is little-endian +//format index (1)-table(3)-file offset(4)-length(4) +bool Load7110Index(char* filename) +{ + FILE* fp; + uint8 buffer[12]; + int table=0; + uint8 index=0; + uint32 offset=0; + uint32 size=0; + int i=0; + fp=fopen(filename, "rb"); + if(NULL==fp) + return false; + do + { + i=0; + fread(buffer, 1, 12,fp); + table=(buffer[3]<<16)|(buffer[2]<<8)|buffer[1]; + index=buffer[0]; + offset=(buffer[7]<<24)|(buffer[6]<<16)|(buffer[5]<<8)|buffer[4]; + size=(buffer[11]<<24)|(buffer[10]<<16)|(buffer[9]<<8)|buffer[8]; + while(itableEnts[i].table!=table&&decompack->tableEnts[i].table!=0) + i++; + if(i==MAX_TABLES) + return false; + //added + decompack->tableEnts[i].table=table; + //----- + decompack->tableEnts[i].location[index].offset=offset; + decompack->tableEnts[i].location[index].size=size; + decompack->tableEnts[i].location[index].used_len=0; + decompack->tableEnts[i].location[index].used_offset=0; + + } + while(!feof(fp)); + fclose(fp); + return true; +} + + +//Cache 1 load function +void SPC7110Load(char* dirname) +{ + char temp_path[PATH_MAX]; + int i=0; + + decompack=new Pack7110; + +#ifndef _XBOX + getcwd(temp_path,PATH_MAX); +#endif + + ZeroMemory(decompack, sizeof(Pack7110)); + +#ifndef _XBOX + if(-1==chdir(dirname)) + { + S9xMessage(0,0,"Graphics Pack not found!"); + } +#endif + +#ifndef _XBOX + Load7110Index("index.bin"); +#else + // D:\\ is always app.path in Xbox + Load7110Index("d:\\index.bin"); +#endif + + for(i=0;itableEnts[i].table!=0) + { + char binname[PATH_MAX]; +#ifndef _XBOX + sprintf(binname,"%06X.bin",decompack->tableEnts[i].table); +#else + sprintf(binname,"%s%06X.bin",filename,decompack->tableEnts[i].table); +#endif + struct stat buf; + if(-1!=stat(binname, &buf)) + decompack->binfiles[i]=new uint8[buf.st_size]; + FILE* fp=fopen(binname, "rb"); + if(fp) + { + fread(decompack->binfiles[i],buf.st_size,1,fp); + fclose(fp); + } + } + } + +#ifndef _XBOX + chdir(temp_path); +#endif + + Copy7110=&MovePackData; + CleanUp7110=&Del7110Gfx; +#ifdef __WIN32__ + #ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_LOG_7110, MF_ENABLED); + #endif +#endif +} + +//Cache 2 load function +void SPC7110Open(char* dirname) +{ + char temp_path[PATH_MAX]; + int i=0; + + decompack=new Pack7110; + +#ifndef _XBOX + getcwd(temp_path,PATH_MAX); +#endif + + ZeroMemory(decompack, sizeof(Pack7110)); + +#ifndef _XBOX + if(-1==chdir(dirname)) + { + S9xMessage(0,0,"Graphics Pack not found!"); + } +#endif + +#ifndef _XBOX + Load7110Index("index.bin"); +#else + // D:\\ is always app.path in Xbox + Load7110Index("d:\\index.bin"); +#endif + + for (i=0; ibinfiles[i]=NULL; + + ReadPackData(); + +#ifndef _XBOX + chdir(temp_path); +#endif + + Copy7110=&ReadPackData; + CleanUp7110=&Close7110Gfx; + +#ifdef __WIN32__ + #ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_LOG_7110, MF_ENABLED); + #endif +#endif +} + +//Cache 3's load function +void SPC7110Grab(char* dirname) +{ + char temp_path[PATH_MAX]; + int i=0; + + decompack=new Pack7110; + +#ifndef _XBOX + getcwd(temp_path,PATH_MAX); +#endif + + int32 buffer_size=1024*1024*cacheMegs;//*some setting + + ZeroMemory(decompack, sizeof(Pack7110)); +#ifndef _XBOX + + if(-1==chdir(dirname)) + { + S9xMessage(0,0,"Graphics Pack not found!"); + } +#endif + +#ifndef _XBOX + Load7110Index("index.bin"); +#else + // D:\\ is always app.path in Xbox + Load7110Index("d:\\index.bin"); +#endif + + for(i=0;itableEnts[i].table!=0) + { + char binname[PATH_MAX]; +#ifndef _XBOX + sprintf(binname,"%06X.bin",decompack->tableEnts[i].table); +#else + sprintf(binname,"%s%06X.bin",filename,decompack->tableEnts[i].table); +#endif + struct stat buf; +//add load/no load calculations here + if(-1!=stat(binname, &buf)) + { + if(buf.st_sizebinfiles[i]=new uint8[buf.st_size]; + FILE* fp=fopen(binname, "rb"); + //use them here + if(fp) + { + if(buf.st_sizebinfiles[i],buf.st_size,1,fp); + fclose(fp); + buffer_size-=buf.st_size; + decompack->tableEnts[i].is_file=false; + } + else + { + decompack->binfiles[i]=(uint8*)fp; + decompack->tableEnts[i].is_file=true; + } + } + } + } + } + +#ifndef _XBOX + chdir(temp_path); +#endif + + Copy7110=&GetPackData; + CleanUp7110=&Drop7110Gfx; + + +#ifdef __WIN32__ + #ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_LOG_7110, MF_ENABLED); + #endif +#endif +} + +//Cache 1 clean up function +void Del7110Gfx() +{ + int i; + if(Settings.SPC7110) + { +#ifdef __WIN32__ + #ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_LOG_7110, MF_GRAYED); + #endif +#endif + Do7110Logging(); + } + for(i=0;ibinfiles[i]!=NULL) + { + delete []decompack->binfiles[i]; + decompack->binfiles[i]=NULL; + } + } + Settings.SPC7110=false; + Settings.SPC7110RTC=false; + if(NULL!=decompack) + delete decompack; + decompack=NULL; + CleanUp7110=NULL; + Copy7110=NULL; +} + +//Cache2 cleanup function +void Close7110Gfx() +{ + int i; + if(Settings.SPC7110) + { +#ifdef __WIN32__ + #ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_LOG_7110, MF_GRAYED); + #endif +#endif + Do7110Logging(); + } + for(i=0;ibinfiles[i]!=NULL) + { + fclose((FILE*)decompack->binfiles[i]); + decompack->binfiles[i]=NULL; + } + } + Settings.SPC7110=false; + Settings.SPC7110RTC=false; + if(NULL!=decompack) + delete decompack; + decompack=NULL; + CleanUp7110=NULL; + Copy7110=NULL; +} + +//cache 3's clean-up code +void Drop7110Gfx() +{ + int i; + if(Settings.SPC7110) + { +#ifdef __WIN32__ + #ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_LOG_7110, MF_GRAYED); + #endif +#endif + Do7110Logging(); + } + for(i=0;ibinfiles[i]!=NULL) + { + if(decompack->tableEnts[i].is_file) + { + fclose((FILE*)decompack->binfiles[i]); + decompack->binfiles[i]=NULL; + } + else + { + delete []decompack->binfiles[i]; + decompack->binfiles[i]=NULL; + } + } + } + Settings.SPC7110=false; + Settings.SPC7110RTC=false; + if(NULL!=decompack) + delete decompack; + decompack=NULL; + CleanUp7110=NULL; + Copy7110=NULL; +} + +//emulate a reset. +void S9xSpc7110Reset() +{ + s7r.reg4800=0; + s7r.reg4801=0; + s7r.reg4802=0; + s7r.reg4803=0; + s7r.reg4804=0; + s7r.reg4805=0; + s7r.reg4806=0; + s7r.reg4807=0; + s7r.reg4808=0; + s7r.reg4809=0; + s7r.reg480A=0; + s7r.reg480B=0; + s7r.reg480C=0; + s7r.reg4811=0; + s7r.reg4812=0; + s7r.reg4813=0; + s7r.reg4814=0; + s7r.reg4815=0; + s7r.reg4816=0; + s7r.reg4817=0; + s7r.reg4818=0; + s7r.reg4820=0; + s7r.reg4821=0; + s7r.reg4822=0; + s7r.reg4823=0; + s7r.reg4824=0; + s7r.reg4825=0; + s7r.reg4826=0; + s7r.reg4827=0; + s7r.reg4828=0; + s7r.reg4829=0; + s7r.reg482A=0; + s7r.reg482B=0; + s7r.reg482C=0; + s7r.reg482D=0; + s7r.reg482E=0; + s7r.reg482F=0; + s7r.reg4830=0; + s7r.reg4831=0; + s7r.reg4832=1; + s7r.reg4833=2; + s7r.reg4834=0; + s7r.reg4840=0; + s7r.reg4841=0; + s7r.reg4842=0; + s7r.written=0; + s7r.offset_add=0; + s7r.AlignBy=1; + s7r.bank50Internal=0; + memset(s7r.bank50,0x00,DECOMP_BUFFER_SIZE); +} + + +//outputs a cumulative log for the game. +//there's nothing really weird here, just +//reading the old log, and writing a new one. +//note the logs are explicitly little-endian, not host byte order. +void Do7110Logging() +{ + uint8 ent_temp; + FILE* flog; + int entries=0; + + if(Settings.SPC7110) + { + //flush last read into logging + (*Copy7110)(); + +#ifdef __MACOSX__ + char name[PATH_MAX + 1]; + strcpy(name, S9xGetFilename(".dat", DEFAULT_DIR)); + flog = fopen(name, "rb"); +#else + if(!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21)) + { +#ifdef _XBOX + flog=fopen("T:\\spl4-sp7.dat","rb"); +#else + flog=fopen("spl4-sp7.dat","rb"); +#endif + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ",21)) + { +#ifdef _XBOX + flog=fopen("T:\\smht-sp7.dat","rb"); +#else + flog=fopen("smht-sp7.dat","rb"); +#endif + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21)) + { +#ifdef _XBOX + flog=fopen("T:\\feoezsp7.dat","rb"); +#else + flog=fopen("feoezsp7.dat","rb"); +#endif + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO",21)) + { +#ifdef _XBOX + flog=fopen("T:\\sjumpsp7.dat","rb"); +#else + flog=fopen("sjumpsp7.dat","rb"); +#endif + } + else + { +#ifdef _XBOX + flog=fopen("T:\\misc-sp7.dat","rb"); +#else + flog=fopen("misc-sp7.dat","rb"); +#endif + } +#endif + + if(flog) + { + uint8 buffer[8]; + int table=0; + uint16 offset=0; + uint16 length=0; + fseek(flog, 35,0); + do + { + int i=0; + Data7110 *log=NULL; + fread(buffer, 1, 8, flog); + table=buffer[0]|(buffer[1]<<8)|(buffer[2]<<16); + offset=buffer[6]|(buffer[7]<<8); + length=buffer[4]|(buffer[5]<<8); + while(itableEnts[i].table==table) + { + log=&(decompack->tableEnts[i].location[(buffer[3])]); + if((log->used_offset+log->used_len)<(offset+length)) + { + log->used_offset=offset; + log->used_len=length; + } + } + i++; + } + } + while(!feof(flog)); + fclose(flog); + } + +#ifdef __MACOSX__ + strcpy(name, S9xGetFilename(".dat", DEFAULT_DIR)); + flog = fopen(name, "rb"); +#else + if(!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21)) + { +#ifdef _XBOX // cwd could be the dvd-rom, so write to T:\\ which is storage region for each title + flog=fopen("T:\\spl4-sp7.dat","wb"); +#else + flog=fopen("spl4-sp7.dat","wb"); +#endif + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ",21)) + { +#ifdef _XBOX + flog=fopen("T:\\smht-sp7.dat","wb"); +#else + flog=fopen("smht-sp7.dat","wb"); +#endif + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21)) + { +#ifdef _XBOX + flog=fopen("T:\\feoezsp7.dat","wb"); +#else + flog=fopen("feoezsp7.dat","wb"); +#endif + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO",21)) + { +#ifdef _XBOX + flog=fopen("T:\\sjumpsp7.dat","wb"); +#else + flog=fopen("sjumpsp7.dat","wb"); +#endif + } + else + { +#ifdef _XBOX + flog=fopen("T:\\misc-sp7.dat","wb"); +#else + flog=fopen("misc-sp7.dat","wb"); +#endif + } +#endif + //count entries + if(flog) + { + int j=0; + int temp=0; + for(j=0;jtableEnts[j].location[k].used_len!=0) + entries++; + } + } + ent_temp=entries&0xFF; + fwrite(&ent_temp,1,1,flog); + ent_temp=(entries>>8)&0xFF; + fwrite(&ent_temp,1,1,flog); + ent_temp=(entries>>16)&0xFF; + fwrite(&ent_temp,1,1,flog); + ent_temp=(entries>>24)&0xFF; + fwrite(&ent_temp,1,1,flog); + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + + ent_temp=0; + fwrite(&ent_temp,1,1,flog); + ent_temp=0; + fwrite(&ent_temp,1,1,flog); + ent_temp=0; + fwrite(&ent_temp,1,1,flog); + + for(j=0;jtableEnts[j].location[k].used_len!=0) + { + ent_temp=decompack->tableEnts[j].table&0xFF; + fwrite(&ent_temp,1,1,flog);//801 + ent_temp=(decompack->tableEnts[j].table>>8)&0xFF;; + fwrite(&ent_temp,1,1,flog);//802 + ent_temp=(decompack->tableEnts[j].table>>16)&0xFF;; + fwrite(&ent_temp,1,1,flog);//803 + ent_temp=k&0xFF; + fwrite(&ent_temp,1,1,flog);//804 + ent_temp=decompack->tableEnts[j].location[k].used_len&0xFF; + fwrite(&ent_temp,1,1,flog);//lsb of + ent_temp=(decompack->tableEnts[j].location[k].used_len>>8)&0xFF; + fwrite(&ent_temp,1,1,flog);//msb of + ent_temp=(decompack->tableEnts[j].location[k].used_offset)&0xFF; + fwrite(&ent_temp,1,1,flog);//lsb of + ent_temp=(decompack->tableEnts[j].location[k].used_offset>>8)&0xFF; + fwrite(&ent_temp,1,1,flog);//msb of + } + } + } + fwrite(&temp,1,4,flog); + fwrite(&temp,1,4,flog); + fclose(flog); + } + } } static void SetSPC7110SRAMMap (uint8 newstate) @@ -232,241 +2373,63 @@ static void SetSPC7110SRAMMap (uint8 newstate) } } -uint8 * S9xGetBasePointerSPC7110 (uint32 address) +bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9) { - uint32 i; - - switch (address & 0xf00000) + FILE* fp; + + if((fp=fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb"))==NULL) + return (FALSE); + int i=0; + uint8 temp=0; + for (i=0;i<16;i++) + fwrite(&rtc_f9->reg[i],1,1,fp); + temp=rtc_f9->index&0x00FF; + fwrite(&temp,1,1,fp); + temp=(rtc_f9->index)>>8; + fwrite(&temp,1,1,fp); + temp=(uint8)rtc_f9->control; + fwrite(&temp,1,1,fp); + temp=(uint8)rtc_f9->init; + fwrite(&temp,1,1,fp); + temp=rtc_f9->last_used&0x00FF; + fwrite(&temp,1,1,fp); + temp=(rtc_f9->last_used>>8)&0x00FF; + fwrite(&temp,1,1,fp); + temp=(rtc_f9->last_used>>16)&0x00FF; + fwrite(&temp,1,1,fp); + temp=(rtc_f9->last_used>>24)&0x00FF;; + fwrite(&temp,1,1,fp); + fclose(fp); + return (TRUE); +} + +bool8 S9xLoadSPC7110RTC (S7RTC *rtc_f9) +{ + FILE* fp; + + if((fp=fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb"))==NULL) + return (FALSE); + for (int i=0; i<16;i++) { - case 0xd00000: - i = s7emu.dx_offset; - break; - - case 0xe00000: - i = s7emu.ex_offset; - break; - - case 0xf00000: - i = s7emu.fx_offset; - break; - - default: - i = 0; - break; + fread(&(rtc_f9->reg[i]),1,1,fp); } - - i += address & 0x0f0000; + uint8 temp=0; + fread(&temp,1,1,fp); + rtc_f9->index=temp; + fread(&temp,1,1,fp); + rtc_f9->index|=(temp<<8); + fread(&rtc_f9->control,1,1,fp); + fread(&rtc_f9->init,1,1,fp); - return (&Memory.ROM[i]); + fread(&temp,1,1,fp); + rtc_f9->last_used=temp; + fread(&temp,1,1,fp); + rtc_f9->last_used|=(temp<<8); + fread(&temp,1,1,fp); + rtc_f9->last_used|=(temp<<16); + fread(&temp,1,1,fp); + rtc_f9->last_used|=(temp<<24); + fclose(fp); + return (TRUE); } -uint8 S9xGetSPC7110Byte (uint32 address) -{ - uint32 i; - - switch (address & 0xf00000) - { - case 0xd00000: - i = s7emu.dx_offset; - break; - - case 0xe00000: - i = s7emu.ex_offset; - break; - - case 0xf00000: - i = s7emu.fx_offset; - break; - - default: - i = 0; - break; - } - - i += address & 0x0fffff; - - return (Memory.ROM[i]); -} - -uint8 S9xGetSPC7110 (uint16 address) -{ - if (!Settings.SPC7110RTC && address > 0x483f) - return (OpenBus); - - return (s7emu.mmio_read(address)); -} - -void S9xSetSPC7110 (uint8 byte, uint16 address) -{ - if (!Settings.SPC7110RTC && address > 0x483f) - return; - - if (address == 0x4830) - SetSPC7110SRAMMap(byte); - - s7emu.mmio_write(address, byte); -} - -void S9xSPC7110PreSaveState (void) -{ - s7snap.r4801 = s7emu.r4801; - s7snap.r4802 = s7emu.r4802; - s7snap.r4803 = s7emu.r4803; - s7snap.r4804 = s7emu.r4804; - s7snap.r4805 = s7emu.r4805; - s7snap.r4806 = s7emu.r4806; - s7snap.r4807 = s7emu.r4807; - s7snap.r4808 = s7emu.r4808; - s7snap.r4809 = s7emu.r4809; - s7snap.r480a = s7emu.r480a; - s7snap.r480b = s7emu.r480b; - s7snap.r480c = s7emu.r480c; - - s7snap.r4811 = s7emu.r4811; - s7snap.r4812 = s7emu.r4812; - s7snap.r4813 = s7emu.r4813; - s7snap.r4814 = s7emu.r4814; - s7snap.r4815 = s7emu.r4815; - s7snap.r4816 = s7emu.r4816; - s7snap.r4817 = s7emu.r4817; - s7snap.r4818 = s7emu.r4818; - - s7snap.r481x = s7emu.r481x; - - s7snap.r4814_latch = s7emu.r4814_latch ? TRUE : FALSE; - s7snap.r4815_latch = s7emu.r4815_latch ? TRUE : FALSE; - - s7snap.r4820 = s7emu.r4820; - s7snap.r4821 = s7emu.r4821; - s7snap.r4822 = s7emu.r4822; - s7snap.r4823 = s7emu.r4823; - s7snap.r4824 = s7emu.r4824; - s7snap.r4825 = s7emu.r4825; - s7snap.r4826 = s7emu.r4826; - s7snap.r4827 = s7emu.r4827; - s7snap.r4828 = s7emu.r4828; - s7snap.r4829 = s7emu.r4829; - s7snap.r482a = s7emu.r482a; - s7snap.r482b = s7emu.r482b; - s7snap.r482c = s7emu.r482c; - s7snap.r482d = s7emu.r482d; - s7snap.r482e = s7emu.r482e; - s7snap.r482f = s7emu.r482f; - - s7snap.r4830 = s7emu.r4830; - s7snap.r4831 = s7emu.r4831; - s7snap.r4832 = s7emu.r4832; - s7snap.r4833 = s7emu.r4833; - s7snap.r4834 = s7emu.r4834; - - s7snap.dx_offset = (uint32) s7emu.dx_offset; - s7snap.ex_offset = (uint32) s7emu.ex_offset; - s7snap.fx_offset = (uint32) s7emu.fx_offset; - - s7snap.r4840 = s7emu.r4840; - s7snap.r4841 = s7emu.r4841; - s7snap.r4842 = s7emu.r4842; - - s7snap.rtc_state = (int32) s7emu.rtc_state; - s7snap.rtc_mode = (int32) s7emu.rtc_mode; - s7snap.rtc_index = (uint32) s7emu.rtc_index; - - s7snap.decomp_mode = (uint32) s7emu.decomp.decomp_mode; - s7snap.decomp_offset = (uint32) s7emu.decomp.decomp_offset; - - for (int i = 0; i < SPC7110_DECOMP_BUFFER_SIZE; i++) - s7snap.decomp_buffer[i] = s7emu.decomp.decomp_buffer[i]; - - s7snap.decomp_buffer_rdoffset = (uint32) s7emu.decomp.decomp_buffer_rdoffset; - s7snap.decomp_buffer_wroffset = (uint32) s7emu.decomp.decomp_buffer_wroffset; - s7snap.decomp_buffer_length = (uint32) s7emu.decomp.decomp_buffer_length; - - for (int i = 0; i < 32; i++) - { - s7snap.context[i].index = s7emu.decomp.context[i].index; - s7snap.context[i].invert = s7emu.decomp.context[i].invert; - } -} - -void S9xSPC7110PostLoadState (int version) -{ - s7emu.r4801 = s7snap.r4801; - s7emu.r4802 = s7snap.r4802; - s7emu.r4803 = s7snap.r4803; - s7emu.r4804 = s7snap.r4804; - s7emu.r4805 = s7snap.r4805; - s7emu.r4806 = s7snap.r4806; - s7emu.r4807 = s7snap.r4807; - s7emu.r4808 = s7snap.r4808; - s7emu.r4809 = s7snap.r4809; - s7emu.r480a = s7snap.r480a; - s7emu.r480b = s7snap.r480b; - s7emu.r480c = s7snap.r480c; - - s7emu.r4811 = s7snap.r4811; - s7emu.r4812 = s7snap.r4812; - s7emu.r4813 = s7snap.r4813; - s7emu.r4814 = s7snap.r4814; - s7emu.r4815 = s7snap.r4815; - s7emu.r4816 = s7snap.r4816; - s7emu.r4817 = s7snap.r4817; - s7emu.r4818 = s7snap.r4818; - - s7emu.r481x = s7snap.r481x; - - s7emu.r4814_latch = s7snap.r4814_latch ? true : false; - s7emu.r4815_latch = s7snap.r4815_latch ? true : false; - - s7emu.r4820 = s7snap.r4820; - s7emu.r4821 = s7snap.r4821; - s7emu.r4822 = s7snap.r4822; - s7emu.r4823 = s7snap.r4823; - s7emu.r4824 = s7snap.r4824; - s7emu.r4825 = s7snap.r4825; - s7emu.r4826 = s7snap.r4826; - s7emu.r4827 = s7snap.r4827; - s7emu.r4828 = s7snap.r4828; - s7emu.r4829 = s7snap.r4829; - s7emu.r482a = s7snap.r482a; - s7emu.r482b = s7snap.r482b; - s7emu.r482c = s7snap.r482c; - s7emu.r482d = s7snap.r482d; - s7emu.r482e = s7snap.r482e; - s7emu.r482f = s7snap.r482f; - - s7emu.r4830 = s7snap.r4830; - s7emu.r4831 = s7snap.r4831; - s7emu.r4832 = s7snap.r4832; - s7emu.r4833 = s7snap.r4833; - s7emu.r4834 = s7snap.r4834; - - s7emu.dx_offset = (unsigned) s7snap.dx_offset; - s7emu.ex_offset = (unsigned) s7snap.ex_offset; - s7emu.fx_offset = (unsigned) s7snap.fx_offset; - - s7emu.r4840 = s7snap.r4840; - s7emu.r4841 = s7snap.r4841; - s7emu.r4842 = s7snap.r4842; - - s7emu.rtc_state = (SPC7110::RTC_State) s7snap.rtc_state; - s7emu.rtc_mode = (SPC7110::RTC_Mode) s7snap.rtc_mode; - s7emu.rtc_index = (unsigned) s7snap.rtc_index; - - s7emu.decomp.decomp_mode = (unsigned) s7snap.decomp_mode; - s7emu.decomp.decomp_offset = (unsigned) s7snap.decomp_offset; - - for (int i = 0; i < SPC7110_DECOMP_BUFFER_SIZE; i++) - s7emu.decomp.decomp_buffer[i] = s7snap.decomp_buffer[i]; - - s7emu.decomp.decomp_buffer_rdoffset = (unsigned) s7snap.decomp_buffer_rdoffset; - s7emu.decomp.decomp_buffer_wroffset = (unsigned) s7snap.decomp_buffer_wroffset; - s7emu.decomp.decomp_buffer_length = (unsigned) s7snap.decomp_buffer_length; - - for (int i = 0; i < 32; i++) - { - s7emu.decomp.context[i].index = s7snap.context[i].index; - s7emu.decomp.context[i].invert = s7snap.context[i].invert; - } - - s7emu.update_time(0); -} diff --git a/source/snes9x/spc7110.h b/source/snes9x/spc7110.h index 0592030..7d12b78 100644 --- a/source/snes9x/spc7110.h +++ b/source/snes9x/spc7110.h @@ -159,101 +159,111 @@ **********************************************************************************/ -#ifndef _SPC7110_H_ -#define _SPC7110_H_ -#define SPC7110_DECOMP_BUFFER_SIZE 64 +#ifndef _spc7110_h +#define _spc7110_h +#include "port.h" -// for snapshot only -struct SSPC7110Snapshot +#define DECOMP_BUFFER_SIZE 0x10000 + +extern void (*LoadUp7110)(char*); +extern void (*CleanUp7110)(void); +extern void (*Copy7110)(void); + +extern uint16 cacheMegs; + +void Del7110Gfx(void); +void Close7110Gfx(void); +void Drop7110Gfx(void); +extern "C"{ +uint8 S9xGetSPC7110(uint16 Address); +uint8 S9xGetSPC7110Byte(uint32 Address); +uint8* Get7110BasePtr(uint32); +} +void S9xSetSPC7110 (uint8 data, uint16 Address); +void S9xSpc7110Init(); +uint8* Get7110BasePtr(uint32); +void S9xSpc7110Reset(); +void S9xUpdateRTC (); +void Do7110Logging(); +int S9xRTCDaysInMonth( int month, int year ); + +//These are platform-dependant functions, but should work on +//most systems that use GNU compilers, and on Win32. +void SPC7110Load(char*); +void SPC7110Open(char*); +void SPC7110Grab(char*); + +typedef struct SPC7110RTC { - uint8 r4801; - uint8 r4802; - uint8 r4803; - uint8 r4804; - uint8 r4805; - uint8 r4806; - uint8 r4807; - uint8 r4808; - uint8 r4809; - uint8 r480a; - uint8 r480b; - uint8 r480c; + unsigned char reg[16]; + short index; + uint8 control; + bool init; + time_t last_used; +} S7RTC; - uint8 r4811; - uint8 r4812; - uint8 r4813; - uint8 r4814; - uint8 r4815; - uint8 r4816; - uint8 r4817; - uint8 r4818; +typedef struct SPC7110EmuVars +{ + unsigned char reg4800; + unsigned char reg4801; + unsigned char reg4802; + unsigned char reg4803; + unsigned char reg4804; + unsigned char reg4805; + unsigned char reg4806; + unsigned char reg4807; + unsigned char reg4808; + unsigned char reg4809; + unsigned char reg480A; + unsigned char reg480B; + unsigned char reg480C; + unsigned char reg4811; + unsigned char reg4812; + unsigned char reg4813; + unsigned char reg4814; + unsigned char reg4815; + unsigned char reg4816; + unsigned char reg4817; + unsigned char reg4818; + unsigned char reg4820; + unsigned char reg4821; + unsigned char reg4822; + unsigned char reg4823; + unsigned char reg4824; + unsigned char reg4825; + unsigned char reg4826; + unsigned char reg4827; + unsigned char reg4828; + unsigned char reg4829; + unsigned char reg482A; + unsigned char reg482B; + unsigned char reg482C; + unsigned char reg482D; + unsigned char reg482E; + unsigned char reg482F; + unsigned char reg4830; + unsigned char reg4831; + unsigned char reg4832; + unsigned char reg4833; + unsigned char reg4834; + unsigned char reg4840; + unsigned char reg4841; + unsigned char reg4842; + uint8 AlignBy; + uint8 written; + uint8 offset_add; + uint32 DataRomOffset; + uint32 DataRomSize; + uint32 bank50Internal; + uint8 bank50[DECOMP_BUFFER_SIZE]; - uint8 r481x; - - bool8 r4814_latch; // bool - bool8 r4815_latch; // bool - - uint8 r4820; - uint8 r4821; - uint8 r4822; - uint8 r4823; - uint8 r4824; - uint8 r4825; - uint8 r4826; - uint8 r4827; - uint8 r4828; - uint8 r4829; - uint8 r482a; - uint8 r482b; - uint8 r482c; - uint8 r482d; - uint8 r482e; - uint8 r482f; - - uint8 r4830; - uint8 r4831; - uint8 r4832; - uint8 r4833; - uint8 r4834; - - uint32 dx_offset; // unsigned - uint32 ex_offset; // unsigned - uint32 fx_offset; // unsigned - - uint8 r4840; - uint8 r4841; - uint8 r4842; - - int32 rtc_state; // enum RTC_State - int32 rtc_mode; // enum RTC_Mode - uint32 rtc_index; // unsigned - - uint32 decomp_mode; // unsigned - uint32 decomp_offset; // unsigned - - uint8 decomp_buffer[SPC7110_DECOMP_BUFFER_SIZE]; - - uint32 decomp_buffer_rdoffset; // unsigned - uint32 decomp_buffer_wroffset; // unsigned - uint32 decomp_buffer_length; // unsigned - - struct ContextState - { - uint8 index; - uint8 invert; - } context[32]; -}; - -extern struct SSPC7110Snapshot s7snap; - -void S9xInitSPC7110 (void); -void S9xResetSPC7110 (void); -void S9xSPC7110PreSaveState (void); -void S9xSPC7110PostLoadState (int); -void S9xSetSPC7110 (uint8, uint16); -uint8 S9xGetSPC7110 (uint16); -uint8 S9xGetSPC7110Byte (uint32); -uint8 * S9xGetBasePointerSPC7110 (uint32); +} SPC7110Regs; +extern SPC7110Regs s7r; +extern S7RTC rtc_f9; +// These are defined in spc7110.cpp +bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9); +bool8 S9xLoadSPC7110RTC (S7RTC *rtc_f9); #endif + diff --git a/source/snes9x/spc7110dec.cpp b/source/snes9x/spc7110dec.cpp deleted file mode 100644 index d4b495d..0000000 --- a/source/snes9x/spc7110dec.cpp +++ /dev/null @@ -1,529 +0,0 @@ -/***** - * SPC7110 emulator - version 0.03 (2008-08-10) - * Copyright (c) 2008, byuu and neviksti - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * The software is provided "as is" and the author disclaims all warranties - * with regard to this software including all implied warranties of - * merchantibility and fitness, in no event shall the author be liable for - * any special, direct, indirect, or consequential damages or any damages - * whatsoever resulting from loss of use, data or profits, whether in an - * action of contract, negligence or other tortious action, arising out of - * or in connection with the use or performance of this software. - *****/ - - -#ifdef _SPC7110EMU_CPP_ - -uint8 SPC7110Decomp::read() { - if(decomp_buffer_length == 0) { - //decompress at least (decomp_buffer_size / 2) bytes to the buffer - switch(decomp_mode) { - case 0: mode0(false); break; - case 1: mode1(false); break; - case 2: mode2(false); break; - default: return 0x00; - } - } - - uint8 data = decomp_buffer[decomp_buffer_rdoffset++]; - decomp_buffer_rdoffset &= decomp_buffer_size - 1; - decomp_buffer_length--; - return data; -} - -void SPC7110Decomp::write(uint8 data) { - decomp_buffer[decomp_buffer_wroffset++] = data; - decomp_buffer_wroffset &= decomp_buffer_size - 1; - decomp_buffer_length++; -} - -uint8 SPC7110Decomp::dataread() { - unsigned size = memory_cartrom_size() - 0x100000; - while(decomp_offset >= size) decomp_offset -= size; - return memory_cartrom_read(0x100000 + decomp_offset++); -} - -void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) { - decomp_mode = mode; - decomp_offset = offset; - - decomp_buffer_rdoffset = 0; - decomp_buffer_wroffset = 0; - decomp_buffer_length = 0; - - //reset context states - for(unsigned i = 0; i < 32; i++) { - context[i].index = 0; - context[i].invert = 0; - } - - switch(decomp_mode) { - case 0: mode0(true); break; - case 1: mode1(true); break; - case 2: mode2(true); break; - } - - //decompress up to requested output data index - while(index--) read(); -} - -// - -void SPC7110Decomp::mode0(bool init) { - static uint8 val, in, span; - static int out, inverts, lps, in_count; - - if(init == true) { - out = inverts = lps = 0; - span = 0xff; - val = dataread(); - in = dataread(); - in_count = 8; - return; - } - - while(decomp_buffer_length < (decomp_buffer_size >> 1)) { - for(unsigned bit = 0; bit < 8; bit++) { - //get context - uint8 mask = (1 << (bit & 3)) - 1; - uint8 con = mask + ((inverts & mask) ^ (lps & mask)); - if(bit > 3) con += 15; - - //get prob and mps - unsigned prob = probability(con); - unsigned mps = (((out >> 15) & 1) ^ context[con].invert); - - //get bit - unsigned flag_lps; - if(val <= span - prob) { //mps - span = span - prob; - out = (out << 1) + mps; - flag_lps = 0; - } else { //lps - val = val - (span - (prob - 1)); - span = prob - 1; - out = (out << 1) + 1 - mps; - flag_lps = 1; - } - - //renormalize - unsigned shift = 0; - while(span < 0x7f) { - shift++; - - span = (span << 1) + 1; - val = (val << 1) + (in >> 7); - - in <<= 1; - if(--in_count == 0) { - in = dataread(); - in_count = 8; - } - } - - //update processing info - lps = (lps << 1) + flag_lps; - inverts = (inverts << 1) + context[con].invert; - - //update context state - if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; - if(flag_lps) context[con].index = next_lps(con); - else if(shift) context[con].index = next_mps(con); - } - - //save byte - write(out); - } -} - -void SPC7110Decomp::mode1(bool init) { - static int pixelorder[4], realorder[4]; - static uint8 in, val, span; - static int out, inverts, lps, in_count; - - if(init == true) { - for(unsigned i = 0; i < 4; i++) pixelorder[i] = i; - out = inverts = lps = 0; - span = 0xff; - val = dataread(); - in = dataread(); - in_count = 8; - return; - } - - while(decomp_buffer_length < (decomp_buffer_size >> 1)) { - for(unsigned pixel = 0; pixel < 8; pixel++) { - //get first symbol context - unsigned a = ((out >> (1 * 2)) & 3); - unsigned b = ((out >> (7 * 2)) & 3); - unsigned c = ((out >> (8 * 2)) & 3); - unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); - - //update pixel order - unsigned m, n; - for(m = 0; m < 4; m++) if(pixelorder[m] == a) break; - for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; - pixelorder[0] = a; - - //calculate the real pixel order - for(m = 0; m < 4; m++) realorder[m] = pixelorder[m]; - - //rotate reference pixel c value to top - for(m = 0; m < 4; m++) if(realorder[m] == c) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = c; - - //rotate reference pixel b value to top - for(m = 0; m < 4; m++) if(realorder[m] == b) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = b; - - //rotate reference pixel a value to top - for(m = 0; m < 4; m++) if(realorder[m] == a) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = a; - - //get 2 symbols - for(unsigned bit = 0; bit < 2; bit++) { - //get prob - unsigned prob = probability(con); - - //get symbol - unsigned flag_lps; - if(val <= span - prob) { //mps - span = span - prob; - flag_lps = 0; - } else { //lps - val = val - (span - (prob - 1)); - span = prob - 1; - flag_lps = 1; - } - - //renormalize - unsigned shift = 0; - while(span < 0x7f) { - shift++; - - span = (span << 1) + 1; - val = (val << 1) + (in >> 7); - - in <<= 1; - if(--in_count == 0) { - in = dataread(); - in_count = 8; - } - } - - //update processing info - lps = (lps << 1) + flag_lps; - inverts = (inverts << 1) + context[con].invert; - - //update context state - if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; - if(flag_lps) context[con].index = next_lps(con); - else if(shift) context[con].index = next_mps(con); - - //get next context - con = 5 + (con << 1) + ((lps ^ inverts) & 1); - } - - //get pixel - b = realorder[(lps ^ inverts) & 3]; - out = (out << 2) + b; - } - - //turn pixel data into bitplanes - unsigned data = morton_2x8(out); - write(data >> 8); - write(data >> 0); - } -} - -void SPC7110Decomp::mode2(bool init) { - static int pixelorder[16], realorder[16]; - static uint8 bitplanebuffer[16], buffer_index; - static uint8 in, val, span; - static int out0, out1, inverts, lps, in_count; - - if(init == true) { - for(unsigned i = 0; i < 16; i++) pixelorder[i] = i; - buffer_index = 0; - out0 = out1 = inverts = lps = 0; - span = 0xff; - val = dataread(); - in = dataread(); - in_count = 8; - return; - } - - while(decomp_buffer_length < (decomp_buffer_size >> 1)) { - for(unsigned pixel = 0; pixel < 8; pixel++) { - //get first symbol context - unsigned a = ((out0 >> (0 * 4)) & 15); - unsigned b = ((out0 >> (7 * 4)) & 15); - unsigned c = ((out1 >> (0 * 4)) & 15); - unsigned con = 0; - unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); - - //update pixel order - unsigned m, n; - for(m = 0; m < 16; m++) if(pixelorder[m] == a) break; - for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; - pixelorder[0] = a; - - //calculate the real pixel order - for(m = 0; m < 16; m++) realorder[m] = pixelorder[m]; - - //rotate reference pixel c value to top - for(m = 0; m < 16; m++) if(realorder[m] == c) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = c; - - //rotate reference pixel b value to top - for(m = 0; m < 16; m++) if(realorder[m] == b) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = b; - - //rotate reference pixel a value to top - for(m = 0; m < 16; m++) if(realorder[m] == a) break; - for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; - realorder[0] = a; - - //get 4 symbols - for(unsigned bit = 0; bit < 4; bit++) { - //get prob - unsigned prob = probability(con); - - //get symbol - unsigned flag_lps; - if(val <= span - prob) { //mps - span = span - prob; - flag_lps = 0; - } else { //lps - val = val - (span - (prob - 1)); - span = prob - 1; - flag_lps = 1; - } - - //renormalize - unsigned shift = 0; - while(span < 0x7f) { - shift++; - - span = (span << 1) + 1; - val = (val << 1) + (in >> 7); - - in <<= 1; - if(--in_count == 0) { - in = dataread(); - in_count = 8; - } - } - - //update processing info - lps = (lps << 1) + flag_lps; - unsigned invertbit = context[con].invert; - inverts = (inverts << 1) + invertbit; - - //update context state - if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; - if(flag_lps) context[con].index = next_lps(con); - else if(shift) context[con].index = next_mps(con); - - //get next context - con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0); - } - - //get pixel - b = realorder[(lps ^ inverts) & 0x0f]; - out1 = (out1 << 4) + ((out0 >> 28) & 0x0f); - out0 = (out0 << 4) + b; - } - - //convert pixel data into bitplanes - unsigned data = morton_4x8(out0); - write(data >> 24); - write(data >> 16); - bitplanebuffer[buffer_index++] = data >> 8; - bitplanebuffer[buffer_index++] = data >> 0; - - if(buffer_index == 16) { - for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]); - buffer_index = 0; - } - } -} - -// - -const uint8 SPC7110Decomp::evolution_table[53][4] = { -//{ prob, nextlps, nextmps, toggle invert }, - - { 0x5a, 1, 1, 1 }, - { 0x25, 6, 2, 0 }, - { 0x11, 8, 3, 0 }, - { 0x08, 10, 4, 0 }, - { 0x03, 12, 5, 0 }, - { 0x01, 15, 5, 0 }, - - { 0x5a, 7, 7, 1 }, - { 0x3f, 19, 8, 0 }, - { 0x2c, 21, 9, 0 }, - { 0x20, 22, 10, 0 }, - { 0x17, 23, 11, 0 }, - { 0x11, 25, 12, 0 }, - { 0x0c, 26, 13, 0 }, - { 0x09, 28, 14, 0 }, - { 0x07, 29, 15, 0 }, - { 0x05, 31, 16, 0 }, - { 0x04, 32, 17, 0 }, - { 0x03, 34, 18, 0 }, - { 0x02, 35, 5, 0 }, - - { 0x5a, 20, 20, 1 }, - { 0x48, 39, 21, 0 }, - { 0x3a, 40, 22, 0 }, - { 0x2e, 42, 23, 0 }, - { 0x26, 44, 24, 0 }, - { 0x1f, 45, 25, 0 }, - { 0x19, 46, 26, 0 }, - { 0x15, 25, 27, 0 }, - { 0x11, 26, 28, 0 }, - { 0x0e, 26, 29, 0 }, - { 0x0b, 27, 30, 0 }, - { 0x09, 28, 31, 0 }, - { 0x08, 29, 32, 0 }, - { 0x07, 30, 33, 0 }, - { 0x05, 31, 34, 0 }, - { 0x04, 33, 35, 0 }, - { 0x04, 33, 36, 0 }, - { 0x03, 34, 37, 0 }, - { 0x02, 35, 38, 0 }, - { 0x02, 36, 5, 0 }, - - { 0x58, 39, 40, 1 }, - { 0x4d, 47, 41, 0 }, - { 0x43, 48, 42, 0 }, - { 0x3b, 49, 43, 0 }, - { 0x34, 50, 44, 0 }, - { 0x2e, 51, 45, 0 }, - { 0x29, 44, 46, 0 }, - { 0x25, 45, 24, 0 }, - - { 0x56, 47, 48, 1 }, - { 0x4f, 47, 49, 0 }, - { 0x47, 48, 50, 0 }, - { 0x41, 49, 51, 0 }, - { 0x3c, 50, 52, 0 }, - { 0x37, 51, 43, 0 }, -}; - -const uint8 SPC7110Decomp::mode2_context_table[32][2] = { -//{ next 0, next 1 }, - - { 1, 2 }, - - { 3, 8 }, - { 13, 14 }, - - { 15, 16 }, - { 17, 18 }, - { 19, 20 }, - { 21, 22 }, - { 23, 24 }, - { 25, 26 }, - { 25, 26 }, - { 25, 26 }, - { 25, 26 }, - { 25, 26 }, - { 27, 28 }, - { 29, 30 }, - - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - { 31, 31 }, - - { 31, 31 }, -}; - -uint8 SPC7110Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; } -uint8 SPC7110Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; } -uint8 SPC7110Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; } -bool SPC7110Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; } - -unsigned SPC7110Decomp::morton_2x8(unsigned data) { - //reverse morton lookup: de-interleave two 8-bit values - //15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8 - //14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0 - return morton16[0][(data >> 0) & 255] + morton16[1][(data >> 8) & 255]; -} - -unsigned SPC7110Decomp::morton_4x8(unsigned data) { - //reverse morton lookup: de-interleave four 8-bit values - //31, 27, 23, 19, 15, 11, 7, 3 -> 31-24 - //30, 26, 22, 18, 14, 10, 6, 2 -> 23-16 - //29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8 - //28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0 - return morton32[0][(data >> 0) & 255] + morton32[1][(data >> 8) & 255] - + morton32[2][(data >> 16) & 255] + morton32[3][(data >> 24) & 255]; -} - -// - -void SPC7110Decomp::reset() { - //mode 3 is invalid; this is treated as a special case to always return 0x00 - //set to mode 3 so that reading decomp port before starting first decomp will return 0x00 - decomp_mode = 3; - - decomp_buffer_rdoffset = 0; - decomp_buffer_wroffset = 0; - decomp_buffer_length = 0; -} - -SPC7110Decomp::SPC7110Decomp() { - decomp_buffer = new uint8_t[decomp_buffer_size]; - reset(); - - //initialize reverse morton lookup tables - for(unsigned i = 0; i < 256; i++) { - #define map(x, y) (((i >> x) & 1) << y) - //2x8-bit - morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6) - + map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4); - morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2) - + map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0); - //4x8-bit - morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7) - + map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6); - morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5) - + map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4); - morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3) - + map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2); - morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1) - + map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0); - #undef map - } -} - -SPC7110Decomp::~SPC7110Decomp() { - delete[] decomp_buffer; -} - -#endif diff --git a/source/snes9x/spc7110dec.h b/source/snes9x/spc7110dec.h deleted file mode 100644 index 3a9c7ce..0000000 --- a/source/snes9x/spc7110dec.h +++ /dev/null @@ -1,67 +0,0 @@ -/***** - * SPC7110 emulator - version 0.03 (2008-08-10) - * Copyright (c) 2008, byuu and neviksti - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * The software is provided "as is" and the author disclaims all warranties - * with regard to this software including all implied warranties of - * merchantibility and fitness, in no event shall the author be liable for - * any special, direct, indirect, or consequential damages or any damages - * whatsoever resulting from loss of use, data or profits, whether in an - * action of contract, negligence or other tortious action, arising out of - * or in connection with the use or performance of this software. - *****/ - - -#ifndef _SPC7110DEC_H_ -#define _SPC7110DEC_H_ - -class SPC7110Decomp { -public: - uint8 read(); - void init(unsigned mode, unsigned offset, unsigned index); - void reset(); - - SPC7110Decomp(); - ~SPC7110Decomp(); - - unsigned decomp_mode; - unsigned decomp_offset; - - //read() will spool chunks half the size of decomp_buffer_size - enum { decomp_buffer_size = SPC7110_DECOMP_BUFFER_SIZE }; //must be >= 64, and must be a power of two - uint8 *decomp_buffer; - unsigned decomp_buffer_rdoffset; - unsigned decomp_buffer_wroffset; - unsigned decomp_buffer_length; - - void write(uint8 data); - uint8 dataread(); - - void mode0(bool init); - void mode1(bool init); - void mode2(bool init); - - static const uint8 evolution_table[53][4]; - static const uint8 mode2_context_table[32][2]; - - struct ContextState { - uint8 index; - uint8 invert; - } context[32]; - - uint8 probability(unsigned n); - uint8 next_lps(unsigned n); - uint8 next_mps(unsigned n); - bool toggle_invert(unsigned n); - - unsigned morton16[2][256]; - unsigned morton32[4][256]; - unsigned morton_2x8(unsigned data); - unsigned morton_4x8(unsigned data); -}; - -#endif diff --git a/source/snes9x/spc7110emu.cpp b/source/snes9x/spc7110emu.cpp deleted file mode 100644 index 156e31c..0000000 --- a/source/snes9x/spc7110emu.cpp +++ /dev/null @@ -1,643 +0,0 @@ -/***** - * SPC7110 emulator - version 0.03 (2008-08-10) - * Copyright (c) 2008, byuu and neviksti - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * The software is provided "as is" and the author disclaims all warranties - * with regard to this software including all implied warranties of - * merchantibility and fitness, in no event shall the author be liable for - * any special, direct, indirect, or consequential damages or any damages - * whatsoever resulting from loss of use, data or profits, whether in an - * action of contract, negligence or other tortious action, arising out of - * or in connection with the use or performance of this software. - *****/ - -#ifdef _SPC7110EMU_CPP_ - -#include "spc7110dec.cpp" - -const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - - -void SPC7110::power() { - reset(); -} - -void SPC7110::reset() { - r4801 = 0x00; - r4802 = 0x00; - r4803 = 0x00; - r4804 = 0x00; - r4805 = 0x00; - r4806 = 0x00; - r4807 = 0x00; - r4808 = 0x00; - r4809 = 0x00; - r480a = 0x00; - r480b = 0x00; - r480c = 0x00; - - decomp.reset(); - - r4811 = 0x00; - r4812 = 0x00; - r4813 = 0x00; - r4814 = 0x00; - r4815 = 0x00; - r4816 = 0x00; - r4817 = 0x00; - r4818 = 0x00; - - r481x = 0x00; - r4814_latch = false; - r4815_latch = false; - - r4820 = 0x00; - r4821 = 0x00; - r4822 = 0x00; - r4823 = 0x00; - r4824 = 0x00; - r4825 = 0x00; - r4826 = 0x00; - r4827 = 0x00; - r4828 = 0x00; - r4829 = 0x00; - r482a = 0x00; - r482b = 0x00; - r482c = 0x00; - r482d = 0x00; - r482e = 0x00; - r482f = 0x00; - - r4830 = 0x00; - mmio_write(0x4831, 0); - mmio_write(0x4832, 1); - mmio_write(0x4833, 2); - r4834 = 0x00; - - r4840 = 0x00; - r4841 = 0x00; - r4842 = 0x00; - - if(cartridge_info_spc7110rtc) { - rtc_state = RTCS_Inactive; - rtc_mode = RTCM_Linear; - rtc_index = 0; - } -} - -unsigned SPC7110::datarom_addr(unsigned addr) { - unsigned size = memory_cartrom_size() - 0x100000; - while(addr >= size) addr -= size; - return addr + 0x100000; -} - -unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); } -unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); } -unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); } -void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; } -void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; } - -void SPC7110::update_time(int offset) { - time_t rtc_time - = (memory_cartrtc_read(16) << 0) - | (memory_cartrtc_read(17) << 8) - | (memory_cartrtc_read(18) << 16) - | (memory_cartrtc_read(19) << 24); - time_t current_time = time(0) - offset; - - //sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic. - //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by - //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow - //memory::cartrtc timestamp to remain valid for up to ~34 years from the last update, even if - //time_t overflows. calculation should be valid regardless of number representation, time_t size, - //or whether time_t is signed or unsigned. - time_t diff - = (current_time >= rtc_time) - ? (current_time - rtc_time) - : (std::numeric_limits::max() - rtc_time + current_time + 1); //compensate for overflow - if(diff > std::numeric_limits::max() / 2) diff = 0; //compensate for underflow - - bool update = true; - if(memory_cartrtc_read(13) & 1) update = false; //do not update if CR0 timer disable flag is set - if(memory_cartrtc_read(15) & 3) update = false; //do not update if CR2 timer disable flags are set - - if(diff > 0 && update == true) { - unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; - unsigned minute = memory_cartrtc_read( 2) + memory_cartrtc_read( 3) * 10; - unsigned hour = memory_cartrtc_read( 4) + memory_cartrtc_read( 5) * 10; - unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; - unsigned month = memory_cartrtc_read( 8) + memory_cartrtc_read( 9) * 10; - unsigned year = memory_cartrtc_read(10) + memory_cartrtc_read(11) * 10; - unsigned weekday = memory_cartrtc_read(12); - - day--; - month--; - year += (year >= 90) ? 1900 : 2000; //range = 1990-2089 - - second += diff; - while(second >= 60) { - second -= 60; - - minute++; - if(minute < 60) continue; - minute = 0; - - hour++; - if(hour < 24) continue; - hour = 0; - - day++; - weekday = (weekday + 1) % 7; - unsigned days = months[month % 12]; - if(days == 28) { - bool leapyear = false; - if((year % 4) == 0) { - leapyear = true; - if((year % 100) == 0 && (year % 400) != 0) leapyear = false; - } - if(leapyear) days++; - } - if(day < days) continue; - day = 0; - - month++; - if(month < 12) continue; - month = 0; - - year++; - } - - day++; - month++; - year %= 100; - - memory_cartrtc_write( 0, second % 10); - memory_cartrtc_write( 1, second / 10); - memory_cartrtc_write( 2, minute % 10); - memory_cartrtc_write( 3, minute / 10); - memory_cartrtc_write( 4, hour % 10); - memory_cartrtc_write( 5, hour / 10); - memory_cartrtc_write( 6, day % 10); - memory_cartrtc_write( 7, day / 10); - memory_cartrtc_write( 8, month % 10); - memory_cartrtc_write( 9, month / 10); - memory_cartrtc_write(10, year % 10); - memory_cartrtc_write(11, (year / 10) % 10); - memory_cartrtc_write(12, weekday % 7); - } - - memory_cartrtc_write(16, current_time >> 0); - memory_cartrtc_write(17, current_time >> 8); - memory_cartrtc_write(18, current_time >> 16); - memory_cartrtc_write(19, current_time >> 24); -} - -uint8 SPC7110::mmio_read(unsigned addr) { - addr &= 0xffff; - - switch(addr) { - //================== - //decompression unit - //================== - - case 0x4800: { - uint16 counter = (r4809 + (r480a << 8)); - counter--; - r4809 = counter; - r480a = counter >> 8; - return decomp.read(); - } - case 0x4801: return r4801; - case 0x4802: return r4802; - case 0x4803: return r4803; - case 0x4804: return r4804; - case 0x4805: return r4805; - case 0x4806: return r4806; - case 0x4807: return r4807; - case 0x4808: return r4808; - case 0x4809: return r4809; - case 0x480a: return r480a; - case 0x480b: return r480b; - case 0x480c: { - uint8 status = r480c; - r480c &= 0x7f; - return status; - } - - //============== - //data port unit - //============== - - case 0x4810: { - if(r481x != 0x07) return 0x00; - - unsigned addr = data_pointer(); - unsigned adjust = data_adjust(); - if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend - - unsigned adjustaddr = addr; - if(r4818 & 2) { - adjustaddr += adjust; - set_data_adjust(adjust + 1); - } - - uint8 data = memory_cartrom_read(datarom_addr(adjustaddr)); - if(!(r4818 & 2)) { - unsigned increment = (r4818 & 1) ? data_increment() : 1; - if(r4818 & 4) increment = (int16)increment; //16-bit sign extend - - if((r4818 & 16) == 0) { - set_data_pointer(addr + increment); - } else { - set_data_adjust(adjust + increment); - } - } - - return data; - } - case 0x4811: return r4811; - case 0x4812: return r4812; - case 0x4813: return r4813; - case 0x4814: return r4814; - case 0x4815: return r4815; - case 0x4816: return r4816; - case 0x4817: return r4817; - case 0x4818: return r4818; - case 0x481a: { - if(r481x != 0x07) return 0x00; - - unsigned addr = data_pointer(); - unsigned adjust = data_adjust(); - if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend - - uint8 data = memory_cartrom_read(datarom_addr(addr + adjust)); - if((r4818 & 0x60) == 0x60) { - if((r4818 & 16) == 0) { - set_data_pointer(addr + adjust); - } else { - set_data_adjust(adjust + adjust); - } - } - - return data; - } - - //========= - //math unit - //========= - - case 0x4820: return r4820; - case 0x4821: return r4821; - case 0x4822: return r4822; - case 0x4823: return r4823; - case 0x4824: return r4824; - case 0x4825: return r4825; - case 0x4826: return r4826; - case 0x4827: return r4827; - case 0x4828: return r4828; - case 0x4829: return r4829; - case 0x482a: return r482a; - case 0x482b: return r482b; - case 0x482c: return r482c; - case 0x482d: return r482d; - case 0x482e: return r482e; - case 0x482f: { - uint8 status = r482f; - r482f &= 0x7f; - return status; - } - - //=================== - //memory mapping unit - //=================== - - case 0x4830: return r4830; - case 0x4831: return r4831; - case 0x4832: return r4832; - case 0x4833: return r4833; - case 0x4834: return r4834; - - //==================== - //real-time clock unit - //==================== - - case 0x4840: return r4840; - case 0x4841: { - if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00; - - r4842 = 0x80; - uint8 data = memory_cartrtc_read(rtc_index); - rtc_index = (rtc_index + 1) & 15; - return data; - } - case 0x4842: { - uint8 status = r4842; - r4842 &= 0x7f; - return status; - } - } - - return cpu_regs_mdr; -} - -void SPC7110::mmio_write(unsigned addr, uint8 data) { - addr &= 0xffff; - - switch(addr) { - //================== - //decompression unit - //================== - - case 0x4801: r4801 = data; break; - case 0x4802: r4802 = data; break; - case 0x4803: r4803 = data; break; - case 0x4804: r4804 = data; break; - case 0x4805: r4805 = data; break; - case 0x4806: { - r4806 = data; - - unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16)); - unsigned index = (r4804 << 2); - unsigned length = (r4809 + (r480a << 8)); - unsigned addr = datarom_addr(table + index); - unsigned mode = (memory_cartrom_read(addr + 0)); - unsigned offset = (memory_cartrom_read(addr + 1) << 16) - + (memory_cartrom_read(addr + 2) << 8) - + (memory_cartrom_read(addr + 3) << 0); - - decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode); - r480c = 0x80; - } break; - - case 0x4807: r4807 = data; break; - case 0x4808: r4808 = data; break; - case 0x4809: r4809 = data; break; - case 0x480a: r480a = data; break; - case 0x480b: r480b = data; break; - - //============== - //data port unit - //============== - - case 0x4811: r4811 = data; r481x |= 0x01; break; - case 0x4812: r4812 = data; r481x |= 0x02; break; - case 0x4813: r4813 = data; r481x |= 0x04; break; - case 0x4814: { - r4814 = data; - r4814_latch = true; - if(!r4815_latch) break; - if(!(r4818 & 2)) break; - if(r4818 & 0x10) break; - - if((r4818 & 0x60) == 0x20) { - unsigned increment = data_adjust() & 0xff; - if(r4818 & 8) increment = (int8)increment; //8-bit sign extend - set_data_pointer(data_pointer() + increment); - } else if((r4818 & 0x60) == 0x40) { - unsigned increment = data_adjust(); - if(r4818 & 8) increment = (int16)increment; //16-bit sign extend - set_data_pointer(data_pointer() + increment); - } - } break; - case 0x4815: { - r4815 = data; - r4815_latch = true; - if(!r4814_latch) break; - if(!(r4818 & 2)) break; - if(r4818 & 0x10) break; - - if((r4818 & 0x60) == 0x20) { - unsigned increment = data_adjust() & 0xff; - if(r4818 & 8) increment = (int8)increment; //8-bit sign extend - set_data_pointer(data_pointer() + increment); - } else if((r4818 & 0x60) == 0x40) { - unsigned increment = data_adjust(); - if(r4818 & 8) increment = (int16)increment; //16-bit sign extend - set_data_pointer(data_pointer() + increment); - } - } break; - case 0x4816: r4816 = data; break; - case 0x4817: r4817 = data; break; - case 0x4818: { - if(r481x != 0x07) break; - - r4818 = data; - r4814_latch = r4815_latch = false; - } break; - - //========= - //math unit - //========= - - case 0x4820: r4820 = data; break; - case 0x4821: r4821 = data; break; - case 0x4822: r4822 = data; break; - case 0x4823: r4823 = data; break; - case 0x4824: r4824 = data; break; - case 0x4825: { - r4825 = data; - - if(r482e & 1) { - //signed 16-bit x 16-bit multiplication - int16 r0 = (int16)(r4824 + (r4825 << 8)); - int16 r1 = (int16)(r4820 + (r4821 << 8)); - - signed result = r0 * r1; - r4828 = result; - r4829 = result >> 8; - r482a = result >> 16; - r482b = result >> 24; - } else { - //unsigned 16-bit x 16-bit multiplication - uint16 r0 = (uint16)(r4824 + (r4825 << 8)); - uint16 r1 = (uint16)(r4820 + (r4821 << 8)); - - unsigned result = r0 * r1; - r4828 = result; - r4829 = result >> 8; - r482a = result >> 16; - r482b = result >> 24; - } - - r482f = 0x80; - } break; - case 0x4826: r4826 = data; break; - case 0x4827: { - r4827 = data; - - if(r482e & 1) { - //signed 32-bit x 16-bit division - int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); - int16 divisor = (int16)(r4826 + (r4827 << 8)); - - int32 quotient; - int16 remainder; - - if(divisor) { - quotient = (int32)(dividend / divisor); - remainder = (int32)(dividend % divisor); - } else { - //illegal division by zero - quotient = 0; - remainder = dividend & 0xffff; - } - - r4828 = quotient; - r4829 = quotient >> 8; - r482a = quotient >> 16; - r482b = quotient >> 24; - - r482c = remainder; - r482d = remainder >> 8; - } else { - //unsigned 32-bit x 16-bit division - uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); - uint16 divisor = (uint16)(r4826 + (r4827 << 8)); - - uint32 quotient; - uint16 remainder; - - if(divisor) { - quotient = (uint32)(dividend / divisor); - remainder = (uint16)(dividend % divisor); - } else { - //illegal division by zero - quotient = 0; - remainder = dividend & 0xffff; - } - - r4828 = quotient; - r4829 = quotient >> 8; - r482a = quotient >> 16; - r482b = quotient >> 24; - - r482c = remainder; - r482d = remainder >> 8; - } - - r482f = 0x80; - } break; - - case 0x482e: { - //reset math unit - r4820 = r4821 = r4822 = r4823 = 0; - r4824 = r4825 = r4826 = r4827 = 0; - r4828 = r4829 = r482a = r482b = 0; - r482c = r482d = 0; - - r482e = data; - } break; - - //=================== - //memory mapping unit - //=================== - - case 0x4830: r4830 = data; break; - - case 0x4831: { - r4831 = data; - dx_offset = datarom_addr((data & 7) * 0x100000); - } break; - - case 0x4832: { - r4832 = data; - ex_offset = datarom_addr((data & 7) * 0x100000); - } break; - - case 0x4833: { - r4833 = data; - fx_offset = datarom_addr((data & 7) * 0x100000); - } break; - - case 0x4834: r4834 = data; break; - - //==================== - //real-time clock unit - //==================== - - case 0x4840: { - r4840 = data; - if(!(r4840 & 1)) { - //disable RTC - rtc_state = RTCS_Inactive; - update_time(); - } else { - //enable RTC - r4842 = 0x80; - rtc_state = RTCS_ModeSelect; - } - } break; - - case 0x4841: { - r4841 = data; - - switch(rtc_state) { - case RTCS_ModeSelect: { - if(data == RTCM_Linear || data == RTCM_Indexed) { - r4842 = 0x80; - rtc_state = RTCS_IndexSelect; - rtc_mode = (RTC_Mode)data; - rtc_index = 0; - } - } break; - - case RTCS_IndexSelect: { - r4842 = 0x80; - rtc_index = data & 15; - if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write; - } break; - - case RTCS_Write: { - r4842 = 0x80; - - //control register 0 - if(rtc_index == 13) { - //increment second counter - if(data & 2) update_time(+1); - - //round minute counter - if(data & 8) { - update_time(); - - unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; - //clear seconds - memory_cartrtc_write(0, 0); - memory_cartrtc_write(1, 0); - - if(second >= 30) update_time(+60); - } - } - - //control register 2 - if(rtc_index == 15) { - //disable timer and clear second counter - if((data & 1) && !(memory_cartrtc_read(15) & 1)) { - update_time(); - - //clear seconds - memory_cartrtc_write(0, 0); - memory_cartrtc_write(1, 0); - } - - //disable timer - if((data & 2) && !(memory_cartrtc_read(15) & 2)) { - update_time(); - } - } - - memory_cartrtc_write(rtc_index, data & 15); - rtc_index = (rtc_index + 1) & 15; - } break; - } //switch(rtc_state) - } break; - } -} - -SPC7110::SPC7110() { -} - -#endif diff --git a/source/snes9x/spc7110emu.h b/source/snes9x/spc7110emu.h deleted file mode 100644 index 5f66fec..0000000 --- a/source/snes9x/spc7110emu.h +++ /dev/null @@ -1,136 +0,0 @@ -/***** - * SPC7110 emulator - version 0.03 (2008-08-10) - * Copyright (c) 2008, byuu and neviksti - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * The software is provided "as is" and the author disclaims all warranties - * with regard to this software including all implied warranties of - * merchantibility and fitness, in no event shall the author be liable for - * any special, direct, indirect, or consequential damages or any damages - * whatsoever resulting from loss of use, data or profits, whether in an - * action of contract, negligence or other tortious action, arising out of - * or in connection with the use or performance of this software. - *****/ - - -#ifndef _SPC7110EMU_H_ -#define _SPC7110EMU_H_ - -#include "spc7110dec.h" - -class SPC7110 { -public: - void init(); - void enable(); - void power(); - void reset(); - - unsigned datarom_addr(unsigned addr); - - unsigned data_pointer(); - unsigned data_adjust(); - unsigned data_increment(); - void set_data_pointer(unsigned addr); - void set_data_adjust(unsigned addr); - - void update_time(int offset = 0); - time_t create_time(); - - uint8 mmio_read (unsigned addr); - void mmio_write(unsigned addr, uint8 data); - - uint8 read (unsigned addr); - void write(unsigned addr, uint8 data); - - //spc7110decomp - void decomp_init(); - uint8 decomp_read(); - - SPC7110(); - - //================== - //decompression unit - //================== - uint8 r4801; //compression table low - uint8 r4802; //compression table high - uint8 r4803; //compression table bank - uint8 r4804; //compression table index - uint8 r4805; //decompression buffer index low - uint8 r4806; //decompression buffer index high - uint8 r4807; //??? - uint8 r4808; //??? - uint8 r4809; //compression length low - uint8 r480a; //compression length high - uint8 r480b; //decompression control register - uint8 r480c; //decompression status - - SPC7110Decomp decomp; - - //============== - //data port unit - //============== - uint8 r4811; //data pointer low - uint8 r4812; //data pointer high - uint8 r4813; //data pointer bank - uint8 r4814; //data adjust low - uint8 r4815; //data adjust high - uint8 r4816; //data increment low - uint8 r4817; //data increment high - uint8 r4818; //data port control register - - uint8 r481x; - - bool r4814_latch; - bool r4815_latch; - - //========= - //math unit - //========= - uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0 - uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1 - uint8 r4822; //32-bit dividend B2 - uint8 r4823; //32-bit dividend B3 - uint8 r4824; //16-bit multiplier B0 - uint8 r4825; //16-bit multiplier B1 - uint8 r4826; //16-bit divisor B0 - uint8 r4827; //16-bit divisor B1 - uint8 r4828; //32-bit product B0, 32-bit quotient B0 - uint8 r4829; //32-bit product B1, 32-bit quotient B1 - uint8 r482a; //32-bit product B2, 32-bit quotient B2 - uint8 r482b; //32-bit product B3, 32-bit quotient B3 - uint8 r482c; //16-bit remainder B0 - uint8 r482d; //16-bit remainder B1 - uint8 r482e; //math control register - uint8 r482f; //math status - - //=================== - //memory mapping unit - //=================== - uint8 r4830; //SRAM write enable - uint8 r4831; //$[d0-df]:[0000-ffff] mapping - uint8 r4832; //$[e0-ef]:[0000-ffff] mapping - uint8 r4833; //$[f0-ff]:[0000-ffff] mapping - uint8 r4834; //??? - - unsigned dx_offset; - unsigned ex_offset; - unsigned fx_offset; - - //==================== - //real-time clock unit - //==================== - uint8 r4840; //RTC latch - uint8 r4841; //RTC index/data port - uint8 r4842; //RTC status - - enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state; - enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode; - unsigned rtc_index; - - static const unsigned months[12]; -}; - -#endif diff --git a/source/snes9x/srtc.cpp b/source/snes9x/srtc.cpp index 51531ff..9dd76e4 100644 --- a/source/snes9x/srtc.cpp +++ b/source/snes9x/srtc.cpp @@ -158,71 +158,494 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ -/***** - * S-RTC emulation code - * Copyright (c) byuu - *****/ -#include +#include #include "snes9x.h" -#include "memmap.h" #include "srtc.h" -#include "display.h" +#include "memmap.h" -#define memory_cartrtc_read(a) RTCData.reg[(a)] -#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } -#define cpu_regs_mdr OpenBus +/*** The format of the rtc_data structure is: -static inline unsigned max (unsigned a, unsigned b) +Index Description Range (nibble) +----- -------------- --------------------------------------- + + 0 Seconds low 0-9 + 1 Seconds high 0-5 + + 2 Minutes low 0-9 + 3 Minutes high 0-5 + + 4 Hour low 0-9 + 5 Hour high 0-2 + + 6 Day low 0-9 + 7 Day high 0-3 + + 8 Month 1-C (0xC is December, 12th month) + + 9 Year ones 0-9 + A Year tens 0-9 + B Year High 9-B (9=19xx, A=20xx, B=21xx) + + C Day of week 0-6 (0=Sunday, 1=Monday,...,6=Saturday) + +***/ + +SRTC_DATA rtc; + + +static int month_keys[12] = { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 }; + + +/********************************************************************************************* + * + * Note, if you are doing a save state for this game: + * + * On save: + * + * Call S9xUpdateSrtcTime and save the rtc data structure. + * + * On load: + * + * restore the rtc data structure + * rtc.system_timestamp = time (NULL); + * + * + *********************************************************************************************/ + + +void S9xResetSRTC () { - return ((a > b) ? a : b); + rtc.index = -1; + rtc.mode = MODE_READ; } -static inline unsigned min (unsigned a, unsigned b) +void S9xHardResetSRTC () { - return ((a < b) ? a : b); + ZeroMemory (&rtc, sizeof (rtc)); + rtc.index = -1; + rtc.mode = MODE_READ; + rtc.count_enable = FALSE; + rtc.needs_init = TRUE; + + // Get system timestamp + rtc.system_timestamp = time (NULL); } -#define _SRTCEMU_CPP_ - -#include "srtcemu.h" -#include "srtcemu.cpp" - -static SRTC srtcemu; - - -void S9xInitSRTC (void) +/**********************************************************************************************/ +/* S9xSRTCComputeDayOfWeek() */ +/* Return 0-6 for Sunday-Saturday */ +/**********************************************************************************************/ +unsigned int S9xSRTCComputeDayOfWeek () { - srtcemu.power(); - memset(RTCData.reg, 0, 20); + unsigned year = rtc.data[10]*10 + rtc.data[9]; + unsigned month = rtc.data[8]; + unsigned day = rtc.data[7]*10 + rtc.data[6]; + unsigned day_of_week; + + year += (rtc.data[11] - 9) * 100; + + // Range check the month for valid array indicies + if ( month > 12 ) + month = 1; + + day_of_week = year + (year / 4) + month_keys[month-1] + day - 1; + + if(( year % 4 == 0 ) && ( month <= 2 ) ) + day_of_week--; + + day_of_week %= 7; + + return day_of_week; } -void S9xResetSRTC (void) + +/**********************************************************************************************/ +/* S9xSRTCDaysInMonth() */ +/* Return the number of days in a specific month for a certain year */ +/**********************************************************************************************/ +int S9xSRTCDaysInMmonth( int month, int year ) { - srtcemu.reset(); + int mdays; + + switch ( month ) + { + case 2: + if ( ( year % 4 == 0 ) ) // DKJM2 only uses 199x - 22xx + mdays = 29; + else + mdays = 28; + break; + + case 4: + case 6: + case 9: + case 11: + mdays = 30; + break; + + default: // months 1,3,5,7,8,10,12 + mdays = 31; + break; + } + + return mdays; } -void S9xSetSRTC (uint8 data, uint16 address) + +#define DAYTICKS (60*60*24) +#define HOURTICKS (60*60) +#define MINUTETICKS 60 + + +/**********************************************************************************************/ +/* S9xUpdateSrtcTime() */ +/* Advance the S-RTC time if counting is enabled */ +/**********************************************************************************************/ +void S9xUpdateSrtcTime () { - srtcemu.mmio_write(address, data); + time_t cur_systime; + long time_diff; + + // Keep track of game time by computing the number of seconds that pass on the system + // clock and adding the same number of seconds to the S-RTC clock structure. + // I originally tried using mktime and localtime library functions to keep track + // of time but some of the GNU time functions fail when the year goes to 2099 + // (and maybe less) and this would have caused a bug with DKJM2 so I'm doing + // it this way to get around that problem. + + // Note: Dai Kaijyu Monogatari II only allows dates in the range 1996-21xx. + + if (rtc.count_enable && !rtc.needs_init) + { + cur_systime = time (NULL); + + // This method assumes one time_t clock tick is one second + // which should work on PCs and GNU systems. + // If your tick interval is different adjust the + // DAYTICK, HOURTICK, and MINUTETICK defines + + time_diff = (long) (cur_systime - rtc.system_timestamp); + rtc.system_timestamp = cur_systime; + + if ( time_diff > 0 ) + { + int seconds; + int minutes; + int hours; + int days; + int month; + int year; + int temp_days; + + int year_hundreds; + int year_tens; + int year_ones; + + + if ( time_diff > DAYTICKS ) + { + days = time_diff / DAYTICKS; + time_diff = time_diff - days * DAYTICKS; + } + else + { + days = 0; + } + + if ( time_diff > HOURTICKS ) + { + hours = time_diff / HOURTICKS; + time_diff = time_diff - hours * HOURTICKS; + } + else + { + hours = 0; + } + + if ( time_diff > MINUTETICKS ) + { + minutes = time_diff / MINUTETICKS; + time_diff = time_diff - minutes * MINUTETICKS; + } + else + { + minutes = 0; + } + + if ( time_diff > 0 ) + { + seconds = time_diff; + } + else + { + seconds = 0; + } + + + seconds += (rtc.data[1]*10 + rtc.data[0]); + if ( seconds >= 60 ) + { + seconds -= 60; + minutes += 1; + } + + minutes += (rtc.data[3]*10 + rtc.data[2]); + if ( minutes >= 60 ) + { + minutes -= 60; + hours += 1; + } + + hours += (rtc.data[5]*10 + rtc.data[4]); + if ( hours >= 24 ) + { + hours -= 24; + days += 1; + } + + if ( days > 0 ) + { + year = rtc.data[10]*10 + rtc.data[9]; + year += ( 1000 + rtc.data[11] * 100 ); + + month = rtc.data[8]; + days += (rtc.data[7]*10 + rtc.data[6]); + while ( days > (temp_days = S9xSRTCDaysInMmonth( month, year )) ) + { + days -= temp_days; + month += 1; + if ( month > 12 ) + { + year += 1; + month = 1; + } + } + + year_tens = year % 100; + year_ones = year_tens % 10; + year_tens /= 10; + year_hundreds = (year - 1000) / 100; + + rtc.data[6] = days % 10; + rtc.data[7] = days / 10; + rtc.data[8] = month; + rtc.data[9] = year_ones; + rtc.data[10] = year_tens; + rtc.data[11] = year_hundreds; + rtc.data[12] = S9xSRTCComputeDayOfWeek (); + } + + rtc.data[0] = seconds % 10; + rtc.data[1] = seconds / 10; + rtc.data[2] = minutes % 10; + rtc.data[3] = minutes / 10; + rtc.data[4] = hours % 10; + rtc.data[5] = hours / 10; + + return; + } + } } -uint8 S9xGetSRTC (uint16 address) + +/**********************************************************************************************/ +/* S9xSetSRTC() */ +/* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ +/**********************************************************************************************/ +void S9xSetSRTC (uint8 data, uint16 Address) { - return (srtcemu.mmio_read(address)); + + data &= 0x0F; // Data is only 4-bits, mask out unused bits. + + if( data >= 0xD ) + { + // It's an RTC command + + switch ( data ) + { + case 0xD: + rtc.mode = MODE_READ; + rtc.index = -1; + break; + + case 0xE: + rtc.mode = MODE_COMMAND; + break; + + default: + // Ignore the write if it's an 0xF ??? + // Probably should switch back to read mode -- but this + // sequence never occurs in DKJM2 + break; + } + + return; + } + + if ( rtc.mode == MODE_LOAD_RTC ) + { + if ( (rtc.index >= 0) && (rtc.index < MAX_RTC_INDEX) ) + { + rtc.data[rtc.index++] = data; + + if ( rtc.index == MAX_RTC_INDEX ) + { + // We have all the data for the RTC load + + rtc.system_timestamp = time (NULL); // Get local system time + + // Get the day of the week + rtc.data[rtc.index++] = S9xSRTCComputeDayOfWeek (); + + // Start RTC counting again + rtc.count_enable = TRUE; + rtc.needs_init = FALSE; + } + + return; + } + else + { + // Attempting to write too much data + // error(); // ignore?? + } + } + else if ( rtc.mode == MODE_COMMAND ) + { + switch( data ) + { + case COMMAND_CLEAR_RTC: + // Disable RTC counter + rtc.count_enable = FALSE; + + ZeroMemory (rtc.data, MAX_RTC_INDEX+1); + rtc.index = -1; + rtc.mode = MODE_COMMAND_DONE; + break; + + case COMMAND_LOAD_RTC: + // Disable RTC counter + rtc.count_enable = FALSE; + + rtc.index = 0; // Setup for writing + rtc.mode = MODE_LOAD_RTC; + break; + + default: + rtc.mode = MODE_COMMAND_DONE; + // unrecognized command - need to implement. + } + + return; + } + else + { + if ( rtc.mode == MODE_READ ) + { + // Attempting to write while in read mode. Ignore. + } + + if ( rtc.mode == MODE_COMMAND_DONE ) + { + // Maybe this isn't an error. Maybe we should kick off + // a new E command. But is this valid? + } + } } -void S9xSRTCPreSaveState (void) +/**********************************************************************************************/ +/* S9xGetSRTC() */ +/* This function retrieves data from the S-RTC */ +/**********************************************************************************************/ +uint8 S9xGetSRTC (uint16 Address) { - srtcsnap.rtc_mode = (int32) srtcemu.rtc_mode; - srtcsnap.rtc_index = (int32) srtcemu.rtc_index; + if ( rtc.mode == MODE_READ ) + { + if ( rtc.index < 0 ) + { + S9xUpdateSrtcTime (); // Only update it if the game reads it + rtc.index++; + return ( 0x0f ); // Send start marker. + } + else if (rtc.index > MAX_RTC_INDEX) + { + rtc.index = -1; // Setup for next set of reads + return ( 0x0f ); // Data done marker. + } + else + { + // Feed out the data + return rtc.data[rtc.index++]; + } + } + else + { + return 0x0; + } } -void S9xSRTCPostLoadState (int) +void S9xSRTCPreSaveState () { - srtcemu.rtc_mode = (SRTC::RTC_Mode) srtcsnap.rtc_mode; - srtcemu.rtc_index = (signed) srtcsnap.rtc_index; + if (Settings.SRTC) + { + S9xUpdateSrtcTime (); - srtcemu.update_time(); + int s = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (s > 0x20000) + s = 0x20000; + + Memory.SRAM [s + 0] = rtc.needs_init; + Memory.SRAM [s + 1] = rtc.count_enable; + memmove (&Memory.SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); + Memory.SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; + Memory.SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; + +#ifdef LSB_FIRST + memmove (&Memory.SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); +#else + Memory.SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); + Memory.SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); + Memory.SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); + Memory.SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); + Memory.SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); + Memory.SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); + Memory.SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); + Memory.SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); +#endif + } } + +void S9xSRTCPostLoadState () +{ + if (Settings.SRTC) + { + int s = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (s > 0x20000) + s = 0x20000; + + rtc.needs_init = Memory.SRAM [s + 0]; + rtc.count_enable = Memory.SRAM [s + 1]; + memmove (rtc.data, &Memory.SRAM [s + 2], MAX_RTC_INDEX + 1); + rtc.index = Memory.SRAM [s + 3 + MAX_RTC_INDEX]; + rtc.mode = Memory.SRAM [s + 4 + MAX_RTC_INDEX]; + +#ifdef LSB_FIRST + memmove (&rtc.system_timestamp, &Memory.SRAM [s + 5 + MAX_RTC_INDEX], 8); +#else + rtc.system_timestamp |= (Memory.SRAM [s + 5 + MAX_RTC_INDEX] << 0); + rtc.system_timestamp |= (Memory.SRAM [s + 6 + MAX_RTC_INDEX] << 8); + rtc.system_timestamp |= (Memory.SRAM [s + 7 + MAX_RTC_INDEX] << 16); + rtc.system_timestamp |= (Memory.SRAM [s + 8 + MAX_RTC_INDEX] << 24); + rtc.system_timestamp |= (Memory.SRAM [s + 9 + MAX_RTC_INDEX] << 32); + rtc.system_timestamp |= (Memory.SRAM [s + 10 + MAX_RTC_INDEX] << 40); + rtc.system_timestamp |= (Memory.SRAM [s + 11 + MAX_RTC_INDEX] << 48); + rtc.system_timestamp |= (Memory.SRAM [s + 12 + MAX_RTC_INDEX] << 56); +#endif + S9xUpdateSrtcTime (); + } +} + diff --git a/source/snes9x/srtc.h b/source/snes9x/srtc.h index adda665..895e233 100644 --- a/source/snes9x/srtc.h +++ b/source/snes9x/srtc.h @@ -159,29 +159,73 @@ **********************************************************************************/ -#ifndef _SRTC_H_ -#define _SRTC_H_ -struct SRTCData +#ifndef _srtc_h_ +#define _srtc_h_ + +#include + +#define MAX_RTC_INDEX 0xC + +#define MODE_READ 0 +#define MODE_LOAD_RTC 1 +#define MODE_COMMAND 2 +#define MODE_COMMAND_DONE 3 + +#define COMMAND_LOAD_RTC 0 +#define COMMAND_CLEAR_RTC 4 + + +/*** The format of the rtc_data structure is: + +Index Description Range (nibble) +----- -------------- --------------------------------------- + + 0 Seconds low 0-9 + 1 Seconds high 0-5 + + 2 Minutes low 0-9 + 3 Minutes high 0-5 + + 4 Hour low 0-9 + 5 Hour high 0-2 + + 6 Day low 0-9 + 7 Day high 0-3 + + 8 Month 1-C (0xC is December, 12th month) + + 9 Year ones 0-9 + A Year tens 0-9 + B Year High 9-B (9=19xx, A=20xx, B=21xx) + + C Day of week 0-6 (0=Sunday, 1=Monday,...,6=Saturday) + +***/ + +typedef struct { - uint8 reg[20]; -}; + bool8 needs_init; + bool8 count_enable; // Does RTC mark time or is it frozen + uint8 data [MAX_RTC_INDEX+1]; + int8 index; + uint8 mode; -// for snapshot only -struct SSRTCSnapshot -{ - int32 rtc_mode; // enum RTC_Mode - int32 rtc_index; // signed -}; + time_t system_timestamp; // Of latest RTC load time + uint32 pad; +} SRTC_DATA; -extern struct SRTCData RTCData; -extern struct SSRTCSnapshot srtcsnap; +extern SRTC_DATA rtc; -void S9xInitSRTC (void); -void S9xResetSRTC (void); -void S9xSRTCPreSaveState (void); -void S9xSRTCPostLoadState (int); -void S9xSetSRTC (uint8, uint16); -uint8 S9xGetSRTC (uint16); +void S9xUpdateSrtcTime (); +void S9xSetSRTC (uint8 data, uint16 Address); +uint8 S9xGetSRTC (uint16 Address); +void S9xSRTCPreSaveState (); +void S9xSRTCPostLoadState (); +void S9xResetSRTC (); +void S9xHardResetSRTC (); + +#define SRTC_SRAM_PAD (4 + 8 + 1 + MAX_RTC_INDEX) + +#endif // _srtc_h -#endif diff --git a/source/snes9x/srtcemu.cpp b/source/snes9x/srtcemu.cpp deleted file mode 100644 index 969b966..0000000 --- a/source/snes9x/srtcemu.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/***** - * S-RTC emulation code - * Copyright (c) byuu - *****/ - - -#ifdef _SRTCEMU_CPP_ - -const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - - -void SRTC::power() { - reset(); -} - -void SRTC::reset() { - rtc_mode = RTCM_Read; - rtc_index = -1; - update_time(); -} - -void SRTC::update_time() { - time_t rtc_time - = (memory_cartrtc_read(16) << 0) - | (memory_cartrtc_read(17) << 8) - | (memory_cartrtc_read(18) << 16) - | (memory_cartrtc_read(19) << 24); - time_t current_time = time(0); - - //sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic. - //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by - //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow - //memory::cartrtc timestamp to remain valid for up to ~34 years from the last update, even if - //time_t overflows. calculation should be valid regardless of number representation, time_t size, - //or whether time_t is signed or unsigned. - time_t diff - = (current_time >= rtc_time) - ? (current_time - rtc_time) - : (std::numeric_limits::max() - rtc_time + current_time + 1); //compensate for overflow - if(diff > std::numeric_limits::max() / 2) diff = 0; //compensate for underflow - - if(diff > 0) { - unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; - unsigned minute = memory_cartrtc_read( 2) + memory_cartrtc_read( 3) * 10; - unsigned hour = memory_cartrtc_read( 4) + memory_cartrtc_read( 5) * 10; - unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; - unsigned month = memory_cartrtc_read( 8); - unsigned year = memory_cartrtc_read( 9) + memory_cartrtc_read(10) * 10 + memory_cartrtc_read(11) * 100; - unsigned weekday = memory_cartrtc_read(12); - - day--; - month--; - year += 1000; - - second += diff; - while(second >= 60) { - second -= 60; - - minute++; - if(minute < 60) continue; - minute = 0; - - hour++; - if(hour < 24) continue; - hour = 0; - - day++; - weekday = (weekday + 1) % 7; - unsigned days = months[month % 12]; - if(days == 28) { - bool leapyear = false; - if((year % 4) == 0) { - leapyear = true; - if((year % 100) == 0 && (year % 400) != 0) leapyear = false; - } - if(leapyear) days++; - } - if(day < days) continue; - day = 0; - - month++; - if(month < 12) continue; - month = 0; - - year++; - } - - day++; - month++; - year -= 1000; - - memory_cartrtc_write( 0, second % 10); - memory_cartrtc_write( 1, second / 10); - memory_cartrtc_write( 2, minute % 10); - memory_cartrtc_write( 3, minute / 10); - memory_cartrtc_write( 4, hour % 10); - memory_cartrtc_write( 5, hour / 10); - memory_cartrtc_write( 6, day % 10); - memory_cartrtc_write( 7, day / 10); - memory_cartrtc_write( 8, month); - memory_cartrtc_write( 9, year % 10); - memory_cartrtc_write(10, (year / 10) % 10); - memory_cartrtc_write(11, year / 100); - memory_cartrtc_write(12, weekday % 7); - } - - memory_cartrtc_write(16, current_time >> 0); - memory_cartrtc_write(17, current_time >> 8); - memory_cartrtc_write(18, current_time >> 16); - memory_cartrtc_write(19, current_time >> 24); -} - -//returns day of week for specified date -//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday -//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008 -unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) { - unsigned y = 1900, m = 1; //epoch is 1900-01-01 - unsigned sum = 0; //number of days passed since epoch - - year = max(1900, year); - month = max(1, min(12, month)); - day = max(1, min(31, day)); - - while(y < year) { - bool leapyear = false; - if((y % 4) == 0) { - leapyear = true; - if((y % 100) == 0 && (y % 400) != 0) leapyear = false; - } - sum += leapyear ? 366 : 365; - y++; - } - - while(m < month) { - unsigned days = months[m - 1]; - if(days == 28) { - bool leapyear = false; - if((y % 4) == 0) { - leapyear = true; - if((y % 100) == 0 && (y % 400) != 0) leapyear = false; - } - if(leapyear) days++; - } - sum += days; - m++; - } - - sum += day - 1; - return (sum + 1) % 7; //1900-01-01 was a Monday -} - -uint8 SRTC::mmio_read(unsigned addr) { - addr &= 0xffff; - - if(addr == 0x2800) { - if(rtc_mode != RTCM_Read) return 0x00; - - if(rtc_index < 0) { - update_time(); - rtc_index++; - return 0x0f; - } else if(rtc_index > 12) { - rtc_index = -1; - return 0x0f; - } else { - return memory_cartrtc_read(rtc_index++); - } - } - - return cpu_regs_mdr; -} - -void SRTC::mmio_write(unsigned addr, uint8 data) { - addr &= 0xffff; - - if(addr == 0x2801) { - data &= 0x0f; //only the low four bits are used - - if(data == 0x0d) { - rtc_mode = RTCM_Read; - rtc_index = -1; - return; - } - - if(data == 0x0e) { - rtc_mode = RTCM_Command; - return; - } - - if(data == 0x0f) return; //unknown behavior - - if(rtc_mode == RTCM_Write) { - if(rtc_index >= 0 && rtc_index < 12) { - memory_cartrtc_write(rtc_index++, data); - - if(rtc_index == 12) { - //day of week is automatically calculated and written - unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; - unsigned month = memory_cartrtc_read( 8); - unsigned year = memory_cartrtc_read( 9) + memory_cartrtc_read(10) * 10 + memory_cartrtc_read(11) * 100; - year += 1000; - - memory_cartrtc_write(rtc_index++, weekday(year, month, day)); - } - } - } else if(rtc_mode == RTCM_Command) { - if(data == 0) { - rtc_mode = RTCM_Write; - rtc_index = 0; - } else if(data == 4) { - rtc_mode = RTCM_Ready; - rtc_index = -1; - for(unsigned i = 0; i < 13; i++) memory_cartrtc_write(i, 0); - } else { - //unknown behavior - rtc_mode = RTCM_Ready; - } - } - } -} - -SRTC::SRTC() { -} - -#endif diff --git a/source/snes9x/srtcemu.h b/source/snes9x/srtcemu.h deleted file mode 100644 index fc1af24..0000000 --- a/source/snes9x/srtcemu.h +++ /dev/null @@ -1,30 +0,0 @@ -/***** - * S-RTC emulation code - * Copyright (c) byuu - *****/ - - -#ifndef _SRTCEMU_H_ -#define _SRTCEMU_H_ - -class SRTC { -public: - void update_time(); - unsigned weekday(unsigned year, unsigned month, unsigned day); - - void init(); - void enable(); - void power(); - void reset(); - - uint8 mmio_read (unsigned addr); - void mmio_write(unsigned addr, uint8 data); - - SRTC(); - - static const unsigned months[12]; - enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode; - signed rtc_index; -}; - -#endif diff --git a/source/snes9x/tile.cpp b/source/snes9x/tile.cpp index 00c7572..71f3c21 100644 --- a/source/snes9x/tile.cpp +++ b/source/snes9x/tile.cpp @@ -159,663 +159,569 @@ **********************************************************************************/ -// This file includes itself multiple times. -// The other option would be to have 4 files, where A includes B, and B includes C 3 times, and C includes D 5 times. -// Look for the following marker to find where the divisions are. -// Top-level compilation. -#ifndef _NEWTILE_CPP +// This file includes itself multiple times. The other option would be to have +// 4 files, where A includes B, and B includes C 3 times, and C includes D 5 +// times. Look for the following marker to find where the divisions are. +/*===========================================================================*/ + +#ifndef _NEWTILE_CPP // Top-level compilation #define _NEWTILE_CPP #include "snes9x.h" +#include "gfx.h" #include "ppu.h" -#include "tile.h" -static uint32 pixbit[8][16]; -static uint8 hrbit_odd[256]; -static uint8 hrbit_even[256]; +static uint32 pixbit[8][16]; +static uint8 hrbit_odd[256]; +static uint8 hrbit_even[256]; +void S9xInitTileRenderer(void){ + register int i; -void S9xInitTileRenderer (void) -{ - register int i; + for(i=0; i<16; i++) { + register uint32 b = 0; - for (i = 0; i < 16; i++) - { - register uint32 b = 0; +#if defined(LSB_FIRST) + if (i & 8) + b |= 1; + if (i & 4) + b |= 1<<8; + if (i & 2) + b |= 1<<16; + if (i & 1) + b |= 1<<24; +#else + if (i & 8) + b |= 1<<24; + if (i & 4) + b |= 1<<16; + if (i & 2) + b |= 1<<8; + if (i & 1) + b |= 1; +#endif - #ifdef LSB_FIRST - if (i & 8) - b |= 1; - if (i & 4) - b |= 1 << 8; - if (i & 2) - b |= 1 << 16; - if (i & 1) - b |= 1 << 24; - #else - if (i & 8) - b |= 1 << 24; - if (i & 4) - b |= 1 << 16; - if (i & 2) - b |= 1 << 8; - if (i & 1) - b |= 1; - #endif + for(uint8 bitshift=0; bitshift<8; bitshift++) { + pixbit[bitshift][i]=b<> 4]; \ - p2 |= pixbit[(i)][pix & 0xf]; \ - } + if ((pix = *(tp + (n)))) { \ + p1 |= pixbit[(i)][pix >> 4]; \ + p2 |= pixbit[(i)][pix & 0xf]; \ + } static uint8 ConvertTile2 (uint8 *pCache, uint32 TileAddr, uint32) { - register uint8 *tp = &Memory.VRAM[TileAddr]; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT(0, 0); + DOBIT(1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } static uint8 ConvertTile4 (uint8 *pCache, uint32 TileAddr, uint32) { - register uint8 *tp = &Memory.VRAM[TileAddr]; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - DOBIT(16, 2); - DOBIT(17, 3); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } static uint8 ConvertTile8 (uint8 *pCache, uint32 TileAddr, uint32) { - register uint8 *tp = &Memory.VRAM[TileAddr]; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - DOBIT(16, 2); - DOBIT(17, 3); - DOBIT(32, 4); - DOBIT(33, 5); - DOBIT(48, 6); - DOBIT(49, 7); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + DOBIT(32, 4); + DOBIT(33, 5); + DOBIT(48, 6); + DOBIT(49, 7); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } #undef DOBIT - #define DOBIT(n, i) \ - if ((pix = hrbit_odd[*(tp1 + (n))])) \ - p1 |= pixbit[(i)][pix]; \ - if ((pix = hrbit_odd[*(tp2 + (n))])) \ - p2 |= pixbit[(i)][pix]; + if ((pix = hrbit_odd[*(tp1 + (n))])) \ + p1 |= pixbit[(i)][pix]; \ + if ((pix = hrbit_odd[*(tp2 + (n))])) \ + p2 |= pixbit[(i)][pix]; static uint8 ConvertTile2h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) { - register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - if (Tile == 0x3ff) - tp2 = tp1 - (0x3ff << 4); - else - tp2 = tp1 + (1 << 4); + if(Tile==0x3ff){ + tp2=tp1-(0x3ff<<4); + } else { + tp2=tp1+(1<<4); + } - for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT(0, 0); + DOBIT(1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } static uint8 ConvertTile4h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) { - register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - if (Tile == 0x3ff) - tp2 = tp1 - (0x3ff << 5); - else - tp2 = tp1 + (1 << 5); + if(Tile==0x3ff){ + tp2=tp1-(0x3ff<<5); + } else { + tp2=tp1+(1<<5); + } - for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - DOBIT(16, 2); - DOBIT(17, 3); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } #undef DOBIT - #define DOBIT(n, i) \ - if ((pix = hrbit_even[*(tp1 + (n))])) \ - p1 |= pixbit[(i)][pix]; \ - if ((pix = hrbit_even[*(tp2 + (n))])) \ - p2 |= pixbit[(i)][pix]; + if ((pix = hrbit_even[*(tp1 + (n))])) \ + p1 |= pixbit[(i)][pix]; \ + if ((pix = hrbit_even[*(tp2 + (n))])) \ + p2 |= pixbit[(i)][pix]; static uint8 ConvertTile2h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) { - register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - if (Tile == 0x3ff) - tp2 = tp1 - (0x3ff << 4); - else - tp2 = tp1 + (1 << 4); + if(Tile==0x3ff){ + tp2=tp1-(0x3ff<<4); + } else { + tp2=tp1+(1<<4); + } - for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT(0, 0); + DOBIT(1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } static uint8 ConvertTile4h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) { - register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; - if (Tile == 0x3ff) - tp2 = tp1 - (0x3ff << 5); - else - tp2 = tp1 + (1 << 5); + if(Tile==0x3ff){ + tp2=tp1-(0x3ff<<5); + } else { + tp2=tp1+(1<<5); + } - for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - DOBIT( 0, 0); - DOBIT( 1, 1); - DOBIT(16, 2); - DOBIT(17, 3); - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - - return (non_zero ? TRUE : BLANK_TILE); + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + return (non_zero ? TRUE : BLANK_TILE); } #undef DOBIT -// First-level include: Get all the renderers. - +/*****************************************************************************/ +// First-level include: get all the renderers #include "tile.cpp" + +/*****************************************************************************/ // Functions to select which converter and renderer to use. -void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj) -{ - void (**DT) (uint32, uint32, uint32, uint32); - void (**DCT) (uint32, uint32, uint32, uint32, uint32, uint32); - void (**DMP) (uint32, uint32, uint32, uint32, uint32, uint32); - void (**DB) (uint32, uint32, uint32); - void (**DM7BG1) (uint32, uint32, int); - void (**DM7BG2) (uint32, uint32, int); - bool8 M7M1, M7M2; +void S9xSelectTileRenderers(int BGMode, bool8 sub, bool8 obj){ + void (**DT)(uint32,uint32,uint32,uint32); + void (**DCT)(uint32,uint32,uint32,uint32,uint32,uint32); + void (**DMP)(uint32,uint32,uint32,uint32,uint32,uint32); + void (**DB)(uint32,uint32,uint32); + void (**DM7BG1)(uint32,uint32,int); + void (**DM7BG2)(uint32,uint32,int); + bool8 M7M1, M7M2; - M7M1 = PPU.BGMosaic[0] && PPU.Mosaic > 1; - M7M2 = PPU.BGMosaic[1] && PPU.Mosaic > 1; + M7M1=PPU.BGMosaic[0] && PPU.Mosaic>1; + M7M2=PPU.BGMosaic[1] && PPU.Mosaic>1; - if (!IPPU.DoubleWidthPixels) - { - DT = Renderers_DrawTile16Normal1x1; - DCT = Renderers_DrawClippedTile16Normal1x1; - DMP = Renderers_DrawMosaicPixel16Normal1x1; - DB = Renderers_DrawBackdrop16Normal1x1; - DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal1x1 : Renderers_DrawMode7BG1Normal1x1; - DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal1x1 : Renderers_DrawMode7BG2Normal1x1; - GFX.LinesPerTile = 8; - } - else - { - bool8 hires, interlace; + if(!IPPU.DoubleWidthPixels){ + DT=Renderers_DrawTile16Normal1x1; + DCT=Renderers_DrawClippedTile16Normal1x1; + DMP=Renderers_DrawMosaicPixel16Normal1x1; + DB=Renderers_DrawBackdrop16Normal1x1; + DM7BG1=M7M1?Renderers_DrawMode7MosaicBG1Normal1x1:Renderers_DrawMode7BG1Normal1x1; + DM7BG2=M7M2?Renderers_DrawMode7MosaicBG2Normal1x1:Renderers_DrawMode7BG2Normal1x1; + GFX.LinesPerTile = 8; + } else { + bool8 hires, interlace; + if(obj){ // OBJ + hires=(BGMode==5 || BGMode==6 || IPPU.PseudoHires); + interlace=IPPU.InterlaceOBJ; + } else if(BGMode==5 || BGMode==6){ + hires=TRUE; + interlace=IPPU.Interlace; + } else { + hires=IPPU.PseudoHires; + interlace=FALSE; + } + if(sub) hires=FALSE; - if (obj) // OBJ - { - hires = (BGMode == 5 || BGMode == 6 || IPPU.PseudoHires); - interlace = IPPU.InterlaceOBJ; - } - else - if (BGMode == 5 || BGMode == 6) - { - hires = TRUE; - interlace = IPPU.Interlace; - } - else - { - hires = IPPU.PseudoHires; - interlace = FALSE; - } + if(hires && interlace){ + DT=Renderers_DrawTile16HiresInterlace; + DCT=Renderers_DrawClippedTile16HiresInterlace; + DMP=Renderers_DrawMosaicPixel16HiresInterlace; + DB=Renderers_DrawBackdrop16Hires; + DM7BG1=M7M1?Renderers_DrawMode7MosaicBG1Hires:Renderers_DrawMode7BG1Hires; + DM7BG2=M7M2?Renderers_DrawMode7MosaicBG2Hires:Renderers_DrawMode7BG2Hires; + GFX.LinesPerTile = 4; + } else if(hires){ + DT=Renderers_DrawTile16Hires; + DCT=Renderers_DrawClippedTile16Hires; + DMP=Renderers_DrawMosaicPixel16Hires; + DB=Renderers_DrawBackdrop16Hires; + DM7BG1=M7M1?Renderers_DrawMode7MosaicBG1Hires:Renderers_DrawMode7BG1Hires; + DM7BG2=M7M2?Renderers_DrawMode7MosaicBG2Hires:Renderers_DrawMode7BG2Hires; + GFX.LinesPerTile = 8; + } else if(interlace){ + DT=Renderers_DrawTile16Interlace; + DCT=Renderers_DrawClippedTile16Interlace; + DMP=Renderers_DrawMosaicPixel16Interlace; + DB=Renderers_DrawBackdrop16Normal2x1; + DM7BG1=M7M1?Renderers_DrawMode7MosaicBG1Normal2x1:Renderers_DrawMode7BG1Normal2x1; + DM7BG2=M7M2?Renderers_DrawMode7MosaicBG2Normal2x1:Renderers_DrawMode7BG2Normal2x1; + GFX.LinesPerTile = 4; + } else { + DT=Renderers_DrawTile16Normal2x1; + DCT=Renderers_DrawClippedTile16Normal2x1; + DMP=Renderers_DrawMosaicPixel16Normal2x1; + DB=Renderers_DrawBackdrop16Normal2x1; + DM7BG1=M7M1?Renderers_DrawMode7MosaicBG1Normal2x1:Renderers_DrawMode7BG1Normal2x1; + DM7BG2=M7M2?Renderers_DrawMode7MosaicBG2Normal2x1:Renderers_DrawMode7BG2Normal2x1; + GFX.LinesPerTile = 8; + } + } - if (sub) - hires = FALSE; + GFX.DrawTileNomath=DT[0]; + GFX.DrawClippedTileNomath=DCT[0]; + GFX.DrawMosaicPixelNomath=DMP[0]; + GFX.DrawBackdropNomath=DB[0]; + GFX.DrawMode7BG1Nomath=DM7BG1[0]; + GFX.DrawMode7BG2Nomath=DM7BG2[0]; - if (hires && interlace) - { - DT = Renderers_DrawTile16HiresInterlace; - DCT = Renderers_DrawClippedTile16HiresInterlace; - DMP = Renderers_DrawMosaicPixel16HiresInterlace; - DB = Renderers_DrawBackdrop16Hires; - DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Hires : Renderers_DrawMode7BG1Hires; - DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires; - GFX.LinesPerTile = 4; - } - else - if (hires) - { - DT = Renderers_DrawTile16Hires; - DCT = Renderers_DrawClippedTile16Hires; - DMP = Renderers_DrawMosaicPixel16Hires; - DB = Renderers_DrawBackdrop16Hires; - DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Hires : Renderers_DrawMode7BG1Hires; - DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires; - GFX.LinesPerTile = 8; - } - else - if (interlace) - { - DT = Renderers_DrawTile16Interlace; - DCT = Renderers_DrawClippedTile16Interlace; - DMP = Renderers_DrawMosaicPixel16Interlace; - DB = Renderers_DrawBackdrop16Normal2x1; - DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal2x1 : Renderers_DrawMode7BG1Normal2x1; - DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal2x1 : Renderers_DrawMode7BG2Normal2x1; - GFX.LinesPerTile = 4; - } - else - { - DT = Renderers_DrawTile16Normal2x1; - DCT = Renderers_DrawClippedTile16Normal2x1; - DMP = Renderers_DrawMosaicPixel16Normal2x1; - DB = Renderers_DrawBackdrop16Normal2x1; - DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal2x1 : Renderers_DrawMode7BG1Normal2x1; - DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal2x1 : Renderers_DrawMode7BG2Normal2x1; - GFX.LinesPerTile = 8; - } - } - - GFX.DrawTileNomath = DT[0]; - GFX.DrawClippedTileNomath = DCT[0]; - GFX.DrawMosaicPixelNomath = DMP[0]; - GFX.DrawBackdropNomath = DB[0]; - GFX.DrawMode7BG1Nomath = DM7BG1[0]; - GFX.DrawMode7BG2Nomath = DM7BG2[0]; - - int i; - - if (!Settings.Transparency) - i = 0; - else - { - i = (Memory.FillRAM[0x2131] & 0x80) ? 4 : 1; - if (Memory.FillRAM[0x2131] & 0x40) - { - i++; - if (Memory.FillRAM[0x2130] & 2) - i++; - } - } - - GFX.DrawTileMath = DT[i]; - GFX.DrawClippedTileMath = DCT[i]; - GFX.DrawMosaicPixelMath = DMP[i]; - GFX.DrawBackdropMath = DB[i]; - GFX.DrawMode7BG1Math = DM7BG1[i]; - GFX.DrawMode7BG2Math = DM7BG2[i]; + int i; + if(!Settings.Transparency){ + i=0; + } else { + i=((Memory.FillRAM[0x2131]&0x80)?4:1); + if(Memory.FillRAM[0x2131]&0x40){ + i++; + if(Memory.FillRAM[0x2130]&2) i++; + } + } + GFX.DrawTileMath=DT[i]; + GFX.DrawClippedTileMath=DCT[i]; + GFX.DrawMosaicPixelMath=DMP[i]; + GFX.DrawBackdropMath=DB[i]; + GFX.DrawMode7BG1Math=DM7BG1[i]; + GFX.DrawMode7BG2Math=DM7BG2[i]; } -void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) -{ - switch (depth) - { - case 8: - BG.ConvertTile = BG.ConvertTileFlip = ConvertTile8; - BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_8BIT]; - BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_8BIT]; - BG.TileShift = 6; - BG.PaletteShift = 0; - BG.PaletteMask = 0; - BG.DirectColourMode = Memory.FillRAM[0x2130] & 1; - - break; - - case 4: - if (hires) - { - if (sub || mosaic) - { - BG.ConvertTile = ConvertTile4h_even; - BG.Buffer = IPPU.TileCache[TILE_4BIT_EVEN]; - BG.Buffered = IPPU.TileCached[TILE_4BIT_EVEN]; - BG.ConvertTileFlip = ConvertTile4h_odd; - BG.BufferFlip = IPPU.TileCache[TILE_4BIT_ODD]; - BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_ODD]; - } - else - { - BG.ConvertTile = ConvertTile4h_odd; - BG.Buffer = IPPU.TileCache[TILE_4BIT_ODD]; - BG.Buffered = IPPU.TileCached[TILE_4BIT_ODD]; - BG.ConvertTileFlip = ConvertTile4h_even; - BG.BufferFlip = IPPU.TileCache[TILE_4BIT_EVEN]; - BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_EVEN]; - } - } - else - { - BG.ConvertTile = BG.ConvertTileFlip = ConvertTile4; - BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_4BIT]; - BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_4BIT]; - } - - BG.TileShift = 5; - BG.PaletteShift = 10 - 4; - BG.PaletteMask = 7 << 4; - BG.DirectColourMode = FALSE; - - break; - - case 2: - if (hires) - { - if (sub || mosaic) - { - BG.ConvertTile = ConvertTile2h_even; - BG.Buffer = IPPU.TileCache[TILE_2BIT_EVEN]; - BG.Buffered = IPPU.TileCached[TILE_2BIT_EVEN]; - BG.ConvertTileFlip = ConvertTile2h_odd; - BG.BufferFlip = IPPU.TileCache[TILE_2BIT_ODD]; - BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_ODD]; - } - else - { - BG.ConvertTile = ConvertTile2h_odd; - BG.Buffer = IPPU.TileCache[TILE_2BIT_ODD]; - BG.Buffered = IPPU.TileCached[TILE_2BIT_ODD]; - BG.ConvertTileFlip = ConvertTile2h_even; - BG.BufferFlip = IPPU.TileCache[TILE_2BIT_EVEN]; - BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_EVEN]; - } - } - else - { - BG.ConvertTile = BG.ConvertTileFlip = ConvertTile2; - BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_2BIT]; - BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_2BIT]; - } - - BG.TileShift = 4; - BG.PaletteShift = 10 - 2; - BG.PaletteMask = 7 << 2; - BG.DirectColourMode = FALSE; - - break; - } +void S9xSelectTileConverter(int depth, bool8 hires, bool8 sub, bool8 mosaic){ + switch(depth){ + case 8: + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile8; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_8BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_8BIT]; + BG.TileShift = 6; + BG.PaletteShift = 0; + BG.PaletteMask = 0; + BG.DirectColourMode = (Memory.FillRAM[0x2130]&1); + break; + case 4: + if(hires){ + if(sub || mosaic){ + BG.ConvertTile = ConvertTile4h_even; + BG.Buffer = IPPU.TileCache[TILE_4BIT_EVEN]; + BG.Buffered = IPPU.TileCached[TILE_4BIT_EVEN]; + BG.ConvertTileFlip = ConvertTile4h_odd; + BG.BufferFlip = IPPU.TileCache[TILE_4BIT_ODD]; + BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_ODD]; + } else { + BG.ConvertTile = ConvertTile4h_odd; + BG.Buffer = IPPU.TileCache[TILE_4BIT_ODD]; + BG.Buffered = IPPU.TileCached[TILE_4BIT_ODD]; + BG.ConvertTileFlip = ConvertTile4h_even; + BG.BufferFlip = IPPU.TileCache[TILE_4BIT_EVEN]; + BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_EVEN]; + } + } else { + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile4; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_4BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_4BIT]; + } + BG.TileShift = 5; + BG.PaletteShift = 10-4; + BG.PaletteMask = 7<<4; + BG.DirectColourMode = FALSE; + break; + case 2: + if(hires){ + if(sub || mosaic){ + BG.ConvertTile = ConvertTile2h_even; + BG.Buffer = IPPU.TileCache[TILE_2BIT_EVEN]; + BG.Buffered = IPPU.TileCached[TILE_2BIT_EVEN]; + BG.ConvertTileFlip = ConvertTile2h_odd; + BG.BufferFlip = IPPU.TileCache[TILE_2BIT_ODD]; + BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_ODD]; + } else { + BG.ConvertTile = ConvertTile2h_odd; + BG.Buffer = IPPU.TileCache[TILE_2BIT_ODD]; + BG.Buffered = IPPU.TileCached[TILE_2BIT_ODD]; + BG.ConvertTileFlip = ConvertTile2h_even; + BG.BufferFlip = IPPU.TileCache[TILE_2BIT_EVEN]; + BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_EVEN]; + } + } else { + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile2; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_2BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_2BIT]; + } + BG.TileShift = 4; + BG.PaletteShift = 10-2; + BG.PaletteMask = 7<<2; + BG.DirectColourMode = FALSE; + break; + } } -/*****************************************************************************/ +/*===========================================================================*/ #else -#ifndef NAME1 // First-level: Get all the renderers. -/*****************************************************************************/ +#ifndef NAME1 // First-level: Get all renderers +/*===========================================================================*/ #define GET_CACHED_TILE() \ - uint32 TileNumber; \ - uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \ - if (Tile & 0x100) \ - TileAddr += BG.NameSelect; \ - TileAddr &= 0xffff; \ - TileNumber = TileAddr >> BG.TileShift; \ - if (Tile & H_FLIP) \ - { \ - pCache = &BG.BufferFlip[TileNumber << 6]; \ - if (!BG.BufferedFlip[TileNumber]) \ - BG.BufferedFlip[TileNumber] = BG.ConvertTileFlip(pCache, TileAddr, Tile & 0x3ff); \ - } \ - else \ - { \ - pCache = &BG.Buffer[TileNumber << 6]; \ - if (!BG.Buffered[TileNumber]) \ - BG.Buffered[TileNumber] = BG.ConvertTile(pCache, TileAddr, Tile & 0x3ff); \ - } + uint32 TileNumber; \ + uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \ + if ((Tile & 0x100)) \ + TileAddr += BG.NameSelect; \ + TileAddr &= 0xffff; \ + TileNumber = (TileAddr >> BG.TileShift); \ + if((Tile & H_FLIP)) { \ + pCache = &BG.BufferFlip[TileNumber << 6]; \ + if(!BG.BufferedFlip[TileNumber]) \ + BG.BufferedFlip[TileNumber] = BG.ConvertTileFlip (pCache, TileAddr, Tile&0x3ff); \ + } else { \ + pCache = &BG.Buffer[TileNumber << 6]; \ + if(!BG.Buffered[TileNumber]) \ + BG.Buffered[TileNumber] = BG.ConvertTile (pCache, TileAddr, Tile&0x3ff); \ + } #define IS_BLANK_TILE() \ - (BG.Buffered[TileNumber] == BLANK_TILE) + (BG.Buffered[TileNumber] == BLANK_TILE) #define SELECT_PALETTE() \ - if (BG.DirectColourMode) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps(); \ - GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; \ - } \ - else \ - GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; \ - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors + if(BG.DirectColourMode) { \ + if(IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[(Tile>>10) & 7]; \ + } else { \ + GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; \ + } \ + GFX.ScreenColors = GFX.ClipColors?BlackColourMap:GFX.RealScreenColors; -#define NOMATH(Op, Main, Sub, SD) \ - (Main) +#define NOMATH(Op, Main, Sub, SD) (Main) +#define REGMATH(Op, Main, Sub, SD) (COLOR_##Op((Main),((SD)&0x20)?(Sub):GFX.FixedColour)) +#define MATHF1_2(Op, Main, Sub, SD) (GFX.ClipColors?(COLOR_##Op((Main),GFX.FixedColour)):(COLOR_##Op##1_2((Main),GFX.FixedColour))) +#define MATHS1_2(Op, Main, Sub, SD) (GFX.ClipColors?REGMATH(Op,Main,Sub,SD):(((SD)&0x20)?COLOR_##Op##1_2((Main),(Sub)):COLOR_##Op((Main),GFX.FixedColour))) -#define REGMATH(Op, Main, Sub, SD) \ - (COLOR_##Op((Main), ((SD) & 0x20) ? (Sub) : GFX.FixedColour)) - -#define MATHF1_2(Op, Main, Sub, SD) \ - (GFX.ClipColors ? (COLOR_##Op((Main), GFX.FixedColour)) : (COLOR_##Op##1_2((Main), GFX.FixedColour))) - -#define MATHS1_2(Op, Main, Sub, SD) \ - (GFX.ClipColors ? REGMATH(Op, Main, Sub, SD) : (((SD) & 0x20) ? COLOR_##Op##1_2((Main), (Sub)) : COLOR_##Op((Main), GFX.FixedColour))) - -// Basic routine to render an unclipped tile. -// Input parameters: -// BPSTART = either StartLine or (StartLine * 2 + BG.InterlaceLine), -// so interlace modes can render every other line from the tile. -// PITCH = 1 or 2, again so interlace can count lines properly. -// DRAW_PIXEL(N, M) is a routine to actually draw the pixel. N is the pixel in the row to draw, -// and M is a test which if false means the pixel should be skipped. -// Z1 is the "draw if Z1 > cur_depth". -// Z2 is the "cur_depth = new_depth". OBJ need the two separate. -// Pix is the pixel to draw. - -#define Z1 GFX.Z1 -#define Z2 GFX.Z2 +/*****************************************************************************/ +// Basic routine to render an unclipped tile. Input parameters: +// BPSTART = either StartLine or (StartLine*2 + BG.InterlaceLine), so +// interlace modes can render every other line from the tile. +// PITCH = 1 or 2, again so interlace can count lines properly. +// DRAW_PIXEL(N,M) is a routine to actually draw the pixel. N is the pixel in +// the row to draw, and M is a test which if false means the pixel should +// be skipped. +// Z1 is the "draw if Z1>cur_depth". +// Z2 is the "cur_depth = new_depth". OBJ need the two separate. +// Pix is the pixel to draw. +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 #define DRAW_TILE() \ - uint8 *pCache; \ - register int32 l; \ - register uint8 *bp, Pix; \ - \ - GET_CACHED_TILE(); \ - if (IS_BLANK_TILE()) \ - return; \ - SELECT_PALETTE(); \ - \ - if (!(Tile & (V_FLIP | H_FLIP))) \ - { \ - bp = pCache + BPSTART; \ - for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ - { \ - DRAW_PIXEL(0, Pix = bp[0]); \ - DRAW_PIXEL(1, Pix = bp[1]); \ - DRAW_PIXEL(2, Pix = bp[2]); \ - DRAW_PIXEL(3, Pix = bp[3]); \ - DRAW_PIXEL(4, Pix = bp[4]); \ - DRAW_PIXEL(5, Pix = bp[5]); \ - DRAW_PIXEL(6, Pix = bp[6]); \ - DRAW_PIXEL(7, Pix = bp[7]); \ - } \ - } \ - else \ - if (!(Tile & V_FLIP)) \ - { \ - bp = pCache + BPSTART; \ - for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ - { \ - DRAW_PIXEL(0, Pix = bp[7]); \ - DRAW_PIXEL(1, Pix = bp[6]); \ - DRAW_PIXEL(2, Pix = bp[5]); \ - DRAW_PIXEL(3, Pix = bp[4]); \ - DRAW_PIXEL(4, Pix = bp[3]); \ - DRAW_PIXEL(5, Pix = bp[2]); \ - DRAW_PIXEL(6, Pix = bp[1]); \ - DRAW_PIXEL(7, Pix = bp[0]); \ - } \ - } \ - else \ - if (!(Tile & H_FLIP)) \ - { \ - bp = pCache + 56 - BPSTART; \ - for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ - { \ - DRAW_PIXEL(0, Pix = bp[0]); \ - DRAW_PIXEL(1, Pix = bp[1]); \ - DRAW_PIXEL(2, Pix = bp[2]); \ - DRAW_PIXEL(3, Pix = bp[3]); \ - DRAW_PIXEL(4, Pix = bp[4]); \ - DRAW_PIXEL(5, Pix = bp[5]); \ - DRAW_PIXEL(6, Pix = bp[6]); \ - DRAW_PIXEL(7, Pix = bp[7]); \ - } \ - } \ - else \ - { \ - bp = pCache + 56 - BPSTART; \ - for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ - { \ - DRAW_PIXEL(0, Pix = bp[7]); \ - DRAW_PIXEL(1, Pix = bp[6]); \ - DRAW_PIXEL(2, Pix = bp[5]); \ - DRAW_PIXEL(3, Pix = bp[4]); \ - DRAW_PIXEL(4, Pix = bp[3]); \ - DRAW_PIXEL(5, Pix = bp[2]); \ - DRAW_PIXEL(6, Pix = bp[1]); \ - DRAW_PIXEL(7, Pix = bp[0]); \ - } \ - } + uint8 *pCache; \ + register int32 l; \ + register uint8 *bp, Pix; \ +\ + GET_CACHED_TILE(); \ + if(IS_BLANK_TILE()) return; \ + SELECT_PALETTE(); \ +\ + if (!(Tile & (V_FLIP | H_FLIP))) { \ + bp = pCache + BPSTART; \ + for(l = LineCount; l > 0; l--, bp += 8*PITCH, Offset += GFX.PPL) { \ + DRAW_PIXEL(0,Pix=bp[0]); \ + DRAW_PIXEL(1,Pix=bp[1]); \ + DRAW_PIXEL(2,Pix=bp[2]); \ + DRAW_PIXEL(3,Pix=bp[3]); \ + DRAW_PIXEL(4,Pix=bp[4]); \ + DRAW_PIXEL(5,Pix=bp[5]); \ + DRAW_PIXEL(6,Pix=bp[6]); \ + DRAW_PIXEL(7,Pix=bp[7]); \ + } \ + } else if(!(Tile & V_FLIP)) { \ + bp = pCache + BPSTART; \ + for(l = LineCount; l > 0; l--, bp += 8*PITCH, Offset += GFX.PPL) { \ + DRAW_PIXEL(0,Pix=bp[7]); \ + DRAW_PIXEL(1,Pix=bp[6]); \ + DRAW_PIXEL(2,Pix=bp[5]); \ + DRAW_PIXEL(3,Pix=bp[4]); \ + DRAW_PIXEL(4,Pix=bp[3]); \ + DRAW_PIXEL(5,Pix=bp[2]); \ + DRAW_PIXEL(6,Pix=bp[1]); \ + DRAW_PIXEL(7,Pix=bp[0]); \ + } \ + } else if(!(Tile & H_FLIP)) { \ + bp = pCache + 56 - BPSTART; \ + for(l = LineCount; l > 0; l--, bp -= 8*PITCH, Offset += GFX.PPL) { \ + DRAW_PIXEL(0,Pix=bp[0]); \ + DRAW_PIXEL(1,Pix=bp[1]); \ + DRAW_PIXEL(2,Pix=bp[2]); \ + DRAW_PIXEL(3,Pix=bp[3]); \ + DRAW_PIXEL(4,Pix=bp[4]); \ + DRAW_PIXEL(5,Pix=bp[5]); \ + DRAW_PIXEL(6,Pix=bp[6]); \ + DRAW_PIXEL(7,Pix=bp[7]); \ + } \ + } else { \ + bp = pCache + 56 - BPSTART; \ + for(l = LineCount; l > 0; l--, bp -= 8*PITCH, Offset += GFX.PPL) { \ + DRAW_PIXEL(0,Pix=bp[7]); \ + DRAW_PIXEL(1,Pix=bp[6]); \ + DRAW_PIXEL(2,Pix=bp[5]); \ + DRAW_PIXEL(3,Pix=bp[4]); \ + DRAW_PIXEL(4,Pix=bp[3]); \ + DRAW_PIXEL(5,Pix=bp[2]); \ + DRAW_PIXEL(6,Pix=bp[1]); \ + DRAW_PIXEL(7,Pix=bp[0]); \ + } \ + } -#define NAME1 DrawTile16 -#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount - -// Second-level include: Get the DrawTile16 renderers. +#define NAME1 DrawTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount +// Second-level include: Get the DrawTile16 renderers #include "tile.cpp" #undef NAME1 @@ -824,105 +730,86 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) #undef Z1 #undef Z2 +/*****************************************************************************/ // Basic routine to render a clipped tile. Inputs same as above. -#define Z1 GFX.Z1 -#define Z2 GFX.Z2 - +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 #define DRAW_TILE() \ - uint8 *pCache; \ - register int32 l; \ - register uint8 *bp, Pix, w; \ - \ - GET_CACHED_TILE(); \ - if (IS_BLANK_TILE()) \ - return; \ - SELECT_PALETTE(); \ - \ - if (!(Tile & (V_FLIP | H_FLIP))) \ - { \ - bp = pCache + BPSTART; \ - for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ - { \ - w = Width; \ - switch (StartPixel) \ - { \ - case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \ - case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \ - case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \ - case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \ - case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \ - case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \ - case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \ - case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ - } \ - } \ - } \ - else \ - if (!(Tile & V_FLIP)) \ - { \ - bp = pCache + BPSTART; \ - for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ - { \ - w = Width; \ - switch (StartPixel) \ - { \ - case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \ - case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \ - case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \ - case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \ - case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \ - case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \ - case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \ - case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ - } \ - } \ - } \ - else \ - if (!(Tile & H_FLIP)) \ - { \ - bp = pCache + 56 - BPSTART; \ - for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ - { \ - w = Width; \ - switch (StartPixel) \ - { \ - case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \ - case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \ - case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \ - case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \ - case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \ - case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \ - case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \ - case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ - } \ - } \ - } \ - else \ - { \ - bp = pCache + 56 - BPSTART; \ - for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ - { \ - w = Width; \ - switch (StartPixel) \ - { \ - case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \ - case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \ - case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \ - case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \ - case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \ - case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \ - case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \ - case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ - } \ - } \ - } + uint8 *pCache; \ + register int32 l; \ + register uint8 *bp, Pix, w; \ +\ + GET_CACHED_TILE(); \ + if(IS_BLANK_TILE()) return; \ + SELECT_PALETTE(); \ +\ + if (!(Tile & (V_FLIP | H_FLIP))) { \ + bp = pCache + BPSTART; \ + for(l = LineCount; l > 0; l--, bp += 8*PITCH, Offset += GFX.PPL) { \ + w=Width; \ + switch(StartPixel){ \ + case 0: DRAW_PIXEL(0,Pix=bp[0]); if(!--w) break; \ + case 1: DRAW_PIXEL(1,Pix=bp[1]); if(!--w) break; \ + case 2: DRAW_PIXEL(2,Pix=bp[2]); if(!--w) break; \ + case 3: DRAW_PIXEL(3,Pix=bp[3]); if(!--w) break; \ + case 4: DRAW_PIXEL(4,Pix=bp[4]); if(!--w) break; \ + case 5: DRAW_PIXEL(5,Pix=bp[5]); if(!--w) break; \ + case 6: DRAW_PIXEL(6,Pix=bp[6]); if(!--w) break; \ + case 7: DRAW_PIXEL(7,Pix=bp[7]); break; \ + } \ + } \ + } else if(!(Tile & V_FLIP)) { \ + bp = pCache + BPSTART; \ + for(l = LineCount; l > 0; l--, bp += 8*PITCH, Offset += GFX.PPL) { \ + w=Width; \ + switch(StartPixel){ \ + case 0: DRAW_PIXEL(0,Pix=bp[7]); if(!--w) break; \ + case 1: DRAW_PIXEL(1,Pix=bp[6]); if(!--w) break; \ + case 2: DRAW_PIXEL(2,Pix=bp[5]); if(!--w) break; \ + case 3: DRAW_PIXEL(3,Pix=bp[4]); if(!--w) break; \ + case 4: DRAW_PIXEL(4,Pix=bp[3]); if(!--w) break; \ + case 5: DRAW_PIXEL(5,Pix=bp[2]); if(!--w) break; \ + case 6: DRAW_PIXEL(6,Pix=bp[1]); if(!--w) break; \ + case 7: DRAW_PIXEL(7,Pix=bp[0]); break; \ + } \ + } \ + } else if(!(Tile & H_FLIP)) { \ + bp = pCache + 56 - BPSTART; \ + for(l = LineCount; l > 0; l--, bp -= 8*PITCH, Offset += GFX.PPL) { \ + w=Width; \ + switch(StartPixel){ \ + case 0: DRAW_PIXEL(0,Pix=bp[0]); if(!--w) break; \ + case 1: DRAW_PIXEL(1,Pix=bp[1]); if(!--w) break; \ + case 2: DRAW_PIXEL(2,Pix=bp[2]); if(!--w) break; \ + case 3: DRAW_PIXEL(3,Pix=bp[3]); if(!--w) break; \ + case 4: DRAW_PIXEL(4,Pix=bp[4]); if(!--w) break; \ + case 5: DRAW_PIXEL(5,Pix=bp[5]); if(!--w) break; \ + case 6: DRAW_PIXEL(6,Pix=bp[6]); if(!--w) break; \ + case 7: DRAW_PIXEL(7,Pix=bp[7]); break; \ + } \ + } \ + } else { \ + bp = pCache + 56 - BPSTART; \ + for(l = LineCount; l > 0; l--, bp -= 8*PITCH, Offset += GFX.PPL) { \ + w=Width; \ + switch(StartPixel){ \ + case 0: DRAW_PIXEL(0,Pix=bp[7]); if(!--w) break; \ + case 1: DRAW_PIXEL(1,Pix=bp[6]); if(!--w) break; \ + case 2: DRAW_PIXEL(2,Pix=bp[5]); if(!--w) break; \ + case 3: DRAW_PIXEL(3,Pix=bp[4]); if(!--w) break; \ + case 4: DRAW_PIXEL(4,Pix=bp[3]); if(!--w) break; \ + case 5: DRAW_PIXEL(5,Pix=bp[2]); if(!--w) break; \ + case 6: DRAW_PIXEL(6,Pix=bp[1]); if(!--w) break; \ + case 7: DRAW_PIXEL(7,Pix=bp[0]); break; \ + } \ + } \ + } -#define NAME1 DrawClippedTile16 -#define ARGS uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount - -// Second-level include: Get the DrawClippedTile16 renderers. +#define NAME1 DrawClippedTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount +// Second-level include: Get the DrawClippedTile16 renderers #include "tile.cpp" #undef NAME1 @@ -931,44 +818,39 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) #undef Z1 #undef Z2 -// Basic routine to render a single mosaic pixel. -// DRAW_PIXEL, BPSTART, Z1, Z2 and Pix are the same as above, but PITCH is not used. - -#define Z1 GFX.Z1 -#define Z2 GFX.Z2 +/*****************************************************************************/ +// Basic routine to render a single mosaic pixel. DRAW_PIXEL, BPSTART, Z1, Z2 +// and Pix are the same as above, but PITCH is not used. +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 #define DRAW_TILE() \ - uint8 *pCache; \ - register int32 l, w; \ - register uint8 Pix; \ - \ - GET_CACHED_TILE(); \ - if (IS_BLANK_TILE()) \ - return; \ - SELECT_PALETTE(); \ - \ - if (Tile & H_FLIP) \ - StartPixel = 7 - StartPixel; \ - \ - if (Tile & V_FLIP) \ - Pix = pCache[56 - BPSTART + StartPixel]; \ - else \ - Pix = pCache[BPSTART + StartPixel]; \ - \ - if (Pix) \ - { \ - for (l = LineCount; l > 0; l--, Offset += GFX.PPL) \ - { \ - for (w = Width - 1; w >= 0; w--) \ - DRAW_PIXEL(w, 1); \ - } \ - } + uint8 *pCache; \ + register int32 l, w; \ + register uint8 Pix; \ +\ + GET_CACHED_TILE(); \ + if(IS_BLANK_TILE()) return; \ + SELECT_PALETTE(); \ +\ + if (Tile & H_FLIP) StartPixel = 7 - StartPixel; \ + if (Tile & V_FLIP) { \ + Pix = pCache[56 - BPSTART + StartPixel]; \ + } else { \ + Pix = pCache[BPSTART + StartPixel]; \ + } \ + if(Pix){ \ + for(l = LineCount; l > 0; l--, Offset += GFX.PPL) { \ + for(w = Width-1; w>=0; w--) { \ + DRAW_PIXEL(w,1); \ + } \ + } \ + } -#define NAME1 DrawMosaicPixel16 -#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount - -// Second-level include: Get the DrawMosaicPixel16 renderers. +#define NAME1 DrawMosaicPixel16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount +// Second-level include: Get the DrawMosaicPixel16 renderers #include "tile.cpp" #undef NAME1 @@ -977,33 +859,32 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) #undef Z1 #undef Z2 -// Basic routine to render the backdrop. -// DRAW_PIXEL is the same as above, but since we're just replicating a single pixel there's no need for PITCH or BPSTART -// (or interlace at all, really). -// The backdrop is always depth = 1, so Z1 = Z2 = 1. And backdrop is always color 0. - -#define NO_INTERLACE 1 -#define Z1 1 -#define Z2 1 -#define Pix 0 +/*****************************************************************************/ +// Basic routine to render the backdrop. DRAW_PIXEL is the same as above, but +// since we're just replicating a single pixel there's no need for PITCH or +// BPSTART (or interlace at all, really). The backdrop is always depth=1, so +// Z1=Z2=1. And backdrop is always color 0. +#define NO_INTERLACE 1 +#define Z1 1 +#define Z2 1 +#define Pix 0 #define DRAW_TILE() \ - register uint32 l, x; \ - \ - GFX.RealScreenColors = IPPU.ScreenColors; \ - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ - \ - for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) \ - { \ - for (x = Left; x < Right; x++) \ - DRAW_PIXEL(x, 1); \ - } + register uint32 l, x; \ +\ + GFX.RealScreenColors = IPPU.ScreenColors; \ + GFX.ScreenColors = GFX.ClipColors?BlackColourMap:GFX.RealScreenColors; \ +\ + for(l=GFX.StartY; l<=GFX.EndY; l++, Offset+=GFX.PPL) { \ + for(x=Left; xM7HOFS << 19) >> 19; \ - int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ - \ - int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ - int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ - \ - if (PPU.Mode7VFlip) \ - starty = 255 - (int) (Line + 1); \ - else \ - starty = Line + 1; \ - \ - yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ - \ - int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ - int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ - \ - if (PPU.Mode7HFlip) \ - { \ - startx = Right - 1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = Left; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ - \ - int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ - int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ - int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ - \ - uint8 Pix; \ - \ - if (!PPU.Mode7Repeat) \ - { \ - for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ - { \ - int X = ((AA + BB) >> 8) & 0x3ff; \ - int Y = ((CC + DD) >> 8) & 0x3ff; \ - \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - \ - DRAW_PIXEL(x, Pix = (b & MASK)); \ - } \ - } \ - else \ - { \ - for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ - { \ - int X = ((AA + BB) >> 8); \ - int Y = ((CC + DD) >> 8); \ - \ - uint8 b; \ - \ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - } \ - else \ - if (PPU.Mode7Repeat == 3) \ - b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - else \ - continue; \ - \ - DRAW_PIXEL(x, Pix = (b & MASK)); \ - } \ - } \ - } + uint8 *VRAM1 = Memory.VRAM + 1; \ +\ + if(DCMODE) { \ + if(IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[0]; \ + } else { \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + } \ + GFX.ScreenColors = GFX.ClipColors?BlackColourMap:GFX.RealScreenColors; \ +\ + int aa, cc; \ + int startx; \ +\ + uint32 Offset = GFX.StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; \ +\ + for(uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) { \ + int yy, starty; \ +\ + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ +\ + int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ + int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ +\ + if (PPU.Mode7VFlip) { \ + starty = 255 - (int) (Line+1); \ + } else { \ + starty = Line+1; \ + } \ +\ + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ +\ + int BB = ((l->MatrixB*starty)&~63) + ((l->MatrixB*yy)&~63) + (CentreX << 8); \ + int DD = ((l->MatrixD*starty)&~63) + ((l->MatrixD*yy)&~63) + (CentreY << 8); \ +\ + if(PPU.Mode7HFlip) { \ + startx = Right - 1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } else { \ + startx = Left; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ +\ + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA*startx + ((l->MatrixA*xx)&~63); \ + int CC = l->MatrixC*startx + ((l->MatrixC*xx)&~63); \ + uint8 Pix; \ +\ + if(!PPU.Mode7Repeat) { \ + for(uint32 x = Left; x> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + DRAW_PIXEL(x, Pix=(b&MASK)); \ + } \ + } else { \ + for(uint32 x = Left; x> 8); \ + int Y = ((CC + DD) >> 8); \ +\ + uint8 b; \ + if (((X | Y) & ~0x3ff) == 0) { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } else if(PPU.Mode7Repeat == 3) { \ + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } else { \ + continue; \ + } \ + DRAW_PIXEL(x, Pix=(b&MASK)); \ + } \ + } \ + } #define DRAW_TILE_MOSAIC() \ - uint8 *VRAM1 = Memory.VRAM + 1; \ - \ - if (DCMODE) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps(); \ - GFX.RealScreenColors = DirectColourMaps[0]; \ - } \ - else \ - GFX.RealScreenColors = IPPU.ScreenColors; \ - \ - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ - \ - int aa, cc; \ - int startx, StartY = GFX.StartY; \ - \ - int HMosaic = 1, VMosaic = 1, MosaicStart = 0; \ - int32 MLeft = Left, MRight = Right; \ - \ - if (PPU.BGMosaic[0]) \ - { \ - VMosaic = PPU.Mosaic; \ - MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % VMosaic; \ - StartY -= MosaicStart; \ - } \ - \ - if (PPU.BGMosaic[BG]) \ - { \ - HMosaic = PPU.Mosaic; \ - MLeft -= MLeft % HMosaic; \ - MRight += HMosaic - 1; \ - MRight -= MRight % HMosaic; \ - } \ - \ - uint32 Offset = StartY * GFX.PPL; \ - struct SLineMatrixData *l = &LineMatrixData[StartY]; \ - \ - for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) \ - { \ - if (Line + VMosaic > GFX.EndY) \ - VMosaic = GFX.EndY - Line + 1; \ - \ - int yy, starty; \ - \ - int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ - int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ - \ - int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ - int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ - \ - if (PPU.Mode7VFlip) \ - starty = 255 - (int) (Line + 1); \ - else \ - starty = Line + 1; \ - \ - yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ - \ - int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ - int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ - \ - if (PPU.Mode7HFlip) \ - { \ - startx = MRight - 1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = MLeft; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ - \ - int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ - int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ - int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ - \ - uint8 Pix; \ - uint8 ctr = 1; \ - \ - if (!PPU.Mode7Repeat) \ - { \ - for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ - { \ - if (--ctr) \ - continue; \ - ctr = HMosaic; \ - \ - int X = ((AA + BB) >> 8) & 0x3ff; \ - int Y = ((CC + DD) >> 8) & 0x3ff; \ - \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - \ - if ((Pix = (b & MASK))) \ - { \ - for (int32 h = MosaicStart; h < VMosaic; h++) \ - { \ - for (int32 w = x + HMosaic - 1; w >= x; w--) \ - DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ - } \ - } \ - } \ - } \ - else \ - { \ - for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ - { \ - if (--ctr) \ - continue; \ - ctr = HMosaic; \ - \ - int X = ((AA + BB) >> 8); \ - int Y = ((CC + DD) >> 8); \ - \ - uint8 b; \ - \ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - } \ - else \ - if (PPU.Mode7Repeat == 3) \ - b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - else \ - continue; \ - \ - if ((Pix = (b & MASK))) \ - { \ - for (int32 h = MosaicStart; h < VMosaic; h++) \ - { \ - for (int32 w = x + HMosaic - 1; w >= x; w--) \ - DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ - } \ - } \ - } \ - } \ - \ - MosaicStart = 0; \ - } + uint8 *VRAM1 = Memory.VRAM + 1; \ +\ + if(DCMODE) { \ + if(IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[0]; \ + } else { \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + } \ + GFX.ScreenColors = GFX.ClipColors?BlackColourMap:GFX.RealScreenColors; \ +\ + int aa, cc; \ + int startx, StartY=GFX.StartY; \ + int HMosaic=1, VMosaic=1, MosaicStart=0; \ + int32 MLeft=Left, MRight=Right; \ + if(PPU.BGMosaic[0]){ \ + VMosaic=PPU.Mosaic; \ + MosaicStart=((uint32)GFX.StartY-PPU.MosaicStart)%VMosaic; \ + StartY-=MosaicStart; \ + } \ + if(PPU.BGMosaic[BG]){ \ + HMosaic=PPU.Mosaic; \ + MLeft-=MLeft%HMosaic; \ + MRight+=HMosaic-1; MRight-=MRight%HMosaic; \ + } \ +\ + uint32 Offset = StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData[StartY]; \ +\ + for(uint32 Line = StartY; Line <= GFX.EndY; Line+=VMosaic, Offset+=VMosaic*GFX.PPL, l+=VMosaic) { \ + if(Line+VMosaic>GFX.EndY) VMosaic=GFX.EndY-Line+1; \ + int yy, starty; \ +\ + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ +\ + int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ + int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ +\ + if (PPU.Mode7VFlip) { \ + starty = 255 - (int) (Line+1); \ + } else { \ + starty = Line+1; \ + } \ +\ + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ +\ + int BB = ((l->MatrixB*starty)&~63) + ((l->MatrixB*yy)&~63) + (CentreX << 8); \ + int DD = ((l->MatrixD*starty)&~63) + ((l->MatrixD*yy)&~63) + (CentreY << 8); \ +\ + if(PPU.Mode7HFlip) { \ + startx = MRight - 1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } else { \ + startx = MLeft; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ +\ + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA*startx + ((l->MatrixA*xx)&~63); \ + int CC = l->MatrixC*startx + ((l->MatrixC*xx)&~63); \ + uint8 Pix; \ + uint8 ctr=1; \ +\ + if(!PPU.Mode7Repeat) { \ + for(int32 x = MLeft; x> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if((Pix=(b&MASK))){ \ + for(int32 h=MosaicStart; h=x; w--){ \ + DRAW_PIXEL(w+h*GFX.PPL, (w>=(int32)Left && w<(int32)Right)); \ + } \ + } \ + } \ + } \ + } else { \ + for(int32 x = MLeft; x> 8); \ + int Y = ((CC + DD) >> 8); \ +\ + uint8 b; \ + if (((X | Y) & ~0x3ff) == 0) { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } else if(PPU.Mode7Repeat == 3) { \ + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } else { \ + continue; \ + } \ + if((Pix=(b&MASK))){ \ + for(int32 h=MosaicStart; h=x; w--){ \ + DRAW_PIXEL(w+h*GFX.PPL, (w>=(int32)Left && w<(int32)Right)); \ + } \ + } \ + } \ + } \ + } \ + MosaicStart=0; \ + } -#define DRAW_TILE() DRAW_TILE_NORMAL() -#define NAME1 DrawMode7BG1 -#define ARGS uint32 Left, uint32 Right, int D - -// Second-level include: Get the DrawMode7BG1 renderers. +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define NAME1 DrawMode7BG1 +#define ARGS uint32 Left, uint32 Right, int D +// Second-level include: Get the DrawMode7BG1 renderers #include "tile.cpp" #undef NAME1 #undef DRAW_TILE +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG1 -#define DRAW_TILE() DRAW_TILE_MOSAIC() -#define NAME1 DrawMode7MosaicBG1 - -// Second-level include: Get the DrawMode7MosaicBG1 renderers. - +// Second-level include: Get the DrawMode7MosaicBG1 renderers #include "tile.cpp" #undef DRAW_TILE @@ -1299,26 +1127,23 @@ extern struct SLineMatrixData LineMatrixData[240]; #undef DCMODE #undef BG -#define NAME1 DrawMode7BG2 -#define DRAW_TILE() DRAW_TILE_NORMAL() -#define Z1 (D + ((b & 0x80) ? 11 : 3)) -#define Z2 (D + ((b & 0x80) ? 11 : 3)) -#define MASK 0x7f -#define DCMODE 0 -#define BG 1 - -// Second-level include: Get the DrawMode7BG2 renderers. +#define NAME1 DrawMode7BG2 +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define Z1 D+((b&0x80)?11:3) +#define Z2 D+((b&0x80)?11:3) +#define MASK 0x7f +#define DCMODE 0 +#define BG 1 +// Second-level include: Get the DrawMode7BG2 renderers #include "tile.cpp" #undef NAME1 #undef DRAW_TILE +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG2 -#define DRAW_TILE() DRAW_TILE_MOSAIC() -#define NAME1 DrawMode7MosaicBG2 - -// Second-level include: Get the DrawMode7MosaicBG2 renderers. - +// Second-level include: Get the DrawMode7MosaicBG2 renderers #include "tile.cpp" #undef MASK @@ -1333,179 +1158,159 @@ extern struct SLineMatrixData LineMatrixData[240]; #undef Z2 #undef NO_INTERLACE -/*****************************************************************************/ -#else -#ifndef NAME2 // Second-level: Get all the NAME1 renderers. -/*****************************************************************************/ +/*===========================================================================*/ +#else // Second-level: Get all NAME1 renderers +#ifndef NAME2 +/*===========================================================================*/ -#define BPSTART StartLine -#define PITCH 1 +#define BPSTART StartLine +#define PITCH 1 // The 1x1 pixel plotter, for speedhacking modes. - -#define DRAW_PIXEL(N, M) \ - if (Z1 > GFX.DB[Offset + N] && (M)) \ - { \ - GFX.S[Offset + N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + N], GFX.SubZBuffer[Offset + N]); \ - GFX.DB[Offset + N] = Z2; \ - } - -#define NAME2 Normal1x1 - -// Third-level include: Get the Normal1x1 renderers. - +#define DRAW_PIXEL(N,M) \ + if(Z1>GFX.DB[Offset+N] && (M)){ \ + GFX.S[Offset+N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset+N], GFX.SubZBuffer[Offset+N]); \ + GFX.DB[Offset+N] = Z2; \ + } +#define NAME2 Normal1x1 +// Third-level include: get the Normal1x1 renderers #include "tile.cpp" - #undef NAME2 #undef DRAW_PIXEL -// The 2x1 pixel plotter, for normal rendering when we've used hires/interlace already this frame. - -#define DRAW_PIXEL_N2x1(N, M) \ - if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ - { \ - GFX.S[Offset + 2 * N] = GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ - GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ - } - -#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M) -#define NAME2 Normal2x1 - -// Third-level include: Get the Normal2x1 renderers. - +// The 2x1 pixel plotter, for normal rendering when we've used hires/interlace +// already this frame. +#define DRAW_PIXEL_N2x1(N,M) \ + if(Z1>GFX.DB[Offset+2*N] && (M)){ \ + GFX.S[Offset+2*N] = GFX.S[Offset+2*N+1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset+2*N], GFX.SubZBuffer[Offset+2*N]); \ + GFX.DB[Offset+2*N] = GFX.DB[Offset+2*N+1] = Z2; \ + } +#define DRAW_PIXEL(N,M) DRAW_PIXEL_N2x1(N,M) +#define NAME2 Normal2x1 +// Third-level include: get the Normal2x1 renderers #include "tile.cpp" - #undef NAME2 #undef DRAW_PIXEL -// Hires pixel plotter, this combines the main and subscreen pixels as appropriate to render hires or pseudo-hires images. -// Use it only on the main screen, subscreen should use Normal2x1 instead. -// Hires math: -// Main pixel is mathed as normal: Main(x, y) * Sub(x, y). -// Sub pixel is mathed somewhat weird: Basically, for Sub(x + 1, y) we apply the same operation we applied to Main(x, y) -// (e.g. no math, add fixed, add1/2 subscreen) using Main(x, y) as the "corresponding subscreen pixel". -// Also, color window clipping clips Sub(x + 1, y) if Main(x, y) is clipped, not Main(x + 1, y). -// We don't know how Sub(0, y) is handled. - -#define DRAW_PIXEL_H2x1(N, M) \ - if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ - { \ - GFX.S[Offset + 2 * N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ - GFX.S[Offset + 2 * N + 1] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ - GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ - } - -#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) -#define NAME2 Hires - -// Third-level include: Get the Hires renderers. - +// Hires pixel plotter, this combines the main and subscreen pixels as +// appropriate to render hires or pseudo-hires images. Use it only on the main +// screen, subscreen should use Normal2x1 instead. +/* Hires math: + * Main pixel is mathed as normal: Main(x,y)*Sub(x,y) + * Sub pixel is mathed somewhat weird: Basically, for Sub(x+1,y) we apply the + * same operation we applied to Main(x,y) (e.g. no math, add fixed, add1/2 + * subscreen) using Main(x,y) as the "corresponding subscreen pixel". + * Also, color window clipping clips Sub(x+1,y) iff Main(x,y) is clipped, + * not Main(x+1,y). + * We don't know how Sub(0,y) is handled. + */ +#define DRAW_PIXEL_H2x1(N,M) \ + if(Z1>GFX.DB[Offset+2*N] && (M)){ \ + GFX.S[Offset+2*N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset+2*N], GFX.SubZBuffer[Offset+2*N]); \ + GFX.S[Offset+2*N+1] = MATH((GFX.ClipColors?0:GFX.SubScreen[Offset+2*N+2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset+2*N]); \ + GFX.DB[Offset+2*N] = GFX.DB[Offset+2*N+1] = Z2; \ + } +#define DRAW_PIXEL(N,M) DRAW_PIXEL_H2x1(N,M) +#define NAME2 Hires +// Third-level include: get the Hires renderers #include "tile.cpp" - #undef NAME2 #undef DRAW_PIXEL -// Interlace: Only draw every other line, so we'll redefine BPSTART and PITCH to do so. -// Otherwise, it's the same as Normal2x1/Hires2x1. +/* Interlace: Only draw every other line, so we'll redefine BPSTART and PITCH + * to do so. Otherwise, it's the same as Normal2x1/Hires2x1. + */ #undef BPSTART #undef PITCH - -#define BPSTART (StartLine * 2 + BG.InterlaceLine) -#define PITCH 2 +#define BPSTART (StartLine*2+BG.InterlaceLine) +#define PITCH 2 #ifndef NO_INTERLACE -#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M) -#define NAME2 Interlace - -// Third-level include: Get the Interlace renderers. - +#define DRAW_PIXEL(N,M) DRAW_PIXEL_N2x1(N,M) +#define NAME2 Interlace +// Third-level include: get the Interlace renderers #include "tile.cpp" - #undef NAME2 #undef DRAW_PIXEL -#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) -#define NAME2 HiresInterlace - -// Third-level include: Get the HiresInterlace renderers. - +#define DRAW_PIXEL(N,M) DRAW_PIXEL_H2x1(N,M) +#define NAME2 HiresInterlace +// Third-level include: get the HiresInterlace renderers #include "tile.cpp" - #undef NAME2 #undef DRAW_PIXEL -#endif +#endif /* NO_INTERLACE */ #undef BPSTART #undef PITCH -/*****************************************************************************/ -#else // Third-level: Renderers for each math mode for NAME1 + NAME2. -/*****************************************************************************/ +/*===========================================================================*/ +#else // Third-level: Renderers for each math mode for NAME1 + NAME2 +/*===========================================================================*/ -#define CONCAT3(A, B, C) A##B##C -#define MAKENAME(A, B, C) CONCAT3(A, B, C) +#define CONCAT3(A,B,C) A##B##C +#define MAKENAME(A,B,C) CONCAT3(A,B,C) -static void MAKENAME(NAME1, _, NAME2) (ARGS) +static void MAKENAME(NAME1,_,NAME2) (ARGS) { -#define MATH(A, B, C) NOMATH(x, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) NOMATH(x,A,B,C) + DRAW_TILE(); #undef MATH } -static void MAKENAME(NAME1, Add_, NAME2) (ARGS) +static void MAKENAME(NAME1,Add_,NAME2) (ARGS) { -#define MATH(A, B, C) REGMATH(ADD, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) REGMATH(ADD,A,B,C) + DRAW_TILE(); #undef MATH } -static void MAKENAME(NAME1, AddF1_2_, NAME2) (ARGS) +static void MAKENAME(NAME1,AddF1_2_,NAME2) (ARGS) { -#define MATH(A, B, C) MATHF1_2(ADD, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) MATHF1_2(ADD,A,B,C) + DRAW_TILE(); #undef MATH } -static void MAKENAME(NAME1, AddS1_2_, NAME2) (ARGS) +static void MAKENAME(NAME1,AddS1_2_,NAME2) (ARGS) { -#define MATH(A, B, C) MATHS1_2(ADD, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) MATHS1_2(ADD,A,B,C) + DRAW_TILE(); #undef MATH } -static void MAKENAME(NAME1, Sub_, NAME2) (ARGS) +static void MAKENAME(NAME1,Sub_,NAME2) (ARGS) { -#define MATH(A, B, C) REGMATH(SUB, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) REGMATH(SUB,A,B,C) + DRAW_TILE(); #undef MATH } -static void MAKENAME(NAME1, SubF1_2_, NAME2) (ARGS) +static void MAKENAME(NAME1,SubF1_2_,NAME2) (ARGS) { -#define MATH(A, B, C) MATHF1_2(SUB, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) MATHF1_2(SUB,A,B,C) + DRAW_TILE(); #undef MATH } -static void MAKENAME(NAME1, SubS1_2_, NAME2) (ARGS) +static void MAKENAME(NAME1,SubS1_2_,NAME2) (ARGS) { -#define MATH(A, B, C) MATHS1_2(SUB, A, B, C) - DRAW_TILE(); +#define MATH(A,B,C) MATHS1_2(SUB,A,B,C) + DRAW_TILE(); #undef MATH } -static void (*MAKENAME(Renderers_, NAME1, NAME2)[7]) (ARGS) = -{ - MAKENAME(NAME1, _, NAME2), - MAKENAME(NAME1, Add_, NAME2), - MAKENAME(NAME1, AddF1_2_, NAME2), - MAKENAME(NAME1, AddS1_2_, NAME2), - MAKENAME(NAME1, Sub_, NAME2), - MAKENAME(NAME1, SubF1_2_, NAME2), - MAKENAME(NAME1, SubS1_2_, NAME2) +static void (*MAKENAME(Renderers_,NAME1,NAME2)[7])(ARGS)={ + MAKENAME(NAME1,_,NAME2), + MAKENAME(NAME1,Add_,NAME2), + MAKENAME(NAME1,AddF1_2_,NAME2), + MAKENAME(NAME1,AddS1_2_,NAME2), + MAKENAME(NAME1,Sub_,NAME2), + MAKENAME(NAME1,SubF1_2_,NAME2), + MAKENAME(NAME1,SubS1_2_,NAME2) }; #undef MAKENAME diff --git a/source/snes9x/tile.h b/source/snes9x/tile.h index ddd67fc..8b6d20c 100644 --- a/source/snes9x/tile.h +++ b/source/snes9x/tile.h @@ -159,11 +159,12 @@ **********************************************************************************/ + #ifndef _TILE_H_ #define _TILE_H_ -void S9xInitTileRenderer (void); -void S9xSelectTileRenderers (int, bool8, bool8); -void S9xSelectTileConverter (int, bool8, bool8, bool8); +void S9xInitTileRenderer(void); +void S9xSelectTileRenderers(int BGMode, bool8 sub, bool8 obj); +void S9xSelectTileConverter(int depth, bool8 hires, bool8 sub, bool8 mosaic); #endif