From e7d0b3df787abc96a6a6b5feafd3dbdde3db31af Mon Sep 17 00:00:00 2001 From: dborth Date: Wed, 25 Nov 2009 06:35:14 +0000 Subject: [PATCH] initial port of snes9x 1.52 beta --- Makefile.gc | 11 +- Makefile.wii | 9 +- source/ngc/audio.cpp | 19 +- source/ngc/cheatmgr.cpp | 4 +- source/ngc/cheatmgr.h | 14 - source/ngc/filebrowser.cpp | 72 +- source/ngc/freeze.cpp | 307 +- source/ngc/freeze.h | 28 +- source/ngc/menu.cpp | 22 +- source/ngc/patch.cpp | 3 +- source/ngc/patch.h | 18 - source/ngc/s9xconfig.cpp | 23 +- source/ngc/s9xsupport.cpp | 161 +- source/ngc/snes9xGX.cpp | 32 +- source/ngc/sram.cpp | 93 +- source/snes9x/65c816.h | 160 +- source/snes9x/apu.cpp | 1054 ---- source/snes9x/apu.h | 297 - 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/apu.h | 201 + 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/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 | 708 ++- source/snes9x/cheats.h | 121 +- source/snes9x/cheats2.cpp | 321 +- source/snes9x/clip.cpp | 378 +- source/snes9x/controls.cpp | 5761 ++++++++++++-------- source/snes9x/controls.h | 467 +- source/snes9x/copyright.h | 233 - source/snes9x/cpu.cpp | 352 +- source/snes9x/cpuaddr.h | 675 ++- source/snes9x/cpuexec.cpp | 124 +- source/snes9x/cpuexec.h | 152 +- source/snes9x/cpumacro.h | 1218 +++-- source/snes9x/cpuops.cpp | 5624 ++++++++++--------- 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 | 1708 +++--- source/snes9x/dma.h | 36 +- source/snes9x/{3d.h => dsp.cpp} | 92 +- source/snes9x/dsp.h | 602 ++ source/snes9x/dsp1.cpp | 2490 ++++++--- source/snes9x/dsp1emu.c.inc | 1394 ----- source/snes9x/{dsp2emu.c.inc => dsp2.cpp} | 442 +- source/snes9x/{dsp3emu.c.inc => dsp3.cpp} | 1110 ++-- source/snes9x/dsp4.cpp | 2204 ++++++++ source/snes9x/dsp4emu.c.inc | 2396 -------- source/snes9x/font.h | 281 +- source/snes9x/fxdbg.cpp | 1522 +++++- source/snes9x/fxemu.cpp | 1285 +++-- source/snes9x/fxemu.h | 98 +- source/snes9x/fxinst.cpp | 5714 +++++++++++++------ source/snes9x/fxinst.h | 542 +- source/snes9x/getset.h | 1335 +++-- source/snes9x/gfx.cpp | 3645 +++++++------ source/snes9x/gfx.h | 322 +- source/snes9x/globals.cpp | 407 +- source/snes9x/language.h | 46 +- source/snes9x/{spc700.h => logger.cpp} | 144 +- source/snes9x/{s9xdebug.h => logger.h} | 29 +- source/snes9x/memmap.cpp | 2661 +++++---- 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 | 338 +- source/snes9x/ppu.cpp | 4199 ++++++-------- source/snes9x/ppu.h | 1028 ++-- source/snes9x/reader.cpp | 337 ++ source/snes9x/{dsp1.h => reader.h} | 88 +- source/snes9x/s9xdebug.cpp | 2307 -------- source/snes9x/sa1.cpp | 1680 +++--- source/snes9x/sa1.h | 245 +- source/snes9x/sa1cpu.cpp | 207 +- source/snes9x/sar.h | 47 +- source/snes9x/{apumem.h => screenshot.cpp} | 263 +- 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 | 757 +-- source/snes9x/seta011.cpp | 143 +- source/snes9x/seta018.cpp | 187 +- source/snes9x/snapshot.cpp | 4230 +++++++------- source/snes9x/snapshot.h | 37 +- source/snes9x/snes9x.cpp | 1264 ----- source/snes9x/snes9x.h | 479 +- source/snes9x/soundux.cpp | 2442 --------- source/snes9x/soundux.h | 352 -- source/snes9x/spc700.cpp | 2650 --------- 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 +- 132 files changed, 46222 insertions(+), 46668 deletions(-) delete mode 100644 source/ngc/cheatmgr.h delete mode 100644 source/ngc/patch.h delete mode 100644 source/snes9x/apu.cpp delete mode 100644 source/snes9x/apu.h create mode 100644 source/snes9x/apu/SNES_SPC.cpp create mode 100644 source/snes9x/apu/SNES_SPC.h create mode 100644 source/snes9x/apu/SNES_SPC_misc.cpp create mode 100644 source/snes9x/apu/SNES_SPC_state.cpp create mode 100644 source/snes9x/apu/SPC_CPU.h create mode 100644 source/snes9x/apu/SPC_DSP.cpp create mode 100644 source/snes9x/apu/SPC_DSP.h create mode 100644 source/snes9x/apu/SPC_Filter.cpp create mode 100644 source/snes9x/apu/SPC_Filter.h create mode 100644 source/snes9x/apu/apu.cpp create mode 100644 source/snes9x/apu/apu.h create mode 100644 source/snes9x/apu/blargg_common.h create mode 100644 source/snes9x/apu/blargg_config.h create mode 100644 source/snes9x/apu/blargg_endian.h create mode 100644 source/snes9x/apu/blargg_source.h create mode 100644 source/snes9x/apu/license.txt create mode 100644 source/snes9x/apu/resampler.h create mode 100644 source/snes9x/apu/ring_buffer.h delete mode 100644 source/snes9x/apudebug.cpp delete mode 100644 source/snes9x/copyright.h delete mode 100644 source/snes9x/data.cpp rename source/snes9x/{3d.h => dsp.cpp} (83%) create mode 100644 source/snes9x/dsp.h delete mode 100644 source/snes9x/dsp1emu.c.inc rename source/snes9x/{dsp2emu.c.inc => dsp2.cpp} (57%) rename source/snes9x/{dsp3emu.c.inc => dsp3.cpp} (52%) create mode 100644 source/snes9x/dsp4.cpp delete mode 100644 source/snes9x/dsp4emu.c.inc rename source/snes9x/{spc700.h => logger.cpp} (74%) rename source/snes9x/{s9xdebug.h => logger.h} (92%) create mode 100644 source/snes9x/movie.cpp create mode 100644 source/snes9x/movie.h create mode 100644 source/snes9x/reader.cpp rename source/snes9x/{dsp1.h => reader.h} (84%) delete mode 100644 source/snes9x/s9xdebug.cpp rename source/snes9x/{apumem.h => screenshot.cpp} (66%) delete mode 100644 source/snes9x/snes9x.cpp delete mode 100644 source/snes9x/soundux.cpp delete mode 100644 source/snes9x/soundux.h delete mode 100644 source/snes9x/spc700.cpp create mode 100644 source/snes9x/spc7110dec.cpp create mode 100644 source/snes9x/spc7110dec.h create mode 100644 source/snes9x/spc7110emu.cpp create mode 100644 source/snes9x/spc7110emu.h create mode 100644 source/snes9x/srtcemu.cpp create mode 100644 source/snes9x/srtcemu.h diff --git a/Makefile.gc b/Makefile.gc index 580f199..b8e3a9b 100644 --- a/Makefile.gc +++ b/Makefile.gc @@ -19,19 +19,16 @@ 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/sz + source/ngc/gui source/ngc source/snes9x source/snes9x/apu \ + source/sz INCLUDES := source/snes9x source/ngc #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -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 \ +CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) -DNO_SOUND \ + -DZLIB -DRIGHTSHIFT_IS_SAR -DCPU_SHUTDOWN -DCORRECT_VRAM_READS \ -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 a32dd37..90cdd95 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -19,7 +19,8 @@ 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/sz source/unzip + source/ngc/gui source/ngc source/snes9x source/snes9x/apu \ + source/sz source/unzip INCLUDES := source/snes9x source/ngc source/unzip #--------------------------------------------------------------------------------- @@ -27,11 +28,7 @@ INCLUDES := source/snes9x source/ngc source/unzip #--------------------------------------------------------------------------------- CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ - -DNGC \ - -DNO_ASM -DRIGHTSHIFT_IS_SAR \ - -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ - -DSPC700_C -DSDD1_DECOMP \ - -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ + -DZLIB -DRIGHTSHIFT_IS_SAR -DCPU_SHUTDOWN -DCORRECT_VRAM_READS \ -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 dc95f37..788b7cd 100644 --- a/source/ngc/audio.cpp +++ b/source/ngc/audio.cpp @@ -18,14 +18,11 @@ #include "snes9x.h" #include "memmap.h" -#include "s9xdebug.h" #include "cpuexec.h" #include "ppu.h" -#include "apu.h" +#include "apu/apu.h" #include "display.h" #include "gfx.h" -#include "soundux.h" -#include "spc700.h" #include "spc7110.h" #include "controls.h" @@ -42,6 +39,7 @@ 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 @@ -58,8 +56,9 @@ AudioThread (void *arg) memset (soundbuffer[whichab], 0, AUDIOBUFFER); else { - so.samples_mixed_so_far = so.play_position = 0; + LWP_MutexLock(audiomutex); S9xMixSamples (soundbuffer[whichab], AUDIOBUFFER >> 1); + LWP_MutexUnlock(audiomutex); } LWP_ThreadSleep (audioqueue); } @@ -85,6 +84,13 @@ GCMixSamples () } } +static void FinalizeSamplesCallback (void *data) +{ + LWP_MutexLock(audiomutex); + S9xFinalizeSamples(); + LWP_MutexUnlock(audiomutex); +} + /**************************************************************************** * InitAudio ***************************************************************************/ @@ -98,6 +104,7 @@ InitAudio () #else ASND_Init(); #endif + LWP_MutexInit(&audiomutex, false); LWP_CreateThread (&athread, AudioThread, NULL, astack, AUDIOSTACK, 70); } @@ -117,9 +124,11 @@ 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/cheatmgr.cpp b/source/ngc/cheatmgr.cpp index 1877956..7ec5d25 100644 --- a/source/ngc/cheatmgr.cpp +++ b/source/ngc/cheatmgr.cpp @@ -8,7 +8,7 @@ * Cheat handling ***************************************************************************/ -#include "memmap.h" +#include "port.h" #include "cheats.h" #include "snes9xGX.h" @@ -58,7 +58,7 @@ static bool NGCLoadCheatFile (int length) * Called when a ROM is first loaded ***************************************************************************/ void -SetupCheats() +WiiSetupCheats() { char filepath[1024]; int offset = 0; diff --git a/source/ngc/cheatmgr.h b/source/ngc/cheatmgr.h deleted file mode 100644 index dae6791..0000000 --- a/source/ngc/cheatmgr.h +++ /dev/null @@ -1,14 +0,0 @@ -/**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port - * - * Tantric August 2008 - * - * cheatmgr.h - * - * Cheat handling - ***************************************************************************/ -#include "cheats.h" - -void SetupCheats(); - -extern SCheatData Cheat; diff --git a/source/ngc/filebrowser.cpp b/source/ngc/filebrowser.cpp index 584c500..6c90c0a 100644 --- a/source/ngc/filebrowser.cpp +++ b/source/ngc/filebrowser.cpp @@ -26,6 +26,7 @@ #include "snes9x.h" #include "memmap.h" +#include "cheats.h" #include "filebrowser.h" #include "snes9xGX.h" @@ -37,8 +38,6 @@ #include "memcardop.h" #include "input.h" #include "gcunzip.h" -#include "cheatmgr.h" -#include "patch.h" #include "freeze.h" #include "sram.h" @@ -490,6 +489,39 @@ 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 * @@ -497,11 +529,9 @@ int BrowserLoadSz() ***************************************************************************/ int BrowserLoadFile() { - char filepath[1024]; int loaded = 0; - int device; - + if(!FindDevice(browser.dir, &device)) return 0; @@ -514,24 +544,7 @@ int BrowserLoadFile() SNESROMSize = 0; S9xDeleteCheats(); - - 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(); - } - } + Memory.LoadROM("ROM"); if (SNESROMSize <= 0) { @@ -539,22 +552,11 @@ int BrowserLoadFile() } else { - // load UPS/IPS/PPF patch - LoadPatch(); - - Memory.LoadROM ("BLANK.SMC"); - Memory.LoadSRAM ("BLANK"); - // load SRAM or snapshot if (GCSettings.AutoLoad == 1) LoadSRAMAuto(SILENT); else if (GCSettings.AutoLoad == 2) - NGCUnfreezeGameAuto(SILENT); - - // setup cheats - if(GCSettings.SaveMethod != DEVICE_MC_SLOTA && - GCSettings.SaveMethod != DEVICE_MC_SLOTB) - SetupCheats(); + LoadSnapshotAuto(SILENT); ResetBrowser(); loaded = 1; diff --git a/source/ngc/freeze.cpp b/source/ngc/freeze.cpp index 07d9dcc..62463d8 100644 --- a/source/ngc/freeze.cpp +++ b/source/ngc/freeze.cpp @@ -7,127 +7,42 @@ * 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 "pngu.h" #include "snes9x.h" +#include "port.h" #include "memmap.h" -#include "soundux.h" #include "snapshot.h" -#include "srtc.h" #include "snes9xGX.h" -#include "memcardop.h" -#include "freeze.h" #include "fileop.h" #include "filebrowser.h" #include "menu.h" #include "video.h" +#include "pngu.h" -extern void S9xSRTCPreSaveState (); -extern void NGCFreezeStruct (); -extern bool8 S9xUnfreezeGame (const char *filename); +bool8 S9xOpenSnapshotFile(const char *filepath, bool8 readonly, STREAM *file) +{ + return FALSE; +} -static int bufoffset; +void S9xCloseSnapshotFile(STREAM s) +{ + +} /**************************************************************************** - * GetMem - * - * Return x bytes from memory buffer + * SaveSnapshot ***************************************************************************/ + int -GetMem (char *buffer, int len) +SaveSnapshot (char * filepath, bool silent) { - memcpy (buffer, savebuffer + bufoffset, len); - bufoffset += len; - - return len; -} - -/**************************************************************************** - * 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; -} - - -/**************************************************************************** - * NGCFreezeGame - * - * Do freeze game for Nintendo Gamecube - ***************************************************************************/ -int -NGCFreezeGame (char * filepath, bool silent) -{ - int offset = 0; // bytes written (actual) - int woffset = 0; // bytes written (expected) int imgSize = 0; // image screenshot bytes written - char msg[100]; int device; if(!FindDevice(filepath, &device)) @@ -158,191 +73,85 @@ NGCFreezeGame (char * filepath, bool silent) FreeSaveBuffer (); } - S9xSetSoundMute (TRUE); - S9xPrepareSoundForSnapshotSave (FALSE); - - AllocSaveBuffer (); - // copy freeze mem into savebuffer - bufoffset contains # bytes written - NGCFreezeMemBuffer (); - woffset = bufoffset; - - S9xPrepareSoundForSnapshotSave (TRUE); - S9xSetSoundMute (FALSE); - - if(device == DEVICE_MC_SLOTA || device == DEVICE_MC_SLOTB) // MC Slot A or B - { - // set freezecomment - char freezecomment[2][32]; - memset(freezecomment, 0, 64); - sprintf (freezecomment[0], "%s Snapshot", APPNAME); - sprintf (freezecomment[1], Memory.ROMName); - SetMCSaveComments(freezecomment); - - char * zipbuffer = (char *)memalign(32, SAVEBUFFERSIZE); - - // Zip and copy in the freeze - uLongf DestBuffSize = (uLongf) SAVEBUFFERSIZE; - int err = compress2((Bytef*)(zipbuffer), (uLongf*)&DestBuffSize, (const Bytef*)savebuffer, (uLongf)bufoffset, Z_BEST_COMPRESSION); - - if(err!=Z_OK) - { - sprintf (msg, "Zip error %s",zError(err)); - ErrorPrompt(msg); - goto done; - } - - int zippedsize = (int)DestBuffSize; - int decompressedsize = (int)bufoffset; - memset(savebuffer, 0, SAVEBUFFERSIZE); - memcpy(savebuffer, &zippedsize, 4); - memcpy(savebuffer+4, &decompressedsize, 4); - memcpy(savebuffer+8, zipbuffer, DestBuffSize); - free(zipbuffer); - - woffset = zippedsize + 8; - } - - offset = SaveFile(filepath, woffset, silent); - -done: - - FreeSaveBuffer (); - - if(offset > 0) // save successful! + STREAM fp = OPEN_STREAM(filepath, "wb"); + + if(!fp) { if(!silent) - InfoPrompt("Save successful"); - return 1; + ErrorPrompt("Save failed!"); + return 0; } - return 0; + + S9xFreezeToStream(fp); + CLOSE_STREAM(fp); + + if(!silent) + InfoPrompt("Save successful"); + return 1; } int -NGCFreezeGameAuto (bool silent) +SaveSnapshotAuto (bool silent) { char filepath[1024]; if(!MakeFilePath(filepath, FILE_SNAPSHOT, Memory.ROMFilename, 0)) return false; - return NGCFreezeGame(filepath, silent); + return SaveSnapshot(filepath, silent); } /**************************************************************************** - * NGCUnFreezeBlock + * LoadSnapshot ***************************************************************************/ int -NGCUnFreezeBlock (char *name, uint8 * block, int size) +LoadSnapshot (char * filepath, bool silent) { - 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; -} - -/**************************************************************************** - * NGCUnfreezeGame - ***************************************************************************/ -int -NGCUnfreezeGame (char * filepath, bool silent) -{ - int offset = 0; - int result = 0; - char msg[80]; - bufoffset = 0; int device; if(!FindDevice(filepath, &device)) return 0; - - AllocSaveBuffer(); - offset = LoadFile(filepath, silent); + STREAM fp = OPEN_STREAM(filepath, "rb"); - if(device == DEVICE_MC_SLOTA || device == DEVICE_MC_SLOTB) // MC in slot A or slot B - { - if (offset) - { - char * zipbuffer = (char *)memalign(32, SAVEBUFFERSIZE); - memset (zipbuffer, 0, SAVEBUFFERSIZE); - uLongf zipsize = 0; - uLongf decompressedsize = 0; - uLongf DestBuffSize = SAVEBUFFERSIZE; - memcpy (&zipsize, savebuffer, 4); - memcpy (&decompressedsize, savebuffer+4, 4); - - int err= uncompress((Bytef*)zipbuffer, (uLongf*)&DestBuffSize, (const Bytef*)(savebuffer+8), zipsize); - - if ( err!=Z_OK ) - { - offset = 0; - sprintf (msg, "Unzip error %s",zError(err)); - ErrorPrompt(msg); - } - else if ( DestBuffSize != decompressedsize ) - { - offset = 0; - ErrorPrompt("Unzipped size doesn't match expected size!"); - } - else - { - offset = decompressedsize; - memset(savebuffer, 0, SAVEBUFFERSIZE); - memcpy (savebuffer, zipbuffer, decompressedsize); - } - free(zipbuffer); - } - } - - if(offset > 0) - { - if (S9xUnfreezeGame ("AGAME") == SUCCESS) - result = 1; - else - ErrorPrompt("Error thawing"); - } - else + if(!fp) { if(!silent) - ErrorPrompt("Freeze file not found"); + ErrorPrompt("Unable to open snapshot!"); + return 0; } - FreeSaveBuffer(); - return result; + + 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; } int -NGCUnfreezeGameAuto (bool silent) +LoadSnapshotAuto (bool silent) { char filepath[1024]; if(!MakeFilePath(filepath, FILE_SNAPSHOT, Memory.ROMFilename, 0)) return false; - return NGCUnfreezeGame(filepath, silent); + return LoadSnapshot(filepath, silent); } diff --git a/source/ngc/freeze.h b/source/ngc/freeze.h index c6b476f..55cf43d 100644 --- a/source/ngc/freeze.h +++ b/source/ngc/freeze.h @@ -7,30 +7,14 @@ * 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 _NGCMEMFILE_ -#define _NGCMEMFILE_ +#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 NGCFreezeGame (char * filepath, bool silent); -int NGCFreezeGameAuto (bool silent); -int NGCUnfreezeGame (char * filepath, bool silent); -int NGCUnfreezeGameAuto (bool silent); +int SaveSnapshot (char * filepath, bool silent); +int SaveSnapshotAuto (bool silent); +int LoadSnapshot (char * filepath, bool silent); +int LoadSnapshotAuto (bool silent); #endif diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 71c31b2..5483646 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -22,16 +22,6 @@ #include "snes9x.h" #include "memmap.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 "cheats.h" #include "snes9xGX.h" @@ -46,9 +36,7 @@ #include "freeze.h" #include "preferences.h" #include "button_mapping.h" -#include "cheatmgr.h" #include "input.h" -#include "patch.h" #include "filter.h" #include "filelist.h" #include "gui/gui.h" @@ -567,14 +555,14 @@ void AutoSave() else if (GCSettings.AutoSave == 2) { if (WindowPrompt("Save", "Save Snapshot?", "Save", "Don't Save") ) - NGCFreezeGameAuto(NOTSILENT); + SaveSnapshotAuto(NOTSILENT); } else if (GCSettings.AutoSave == 3) { if (WindowPrompt("Save", "Save SRAM and Snapshot?", "Save", "Don't Save") ) { SaveSRAMAuto(NOTSILENT); - NGCFreezeGameAuto(NOTSILENT); + SaveSnapshotAuto(NOTSILENT); } } } @@ -1712,7 +1700,7 @@ static int MenuGameSaves(int action) result = LoadSRAM(filepath, NOTSILENT); break; case FILE_SNAPSHOT: - result = NGCUnfreezeGame (filepath, NOTSILENT); + result = LoadSnapshot (filepath, NOTSILENT); break; } if(result) @@ -1742,7 +1730,7 @@ static int MenuGameSaves(int action) if(i < 100) { MakeFilePath(filepath, FILE_SNAPSHOT, Memory.ROMFilename, i); - NGCFreezeGame (filepath, NOTSILENT); + SaveSnapshot (filepath, NOTSILENT); menu = MENU_GAME_SAVE; } } @@ -1755,7 +1743,7 @@ static int MenuGameSaves(int action) SaveSRAM(filepath, NOTSILENT); break; case FILE_SNAPSHOT: - NGCFreezeGame (filepath, NOTSILENT); + SaveSnapshot (filepath, NOTSILENT); break; } menu = MENU_GAME_SAVE; diff --git a/source/ngc/patch.cpp b/source/ngc/patch.cpp index 8cc0183..2901d86 100644 --- a/source/ngc/patch.cpp +++ b/source/ngc/patch.cpp @@ -10,6 +10,7 @@ #include +#include "snes9x.h" #include "memmap.h" #include "snes9xGX.h" @@ -406,7 +407,7 @@ bool patchApplyPPF(MFILE *f, u8 **rom, int *size) return res; } -void LoadPatch() +void WiiLoadPatch() { int patchsize = 0; int patchtype; diff --git a/source/ngc/patch.h b/source/ngc/patch.h deleted file mode 100644 index 2d0c97b..0000000 --- a/source/ngc/patch.h +++ /dev/null @@ -1,18 +0,0 @@ -/**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port - * - * Tantric October 2008 - * - * patch.h - * - * IPS/UPS/PPF patch support - ***************************************************************************/ - -#ifndef PATCH_H -#define PATCH_H - -#include "memfile.h" - -void LoadPatch(); - -#endif diff --git a/source/ngc/s9xconfig.cpp b/source/ngc/s9xconfig.cpp index f4e33dc..96f8fa3 100644 --- a/source/ngc/s9xconfig.cpp +++ b/source/ngc/s9xconfig.cpp @@ -105,28 +105,21 @@ 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.ApplyCheats = true; - - Settings.BlockInvalidVRAMAccess = false; + Settings.BlockInvalidVRAMAccessMaster = false; Settings.HDMATimingHack = 100; + Settings.ApplyCheats = true; + Settings.DontSaveOopsSnapshot = true; - // Sound defaults. On GC this is 32Khz/16bit/Stereo/InterpolatedSound - Settings.APUEnabled = true; - Settings.NextAPUEnabled = true; + // Sound 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 @@ -142,22 +135,14 @@ 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 f675c1a..6bdc9f7 100644 --- a/source/ngc/s9xsupport.cpp +++ b/source/ngc/s9xsupport.cpp @@ -8,8 +8,7 @@ * * s9xsupport.cpp * - * This file contains the supporting functions defined in porting.html, with - * others taken from unix/x11.cpp and unix/unix.cpp + * Snes9x support functions ***************************************************************************/ #include @@ -22,15 +21,8 @@ #include "snes9x.h" #include "memmap.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 "apu/apu.h" #include "controls.h" #include "snes9xGX.h" @@ -41,6 +33,11 @@ static long long prev; static long long now; /*** Miscellaneous Functions ***/ +void S9xExit() +{ + ExitApp(); +} + void S9xMessage(int /*type */, int /*number */, const char *message) { #define MAX_MESSAGE_LEN (36 * 3) @@ -51,43 +48,6 @@ void S9xMessage(int /*type */, int /*number */, const char *message) S9xSetInfoString(buffer); } -void S9xExit() -{ - ExitApp(); -} - -/*** File based functions ***/ -const char * -S9xChooseFilename(bool8 read_only) -{ - return NULL; -} - -const char * -S9xChooseMovieFilename(bool8 read_only) -{ - return NULL; -} - -const char * -S9xGetDirectory(enum s9x_getdirtype dirtype) -{ - return NULL; -} - -const char * -S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype) -{ - return NULL; -} - -const char * -S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype) -{ - return NULL; -} - -/*** Memory based functions ***/ void S9xAutoSaveSRAM() { @@ -96,37 +56,27 @@ void S9xAutoSaveSRAM() /*** Sound based functions ***/ void S9xToggleSoundChannel(int c) { - if (c == 8) - so.sound_switch = 255; - else - so.sound_switch ^= 1 << c; - S9xSetSoundControl(so.sound_switch); + static int sound_switch = 255; + + if (c == 8) + sound_switch = 255; + else + sound_switch ^= 1 << c; + + S9xSetSoundControl (sound_switch); } /**************************************************************************** * OpenSoundDevice * - * Main initialisation for NGC sound system + * Main initialisation for Wii sound system ***************************************************************************/ -bool8 S9xOpenSoundDevice(int mode, bool8 stereo, int buffer_size) +bool8 S9xOpenSoundDevice(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() { @@ -246,41 +196,72 @@ 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. ***************************************************************************/ -/*** splitpath function ***/ -void _splitpath(char const *buffer, char *drive, char *dir, char *fname, - char *ext) +const char *S9xChooseFilename(bool8 read_only) { - return; // Do nothing - NGC code should NEVER call a function which relies on it + ExitApp(); + return NULL; +} + +const char * S9xChooseMovieFilename(bool8 read_only) +{ + ExitApp(); + return NULL; +} + +const char * S9xGetDirectory(enum s9x_getdirtype dirtype) +{ + ExitApp(); + return NULL; +} + +const char * S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype) +{ + ExitApp(); + return NULL; +} + +const char * S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype) +{ + ExitApp(); + return NULL; +} + +const char * S9xBasename(const 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(); } void _makepath(char *filename, const char *drive, const char *dir, const char *fname, const char *ext) { - return; // Do nothing - NGC code should NEVER call a function which relies on it + ExitApp(); } -char * -S9xBasename(char *name) +int dup(int fildes) { - return name; + 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 7e6a826..3e3203c 100644 --- a/source/ngc/snes9xGX.cpp +++ b/source/ngc/snes9xGX.cpp @@ -31,15 +31,7 @@ #include "snes9x.h" #include "memmap.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 "apu/apu.h" #include "controls.h" #include "snes9xGX.h" @@ -343,24 +335,10 @@ void USBGeckoOutput() devoptab_list[STD_ERR] = &gecko_out; } -/**************************************************************************** - * MAIN - * - * Steps to Snes9x Emulation : - * 1. Initialise GC Video - * 2. Initialise libfreetype (Nice to read something) - * 3. Set S9xSettings to standard defaults (s9xconfig.h) - * 4. Allocate Snes9x Memory - * 5. Allocate APU Memory - * 6. Set Pixel format to RGB565 for GL Rendering - * 7. Initialise Snes9x/GC Sound System - * 8. Initialise Snes9x Graphics subsystem - * 9. Let's Party! - ***************************************************************************/ 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 @@ -432,6 +410,7 @@ main(int argc, char *argv[]) S9xUnmapAllControls (); SetDefaultButtonMap (); + S9xReportControllers(); // Allocate SNES Memory if (!Memory.Init ()) @@ -444,15 +423,14 @@ main(int argc, char *argv[]) // Set Pixel Renderer to match 565 S9xSetRenderPixelFormat (RGB565); - // Initialise Snes Sound System - S9xInitSound (5, TRUE, 1024); + // Initialise Sound System + S9xInitSound (512, 0); // Initialise Graphics setGFX (); if (!S9xGraphicsInit ()) ExitApp(); - S9xSetSoundMute (TRUE); S9xInitSync(); // initialize frame sync // Initialize font system diff --git a/source/ngc/sram.cpp b/source/ngc/sram.cpp index cda4050..4375ad0 100644 --- a/source/ngc/sram.cpp +++ b/source/ngc/sram.cpp @@ -32,55 +32,47 @@ bool LoadSRAM (char * filepath, bool silent) { - int offset = 0; + int len = 0; int device; - + bool result = false; + if(!FindDevice(filepath, &device)) return 0; - AllocSaveBuffer(); + Memory.ClearSRAM(); - offset = LoadFile(filepath, silent); + int size = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (offset > 0) + if (size > 0x20000) + size = 0x20000; + + if (size) { - int size = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; + len = LoadFile((char *)Memory.SRAM, filepath, size, silent); - if (size > 0x20000) - size = 0x20000; - - if (device == DEVICE_MC_SLOTA || device == DEVICE_MC_SLOTB || - offset == size + 512 || offset == size + 512 + SRTC_SRAM_PAD) + if (len > 0) { - // SRAM has a 512 byte header - remove it, then import the SRAM, - // ignoring anything after the SRAM - memcpy(Memory.SRAM, savebuffer+512, size); - } - else if (offset == size || offset == size + SRTC_SRAM_PAD) - { - // SRAM data should be at the start of the file, just import it and - // ignore anything after the SRAM - memcpy (Memory.SRAM, savebuffer, size); - } - else - { - ErrorPrompt("Incompatible SRAM save!"); - } + if (len - size == 512) + memmove(Memory.SRAM, Memory.SRAM + 512, size); - S9xSoftReset(); - FreeSaveBuffer (); - return true; - } - else - { - FreeSaveBuffer (); - - // if we reached here, nothing was done! - if(!silent) + 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) + { + // if we reached here, nothing was done! ErrorPrompt("SRAM file not found"); - - return false; + } + S9xSoftReset(); } + return result; } bool @@ -122,6 +114,12 @@ SaveSRAM (char * filepath, bool silent) if(!FindDevice(filepath, &device)) return 0; + if (Settings.SuperFX && Memory.ROMType < 0x15) // doesn't have SRAM + return true; + + if (Settings.SA1 && Memory.ROMType == 0x34) // doesn't have SRAM + return true; + // determine SRAM size int size = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; @@ -130,22 +128,17 @@ SaveSRAM (char * filepath, bool silent) if (size > 0) { - if(device == DEVICE_MC_SLOTA || device == DEVICE_MC_SLOTB) + offset = SaveFile((char *)Memory.SRAM, filepath, size, silent); + + if (Settings.SRTC || Settings.SPC7110RTC) { - // Set the sramcomments - char sramcomment[2][32]; - memset(sramcomment, 0, 64); - sprintf (sramcomment[0], "%s SRAM", APPNAME); - sprintf (sramcomment[1], Memory.ROMName); - SetMCSaveComments(sramcomment); + int pathlen = strlen(filepath); + filepath[pathlen-3] = 'r'; + filepath[pathlen-2] = 't'; + filepath[pathlen-1] = 'c'; + SaveFile((char *)RTCData.reg, filepath, 20, silent); } - AllocSaveBuffer (); - // copy in the SRAM, leaving a 512 byte header (for compatibility with other platforms) - memcpy(savebuffer+512, Memory.SRAM, size); - offset = SaveFile(filepath, size+512, silent); - FreeSaveBuffer (); - if (offset > 0) { if (!silent) diff --git a/source/snes9x/65c816.h b/source/snes9x/65c816.h index bee73da..75bc917 100644 --- a/source/snes9x/65c816.h +++ b/source/snes9x/65c816.h @@ -159,104 +159,102 @@ **********************************************************************************/ +#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 -#ifndef _65c816_h_ -#define _65c816_h_ +#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) -#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 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 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)) +#define SetFlags(f) (Registers.P.W |= (f)) +#define ClearFlags(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 PBPC PC.xPBPC -#define PCw PC.W.xPC -#define PCh PC.B.xPCh -#define PCl PC.B.xPCl -#define PB PC.B.xPB +#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 -EXTERN_C struct SRegisters Registers; +extern struct SRegisters Registers; #endif - diff --git a/source/snes9x/apu.cpp b/source/snes9x/apu.cpp deleted file mode 100644 index eab62d7..0000000 --- a/source/snes9x/apu.cpp +++ /dev/null @@ -1,1054 +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 -#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.h b/source/snes9x/apu.h deleted file mode 100644 index 4a368bb..0000000 --- a/source/snes9x/apu.h +++ /dev/null @@ -1,297 +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 _apu_h_ -#define _apu_h_ - -#include "spc700.h" - -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); -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); -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 - - -#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 - -#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 new file mode 100644 index 0000000..fb3b147 --- /dev/null +++ b/source/snes9x/apu/SNES_SPC.cpp @@ -0,0 +1,564 @@ +// 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 new file mode 100644 index 0000000..74bfe0b --- /dev/null +++ b/source/snes9x/apu/SNES_SPC.h @@ -0,0 +1,287 @@ +// 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 new file mode 100644 index 0000000..5a313a0 --- /dev/null +++ b/source/snes9x/apu/SNES_SPC_misc.cpp @@ -0,0 +1,407 @@ +// 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 new file mode 100644 index 0000000..3d9d3f3 --- /dev/null +++ b/source/snes9x/apu/SNES_SPC_state.cpp @@ -0,0 +1,142 @@ +// 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 new file mode 100644 index 0000000..664fc48 --- /dev/null +++ b/source/snes9x/apu/SPC_CPU.h @@ -0,0 +1,1220 @@ +// 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 new file mode 100644 index 0000000..05eca32 --- /dev/null +++ b/source/snes9x/apu/SPC_DSP.cpp @@ -0,0 +1,1062 @@ +// 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 new file mode 100644 index 0000000..6705a49 --- /dev/null +++ b/source/snes9x/apu/SPC_DSP.h @@ -0,0 +1,317 @@ +// 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 new file mode 100644 index 0000000..b3d5770 --- /dev/null +++ b/source/snes9x/apu/SPC_Filter.cpp @@ -0,0 +1,68 @@ +// 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 new file mode 100644 index 0000000..d5c83cb --- /dev/null +++ b/source/snes9x/apu/SPC_Filter.h @@ -0,0 +1,47 @@ +// 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 new file mode 100644 index 0000000..0529ff3 --- /dev/null +++ b/source/snes9x/apu/apu.cpp @@ -0,0 +1,633 @@ +/********************************************************************************** + 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/apu.h b/source/snes9x/apu/apu.h new file mode 100644 index 0000000..cdd5931 --- /dev/null +++ b/source/snes9x/apu/apu.h @@ -0,0 +1,201 @@ +/********************************************************************************** + 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 _APU_H_ +#define _APU_H_ + +#include "snes9x.h" +#include "SNES_SPC.h" + +typedef void (*apu_callback) (void *); + +#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8) + +bool8 S9xInitAPU (void); +void S9xDeinitAPU (void); +void S9xResetAPU (void); +void S9xSoftResetAPU (void); +uint8 S9xAPUReadPort (int); +void S9xAPUWritePort (int, uint8); +void S9xAPUExecute (void); +void S9xAPUEndScanline (void); +void S9xAPUSetReferenceTime (int32); +void S9xAPUTimingSetSpeedup (int); +void S9xAPULoadState (uint8 *); +void S9xAPUSaveState (uint8 *); +void S9xDumpSPCSnapshot (void); + +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 *); + +extern SNES_SPC *spc_core; + +#endif diff --git a/source/snes9x/apu/blargg_common.h b/source/snes9x/apu/blargg_common.h new file mode 100644 index 0000000..8232803 --- /dev/null +++ b/source/snes9x/apu/blargg_common.h @@ -0,0 +1,187 @@ +// 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 new file mode 100644 index 0000000..9dc69db --- /dev/null +++ b/source/snes9x/apu/blargg_config.h @@ -0,0 +1,24 @@ +// 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 new file mode 100644 index 0000000..f2daca6 --- /dev/null +++ b/source/snes9x/apu/blargg_endian.h @@ -0,0 +1,185 @@ +// 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 new file mode 100644 index 0000000..5e45c4f --- /dev/null +++ b/source/snes9x/apu/blargg_source.h @@ -0,0 +1,100 @@ +/* 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 new file mode 100644 index 0000000..5faba9d --- /dev/null +++ b/source/snes9x/apu/license.txt @@ -0,0 +1,504 @@ + 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 new file mode 100644 index 0000000..c942bf3 --- /dev/null +++ b/source/snes9x/apu/resampler.h @@ -0,0 +1,161 @@ +/* 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 new file mode 100644 index 0000000..b743c47 --- /dev/null +++ b/source/snes9x/apu/ring_buffer.h @@ -0,0 +1,111 @@ +/* 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 deleted file mode 100644 index 495979a..0000000 --- a/source/snes9x/apudebug.cpp +++ /dev/null @@ -1,509 +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 "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/bsx.cpp b/source/snes9x/bsx.cpp index e594ae3..8b2d23a 100644 --- a/source/snes9x/bsx.cpp +++ b/source/snes9x/bsx.cpp @@ -158,49 +158,47 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ - - - -// Anonymous wrote: +// Dreamer Nom 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 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 struct SBSX_RTC { - int hours; - int minutes; - int seconds; - int ticks; + int hours; + int minutes; + int seconds; + int ticks; }; -struct SBSX_RTC BSX_RTC; +static struct SBSX_RTC BSX_RTC; // flash card vendor information -const uint8 flashcard[20] = +static const uint8 flashcard[20] = { 0x4D, 0x00, 0x50, 0x00, // vendor id 0x00, 0x00, // ? @@ -209,7 +207,7 @@ const uint8 flashcard[20] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const uint8 init2192[32] = // FIXME +static const uint8 init2192[32] = // FIXME { 00, 00, 00, 00, 00, // unknown 01, 01, 00, 00, 00, @@ -221,29 +219,29 @@ const uint8 init2192[32] = // FIXME 00, 00, 00, 00, 00, 00, 00, 00, 00 }; -bool8 FlashMode; -uint32 FlashSize; -uint8 *MapROM, *FlashROM; +static bool8 FlashMode; +static uint32 FlashSize; +static 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 @@ -266,7 +264,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 @@ -300,7 +298,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 @@ -329,7 +327,7 @@ static void BSX_Map_HiROM(void) } } -static void BSX_Map_MMC(void) +static void BSX_Map_MMC (void) { int c; @@ -341,7 +339,7 @@ static void BSX_Map_MMC(void) } } -static void BSX_Map_FlashIO(void) +static void BSX_Map_FlashIO (void) { int c; @@ -357,7 +355,7 @@ static void BSX_Map_FlashIO(void) } } -static void BSX_Map_SRAM(void) +static void BSX_Map_SRAM (void) { int c; @@ -370,7 +368,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; @@ -407,7 +405,7 @@ static void map_psram_mirror_sub(uint32 bank) } } -static void BSX_Map_PSRAM(void) +static void BSX_Map_PSRAM (void) { int c; @@ -445,7 +443,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; @@ -478,7 +476,7 @@ static void BSX_Map_BIOS(void) } } -static void BSX_Map_RAM(void) +static void BSX_Map_RAM (void) { int c; @@ -494,7 +492,7 @@ static void BSX_Map_RAM(void) } } -static void BSX_Map_Dirty(void) +static void BSX_Map_Dirty (void) { // for the quick bank change @@ -527,7 +525,7 @@ static void BSX_Map_Dirty(void) } } -static void BSX_Map(void) +static void BSX_Map (void) { #ifdef BSX_DEBUG printf("BS: Remapping\n"); @@ -582,20 +580,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; @@ -608,7 +606,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; @@ -616,7 +614,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) @@ -654,10 +652,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; @@ -776,210 +774,207 @@ void S9xSetBSX(uint8 byte, uint32 address) } } -uint8 S9xGetBSXPPU(uint16 address) +uint8 S9xGetBSXPPU (uint16 address) { - uint8 t = 0; + uint8 t; - if (address >= 0x2188 && address <= 0x219F) + // known read registers + switch (address) { - // known read registers - switch(address) - { - // Test register low? (r/w) - case 0x2188: - t = BSX.PPU[0x2188]; - break; + // Test register low? (r/w) + case 0x2188: + t = BSX.PPU[0x2188 - BSXPPUBASE]; + break; - // Test register high? (r/w) - case 0x2189: - t = BSX.PPU[0x2189]; - break; + // Test register high? (r/w) + case 0x2189: + t = BSX.PPU[0x2189 - BSXPPUBASE]; + break; - case 0x218A: - t = BSX.PPU[0x218A]; - break; + case 0x218A: + t = BSX.PPU[0x218A - BSXPPUBASE]; + break; - case 0x218C: - t = BSX.PPU[0x218C]; - break; + case 0x218C: + t = BSX.PPU[0x218C - BSXPPUBASE]; + break; - // Transmission number low? (r/w) - case 0x218E: - t = BSX.PPU[0x218E]; - break; + // Transmission number low? (r/w) + case 0x218E: + t = BSX.PPU[0x218E - BSXPPUBASE]; + break; - // Transmission number high? (r/w) - case 0x218F: - t = BSX.PPU[0x218F]; - break; + // Transmission number high? (r/w) + case 0x218F: + t = BSX.PPU[0x218F - BSXPPUBASE]; + break; - // Status register? (r) - case 0x2190: - t = BSX.PPU[0x2190]; - break; + // Status register? (r) + case 0x2190: + t = BSX.PPU[0x2190 - BSXPPUBASE]; + break; - // Data register? (r/w) - case 0x2192: - t = BSX.PPU[0x2192]; + // Data register? (r/w) + case 0x2192: + t = BSX.PPU[0x2192 - BSXPPUBASE]; - // 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; + // test + t = BSX.test2192[BSX.out_index++]; + if (BSX.out_index == 32) BSX.out_index = 0; - break; - // Data register? (r/w) - case 0x2192: - BSX.PPU[0x2192] = 0x01; // ? - BSX.PPU[0x2190] = 0x80; // ? - 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; - // Transmission status? (r/w) - case 0x2193: - BSX.PPU[0x2193] = byte; - break; + BSX.test2192[10] = BSX_RTC.seconds; + BSX.test2192[11] = BSX_RTC.minutes; + BSX.test2192[12] = BSX_RTC.hours; - // Reset? (r/w) - case 0x2194: - BSX.PPU[0x2194] = byte; - break; + break; - // Unknown (r/w) - case 0x2197: - BSX.PPU[0x2197] = byte; - break; + // Transmission status? (r/w) + case 0x2193: + // Data ready when bits 2/3 clear? + t = BSX.PPU[0x2193 - BSXPPUBASE] & ~0x0C; + 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; - } + // 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; } } -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[_MAX_PATH + 1], name[_MAX_PATH + 1]; + char path[PATH_MAX + 1], name[PATH_MAX + 1]; bool8 r = FALSE; strcpy(path, S9xGetDirectory(BIOS_DIR)); @@ -1012,10 +1007,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; @@ -1097,7 +1092,7 @@ void S9xInitBSX(void) } } -void S9xResetBSX(void) +void S9xResetBSX (void) { if (Settings.BSXItself) memset(Memory.ROM, 0, FLASH_SIZE); @@ -1149,7 +1144,7 @@ void S9xResetBSX(void) BSX_Map(); } -void S9xFixBSXAfterSnapshotLoad(void) +void S9xBSXPostLoadState (void) { uint8 temp[16]; bool8 pd1, pd2; @@ -1166,34 +1161,30 @@ void S9xFixBSXAfterSnapshotLoad(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 abf74ab..4b33b44 100644 --- a/source/snes9x/bsx.h +++ b/source/snes9x/bsx.h @@ -159,8 +159,6 @@ **********************************************************************************/ - - #ifndef _BSX_H_ #define _BSX_H_ @@ -183,17 +181,15 @@ 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 S9xFixBSXAfterSnapshotLoad(void); -END_EXTERN_C +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); #endif diff --git a/source/snes9x/c4.cpp b/source/snes9x/c4.cpp index 978e535..308a38d 100644 --- a/source/snes9x/c4.cpp +++ b/source/snes9x/c4.cpp @@ -159,155 +159,146 @@ **********************************************************************************/ - #include -#include -#include "c4.h" +#include "snes9x.h" #include "memmap.h" -extern "C" { -short C4WFXVal; -short C4WFYVal; -short C4WFZVal; -short C4WFX2Val; -short C4WFY2Val; -short C4WFDist; -short C4WFScale; +#define C4_PI 3.14159265 -static double tanval; -static double c4x, c4y, c4z; -static double c4x2, c4y2, c4z2; +int16 C4WFXVal; +int16 C4WFYVal; +int16 C4WFZVal; +int16 C4WFX2Val; +int16 C4WFY2Val; +int16 C4WFDist; +int16 C4WFScale; +int16 C41FXVal; +int16 C41FYVal; +int16 C41FAngleRes; +int16 C41FDist; +int16 C41FDistVal; -void C4TransfWireFrame () +static double tanval; +static double c4x, c4y, c4z; +static double c4x2, c4y2, c4z2; + + +void C4TransfWireFrame (void) { - 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 * 3.14159265 * 2 / 128; - c4y2 = c4y * cos (tanval) - c4z * sin (tanval); - c4z2 = c4y * sin (tanval) + c4z * cos (tanval); + // Rotate X + tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; + c4y2 = c4y * cos(tanval) - c4z * sin(tanval); + c4z2 = c4y * sin(tanval) + c4z * 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 Y + tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; + c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); + c4z = c4x * -sin(tanval) + c4z2 * 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); + // Rotate Z + tanval = -(double) C4WFDist * C4_PI * 2 / 128; + c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); + c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); - // Scale - C4WFXVal = (short) (c4x*(double)C4WFScale/(0x90*(c4z+0x95))*0x95); - C4WFYVal = (short) (c4y*(double)C4WFScale/(0x90*(c4z+0x95))*0x95); + // Scale + C4WFXVal = (int16) (c4x * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); + C4WFYVal = (int16) (c4y * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); } -void C4TransfWireFrame2 () +void C4TransfWireFrame2 (void) { - c4x = (double)C4WFXVal; - c4y = (double)C4WFYVal; - c4z = (double)C4WFZVal; + c4x = (double) C4WFXVal; + c4y = (double) C4WFYVal; + c4z = (double) C4WFZVal; - // Rotate X - tanval = -(double) C4WFX2Val * 3.14159265 * 2 / 128; - c4y2 = c4y * cos (tanval) - c4z * sin (tanval); - c4z2 = c4y * sin (tanval) + c4z * cos (tanval); + // Rotate X + tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; + c4y2 = c4y * cos(tanval) - c4z * sin(tanval); + c4z2 = c4y * sin(tanval) + c4z * 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 Y + tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; + c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); + c4z = c4x * -sin(tanval) + c4z2 * 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); + // Rotate Z + tanval = -(double) C4WFDist * C4_PI * 2 / 128; + c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); + c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); - // Scale - C4WFXVal =(short)(c4x * (double)C4WFScale / 0x100); - C4WFYVal =(short)(c4y * (double)C4WFScale / 0x100); + // Scale + C4WFXVal = (int16) (c4x * (double) C4WFScale / 0x100); + C4WFYVal = (int16) (c4y * (double) C4WFScale / 0x100); } -void C4CalcWireFrame () +void C4CalcWireFrame (void) { - 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; - } + 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; + } } -short C41FXVal; -short C41FYVal; -short C41FAngleRes; -short C41FDist; -short C41FDistVal; - -void C4Op1F () +void C4Op1F (void) { - 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; - } + 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; + } } -void C4Op15() +void C4Op15 (void) { - tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - C41FDist = (short) tanval; + tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + C41FDist = (int16) tanval; } -void C4Op0D() +void C4Op0D (void) { - tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - tanval = C41FDistVal / tanval; - C41FYVal = (short) (C41FYVal * tanval * 0.99); - C41FXVal = (short) (C41FXVal * tanval * 0.98); + tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (int16) (C41FYVal * tanval * 0.99); + C41FXVal = (int16) (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) @@ -322,4 +313,13 @@ uint8 * S9xGetMemPointerC4 (uint16 Address) return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); } -}//end extern C +#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 diff --git a/source/snes9x/c4.h b/source/snes9x/c4.h index 9bc9d83..b72da27 100644 --- a/source/snes9x/c4.h +++ b/source/snes9x/c4.h @@ -159,45 +159,50 @@ **********************************************************************************/ - #ifndef _C4_H_ #define _C4_H_ -#include "port.h" -#include "memmap.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; -extern "C" { +#ifdef ZSNES_C4 +extern uint8 *C4Ram; +#endif -extern int16 C4WFXVal; -extern int16 C4WFYVal; -extern int16 C4WFZVal; -extern int16 C4WFX2Val; -extern int16 C4WFY2Val; -extern int16 C4WFDist; -extern int16 C4WFScale; +#ifdef ZSNES_C4 +START_EXTERN_C +#endif -void C4TransfWireFrame(); -void C4TransfWireFrame2(); -void C4CalcWireFrame(); +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); -extern int16 C41FXVal; -extern int16 C41FYVal; -extern int16 C41FAngleRes; -extern int16 C41FDist; -extern int16 C41FDistVal; +#ifdef ZSNES_C4 +END_EXTERN_C +#endif -void C4Op1F(); -void C4Op15(); -void C4Op0D(); +uint8 * S9xGetBasePointerC4 (uint16); +uint8 * S9xGetMemPointerC4 (uint16); -extern int16 C4CosTable[]; -extern int16 C4SinTable[]; - -} - -static inline uint8 *C4GetMemPointer(uint32 Address){ - return (Memory.ROM + ((Address&0xff0000)>>1) + (Address&0x7fff)); +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 ea80989..ff35ff5 100644 --- a/source/snes9x/c4emu.cpp +++ b/source/snes9x/c4emu.cpp @@ -159,930 +159,1064 @@ **********************************************************************************/ - -#ifndef ZSNES_C4 -#ifdef HAVE_CONFIG_H - #include -#endif #include #include "snes9x.h" -#include "sar.h" #include "memmap.h" -#include "ppu.h" -#include "c4.h" +#include "sar.h" -void S9xInitC4 () +static int16 C4SinTable[512] = { - // Stupid zsnes code, we can't do the logical thing without breaking - // savestates -// Memory.C4RAM = &Memory.FillRAM [0x6000]; - memset(Memory.C4RAM, 0, 0x2000); + 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); } uint8 S9xGetC4 (uint16 Address) { - if(Address==0x7f5e) return 0; - return (Memory.C4RAM [Address-0x6000]); -} + if (Address == 0x7f5e) + return (0); -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; - } + return (Memory.C4RAM[Address - 0x6000]); } void S9xSetC4 (uint8 byte, uint16 Address) { - int i; + Memory.C4RAM[Address - 0x6000] = byte; - Memory.C4RAM [Address-0x6000] = byte; - if (Address == 0x7f4f) + 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 - S9xC4ProcessSprites(); - break; + case 0x00: // Sprite + #ifdef DEBUGGER + //printf("00 Sprite!\n"); + #endif + C4ProcessSprites(); + 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 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 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; + 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 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; + WRITE_WORD(Memory.C4RAM + 0x1f80, (uint16) tmp); + 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 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 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 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 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 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 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 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 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 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; - 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; + 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; - 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; + #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 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; + 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 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; + int16 y = READ_WORD(Memory.C4RAM + 0x1f83) - READ_WORD(Memory.C4RAM + 0x1f89); + int16 left, right; - 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; + 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 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 < 0 && right < 0) + { + left = 1; + right = 0; + } + else + if (left < 0) + left = 0; + else + if (right < 0) + 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; + 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; + } - 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)); - } + 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)); + } } - -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 0a94e39..fc5d076 100644 --- a/source/snes9x/cheats.cpp +++ b/source/snes9x/cheats.cpp @@ -159,426 +159,404 @@ **********************************************************************************/ - -#include #include -#include #include "snes9x.h" -#include "cheats.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); + 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; - 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."); + uint32 data = 0; - address = data >> 8; - byte = (uint8) data; - return (NULL); + 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); } -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]; - if (strlen (code) != 14) - return ("Invalid Gold Finger code should be 14 hex digits in length."); + char tmp[15]; + int i; - strncpy (tmp, code, 5); - tmp [5] = 0; - if (sscanf (tmp, "%x", &address) != 1) - return ("Invalid Gold Finger code."); + if (strlen(code) != 14) + return ("Invalid Gold Finger code - should be 14 hex digits in length."); - 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); -} + strncpy(tmp, code, 5); + tmp[5] = 0; + if (sscanf(tmp, "%x", &address) != 1) + return ("Invalid Gold Finger code."); -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++) + for (i = 0; i < 3; i++) { - 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); + unsigned int byte; - return (NULL); + strncpy(tmp, code + 5 + i * 2, 2); + tmp[2] = 0; + if (sscanf(tmp, "%x", &byte) != 1) + break; + bytes[i] = (uint8) byte; + } + + 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); } 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); } -#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) +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool8 is_signed, bool8 update) { - int l; + int l, i; - 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; + } - 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); - } + 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); + } - 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 < 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 < 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 < 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 < 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 < 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 < 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); + 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); } -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; + int l, i; - 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; + } - int i; + 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); + } - 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 < 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); + } - 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 < 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 < 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 < 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 < 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 = 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 < 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); + 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; + int l, i; - 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; + } - int i; + 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); + } - { + 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 < 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 = 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 < 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 = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_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); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_BITS, i); } void S9xOutputCheatSearchResults (SCheatData *d) { - int i; - for (i = 0; i < 0x20000; i++) - { - if (TEST_BIT (d->WRAM_BITS, i)) - printf ("WRAM: %05x: %02x\n", i, d->RAM [i]); - } + int 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 < 0x20000; i++) + { + if (TEST_BIT(d->WRAM_BITS, i)) + printf("WRAM: %05x: %02x\n", i, d->RAM[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 < 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]); + } } - diff --git a/source/snes9x/cheats.h b/source/snes9x/cheats.h index 199189f..53411b8 100644 --- a/source/snes9x/cheats.h +++ b/source/snes9x/cheats.h @@ -159,89 +159,88 @@ **********************************************************************************/ - #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)]; -#define WRAM_BITS ALL_BITS -#define SRAM_BITS ALL_BITS + (0x20000 >> 5) -#define IRAM_BITS ALL_BITS + (0x30000 >> 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]; + 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; -void S9xInitCheatData (); +extern SCheatData Cheat; +extern Watch watches[16]; -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 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 *); void S9xStartCheatSearch (SCheatData *); -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 S9xSearchForChange (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, bool8, bool8); +void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8, bool8); +void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8); void S9xOutputCheatSearchResults (SCheatData *); -#endif +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 55fb2dd..0804e77 100644 --- a/source/snes9x/cheats2.cpp +++ b/source/snes9x/cheats2.cpp @@ -159,223 +159,232 @@ **********************************************************************************/ - -#include -#include -#include #include "snes9x.h" -#include "cheats.h" #include "memmap.h" +#include "cheats.h" -#ifndef INLINE -#define INLINE inline -#endif +static uint8 S9xGetByteFree (uint32); +static void S9xSetByteFree (uint8, uint32); -extern SCheatData Cheat; -Watch watches [16]; -// read a byte without altering CPU -INLINE uint8 S9xGetByteFree (uint32 Address) +static uint8 S9xGetByteFree (uint32 address) { - uint32 Cycles = CPU.Cycles; - uint32 WaitAddress = CPU.WaitAddress; - uint8 rv = S9xGetByte (Address); + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + uint8 byte; + + byte = S9xGetByte(address); + CPU.WaitAddress = WaitAddress; CPU.Cycles = Cycles; - return rv; + + return (byte); } -INLINE void S9xSetByteFree (uint8 Byte, uint32 Address) + +static 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 S9xInitCheatData () +void S9xInitWatchedAddress (void) { - Cheat.RAM = Memory.RAM; - Cheat.SRAM = Memory.SRAM; - Cheat.FillRAM = Memory.FillRAM; + for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) + watches[i].on = false; + } -void S9xAddCheat (bool8 enable, bool8 save_current_value, - uint32 address, uint8 byte) +void S9xInitCheatData (void) { - 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.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])) { - Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByteFree (address); - Cheat.c [Cheat.num_cheats].saved = TRUE; + 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.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--; //MK: This used to set it to 0?? - } + memmove(&Cheat.c[which1], &Cheat.c[which1 + 1], sizeof(Cheat.c[0]) * (Cheat.num_cheats - which1 - 1)); + + Cheat.num_cheats--; + } } -void S9xDeleteCheats () +void S9xDeleteCheats (void) { - 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); - } -} - -void S9xDisableCheat (uint32 which1) -{ - if (which1 < Cheat.num_cheats && Cheat.c [which1].enabled) - { - S9xRemoveCheat (which1); - Cheat.c [which1].enabled = FALSE; - } + S9xRemoveCheats(); + Cheat.num_cheats = 0; } void S9xRemoveCheat (uint32 which1) { - if (Cheat.c [which1].saved) - { - uint32 address = Cheat.c [which1].address; + if (Cheat.c[which1].saved) + { + uint32 address = Cheat.c[which1].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].saved_byte; - else - S9xSetByte (Cheat.c [which1].saved_byte, address); - } + 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); +} + +void S9xEnableCheat (uint32 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; + } } 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); + if (!Cheat.c[which1].saved) + { + Cheat.c[which1].saved_byte = S9xGetByteFree(address); + Cheat.c[which1].saved = TRUE; + } - 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 - S9xSetByte (Cheat.c [which1].byte, address); - Cheat.c [which1].saved = TRUE; + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c[which1].byte; + else + S9xSetByteFree(Cheat.c[which1].byte, address); } -void S9xApplyCheats () +void S9xApplyCheats (void) { - 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); + if (Settings.ApplyCheats) + { + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c[i].enabled) + S9xApplyCheat(i); + } } bool8 S9xLoadCheatFile (const char *filename) { - Cheat.num_cheats = 0; + FILE *fs; + uint8 data[28]; - FILE *fs = fopen (filename, "rb"); - uint8 data [28]; + Cheat.num_cheats = 0; - if (!fs) - return (FALSE); + fs = fopen(filename, "rb"); + 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; - } - fclose (fs); + 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; + } - return (TRUE); + fclose(fs); + + return (TRUE); } bool8 S9xSaveCheatFile (const char *filename) { - 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) + if (Cheat.num_cheats == 0) { - data [6] = 254; - data [7] = 252; + remove(filename); + return (TRUE); } - if (!Cheat.c [i].enabled) - data [0] |= 4; - if (Cheat.c [i].saved) - data [0] |= 8; + FILE *fs; + uint8 data[28]; - 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; + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); - memmove (&data [8], Cheat.c [i].name, 19); - if (fwrite (data, 28, 1, fs) != 1) + for (uint32 i = 0; i < Cheat.num_cheats; i++) { - fclose (fs); - return (FALSE); + 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); + } } - } - return (fclose (fs) == 0); + + return (fclose(fs) == 0); } - - diff --git a/source/snes9x/clip.cpp b/source/snes9x/clip.cpp index 13947d3..e64cfee 100644 --- a/source/snes9x/clip.cpp +++ b/source/snes9x/clip.cpp @@ -159,189 +159,231 @@ **********************************************************************************/ - - #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 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, uint8, uint8); +static inline void StoreWindowRegions (uint8, struct ClipData *, int, int16 *, uint8 *, bool8, bool8 s = FALSE); - // Never get here - return 0; + +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); } -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; +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; } -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; +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; - // 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; - } - } - } + // 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). - // Get a bitmap of which regions correspond to each window. - uint8 W1, W2; + if (PPU.Window1Left <= PPU.Window1Right) + { + if (PPU.Window1Left > 0) + { + windows[2] = 256; + windows[1] = PPU.Window1Left; + n_regions = 2; + } - 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.Window1Right < 255) + { + windows[n_regions + 1] = 256; + windows[n_regions] = PPU.Window1Right + 1; + n_regions++; + } + } - // 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 <= PPU.Window2Right) + { + for (i = 0; i <= n_regions; i++) + { + if (PPU.Window2Left == windows[i]) + break; - 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]; - // 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); + windows[i] = PPU.Window2Left; + n_regions++; + break; + } + } - // 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<= 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); + } + } } diff --git a/source/snes9x/controls.cpp b/source/snes9x/controls.cpp index 96efb9f..89e8f03 100644 --- a/source/snes9x/controls.cpp +++ b/source/snes9x/controls.cpp @@ -159,2512 +159,3308 @@ **********************************************************************************/ - -#include -#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 "ppu.h" +#include "movie.h" #include "display.h" -#include "cpuexec.h" -#include "snapshot.h" -#include "spc7110.h" -//#include "movie.h" #ifdef NETPLAY_SUPPORT #include "netplay.h" #endif -#ifdef __WIN32__ -#define snprintf _snprintf // needs ANSI compliant name -#endif +using namespace std; -using namespace std; +#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 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 POLL_ALL NUMCTLS -#define POLL_ALL NUMCTLS +#define SUPERSCOPE_FIRE 0x80 +#define SUPERSCOPE_CURSOR 0x40 +#define SUPERSCOPE_TURBO 0x20 +#define SUPERSCOPE_PAUSE 0x10 +#define SUPERSCOPE_OFFSCREEN 0x02 -static map keymap; -static set pollmap[NUMCTLS+1]; -static vector multis; -struct exemulti { - int32 pos; - bool8 data1; - s9xcommand_t *script; -}; -static set exemultis; +#define JUSTIFIER_TRIGGER 0x80 +#define JUSTIFIER_START 0x20 +#define JUSTIFIER_SELECT 0x08 -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 MAP_UNKNOWN (-1) +#define MAP_NONE 0 +#define MAP_BUTTON 1 +#define MAP_AXIS 2 +#define MAP_POINTER 3 -struct crosshair { - uint8 set; - uint8 img; - uint8 fg; - uint8 bg; +#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; }; -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]; +struct crosshair +{ + uint8 set; + uint8 img; + uint8 fg, bg; +}; -#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 +{ + int16 x, y; + int16 V_adj; + bool8 V_var; + int16 H_adj; + bool8 H_var; + bool8 mapped; +} pseudopointer[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 +{ + uint16 buttons; + uint16 turbos; + uint16 toggleturbo; + uint16 togglestick; + uint8 turbo_ct; +} joypad[8]; -uint8 read_idx[2 /* ports */][2 /* per port */]; +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]; -bool8 pad_read = 0, pad_read_last = 0; +static struct +{ + int16 x, y; + uint8 phys_buttons; + uint8 next_buttons; + uint8 read_buttons; + uint32 ID; + struct crosshair crosshair; +} superscope; -#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 +{ + 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 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(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 + 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) \ -#define S(x) x +#define S(x) x -enum command_numbers { - THE_COMMANDS - LAST_COMMAND // must be last! +enum command_numbers +{ + THE_COMMANDS, + LAST_COMMAND }; #undef S -#define S(x) #x +#define S(x) #x -static const char *command_names[LAST_COMMAND+1]={ - THE_COMMANDS - NULL // This MUST be last! +static const char *command_names[LAST_COMMAND + 1] = +{ + THE_COMMANDS, + NULL }; #undef S #undef THE_COMMANDS -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 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 *speed_names[4]={ "Var", "Slow", "Med", "Fast" }; -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, 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 S9xDisplayStateChange(const char *str, bool8 on){ - snprintf(buf, sizeof(buf), "%s %s", str, on?"on":"off"); - S9xSetInfoString(buf); +static void DisplayStateChange (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; - if(x>295) x=295; - if(x<40) x=40; - if(y>PPU.ScreenHeight-1) y=PPU.ScreenHeight-1; - if(y<0) y=0; +static void DoGunLatch (int x, int y) +{ + x += 40; - PPU.GunVLatch = (uint16) (y + 1); - PPU.GunHLatch = (uint16) x; + 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; } -#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; +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){ - int i, j; +void S9xControlsSoftReset (void) +{ + for (set::iterator it = exemultis.begin(); it != exemultis.end(); it++) + delete *it; + exemultis.clear(); - 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; + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + read_idx[i][j]=0; + + FLAG_LATCH = FALSE; } -void S9xUnmapAllControls(void){ - int i; +void S9xUnmapAllControls (void) +{ + S9xControlsReset(); - S9xControlsReset(); - keymap.clear(); - for(i=0; i<(int)multis.size(); i++){ - free(multis[i]); - } - multis.clear(); - for(i=0; i1) 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; +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; } -bool S9xVerifyControllers(void){ - bool ret=false; - int port; - int i, used[NUMCTLS]; - - 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; - } - } - - return ret; -} - -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; - 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; - - case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: - case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: - *controller=CTL_JOYPAD; - *id1=i-JOYPAD0; - 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; - } -} - -void S9xReportControllers(void){ - int port, i; - static char buf[128]; // static because S9xMessage keeps our pointer instead of copying - char *c=buf; - - S9xVerifyControllers(); - for(port=0; port<2; port++){ - c+=sprintf(c, "Port %d: ", port+1); - switch(newcontrollers[port]){ - case NONE: - c+=sprintf(c, ". "); - break; - - 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; - - 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 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, 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"); - 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.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; - - 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; - - 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 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; - - 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 *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; - - default: - return strdup("BUG: Unknown command type"); - } - - return strdup(s.c_str()); -} - -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 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; -} - -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; -} - -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"; - } -} - -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; - - 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=-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; -} - -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==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; - } - 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(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; -} - -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; - } - - 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; - } - 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; - } - - 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; -} - -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; - } - - 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; -} - -void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ - int i; - - 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){ - 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, +bool S9xVerifyControllers (void) +{ + bool ret = false; + int port, i, used[NUMCTLS]; + + for (i = 0; i < NUMCTLS; used[i++] = 0) ; + + for (port = 0; port < 2; port++) + { + switch (i = newcontrollers[port]) + { + case MOUSE0: + case MOUSE1: + if (!Settings.MouseMaster) { - 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()) + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + if (used[i]++ > 0) { - S9xSetInfoString("No movie in progress."); - return; - } + 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; + } - char msg[128]; - sprintf(msg, "Select frame number (current: %d)", S9xMovieGetFrameCounter()); + break; - 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 SUPERSCOPE: + if (!Settings.SuperScopeMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } - case LAST_COMMAND: break; - /* no default, so we get compiler warnings */ - } - } - return; + 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; + } - 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; + break; - 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 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; + } - 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; + 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; + } - 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; + break; - 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 MP5: + if (!Settings.MultiPlayer5Master) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } - case S9xButtonPort: - case S9xAxisPort: - case S9xPointerPort: - S9xHandlePortCommand(cmd, data1, data2); - return; + 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; + } + } + } - 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; + 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: - fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type); - return; - } + default: + break; + } + } + + return (ret); } +void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4) +{ + int i; -static void do_polling(int mp){ - set::iterator itr; + *controller = CTL_NONE; + *id1 = *id2 = *id3 = *id4 = -1; - 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; + if (port < 0 || port > 1) + return; - case MAP_AXIS: - int16 value; - if(S9xPollAxis(*itr, &value)) S9xReportAxis(*itr, value); - break; + 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 MAP_POINTER: - int16 x, y; - if(S9xPollPointer(*itr, &x, &y)) S9xReportPointer(*itr, x, y); - break; + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + *controller = CTL_JOYPAD; + *id1 = i - JOYPAD0; + return; - default: - break; - } - } + 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; + } } -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 S9xReportControllers (void) +{ + static char mes[128]; + char *c = mes; + + S9xVerifyControllers(); + + for (int port = 0; port < 2; port++) + { + c += sprintf(c, "Port %d: ", port + 1); + + switch (newcontrollers[port]) + { + case NONE: + c += sprintf(c, ". "); + 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); + } + + 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 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); } -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; +char * S9xGetCommandName (s9xcommand_t command) +{ + string s; + char c; - 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; + switch (command.type) + { + case S9xButtonJoypad: + if (command.button.joypad.buttons == 0) + return (strdup("None")); + if (command.button.joypad.buttons & 0x000f) + return (strdup("None")); - 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; + 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.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; + + 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; + + 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 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; + + 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())); } -uint8 S9xReadJOYSERn(int n){ - int i, j, r; - - if(n>1) n-=0x4016; - assert(n==0 || n==1); - - 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<>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; - } - } +static bool strless (const char *a, const char *b) +{ + return (strcmp(a, b) < 0); } -void S9xDoAutoJoypad(void){ - int n, i, j; +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; + + 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); +} + +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]); +} + +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); +} + +bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + 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 = -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); +} + +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 == 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); +} + +bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + 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 < 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); +} + +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; + } + + 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); + } + + 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); + } + + 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); +} + +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; + } + + 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); +} + +void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ + int i; + + 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) + { + 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 && !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; + } +} + +static void do_polling (int mp) +{ + set::iterator itr; + + if (S9xMoviePlaying()) + return; + + if (pollmap[mp].empty()) + return; + + 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_POINTER: + { + int16 x, y; + if (S9xPollPointer(*itr, &x, &y)) + S9xReportPointer(*itr, x, y); + 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; + } +} + +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; + + 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; +} + +uint8 S9xReadJOYSERn (int n) +{ + int i, j, r; + + if (n > 1) + n -= 0x4016; + assert(n == 0 || n == 1); + + 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); + } + } +} + +void S9xDoAutoJoypad (void) +{ + int i, j; + + S9xSetJoypadLatch(1); + S9xSetJoypadLatch(0); - S9xSetJoypadLatch(1); - S9xSetJoypadLatch(0); -#ifndef NGC S9xMovieUpdate(false); -#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; - } - } + + 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; + } + } } -void S9xControlEOF(void){ - int i, j, n; - struct crosshair *c; +void S9xControlEOF (void) +{ + struct crosshair *c; + int i, j; - PPU.GunVLatch=1000; /* i.e., never latch */ - PPU.GunHLatch=0; + PPU.GunVLatch = 1000; // i.e., never latch + PPU.GunHLatch = 0; - 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); + 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; - 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 (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) + { + joypad[i - JOYPAD0].turbo_ct = 0; + joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; + } + } - 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; - } - } + break; - 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_adj= turbo_time) + { + joypad[i - JOYPAD0].turbo_ct = 0; + joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; + } - 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); + 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); + + 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(); -#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!=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; - } - } + if (fg) + { + fgcolor = 0; + if (*fg == 't') + { + fg++; + fgcolor = 16; + } - 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; - } - } + 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(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 (!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; + } } -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!=NULL) *idx=c->img; - if(fg!=NULL) *fg=color_names[c->fg]; - if(bg!=NULL) *bg=color_names[c->bg]; + if (idx) + *idx = c->img; + + if (fg) + *fg = color_names[c->fg]; + + if (bg) + *bg = color_names[c->bg]; } -uint16 MovieGetJoypad(int i){ - if(i<0 || i>7) return 0; - return joypad[i].buttons; -} +void S9xControlPreSaveState (struct SControlSnapshot *s) +{ + ZeroMemory(s, sizeof(*s)); + s->ver = 3; -void MovieSetJoypad(int i, uint16 buttons){ - if(i<0 || i>7) return; - joypad[i].buttons=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]; + } -// 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; -} + for (int j = 0; j < 2; j++) + s->mouse_speed[j] = (mouse[j].buttons & 0x30) >> 4; -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]); -} + s->justifier_select = ((justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0); -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; -} +#define COPY(x) { memcpy((char *) s->internal + i, &(x), sizeof(x)); i += sizeof(x); } -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++; -} + int i = 0; -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++) + for (int j = 0; j < 8; j++) COPY(joypad[j].buttons); - for(j=0; j<2; j++) { + + for (int j = 0; j < 2; j++) + { COPY(mouse[j].delta_x); COPY(mouse[j].delta_y); COPY(mouse[j].old_x); @@ -2673,54 +3469,70 @@ void S9xControlPreSave(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(j=0; j<2; j++) COPY(justifier.x[j]); - for(j=0; j<2; j++) COPY(justifier.y[j]); + + for (int j = 0; j < 2; j++) + COPY(justifier.x[j]); + for (int j = 0; j < 2; j++) + COPY(justifier.y[j]); COPY(justifier.buttons); - for(j=0; j<2; j++) COPY(justifier.offscreen[j]); - for(j=0; j<2; j++) - for(int k=0; k<2; k++) + 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++) 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 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) +void S9xControlPostLoadState (struct SControlSnapshot *s) +{ + if (curcontrollers[0] == MP5 && s->ver < 1) { -#define COPY(x) {memcpy(&(x), (char*)s->internal+i, sizeof(x)); i+=sizeof(x);} - i=0; - for(j=0; j<8; j++) + // 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++) COPY(joypad[j].buttons); - for(j=0; j<2; j++) { + + for (int j = 0; j < 2; j++) + { COPY(mouse[j].delta_x); COPY(mouse[j].delta_y); COPY(mouse[j].old_x); @@ -2729,24 +3541,141 @@ void S9xControlPostLoad(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(j=0; j<2; j++) COPY(justifier.x[j]); - for(j=0; j<2; j++) COPY(justifier.y[j]); + + for (int j = 0; j < 2; j++) + COPY(justifier.x[j]); + for (int j = 0; j < 2; j++) + COPY(justifier.y[j]); COPY(justifier.buttons); - for(j=0; j<2; j++) COPY(justifier.offscreen[j]); - for(j=0; j<2; j++) - for(int k=0; k<2; k++) + 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++) 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 a81d695..db434c6 100644 --- a/source/snes9x/controls.h +++ b/source/snes9x/controls.h @@ -159,292 +159,279 @@ **********************************************************************************/ +#ifndef _CONTROLS_H_ +#define _CONTROLS_H_ -#ifndef FOO_H -#define FOO_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 -#include "port.h" +#define S9xButtonPseudopointer 254 +#define S9xAxisPseudopointer 253 +#define S9xAxisPseudobuttons 252 -#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 +// 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 S9xButtonPseudopointer 254 -#define S9xAxisPseudopointer 253 -#define S9xAxisPseudobuttons 252 +#define S9xButtonPort 251 +#define S9xAxisPort 250 +#define S9xPointerPort 249 -// 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 +#define S9xBadMapping 255 +#define InvalidControlID ((uint32) -1) -#define S9xBadMapping 255 -#define InvalidControlID ((uint32)-1) +// 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. -// 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) +#define PseudoPointerBase (InvalidControlID - 8) +#define PseudoButtonBase (PseudoPointerBase - 256) -// 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; +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... -/* Starting out... */ -void S9xUnmapAllControls(void); +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); -/* 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); +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); -/* - * 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); +// 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. -/* - * 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); +bool S9xVerifyControllers (void); -/* - * Generic mapping functions - */ -s9xcommand_t S9xGetMapping(uint32 id); -void S9xUnmapID(uint32 id); +// Functions for translation s9xcommand_t's into strings, and vice versa. +// free() the returned string after you're done with it. -/* - * 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); +char * S9xGetCommandName (s9xcommand_t command); +s9xcommand_t S9xGetCommandT (const char *name); -/* - * 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); +// 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. -/* - * 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); +const char ** S9xGetAllSnes9xCommands (void); -/* - * 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); +// Generic mapping functions -/******* - * These functions are called by snes9x into your port, so each port should - * implement them. - */ +s9xcommand_t S9xGetMapping (uint32 id); +void S9xUnmapID (uint32 id); -/* - * 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); +// 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. -/* - * 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); +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. -/* - * 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 S9xOnSNESPadRead (void); #endif -/* 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); +// 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); -/******* - * 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 */ -void S9xControlsReset(void); -void S9xControlsSoftReset(void); +// Use when resetting snes9x. -/* Use when writing to $4016 */ -void S9xSetJoypadLatch(bool latch); +void S9xControlsReset (void); +void S9xControlsSoftReset (void); -/* Use when reading $4016/7 (JOYSER0 and JOYSER1) */ -uint8 S9xReadJOYSERn(int n); +// Use when writing to $4016. -/* End-Of-Frame processing. Sets gun latch variables and tries to draw - * crosshairs */ -void S9xControlEOF(void); +void S9xSetJoypadLatch (bool latch); -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! +// 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! }; -void S9xControlPreSave(struct SControlSnapshot *s); -void S9xControlPostLoad(struct SControlSnapshot *s); +void S9xControlPreSaveState (struct SControlSnapshot *s); +void S9xControlPostLoadState (struct SControlSnapshot *s); #endif diff --git a/source/snes9x/copyright.h b/source/snes9x/copyright.h deleted file mode 100644 index e90dd1a..0000000 --- a/source/snes9x/copyright.h +++ /dev/null @@ -1,233 +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. -**********************************************************************************/ - - - -/* - * 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 da2c234..0e03079 100644 --- a/source/snes9x/cpu.cpp +++ b/source/snes9x/cpu.cpp @@ -159,283 +159,165 @@ **********************************************************************************/ - - #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 "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" -#endif - - -#ifndef ZSNES_FX +#include "apu/apu.h" #include "fxemu.h" - -extern struct FxInit_s SuperFX; - -void S9xResetSuperFX () -{ - 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); -} +#include "sdd1.h" +#include "srtc.h" +#include "snapshot.h" +#include "cheats.h" +#include "logger.h" +#ifdef DEBUGGER +#include "debug.h" #endif -void S9xSoftResetCPU () +static void S9xResetCPU (void); +static void S9xSoftResetCPU (void); + + +static void S9xResetCPU (void) { - 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; + 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); +} - ICPU.ShiftedPB = 0; - ICPU.ShiftedDB = 0; - SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); - ClearFlags (Decimal); +static void S9xSoftResetCPU (void) +{ + 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; - CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); - CPU.BranchSkip = FALSE; - CPU.NMIActive = FALSE; - CPU.IRQActive = FALSE; - CPU.WaitingForInterrupt = FALSE; + 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.InDMA = FALSE; CPU.InHDMA = FALSE; - CPU.InDMAorHDMA = FALSE; + CPU.InDMAorHDMA = FALSE; CPU.InWRAMDMAorHDMA = FALSE; CPU.HDMARanInDMA = 0; - 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; + 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; 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; - CPU.WhichEvent = HC_RENDER_EVENT; - CPU.NextEvent = Timings.RenderPos; + S9xSetPCBase(Registers.PBPC); - S9xSetPCBase (Registers.PBPC); + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + ICPU.CPUExecuting = TRUE; - ICPU.S9xOpcodes = S9xOpcodesE1; - ICPU.S9xOpLengths = S9xOpLengthsM1X1; - ICPU.CPUExecuting = TRUE; - - S9xUnpackStatus(); + 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) { -#ifndef NGC - ResetLogger(); - S9xResetSaveTimer (FALSE); -#endif + S9xResetSaveTimer(FALSE); + S9xResetLogger(); - ZeroMemory (Memory.FillRAM, 0x8000); - memset (Memory.VRAM, 0x00, 0x10000); - memset (Memory.RAM, 0x55, 0x20000); + memset(Memory.RAM, 0x55, 0x20000); + memset(Memory.VRAM, 0x00, 0x10000); + ZeroMemory(Memory.FillRAM, 0x8000); if (Settings.BS) S9xResetBSX(); - if(Settings.SPC7110) - S9xSpc7110Reset(); - S9xResetCPU (); - S9xResetPPU (); - S9xResetSRTC (); - if (Settings.SDD1) - S9xResetSDD1 (); - S9xResetDMA (); - S9xResetAPU (); - S9xResetDSP1 (); - S9xSA1Init (); - if (Settings.C4) - S9xInitC4 (); - - S9xInitCheatData (); + S9xResetCPU(); + S9xResetPPU(); + S9xResetDMA(); + S9xResetAPU(); + 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) - ResetOBC1(); - if (Settings.SuperFX) - S9xResetSuperFX (); -#ifdef ZSNES_FX - WinterGold = Settings.WinterGold; -#endif -// Settings.Paused = FALSE; + S9xResetOBC1(); + if (Settings.SRTC) + S9xResetSRTC(); + + S9xInitCheatData(); } void S9xSoftReset (void) { -#ifndef NGC - S9xResetSaveTimer (FALSE); -#endif + S9xResetSaveTimer(FALSE); + + memset(Memory.VRAM, 0x00, 0x10000); + ZeroMemory(Memory.FillRAM, 0x8000); + 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); - if(Settings.SPC7110) - S9xSpc7110Reset(); - S9xSoftResetCPU (); - S9xSoftResetPPU (); - S9xResetSRTC (); - if (Settings.SDD1) - S9xResetSDD1 (); + S9xSoftResetCPU(); + S9xSoftResetPPU(); + S9xResetDMA(); + S9xSoftResetAPU(); - S9xResetDMA (); - S9xResetAPU (); - S9xResetDSP1 (); - if(Settings.OBC1) - ResetOBC1(); - S9xSA1Init (); - if (Settings.C4) - S9xInitC4 (); + 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 (); - -// Settings.Paused = FALSE; + S9xInitCheatData(); } - -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 bc66a73..df2446b 100644 --- a/source/snes9x/cpuaddr.h +++ b/source/snes9x/cpuaddr.h @@ -159,395 +159,516 @@ **********************************************************************************/ - - #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 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 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 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 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 uint32 RelativeSlow (AccessMode a) // branch $xx +{ + int8 offset = Immediate8Slow(a); -STATIC inline uint32 RelativeSlow (AccessMode a) { // branch $xx - int8 offset = Immediate8Slow(a); - return ((int16)Registers.PCw + offset) & 0xffff; + 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; - 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; +static inline uint32 AbsoluteIndexedIndirectSlow (AccessMode a) // (a,X) +{ + uint16 addr; - // Address load wraps within the bank - uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); - OpenBus = addr2>>8; - return addr2; + 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); } -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 6c17356..649df5d 100644 --- a/source/snes9x/cpuexec.cpp +++ b/source/snes9x/cpuexec.cpp @@ -159,38 +159,21 @@ **********************************************************************************/ - - #include "snes9x.h" #include "memmap.h" #include "cpuops.h" -#include "ppu.h" -#include "cpuexec.h" -#include "s9xdebug.h" -#include "snapshot.h" -#include "gfx.h" -#include "missing.h" -#include "apu.h" #include "dma.h" -#include "sa1.h" -#include "spc7110.h" - -#ifndef ZSNES_FX +#include "apu/apu.h" #include "fxemu.h" -extern struct FxInit_s SuperFX; +#include "snapshot.h" +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" #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) @@ -211,7 +194,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++) @@ -227,7 +210,7 @@ void S9xMainLoop (void) } } } -#endif + #endif CHECK_SOUND(); @@ -235,7 +218,7 @@ void S9xMainLoop (void) { if (CPU.IRQPending) // FIXME: In case of IRQ during WRAM refresh - CPU.IRQPending = 0; + CPU.IRQPending--; else { if (CPU.WaitingForInterrupt) @@ -258,7 +241,7 @@ void S9xMainLoop (void) if (CPU.Flags & SCAN_KEYS_FLAG) break; -#ifdef DEBUGGER + #ifdef DEBUGGER if (CPU.Flags & DEBUG_MODE_FLAG) break; @@ -270,13 +253,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 - doOp: + #endif + register uint8 Op; register struct SOpcodes *Opcodes; @@ -295,50 +278,41 @@ 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 = GetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); - if (oldPCBase!=CPU.PCBase || (Registers.PCw&~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) + CPU.PCBase = S9xGetBasePointer(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(); - APURegisters.PC = IAPU.PC - IAPU.RAM; - S9xAPUPackStatus(); + S9xPackStatus(); - 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) @@ -348,22 +322,35 @@ void S9xSetIRQ (uint32 source) CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } + +#ifdef DEBUGGER + S9xTraceMessage("--- /IRQ low"); +#endif } void S9xClearIRQ (uint32 source) { - CLEAR_IRQ_SOURCE(source); + CPU.IRQActive &= ~source; + if (!CPU.IRQActive) + CPU.Flags &= ~IRQ_FLAG; + +#ifdef DEBUGGER + S9xTraceMessage("--- /IRQ high"); +#endif } void S9xDoHEventProcessing (void) { #ifdef DEBUGGER - char mes[256]; + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event processing (%02d) expected HC:%04d executed HC:%04d", + CPU.WhichEvent, CPU.NextEvent, CPU.Cycles); #endif #ifdef CPU_SHUTDOWN CPU.WaitCounter++; #endif + switch (CPU.WhichEvent) { case HC_HBLANK_START_EVENT: @@ -375,8 +362,7 @@ void S9xDoHEventProcessing (void) if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) { #ifdef DEBUGGER - sprintf(mes, "*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); - S9xTraceMessage(mes); + S9xTraceFormattedMessage("*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); #endif PPU.HDMA = S9xDoHDMA(PPU.HDMA); } @@ -397,20 +383,13 @@ void S9xDoHEventProcessing (void) S9xSuperFXExec(); #endif - #ifndef STORM - if (Settings.SoundSync) - S9xGenerateSound(); - #endif - + S9xAPUEndScanline(); CPU.Cycles -= Timings.H_Max; - APU.NextAPUTimerPos -= (Timings.H_Max << SNES_APU_ACCURACY); - APU.Cycles -= (Timings.H_Max << SNES_APU_ACCURACY); + S9xAPUSetReferenceTime(CPU.Cycles); 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 { @@ -487,7 +466,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; @@ -531,7 +510,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); @@ -539,12 +518,10 @@ void S9xDoHEventProcessing (void) case HC_WRAM_REFRESH_EVENT: #ifdef DEBUGGER - sprintf(mes, "*** WRAM Refresh HC:%04d", CPU.Cycles); - S9xTraceMessage(mes); + S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); #endif S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; - S9xAPUExecute(); S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); @@ -557,13 +534,18 @@ 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_H_BEAM_IRQ_SOURCE); + S9xSetIRQ(PPU_IRQ_SOURCE); else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + S9xSetIRQ(PPU_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 101c354..542b73c 100644 --- a/source/snes9x/cpuexec.h +++ b/source/snes9x/cpuexec.h @@ -159,126 +159,102 @@ **********************************************************************************/ - - #ifndef _CPUEXEC_H_ #define _CPUEXEC_H_ -#include "snes9x.h" +#include "ppu.h" -struct SOpcodes { -#ifdef __WIN32__ - void (__cdecl *S9xOpcode)( void); -#else - void (*S9xOpcode)( void); -#endif +struct SOpcodes +{ + void (*S9xOpcode) (void); }; struct SICPU { - 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; + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + uint32 Frame; + uint32 FrameAdvanceCount; }; -START_EXTERN_C -extern struct SICPU ICPU; -END_EXTERN_C +extern struct SICPU ICPU; -#include "ppu.h" -#include "memmap.h" -#include "65c816.h" +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]; -START_EXTERN_C void S9xMainLoop (void); void S9xReset (void); void S9xSoftReset (void); -void S9xDoHEventProcessing (); +void S9xDoHEventProcessing (void); void S9xClearIRQ (uint32); void S9xSetIRQ (uint32); -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() +static inline void S9xUnpackStatus (void) { - 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() +static inline void S9xPackStatus (void) { - 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 CLEAR_IRQ_SOURCE (uint32 M) +static inline void S9xFixCycles (void) { - 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 ()) + if (CheckEmulation()) { - ICPU.S9xOpcodes = S9xOpcodesM1X1; - ICPU.S9xOpLengths = S9xOpLengthsM1X1; + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + if (CheckMemory()) + { + if (CheckIndex()) + { + ICPU.S9xOpcodes = S9xOpcodesM1X1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM1X0; + ICPU.S9xOpLengths = S9xOpLengthsM1X0; + } } else { - ICPU.S9xOpcodes = S9xOpcodesM1X0; - ICPU.S9xOpLengths = S9xOpLengthsM1X0; + if (CheckIndex()) + { + ICPU.S9xOpcodes = S9xOpcodesM0X1; + ICPU.S9xOpLengths = S9xOpLengthsM0X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM0X0; + ICPU.S9xOpLengths = S9xOpLengthsM0X0; + } } - } - 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 f0cd870..d8bcb72 100644 --- a/source/snes9x/cpumacro.h +++ b/source/snes9x/cpumacro.h @@ -159,642 +159,730 @@ **********************************************************************************/ - - #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); \ - 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 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 inline void SetZN (uint8 Work) { - ICPU._Zero = Work; - ICPU._Negative = Work; + +static inline void SetZN (uint16 Work16) +{ + ICPU._Zero = Work16 != 0; + ICPU._Negative = (uint8) (Work16 >> 8); } -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 SetZN (uint8 Work8) +{ + ICPU._Zero = Work8; + ICPU._Negative = Work8; +} - A1 += W1+CheckCarry(); - if(A1>0x09){ - A1-=0x0A; - A1&=0x0F; - A2+=0x10; +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); } - - 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); - } else { - uint16 Ans16 = Registers.AL + Work8 + CheckCarry(); + { + uint32 Ans32 = Registers.A.W + Work16 + CheckCarry(); - ICPU._Carry = Ans16 >= 0x100; + ICPU._Carry = Ans32 >= 0x10000; - if (~(Registers.AL ^ Work8) & - (Work8 ^ (uint8) Ans16) & 0x80) - SetOverflow(); + 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); + } else - ClearOverflow(); - Registers.AL = (uint8) Ans16; - SetZN (Registers.AL); - } -} + { + uint16 Ans16 = Registers.AL + Work8 + CheckCarry(); -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; + ICPU._Carry = Ans16 >= 0x100; - A1 += W1 + CheckCarry (); - if(A1>0x0009) { - A1 -= 0x000A; - A1 &= 0x000F; - A2 += 0x0010; + if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8) Ans16) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = (uint8) Ans16; + SetZN(Registers.AL); } - - 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; - 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; - +static inline void CMP (uint16 val) +{ + int32 Int32 = (int32) Registers.A.W - (int32) val; 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); - } + SetZN((uint16) Int32); } -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); - } else { - int16 Int16 = (int16) Registers.AL - (int16) Work8 + (int16) CheckCarry() - 1; - +static inline void CMP (uint8 val) +{ + int16 Int16 = (int16) Registers.AL - (int16) val; ICPU._Carry = Int16 >= 0; - if ((Registers.AL ^ Work8) & - (Registers.AL ^ (uint8) Int16) & 0x80) - SetOverflow (); - else - ClearOverflow (); - Registers.AL = (uint8) Int16; - SetZN (Registers.AL); - } + SetZN((uint8) Int16); } -STATIC inline void STA16 (uint32 OpAddress, enum s9xwrap_t w) { - S9xSetWord (Registers.A.W, OpAddress, w); - OpenBus = Registers.AH; +static inline void CPX (uint16 val) +{ + int32 Int32 = (int32) Registers.X.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); } -STATIC inline void STA8 (uint32 OpAddress) { - S9xSetByte (Registers.AL, OpAddress); - OpenBus = Registers.AL; +static inline void CPX (uint8 val) +{ + int16 Int16 = (int16) Registers.XL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); } -STATIC inline void STX16 (uint32 OpAddress, enum s9xwrap_t w) { - S9xSetWord (Registers.X.W, OpAddress, w); - OpenBus = Registers.XH; +static inline void CPY (uint16 val) +{ + int32 Int32 = (int32) Registers.Y.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); } -STATIC inline void STX8 (uint32 OpAddress) { - S9xSetByte (Registers.XL, OpAddress); - OpenBus = Registers.XL; +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; + + if ((Registers.A.W ^ Work16) & (Registers.A.W ^ (uint16) Int32) & 0x8000) + SetOverflow(); + else + 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; + + 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); + } + 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); + } +} + +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 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 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 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 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 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 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 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 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 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; -} #endif diff --git a/source/snes9x/cpuops.cpp b/source/snes9x/cpuops.cpp index d55e321..e50b78f 100644 --- a/source/snes9x/cpuops.cpp +++ b/source/snes9x/cpuops.cpp @@ -159,1369 +159,1382 @@ **********************************************************************************/ - - -/*****************************************************************************/ -/* CPU-S9xOpcodes.CPP */ -/* This file contains all the opcodes */ -/*****************************************************************************/ - #include "snes9x.h" #include "memmap.h" -#include "s9xdebug.h" -#include "missing.h" -#ifdef DEBUGGER +#include "apu/apu.h" + // for "Magic WDM" features -#include "display.h" +#ifdef DEBUGGER #include "snapshot.h" +#include "display.h" +#include "debug.h" +#include "missing.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 (95E1, DirectIndexedXE1, WRAP_BANK, STA) -wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) -wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) -wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) +wOP8 (85M1, Direct, WRAP_BANK, STA) +wOP16(85M0, Direct, WRAP_BANK, STA) +wOPM (85Slow, DirectSlow, 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 (95E1, DirectIndexedXE1, WRAP_BANK, STA) +wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) +wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) +wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, 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 (92E1, DirectIndirectE1, WRAP_NONE, STA) +wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) +wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) +wOPM (92Slow, DirectIndirectSlow, 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 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) +wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) -wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) -wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) -wOPM (87Slow, DirectIndirectLongSlow, 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 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) -wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) -wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) +wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) +wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) +wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) -wOP8 (8DM1, Absolute, WRAP_NONE, STA) -wOP16(8DM0, Absolute, WRAP_NONE, STA) -wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) +wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOPM (97Slow, DirectIndirectIndexedLongSlow, 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 (8DM1, Absolute, WRAP_NONE, STA) +wOP16(8DM0, Absolute, WRAP_NONE, STA) +wOPM (8DSlow, AbsoluteSlow, 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 (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 (8FM1, AbsoluteLong, WRAP_NONE, STA) -wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) -wOPM (8FSlow, AbsoluteLongSlow, 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 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) -wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) -wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) +wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) +wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) +wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) -wOP8 (83M1, StackRelative, WRAP_NONE, STA) -wOP16(83M0, StackRelative, WRAP_NONE, STA) -wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) +wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) -wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) -wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) -wOPM (93Slow, StackRelativeIndirectIndexedSlow, 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) /* 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() + +inline void CPUShutdown (void) { if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) { @@ -1543,554 +1556,665 @@ inline void CPUShutdown() CPU.WaitCounter--; } } + #else -inline void CPUShutdown() + +inline void CPUShutdown (void) { 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); - missing.decimal_mode = 1; +// SED +static void OpF8 (void) +{ + SetDecimal(); + AddCycles(ONE_CYCLE); +#ifdef DEBUGGER + missing.decimal_mode = 1; +#endif } -/* 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++; @@ -2101,1540 +2225,1774 @@ 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: 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 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 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); - uint8 A1 = ICPU._Carry; - uint8 A2 = Registers.PH; - ICPU._Carry = A2 & 1; - Registers.PH = A1; +static void OpFB (void) +{ + AddCycles(ONE_CYCLE); - if (CheckEmulation()) { - SetFlags (MemoryFlag | IndexFlag); - Registers.SH = 1; - missing.emulate6502 = 1; - } - if (CheckIndex ()) { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); + 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(); } -/*****************************************************************************/ - /* 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 -#ifndef SA1_OPCODES - CPU.BRKTriggered = TRUE; -#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 (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; - if (!CheckEmulation()) { - PushB (Registers.PB); - PushW (Registers.PCw + 1); - S9xPackStatus (); - PushB (Registers.PL); - OpenBus = Registers.PL; - ClearDecimal (); - SetIRQ (); + uint16 addr; - addr = S9xGetWord (0xFFE4); - } else { - PushWE (Registers.PCw + 1); - S9xPackStatus (); - PushBE (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 (0xFFF4); - } - S9xSetPCBase(addr); - OpenBus = addr>>8; + 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; } -/*****************************************************************************/ - /* 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; - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); +static void Op54X1 (void) +{ + uint32 SrcBank; - S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), - ICPU.ShiftedDB + Registers.Y.W); + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); - Registers.XL++; - Registers.YL++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - AddCycles(TWO_CYCLES); + Registers.XL++; + Registers.YL++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + 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++; - } - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; + if (CheckIndex()) + { + Registers.XL++; + Registers.YL++; + } + else + { + Registers.X.W++; + Registers.Y.W++; + } - AddCycles(TWO_CYCLES); + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + 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--; - } - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; + if (CheckIndex()) + { + Registers.XL--; + Registers.YL--; + } + else + { + Registers.X.W--; + Registers.Y.W--; + } - AddCycles(TWO_CYCLES); + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + 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; - 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 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(); } -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); - missing.emulate6502 = 1; - } - if (CheckIndex ()) { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ(); */ + 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(); } -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); - missing.emulate6502 = 1; - } - if (CheckIndex ()) { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + 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); - missing.emulate6502 = 1; - } - if (CheckIndex ()) { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + 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); - if (CheckIndex ()) { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ(); */ +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(); } -/*****************************************************************************/ +/* 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) -#ifdef DEBUGGER -extern FILE *trace; -extern FILE *trace2; -#endif -static void Op42 (void) { -#ifdef DEBUGGER - uint8 byte = (uint8) -#endif - 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; -#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]; +/* WDM (Reserved S9xOpcode) ************************************************ */ - _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; +#ifdef DEBUGGER +extern FILE *trace, *trace2; +#endif - default: - break; - } +static void Op42 (void) +{ +#ifdef DEBUGGER + uint8 byte = (uint8) S9xGetWord(Registers.PBPC); +#else + S9xGetWord(Registers.PBPC); +#endif + 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; + + #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 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; + } #endif } -/*****************************************************************************/ +/* CPU-S9xOpcodes Definitions ************************************************/ -/*****************************************************************************/ -/* 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 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 06d8c16..49c7701 100644 --- a/source/snes9x/cpuops.h +++ b/source/snes9x/cpuops.h @@ -159,16 +159,14 @@ **********************************************************************************/ - - #ifndef _CPUOPS_H_ #define _CPUOPS_H_ -void S9xOpcode_NMI (); -void S9xOpcode_IRQ (); + +void S9xOpcode_NMI (void); +void S9xOpcode_IRQ (void); #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 c0ee542..7d13764 100644 --- a/source/snes9x/crosshairs.cpp +++ b/source/snes9x/crosshairs.cpp @@ -159,487 +159,508 @@ **********************************************************************************/ - -#ifdef HAVE_CONFIG_H - #include -#endif -#include -#include - #ifdef HAVE_LIBPNG #include #endif - #include "port.h" #include "crosshairs.h" -static char *crosshairs[32]={ - "` " /* Crosshair 0 (no image) */ - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " ", +static const 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; - 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; - } +bool S9xLoadCrosshairFile (int idx, const char *filename) +{ + if (idx < 1 || idx > 31) + return (false); - if((fp=fopen(filename, "rb"))==NULL){ - fprintf(stderr, "S9xLoadCrosshairFile: Couldn't open "); - perror(filename); - free(s); - 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); + } - 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; - } - 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; - } + 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); + } - png_init_io(png_ptr, fp); - png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); + 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_uint_32 width, height; - int bit_depth, color_type; + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_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(bit_depth==16) - png_set_strip_16(png_ptr); + png_uint_32 width, height; + int bit_depth, color_type; - 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_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); + } - int num_palette=0, num_trans=0; - int fgcol=-1, bgcol=-1, transcol=-1; - png_color *pngpal; - png_byte *trans; + if (bit_depth == 16) + png_set_strip_16(png_ptr); - png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette); - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + 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(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_color *pngpal; + png_byte *trans; + int num_palette = 0, num_trans = 0; + int transcol = -1, fgcol = -1, bgcol = -1; - 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; - } - } + png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette); + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); - 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; - } + 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_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 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; + } - 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 + 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 #endif - { - 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); + { + 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); + } - if(crosshairs[idx]!=NULL && crosshairs[idx][0]!='`') free(crosshairs[idx]); - crosshairs[idx]=s; - return true; + 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); } -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 b9c7ac5..b246178 100644 --- a/source/snes9x/crosshairs.h +++ b/source/snes9x/crosshairs.h @@ -159,62 +159,59 @@ **********************************************************************************/ +#ifndef _CROSSHAIRS_H_ +#define _CROSSHAIRS_H_ -#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 '.'. -/* - * 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); +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. - */ -const char *S9xGetCrosshair(int idx); +// Return the specified crosshair. Woo-hoo. +// char * to a 225-byte string, with '#' marking foreground, '.' marking background, +// and anything else transparent. -/* - * 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 +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 }; -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 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); +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); #endif diff --git a/source/snes9x/data.cpp b/source/snes9x/data.cpp deleted file mode 100644 index 6c7b563..0000000 --- a/source/snes9x/data.cpp +++ /dev/null @@ -1,613 +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 "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 c571d71..79b884a 100644 --- a/source/snes9x/display.h +++ b/source/snes9x/display.h @@ -159,65 +159,63 @@ **********************************************************************************/ - - #ifndef _DISPLAY_H_ #define _DISPLAY_H_ -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, +enum s9x_getdirtype +{ + DEFAULT_DIR = 0, + HOME_DIR, + ROMFILENAME_DIR, + ROM_DIR, + SRAM_DIR, + SNAPSHOT_DIR, + SCREENSHOT_DIR, + SPC_DIR, CHEAT_DIR, - PACK_DIR, + IPS_DIR, BIOS_DIR, - LOG_DIR + LOG_DIR, + LAST_DIR }; -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 + +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 *); #endif - diff --git a/source/snes9x/dma.cpp b/source/snes9x/dma.cpp index bc4d107..a29628f 100644 --- a/source/snes9x/dma.cpp +++ b/source/snes9x/dma.cpp @@ -159,61 +159,54 @@ **********************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif - #include "snes9x.h" #include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "missing.h" #include "dma.h" -#include "apu.h" -#include "gfx.h" -#include "sa1.h" -#include "spc7110.h" +#include "apu/apu.h" #include "sdd1emu.h" +#include "spc7110emu.h" +#ifdef DEBUGGER +#include "missing.h" +#endif 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; - #if 1 - //printf("HDMA and DMA use the same channel %d!\n", dma_channel); + #ifdef DEBUGGER + 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]; @@ -247,7 +240,8 @@ bool8 S9xDoDMA (uint8 Channel) { CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; - return FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + return (FALSE); } } @@ -261,17 +255,18 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; - return TRUE; + CPU.CurrentDMAorHDMAChannel = -1; + 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); @@ -295,70 +290,21 @@ bool8 S9xDoDMA (uint8 Channel) // Hacky support for pre-decompressed S-DD1 data inc = !d->AAddressDecrement ? 1 : -1; - if (Settings.SDD1Pack) // XXX: Settings.SDD1Pack == true -> on-the-fly decoding. Weird. + uint8 *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); + if (in_ptr) { - // 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; + in_ptr += d->AAddress; + SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); } + #ifdef DEBUGGER else { - // 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)]; - - 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; - } - } + 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; } Memory.FillRAM[0x4801] = 0; @@ -366,45 +312,20 @@ bool8 S9xDoDMA (uint8 Channel) // SPC7110 - uint8 *spc7110_dma = NULL; - bool8 s7_wrap = FALSE; + uint8 *spc7110_dma = NULL; - if (Settings.SPC7110) + if (Settings.SPC7110) { if (d->AAddress == 0x4800 || d->ABank == 0x50) { - uint32 i, j; + spc7110_dma = new uint8[d->TransferBytes]; + for (int i = 0; i < d->TransferBytes; i++) + spc7110_dma[i] = s7emu.decomp.read(); - 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); + int32 icount = s7emu.r4809 | (s7emu.r480a << 8); icount -= d->TransferBytes; - s7r.reg4809 = 0x00ff & icount; - s7r.reg480A = (0xff00 & icount) >> 8; - - s7r.bank50Internal += d->TransferBytes; - s7r.bank50Internal %= DECOMP_BUFFER_SIZE; + s7emu.r4809 = icount & 0x00ff; + s7emu.r480a = (icount & 0xff00) >> 8; inc = 1; d->AAddress -= count; @@ -428,7 +349,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 = GetBasePointer((d->ABank << 16) + addr); + uint8 *base = S9xGetBasePointer((d->ABank << 16) + addr); if (!base) { sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); @@ -453,96 +374,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) - { - uint8 *line = base + (num_chars - char_count) * 2; - for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 2) + 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 *q = line; - for (int32 l = 0; l < 8; l++, q += bytes_per_line) + uint8 *line = base + (num_chars - char_count) * 2; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 2) { - for (int32 b = 0; b < 2; b++) + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) { - 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); + 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; } - - 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; } } } @@ -580,7 +501,7 @@ bool8 S9xDoDMA (uint8 Channel) // CPU -> PPU int32 b = 0; uint16 p = d->AAddress; - uint8 *base = GetBasePointer((d->ABank << 16) + d->AAddress); + uint8 *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); bool8 inWRAM_DMA; int32 rem = count; @@ -622,7 +543,8 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; \ CPU.InDMAorHDMA = FALSE; \ CPU.InWRAMDMAorHDMA = FALSE; \ - return FALSE; \ + CPU.CurrentDMAorHDMAChannel = -1; \ + return (FALSE); \ } while (1) @@ -652,7 +574,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); @@ -660,7 +582,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; @@ -684,7 +606,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = S9xGetByte((d->ABank << 16) + p); @@ -696,7 +618,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2100 + d->BAddress); UPDATE_COUNTERS; @@ -706,7 +628,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -716,7 +638,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -734,7 +656,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = S9xGetByte((d->ABank << 16) + p); @@ -746,7 +668,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -756,7 +678,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2102 + d->BAddress); UPDATE_COUNTERS; @@ -766,7 +688,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = S9xGetByte((d->ABank << 16) + p); S9xSetPPU(Work, 0x2103 + d->BAddress); UPDATE_COUNTERS; @@ -794,114 +716,114 @@ bool8 S9xDoDMA (uint8 Channel) { switch (d->BAddress) { - 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) - { + case 0x04: // OAMDATA do { Work = *(base + p); - REGISTER_2118_linear(Work); + REGISTER_2104(Work); UPDATE_COUNTERS; CHECK_SOUND(); } while (--count > 0); - } - else - { + + 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 do { Work = *(base + p); - REGISTER_2118_tile(Work); + REGISTER_2122(Work); UPDATE_COUNTERS; CHECK_SOUND(); } while (--count > 0); - } - break; + break; - case 0x19: // VMDATAH - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif - if (!PPU.VMA.FullGraphicCount) - { + 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); - REGISTER_2119_linear(Work); + S9xSetPPU(Work, 0x2100 + d->BAddress); 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 - 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; + break; } } else @@ -917,7 +839,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: while (count > 1) { Work = *(base + p); @@ -925,7 +847,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = *(base + p); REGISTER_2119_linear(Work); UPDATE_COUNTERS; @@ -948,7 +870,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: while (count > 1) { Work = *(base + p); @@ -956,7 +878,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = *(base + p); REGISTER_2119_tile(Work); UPDATE_COUNTERS; @@ -981,7 +903,7 @@ bool8 S9xDoDMA (uint8 Channel) // DMA mode 1 general case switch (b) { - default: + default: while (count > 1) { Work = *(base + p); @@ -989,7 +911,7 @@ bool8 S9xDoDMA (uint8 Channel) UPDATE_COUNTERS; count--; - case 1: + case 1: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -1014,7 +936,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = *(base + p); @@ -1026,7 +948,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = *(base + p); S9xSetPPU(Work, 0x2100 + d->BAddress); UPDATE_COUNTERS; @@ -1036,7 +958,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -1046,7 +968,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -1064,7 +986,7 @@ bool8 S9xDoDMA (uint8 Channel) { switch (b) { - default: + default: do { Work = *(base + p); @@ -1076,7 +998,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 1: + case 1: Work = *(base + p); S9xSetPPU(Work, 0x2101 + d->BAddress); UPDATE_COUNTERS; @@ -1086,7 +1008,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 2: + case 2: Work = *(base + p); S9xSetPPU(Work, 0x2102 + d->BAddress); UPDATE_COUNTERS; @@ -1096,7 +1018,7 @@ bool8 S9xDoDMA (uint8 Channel) break; } - case 3: + case 3: Work = *(base + p); S9xSetPPU(Work, 0x2103 + d->BAddress); UPDATE_COUNTERS; @@ -1121,7 +1043,7 @@ bool8 S9xDoDMA (uint8 Channel) if (rem <= 0) break; - base = GetBasePointer((d->ABank << 16) + d->AAddress); + base = S9xGetBasePointer((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))); @@ -1142,7 +1064,8 @@ bool8 S9xDoDMA (uint8 Channel) CPU.InDMA = FALSE; \ CPU.InDMAorHDMA = FALSE; \ CPU.InWRAMDMAorHDMA = FALSE; \ - return FALSE; \ + CPU.CurrentDMAorHDMAChannel = -1; \ + return (FALSE); \ } if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) @@ -1152,107 +1075,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); - 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) - { + 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; + 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; } CHECK_SOUND(); @@ -1266,96 +1189,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); - 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) - { + case 0: + case 2: + case 6: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); UPDATE_COUNTERS; count--; - } - break; + 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; } CHECK_SOUND(); @@ -1363,13 +1286,9 @@ 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 + 30; + Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; if (Timings.NMITriggerPos >= Timings.H_Max) Timings.NMITriggerPos -= Timings.H_Max; } @@ -1377,11 +1296,11 @@ bool8 S9xDoDMA (uint8 Channel) // Release the memory used in SPC7110 DMA if (Settings.SPC7110) { - if (spc7110_dma && s7_wrap) + if (spc7110_dma) delete [] spc7110_dma; } -#if 1 +#if 0 // 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); @@ -1390,387 +1309,464 @@ 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){ - //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); - } + for (uint8 mask = 1; mask; mask <<= 1, p++, d++) + { + if (byte & mask) + { + CPU.InWRAMDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = d; - 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->HDMAIndirectAddressing) + { + ShiftedIBank = (p->IndirectBank << 16); + IAddr = p->IndirectAddress; + } + else + { + ShiftedIBank = (p->ABank << 16); + IAddr = p->Address; + } -#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 (!HDMAMemPointers[d]) + HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr); - 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]; - } - } + 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; + } + } - 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; - } - } - } + #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 - S9xAPUExecute(); + if (!p->ReverseTransfer) + { + if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) + { + // HDMA REALLY-SLOW PATH + HDMAMemPointers[d] = NULL; - CPU.InHDMA = FALSE; + #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.InDMAorHDMA = CPU.InDMA; CPU.InWRAMDMAorHDMA = temp; + CPU.CurrentDMAorHDMAChannel = tmpch; - return (byte); + return (byte); } -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; +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; DMA[d].UnusedBit43x0 = 1; - } + } } diff --git a/source/snes9x/dma.h b/source/snes9x/dma.h index 38c5666..396811e 100644 --- a/source/snes9x/dma.h +++ b/source/snes9x/dma.h @@ -159,17 +159,37 @@ **********************************************************************************/ - - #ifndef _DMA_H_ #define _DMA_H_ -START_EXTERN_C -void S9xResetDMA (); -uint8 S9xDoHDMA (uint8); -void S9xStartHDMA (); +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); -END_EXTERN_C +void S9xStartHDMA (void); +uint8 S9xDoHDMA (uint8); +void S9xResetDMA (void); #endif - diff --git a/source/snes9x/3d.h b/source/snes9x/dsp.cpp similarity index 83% rename from source/snes9x/3d.h rename to source/snes9x/dsp.cpp index 0122ce2..49eba75 100644 --- a/source/snes9x/3d.h +++ b/source/snes9x/dsp.cpp @@ -159,67 +159,55 @@ **********************************************************************************/ - - -#ifndef _3D_H_ -#define _3D_H_ - -#if defined(USE_OPENGL) -#include -#include - -#ifdef __linux__ -#include +#include "snes9x.h" +#include "memmap.h" +#ifdef DEBUGGER +#include "missing.h" #endif -typedef struct +uint8 (*GetDSP) (uint16) = NULL; +void (*SetDSP) (uint8, uint16) = NULL; + + +void S9xResetDSP (void) { - bool8 packed_pixels_extension_present; - bool8 draw_cube; - uint32 version; - // Texture format - GLint internal_format; - GLint format; - GLint type; + memset(&DSP1, 0, sizeof(DSP1)); + DSP1.waiting4command = TRUE; + DSP1.first_parameter = 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(&DSP2, 0, sizeof(DSP2)); + DSP2.waiting4command = TRUE; -extern OpenGLData OpenGL; + memset(&DSP3, 0, sizeof(DSP3)); + DSP3_Reset(); -bool8 S9xOpenGLInit (); -bool8 S9xOpenGLInit2 (); -void S9xOpenGLPutImage (int width, int height); -void S9xOpenGLDeinit (); + memset(&DSP4, 0, sizeof(DSP4)); + DSP4.waiting4command = TRUE; +} -#endif - -#ifdef USE_GLIDE -#include - -typedef struct +uint8 S9xGetDSP (uint16 address) { - 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 (); +#ifdef DEBUGGER + if (Settings.TraceDSP) + { + sprintf(String, "DSP read: 0x%04X", address); + S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); + } #endif + return ((*GetDSP)(address)); +} + +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 + (*SetDSP)(byte, address); +} diff --git a/source/snes9x/dsp.h b/source/snes9x/dsp.h new file mode 100644 index 0000000..24cc62e --- /dev/null +++ b/source/snes9x/dsp.h @@ -0,0 +1,602 @@ +/********************************************************************************** + 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 2ce54c9..f6be5c8 100644 --- a/source/snes9x/dsp1.cpp +++ b/source/snes9x/dsp1.cpp @@ -158,897 +158,1719 @@ 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 - if (Settings.TraceDSP) - { - sprintf (String, "DSP read: 0x%04X", address); - S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); - } +//#define DebugDSP1 #endif - 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); - } +#ifdef DebugDSP1 +static FILE *LogFile = NULL; #endif - (*SetDSP)(byte, address); - //DSP1SetByte(byte, address); + +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); } -void DSP1SetByte(uint8 byte, uint16 address) +static void Start_Log (void) { - if (address < DSP1.boundary) - { -// if ((address & 1) == 0) -// { - if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) + 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) { 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; -// printf("Op%02X\n",byte); - // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a + #ifdef DEBUGGER + //printf("OP%02X\n",byte); + #endif + 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; - // 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; + 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; } - 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) -// { -// } + else + if (DSP1.first_parameter && (DSP1.in_count != 0 || (DSP1.in_count == 0 && DSP1.in_index == 0))) + ; 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 0x00: // Multiple - Op00Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op00Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + case 0x1f: + DSP1.out_count = 2048; + 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; + 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; } } } } - } -} - -uint8 DSP1GetByte(uint16 address) -{ - uint8 t; - if (address < DSP1.boundary) - { - if (DSP1.out_count) - { - //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) - { - 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; - } - } - } - DSP1.waiting4command = TRUE; - //} - } - else - { - // 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 DSP1GetByte (uint16 address) { - uint8 t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { + uint8 t; + + if (address < DSP0.boundary) + { if (DSP1.out_count) { - t = (uint8) DSP1.output [DSP1.out_index]; + t = (uint8) DSP1.output[DSP1.out_index]; + DSP1.out_index++; - if(DSP1.out_count==DSP1.out_index) - DSP1.out_count=0; + + if (--DSP1.out_count == 0) + { + if (DSP1.command == 0x1a || DSP1.command == 0x0a) + { + 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 == 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; } 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; + } + else + t = 0x80; + + return (t); } diff --git a/source/snes9x/dsp1emu.c.inc b/source/snes9x/dsp1emu.c.inc deleted file mode 100644 index cf44240..0000000 --- a/source/snes9x/dsp1emu.c.inc +++ /dev/null @@ -1,1394 +0,0 @@ -/* -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/dsp2emu.c.inc b/source/snes9x/dsp2.cpp similarity index 57% rename from source/snes9x/dsp2emu.c.inc rename to source/snes9x/dsp2.cpp index 7512b2d..9f004ed 100644 --- a/source/snes9x/dsp2emu.c.inc +++ b/source/snes9x/dsp2.cpp @@ -159,20 +159,84 @@ **********************************************************************************/ +#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); - -uint16 DSP2Op09Word1=0; -uint16 DSP2Op09Word2=0; -bool DSP2Op05HasLen=false; -int DSP2Op05Len=0; -bool DSP2Op06HasLen=false; -int DSP2Op06Len=0; -uint8 DSP2Op05Transparent=0; - -void DSP2_Op05 () +// 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) { - uint8 color; // Overlay bitmap with transparency. // Input: // @@ -198,136 +262,52 @@ void DSP2_Op05 () // size = 0. I don't think it's worth implementing this quirk unless it's // proven necessary. - int n; - unsigned char c1; - unsigned char c2; - unsigned char *p1 = DSP1.parameters; - unsigned char *p2 = &DSP1.parameters[DSP2Op05Len]; - unsigned char *p3 = DSP1.output; + uint8 color; + uint8 c1, c2; + uint8 *p1 = DSP2.parameters; + uint8 *p2 = DSP2.parameters + DSP2.Op05Len; + uint8 *p3 = DSP2.output; - color = DSP2Op05Transparent&0x0f; + color = DSP2.Op05Transparent & 0x0f; - for( n = 0; n < DSP2Op05Len; n++ ) + for (int32 n = 0; n < DSP2.Op05Len; 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); } } -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 () +// reverse bitmap +static void DSP2_Op06 (void) { // Input: // size // bitmap - int i, j; - - for ( i = 0, j = DSP2Op06Len - 1; i < DSP2Op06Len; i++, j-- ) - { - DSP1.output[j] = (DSP1.parameters[i] << 4) | (DSP1.parameters[i] >> 4); - } + for (int32 i = 0, j = DSP2.Op06Len - 1; i < DSP2.Op06Len; i++, j--) + DSP2.output[j] = (DSP2.parameters[i] << 4) | (DSP2.parameters[i] >> 4); } -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() +// multiply +static void DSP2_Op09 (void) { - // Overload's algorithm - use this unless doing hardware testing + DSP2.Op09Word1 = DSP2.parameters[0] | (DSP2.parameters[1] << 8); + DSP2.Op09Word2 = DSP2.parameters[2] | (DSP2.parameters[3] << 8); - // 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]; +#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 } -#else - -void DSP2_Op0D() +// scale bitmap +static void DSP2_Op0D (void) { // Bit accurate hardware algorithm - uses fixed point math // This should match the DSP2 Op0D output exactly @@ -343,74 +323,198 @@ void DSP2_Op0D() // 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]; - 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 + if (DSP2.Op0DInLen <= DSP2.Op0DOutLen) + multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 else - multiplier = (DSP2Op0DInLen << 17) / ((DSP2Op0DOutLen<<1) + 1); + multiplier = (DSP2.Op0DInLen << 17) / ((DSP2.Op0DOutLen << 1) + 1); pixloc = 0; - for ( i=0; i < DSP2Op0DOutLen * 2; i++ ) - { - j = pixloc >> 16; - if ( j & 1 ) - pixelarray[i] = DSP1.parameters[j>>1] & 0x0f; + for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) + { + int32 j = pixloc >> 16; + + if (j & 1) + pixelarray[i] = DSP2.parameters[j >> 1] & 0x0f; else - pixelarray[i] = (DSP1.parameters[j>>1] & 0xf0) >> 4; + pixelarray[i] = (DSP2.parameters[j >> 1] & 0xf0) >> 4; pixloc += multiplier; } - for ( i=0; i < DSP2Op0DOutLen; i++ ) - DSP1.output[i] = ( pixelarray[i<<1] << 4 ) | pixelarray[(i<<1)+1]; + for (int32 i = 0; i < DSP2.Op0DOutLen; i++) + DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; } -#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() +/* +static void DSP2_Op0D (void) { - // 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). + // Overload's algorithm - use this unless doing hardware testing - float multiplier; - float pixloc; - int i, j; - uint8 pixelarray[512]; + // 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 - if (DSP2Op0DInLen <= DSP2Op0DOutLen) - multiplier = (float) 1.0; - else - multiplier = (float) ((DSP2Op0DInLen * 2.0) / (DSP2Op0DOutLen * 2.0 + 1.0)); + int32 pixel_offset; + uint8 pixelarray[512]; - pixloc = 0.0; - for ( i=0; i < DSP2Op0DOutLen * 2; i++ ) + for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) { - // j = (int)(i * multiplier); - j = (int) pixloc; + pixel_offset = (i * DSP2.Op0DInLen) / DSP2.Op0DOutLen; - if ( j & 1 ) - pixelarray[i] = DSP1.parameters[j>>1] & 0x0f; + if ((pixel_offset & 1) == 0) + pixelarray[i] = DSP2.parameters[pixel_offset >> 1] >> 4; else - pixelarray[i] = (DSP1.parameters[j>>1] & 0xf0) >> 4; - - pixloc += multiplier; // use an add in the loop instead of multiply to increase loop speed + pixelarray[i] = DSP2.parameters[pixel_offset >> 1] & 0x0f; } - for ( i=0; i < DSP2Op0DOutLen; i++ ) - DSP1.output[i] = ( pixelarray[i<<1] << 4 ) | pixelarray[(i<<1)+1]; + 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; + } + } + } } -#endif +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; + } + else + t = 0x80; + + return (t); +} diff --git a/source/snes9x/dsp3emu.c.inc b/source/snes9x/dsp3.cpp similarity index 52% rename from source/snes9x/dsp3emu.c.inc rename to source/snes9x/dsp3.cpp index 06b91c8..a8614c4 100644 --- a/source/snes9x/dsp3emu.c.inc +++ b/source/snes9x/dsp3.cpp @@ -159,16 +159,13 @@ **********************************************************************************/ +#include "snes9x.h" +#include "memmap.h" +static void (*SetDSP3) (void); -#ifndef __cplusplus -//C++ in C -typedef unsigned char bool; -#define true 1 -#define false 0 -#endif - -uint16 DSP3_DataROM[1024] = { +static const 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, @@ -299,1004 +296,957 @@ uint16 DSP3_DataROM[1024] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; -void (*SetDSP3)(); -void DSP3_Command(); +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); -uint16 DSP3_DR; -uint16 DSP3_SR; -uint16 DSP3_MemoryIndex; -void DSP3_Reset() +void DSP3_Reset (void) { - DSP3_DR = 0x0080; - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_Command; + DSP3.DR = 0x0080; + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_Command; } -void DSP3_MemorySize() +/* +static void DSP3_MemorySize (void) { - DSP3_DR = 0x0300; + DSP3.DR = 0x0300; + SetDSP3 = &DSP3_Reset; +} +*/ + +static void DSP3_TestMemory (void) +{ + DSP3.DR = 0x0000; SetDSP3 = &DSP3_Reset; } -void DSP3_TestMemory() +static void DSP3_DumpDataROM (void) { - DSP3_DR = 0x0000; - SetDSP3 = &DSP3_Reset; -} - -void DSP3_DumpDataROM() -{ - DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++]; - if (DSP3_MemoryIndex == 1024) + DSP3.DR = DSP3_DataROM[DSP3.MemoryIndex++]; + if (DSP3.MemoryIndex == 1024) SetDSP3 = &DSP3_Reset; } -void DSP3_MemoryDump() +static void DSP3_MemoryDump (void) { - DSP3_MemoryIndex = 0; + DSP3.MemoryIndex = 0; SetDSP3 = &DSP3_DumpDataROM; DSP3_DumpDataROM(); } -int16 DSP3_WinLo; -int16 DSP3_WinHi; - -void DSP3_OP06() +static void DSP3_OP06 (void) { - DSP3_WinLo = (uint8)(DSP3_DR); - DSP3_WinHi = (uint8)(DSP3_DR >> 8); + DSP3.WinLo = (uint8) (DSP3.DR); + DSP3.WinHi = (uint8) (DSP3.DR >> 8); DSP3_Reset(); } -void DSP3_OP03() +static void DSP3_OP03 (void) { - 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; } -int16 DSP3_AddLo; -int16 DSP3_AddHi; - -void DSP3_OP07_B() +static void DSP3_OP07_B (void) { - int16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1); - DSP3_DR = Ofs >> 1; + int16 Ofs = (DSP3.WinLo * DSP3.AddHi << 1) + (DSP3.AddLo << 1); + + DSP3.DR = Ofs >> 1; SetDSP3 = &DSP3_Reset; } -void DSP3_OP07_A() +static void DSP3_OP07_A (void) { - 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; } -void DSP3_OP07() +static void DSP3_OP07 (void) { - 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; } -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; - -uint16 DSP3_X; -uint16 DSP3_Y; - -void DSP3_Coordinate() +static void DSP3_Coordinate (void) { - DSP3_Index++; + DSP3.Index++; - switch (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; - } } } -uint8 DSP3_Bitmap[8]; -uint8 DSP3_Bitplane[8]; -uint16 DSP3_BMIndex; -uint16 DSP3_BPIndex; -uint16 DSP3_Count; - -void DSP3_Convert_A() +static void DSP3_Convert_A (void) { - 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) { - short i, j; - for (i=0; i < 8; i++) - for (j=0; j < 8; j++) + for (int i = 0; i < 8; i++) + { + for (int 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; } } } -void DSP3_Convert() +static void DSP3_Convert (void) { - DSP3_Count = DSP3_DR; - DSP3_BMIndex = 0; + DSP3.Count = DSP3.DR; + DSP3.BMIndex = 0; SetDSP3 = &DSP3_Convert_A; } -bool DSP3_GetBits(uint8 Count) +static bool8 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); } -void DSP3_Decode_Data() +static void DSP3_Decode_Data (void) { - 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; } -void DSP3_Decode_Tree() +static void DSP3_Decode_Tree (void) { - 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(); } -void DSP3_Decode_Symbols() +static void DSP3_Decode_Symbols (void) { - 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(); } -void DSP3_Decode_A() +static void DSP3_Decode_A (void) { - 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; } -void DSP3_Decode() +static void DSP3_Decode (void) { - 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 -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() +static void DSP3_OP3E (void) { - op3e_x = (uint8)(DSP3_DR & 0x00ff); - op3e_y = (uint8)((DSP3_DR & 0xff00)>>8); + DSP3. op3e_x = (uint8) (DSP3.DR & 0x00ff); + DSP3. op3e_y = (uint8) ((DSP3.DR & 0xff00) >> 8); DSP3_OP03(); - op1e_terrain[ DSP3_DR ] = 0x00; - op1e_cost[ DSP3_DR ] = 0xff; - op1e_weight[ DSP3_DR ] = 0; + DSP3.op1e_terrain[DSP3.DR] = 0x00; + DSP3.op1e_cost[DSP3.DR] = 0xff; + DSP3.op1e_weight[DSP3.DR] = 0; - op1e_max_search_radius = 0; - op1e_max_path_radius = 0; + DSP3.op1e_max_search_radius = 0; + DSP3.op1e_max_path_radius = 0; } -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() +static void DSP3_OP1E (void) { - int lcv; + DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); + DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); - op1e_min_radius = (uint8)(DSP3_DR & 0x00ff); - op1e_max_radius = (uint8)((DSP3_DR & 0xff00)>>8); + if (DSP3.op1e_min_radius == 0) + DSP3.op1e_min_radius++; - if( op1e_min_radius == 0 ) - op1e_min_radius++; + if (DSP3.op1e_max_search_radius >= DSP3.op1e_min_radius) + DSP3.op1e_min_radius = DSP3.op1e_max_search_radius + 1; - if( op1e_max_search_radius >= op1e_min_radius ) - op1e_min_radius = op1e_max_search_radius+1; + if (DSP3.op1e_max_radius > DSP3.op1e_max_search_radius) + DSP3.op1e_max_search_radius = DSP3.op1e_max_radius; - if( op1e_max_radius > op1e_max_search_radius ) - op1e_max_search_radius = op1e_max_radius; + 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_lcv_turns = 6; + DSP3.op1e_turn = 0; - op1e_lcv_turns = 6; - op1e_turn = 0; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_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 ); + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); DSP3_OP1E_A(); } -void DSP3_OP1E_A() +static void DSP3_OP1E_A (void) { - int lcv; + if (DSP3.op1e_lcv_steps == 0) + { + DSP3.op1e_lcv_radius++; - if( op1e_lcv_steps == 0 ) { - op1e_lcv_radius++; + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; - op1e_lcv_steps = op1e_lcv_radius; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_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 ); + for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); } - if( op1e_lcv_radius > op1e_max_radius ) { - op1e_turn++; - op1e_lcv_turns--; + if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) + { + DSP3.op1e_turn++; + DSP3.op1e_lcv_turns--; - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; - op1e_x = op3e_x; - op1e_y = op3e_y; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); } - if( op1e_lcv_turns == 0 ) { - DSP3_DR = 0xffff; - DSP3_SR = 0x0080; + if (DSP3.op1e_lcv_turns == 0) + { + DSP3.DR = 0xffff; + DSP3.SR = 0x0080; SetDSP3 = &DSP3_OP1E_B; return; } - DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); DSP3_OP03(); - op1e_cell = DSP3_DR; + DSP3.op1e_cell = DSP3.DR; - DSP3_SR = 0x0080; + DSP3.SR = 0x0080; SetDSP3 = &DSP3_OP1E_A1; } -void DSP3_OP1E_A1() +static void DSP3_OP1E_A1 (void) { - DSP3_SR = 0x0084; + DSP3.SR = 0x0084; SetDSP3 = &DSP3_OP1E_A2; } -void DSP3_OP1E_A2() +static void DSP3_OP1E_A2 (void) { - op1e_terrain[ op1e_cell ] = (uint8)(DSP3_DR & 0x00ff); + DSP3.op1e_terrain[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); - DSP3_SR = 0x0084; + DSP3.SR = 0x0084; SetDSP3 = &DSP3_OP1E_A3; } -void DSP3_OP1E_A3() +static void DSP3_OP1E_A3 (void) { - op1e_cost[ op1e_cell ] = (uint8)(DSP3_DR & 0x00ff); + DSP3.op1e_cost[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); - 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; + 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]; } + else + DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; - DSP3_OP1E_D( (int16)(op1e_turn+2), &op1e_x, &op1e_y ); - op1e_lcv_steps--; + DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); + DSP3.op1e_lcv_steps--; - DSP3_SR = 0x0080; + DSP3.SR = 0x0080; DSP3_OP1E_A(); } - -void DSP3_OP1E_B() +static void DSP3_OP1E_B (void) { - op1e_x = op3e_x; - op1e_y = op3e_y; - op1e_lcv_radius = 1; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + DSP3.op1e_lcv_radius = 1; - op1e_search = 0; + DSP3.op1e_search = 0; DSP3_OP1E_B1(); SetDSP3 = &DSP3_OP1E_C; } - -void DSP3_OP1E_B1() +static void DSP3_OP1E_B1 (void) { - while( op1e_lcv_radius < op1e_max_radius ) { - op1e_y--; + while (DSP3.op1e_lcv_radius < DSP3.op1e_max_radius) + { + DSP3.op1e_y--; - op1e_lcv_turns = 6; - op1e_turn = 5; + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 5; - while( op1e_lcv_turns ) { - op1e_lcv_steps = op1e_lcv_radius; + while (DSP3.op1e_lcv_turns) + { + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; - while( op1e_lcv_steps ) { - DSP3_OP1E_D1( op1e_turn, &op1e_x, &op1e_y ); + while (DSP3.op1e_lcv_steps) + { + DSP3_OP1E_D1(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); - if( 0 <= op1e_y && op1e_y < DSP3_WinHi && - 0 <= op1e_x && op1e_x < DSP3_WinLo ) { - DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); + 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); DSP3_OP03(); - op1e_cell = DSP3_DR; - if( op1e_cost[ op1e_cell ] < 0x80 && - op1e_terrain[ op1e_cell ] < 0x40 ) { - DSP3_OP1E_B2(); - } // end cell perimeter + 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_lcv_steps--; + DSP3.op1e_lcv_steps--; } // end search line - op1e_turn--; - if( op1e_turn == 0 ) op1e_turn = 6; + DSP3.op1e_turn--; + if (DSP3.op1e_turn == 0) + DSP3.op1e_turn = 6; - op1e_lcv_turns--; + DSP3.op1e_lcv_turns--; } // end circle search - op1e_lcv_radius++; + DSP3.op1e_lcv_radius++; } // end radius search } - -void DSP3_OP1E_B2() +static void DSP3_OP1E_B2 (void) { - 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 = op1e_x; - y = op1e_y; + while (lcv_turns) + { + x = DSP3.op1e_x; + y = DSP3.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( op1e_terrain[ cell ] < 0x80 || op1e_weight[ cell ] == 0 ) { - if( op1e_weight[ cell ] < path ) { - path = op1e_weight[ cell ]; - } + 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]; } } // end step travel lcv_turns--; } // end while turns - if( path != 0xff ) { - op1e_weight[ op1e_cell ] = path + op1e_cost[ op1e_cell ]; - } + if (path != 0xff) + DSP3.op1e_weight[DSP3.op1e_cell] = path + DSP3.op1e_cost[DSP3.op1e_cell]; } - -void DSP3_OP1E_C() +static void DSP3_OP1E_C (void) { - int lcv; + DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); + DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); - op1e_min_radius = (uint8)(DSP3_DR & 0x00ff); - op1e_max_radius = (uint8)((DSP3_DR & 0xff00)>>8); + if (DSP3.op1e_min_radius == 0) + DSP3.op1e_min_radius++; - if( op1e_min_radius == 0 ) - op1e_min_radius++; + if (DSP3.op1e_max_path_radius >= DSP3.op1e_min_radius) + DSP3.op1e_min_radius = DSP3.op1e_max_path_radius + 1; - if( op1e_max_path_radius >= op1e_min_radius ) - op1e_min_radius = op1e_max_path_radius+1; + if (DSP3.op1e_max_radius > DSP3.op1e_max_path_radius) + DSP3.op1e_max_path_radius = DSP3.op1e_max_radius; - if( op1e_max_radius > op1e_max_path_radius ) - op1e_max_path_radius = op1e_max_radius; + 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_lcv_turns = 6; + DSP3.op1e_turn = 0; - op1e_lcv_turns = 6; - op1e_turn = 0; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_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 ); + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); DSP3_OP1E_C1(); } - -void DSP3_OP1E_C1() +static void DSP3_OP1E_C1 (void) { - int lcv; + if (DSP3.op1e_lcv_steps == 0) + { + DSP3.op1e_lcv_radius++; - if( op1e_lcv_steps == 0 ) { - op1e_lcv_radius++; + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; - op1e_lcv_steps = op1e_lcv_radius; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_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 ); + for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); } - if( op1e_lcv_radius > op1e_max_radius ) { - op1e_turn++; - op1e_lcv_turns--; + if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) + { + DSP3.op1e_turn++; + DSP3.op1e_lcv_turns--; - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; - op1e_x = op3e_x; - op1e_y = op3e_y; + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); } - if( op1e_lcv_turns == 0 ) { - DSP3_DR = 0xffff; - DSP3_SR = 0x0080; + if (DSP3.op1e_lcv_turns == 0) + { + DSP3.DR = 0xffff; + DSP3.SR = 0x0080; SetDSP3 = &DSP3_Reset; return; } - DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); DSP3_OP03(); - op1e_cell = DSP3_DR; + DSP3.op1e_cell = DSP3.DR; - DSP3_SR = 0x0080; + DSP3.SR = 0x0080; SetDSP3 = &DSP3_OP1E_C2; } - -void DSP3_OP1E_C2() +static void DSP3_OP1E_C2 (void) { - DSP3_DR = op1e_weight[ op1e_cell ]; + DSP3.DR = DSP3.op1e_weight[DSP3.op1e_cell]; - DSP3_OP1E_D( (int16)(op1e_turn+2), &op1e_x, &op1e_y ); - op1e_lcv_steps--; + DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); + DSP3.op1e_lcv_steps--; - DSP3_SR = 0x0084; + DSP3.SR = 0x0084; SetDSP3 = &DSP3_OP1E_C1; } - -void DSP3_OP1E_D( int16 move, int16 *lo, int16 *hi ) +static 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; } - -void DSP3_OP1E_D1( int16 move, int16 *lo, int16 *hi ) +static 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 uint16 HiAdd[] = + { + 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 }; - const unsigned short LoAdd[] = { + + const uint16 LoAdd[] = + { 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 }; - if( (*lo) & 1 ) - DSP3_AddHi = HiAdd[ move + 8 ]; + int16 Lo; + int16 Hi; + + if ((*lo) & 1) + DSP3.AddHi = HiAdd[move + 8]; else - DSP3_AddHi = HiAdd[ move + 0 ]; - DSP3_AddLo = LoAdd[ move ]; + DSP3.AddHi = HiAdd[move + 0]; - Lo = (uint8)(*lo); - Hi = (uint8)(*hi); + DSP3.AddLo = LoAdd[move]; - if (Lo & 1) Hi += (DSP3_AddLo & 1); + Lo = (uint8) (*lo); + Hi = (uint8) (*hi); - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; + if (Lo & 1) + Hi += (DSP3.AddLo & 1); - *lo = DSP3_AddLo; - *hi = DSP3_AddHi; + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + *lo = DSP3.AddLo; + *hi = DSP3.AddHi; } - -void DSP3_OP10() +static void DSP3_OP10 (void) { - if( DSP3_DR == 0xffff ) { + if (DSP3.DR == 0xffff) DSP3_Reset(); - } else { + else // absorb 2 bytes - DSP3_DR = DSP3_DR; - } + DSP3.DR = DSP3.DR; } - -void DSP3_OP0C_A() +/* +static void DSP3_OP0C_A (void) { // absorb 2 bytes - - DSP3_DR = 0; + DSP3.DR = 0; SetDSP3 = &DSP3_Reset; } +*/ - -void DSP3_OP0C() +static void DSP3_OP0C (void) { // absorb 2 bytes - - DSP3_DR = 0; + DSP3.DR = 0; //SetDSP3 = &DSP3_OP0C_A; SetDSP3 = &DSP3_Reset; } - -void DSP3_OP1C_C() +static void DSP3_OP1C_C (void) { // return 2 bytes - DSP3_DR = 0; + DSP3.DR = 0; SetDSP3 = &DSP3_Reset; } - -void DSP3_OP1C_B() +static void DSP3_OP1C_B (void) { - // absorb 2 bytes - // return 2 bytes - DSP3_DR = 0; + DSP3.DR = 0; SetDSP3 = &DSP3_OP1C_C; } - -void DSP3_OP1C_A() +static void DSP3_OP1C_A (void) { // absorb 2 bytes - SetDSP3 = &DSP3_OP1C_B; } - -void DSP3_OP1C() +static void DSP3_OP1C (void) { // absorb 2 bytes - SetDSP3 = &DSP3_OP1C_A; } - -void DSP3_Command() +static void DSP3_Command (void) { - if (DSP3_DR < 0x40) + if (DSP3.DR < 0x40) { - switch (DSP3_DR) + 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; + 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; + + DSP3.SR = 0x0080; + DSP3.Index = 0; } } -void DSP3SetByte(uint8 byte, uint16 address) +void DSP3SetByte (uint8 byte, uint16 address) { - if (address < DSP1.boundary) - { - if (DSP3_SR & 0x04) + if (address < DSP0.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 < DSP1.boundary) - { - uint8 byte; + if (address < DSP0.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 new file mode 100644 index 0000000..afb415f --- /dev/null +++ b/source/snes9x/dsp4.cpp @@ -0,0 +1,2204 @@ +/********************************************************************************** + 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 deleted file mode 100644 index 2a65842..0000000 --- a/source/snes9x/dsp4emu.c.inc +++ /dev/null @@ -1,2396 +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 "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 1b126cc..f6fae04 100644 --- a/source/snes9x/font.h +++ b/source/snes9x/font.h @@ -159,142 +159,151 @@ **********************************************************************************/ +#ifndef _FONT_H_ +#define _FONT_H_ -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 -" .. . . ... . .... .... . . . . . ..... . . . . ", -" .##. .#. .#. .###. .#... ... .####. .####. .#..#. .#.#. .#. ..... .#####. ....#. .#.#. .#. ", -" ..#. .#. . .#. .#. .#.##. .###. ...#. ..... .#..#. .#.#. .#. .#####. .#...#. .###.#. .#.#. .#.#. ", -" .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", -" ..#. .#..#. .##. ..#.. .#.#. ..#. ..#. ....#. . .#. .#.#. .#..#. .#...#. .#. .#. . ", -" .##. .####. ..#.#. .#.. .#. ...#. ...#. ..#. ..#. .#.#. .#.#. .#####. ..#. ...#. ", -" ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", -" . . .. ... . ..... .... .. ... . .. .. . . .. ... ", -" ", - -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", - -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" " +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 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }; +#endif diff --git a/source/snes9x/fxdbg.cpp b/source/snes9x/fxdbg.cpp index f51c94d..d3b5e31 100644 --- a/source/snes9x/fxdbg.cpp +++ b/source/snes9x/fxdbg.cpp @@ -159,325 +159,1251 @@ **********************************************************************************/ +#ifdef DEBUGGER - -#include "fxemu.h" +#include "snes9x.h" #include "fxinst.h" -#include -#include - -extern const char *fx_apvMnemonicTable[]; -extern struct FxRegs_s GSU; - +#include "fxemu.h" /* 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) +*/ - */ -void FxPipeString(char * pvString) +/* +static const char *fx_apvMnemonicTable[] = { - 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; + // ALT0 Table - /* 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)]; + // 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", - /* The actual next two bytes to be read */ - vByte1 = PRGBANK(USEX16(R15)); - vByte2 = PRGBANK(USEX16(R15+1)); + // 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", - /* Print ROM address of the pipe */ - sprintf(pvString, "%02x:%04x %02x ", - USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); - p = &pvString[strlen(pvString)]; + // 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", - /* 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); -} + // 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", -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", + // 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", - /* - * ALT1 Table - */ + // 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", - /* 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)", + // 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", - /* - * ALT2 Table - */ + // 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", - /* 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", + // 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", - /* - * ALT3 Table - */ + // 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", - /* 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)", + // 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); +} +*/ + +#endif diff --git a/source/snes9x/fxemu.cpp b/source/snes9x/fxemu.cpp index 2b7e660..69da874 100644 --- a/source/snes9x/fxemu.cpp +++ b/source/snes9x/fxemu.cpp @@ -159,644 +159,813 @@ **********************************************************************************/ - -#include "fxemu.h" +#include "snes9x.h" +#include "memmap.h" #include "fxinst.h" -#include -#include -#include +#include "fxemu.h" -/* The FxChip Emulator's internal variables */ -struct FxRegs_s GSU = FxRegs_s_null; +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); -uint32 (**fx_ppfFunctionTable)(uint32) = 0; -void (**fx_ppfPlotTable)() = 0; -void (**fx_ppfOpcodeTable)() = 0; -#if 0 -void fx_setCache() +void S9xInitSuperFX (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)) - { - 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); - } -} -#endif - -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); + memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s)); } -void FxFlushCache() +void S9xResetSuperFX (void) { - GSU.vCacheFlags = 0; - GSU.vCacheBaseReg = 0; - GSU.bCacheActive = FALSE; -// GSU.vPipe = 0x1; + // 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); } -static void fx_backupCache() +void S9xSetSuperFX (uint8 byte, uint16 address) { -#if 0 - uint32 i; - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - if(v) - for(i=0; i<32; i++) + switch (address) { - if(v&1) - { - if(c < (0x10000-16)) + 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 S9xSuperFXExec (void) +{ + 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); + } +} + +static void FxReset (struct FxInfo_s *psFxInfo) +{ + // 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++) + { + uint32 b = i & 0x7f; + + if (b >= 0x40) { - uint8 * t = &GSU.pvPrgBank[c]; - memcpy(&GSU.avCacheBackup[i<<4],t,16); - memcpy(t,&GSU.pvCache[i<<4],16); + if (GSU.nRomBanks > 1) + b %= GSU.nRomBanks; + else + b &= 1; + + GSU.apvRomBank[i] = &GSU.pvRom[b << 16]; } else { - 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); + b %= GSU.nRomBanks * 2; + GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x200000]; } - } - c = USEX16(c+16); - v >>= 1; } -#endif -} -static void fx_restoreCache() -{ -#if 0 - uint32 i; - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - if(v) - for(i=0; i<32; i++) + // Make RAM bank table + for (int i = 0; i < 4; i++) { - 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; + GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; + GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; } -#endif + + // Start with a nop in the pipe + GSU.vPipe = 0x01; + + // Set pointer to GSU cache + GSU.pvCache = &GSU.pvRegisters[0x100]; + + fx_readRegisterSpace(); } -void fx_flushCache() +static void fx_readRegisterSpace (void) { - fx_restoreCache(); - GSU.vCacheFlags = 0; - GSU.bCacheActive = FALSE; + 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++) + { + 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]; + 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(); } +static void fx_writeRegisterSpace (void) +{ + uint8 *p; -void fx_updateRamBank(uint8 Byte) + 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(); +} + +// Update RamBankReg and RAM Bank pointer +static 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]; } - -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() +// SCBR write seen. We need to update our cached screen pointers +static void fx_dirtySCBR (void) { GSU.vSCBRDirty = TRUE; } -void fx_computeScreenPointers () +static bool8 fx_checkStartAddress (void) { - if (GSU.vMode != GSU.vPrevMode || - GSU.vPrevScreenHeight != GSU.vScreenHeight || - GSU.vSCBRDirty) - { - int i; + // Check if we start inside the cache + if (GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg + 512)) + return (TRUE); - GSU.vSCBRDirty = FALSE; + /* + // Check if we're in an unused area + if (GSU.vPrgBankReg < 0x40 && R15 < 0x8000) + return (FALSE); + */ - /* Make a list of pointers to the start of each screen column */ - switch (GSU.vScreenHeight) + 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()) { - case 128: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = i << 8; - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = i << 9; - } - 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; + CF(G); + fx_writeRegisterSpace(); + /* + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return (FX_ERROR_ILLEGAL_ADDRESS); + */ + + return (0); } - GSU.vPrevMode = GSU.vMode; - GSU.vPrevScreenHeight = GSU.vScreenHeight; - } + + // 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); } -static void fx_writeRegisterSpace() +void fx_computeScreenPointers (void) { - 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(); -} - -/* Reset the FxChip */ -void FxReset(struct FxInit_s *psFxInfo) -{ - 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 - }; - - /* 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]; - - /* 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(i=0; i<256; i++) - { - uint32 b = i & 0x7f; - if (b >= 0x40) + if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) { - if (GSU.nRomBanks > 1) - b %= GSU.nRomBanks; - else - b &= 1; + GSU.vSCBRDirty = FALSE; - GSU.apvRomBank[i] = &GSU.pvRom[ b << 16 ]; + // Make a list of pointers to the start of each screen column + switch (GSU.vScreenHeight) + { + 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 { - b %= GSU.nRomBanks * 2; - GSU.apvRomBank[i] = &GSU.pvRom[ (b << 16) + 0x200000]; + 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); } - } - - /* 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() +/* +static void fx_backupCache (void) { - /* Check if we start inside the cache */ - if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) - return TRUE; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); - /* 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; + if (v) + { + for (int i = 0; i < 32; i++) + { + if (v & 1) + { + 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; - /* 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; + 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); + } + } - /* If not, we're in ROM, so check if the RON flag is set */ - if(!(SCMR&(1<<4))) - return FALSE; - - return TRUE; + c = USEX16(c + 16); + v >>= 1; + } + } } +*/ -/* Execute until the next stop instruction */ -int FxEmulate(uint32 nInstructions) +/* +static void fx_restoreCache() { - uint32 vCount; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); - /* Read registers and initialize GSU session */ - fx_readRegisterSpace(); + if (v) + { + for (int i = 0; i < 32; i++) + { + 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, *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; + } + } +} +*/ + +// Breakpoints +/* +static void FxBreakPointSet (uint32 vAddress) +{ + GSU.bBreakPoint = TRUE; + GSU.vBreakPoint = USEX16(vAddress); +} +*/ + +/* +static void FxBreakPointClear (void) +{ + GSU.bBreakPoint = FALSE; +} +*/ + +// Step by step execution +/* +static uint32 FxStepOver (uint32 nInstructions) +{ + uint32 vCount; + + fx_readRegisterSpace(); + + if (!fx_checkStartAddress()) + { + CF(G); + #if 0 + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return (FX_ERROR_ILLEGAL_ADDRESS); + #else + return (0); + #endif + } + + 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_step_over(nInstructions); - /* 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 - } - /* 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; + if (GSU.vErrorCode) + return (GSU.vErrorCode); + else + return (vCount); } +*/ -/* Breakpoints */ -void FxBreakPointSet(uint32 vAddress) +// Errors +/* +static int FxGetErrorCode (void) { - GSU.bBreakPoint = TRUE; - GSU.vBreakPoint = USEX16(vAddress); + return (GSU.vErrorCode); } -void FxBreakPointClear() +*/ + +/* +static int FxGetIllegalAddress (void) { - GSU.bBreakPoint = FALSE; + return (GSU.vIllegalAddress); } +*/ -/* Step by step execution */ -int FxStepOver(uint32 nInstructions) +// Access to internal registers +/* +static uint32 FxGetColorRegister (void) { - uint32 vCount; - fx_readRegisterSpace(); - - /* 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 - } - - 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; + return (GSU.vColorReg & 0xff); } +*/ -/* Errors */ -int FxGetErrorCode() +/* +static uint32 FxGetPlotOptionRegister (void) { - return GSU.vErrorCode; + return (GSU.vPlotOptionReg & 0x1f); } +*/ -int FxGetIllegalAddress() +/* +static uint32 FxGetSourceRegisterIndex (void) { - return GSU.vIllegalAddress; + return (GSU.pvSreg - GSU.avReg); } +*/ -/* Access to internal registers */ -uint32 FxGetColorRegister() +/* +static uint32 FxGetDestinationRegisterIndex (void) { - return GSU.vColorReg & 0xff; + return (GSU.pvDreg - GSU.avReg); } +*/ -uint32 FxGetPlotOptionRegister() +// Get the byte currently in the pipe +/* +static uint8 FxPipe (void) { - return GSU.vPlotOptionReg & 0x1f; + return (GSU.vPipe); } - -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 a9e1ee4..bd7e422 100644 --- a/source/snes9x/fxemu.h +++ b/source/snes9x/fxemu.h @@ -159,76 +159,62 @@ **********************************************************************************/ - #ifndef _FXEMU_H_ -#define _FXEMU_H_ 1 +#define _FXEMU_H_ -#include "port.h" +#ifndef ZSNES_FX -/* The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator */ -struct FxInit_s +// The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator +struct FxInfo_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; }; -/* Reset the FxChip */ -extern void FxReset(struct FxInit_s *psFxInfo); +extern struct FxInfo_s SuperFX; -/* Execute until the next stop instruction */ -extern int FxEmulate(uint32 nInstructions); +void S9xInitSuperFX (void); +void S9xSetSuperFX (uint8, uint16); +uint8 S9xGetSuperFX (uint16); +void fx_flushCache (void); +void fx_computeScreenPointers (void); +uint32 fx_run (uint32); -/* Write access to the cache */ -extern void FxCacheWriteAccess(uint16 vAddress); -extern void FxFlushCache(); /* Callled when the G flag in SFR is set to zero */ +#define FX_BREAKPOINT (-1) +#define FX_ERROR_ILLEGAL_ADDRESS (-2) -/* Breakpoint */ -extern void FxBreakPointSet(uint32 vAddress); -extern void FxBreakPointClear(); +#else -/* Step by step execution */ -extern int FxStepOver(uint32 nInstructions); +extern uint8 *SFXPlotTable; -/* Errors */ -extern int FxGetErrorCode(); -extern int FxGetIllegalAddress(); +#define S9xSetSuperFX S9xSuperFXWriteReg +#define S9xGetSuperFX S9xSuperFXReadReg -/* 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 (); +START_EXTERN_C +void S9xSuperFXWriteReg (uint8, uint32); +uint8 S9xSuperFXReadReg (uint32); +void S9xSuperFXPreSaveState (void); +void S9xSuperFXPostSaveState (void); +void S9xSuperFXPostLoadState (void); +END_EXTERN_C #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 e669e9d..fc564d4 100644 --- a/source/snes9x/fxinst.cpp +++ b/source/snes9x/fxinst.cpp @@ -159,1832 +159,4250 @@ **********************************************************************************/ - -#define FX_DO_ROMBUFFER - -#include "fxemu.h" +#include "snes9x.h" #include "fxinst.h" -#include -#include +#include "fxemu.h" -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) */ +// 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) - * - */ -/* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ -static void fx_stop() +/* + 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) { - 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() { CLRFLAGS; R15++; } - -extern void fx_flushCache(); - -/* 02 - cache - reintialize GSU cache */ -static void fx_cache() +// 01 - nop - no operation +static void fx_nop (void) { - uint32 c = R15 & 0xfff0; - if(GSU.vCacheBaseReg != c || !GSU.bCacheActive) - { - fx_flushCache(); - GSU.vCacheBaseReg = c; - GSU.bCacheActive = TRUE; -#if 0 - if(c < (0x10000-512)) + CLRFLAGS; + R15++; +} + +// 02 - cache - reintialize GSU cache +static void fx_cache (void) +{ + uint32 c = R15 & 0xfff0; + + if (GSU.vCacheBaseReg != c || !GSU.bCacheActive) { - uint8 const* t = &ROM(c); - memcpy(GSU.pvCache,t,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 + } + + CLRFLAGS; + R15++; +} + +// 03 - lsr - logic shift right +static void fx_lsr (void) +{ + 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) +{ + 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); +} + +// 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) + +// 06 - blt - branch on less than +static void fx_blt (void) +{ + 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)); +} + +// 08 - bne - branch on not equal +static void fx_bne (void) +{ + BRA_COND(!TEST_Z); +} + +// 09 - beq - branch on equal +static void fx_beq (void) +{ + BRA_COND(TEST_Z); +} + +// 0a - bpl - branch on plus +static void fx_bpl (void) +{ + BRA_COND(!TEST_S); +} + +// 0b - bmi - branch on minus +static void fx_bmi (void) +{ + BRA_COND(TEST_S); +} + +// 0c - bcc - branch on carry clear +static void fx_bcc (void) +{ + BRA_COND(!TEST_CY); +} + +// 0d - bcs - branch on carry set +static void fx_bcs (void) +{ + BRA_COND(TEST_CY); +} + +// 0e - bvc - branch on overflow clear +static void fx_bvc (void) +{ + BRA_COND(!TEST_OV); +} + +// 0f - bvs - branch on overflow set +static void fx_bvs (void) +{ + 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) +#define FX_TO(reg) \ + 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++ + +#define FX_TO_R15(reg) \ + if (TF(B)) \ + { \ + GSU.avReg[(reg)] = SREG; \ + CLRFLAGS; \ + } \ + else \ + { \ + GSU.pvDreg = &GSU.avReg[reg]; \ + R15++; \ + } + +static void fx_to_r0 (void) +{ + FX_TO(0); +} + +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 +#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++ + +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 +#define FX_STB(reg) \ + GSU.vLastRamAdr = GSU.avReg[reg]; \ + RAM(GSU.avReg[reg]) = (uint8) SREG; \ + CLRFLAGS; \ + R15++ + +static void fx_stb_r0 (void) +{ + 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); + R15++; +} + +// 3e - alt2 - set alt2 mode +static void fx_alt2 (void) +{ + SF(ALT2); + CF(B); + R15++; +} + +// 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++; + +#ifdef CHECK_LIMITS + 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 & 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; +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_2bit (void) +{ + 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[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 (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v, c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + 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 & 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; +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_4bit (void) +{ + 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; + TESTR14; +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_8bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v, c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + c = (uint8) GSU.vColorReg; + if (!(GSU.vPlotOptionReg & 0x10)) + { + if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) + return; } 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; + 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; } -/* 03 - lsr - logic shift right */ -static void fx_lsr() +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_8bit (void) { - uint32 v; - GSU.vCarry = SREG & 1; - v = USEX16(SREG) >> 1; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; -/* 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; -} - -/* 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++; - -#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() { 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() { 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() { 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() { 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() { 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) */ -#define FX_TO(reg) \ -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++; -#define FX_TO_R15(reg) \ -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); } - -/* 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); } - -/* 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++ -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); } - -/* 30-3b(ALT1) - stb (rn) - store byte */ -#define FX_STB(reg) \ -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); } - -/* 3c - loop - decrement loop counter, and branch on not zero */ -static void fx_loop() -{ - GSU.vSign = GSU.vZero = --R12; - if( (uint16) R12 != 0 ) - R15 = R13; - else R15++; - - CLRFLAGS; -} - -/* 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() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; + CLRFLAGS; #ifdef CHECK_LIMITS - 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 & 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; -} - -/* 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; - - 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); + 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; + 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 - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static void fx_plot_4bit() +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_obj (void) { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; +#ifdef DEBUGGER + fprintf(stderr, "ERROR fx_plot_obj called\n"); #endif - 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(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(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static void fx_rpix_4bit() +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_obj (void) { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; - - R15++; - CLRFLAGS; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; +#ifdef DEBUGGER + fprintf(stderr, "ERROR fx_rpix_obj called\n"); #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; - TESTR14; } -/* 8c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static void fx_plot_8bit() +// 4d - swap - swap upper and lower byte of a register +static void fx_swap (void) { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; - -#ifdef CHECK_LIMITS - 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); - - 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; + 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; } -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static void fx_rpix_8bit() +// 4e - color - copy source register to color register +static void fx_color (void) { - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; + uint8 c = (uint8) SREG; - R15++; - CLRFLAGS; + 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); -#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; + CLRFLAGS; + R15++; } -/* 4o - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static void fx_plot_obj() +// 4e (ALT1) - cmode - set plot option register +static void fx_cmode (void) { - //printf ("ERROR fx_plot_obj called\n"); + 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++; } -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static void fx_rpix_obj() +// 4f - not - perform exclusive exor with 1 on all bits +static void fx_not (void) { - //printf ("ERROR fx_rpix_obj called\n"); + uint32 v = ~SREG; + 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() -{ - 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; -} - -/* 4e - color - copy source register to color register */ -static void fx_color() -{ - 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(ALT1) - cmode - set plot option register */ -static void fx_cmode() -{ - GSU.vPlotOptionReg = SREG; - - if(GSU.vPlotOptionReg & 0x10) - { - /* OBJ Mode (for drawing into sprites) */ - GSU.vScreenHeight = 256; - } - else - GSU.vScreenHeight = GSU.vScreenRealHeight; - - fx_computeScreenPointers (); - CLRFLAGS; - R15++; -} - -/* 4f - not - perform exclusive exor with 1 on all bits */ -static void fx_not() -{ - 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 -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); } + 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 -/* 50-5f(ALT1) - adc rn - add with carry, register + register */ +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 #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 -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); } + 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 -/* 50-5f(ALT2) - add #n - add, register + immediate */ +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 #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 -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); } + 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 -/* 50-5f(ALT3) - adc #n - add with carry, register + immediate */ +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 #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 -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); } + 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 -/* 60-6f - sub rn - subtract, register - register */ +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 #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 -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); } + 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 -/* 60-6f(ALT1) - sbc rn - subtract with carry, register - register */ +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 #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 -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); } + 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 -/* 60-6f(ALT2) - sub #n - subtract, register - immediate */ +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 #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 -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); } + 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 -/* 60-6f(ALT3) - cmp rn - compare, register, register */ +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 #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; -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); } + 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 -/* 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) */ -static void fx_merge() +static void fx_cmp_r0 (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; + FX_CMP(0); } -/* 71-7f - and rn - reister & register */ +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 #define FX_AND(reg) \ -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); } + uint32 v = SREG & GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 71-7f(ALT1) - bic rn - reister & ~register */ +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 #define FX_BIC(reg) \ -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); } + uint32 v = SREG & ~GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 71-7f(ALT2) - and #n - reister & immediate */ +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 #define FX_AND_I(imm) \ -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); } + uint32 v = SREG & imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 71-7f(ALT3) - bic #n - reister & ~immediate */ +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 #define FX_BIC_I(imm) \ -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); } + uint32 v = SREG & ~imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 80-8f - mult rn - 8 bit to 16 bit signed multiply, register * register */ +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 #define FX_MULT(reg) \ -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); } + uint32 v = (uint32) (SEX8(SREG) * SEX8(GSU.avReg[reg])); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 80-8f(ALT1) - umult rn - 8 bit to 16 bit unsigned multiply, register * register */ +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 #define FX_UMULT(reg) \ -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); } + uint32 v = USEX8(SREG) * USEX8(GSU.avReg[reg]); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 80-8f(ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate */ +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 #define FX_MULT_I(imm) \ -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); } + uint32 v = (uint32) (SEX8(SREG) * ((int32) imm)); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 80-8f(ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate */ +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 #define FX_UMULT_I(imm) \ -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); } + uint32 v = USEX8(SREG) * ((uint32) imm); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* 90 - sbk - store word to last accessed RAM address */ -static void fx_sbk() +static void fx_umult_i0 (void) { - RAM(GSU.vLastRamAdr) = (uint8)SREG; - RAM(GSU.vLastRamAdr^1) = (uint8)(SREG>>8); - CLRFLAGS; - R15++; + FX_UMULT_I(0); } -/* 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() +static void fx_umult_i1 (void) { - uint32 v = (uint32)SEX8(SREG); - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; + FX_UMULT_I(1); } -/* 96 - asr - aritmetric shift right by one */ -static void fx_asr() +static void fx_umult_i2 (void) { - uint32 v; - GSU.vCarry = SREG & 1; - v = (uint32)(SEX16(SREG)>>1); - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; + FX_UMULT_I(2); } -/* 96(ALT1) - div2 - aritmetric shift right by one */ -static void fx_div2() +static void fx_umult_i3 (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; + FX_UMULT_I(3); } -/* 97 - ror - rotate right by one */ -static void fx_ror() +static void fx_umult_i4 (void) { - uint32 v = (USEX16(SREG)>>1) | (GSU.vCarry<<15); - GSU.vCarry = SREG & 1; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; + FX_UMULT_I(4); } -/* 98-9d - jmp rn - jump to address of register */ +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 #define FX_JMP(reg) \ -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); } + R15 = GSU.avReg[reg]; \ + CLRFLAGS -/* 98-9d(ALT1) - ljmp rn - set program bank to source register and jump to address of register */ +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 #define FX_LJMP(reg) \ -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); } + GSU.vPrgBankReg = GSU.avReg[reg] & 0x7f; \ + GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; \ + R15 = SREG; \ + GSU.bCacheActive = FALSE; \ + fx_cache(); \ + R15-- -/* 9e - lob - set upper byte to zero (keep low byte) */ -static void fx_lob() +static void fx_ljmp_r8 (void) { - uint32 v = USEX8(SREG); - R15++; DREG = v; - GSU.vSign = v<<8; - GSU.vZero = v<<8; - TESTR14; - CLRFLAGS; + FX_LJMP(8); } -/* 9f - fmult - 16 bit to 32 bit signed multiplication, upper 16 bits only */ -static void fx_fmult() +static void fx_ljmp_r9 (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; + FX_LJMP(9); } -/* 9f(ALT1) - lmult - 16 bit to 32 bit signed multiplication */ -static void fx_lmult() +static void fx_ljmp_r10 (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; + FX_LJMP(10); } -/* a0-af - ibt rn,#pp - immediate byte transfer */ +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 #define FX_IBT(reg) \ -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); } + uint8 v = PIPE; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + GSU.avReg[reg] = SEX8(v); \ + CLRFLAGS -/* a0-af(ALT1) - lms rn,(yy) - load word from RAM (short address) */ +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) #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; -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); } + 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 -/* 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? */ +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 ? #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++; -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); } + 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++ -/* b0-bf - from rn - set source register */ -/* b0-bf(B) - moves rn - move register to register, and set flags, (if B flag is set) */ +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) #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++; } -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); } + 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++; \ + } -/* c0 - hib - move high-byte to low-byte */ -static void fx_hib() +static void fx_from_r0 (void) { - uint32 v = USEX8(SREG>>8); - R15++; DREG = v; - GSU.vSign = v<<8; - GSU.vZero = v<<8; - TESTR14; - CLRFLAGS; + FX_FROM(0); } -/* c1-cf - or rn */ +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 #define FX_OR(reg) \ -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); } + uint32 v = SREG | GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* c1-cf(ALT1) - xor rn */ +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 #define FX_XOR(reg) \ -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); } + uint32 v = SREG ^ GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* c1-cf(ALT2) - or #n */ +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 #define FX_OR_I(imm) \ -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); } + uint32 v = SREG | imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* c1-cf(ALT3) - xor #n */ +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 #define FX_XOR_I(imm) \ -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); } + uint32 v = SREG ^ imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS -/* d0-de - inc rn - increase by one */ +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 #define FX_INC(reg) \ -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; } + GSU.avReg[reg] += 1; \ + GSU.vSign = GSU.avReg[reg]; \ + GSU.vZero = GSU.avReg[reg]; \ + CLRFLAGS; \ + R15++ -/* df - getc - transfer ROM buffer to color register */ -static void fx_getc() +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) { #ifndef FX_DO_ROMBUFFER - uint8 c; - c = ROM(R14); + uint8 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() +// df (ALT2) - ramb - set current RAM bank +static void fx_ramb (void) { - 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() +// df (ALT3) - romb - set current ROM bank +static void fx_romb (void) { - 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++; -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; } + GSU.avReg[reg] -= 1; \ + GSU.vSign = GSU.avReg[reg]; \ + GSU.vZero = GSU.avReg[reg]; \ + CLRFLAGS; \ + R15++ -/* ef - getb - get byte from ROM at address R14 */ -static void fx_getb() +static void fx_dec_r0 (void) { - uint32 v; -#ifndef FX_DO_ROMBUFFER - v = (uint32)ROM(R14); -#else - v = (uint32)GSU.vRomBuffer; -#endif - R15++; DREG = v; - TESTR14; - CLRFLAGS; + FX_DEC(0); } -/* ef(ALT1) - getbh - get high-byte from ROM at address R14 */ -static void fx_getbh() +static void fx_dec_r1 (void) { - uint32 v; -#ifndef FX_DO_ROMBUFFER - uint32 c; - c = (uint32)ROM(R14); -#else - uint32 c = USEX8(GSU.vRomBuffer); -#endif - v = USEX8(SREG) | (c<<8); - R15++; DREG = v; - TESTR14; - CLRFLAGS; + FX_DEC(1); } -/* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ -static void fx_getbl() +static void fx_dec_r2 (void) { - uint32 v; -#ifndef FX_DO_ROMBUFFER - uint32 c; - c = (uint32)ROM(R14); -#else - uint32 c = USEX8(GSU.vRomBuffer); -#endif - v = (SREG & 0xff00) | c; - R15++; DREG = v; - TESTR14; - CLRFLAGS; + FX_DEC(2); } -/* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ -static void fx_getbs() +static void fx_dec_r3 (void) { - uint32 v; -#ifndef FX_DO_ROMBUFFER - int8 c; - c = ROM(R14); - v = SEX8(c); -#else - v = SEX8(GSU.vRomBuffer); -#endif - R15++; DREG = v; - TESTR14; - CLRFLAGS; + FX_DEC(3); } -/* f0-ff - iwt rn,#xx - immediate word transfer to register */ +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; +#ifndef FX_DO_ROMBUFFER + v = (uint32) ROM(R14); +#else + v = (uint32) GSU.vRomBuffer; +#endif + R15++; + DREG = v; + TESTR14; + CLRFLAGS; +} + +// ef (ALT1) - getbh - get high-byte from ROM at address R14 +static void fx_getbh (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 c = (uint32) ROM(R14); +#else + uint32 c = USEX8(GSU.vRomBuffer); +#endif + 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) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 c = (uint32) ROM(R14); +#else + uint32 c = USEX8(GSU.vRomBuffer); +#endif + 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) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + int8 c; + c = ROM(R14); + v = SEX8(c); +#else + v = SEX8(GSU.vRomBuffer); +#endif + R15++; + DREG = v; + TESTR14; + CLRFLAGS; +} + +// 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; -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); } + uint32 v = PIPE; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + v |= USEX8(PIPE) << 8; \ + FETCHPIPE; \ + R15++; \ + GSU.avReg[reg] = v; \ + CLRFLAGS -/* f0-ff(ALT1) - lm rn,(xx) - load word from RAM */ +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 #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; -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); } + 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 -/* 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? */ +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 ? #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++; -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); } + 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++ -/*** GSU executions functions ***/ - -static uint32 fx_run(uint32 nInstructions) +static void fx_sm_r0 (void) { - 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); -#endif -*/ - return (nInstructions - GSU.vInstCount); + FX_SM(0); } -static uint32 fx_run_to_breakpoint(uint32 nInstructions) +static void fx_sm_r1 (void) { - uint32 vCounter = 0; - while(TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - if(USEX16(R15) == GSU.vBreakPoint) + 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 +#ifndef FX_ADDRESS_CHECK + 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) { - 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; + 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); + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); #endif -*/ - return vCounter; +#endif + + return (vCounter); } +*/ -#ifdef FX_FUNCTION_TABLE -uint32 (*FX_FUNCTION_TABLE[])(uint32) = -#else -uint32 (*fx_apfFunctionTable[])(uint32) = -#endif +/* +uint32 fx_step_over (uint32 nInstructions) { - &fx_run, - &fx_run_to_breakpoint, - &fx_step_over, + 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); +} +*/ + +// Special table for the different plot configurations + +void (*fx_PlotTable[]) (void) = +{ + &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 }; -/*** Special table for the different plot configurations ***/ +// Opcode table -#ifdef FX_PLOT_TABLE -void (*FX_PLOT_TABLE[])() = -#else -void (*fx_apfPlotTable[])() = -#endif +void (*fx_OpcodeTable[]) (void) = { - &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, + // 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 }; - -/*** 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 e78e682..498e027 100644 --- a/source/snes9x/fxinst.h +++ b/source/snes9x/fxinst.h @@ -159,73 +159,74 @@ **********************************************************************************/ - #ifndef _FXINST_H_ -#define _FXINST_H_ 1 +#define _FXINST_H_ + +#ifndef ZSNES_FX /* * 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 @@ -236,44 +237,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 @@ -281,270 +282,247 @@ * */ -/* 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 */ + // Other emulator variables + int32 vErrorCode; + uint32 vIllegalAddress; - int32 vErrorCode; - uint32 vIllegalAddress; + uint8 bBreakPoint; + uint32 vBreakPoint; + uint32 vStepPoint; - uint8 bBreakPoint; - uint32 vBreakPoint; - uint32 vStepPoint; + 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 * 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 */ + 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); - 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 *pvRamBank; // Pointer to current RAM-bank + uint8 *pvRomBank; // Pointer to current ROM-bank + uint8 *pvPrgBank; // Pointer to current program ROM-bank - uint8 * pvRamBank; /* Pointer to current RAM-bank */ - uint8 * pvRomBank; /* Pointer to current ROM-bank */ - uint8 * pvPrgBank; /* Pointer to current program ROM-bank */ + uint8 *apvRamBank[FX_RAM_BANKS]; // Ram bank table (max 256kb) + uint8 *apvRomBank[256]; // Rom bank table - 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 */ + 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 }; -#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, \ -} +extern struct FxRegs_s GSU; -/* 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 SEX16(a) ((int32)((int16)(a))) -#define SEX8(a) ((int32)((int8)(a))) +// Sign extend from 8/16 bit to 32 bit +#define SEX8(a) ((int32) ((int8) (a))) +#define SEX16(a) ((int32) ((int16) (a))) -/* Unsign extend from 8/16 bit to 32 bit */ -#define USEX16(a) ((uint32)((uint16)(a))) -#define USEX8(a) ((uint32)((uint8)(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))) -#define SUSEX16(a) ((int32)((uint16)(a))) +// Set/Clr Sign and Zero flag +#define TSZ(num) TS(S, ((num) & 0x8000)); TS(Z, (!USEX16(num))) -/* Set/Clr Sign and Zero flag */ -#define TSZ(num) TS(S, (num & 0x8000)); TS(Z, (!USEX16(num)) ) +// Clear flags +#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1 | FLG_ALT2 | FLG_B); GSU.pvDreg = GSU.pvSreg = &R0 -/* Clear flags */ -#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1|FLG_ALT2|FLG_B); GSU.pvDreg = GSU.pvSreg = &R0; +// Read current RAM-Bank +#define RAM(adr) GSU.pvRamBank[USEX16(adr)] -/* Read current RAM-Bank */ -#define RAM(adr) GSU.pvRamBank[USEX16(adr)] +// Read current ROM-Bank +#define ROM(idx) GSU.pvRomBank[USEX16(idx)] -/* Read current ROM-Bank */ -#define ROM(idx) (GSU.pvRomBank[USEX16(idx)]) +// Access the current value in the pipe +#define PIPE GSU.vPipe -/* Access the current value in the pipe */ -#define PIPE GSU.vPipe +// Access data in the current program bank +#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] -/* Access data in the current program bank */ -#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] - -/* Update pipe from ROM */ +// 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_ppfOpcodeTable[ (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_OpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \ +} -#define FX_FUNCTION_RUN 0 -#define FX_FUNCTION_RUN_TO_BREAKPOINT 1 -#define FX_FUNCTION_STEP_OVER 2 +extern void (*fx_PlotTable[]) (void); +extern void (*fx_OpcodeTable[]) (void); -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) */ +// 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 d962381..b295953 100644 --- a/source/snes9x/getset.h +++ b/source/snes9x/getset.h @@ -159,797 +159,730 @@ **********************************************************************************/ - - #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 "C" +extern uint8 OpenBus; + +inline uint8 S9xGetByte (uint32 Address) { - extern uint8 OpenBus; + 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); + } } -INLINE uint8 S9xGetByte (uint32 Address) +inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) { - int block; - uint8 *GetAddress = Memory.Map [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; + uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); + if ((Address & mask) == mask) + { + PC_t a; - if(!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed [block]; + OpenBus = S9xGetByte(Address); - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { + 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) +{ #ifdef CPU_SHUTDOWN - if (Memory.BlockIsRAM [block]) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + CPU.WaitAddress = 0xffffffff; #endif - return (*(GetAddress + (Address & 0xffff))); - } - 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))); + int block; + uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - case CMemory::MAP_LOROM_SRAM_B: - return (*(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB))); + if (!CPU.InDMAorHDMA) + CPU.Cycles += Memory.MemorySpeed[block]; - case CMemory::MAP_RONLY_SRAM: - case CMemory::MAP_HIROM_SRAM: - return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + - ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + SetAddress += (Address & 0xffff); + *SetAddress = Byte; - case CMemory::MAP_BWRAM: - return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + 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_C4: - return (S9xGetC4 (Address & 0xffff)); + switch ((pint) SetAddress) + { + case CMemory::MAP_CPU: + S9xSetCPU(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_PPU: + if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) + return; + S9xSetPPU(Byte, Address & 0xffff); + return; - case CMemory::MAP_SPC7110_DRAM: -#ifdef SPC7110_DEBUG - printf("reading Bank 50 (byte)\n"); -#endif - return S9xGetSPC7110(0x4800); + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = Byte; + CPU.SRAMModified = TRUE; + } - case CMemory::MAP_OBC_RAM: - return GetOBC1(Address & 0xffff); + return; - case CMemory::MAP_SETA_DSP: - return S9xGetSetaDSP(Address); + 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_RISC: - return S9xGetST018(Address); + return; - case CMemory::MAP_BSX: - return S9xGetBSX(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_DEBUG: -#ifdef DEBUGGER - printf ("DEBUG R(B) %06x\n", Address); -#endif - default: - case CMemory::MAP_NONE: - return OpenBus; - } + 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; + } } -#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 +inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01) { - 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)]; + uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); + if ((Address & mask) == mask) + { + PC_t a; - if(!CPU.InDMAorHDMA) - CPU.Cycles += (Memory.MemorySpeed [block]<<1); + if (!o) + S9xSetByte((uint8) Word, Address); + 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 - if (Memory.BlockIsRAM [block]) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + CPU.WaitAddress = 0xffffffff; #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); - } + int block; + uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - 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); - } + if (!CPU.InDMAorHDMA) + CPU.Cycles += (Memory.MemorySpeed[block] << 1); - 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)); - } + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + SetAddress += (Address & 0xffff); + WRITE_WORD(SetAddress, Word); - case CMemory::MAP_BWRAM: - return READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + 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; + } - case CMemory::MAP_C4: - return (S9xGetC4 (Address & 0xffff) | - (S9xGetC4 ((Address + 1) & 0xffff) << 8)); + 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); + } - 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); + return; - case CMemory::MAP_SETA_DSP: - return S9xGetSetaDSP(Address)| (S9xGetSetaDSP((Address+1))<<8); + 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; + } - case CMemory::MAP_SETA_RISC: - return S9xGetST018(Address)| (S9xGetST018((Address+1))<<8); + 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); + } - case CMemory::MAP_BSX: - return S9xGetBSX(Address)| (S9xGetBSX((Address+1))<<8); + return; - case CMemory::MAP_DEBUG: -#ifdef DEBUGGER - printf ("DEBUG R(W) %06x\n", Address); -#endif - default: - case CMemory::MAP_NONE: - return (OpenBus | (OpenBus<<8)); - } + 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 S9xSetByte (uint8 Byte, uint32 Address) +inline void S9xSetPCBase (uint32 Address) { -#if defined(CPU_SHUTDOWN) - CPU.WaitAddress = 0xffffffff; -#endif - int block; - uint8 *SetAddress = Memory.WriteMap [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; + Registers.PBPC = Address & 0xffffff; + ICPU.ShiftedPB = Address & 0xff0000; - if (!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed [block]; + int block; + uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + CPU.MemSpeed = Memory.MemorySpeed[block]; + CPU.MemSpeedx2 = CPU.MemSpeed << 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; - } - *SetAddress = Byte; -#else - *(SetAddress + (Address & 0xffff)) = Byte; -#endif - return; - } + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + CPU.PCBase = GetAddress; + return; + } - switch ((pint) SetAddress) - { - case CMemory::MAP_PPU: - if(CPU.InDMAorHDMA && (Address&0xff00)==0x2100) return; - S9xSetPPU (Byte, Address & 0xffff); - 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_CPU: - S9xSetCPU (Byte, 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_DSP: -#ifdef DSP_DUMMY_LOOPS - printf("DSP Byte: %02X to %06X\n", Byte, Address); -#endif - S9xSetDSP (Byte, 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_LOROM_SRAM: - if (Memory.SRAMMask) - { - *(Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Memory.SRAMMask))=Byte; - CPU.SRAMModified = TRUE; - } - return; + case CMemory::MAP_BWRAM: + CPU.PCBase = Memory.BWRAM - 0x6000 - (Address & 0x8000); + 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_SA1RAM: + CPU.PCBase = Memory.SRAM; + 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_SPC7110_ROM: + CPU.PCBase = S9xGetBasePointerSPC7110(Address); + return; - case CMemory::MAP_BWRAM: - *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; - CPU.SRAMModified = TRUE; - return; + case CMemory::MAP_C4: + CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff); + return; - case CMemory::MAP_SA1RAM: - *(Memory.SRAM + (Address & 0xffff)) = Byte; - SA1.Executing = !SA1.Waiting; - break; + case CMemory::MAP_OBC_RAM: + CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff); + return; - case CMemory::MAP_C4: - S9xSetC4 (Byte, Address & 0xffff); - return; + case CMemory::MAP_BSX: + CPU.PCBase = S9xGetBasePointerBSX(Address); + 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; - } + case CMemory::MAP_NONE: + default: + CPU.PCBase = NULL; + 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 +inline uint8 * S9xGetBasePointer (uint32 Address) { - 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; - } + uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; -#if defined(CPU_SHUTDOWN) - CPU.WaitAddress = 0xffffffff; -#endif - int block; - uint8 *SetAddress = Memory.WriteMap [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress); - if (!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed [block] << 1; + 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)); - 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; - } + 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)); - 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_BWRAM: + return (Memory.BWRAM - 0x6000 - (Address & 0x8000)); - 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_SA1RAM: + return (Memory.SRAM); - 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_SPC7110_ROM: + return (S9xGetBasePointerSPC7110(Address)); - 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; - } + case CMemory::MAP_C4: + return (S9xGetBasePointerC4(Address & 0xffff)); - CPU.SRAMModified = TRUE; - } - return; + case CMemory::MAP_OBC_RAM: + return (S9xGetBasePointerOBC1(Address & 0xffff)); - 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; - } + case CMemory::MAP_NONE: + default: + return (NULL); + } } -INLINE uint8 *GetBasePointer (uint32 Address) +inline uint8 * S9xGetMemPointer (uint32 Address) { - uint8 *GetAddress = Memory.Map [((Address&0xffffff) >> MEMMAP_SHIFT)]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (GetAddress); + uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; - switch ((pint) GetAddress) - { -// case CMemory::MAP_SPC7110_DRAM: -#ifdef SPC7110_DEBUG -// printf("Getting Base pointer to DRAM\n"); -#endif -// { -// return s7r.bank50; -// } + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress + (Address & 0xffff)); - case CMemory::MAP_SPC7110_ROM: -#ifdef SPC7110_DEBUG - printf("Getting Base pointer to SPC7110ROM\n"); -#endif - return Get7110BasePtr(Address); + 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_SA1RAM: - return (Memory.SRAM); + 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_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_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_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 & 0x7fff)); - case CMemory::MAP_BWRAM: - return (Memory.BWRAM - 0x6000 - (Address&0x8000)); + case CMemory::MAP_SA1RAM: + return (Memory.SRAM + (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_SPC7110_ROM: + return (S9xGetBasePointerSPC7110(Address) + (Address & 0xffff)); - case CMemory::MAP_C4: - return (S9xGetBasePointerC4(Address & 0xffff)); + case CMemory::MAP_C4: + return (S9xGetMemPointerC4(Address & 0xffff)); - case CMemory::MAP_OBC_RAM: - return (S9xGetBasePointerOBC1(Address & 0xffff)); + case CMemory::MAP_OBC_RAM: + return (S9xGetMemPointerOBC1(Address & 0xffff)); - case CMemory::MAP_DEBUG: -#ifdef DEBUGGER - printf ("GBP %06x\n", Address); -#endif - default: - case CMemory::MAP_NONE: - return (0); - } + 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_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 - diff --git a/source/snes9x/gfx.cpp b/source/snes9x/gfx.cpp index 80a439d..c5bfae7 100644 --- a/source/snes9x/gfx.cpp +++ b/source/snes9x/gfx.cpp @@ -159,1830 +159,2131 @@ **********************************************************************************/ - - -#include #include "snes9x.h" -#include "cpuexec.h" -#include "gfx.h" #include "ppu.h" #include "tile.h" -#include "display.h" #include "controls.h" -#include "screenshot.h" - +#include "crosshairs.h" #include "cheats.h" - -#ifndef NGC #include "movie.h" -#endif - +#include "screenshot.h" #include "font.h" -static int font_width = 8; -static int font_height = 9; +#include "display.h" -// 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) +extern struct SCheatData Cheat; +extern struct SLineData LineData[240]; +extern struct SLineMatrixData LineMatrixData[240]; -void ComputeClipWindows (); +void S9xComputeClipWindows (void); -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; +static int font_width = 8, font_height = 9; -bool8 S9xGraphicsInit(){ - S9xInitTileRenderer(); - ZeroMemory(BlackColourMap, 256*sizeof(uint16)); +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); + +#define TILE_PLUS(t, x) (((t) & 0xfc00) | ((t + x) & 0x3ff)) + + +bool8 S9xGraphicsInit (void) +{ + 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; - Settings.BG_Forced=0; - IPPU.OBJChanged=TRUE; - IPPU.DirectColourMapsNeedRebuild=TRUE; - GFX.RealPPL=GFX.Pitch>>1; - S9xFixColourBrightness(); + GFX.DoInterlace = 0; + GFX.InterlaceFrame = 0; + GFX.RealPPL = GFX.Pitch >> 1; + IPPU.OBJChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + Settings.BG_Forced = 0; + S9xFixColourBrightness(); - 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.X2 = (uint16 *) malloc(sizeof(uint16) * 0x10000); + GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000); - 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; + 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); - 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); - } - } - } + if (!GFX.X2 || !GFX.ZERO || !GFX.SubScreen || !GFX.ZBuffer || !GFX.SubZBuffer) + { + S9xGraphicsDeinit(); + return (FALSE); + } -#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 + // 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; - /* 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); - } - } - } + for (uint32 g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g << 1; + if (g2 > MAX_GREEN) + g2 = MAX_GREEN; - GFX.Repainting = FALSE; + for (uint32 b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b << 1; + if (b2 > MAX_BLUE) + b2 = MAX_BLUE; - return TRUE; + 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); + } + } + } -FAIL: - S9xGraphicsDeinit(); - return FALSE; + // 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_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; +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]; +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; + 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; +void S9xStartScreenRefresh (void) +{ + if (IPPU.RenderThisFrame) + { + if (GFX.DoInterlace && GFX.InterlaceFrame == 0) + GFX.InterlaceFrame = 1; + else + { + if (!S9xInitUpdate()) + { + IPPU.RenderThisFrame = FALSE; + return; + } - 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 + 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; + } + } #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; - } + + if (CPU.SRAMModified) + { + if (!CPU.AutoSaveTimer) + { + if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) + CPU.SRAMModified = FALSE; + } + else + { + if (!--CPU.AutoSaveTimer) + { + S9xAutoSaveSRAM(); + CPU.SRAMModified = 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 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 { + 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) S9xSetupOBJ(); - PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags; - } -} - -bool watchesCleared=false; -#ifndef NGC -void S9xDisplayWatchedAddresses () -{ - if(!watchesCleared) - { - for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) - watches[i].on = false; - watchesCleared = true; - } - - for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) - { - if(!watches[i].on) - break; - - int32 displayNumber = 0; - - extern struct SCheatData Cheat; - for(int r=0;r= 8388608) - displayNumber -= 16777216; - - sprintf(buf, "%s,%ds = %d", watches[i].desc, watches[i].size, (int)displayNumber); } - - DisplayString(buf, 6+i, 1, false); + 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; } } -#endif -void S9xReRefresh () +static inline void RenderScreen (bool8 sub) { - if(Settings.StopEmulation) - return; + uint8 BGActive; + int D; - GFX.Repainting = TRUE; - S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight/*, Settings.SixteenBit*/); - GFX.Repainting = FALSE; + if (!sub) + { + 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 + } + + if (BGActive & 0x10) + { + 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); + 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 (void) +{ + if (IPPU.OBJChanged) + SetupOBJ(); -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; - } + // XXX: Check ForceBlank? Or anything else? + PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags; -#ifndef NGC - if(Settings.TakeScreenshot) - S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); -#endif - S9xControlEOF(); + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) + GFX.EndY = PPU.ScreenHeight - 1; - if(Settings.AutoDisplayMessages || Settings.OpenGLEnable || Settings.GlideEnable) - S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 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. - S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); - } - } else { - S9xControlEOF(); - } + if (PPU.RecomputeClipWindows) + { + S9xComputeClipWindows(); + PPU.RecomputeClipWindows = FALSE; + } - S9xApplyCheats(); + 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; -#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; + 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; -void S9xSetupOBJ() { - int SmallWidth, SmallHeight; - int LargeWidth, LargeHeight; + switch (PPU.OBJSizeSelect) + { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; - 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; + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; - /* 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. */ + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; - int Height; - uint8 S; + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; - 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); + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; - 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; - } - } - } - } + case 7: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } - /* 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; - } - } + // 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. - IPPU.OBJChanged = FALSE; + 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; } -void DrawOBJS(int D){ - CHECK_SOUND(); +static void DrawOBJS (int D) +{ + CHECK_SOUND(); - void (*DrawTile)(uint32,uint32,uint32,uint32)=NULL; - void (*DrawClippedTile)(uint32,uint32,uint32,uint32,uint32,uint32)=NULL; + void (*DrawTile) (uint32, uint32, uint32, uint32) = NULL; + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32) = NULL; - int PixWidth = IPPU.DoubleWidthPixels?2:1; - GFX.Z1=2; - BG.InterlaceLine = GFX.InterlaceFrame?8:0; + 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; - } + 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; - 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; + 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; - if (PPU.OBJ[S].HFlip) - { - TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; - BaseTile |= H_FLIP; - TileInc = -1; - } + 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; - GFX.Z2 = D+PPU.OBJ[S].Priority*4; + if (PPU.OBJ[S].HFlip) + { + TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; + BaseTile |= H_FLIP; + TileInc = -1; + } - 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= 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; + } + } + } + } + } } -#define TILE_PLUS(t, x) (((t)&0xfc00)|((t+x)&0x3ff)) +static void DrawBackground (int bg, uint8 Zh, uint8 Zl) +{ + CHECK_SOUND(); -static void DrawBackground(int bg, uint8 Zh, uint8 Zl){ - CHECK_SOUND(); + BG.TileAddress = PPU.BG[bg].NameBase << 1; - BG.TileAddress = PPU.BG[bg].NameBase<<1; + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; - 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; - 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; - 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); - void (*DrawTile)(uint32,uint32,uint32,uint32); - void (*DrawClippedTile)(uint32,uint32,uint32,uint32,uint32,uint32); - for(int clip=0; clip>(IPPU.Interlace?1:0); + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } - for(Lines=1; LinesGFX.EndY) Lines=GFX.EndY-Y+1; - VirtAlign<<=3; + 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); - 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; + for (Lines = 1; Lines < GFX.LinesPerTile - VirtAlign; Lines++) + { + if ((VOffset != LineData[Y + Lines].BG[bg].VOffset) || (HOffset != LineData[Y + Lines].BG[bg].HOffset)) + break; + } - 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); - } + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY - Y + 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); - } - } - } - } - } + 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); + } + } + } + } } -static void DrawBackgroundMosaic(int bg, uint8 Zh, uint8 Zl){ - CHECK_SOUND(); +static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl) +{ + CHECK_SOUND(); - BG.TileAddress = PPU.BG[bg].NameBase<<1; + BG.TileAddress = PPU.BG[bg].NameBase << 1; - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; + 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; + 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; + 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); + 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; + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawPix = GFX.DrawMosaicPixelMath; + else + DrawPix = GFX.DrawMosaicPixelNomath; - 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; + 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; - 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); - } + Lines = PPU.Mosaic - MosaicStart; + if (Y + MosaicStart + Lines > GFX.EndY) + Lines = GFX.EndY - Y - MosaicStart + 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; - } - } + 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; + } + } } -static void DrawBackgroundOffset(int bg, uint8 Zh, uint8 Zl, int VOffOff){ - CHECK_SOUND(); +static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff) +{ + CHECK_SOUND(); - BG.TileAddress = PPU.BG[bg].NameBase<<1; + BG.TileAddress = PPU.BG[bg].NameBase << 1; - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; - uint16 *BPS0, *BPS1, *BPS2, *BPS3; + 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; + 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; + 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; + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } - 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; + 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; - 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++; + if (HOffsetRow & 0x20) + { + s1 = BPS2; + s2 = BPS3; + } + else + { + s1 = BPS0; + s2 = BPS1; + } - 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; + s1 += (HOffsetRow & 0x1f) << 5; + s2 += (HOffsetRow & 0x1f) << 5; + s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); + int32 VOffsetOffset = s - s1; - 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 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; - 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; - } - } - } + 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; + } + } + } } -static void DrawBackgroundOffsetMosaic(int bg, uint8 Zh, uint8 Zl, int VOffOff){ - CHECK_SOUND(); +static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff) +{ + CHECK_SOUND(); - BG.TileAddress = PPU.BG[bg].NameBase<<1; + BG.TileAddress = PPU.BG[bg].NameBase << 1; - uint32 Tile; - uint16 *SC0, *SC1, *SC2, *SC3; - uint16 *BPS0, *BPS1, *BPS2, *BPS3; + 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; + 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; + 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; + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); - uint32 VOff = LineData[Y].BG[2].VOffset - 1; - uint32 HOff = LineData[Y].BG[2].HOffset; + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawPix = GFX.DrawMosaicPixelMath; + else + DrawPix = GFX.DrawMosaicPixelNomath; - 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; + for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic) + { + uint32 Y2 = IPPU.Interlace ? Y * 2 : Y; + uint32 VOff = LineData[Y].BG[2].VOffset - 1; + uint32 HOff = LineData[Y].BG[2].HOffset; - 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; + Lines = PPU.Mosaic - MosaicStart; + if (Y + MosaicStart + Lines > GFX.EndY) + Lines = GFX.EndY - Y - MosaicStart + 1; - 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++; + uint32 HOffsetRow = VOff >> Offset2Shift; + uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; + uint16 *s, *s1, *s2; - 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; + if (HOffsetRow & 0x20) + { + s1 = BPS2; + s2 = BPS3; + } + else + { + s1 = BPS0; + s2 = BPS1; + } - 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); - } + s1 += (HOffsetRow & 0x1f) << 5; + s2 += (HOffsetRow & 0x1f) << 5; + s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); + int32 VOffsetOffset = s - s1; - 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; - } - } + 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; + } + } } -static inline void DrawBackgroundMode7(int bg, void (*DrawMath)(uint32,uint32,int), void (*DrawNomath)(uint32,uint32,int), int D){ - CHECK_SOUND(); +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 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); } - -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(); + } +} - if (Settings.Paused && !unfreezing_from_stream) +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++) { - //refresh screen to show new message immediately - S9xReRefresh(); + char p = font[line][offset + w]; + + if (p == '#') + *s = Settings.DisplayColor; + else + if (p == '.') + *s = black; } } } -static inline void FontPixToScreen(char p, uint16 *s) +static void DisplayStringFromBottom (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) { - 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) + for (int i = 0 ; i < len ; i++, char_count++) { - 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 (char_count >= max_chars || (uint8) string[i] < 32) { - if(!allowWrap) + if (!allowWrap) break; - 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) + dst += font_height * GFX.RealPPL - (font_width - 1) * max_chars; + if (dst >= GFX.Screen + IPPU.RenderedScreenHeight * GFX.RealPPL) break; char_count -= max_chars; } - if((unsigned char) string[i]<32) continue; - DisplayChar(Screen, string[i]); - Screen += /*Settings.SixteenBit ? (display_fontwidth-display_hfontaccessscale)*sizeof(uint16) :*/ (display_fontwidth-display_hfontaccessscale); - } + if ((uint8) string[i] < 32) + continue; - // 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; + S9xDisplayChar(dst, string[i]); + dst += font_width - 1; } } -// input display -static void S9xDisplayPressedKeys () +static void DisplayFrameRate (void) { -#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 - - enum controllers controller; - int8 ids[4]; - - 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; - - S9xGetController(1, &controller, &ids[0],&ids[1],&ids[2],&ids[3]); -#ifndef NGC - bool singlePlayer = (controller == CTL_NONE || (controller == CTL_JOYPAD && !(MovieGetJoypad(1) & 0xffff))); + char string[10]; +#ifdef DEBUGGER + const int len = 8; + sprintf(string, "%02d/%02d %02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond, (int) IPPU.FrameCount); #else - bool singlePlayer = (controller == CTL_NONE || (controller == CTL_JOYPAD)); + const int len = 5; + sprintf(string, "%02d/%02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond); #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++) + + S9xDisplayString(string, 1, IPPU.RenderedScreenWidth - (font_width - 1) * len - 1, false); +} + +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 + + 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) { - const int id = ids[idid]; - if(id == -1) - continue; - - bool skip = false; - switch(controller) + case CTL_MOUSE: { - default: { - skip = true; - } break; - - 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, !singlePlayer?"P%d: ":" ",id+1); - - for (int i=0; i < 15; i++) - { - int j = KeyOrder[i]; - int mask = (1 << (j+1)); - string[strlen("P?: ")+i]= ((tempJoypad & mask)!=0) ? KeyMap[j] : ' '; - } - } -#endif - } 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; + 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; } - if(skip) - continue; + case CTL_SUPERSCOPE: + { + 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; + } - len=strlen(string); + 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; + } - DisplayString(string, line, 1, false); + 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] : ' '; + } - line++; + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_MP5: + { + for (int n = 0; n < 4; n++) + { + if (ids[n] != -1) + { + sprintf(string, "#%d %d: ", port, ids[n]); + uint16 pad = MovieGetJoypad(ids[n]); + 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_NONE: + { + sprintf(string, "#%d -", port); + S9xDisplayString(string, line++, 1, false); + break; + } } } } -void S9xDisplayMessages(uint16 *screen, int ppl, int width, int height, int scale) +static void DisplayWatchedAddresses (void) { - 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; + for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) + { + if (!watches[i].on) + break; + 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) - S9xDisplayFrameRate(); + DisplayFrameRate(); - if (Settings.DisplayPressedKeys==2) - S9xDisplayPressedKeys(); + if (Settings.DisplayWatchedAddresses) + DisplayWatchedAddresses(); - if (GFX.FrameDisplay -#ifndef NGC - && S9xMovieActive() -#endif -#ifdef NETPLAY_SUPPORT - || Settings.NetPlay -#endif - ) - DisplayString(GFX.FrameDisplayString, 4, 1, false); + if (Settings.DisplayPressedKeys) + DisplayPressedKeys(); + + if (Settings.DisplayMovieFrame && S9xMovieActive()) + S9xDisplayString(GFX.FrameDisplayString, 1, 1, false); if (GFX.InfoString && *GFX.InfoString) - 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; + S9xDisplayString(GFX.InfoString, 5, 1, true); } -#include "crosshairs.h" +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 + } -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 + return (0); } -void S9xDrawCrosshair(const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y) { - int16 r, rx=1, c, cx=1, W, H, rws; +void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y) +{ + if (!crosshair) + return; - 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) + 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) #endif { - 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)]; + uint16 *s = GFX.Screen + y * GFX.RealPPL + x; - 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; - } - } - } - } + 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; + } + } + } } - #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)); \ -}\ -uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \ -{ \ - return (BUILD_PIXEL2_##F(R,G,B)); \ + return (BUILD_PIXEL_##F(R, G, B)); \ } \ -void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ +\ +uint32 BuildPixel2##F (uint32 R, uint32 G, uint32 B) \ { \ - DECOMPOSE_PIXEL_##F(pixel,R,G,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); \ } _BUILD_PIXEL(RGB565) @@ -1994,73 +2295,69 @@ _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; \ -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); +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; bool8 S9xSetRenderPixelFormat (int format) { - extern uint32 current_graphic_format; + switch (format) + { + case RGB565: + _BUILD_SETUP(RGB565) + return (TRUE); - current_graphic_format = format; + case RGB555: + _BUILD_SETUP(RGB555) + return (TRUE); - 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); + 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; +#endif diff --git a/source/snes9x/gfx.h b/source/snes9x/gfx.h index 1946174..78a0fde 100644 --- a/source/snes9x/gfx.h +++ b/source/snes9x/gfx.h @@ -159,177 +159,150 @@ **********************************************************************************/ - - #ifndef _GFX_H_ #define _GFX_H_ -#include "port.h" -#include "snes9x.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]; -struct SGFX{ - // Initialize these variables - uint16 *Screen; - uint16 *SubScreen; - uint8 *ZBuffer; - uint8 *SubZBuffer; - uint32 Pitch; - uint32 ScreenSize; + struct ClipData *Clip; - uint16 *S; - uint8 *DB; + struct + { + uint8 RTOFlags; + int16 Tiles; - // 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]; + struct + { + int8 Sprite; + uint8 Line; + } OBJ[32]; + } OBJLines[SNES_HEIGHT_EXTENDED]; #ifdef GFX_MULTI_FORMAT - 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); + uint32 PixelFormat; + uint32 (*BuildPixel) (uint32, uint32, uint32); + uint32 (*BuildPixel2) (uint32, uint32, uint32); + void (*DecomposePixel) (uint32, uint32 &, uint32 &, uint32 &); #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); + 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]; }; -struct SLineData { - struct { - uint16 VOffset; - uint16 HOffset; - } BG [4]; +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; }; -#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 SLineData +{ + struct + { + uint16 VOffset; + uint16 HOffset; + } BG[4]; }; 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 SBG BG; -extern uint16 BlackColourMap [256]; -extern uint16 DirectColourMaps [8][256]; +extern uint16 BlackColourMap[256]; +extern uint16 DirectColourMaps[8][256]; +extern uint8 mul_brightness[16][32]; +extern struct SBG BG; +extern struct SGFX GFX; -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 H_FLIP 0x4000 +#define V_FLIP 0x8000 +#define BLANK_TILE 2 #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) -#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_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)) -inline uint16 COLOR_SUB(uint16 C1, uint16 C2) +#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) { uint16 mC1, mC2, v = ALPHA_BITS_MASK; @@ -345,44 +318,33 @@ inline uint16 COLOR_SUB(uint16 C1, uint16 C2) mC2 = C2 & THIRD_COLOR_MASK; if (mC1 > mC2) v += (mC1 - mC2); - return v; + return (v); } -#endif - -#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 Width, int Height); -bool8 S9xContinueUpdate (int Width, int Height); -void S9xSetPalette (); -void S9xSyncSpeed (); - -extern void (*S9xCustomDisplayString) (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); // called instead of S9xDisplayString if set to non-NULL +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 format); +bool8 S9xSetRenderPixelFormat (int); #endif -END_EXTERN_C +// external port interface which must be implemented or initialised for each port +bool8 S9xGraphicsInit (void); +void S9xGraphicsDeinit (void); +bool8 S9xInitUpdate (void); +bool8 S9xDeinitUpdate (int, int); +bool8 S9xContinueUpdate (int, int); +void S9xReRefresh (void); +void S9xSetPalette (void); +void S9xSyncSpeed (void); + +// called instead of S9xDisplayString if set to non-NULL +extern void (*S9xCustomDisplayString) (const char *, int, int, bool); #endif - diff --git a/source/snes9x/globals.cpp b/source/snes9x/globals.cpp index 65cff41..2d02e71 100644 --- a/source/snes9x/globals.cpp +++ b/source/snes9x/globals.cpp @@ -159,235 +159,236 @@ **********************************************************************************/ - - #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 "gfx.h" -#include "soundux.h" +#include "srtc.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 -START_EXTERN_C -char String[513]; +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; -struct Missing missing; +char String[513]; +uint8 OpenBus = 0; +uint8 *HDMAMemPointers[8]; +uint16 BlackColourMap[256]; +uint16 DirectColourMaps[8][256]; -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; +SnesModel M1SNES = { 1, 3, 2 }; +SnesModel M2SNES = { 2, 4, 3 }; +SnesModel *Model = &M1SNES; #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 - -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 +#ifdef ZSNES_FX +uint8 *SFXPlotTable = NULL; #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 current_graphic_format = RGB565; +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; #endif -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 -}; - -//modified per anomie Mode 5 findings -int HDMA_ModeByteCounts [8] = { - 1, 2, 2, 4, 4, 4, 2, 4 -}; - -uint16 BlackColourMap [256]; -uint16 DirectColourMaps [8][256]; - -uint32 HeadMask [4] = { -#ifdef LSB_FIRST - 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000 -#else - 0xffffffff, 0x00ffffff, 0x0000ffff, 0x000000ff -#endif -}; - -uint32 TailMask [5] = { -#ifdef LSB_FIRST - 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff -#else - 0x00000000, 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff -#endif -}; - -START_EXTERN_C -uint8 APUROM [64] = +uint16 SignExtend[2] = { - 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 + 0x0000, + 0xff00 }; -#ifdef NETPLAY_SUPPORT -struct SNetPlay NetPlay; -#endif - -// Raw SPC700 instruction cycle lengths -int32 S9xAPUCycleLengths [256] = +int HDMA_ModeByteCounts[8] = { - /* 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 + 1, 2, 2, 4, 4, 4, 2, 4 }; -// Actual data used by CPU emulation, will be scaled by APUReset routine -// to be relative to the 65c816 instruction lengths. -int32 S9xAPUCycles [256] = +uint8 mul_brightness[16][32] = { - /* 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 + { 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 } }; -END_EXTERN_C +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/language.h b/source/snes9x/language.h index 3bf22f9..a0fa607 100644 --- a/source/snes9x/language.h +++ b/source/snes9x/language.h @@ -159,30 +159,28 @@ **********************************************************************************/ +#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" -/* 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." +// 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" +#endif diff --git a/source/snes9x/spc700.h b/source/snes9x/logger.cpp similarity index 74% rename from source/snes9x/spc700.h rename to source/snes9x/logger.cpp index fb29bb7..4c75c5e 100644 --- a/source/snes9x/spc700.h +++ b/source/snes9x/logger.cpp @@ -159,79 +159,89 @@ **********************************************************************************/ +#include "snes9x.h" +#include "movie.h" +#include "logger.h" -#ifndef _SPC700_H_ -#define _SPC700_H_ +static int resetno = 0; +static int framecounter = 0; +static FILE *video = NULL; +static FILE *audio = NULL; -#define Carry 1 -#define Zero 2 -#define Interrupt 4 -#define HalfCarry 8 -#define BreakFlag 16 -#define DirectPageFlag 32 -#define Overflow 64 -#define Negative 128 -#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 +void S9xResetLogger (void) { -#ifdef LSB_FIRST - struct { uint8 A, Y; } B; -#else - struct { uint8 Y, A; } B; -#endif - uint16 W; -} YAndA; + if (!Settings.DumpStreams) + return; -struct SAPURegisters{ - uint8 P; - YAndA YA; - uint8 X; - uint8 S; - uint16 PC; -}; + char buffer[128]; -EXTERN_C struct SAPURegisters APURegisters; + S9xCloseLogger(); + framecounter = 0; -#ifdef DEBUGGER -#define APU_EXECUTE1() \ -{ \ - if (APU.Flags & TRACE_FLAG) \ - S9xTraceAPU (); \ - APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ - (*S9xApuOpcodes[*IAPU.PC]) (); \ + 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++; } -#else -#define APU_EXECUTE1() \ -{ \ - APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ - (*S9xApuOpcodes[*IAPU.PC]) (); \ -} -#endif -#endif +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(); + } + + } +} + +void S9xAudioLogger (void *samples, int length) +{ + if (audio) + fwrite(samples, 1, length, audio); +} diff --git a/source/snes9x/s9xdebug.h b/source/snes9x/logger.h similarity index 92% rename from source/snes9x/s9xdebug.h rename to source/snes9x/logger.h index 289fd9d..7689d3a 100644 --- a/source/snes9x/s9xdebug.h +++ b/source/snes9x/logger.h @@ -159,29 +159,12 @@ **********************************************************************************/ +#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/memmap.cpp b/source/snes9x/memmap.cpp index 972136a..a5ed61d 100644 --- a/source/snes9x/memmap.cpp +++ b/source/snes9x/memmap.cpp @@ -159,92 +159,721 @@ **********************************************************************************/ - -#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.h" +#include "unzip/unzip.h" #endif #ifdef JMA_SUPPORT #include "jma/s9x-jma.h" #endif -#ifdef __WIN32__ -#ifndef _XBOX -#include "win32/wsnes9x.h" // FIXME: shouldn't be necessary -#endif -#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__ -#define snprintf _snprintf // needs ANSI compliant name +#ifdef GEKKO +extern int WiiFileLoader(); +extern void WiiLoadPatch(); +extern void WiiSetupCheats(); #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)) -#endif - -#ifndef ZSNES_FX -extern struct FxInit_s SuperFX; -#else -EXTERN_C uint8 *SFXPlotTable; +#define min(a, b) (((a) < (b)) ? (a) : (b)) #endif static bool8 stopMovie = TRUE; -static char LastRomFilename[_MAX_PATH + 1] = ""; +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 const uint32 crc32Table[256] = { @@ -302,20 +931,18 @@ 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) { - if (Settings.DisplayColor == 0xffff) - { - Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); - SET_UI_COLOR(0, 255, 0); - } + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); uint8 blocks[256]; int nblocks = size >> 16; @@ -326,7 +953,7 @@ static void S9xDeinterleaveType1 (int size, uint8 *base) blocks[i * 2 + 1] = i; } - uint8 *tmp = (uint8 *) memalign(32, 0x8000); + uint8 *tmp = (uint8 *) malloc(0x8000); if (tmp) { for (int i = 0; i < nblocks * 2; i++) @@ -353,11 +980,8 @@ static void S9xDeinterleaveType1 (int size, uint8 *base) static void S9xDeinterleaveType2 (int size, uint8 *base) { // for odd Super FX images - if (Settings.DisplayColor == 0xffff || Settings.DisplayColor == BUILD_PIXEL(0, 31, 0)) - { - Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); - SET_UI_COLOR(255, 119, 25); - } + Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); + SET_UI_COLOR(255, 119, 25); uint8 blocks[256]; int nblocks = size >> 16; @@ -370,7 +994,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 *) memalign(32, 0x10000); + uint8 *tmp = (uint8 *) malloc(0x10000); if (tmp) { for (int i = 0; i < nblocks * 2; i++) @@ -400,13 +1024,10 @@ static void S9xDeinterleaveGD24 (int size, uint8 *base) if (size != 0x300000) return; - if (Settings.DisplayColor == 0xffff) - { - Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); - SET_UI_COLOR(0, 255, 255); - } + Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); + SET_UI_COLOR(0, 255, 255); - uint8 *tmp = (uint8 *) memalign(32, 0x80000); + uint8 *tmp = (uint8 *) malloc(0x80000); if (tmp) { memmove(tmp, &base[0x180000], 0x80000); @@ -424,26 +1045,26 @@ static void S9xDeinterleaveGD24 (int size, uint8 *base) bool8 CMemory::Init (void) { - RAM = (uint8 *) memalign(32, 0x20000); - SRAM = (uint8 *) memalign(32, 0x20000); - VRAM = (uint8 *) memalign(32, 0x10000); - ROM = (uint8 *) memalign(32, MAX_ROM_SIZE + 0x200 + 0x8000); + RAM = (uint8 *) malloc(0x20000); + SRAM = (uint8 *) malloc(0x20000); + VRAM = (uint8 *) malloc(0x10000); + ROM = (uint8 *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000); - 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.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.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); + 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); if (!RAM || !SRAM || !VRAM || !ROM || !IPPU.TileCache[TILE_2BIT] || @@ -497,6 +1118,7 @@ bool8 CMemory::Init (void) ROM += 0x8000; C4RAM = ROM + 0x400000 + 8192 * 8; // C4 + OBC1RAM = ROM + 0x400000; // OBC1 BIOSROM = ROM + 0x300000; // BS BSRAM = ROM + 0x400000; // BS @@ -516,9 +1138,6 @@ bool8 CMemory::Init (void) SuperFX.pvRom = (uint8 *) ROM; #endif - SDD1Data = NULL; - SDD1Index = NULL; - PostRomInitFunc = NULL; return (TRUE); @@ -526,12 +1145,6 @@ 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); @@ -572,27 +1185,10 @@ 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) @@ -763,7 +1359,136 @@ 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) { @@ -772,13 +1497,11 @@ 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 = 0xffff; + Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); CalculatedSize = 0; @@ -786,13 +1509,22 @@ 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); @@ -819,18 +1551,12 @@ again: (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a) ExtendedFormat = YEAH; - // if both vectors are invalid, it's type 1 LoROM + // if both vectors are invalid, it's type 1 interleaved LoROM if (ExtendedFormat == NOPE && ((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) && ((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000)) { - if (Settings.DisplayColor == 0xffff) - { - Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); - SET_UI_COLOR(0, 255, 0); - } - - if (!Settings.ForceInterleaved) + if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved) S9xDeinterleaveType1(totalFileSize, ROM); } @@ -861,7 +1587,7 @@ again: bool8 interleaved, tales = FALSE; - interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; + interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24; if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) { @@ -975,7 +1701,7 @@ again: if (tales) { - uint8 *tmp = (uint8 *) memalign(32, CalculatedSize - 0x400000); + uint8 *tmp = (uint8 *) malloc(CalculatedSize - 0x400000); if (tmp) { S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM..."); @@ -986,178 +1712,29 @@ again: } } - if (strncmp(LastRomFilename, filename, _MAX_PATH)) + if (strncmp(LastRomFilename, filename, PATH_MAX + 1)) { - strncpy(LastRomFilename, filename, _MAX_PATH); - LastRomFilename[_MAX_PATH] = 0; + strncpy(LastRomFilename, filename, PATH_MAX + 1); + LastRomFilename[PATH_MAX] = 0; } - FreeSDD1Data(); - if (CleanUp7110) - (*CleanUp7110)(); - ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; - -#ifndef NGC - S9xLoadCheatFile(S9xGetFilename(".cht", PATCH_DIR)); +#ifdef GEKKO + WiiSetupCheats(); +#else + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_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; @@ -1165,7 +1742,7 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); - Settings.DisplayColor = 0xffff; + Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); CalculatedSize = 0; @@ -1217,23 +1794,15 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) return (FALSE); } - FreeSDD1Data(); - if (CleanUp7110) - (*CleanUp7110)(); - ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; -#ifndef NGC - S9xLoadCheatFile(S9xGetFilename(".cht", PATCH_DIR)); -#endif + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); InitROM(); S9xInitCheatData(); -#ifndef NGC S9xApplyCheats(); -#endif S9xReset(); @@ -1252,10 +1821,9 @@ 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; -#ifndef NGC - if (!Settings.NoPatch) + if (!Settings.NoPatch) CheckForIPSPatch(cartA, HeaderCount != 0, Multi.cartSizeA); -#endif + strcpy(Multi.fileNameA, cartA); memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); } @@ -1277,17 +1845,16 @@ 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[_MAX_PATH + 1]; + char path[PATH_MAX + 1]; strcpy(path, S9xGetDirectory(BIOS_DIR)); strcat(path, SLASH_STR); @@ -1331,10 +1898,9 @@ 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]) @@ -1357,23 +1923,37 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadLastROM (void) +bool8 CMemory::LoadSRTC (void) { - if (Multi.cartType) + FILE *fp; + + fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb"); + if (!fp) return (FALSE); - bool8 r; + fread(RTCData.reg, 1, 20, fp); + fclose(fp); - stopMovie = FALSE; - r = LoadROM(LastRomFilename); - stopMovie = TRUE; + return (TRUE); +} - return (r); +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); } void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) { - if(onlyNonSavedSRAM) + if (onlyNonSavedSRAM) if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM return; @@ -1382,18 +1962,17 @@ void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) bool8 CMemory::LoadSRAM (const char *filename) { - ClearSRAM(); - -#ifndef NGC FILE *file; int size, len; - char sramName[_MAX_PATH + 1]; + char sramName[PATH_MAX + 1]; + strcpy(sramName, filename); + ClearSRAM(); if (Multi.cartType && Multi.sramSizeB) { - char temp[_MAX_PATH + 1]; + char temp[PATH_MAX + 1]; strcpy(temp, ROMFilename); strcpy(ROMFilename, Multi.fileNameB); @@ -1426,18 +2005,8 @@ bool8 CMemory::LoadSRAM (const char *filename) if (len - size == 512) memmove(SRAM, SRAM + 512, size); - if (len == size + SRTC_SRAM_PAD) - { - S9xSRTCPostLoadState(); - S9xResetSRTC(); - rtc.index = -1; - rtc.mode = MODE_READ; - } - else - S9xHardResetSRTC(); - - if (Settings.SPC7110RTC) - S9xLoadSPC7110RTC(&rtc_f9); + if (Settings.SRTC || Settings.SPC7110RTC) + LoadSRTC(); return (TRUE); } @@ -1446,7 +2015,7 @@ bool8 CMemory::LoadSRAM (const char *filename) { // The BS game's SRAM was not found // Try to read BS-X.srm instead - char path[_MAX_PATH + 1]; + char path[PATH_MAX + 1]; strcpy(path, S9xGetDirectory(SRAM_DIR)); strcat(path, SLASH_STR); @@ -1461,25 +2030,18 @@ 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); } @@ -1493,13 +2055,13 @@ bool8 CMemory::SaveSRAM (const char *filename) FILE *file; int size; - char sramName[_MAX_PATH + 1]; + char sramName[PATH_MAX + 1]; strcpy(sramName, filename); if (Multi.cartType && Multi.sramSizeB) { - char name[_MAX_PATH + 1], temp[_MAX_PATH + 1]; + char name[PATH_MAX + 1], temp[PATH_MAX + 1]; strcpy(temp, ROMFilename); strcpy(ROMFilename, Multi.fileNameB); @@ -1512,25 +2074,15 @@ 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; @@ -1541,11 +2093,12 @@ 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.SPC7110RTC) - S9xSaveSPC7110RTC(&rtc_f9); + #endif + + if (Settings.SRTC || Settings.SPC7110RTC) + SaveSRTC(); return (TRUE); } @@ -1587,7 +2140,7 @@ char * CMemory::Safe (const char *s) free(safe); safe_len = len + 1; - safe = (char *) memalign(32, safe_len); + safe = (char *) malloc(safe_len); } for (int i = 0; i < len; i++) @@ -1626,7 +2179,7 @@ char * CMemory::SafeANK (const char *s) free(safe); safe_len = len + 1; - safe = (char *) memalign(32, safe_len); + safe = (char *) malloc(safe_len); } for (int i = 0; i < len; i++) @@ -1655,9 +2208,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; @@ -1678,34 +2231,42 @@ void CMemory::ParseSNESHeader (uint8 *RomHeader) memmove(ROMId, &RomHeader[0x02], 4); - if (RomHeader[0x2A] == 0x33) - memmove(CompanyId, &RomHeader[0x00], 2); + if (RomHeader[0x2A] != 0x33) + CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F); else - sprintf(CompanyId, "%02X", RomHeader[0x2A]); + 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; + } } 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.BS = FALSE; Settings.OBC1 = FALSE; - Settings.SETA = FALSE; + Settings.SETA = 0; + Settings.SRTC = FALSE; + Settings.BS = FALSE; #ifndef ZSNES_FX SuperFX.nRomBanks = CalculatedSize >> 15; #endif - s7r.DataRomSize = 0; + SA1.Executing = FALSE; //// Parse ROM header and read ROM informatoin + CompanyId = -1; memset(ROMId, 0, 5); - memset(CompanyId, 0, 3); uint8 *RomHeader = ROM + 0x7FB0; if (ExtendedFormat == BIGFIRST) @@ -1721,73 +2282,66 @@ 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) - DSP1.version = 3; // DSP4 + Settings.DSP = 4; // DSP4 else - DSP1.version = 0; // DSP1 + Settings.DSP = 1; // DSP1 } else if (ROMType == 0x05) { if (ROMSpeed == 0x20) - DSP1.version = 1; // DSP2 + Settings.DSP = 2; // DSP2 else if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2) - DSP1.version = 2; // DSP3 + Settings.DSP = 3; // DSP3 else - DSP1.version = 0; // DSP1 + Settings.DSP = 1; // DSP1 } - if (DSP1.version != 0xff) - Settings.DSP1Master = !Settings.ForceNoDSP1; - - switch (DSP1.version) + switch (Settings.DSP) { - case 0: // DSP1 + case 1: // DSP1 if (HiROM) { - DSP1.boundary = 0x7000; - DSP1.maptype = M_DSP1_HIROM; + DSP0.boundary = 0x7000; + DSP0.maptype = M_DSP1_HIROM; } else if (CalculatedSize > 0x100000) { - DSP1.boundary = 0x4000; - DSP1.maptype = M_DSP1_LOROM_L; + DSP0.boundary = 0x4000; + DSP0.maptype = M_DSP1_LOROM_L; } else { - DSP1.boundary = 0xc000; - DSP1.maptype = M_DSP1_LOROM_S; + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP1_LOROM_S; } SetDSP = &DSP1SetByte; GetDSP = &DSP1GetByte; break; - case 1: // DSP2 - DSP1.boundary = 0x10000; - DSP1.maptype = M_DSP2_LOROM; + case 2: // DSP2 + DSP0.boundary = 0x10000; + DSP0.maptype = M_DSP2_LOROM; SetDSP = &DSP2SetByte; GetDSP = &DSP2GetByte; break; - case 2: // DSP3 - DSP1.boundary = 0xc000; - DSP1.maptype = M_DSP3_LOROM; + case 3: // DSP3 + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP3_LOROM; SetDSP = &DSP3SetByte; GetDSP = &DSP3GetByte; - DSP3_Reset(); break; - case 3: // DSP4 - DSP1.boundary = 0xc000; - DSP1.maptype = M_DSP4_LOROM; + case 4: // DSP4 + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP4_LOROM; SetDSP = &DSP4SetByte; GetDSP = &DSP4GetByte; break; @@ -1798,11 +2352,6 @@ 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) @@ -1810,6 +2359,7 @@ void CMemory::InitROM (void) // SRTC case 0x5535: Settings.SRTC = TRUE; + S9xInitSRTC(); break; // SPC7110 @@ -1817,7 +2367,7 @@ void CMemory::InitROM (void) Settings.SPC7110RTC = TRUE; case 0xF53A: Settings.SPC7110 = TRUE; - S9xSpc7110Init(); + S9xInitSPC7110(); break; // OBC1 @@ -1828,7 +2378,7 @@ void CMemory::InitROM (void) // SA1 case 0x3423: case 0x3523: - Settings.SA1 = !Settings.ForceNoSA1; + Settings.SA1 = TRUE; break; // SuperFX @@ -1836,23 +2386,20 @@ void CMemory::InitROM (void) case 0x1420: case 0x1520: case 0x1A20: - Settings.SuperFX = !Settings.ForceNoSuperFX; - if (Settings.SuperFX) - { - if (ROM[0x7FDA] == 0x33) - SRAMSize = ROM[0x7FBD]; - else - SRAMSize = 5; - } - + Settings.SuperFX = TRUE; + #ifndef ZSNES_FX + S9xInitSuperFX(); + #endif + if (ROM[0x7FDA] == 0x33) + SRAMSize = ROM[0x7FBD]; + else + SRAMSize = 5; break; // SDD1 case 0x4332: case 0x4532: - Settings.SDD1 = !Settings.ForceNoSDD1; - if (Settings.SDD1) - S9xLoadSDD1Data(); + Settings.SDD1 = TRUE; break; // ST018 @@ -1885,7 +2432,7 @@ void CMemory::InitROM (void) // C4 case 0xF320: - Settings.C4 = !Settings.ForceNoC4; + Settings.C4 = TRUE; break; } @@ -2025,11 +2572,8 @@ void CMemory::InitROM (void) // checksum if (!isChecksumOK || ((uint32) CalculatedSize > (uint32) (((1 << (ROMSize - 7)) * 128) * 1024))) { - if (Settings.DisplayColor == 0xffff || Settings.DisplayColor != BUILD_PIXEL(31, 0, 0)) - { - Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); - SET_UI_COLOR(255, 255, 0); - } + Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); + SET_UI_COLOR(255, 255, 0); } if (Multi.cartType == 4) @@ -2054,16 +2598,19 @@ 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; - - IAPU.OneCycle = SNES_APU_ONE_CYCLE_SCALED; + /* 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; CPU.FastROMSpeed = 0; ResetSpeedMap(); IPPU.TotalEmulatedFrames = 0; - Settings.Shutdown = Settings.ShutdownMaster; - //// Hack games ApplyROMFixes(); @@ -2075,34 +2622,28 @@ 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, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s CRC32: %08X", + sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X", displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"), - MapType(), Size(), KartContents(), MapMode(), TVStandard(), StaticRAMSize(), ROMId, CompanyId, ROMCRC32); + MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32); S9xMessage(S9X_INFO, S9X_ROM_INFO, String); - // 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.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; - Settings.ForceHiROM = Settings.ForceLoROM = FALSE; - Settings.ForceHeader = Settings.ForceNoHeader = FALSE; - Settings.ForceInterleaved = Settings.ForceNotInterleaved = Settings.ForceInterleaved2 = FALSE; + Settings.TakeScreenshot = FALSE; -#ifndef NGC if (stopMovie) S9xMovieStop(TRUE); -#endif + if (PostRomInitFunc) PostRomInitFunc(); @@ -2295,7 +2836,7 @@ void CMemory::map_HiROMSRAM (void) void CMemory::map_DSP (void) { - switch (DSP1.maptype) + switch (DSP0.maptype) { case M_DSP1_LOROM_S: map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); @@ -2385,7 +2926,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); @@ -2393,7 +2934,7 @@ void CMemory::Map_LoROMMap (void) map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); - if (Settings.DSP1Master) + if (Settings.DSP) map_DSP(); else if (Settings.C4) @@ -2413,7 +2954,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); @@ -2432,7 +2973,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); @@ -2449,7 +2990,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); @@ -2465,7 +3006,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); @@ -2485,7 +3026,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); @@ -2515,7 +3056,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); @@ -2538,7 +3079,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 @@ -2567,7 +3108,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); @@ -2585,7 +3126,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); @@ -2603,7 +3144,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); @@ -2645,7 +3186,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); @@ -2653,7 +3194,7 @@ void CMemory::Map_HiROMMap (void) map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); - if (Settings.DSP1Master) + if (Settings.DSP) map_DSP(); map_HiROMSRAM(); @@ -2664,7 +3205,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); @@ -2680,7 +3221,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); @@ -2700,20 +3241,18 @@ void CMemory::Map_SameGameHiROMMap (void) void CMemory::Map_SPC7110HiROMMap (void) { - //printf("Map_SPC7110HiROMMap\n"); + printf("Map_SPC7110HiROMMap\n"); map_System(); - 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(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_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_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); - - map_WRAM(); + map_WRAM(); map_WriteProtectROM(); } @@ -2786,25 +3325,11 @@ 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]; @@ -2812,7 +3337,7 @@ const char * CMemory::StaticRAMSize (void) if (SRAMSize > 16) strcpy(str, "Corrupt"); else - sprintf(str, "%dKB", (SRAMMask + 1) / 1024); + sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024); return (str); } @@ -2843,8 +3368,8 @@ const char * CMemory::Revision (void) const char * CMemory::KartContents (void) { - static char str[30]; - static char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; + static char str[64]; + static const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; char chip[16]; @@ -2852,10 +3377,10 @@ const char * CMemory::KartContents (void) return ("ROM"); if (Settings.BS) - strcpy(chip, "+BSX"); + strcpy(chip, "+BS"); else if (Settings.SuperFX) - strcpy(chip, "+SuperFX"); + strcpy(chip, "+Super FX"); else if (Settings.SDD1) strcpy(chip, "+S-DD1"); @@ -2887,8 +3412,8 @@ const char * CMemory::KartContents (void) if (Settings.SETA == ST_018) strcpy(chip, "+ST-018"); else - if (Settings.DSP1Master) - sprintf(chip, "+DSP%d", DSP1.version + 1); + if (Settings.DSP) + sprintf(chip, "+DSP-%d", Settings.DSP); else strcpy(chip, ""); @@ -2897,6 +3422,81 @@ 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) @@ -2921,10 +3521,8 @@ bool8 CMemory::match_id (const char *str) void CMemory::ApplyROMFixes (void) { -#ifdef __W32_HEAP - if (_HEAPOK != _heapchk()) - MessageBox(GUI.hWnd, "CMemory::ApplyROMFixes", "Heap Corrupt", MB_OK); -#endif + Settings.Shutdown = Settings.ShutdownMaster; + Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster; //// Warnings @@ -2950,82 +3548,128 @@ void CMemory::ApplyROMFixes (void) //// APU timing hacks :( - // This game cannot work well anyway - if (match_id("AVCJ")) // Rendering Ranger R2 + Timings.APUSpeedup = 0; + + if (!Settings.DisableGameSpecificHacks) { - IAPU.OneCycle = (int32) (15.7 * (1 << SNES_APU_ACCURACY)); - //printf("APU OneCycle hack: %d\n", IAPU.OneCycle); + 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; } - // 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); - } + S9xAPUTimingSetSpeedup(Timings.APUSpeedup); - 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 :( + //// Other timing hacks :( Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; - // 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 + if (!Settings.DisableGameSpecificHacks) { - Timings.HDMAStart -= 10; - Timings.HBlankStart -= 10; - //printf("HDMA timing hack: %d\n", Timings.HDMAStart); + // 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); + } } - // 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 + if (!Settings.DisableGameSpecificHacks) { - Timings.DMACPUSync = 20; - //printf("DMA sync: %d\n", Timings.DMACPUSync); + // 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"); + } } //// CPU speed-ups (CPU_Shutdown()) @@ -3037,8 +3681,6 @@ 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 @@ -3046,8 +3688,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; } @@ -3266,408 +3908,563 @@ void CMemory::ApplyROMFixes (void) // Super Shougi 3 - Kitaihei (J) } - //// SRAM fixes + //// SRAM initial value - if (match_na("HITOMI3")) + if (!Settings.DisableGameSpecificHacks) { - SRAMSize = 1; - SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1; + 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. } - // 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; + //// OAM hacks :( - // 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 + if (!Settings.DisableGameSpecificHacks) { - SNESGameFixes.Uniracers = TRUE; - //printf("Applied Uniracers hack.\n"); + // 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"); + } } - - /* - // 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); + } + + 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; - } + const int32 IPS_EOF = 0x00454F46l; + int32 ofs; + char fname[6]; - int32 ofs; + fname[5] = 0; + for (int i = 0; i < 5; i++) + { + int c = r->get_char(); + if (c == EOF) + return (0); + fname[i] = (char) c; + } - for (;;) - { - long len; - long rlen; - int rchar; + if (strncmp(fname, "PATCH", 5)) + return (0); - ofs = ReadInt (r, 3); - if (ofs == -1) - goto err_eof; + for (;;) + { + long len, rlen; + int rchar; - if (ofs == IPS_EOF) - break; + ofs = ReadInt(r, 3); + if (ofs == -1) + return (0); - ofs -= offset; + if (ofs == IPS_EOF) + break; - len = ReadInt (r, 2); - if (len == -1) - goto err_eof; + ofs -= offset; - /* Apply patch block */ - if (len) - { - if (ofs + len > CMemory::MAX_ROM_SIZE) - goto err_eof; + len = ReadInt(r, 2); + if (len == -1) + return (0); - 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; + if (len) + { + if (ofs + len > CMemory::MAX_ROM_SIZE) + return (0); - rchar = r->get_char(); - if (rchar == EOF) - goto err_eof; + while (len--) + { + rchar = r->get_char(); + if (rchar == EOF) + return (0); + Memory.ROM[ofs++] = (uint8) rchar; + } - if (ofs + rlen > CMemory::MAX_ROM_SIZE) - goto err_eof; + if (ofs > rom_size) + rom_size = ofs; + } + else + { + rlen = ReadInt(r, 2); + if (rlen == -1) + return (0); - while (rlen--) - Memory.ROM [ofs++] = (uint8) rchar; + rchar = r->get_char(); + if (rchar == EOF) + return (0); - if (ofs > rom_size) - rom_size = ofs; - } - } + if (ofs + rlen > CMemory::MAX_ROM_SIZE) + return (0); - // 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; + while (rlen--) + Memory.ROM[ofs++] = (uint8) rchar; -err_eof: - return 0; + if (ofs > rom_size) + rom_size = ofs; + } + } + + ofs = ReadInt(r, 3); + if (ofs != -1 && ofs - offset < rom_size) + rom_size = ofs - offset; + + return (1); } -#endif - -#ifndef NGC +#ifdef UNZIP_SUPPORT static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print) { - int port; - int l=strlen(ext); + unz_file_info info; + int port, 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; + 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); } #endif -#ifndef NGC - void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, int32 &rom_size) { - if(Settings.NoPatch) return; + if (Settings.NoPatch) + return; - 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; + 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]; - _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; - } + _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; + } #ifdef UNZIP_SUPPORT - 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; - } - } + 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; + } + } #endif - 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; - } + 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; + } } -#endif -#undef INLINE -#define INLINE -#include "getset.h" diff --git a/source/snes9x/memmap.h b/source/snes9x/memmap.h index 09ca296..224e6a3 100644 --- a/source/snes9x/memmap.h +++ b/source/snes9x/memmap.h @@ -159,26 +159,19 @@ **********************************************************************************/ +#ifndef _MEMMAP_H_ +#define _MEMMAP_H_ -#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) +#define MEMMAP_BLOCK_SIZE (0x1000) +#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) +#define MEMMAP_SHIFT (12) +#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) struct CMemory { enum -#ifdef HW_RVL - { MAX_ROM_SIZE = 0x800000 }; // Wii - lots of memory -#else - { MAX_ROM_SIZE = 0x500000 }; // GameCube - less memory to play with -#endif + { MAX_ROM_SIZE = 0x800000 }; + enum file_formats { FILE_ZIP, FILE_JMA, FILE_DEFAULT }; @@ -190,26 +183,25 @@ struct CMemory enum { - MAP_PPU, MAP_CPU, + MAP_PPU, MAP_LOROM_SRAM, MAP_LOROM_SRAM_B, MAP_HIROM_SRAM, MAP_DSP, - MAP_C4, + MAP_SA1RAM, 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 }; @@ -223,6 +215,7 @@ struct CMemory uint8 *FillRAM; uint8 *BWRAM; uint8 *C4RAM; + uint8 *OBC1RAM; uint8 *BSRAM; uint8 *BIOSROM; @@ -233,11 +226,11 @@ struct CMemory uint8 MemorySpeed[MEMMAP_NUM_BLOCKS]; uint8 ExtendedFormat; - char ROMFilename[_MAX_PATH + 1]; + char ROMFilename[PATH_MAX + 1]; char ROMName[ROM_NAME_LEN]; char RawROMName[ROM_NAME_LEN]; char ROMId[5]; - char CompanyId[3]; + int32 CompanyId; uint8 ROMRegion; uint8 ROMSpeed; uint8 ROMType; @@ -254,19 +247,11 @@ 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 (*PostRomInitFunc) (void); bool8 Init (void); void Deinit (void); - void FreeSDD1Data (void); int ScoreHiROM (bool8, int32 romoff = 0); int ScoreLoROM (bool8, int32 romoff = 0); @@ -276,10 +261,11 @@ 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 *); @@ -333,13 +319,15 @@ struct CMemory void ApplyROMFixes (void); void CheckForIPSPatch (const char *, bool8, int32 &); - const char * TVStandard (void); + void MakeRomInfoText (char *); + 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 @@ -350,21 +338,20 @@ struct SMulti uint32 sramMaskA, sramMaskB; uint32 cartOffsetA, cartOffsetB; uint8 *sramA, *sramB; - char fileNameA[_MAX_PATH + 1], fileNameB[_MAX_PATH + 1]; + char fileNameA[PATH_MAX + 1], fileNameB[PATH_MAX + 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 { @@ -379,25 +366,6 @@ 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 // NO_INLINE_SET_GET - -#endif // _memmap_h_ +#endif diff --git a/source/snes9x/messages.h b/source/snes9x/messages.h index eb55261..1e6c565 100644 --- a/source/snes9x/messages.h +++ b/source/snes9x/messages.h @@ -159,49 +159,49 @@ **********************************************************************************/ +#ifndef _MESSAGES_H_ +#define _MESSAGES_H_ - -#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 +// Types of message sent to S9xMessage() +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,4 +210,3 @@ enum { }; #endif - diff --git a/source/snes9x/missing.h b/source/snes9x/missing.h index ef7c8d8..527cb90 100644 --- a/source/snes9x/missing.h +++ b/source/snes9x/missing.h @@ -159,80 +159,82 @@ **********************************************************************************/ - +#ifdef DEBUGGER #ifndef _MISSING_H_ #define _MISSING_H_ -struct HDMA +struct MissingHDMA { - 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 { - 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; + 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; }; -EXTERN_C struct Missing missing; +extern struct Missing missing; + #endif +#endif diff --git a/source/snes9x/movie.cpp b/source/snes9x/movie.cpp new file mode 100644 index 0000000..7a1383f --- /dev/null +++ b/source/snes9x/movie.cpp @@ -0,0 +1,1171 @@ +/********************************************************************************** + 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 new file mode 100644 index 0000000..293aa7c --- /dev/null +++ b/source/snes9x/movie.h @@ -0,0 +1,241 @@ +/********************************************************************************** + 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 edb8193..d4f86d6 100644 --- a/source/snes9x/obc1.cpp +++ b/source/snes9x/obc1.cpp @@ -159,124 +159,102 @@ **********************************************************************************/ - -#include +#include "snes9x.h" #include "memmap.h" -#include "obc1.h" -static uint8 *OBC1_RAM = NULL; -int OBC1_Address; -int OBC1_BasePtr; -int OBC1_Shift; - -extern "C" +uint8 S9xGetOBC1 (uint16 Address) { -uint8 GetOBC1 (uint16 Address) -{ - switch(Address) { + switch (Address) + { case 0x7ff0: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)]; + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)]); case 0x7ff1: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1]; + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1]); case 0x7ff2: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2]; + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2]); case 0x7ff3: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3]; + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3]); case 0x7ff4: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]); } - return OBC1_RAM[Address & 0x1fff]; + return (Memory.OBC1RAM[Address - 0x6000]); } -void SetOBC1 (uint8 Byte, uint16 Address) +void S9xSetOBC1 (uint8 Byte, uint16 Address) { - switch(Address) { + switch (Address) + { case 0x7ff0: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)] = Byte; + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)] = Byte; break; - } case 0x7ff1: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1] = Byte; + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1] = Byte; break; - } case 0x7ff2: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2] = Byte; + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2] = Byte; break; - } case 0x7ff3: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3] = Byte; + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3] = Byte; break; - } case 0x7ff4: { - 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; + 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; 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; - } } - OBC1_RAM[Address & 0x1fff] = Byte; + 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; } uint8 * S9xGetBasePointerOBC1 (uint16 Address) { if (Address >= 0x7ff0 && Address <= 0x7ff6) return (NULL); - return (OBC1_RAM - 0x6000); + return (Memory.OBC1RAM - 0x6000); } uint8 * S9xGetMemPointerOBC1 (uint16 Address) { if (Address >= 0x7ff0 && Address <= 0x7ff6) return (NULL); - 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; -} - + return (Memory.OBC1RAM + Address - 0x6000); } diff --git a/source/snes9x/obc1.h b/source/snes9x/obc1.h index 9177693..0153183 100644 --- a/source/snes9x/obc1.h +++ b/source/snes9x/obc1.h @@ -159,18 +159,22 @@ **********************************************************************************/ - - #ifndef _OBC1_H_ #define _OBC1_H_ -START_EXTERN_C -uint8 GetOBC1 (uint16 Address); -void SetOBC1 (uint8 Byte, uint16 Address); +struct SOBC1 +{ + uint16 address; + uint16 basePtr; + uint16 shift; +}; + +extern struct SOBC1 OBC1; + +void S9xSetOBC1 (uint8, uint16); +uint8 S9xGetOBC1 (uint16); +void S9xResetOBC1 (void); 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 bdda64c..fa58f19 100644 --- a/source/snes9x/pixform.h +++ b/source/snes9x/pixform.h @@ -159,8 +159,6 @@ **********************************************************************************/ - - #ifndef _PIXFORM_H_ #define _PIXFORM_H_ @@ -168,229 +166,226 @@ 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(Pixel,R,G,B) ((*GFX.DecomposePixel) (Pixel, 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(PIX, R, G, B) ((*GFX.DecomposePixel) (PIX, R, G, B)) -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; +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; #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_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 +#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 /* 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_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 +#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 /* 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 -/* 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 CONCAT(X, Y) X##Y -#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) +// 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 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 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 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 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 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 +#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) #endif +#endif diff --git a/source/snes9x/port.h b/source/snes9x/port.h index ec23aba..98f6e95 100644 --- a/source/snes9x/port.h +++ b/source/snes9x/port.h @@ -159,243 +159,142 @@ **********************************************************************************/ - - #ifndef _PORT_H_ #define _PORT_H_ +#include +#include #include - -#ifndef STORM -//#include +#ifndef GEKKO +#include +#endif +#include #include -#else +#ifdef HAVE_STRINGS_H #include -#include #endif - -#ifndef ACCEPT_SIZE_T -#ifdef __WIN32__ -#define ACCEPT_SIZE_T int -#else -#define ACCEPT_SIZE_T unsigned int -#endif -#endif - #include -/* #define PIXEL_FORMAT RGB565 */ +#ifdef __WIN32__ +#include +#endif + +#define CHECK_SOUND() #define GFX_MULTI_FORMAT -#ifndef NOASM -//#define USE_X86_ASM +#ifdef __WIN32__ +#define RIGHTSHIFT_IS_SAR +#define SNES_JOY_READ_CALLBACKS #endif #ifdef __MACOSX__ - - #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__ */ +#undef GFX_MULTI_FORMAT +#define PIXEL_FORMAT RGB555 +#endif #ifndef snes9x_types_defined #define snes9x_types_defined - -typedef unsigned char bool8; - +typedef unsigned char bool8; #ifdef HAVE_STDINT_H #include - -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 */ - +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 #ifdef PTR_NOT_INT -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 +typedef long pint; +#else +typedef int pint; #endif - -# 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" +#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++ +__extension__ +#endif +typedef long long int64; +typedef unsigned long long uint64; +#endif // __WIN32__ +#endif // HAVE_STDINT_H +#endif // snes9x_types_defined #ifndef TRUE -#define TRUE 1 +#define TRUE 1 #endif - #ifndef FALSE -#define FALSE 0 +#define FALSE 0 #endif -#ifdef STORM -#define EXTERN_C -#define START_EXTERN_C -#define END_EXTERN_C +#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 #else -#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 +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH #endif #endif #ifndef __WIN32__ - -#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 +#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 #else -#define CHECK_SOUND() +#define strcasecmp stricmp +#define strncasecmp strnicmp +#define S9xDisplayString S9xCustomDisplayString #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) -#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" +#define SIG_PF void (*) (int) #endif #ifdef __linux -#define TITLE "Snes9X: Linux" +#define TITLE "Snes9x: Linux" #define SYS_CONFIG_FILE "/etc/snes9x/snes9x.conf" #endif @@ -403,41 +302,32 @@ EXTERN_C void MixSound(void); #define TITLE "Snes9x" #endif -#ifdef STORM -#define STATIC -#define strncasecmp strnicmp +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) +#define LSB_FIRST +#define FAST_LSB_WORD_ACCESS #else -#define STATIC static +#define MSB_FIRST #endif #ifdef FAST_LSB_WORD_ACCESS -#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) +#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) #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) = (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) +#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) #endif -#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 edb9927..738cfa2 100644 --- a/source/snes9x/ppu.cpp +++ b/source/snes9x/ppu.cpp @@ -159,57 +159,41 @@ **********************************************************************************/ - - #include "snes9x.h" #include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "missing.h" -#include "apu.h" #include "dma.h" -#include "gfx.h" -#include "display.h" -#include "sa1.h" +#include "apu/apu.h" +#include "fxemu.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 - -#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); +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" #endif -uint32 justifiers=0xFFFF00AA; -uint8 in_bit=0; +extern uint8 *HDMAMemPointers[8]; -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 -#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 + + 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. @@ -219,7 +203,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); @@ -229,43 +213,31 @@ static inline void S9xLatchCounters (bool force) PPU.HBeamPosLatched = (uint16) (hc / ONE_DOT_CYCLE); - // 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; + } - 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; - } + 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; - // 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; + Memory.FillRAM[0x213f] |= 0x40; } PPU.GunVLatch = 1000; @@ -277,10 +249,10 @@ void S9xCheckMissingHTimerPosition (int32 hc) if (PPU.HTimerPosition == hc) { if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_H_BEAM_IRQ_SOURCE); + S9xSetIRQ(PPU_IRQ_SOURCE); else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + S9xSetIRQ(PPU_IRQ_SOURCE); } } @@ -301,10 +273,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_H_BEAM_IRQ_SOURCE); + S9xSetIRQ(PPU_IRQ_SOURCE); else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + S9xSetIRQ(PPU_IRQ_SOURCE); } } @@ -312,9 +284,9 @@ void S9xUpdateHVTimerPosition (void) { if (PPU.HTimerEnabled) { -#ifdef DEBUGGER + #ifdef DEBUGGER missing.hirq_pos = PPU.IRQHBeamPos; -#endif + #endif if (PPU.IRQHBeamPos != 0) { // IRQ_read @@ -326,6 +298,7 @@ void S9xUpdateHVTimerPosition (void) if (PPU.IRQHBeamPos > 326) PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); } + PPU.HTimerPosition += 14; // /IRQ PPU.HTimerPosition += 4; @@ -451,2402 +424,1761 @@ 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 S9xFixColourBrightness (void) { - 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) { -// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, Byte, Address); + // MAP_PPU: $2000-$3FFF - // Take care of DMA wrapping - if(CPU.InDMAorHDMA && Address>0x21ff) Address=0x2100+(Address&0xff); + if (CPU.InDMAorHDMA) + { + if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) + { + // S9xSetPPU() is called to write to DMA[].AAddress + if ((Address & 0xff00) == 0x2100) + { + // Cannot access to Address Bus B ($2100-$21ff) via (H)DMA + return; + } + else + { + // 0x2000-0x3FFF is connected to Address Bus A + // SA1, SuperFX and SRTC are mapped here + // I don't bother for now... + return; + } + } + else + { + // S9xSetPPU() is called to read from $21xx + // Take care of DMA wrapping + if (Address > 0x21ff) + Address = 0x2100 + (Address & 0xff); + } + } - if (Address <= 0x219F) +#ifdef DEBUGGER + if (CPU.InHDMA) + S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte); +#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: - // Brightness and screen blank bit - if (Byte != Memory.FillRAM [0x2100]) - { - FLUSH_REDRAW (); - if (PPU.Brightness != (Byte & 0xF)) + case 0x2100: // INIDISP + if (Byte != Memory.FillRAM[0x2100]) { - IPPU.ColorsChanged = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - PPU.Brightness = Byte & 0xF; - S9xFixColourBrightness (); - if (PPU.Brightness > IPPU.MaxBrightness) - IPPU.MaxBrightness = PPU.Brightness; + 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) != (Byte & 0x80)) + + if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) { - 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; + PPU.OAMAddr = PPU.SavedOAMAddr; - 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) - { - 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; - } - 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 (Byte & 0x02) - missing.sprite_double_height = 1; - - if (Byte & 1) - missing.interlace = 1; -#endif - if((Memory.FillRAM [0x2133] ^ Byte)&3) - { - FLUSH_REDRAW (); - if((Memory.FillRAM [0x2133] ^ Byte)&2) + uint8 tmp = 0; + if (PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xfe) >> 1; + if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) + { + PPU.FirstSprite = tmp; IPPU.OBJChanged = TRUE; - if(PPU.BGMode==5 || PPU.BGMode==6) - IPPU.Interlace = Byte&1; - IPPU.InterlaceOBJ = Byte&2; + } + + PPU.OAMFlip = 0; } - } - break; - case 0x2134: - case 0x2135: - case 0x2136: - // Matrix 16bit x 8bit multiply result (read-only) - return; + break; - 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) + case 0x2101: // OBSEL + if (Byte != Memory.FillRAM[0x2101]) { -#ifdef DEBUGGER - missing.unknownppu_write = Address; - if (Settings.TraceUnknownRegisters) + 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)) { - sprintf (String, "Unknown register write: $%02X->$%04X\n", - Byte, Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif } -#endif } else { - if (!Settings.SuperFX) + if (PPU.FirstSprite != 0) { - return; + PPU.FirstSprite = 0; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif } + } -#ifdef ZSNES_FX - Memory.FillRAM [Address] = Byte; - if (Address < 0x3040) - S9xSuperFXWriteReg (Byte, Address); -#else - switch (Address) + 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) { - 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 (); - } + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_sub = 1; 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; + missing.fixed_colour_sub = 1; } -#endif - return; + else + { + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_add = 1; + else + missing.fixed_colour_add = 1; + } + #endif } - } - Memory.FillRAM[Address] = Byte; -} + break; -/******************************************************************************/ -/* S9xGetPPU() */ -/* This function retrieves a PPU Register */ -/******************************************************************************/ -uint8 S9xGetPPU (uint16 Address) -{ - uint8 byte = OpenBus; - - if(Address<0x2100)//not a real PPU reg - return OpenBus; //treat as unmapped memory returning last byte on the bus - - // 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 - { - byte = PPU.OAMData [((PPU.OAMAddr&0x10f) << 1) + 1]; - PPU.OAMAddr=(PPU.OAMAddr+1)&0x1ff; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + case 0x2132: // COLDATA + if (Byte != Memory.FillRAM[0x2132]) { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; -#ifdef DEBUGGER - missing.sprite_priority_rotation = 1; -#endif + FLUSH_REDRAW(); + if (Byte & 0x80) + PPU.FixedColourBlue = Byte & 0x1f; + if (Byte & 0x40) + PPU.FixedColourGreen = Byte & 0x1f; + if (Byte & 0x20) + PPU.FixedColourRed = Byte & 0x1f; } - } - } 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)) + + break; + + case 0x2133: // SETINI + if (Byte != Memory.FillRAM[0x2133]) { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; -#ifdef DEBUGGER - missing.sprite_priority_rotation = 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; + + 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; } - 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) - { - 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 (!Settings.SuperFX) - return OpenBus; -#ifdef ZSNES_FX - if (Address < 0x3040) - byte = S9xSuperFXReadReg (Address); - else - byte = Memory.FillRAM [Address]; - -#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]; - -//if (Address != 0x3030 && Address != 0x3031) -//printf ("%04x\n", Address); -#ifdef CPU_SHUTDOWN - if (Address == 0x3030) - { - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; } else -#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); -} - -/******************************************************************************/ -/* 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; - switch (Address) + if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) { - case 0x4016: - S9xSetJoypadLatch(byte&1); - break; - case 0x4017: - break; - default: -#ifdef DEBUGGER - missing.unknowncpu_write = Address; + 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 register write: $%02X->$%04X\n", - byte, Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + sprintf(String, "Unknown register write: $%02X->$%04X\n", Byte, Address); + S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); } -#endif - break; + } + #endif + } + + Memory.FillRAM[Address] = Byte; +} + +uint8 S9xGetPPU (uint16 Address) +{ + // MAP_PPU: $2000-$3FFF + + if (Address < 0x2100) + return (OpenBus); + + 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); + else + // $2200-$3FFF are connected to Address Bus A + // SA1, SuperFX and SRTC are mapped here + // I don't bother for now... + return (OpenBus); + } + else + { + // S9xGetPPU() is called to write to $21xx + // Take care of DMA wrapping + if (Address > 0x21ff) + Address = 0x2100 + (Address & 0xff); + } + } + + 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)); + else + if (Address <= 0x2183) + { + uint8 byte; + + 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); + + 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); } } 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 0x4200: - // NMI, V & H IRQ and joypad reading enable flags - pV = PPU.VTimerEnabled; + case 0x21c2: + if (Model->_5C77 == 2) + return (0x20); + return (OpenBus); - if (byte & 0x20) + case 0x21c3: + if (Model->_5C77 == 2) + return (0); + return (OpenBus); + + default: + return (OpenBus); + } + } +} + +void S9xSetCPU (uint8 Byte, uint16 Address) +{ + if (Address < 0x4200) + { + CPU.Cycles += ONE_CYCLE; // XSlow + + 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 { - 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; - + uint32 res = Memory.FillRAM[0x4202] * Byte; + // FIXME: The update occurs 8 machine cycles after $4203 is set. Memory.FillRAM[0x4216] = (uint8) res; Memory.FillRAM[0x4217] = (uint8) (res >> 8); break; } - 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; - Memory.FillRAM[0x4214] = (uint8)div; + case 0x4204: // WRDIVL + case 0x4205: // WRDIVH + break; + + case 0x4206: // WRDIVB + { + 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; Memory.FillRAM[0x4215] = div >> 8; - Memory.FillRAM[0x4216] = (uint8)rem; + Memory.FillRAM[0x4216] = (uint8) rem; Memory.FillRAM[0x4217] = rem >> 8; break; } - case 0x4207: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; - - if (PPU.IRQHBeamPos != d) - S9xUpdateHVTimerPosition(); - - break; - - case 0x4208: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); - - if (PPU.IRQHBeamPos != d) - S9xUpdateHVTimerPosition(); - - break; - - 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) - { - 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); + 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; - } - 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; + 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; + + 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; + + 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 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; + + 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; + + case 0x420d: // MEMSEL + if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1)) + { + if (Byte & 1) + { + CPU.FastROMSpeed = ONE_CYCLE; + #ifdef DEBUGGER + missing.fast_rom = 1; + #endif + } + else + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + + Memory.FixROMSpeed(); + } + + 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; } - Memory.FillRAM [Address] = byte; + } + + Memory.FillRAM[Address] = Byte; } -/******************************************************************************/ -/* S9xGetCPU() */ -/* This function retrieves a CPU/DMA Register */ -/******************************************************************************/ uint8 S9xGetCPU (uint16 Address) { - int d; - uint8 byte; -// fprintf(stderr, "read from %04x\n", Address); - - if (Address < 0x4200) + if (Address < 0x4200) { - if(Address==0x4016 || Address==0x4017) + #ifdef SNES_JOY_READ_CALLBACKS + extern bool8 pad_read; + if (Address == 0x4016 || Address == 0x4017) { - extern bool8 pad_read; -#ifdef SNES_JOY_READ_CALLBACKS S9xOnSNESPadRead(); -#endif - pad_read = true; + pad_read = TRUE; } + #endif + + CPU.Cycles += ONE_CYCLE; // XSlow - CPU.Cycles += ONE_CYCLE; switch (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; + case 0x4016: // JOYSER0 + case 0x4017: // JOYSER1 + return (S9xReadJOYSERn(Address)); + default: + return (OpenBus); } -// return (Memory.FillRAM [Address]); } - 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; - - 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); - - 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) - { - extern bool8 pad_read; -#ifdef SNES_JOY_READ_CALLBACKS - S9xOnSNESPadRead(); -#endif - pad_read = true; - } - // 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) + else + if ((Address & 0xff80) == 0x4300) { - sprintf (String, "Unknown register read: $%04X\n", Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } + if (CPU.InDMAorHDMA) + return (OpenBus); -#endif + int d = (Address >> 4) & 0x7; - if(Address>= 0x4800&&Settings.SPC7110) - return S9xGetSPC7110(Address); - - if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) + switch (Address & 0xf) { - return Memory.FillRAM[Address]; - } + 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)); - return OpenBus; - } + 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); + } + } + else + { + 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); + } + } } -void S9xResetPPU () +void S9xResetPPU (void) { - S9xSoftResetPPU(); - S9xControlsReset(); - IPPU.PreviousLine = IPPU.CurrentLine = 0; + S9xSoftResetPPU(); + S9xControlsReset(); PPU.M7HOFS = 0; PPU.M7VOFS = 0; PPU.M7byte = 0; } -void S9xSoftResetPPU () +void S9xSoftResetPPU (void) { - S9xControlsSoftReset(); - PPU.BGMode = 0; - PPU.BG3Priority = 0; - PPU.Brightness = 0; + S9xControlsSoftReset(); + PPU.VMA.High = 0; PPU.VMA.Increment = 1; PPU.VMA.Address = 0; PPU.VMA.FullGraphicCount = 0; PPU.VMA.Shift = 0; - for (uint8 B = 0; B != 4; B++) - { - 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.WRAM = 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; + for (int c = 0; c < 4; c++) + { + 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.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.BGMode = 0; + PPU.BG3Priority = 0; PPU.CGFLIP = 0; - int c; - for (c = 0; c < 256; c++) + PPU.CGFLIPRead = 0; + PPU.CGADD = 0; + + for (int 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.OAMFlip = 0; - PPU.OAMTileAddress = 0; - PPU.OAMAddr = 0; - PPU.IRQVBeamPos = 0x1ff; + PPU.HTimerEnabled = FALSE; + PPU.VTimerEnabled = FALSE; + PPU.HTimerPosition = Timings.H_Max + 1; + PPU.VTimerPosition = Timings.V_Max + 1; PPU.IRQHBeamPos = 0x1ff; - PPU.VBeamPosLatched = 0; - PPU.HBeamPosLatched = 0; + PPU.IRQVBeamPos = 0x1ff; 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; - PPU.CGFLIPRead = 0; - PPU.Need16x8Mulitply = FALSE; - IPPU.ColorsChanged = 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.Need16x8Mulitply = FALSE; + PPU.BGnxOFSbyte = 0; + PPU.HDMA = 0; PPU.HDMAEnded = 0; - IPPU.MaxBrightness = 0; - IPPU.LatchedBlanking = 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.OBJChanged = TRUE; - IPPU.RenderThisFrame = TRUE; IPPU.DirectColourMapsNeedRebuild = TRUE; - 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); + 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 @@ -2856,197 +2188,30 @@ void S9xSoftResetPPU () 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.XB = NULL; - for (c = 0; c < 256; c++) - IPPU.ScreenColors [c] = c; - S9xFixColourBrightness (); - IPPU.PreviousLine = IPPU.CurrentLine = 0; + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; - for (c = 0; c < 2; c++) - memset (&IPPU.Clip [c], 0, sizeof (struct ClipData)); + S9xFixColourBrightness(); - 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 (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 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 35b6d45..02c0e89 100644 --- a/source/snes9x/ppu.h +++ b/source/snes9x/ppu.h @@ -159,630 +159,578 @@ **********************************************************************************/ - - #ifndef _PPU_H_ #define _PPU_H_ -#define FIRST_VISIBLE_LINE 1 +#define FIRST_VISIBLE_LINE 1 -extern uint8 GetBank; -extern uint16 SignExtend [2]; +#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 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 MAX_2BIT_TILES 4096 +#define MAX_4BIT_TILES 2048 +#define MAX_8BIT_TILES 1024 -#define MAX_2BIT_TILES 4096 -#define MAX_4BIT_TILES 2048 -#define MAX_8BIT_TILES 1024 +#define CLIP_OR 0 +#define CLIP_AND 1 +#define CLIP_XOR 2 +#define CLIP_XNOR 3 -#define PPU_H_BEAM_IRQ_SOURCE (1 << 0) -#define PPU_V_BEAM_IRQ_SOURCE (1 << 1) +#define PPU_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 { - 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]; +struct InternalPPU +{ + struct ClipData Clip[2][6]; + bool8 ColorsChanged; + bool8 OBJChanged; + bool8 DirectColourMapsNeedRebuild; + 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 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]; + 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; }; struct SOBJ { - int16 HPos; - uint16 VPos; - uint16 Name; - uint8 VFlip; - uint8 HFlip; - uint8 Priority; - uint8 Palette; - uint8 Size; + int16 HPos; + uint16 VPos; + uint8 HFlip; + uint8 VFlip; + uint16 Name; + uint8 Priority; + uint8 Palette; + uint8 Size; }; -struct SPPU { - uint8 BGMode; - uint8 BG3Priority; - uint8 Brightness; +struct SPPU +{ + struct + { + bool8 High; + uint8 Increment; + uint16 Address; + uint16 Mask1; + uint16 FullGraphicCount; + uint16 Shift; + } VMA; - struct { - bool8 High; - uint8 Increment; - uint16 Address; - uint16 Mask1; - uint16 FullGraphicCount; - uint16 Shift; - } VMA; + uint32 WRAM; - struct { - uint16 SCBase; - uint16 VOffset; - uint16 HOffset; - uint8 BGSize; - uint16 NameBase; - uint16 SCSize; - } BG [4]; + struct + { + uint16 SCBase; + uint16 HOffset; + uint16 VOffset; + uint8 BGSize; + uint16 NameBase; + uint16 SCSize; + } BG[4]; - bool8 CGFLIP; - uint16 CGDATA [256]; - uint8 FirstSprite; - uint8 LastSprite; - struct SOBJ OBJ [128]; - uint8 OAMPriorityRotation; - uint16 OAMAddr; - uint8 RangeTimeOver; + uint8 BGMode; + uint8 BG3Priority; - uint8 OAMFlip; - uint16 OAMTileAddress; - uint16 IRQVBeamPos; - uint16 IRQHBeamPos; - uint16 VBeamPosLatched; - uint16 HBeamPosLatched; + bool8 CGFLIP; + uint8 CGFLIPRead; + uint8 CGADD; + uint16 CGDATA[256]; - uint8 HBeamFlip; - uint8 VBeamFlip; - uint8 HVBeamCounterLatched; + struct SOBJ OBJ[128]; + bool8 OBJThroughMain; + bool8 OBJThroughSub; + bool8 OBJAddition; + uint16 OBJNameBase; + uint16 OBJNameSelect; + uint8 OBJSizeSelect; - short MatrixA; - short MatrixB; - short MatrixC; - short MatrixD; - short CentreX; - short CentreY; - short M7HOFS; - short M7VOFS; + uint16 OAMAddr; + uint16 SavedOAMAddr; + uint8 OAMPriorityRotation; + uint8 OAMFlip; + uint8 OAMReadFlip; + uint16 OAMTileAddress; + uint16 OAMWriteRegister; + uint8 OAMData[512 + 32]; - 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; + uint8 FirstSprite; + uint8 LastSprite; + uint8 RangeTimeOver; - uint16 OAMWriteRegister; - uint8 BGnxOFSbyte; - uint8 M7byte; - uint8 OpenBus1; - uint8 OpenBus2; - uint16 GunVLatch; - uint16 GunHLatch; - short VTimerPosition; + bool8 HTimerEnabled; + bool8 VTimerEnabled; + short HTimerPosition; + short VTimerPosition; + uint16 IRQHBeamPos; + uint16 IRQVBeamPos; - uint8 HDMA; - uint8 HDMAEnded; + 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; }; -#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); +extern uint16 SignExtend[2]; +extern struct SPPU PPU; +extern struct InternalPPU IPPU; +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); - -extern struct SPPU PPU; -extern struct SDMA DMA [8]; -extern struct InternalPPU IPPU; -END_EXTERN_C +void S9xFixColourBrightness (void); +void S9xDoAutoJoypad (void); #include "gfx.h" #include "memmap.h" -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() +typedef struct { - GetBank = 0; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) - GetBank = 1; + uint8 _5C77; + uint8 _5C78; + uint8 _5A22; +} SnesModel; - 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 ? */ +extern SnesModel *Model; +extern SnesModel M1SNES; +extern SnesModel M2SNES; - return (GetBank); +#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(); } -STATIC inline void FLUSH_REDRAW () +static inline void REGISTER_2104 (uint8 Byte) { - if (IPPU.PreviousLine != IPPU.CurrentLine) - S9xUpdateScreen (); -} + 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; -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; + // 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; + } - // 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.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.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.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; - int addr = (PPU.OAMAddr << 1); + 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; + } + } - 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; + 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. :( -#define CHECK_INBLANK \ -{ \ - if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ +#ifdef DEBUGGER +#define CHECK_INBLANK() \ + if (!PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ { \ - return; \ - } \ -} \ + 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() \ + if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ + return; +#endif -STATIC inline void REGISTER_2118 (uint8 Byte) +static inline void REGISTER_2118 (uint8 Byte) { - CHECK_INBLANK; + 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 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; + 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_2118_tile (uint8 Byte) +static inline void REGISTER_2119_tile (uint8 Byte) { - CHECK_INBLANK; + 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) + 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) { - printf ("VRAM write word: $%04X (%d,%d)\n", PPU.VMA.Address, - Memory.FillRAM[0x2115] & 3, - (Memory.FillRAM [0x2115] & 0x0c) >> 2); + 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++; } -#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)) + else { - 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]); + 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.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; + + PPU.CGFLIP ^= 1; } -STATIC inline void REGISTER_2180(uint8 Byte) +static inline void REGISTER_2180 (uint8 Byte) { - Memory.RAM[PPU.WRAM++] = Byte; - PPU.WRAM &= 0x1FFFF; - Memory.FillRAM [0x2180] = 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/reader.cpp b/source/snes9x/reader.cpp new file mode 100644 index 0000000..d69b529 --- /dev/null +++ b/source/snes9x/reader.cpp @@ -0,0 +1,337 @@ +/********************************************************************************** + 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. +**********************************************************************************/ + +// 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" + + +// Generic constructor/destructor + +Reader::Reader (void) +{ + 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 + { + if (gets(buf, sizeof(buf)) == NULL) + { + eof = true; + break; + } + + ret.append(buf); + } + while (*ret.rbegin() != '\n'); + + return (ret); +} + +// snes9x.h STREAM reader + +fReader::fReader (STREAM f) +{ + fp = f; +} + +fReader::~fReader (void) +{ + return; +} + +int fReader::get_char (void) +{ + return (GETC_STREAM(fp)); +} + +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; + } + + c = *head; + head++; + numbytes--; + + return ((int) c); +} + +char * unzReader::gets (char *buf, size_t len) +{ + size_t i; + int c; + + for (i = 0; i < len - 1; i++) + { + c = get_char(); + if (c == EOF) + { + if (i == 0) + return (NULL); + break; + } + + buf[i] = (char) c; + if (buf[i] == '\n') + break; + } + + buf[i] = '\0'; + + return (buf); +} + +size_t unzReader::read (char *buf, size_t len) +{ + 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); +} + +#endif diff --git a/source/snes9x/dsp1.h b/source/snes9x/reader.h similarity index 84% rename from source/snes9x/dsp1.h rename to source/snes9x/reader.h index 8a1074b..dd8e305 100644 --- a/source/snes9x/dsp1.h +++ b/source/snes9x/reader.h @@ -159,64 +159,54 @@ **********************************************************************************/ +#ifndef _READER_H_ +#define _READER_H_ - -#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 +class Reader { - M_DSP1_LOROM_S, - M_DSP1_LOROM_L, - M_DSP1_HIROM, - M_DSP2_LOROM, - M_DSP3_LOROM, - M_DSP4_LOROM + 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; }; -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]; +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); - uint8 temp_save_data [406]; - uint32 maptype; - uint32 boundary; + private: + STREAM fp; }; -START_EXTERN_C -void S9xResetDSP1 (); -uint8 S9xGetDSP (uint16 Address); -void S9xSetDSP (uint8 Byte, uint16 Address); -void S9xPreSaveDSP1(); -void S9xPostLoadDSP1(); +#ifdef UNZIP_SUPPORT -extern struct SDSP1 DSP1; +#define unz_BUFFSIZ 1024 -END_EXTERN_C +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); + private: + unzFile file; + char buffer[unz_BUFFSIZ]; + char *head; + size_t numbytes; +}; + +#endif #endif diff --git a/source/snes9x/s9xdebug.cpp b/source/snes9x/s9xdebug.cpp deleted file mode 100644 index 384f490..0000000 --- a/source/snes9x/s9xdebug.cpp +++ /dev/null @@ -1,2307 +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 -#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/sa1.cpp b/source/snes9x/sa1.cpp index 81d4163..cc1c765 100644 --- a/source/snes9x/sa1.cpp +++ b/source/snes9x/sa1.cpp @@ -159,894 +159,936 @@ **********************************************************************************/ - - #include "snes9x.h" -#include "ppu.h" -#include "cpuexec.h" +#include "memmap.h" -#include "sa1.h" +uint8 SA1OpenBus; -uint8 SA1OpenBus; +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); -static void S9xSA1CharConv2 (); -static void S9xSA1DMA (); -static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift); -void S9xSA1Init () +void S9xSA1Init (void) { - 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; + 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; } -void S9xSA1Reset () +static void S9xSA1Reset (void) { - 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; - - S9xSA1UnpackStatus(); - S9xSA1FixCycles (); - SA1.Executing = TRUE; - SA1.BWRAM = Memory.SRAM; - Memory.FillRAM [0x2225] = 0; -} - -void S9xSA1SetBWRAMMemMap (uint8 val) -{ - int c; - - if (val & 0x80) - { - for (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; - } - 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 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; -} - -uint8 S9xSA1GetByte (uint32 address) -{ - uint8 *GetAddress = SA1.Map [(address&0xffffff) >> MEMMAP_SHIFT]; - 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); - - case CMemory::MAP_DEBUG: - default: -#ifdef DEBUGGER -// printf ("R(B) %06x\n", address); -#endif - return SA1OpenBus; - } -} - -uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) -{ - 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]; - - 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) - { - 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); - } - 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) -{ - 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; - - uint8 *GetAddress = SA1.Map [(address&0xffffff) >> MEMMAP_SHIFT]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - SA1.PCBase = GetAddress; - return; - } - - switch ((pint) GetAddress) - { - case CMemory::MAP_SA1RAM: - SA1.PCBase = Memory.SRAM; - 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_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_DEBUG: -#ifdef DEBUGGER - printf ("SBP %06x\n", address); -#endif - - default: - case CMemory::MAP_NONE: + SA1.WaitingForInterrupt = FALSE; SA1.PCBase = NULL; - return; - } + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + + S9xSA1UnpackStatus(); + S9xSA1FixCycles(); + SA1.Executing = TRUE; + SA1.BWRAM = Memory.SRAM; + Memory.FillRAM[0x2225] = 0; } -void S9xSA1ExecuteDuringSleep () +static 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; + } + + SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; + } + else + { + 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; + } +} + +void S9xSA1PostLoadState (void) +{ + 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) + if (SA1.Executing) { - S9xSA1MainLoop (); - CPU.Cycles += TWO_CYCLES * 2; + while (CPU.Cycles < CPU.NextEvent) + { + S9xSA1MainLoop(); + CPU.Cycles += TWO_CYCLES * 2; + } } - } #endif } -void S9xSetSA1MemMap (uint32 which1, uint8 map) +static void S9xSetSA1MemMap (uint32 which1, uint8 map) { - int c; - int start = which1 * 0x100 + 0xc00; - int start2 = which1 * 0x200; + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; - if (which1 >= 2) - start2 += 0x400; + if (which1 >= 2) + start2 += 0x400; - for (c = 0; c < 0x100; c += 16) - { - uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 12)]; - int i; + 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 (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; - } + 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) { -// 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) + switch (address) { - S9xSA1ReadVariableLengthData (TRUE, FALSE); + 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 (byte); - } - default: - printf ("R: %04x\n", address); - break; - } - return (Memory.FillRAM [address]); + + 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; + 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 & 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 (byte & 0x80) + + 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) { - Memory.FillRAM [0x2301] |= 0x80; - if (Memory.FillRAM [0x220a] & 0x80) - { SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - } + SA1.IRQActive |= DMA_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; } - 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; +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; - 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 (); - } + if (no_shift) + shift = 0; 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; + if (shift == 0) + shift = 16; - 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; + uint8 s = shift + SA1.variable_bit_pos; - case 0x224f: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) + if (s >= 16) { - // 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 (); - } + addr += (s >> 4) << 1; + s &= 15; } - 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) + uint32 data = S9xSA1GetWord(addr) | (S9xSA1GetWord(addr + 2) << 16); + + data >>= s; + Memory.FillRAM[0x230c] = (uint8) data; + Memory.FillRAM[0x230d] = (uint8) (data >> 8); + + if (inc) { - 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; + 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); } - 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 () +uint8 S9xSA1GetByte (uint32 address) { - 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; + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; - switch (depth) - { - case 2: - break; - case 4: - break; - case 8: - for (int l = 0; l < 8; l++, q += 8) + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (*(GetAddress + (address & 0xffff))); + + switch ((pint) GetAddress) { - 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; + 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); } - break; - } } -static void S9xSA1DMA () +uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) { - 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); + PC_t a; - uint8 *s; - uint8 *d; + SA1OpenBus = S9xSA1GetByte(address); - 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; - } + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); - 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; + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); - if (Memory.FillRAM [0x220a] & 0x20) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; -// SA1.Executing = !SA1.Waiting; - } + case WRAP_NONE: + default: + return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8)); + } } -void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) +void S9xSA1SetByte (uint8 byte, uint32 address) { - uint32 addr = Memory.FillRAM [0x2259] | - (Memory.FillRAM [0x225a] << 8) | - (Memory.FillRAM [0x225b] << 16); - uint8 shift = Memory.FillRAM [0x2258] & 15; + uint8 *SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT]; - if (no_shift) - shift = 0; - else - if (shift == 0) - shift = 16; + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + *(SetAddress + (address & 0xffff)) = byte; + return; + } - uint8 s = shift + SA1.variable_bit_pos; + switch ((pint) SetAddress) + { + case CMemory::MAP_PPU: + S9xSetSA1(byte, address & 0xffff); + return; - if (s >= 16) - { - addr += (s >> 4) << 1; - s &= 15; - } - uint32 data = S9xSA1GetWord (addr) | - (S9xSA1GetWord (addr + 2) << 16); + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (address & 0xffff)) = byte; + return; - 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); - } + 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; + } } +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); +} + +void S9xSA1SetPCBase (uint32 address) +{ + SA1Registers.PBPC = address & 0xffffff; + SA1.ShiftedPB = address & 0xff0000; + + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + SA1.PCBase = GetAddress; + 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_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_SA1RAM: + SA1.PCBase = Memory.SRAM; + return; + + default: + SA1.PCBase = NULL; + return; + } +} diff --git a/source/snes9x/sa1.h b/source/snes9x/sa1.h index 96e1194..5890cab 100644 --- a/source/snes9x/sa1.h +++ b/source/snes9x/sa1.h @@ -159,150 +159,149 @@ **********************************************************************************/ +#ifndef _SA1_H_ +#define _SA1_H_ - -#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 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; - 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; +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; }; -#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 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 SA1ClearFlags(f) (SA1Registers.P.W &= ~(f)) -#define SA1SetFlags(f) (SA1Registers.P.W |= (f)) -#define SA1CheckFlag(f) (SA1Registers.PL & (f)) +#define SA1SetFlags(f) (SA1Registers.P.W |= (f)) +#define SA1ClearFlags(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); -void S9xSA1SetWord (uint16, uint32, enum s9xwrap_t w=WRAP_NONE, enum s9xwriteorder_t o=WRITE_01); +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 S9xSA1SetPCBase (uint32); uint8 S9xGetSA1 (uint32); void S9xSetSA1 (uint8, uint32); +void S9xSA1Init (void); +void S9xSA1MainLoop (void); +void S9xSA1ExecuteDuringSleep (void); +void S9xSA1PostLoadState (void); -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; +#define SNES_IRQ_SOURCE (1 << 7) +#define TIMER_IRQ_SOURCE (1 << 6) +#define DMA_IRQ_SOURCE (1 << 5) -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() +static inline void S9xSA1UnpackStatus (void) { - 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() +static inline void S9xSA1PackStatus (void) { - 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 () +static inline void S9xSA1FixCycles (void) { - 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 0183c2e..9bcae88 100644 --- a/source/snes9x/sa1cpu.cpp +++ b/source/snes9x/sa1cpu.cpp @@ -159,120 +159,125 @@ **********************************************************************************/ - - #include "snes9x.h" #include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#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 +#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 //#undef CPU_SHUTDOWN #define SA1_OPCODES #include "cpuops.cpp" -void S9xSA1MainLoop () + +void S9xSA1MainLoop (void) { - int i; - #if 0 - if (SA1.Flags & NMI_FLAG) - { - SA1.Flags &= ~NMI_FLAG; - if (SA1.WaitingForInterrupt) + if (SA1.Flags & NMI_FLAG) { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; + SA1.Flags &= ~NMI_FLAG; + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_NMI(); } - 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 - 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) (); - } + 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)(); + } } - diff --git a/source/snes9x/sar.h b/source/snes9x/sar.h index 140dfeb..acea063 100644 --- a/source/snes9x/sar.h +++ b/source/snes9x/sar.h @@ -159,54 +159,49 @@ **********************************************************************************/ - - #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/apumem.h b/source/snes9x/screenshot.cpp similarity index 66% rename from source/snes9x/apumem.h rename to source/snes9x/screenshot.cpp index df9a3f1..a09c661 100644 --- a/source/snes9x/apumem.h +++ b/source/snes9x/screenshot.cpp @@ -159,152 +159,141 @@ **********************************************************************************/ +#ifdef HAVE_LIBPNG +#include +#endif +#include "snes9x.h" +#include "memmap.h" +#include "display.h" +#include "screenshot.h" -#ifndef _apumemory_h_ -#define _apumemory_h_ -START_EXTERN_C -extern uint8 APUROM[64]; -END_EXTERN_C - -static INLINE uint8 apu_get_reg (uint8 Address) +bool8 S9xDoScreenshot (int width, int height) { - switch (Address) + 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) { - case 0xf0: // -w TEST - return 0; - - case 0xf1: // -w CONTROL - return 0; - - case 0xf2: // rw DSPADDR - return (IAPU.RAM[Address]); - - case 0xf3: // rw DSPDATA - return (S9xGetAPUDSP()); - - 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]); - - case 0xf8: // rw - Normal RAM - case 0xf9: // rw - Normal RAM - return (IAPU.RAM[Address]); - - case 0xfa: // -w T0TARGET - case 0xfb: // -w T1TARGET - case 0xfc: // -w T2TARGET - return 0; - - 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); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); } - return 0; -} - -static INLINE void apu_set_reg (uint8 byte, uint8 Address) -{ - switch (Address) + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { - case 0xf0: // -w TEST - //printf("Write %02X to APU 0xF0!\n", byte); - return; - - 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; + fclose(fp); + unlink(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); } -} -INLINE uint8 S9xAPUGetByteZ (uint8 Address) -{ - if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) - return (apu_get_reg(Address)); - else - return (IAPU.DirectPage[Address]); -} - -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 + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { - APU.ExtraRAM[Address - 0xffc0] = byte; - if (!APU.ShowROM) - IAPU.RAM[Address] = byte; + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + fclose(fp); + unlink(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); } -} -#endif // _apumemory_h_ + 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 1665a3c..4db3061 100644 --- a/source/snes9x/screenshot.h +++ b/source/snes9x/screenshot.h @@ -159,12 +159,9 @@ **********************************************************************************/ +#ifndef _SCREENSHOT_H_ +#define _SCREENSHOT_H_ - -#ifndef SCREENSHOT_H -#define SCREENSHOT_H - -bool8 S9xDoScreenshot(int width, int height); +bool8 S9xDoScreenshot (int, int); #endif - diff --git a/source/snes9x/sdd1.cpp b/source/snes9x/sdd1.cpp index ae5206f..994f2cc 100644 --- a/source/snes9x/sdd1.cpp +++ b/source/snes9x/sdd1.cpp @@ -159,97 +159,37 @@ **********************************************************************************/ - - #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; - 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 () -{ - memset (&Memory.FillRAM [0x4800], 0, 4); - for (int i = 0; i < 4; i++) - { - Memory.FillRAM [0x4804 + i] = i; - S9xSetSDD1MemoryMap (i, i); - } -} - -void S9xSDD1PostLoadState () -{ - 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) + for (int c = 0; c < 0x100; c += 16) { - fwrite (Memory.SDD1LoggedData, 8, - Memory.SDD1LoggedDataCount, fs); - fclose (fs); -#if defined(__linux) - chown (S9xGetFilename (".dat", PATCH_DIR), getuid (), getgid ()); -#endif + uint8 *block = &Memory.ROM[value + (c << 12)]; + for (int i = c; i < c + 16; i++) + Memory.Map[i + bank] = block; } - Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount; - } } -void S9xSDD1LoadLoggedData () +void S9xResetSDD1 (void) { - 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); - } + memset(&Memory.FillRAM[0x4800], 0, 4); + for (int i = 0; i < 4; i++) + { + Memory.FillRAM[0x4804 + i] = i; + S9xSetSDD1MemoryMap(i, i); + } } +void S9xSDD1PostLoadState (void) +{ + for (int i = 0; i < 4; i++) + S9xSetSDD1MemoryMap(i, Memory.FillRAM[0x4804 + i]); +} diff --git a/source/snes9x/sdd1.h b/source/snes9x/sdd1.h index c03c343..afb6107 100644 --- a/source/snes9x/sdd1.h +++ b/source/snes9x/sdd1.h @@ -159,14 +159,11 @@ **********************************************************************************/ - - #ifndef _SDD1_H_ #define _SDD1_H_ -void S9xSetSDD1MemoryMap (uint32 bank, uint32 value); -void S9xResetSDD1 (); -void S9xSDD1PostLoadState (); -void S9xSDD1SaveLoggedData (); -void S9xSDD1LoadLoggedData (); -#endif +void S9xSetSDD1MemoryMap (uint32, uint32); +void S9xResetSDD1 (void); +void S9xSDD1PostLoadState (void); + +#endif diff --git a/source/snes9x/sdd1emu.cpp b/source/snes9x/sdd1emu.cpp index 4104137..29ba5f4 100644 --- a/source/snes9x/sdd1emu.cpp +++ b/source/snes9x/sdd1emu.cpp @@ -158,8 +158,6 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ - - /* S-DD1 decompressor * * Based on code and documentation by Andreas Naive, who deserves a great deal @@ -174,7 +172,7 @@ * S-DD1 issue in the past. */ -#include + #include "port.h" #include "sdd1emu.h" @@ -390,6 +388,7 @@ void SDD1_decompress(uint8 *out, uint8 *in, int len){ } } +#if 0 static uint8 cur_plane; static uint8 num_bits; static uint8 next_byte; @@ -485,4 +484,4 @@ uint8 SDD1_get_byte(void){ return 0; } } - +#endif diff --git a/source/snes9x/sdd1emu.h b/source/snes9x/sdd1emu.h index 86c03e9..e6d56b5 100644 --- a/source/snes9x/sdd1emu.h +++ b/source/snes9x/sdd1emu.h @@ -159,20 +159,9 @@ **********************************************************************************/ +#ifndef _SDD1EMU_H_ +#define _SDD1EMU_H_ -#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 +void SDD1_decompress (uint8 *, uint8 *, int); #endif diff --git a/source/snes9x/seta.cpp b/source/snes9x/seta.cpp index ca3bfba..62ad645 100644 --- a/source/snes9x/seta.cpp +++ b/source/snes9x/seta.cpp @@ -159,21 +159,19 @@ **********************************************************************************/ - +#include "snes9x.h" #include "seta.h" -void (*SetSETA)(uint32, uint8)=&S9xSetST010; -uint8 (*GetSETA)(uint32)=&S9xGetST010; +uint8 (*GetSETA) (uint32) = &S9xGetST010; +void (*SetSETA) (uint32, uint8) = &S9xSetST010; -extern "C"{ -uint8 S9xGetSetaDSP(uint32 Address) + +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 0c49170..9af7c36 100644 --- a/source/snes9x/seta.h +++ b/source/snes9x/seta.h @@ -159,72 +159,64 @@ **********************************************************************************/ +#ifndef _SETA_H_ +#define _SETA_H_ +#define ST_010 0x01 +#define ST_011 0x02 +#define ST_018 0x03 -#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" +struct SST010 { -uint8 S9xGetSetaDSP(uint32 Address); -void S9xSetSetaDSP(uint8 byte,uint32 Address); -uint8 S9xGetST018(uint32 Address); -void S9xSetST018(uint8 Byte, uint32 Address); + uint8 input_params[16]; + uint8 output_params[16]; + uint8 op_reg; + uint8 execute; + bool8 control_enable; +}; -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 +struct SST011 { - uint8 input_params[16]; - uint8 output_params[16]; - uint8 op_reg; - uint8 execute; - bool8 control_enable; -} ST010_Regs; + bool8 waiting4command; + uint8 status; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; +}; -typedef struct SETA_ST011_STRUCT +struct SST018 { - 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; + 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]; +}; -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; +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); #endif -#endif - diff --git a/source/snes9x/seta010.cpp b/source/snes9x/seta010.cpp index e28225a..b4288c1 100644 --- a/source/snes9x/seta010.cpp +++ b/source/snes9x/seta010.cpp @@ -159,61 +159,13 @@ **********************************************************************************/ - -#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 +#include "snes9x.h" +#include "memmap.h" +#include "seta.h" -#ifndef PI -#define PI 3.1415926535897932384626433832795 -#endif - -ST010_Regs ST010; - -uint8 S9xGetST010(uint32 Address) +static const int16 ST010_SinTable[256] = { - 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, @@ -245,155 +197,194 @@ 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 +}; -const unsigned char ST010_ArcTan[32][32] = { +static const uint8 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 } +}; -short ST010_Sin(short Theta) +// Mode 7 scaling constants for all raster lines +static const int16 ST010_M7Scale[176] = { - return ST010_SinTable[(Theta >> 8) & 0xff]; + 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]); } -short ST010_Cos(short Theta) +static int16 ST010_Cos (int16 Theta) { - return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]; + return (ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]); } -void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) +static void ST010_OP01 (int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &Quadrant, int16 &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; } -void ST010_Scale(short Multiplier, short X0, short Y0, int &X1, int &Y1) +static void ST010_Scale (int16 Multiplier, int16 X0, int16 Y0, int32 &X1, int32 &Y1) { X1 = X0 * Multiplier << 1; Y1 = Y0 * Multiplier << 1; } -void ST010_Multiply(short Multiplicand, short Multiplier, int &Product) +static void ST010_Multiply (int16 Multiplicand, int16 Multiplier, int32 &Product) { Product = Multiplicand * Multiplier << 1; } -void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1) +static void ST010_Rotate (int16 Theta, int16 X0, int16 Y0, int16 &X1, int16 &Y1) { X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); } -void SETA_Distance(short Y0, short X0, short &Distance) +static void ST010_SortDrivers (uint16 Positions, uint16 Places[32], uint16 Drivers[32]) { - 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; + 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]; @@ -406,49 +397,82 @@ void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) Sorted = false; } + } + Positions--; - } while (!Sorted); + } + while (!Sorted); + } } -#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] - -void S9xSetST010(uint32 Address, uint8 Byte) +/* +static void SETA_Distance (int16 Y0, int16 X0, int16 &Distance) { - if(!(Address&0x80000)) + 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)) { - ST010.control_enable=TRUE; + ST010.control_enable = TRUE; return; } - //printf("Write %06X:%02X\n", Address, 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; +#ifdef DEBUGGER + printf("Write %06X:%02X\n", Address, Byte); +#endif - if(ST010.execute&0x80) + 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) { - 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; @@ -458,114 +482,113 @@ 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(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]); -#else - int x1, y1; + #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; 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(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], (int&) Memory.SRAM[0x0010]); -#else - int Product; + #ifdef FAST_LSB_WORD_ACCESS + ST010_Multiply(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010]); + #else + int32 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; } @@ -577,162 +600,156 @@ 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(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]); -#else - short x1, y1; + #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; 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(*(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; + #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; 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 - 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 + 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 AI orientation based on specific guidelines - case 0x05: + // calculate the vector length of (x, y) + case 0x04: { - int dx,dy; - int16 a1,b1,c1; - uint16 o1; + 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); - bool wrap=false; + #ifdef FAST_LSB_WORD_ACCESS + *((int16 *) &Memory.SRAM[0x10]) = square; + #else + Memory.SRAM[0x10] = (uint8) (square); + Memory.SRAM[0x11] = (uint8) (square >> 8); + #endif + break; + } - // target (x,y) coordinates - int16 ypos_max = ST010_WORD(0x00C0); - int16 xpos_max = ST010_WORD(0x00C2); + // 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); // 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(o10x8000) + //if ((o1 < 0x6000 && rot > 0xA000) || (rot < 0x6000 && o1 > 0xA000)) + //if (o1 < rot) + if (abs(o1 - rot) > 0x8000) { - 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) - { + if (abs(o1 - rot) == 0x8000) speed = 0x100; - } // slow down for sharp curves - else if(abs(o1-rot)>=0x1000) + else + if (abs(o1 - rot) >= 0x1000) { - uint32 slow = abs(o1-rot); + uint32 slow = abs(o1 - rot); slow >>= 4; // scaling speed -= slow; } @@ -740,7 +757,7 @@ void S9xSetST010(uint32 Address, uint8 Byte) else { speed += accel; - if(speed > speed_max) + if (speed > speed_max) { // clip speed speed = speed_max; @@ -748,35 +765,40 @@ void S9xSetST010(uint32 Address, uint8 Byte) } // prevent negative/positive overflow - if(abs(old_speed-speed)>0x8000) { - if(old_speed 0x8000) + { + if (old_speed < speed) + speed = 0; + else + speed = 0xff00; } // adjust direction by so many degrees // be careful of negative adjustments - if( (o1>rot && (o1-rot)>0x80) || - (o1=0x80) ) + if ((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) { - if(o1rot) rot+=0x280; + if (o1 < rot) + rot -= 0x280; + else + if (o1 > rot) + 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; } @@ -789,36 +811,37 @@ 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: - //printf("Unknown Op\n"); - break; + default: + #ifdef DEBUGGER + printf("Unknown Op\n"); + #endif + 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 9995283..8dceb1b 100644 --- a/source/snes9x/seta011.cpp +++ b/source/snes9x/seta011.cpp @@ -159,148 +159,135 @@ **********************************************************************************/ - -#include -#include "seta.h" +#include "snes9x.h" #include "memmap.h" +#include "seta.h" -ST011_Regs ST011; +static uint8 board[9][9]; // shougi playboard +static int line = 0; // line counter -// shougi playboard -uint8 board[9][9]; -// debug -static int line = 0; - -uint8 S9xGetST011(uint32 Address) +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; - } - // read directly from s-ram + t = 0xFF; else - { - t = Memory.SRAM[address]; - } + t = Memory.SRAM[address]; // read directly from s-ram - // debug -// if(address<0x150) -// printf( "ST011 R: %06X %02X\n", Address, t); +#ifdef DEBUGGER + if (address < 0x150) + printf("ST011 R: %06X %02X\n", Address, t); +#endif - return t; + return (t); } -void S9xSetST011(uint32 Address, uint8 Byte) +void S9xSetST011 (uint32 Address, uint8 Byte) { - uint16 address = (uint16) Address & 0xFFFF; - static bool reset = false; + static bool reset = false; + uint16 address = (uint16) Address & 0xFFFF; - // debug line++; - if(!reset) + if (!reset) { // bootup values ST011.waiting4command = true; reset = true; } - // debug -// if(address<0x150) -// printf( "ST011 W: %06X %02X\n", Address, Byte ); +#ifdef DEBUGGER + if (address < 0x150) + printf("ST011 W: %06X %02X\n", Address, Byte); +#endif - 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; - case 0x07: break; + // unknown + case 0x06: + break; - // unknown - case 0x0E: - { + case 0x07: + break; + + // 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 8dc6bff..3b3f306 100644 --- a/source/snes9x/seta018.cpp +++ b/source/snes9x/seta018.cpp @@ -159,19 +159,17 @@ **********************************************************************************/ - -#include "seta.h" +#include "snes9x.h" #include "memmap.h" +#include "seta.h" -ST018_Regs ST018; +static int line; // line counter -static int line; // line counter -extern "C"{ -uint8 S9xGetST018(uint32 Address) +uint8 S9xGetST018 (uint32 Address) { - uint8 t = 0; - uint16 address = (uint16) Address & 0xFFFF; + uint8 t = 0; + uint16 address = (uint16) Address & 0xFFFF; line++; @@ -181,29 +179,34 @@ 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; - //printf( "ST018 R: %06X %02X\n", Address, t); +#ifdef DEBUGGER + printf("ST018 R: %06X %02X\n", Address, t); +#endif - return t; + return (t); } -void S9xSetST018(uint8 Byte, uint32 Address) +void S9xSetST018 (uint8 Byte, uint32 Address) { - uint16 address = (uint16) Address&0xFFFF; - static bool reset = false; + static bool reset = false; + uint16 address = (uint16) Address & 0xFFFF; - //printf( "ST018 W: %06X %02X\n", Address, Byte ); +#ifdef DEBUGGER + printf("ST018 W: %06X %02X\n", Address, Byte); +#endif line++; @@ -211,36 +214,38 @@ 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; - 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) + + 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++; @@ -249,80 +254,84 @@ 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) { - // Actually execute the command + // qctually 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++; - if (ST018.pass==1) - { - ST018.in_count = 1; - ST018.out_count = 2; + // hardware check? + case 0x0100: + ST018.waiting4command = false; + ST018.pass++; - // Overload's research - ST018.output[0x00] = 0x81; - ST018.output[0x01] = 0x81; - } - else - { - //ST018.in_count = 1; - ST018.out_count = 3; + if (ST018.pass == 1) + { + ST018.in_count = 1; + ST018.out_count = 2; - // no reason to change this - //ST018.output[0x00] = 0x81; - //ST018.output[0x01] = 0x81; - ST018.output[0x02] = 0x81; + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; - // done processing requests - if (ST018.pass==3) - ST018.waiting4command = true; - } - break; + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; - // 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; + // done processing requests + if (ST018.pass == 3) + ST018.waiting4command = true; + } - // Overload's research - ST018.output[0x00] = 0x81; - ST018.output[0x01] = 0x81; - } - else - { - //ST018.in_count = 1; - ST018.out_count = 3; + break; - // no reason to change this - //ST018.output[0x00] = 0x81; - //ST018.output[0x01] = 0x81; - ST018.output[0x02] = 0x81; + // unknown: feels like a security detection + // format identical to 0x0100 + case 0xFF00: + ST018.waiting4command = false; + ST018.pass++; - // done processing requests - if (ST018.pass==3) - ST018.waiting4command = true; - } - break; + 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; } } } -} - diff --git a/source/snes9x/snapshot.cpp b/source/snes9x/snapshot.cpp index 2eee373..c75a39e 100644 --- a/source/snes9x/snapshot.cpp +++ b/source/snes9x/snapshot.cpp @@ -159,1689 +159,1800 @@ **********************************************************************************/ - -#include -#ifdef HAVE_STRINGS_H -#include -#endif -#include -#include -#include #include - -#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) -#include -#include -#include -#endif - -#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 "memmap.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxinst.h" +#include "fxemu.h" #include "sdd1.h" -#include "spc7110.h" -//#include "movie.h" +#include "srtc.h" +#include "snapshot.h" #include "controls.h" -#include "dsp1.h" -#include "c4.h" -#ifndef ZSNES_FX - #include "fxinst.h" -#endif +#include "movie.h" +#include "display.h" #include "language.h" -#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)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) #endif -extern uint8 *SRAM; +typedef struct +{ + int offset; + int offset2; + int size; + int type; + uint16 debuted_in; + uint16 deleted_in; + const char *name; +} FreezeData; -#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 +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 }; -static struct Obsolete { - uint8 SPPU_Joypad1ButtonReadPos; - uint8 SPPU_Joypad2ButtonReadPos; - uint8 SPPU_Joypad3ButtonReadPos; - uint8 SPPU_MouseSpeed[2]; - uint8 SAPU_Flags; -} Obsolete; +#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) -#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 INT_ENTRY(save_version_introduced, field) \ +{ \ + OFFSET(field), \ + 0, \ + sizeof(((STRUCT *) NULL)->field), \ + INT_V, \ + save_version_introduced, \ + 9999, \ + #field \ +} -#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 +#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]; +}; struct SnapshotMovieInfo { uint32 MovieInputDataSize; }; -#undef STRUCT -#define STRUCT struct SnapshotMovieInfo - -#ifndef NGC - static FreezeData SnapMovie [] = { - INT_ENTRY(1, MovieInputDataSize), -}; -#endif - -#undef STRUCT -#define STRUCT struct SCPUState - -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 SRegisters - -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 SPPU - -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) \ - 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(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) \ - 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 - 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 SDMA - -static FreezeData SnapDMA [] = { -#define O(N) \ - {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 SAPU - -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 SAPURegisters - -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 SSoundData - -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 SSA1Registers - -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), -}; - -#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), -}; - - -#ifndef NGC struct SnapshotScreenshotInfo { - uint16 Width; - uint16 Height; - uint8 Data [MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3]; - uint8 Interlaced; + 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 SnapshotScreenshotInfo +#define STRUCT struct SRegisters -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 +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) +}; + +#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) }; -#endif #ifndef ZSNES_FX - extern struct FxRegs_s GSU; - #undef STRUCT - #define STRUCT struct FxRegs_s +#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) +static FreezeData SnapFX[] = { - return (S9xFreezeGame (filename)); + 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 + +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) +}; + +#undef STRUCT +#define STRUCT struct SSA1Registers + +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) +}; + +#undef STRUCT +#define STRUCT struct SDSP1 + +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), +#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), +#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), +#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), +#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) +}; + +#undef STRUCT +#define STRUCT struct SST010 + +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), +#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) +#undef O +}; + +#undef STRUCT +#define STRUCT struct SSRTCSnapshot + +static FreezeData SnapSRTCSnap[] = +{ + INT_ENTRY(6, rtc_mode), + INT_ENTRY(6, rtc_index) +}; + +#undef STRUCT +#define STRUCT struct SBSX + +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) +}; + +#undef STRUCT +#define STRUCT struct SnapshotScreenshotInfo + +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) +}; + +#undef STRUCT +#define STRUCT struct SnapshotMovieInfo + +static FreezeData SnapMovie[] = +{ + INT_ENTRY(6, MovieInputDataSize) +}; + +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); + + +void S9xResetSaveTimer (bool8 dontsave) +{ + static time_t t = -1; + + 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]; + + _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); + } + + t = time(NULL); } bool8 S9xFreezeGame (const char *filename) { - STREAM stream = NULL; + STREAM stream = NULL; -#ifndef NGC - if (S9xOpenSnapshotFile (filename, FALSE, &stream)) -#endif + if (S9xOpenSnapshotFile(filename, FALSE, &stream)) { - S9xPrepareSoundForSnapshotSave (FALSE); + S9xFreezeToStream(stream); + S9xCloseSnapshotFile(stream); - S9xFreezeToStream (stream); -#ifndef NGC - S9xCloseSnapshotFile (stream); -#endif - S9xPrepareSoundForSnapshotSave (TRUE); + S9xResetSaveTimer(TRUE); - 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; - } + const char *base = S9xBasename(filename); + if (S9xMovieActive()) + sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base); else - { - sprintf(String, SAVE_INFO_SNAPSHOT " %s", S9xBasename (filename)); - S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); - } -#endif - return (TRUE); - } - return (FALSE); -} + sprintf(String, SAVE_INFO_SNAPSHOT " %s", base); -bool8 S9xLoadSnapshot (const char *filename) -{ - return (S9xUnfreezeGame (filename)); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (TRUE); + } + + return (FALSE); } bool8 S9xUnfreezeGame (const char *filename) { - char def [PATH_MAX + 1 ]; - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1 ]; - char ext [_MAX_EXT + 1 ] ; + STREAM stream = NULL; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; - _splitpath (filename, drive, dir, def, ext); - S9xResetSaveTimer (!strcmp(ext, "oops") || !strcmp(ext, "oop")); + const char *base = S9xBasename(filename); - ZeroMemory (&Obsolete, sizeof(Obsolete)); + _splitpath(filename, drive, dir, def, ext); + S9xResetSaveTimer(!strcmp(ext, "oops") || !strcmp(ext, "oop") || !strcmp(ext, ".oops") || !strcmp(ext, ".oop")); -#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 + if (S9xOpenSnapshotFile(filename, TRUE, &stream)) { - int result; - if ((result = S9xUnfreezeFromStream (snapshot)) != SUCCESS) + int result; + + result = S9xUnfreezeFromStream(stream); + S9xCloseSnapshotFile(stream); + + if (result != 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; - default: - case FILE_NOT_FOUND: - sprintf (String, SAVE_ERR_ROM_NOT_FOUND, ROMFilename); - 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; + + case FILE_NOT_FOUND: + default: + sprintf(String, SAVE_ERR_ROM_NOT_FOUND, base); + S9xMessage(S9X_ERROR, S9X_ROM_NOT_FOUND, String); + break; } -#ifndef NGC - S9xCloseSnapshotFile (snapshot); -#endif + return (FALSE); } -#ifndef NGC - if(S9xMovieActive()) + if (S9xMovieActive()) { - const char * name = S9xBasename (filename); - if(name && strlen(name) > 3) - name += strlen(name) - 3; + if (S9xMovieReadOnly()) + sprintf(String, MOVIE_INFO_REWIND " %s", base); else - 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; + sprintf(String, MOVIE_INFO_RERECORD " %s", base); } else - { - sprintf(String, SAVE_INFO_LOAD " %s", S9xBasename (filename)); - S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); - } + sprintf(String, SAVE_INFO_LOAD " %s", base); + + 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); } - return (FALSE); -#endif -} + sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); -bool diagnostic_freezing = false; -//#define DIAGNOSTIC_FREEZING_SUPPORT + return (FALSE); +} void S9xFreezeToStream (STREAM stream) { - char buffer [1024]; - int i; + char buffer[1024]; + + S9xSetSoundMute(TRUE); - S9xSetSoundMute (TRUE); #ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPreSaveState (); + if (Settings.SuperFX) + S9xSuperFXPreSaveState(); #endif - S9xUpdateRTC(); - S9xSRTCPreSaveState (); + sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); + WRITE_STREAM(buffer, strlen(buffer), 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)); + sprintf(buffer, "NAM:%06d:%s%c", (int) strlen(Memory.ROMFilename) + 1, Memory.ROMFilename, 0); + WRITE_STREAM(buffer, strlen(buffer) + 1, stream); - // 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, "CPU", &CPU, SnapCPU, COUNT(SnapCPU)); - // Controls - struct SControlSnapshot ctl_snap; - S9xControlPreSave(&ctl_snap); - FreezeStruct (stream, "CTL", &ctl_snap, SnapControls, COUNT (SnapControls)); + FreezeStruct(stream, "REG", &Registers, SnapRegisters, COUNT(SnapRegisters)); - // Timings - FreezeStruct (stream, "TIM", &Timings, SnapTimings, COUNT (SnapTimings)); + FreezeStruct(stream, "PPU", &PPU, SnapPPU, COUNT(SnapPPU)); - // Special chips - if (Settings.SA1) - { - S9xSA1PackStatus (); - FreezeStruct (stream, "SA1", &SA1, SnapSA1, COUNT (SnapSA1)); - FreezeStruct (stream, "SAR", &SA1Registers, SnapSA1Registers, - COUNT (SnapSA1Registers)); - } + 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)); - if (Settings.SPC7110) - { - FreezeStruct (stream, "SP7", &s7r, SnapSPC7110, COUNT (SnapSPC7110)); - } + FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); - if (Settings.SPC7110RTC) - { - FreezeStruct (stream, "RTC", &rtc_f9, SnapS7RTC, COUNT (SnapS7RTC)); - } + FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); - // BS - if (Settings.BS) - { - FreezeStruct (stream, "BSX", &BSX, SnapBSX, COUNT (SnapBSX)); - } + FreezeBlock (stream, "SRA", Memory.SRAM, 0x20000); -#ifndef NGC - if (S9xMovieActive ()) - { - uint8* movie_freeze_buf; - uint32 movie_freeze_size; + FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); - 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 + uint8 soundsnapshot[SPC_SAVE_STATE_BLOCK_SIZE]; + S9xAPUSaveState(soundsnapshot); + FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); - // DSP1 chip - if(Settings.DSP1Master) - { - S9xPreSaveDSP1(); - FreezeStruct (stream, "DSP", &DSP1, SnapDSP1, COUNT (SnapDSP1)); - } + struct SControlSnapshot ctl_snap; + S9xControlPreSaveState(&ctl_snap); + FreezeStruct(stream, "CTL", &ctl_snap, SnapControls, COUNT(SnapControls)); - if (Settings.C4) - { -#ifdef ZSNES_C4 - extern uint8 *C4Ram; - if (C4Ram) - FreezeBlock (stream, "CX4", C4Ram, 8192); -#else - FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); -#endif - } + FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings)); #ifndef ZSNES_FX if (Settings.SuperFX) - FreezeStruct (stream, "SFX", &GSU, SnapFX, COUNT (SnapFX)); + FreezeStruct(stream, "SFX", &GSU, SnapFX, COUNT(SnapFX)); #endif -#ifndef NGC - if(Settings.SnapshotScreenshots) + if (Settings.SA1) { - SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; - ssi->Width = min(IPPU.RenderedScreenWidth, MAX_SNES_WIDTH); + 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); ssi->Height = min(IPPU.RenderedScreenHeight, MAX_SNES_HEIGHT); ssi->Interlaced = GFX.DoInterlace; - 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; + 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; + DECOMPOSE_PIXEL(screen[x], r, g, b); - *(rowpix++) = r; // save pixel as 15-bits-in-3-bytes, for simplicity + *(rowpix++) = r; *(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; } -#endif - S9xSetSoundMute (FALSE); + 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 (); + if (Settings.SuperFX) + S9xSuperFXPostSaveState(); #endif -} -bool unfreezing_from_stream = false; + S9xSetSoundMute(FALSE); +} int S9xUnfreezeFromStream (STREAM stream) { - char buffer [_MAX_PATH + 1]; - char rom_filename [_MAX_PATH + 1]; - int result; + int result = SUCCESS; + int version, len; + char buffer[PATH_MAX + 1]; + + printf("unfreezing ...\n"); - int version; - int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; -#ifdef NGC - GetMem(buffer, len); -#else - if (READ_STREAM (buffer, len, stream) != len) + len = strlen(SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (READ_STREAM(buffer, len, stream) != len) return (WRONG_FORMAT); -#endif - if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) + + if (strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0) return (WRONG_FORMAT); - if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) + + version = atoi(&buffer[strlen(SNAPSHOT_MAGIC) + 1]); + if (version > SNAPSHOT_VERSION) return (WRONG_VERSION); - if ((result = UnfreezeBlock (stream, "NAM", (uint8 *) rom_filename, _MAX_PATH)) != SUCCESS) + result = UnfreezeBlock(stream, "NAM", (uint8 *) buffer, PATH_MAX); + if (result != SUCCESS) return (result); + + printf("unfreezing 2...\n"); - 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}; + 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; do { - if ((result = UnfreezeStructCopy (stream, "CPU", &local_cpu, SnapCPU, COUNT (SnapCPU), version)) != SUCCESS) + result = UnfreezeStructCopy(stream, "CPU", &local_cpu, SnapCPU, COUNT(SnapCPU), version); + if (result != SUCCESS) break; - if ((result = UnfreezeStructCopy (stream, "REG", &local_registers, SnapRegisters, COUNT (SnapRegisters), version)) != SUCCESS) + + result = UnfreezeStructCopy(stream, "REG", &local_registers, SnapRegisters, COUNT(SnapRegisters), version); + if (result != SUCCESS) break; - if ((result = UnfreezeStructCopy (stream, "PPU", &local_ppu, SnapPPU, COUNT (SnapPPU), version)) != SUCCESS) + + result = UnfreezeStructCopy(stream, "PPU", &local_ppu, SnapPPU, COUNT(SnapPPU), version); + if (result != SUCCESS) break; - if ((result = UnfreezeStructCopy (stream, "DMA", &local_dma, SnapDMA, COUNT (SnapDMA), version)) != SUCCESS) + + result = UnfreezeStructCopy(stream, "DMA", &local_dma, SnapDMA, COUNT(SnapDMA), version); + if (result != SUCCESS) break; - if ((result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000)) != SUCCESS) + + result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000); + if (result != SUCCESS) break; - if ((result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000)) != SUCCESS) + + result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000); + if (result != SUCCESS) break; - if ((result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000)) != SUCCESS) + + result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000); + if (result != SUCCESS) break; - if ((result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000)) != SUCCESS) + + result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000); + if (result != SUCCESS) break; - if (UnfreezeStructCopy (stream, "APU", &local_apu, SnapAPU, COUNT (SnapAPU), version) == SUCCESS) + + 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 ((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; - } - 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) - { - 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 + { + result = UnfreezeBlockCopy(stream, "MID", &local_movie_data, mi.MovieInputDataSize); + if (result != SUCCESS) + { + if (S9xMovieActive()) { result = NOT_A_MOVIE_SNAPSHOT; break; } - } else { + } - 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; - } + 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; - 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 ## + result = SUCCESS; + } while (false); if (result == SUCCESS) { - uint32 old_flags = CPU.Flags; + printf("unfreezing 3...\n"); + + uint32 old_flags = CPU.Flags; uint32 sa1_old_flags = SA1.Flags; - S9xReset (); - 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); - } + S9xSetSoundMute(TRUE); - 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); + S9xReset(); - 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(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version); - if (local_timing_data) - UnfreezeStructFromCopy (&Timings, SnapTimings, COUNT (SnapTimings), local_timing_data, version); - else // Must be an old snes9x savestate - { - S9xUpdateHVTimerPosition(); - } + UnfreezeStructFromCopy(&Registers, SnapRegisters, COUNT(SnapRegisters), local_registers, version); - if (local_bsx_data) - UnfreezeStructFromCopy (&BSX, SnapBSX, COUNT (SnapBSX), local_bsx_data, version); + UnfreezeStructFromCopy(&PPU, SnapPPU, COUNT(SnapPPU), local_ppu, version); - if(local_dsp1) - { - UnfreezeStructFromCopy (&DSP1, SnapDSP1, COUNT (SnapDSP1), local_dsp1, version); - S9xPostLoadDSP1(); - } + 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) - { -#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_C4 + memcpy(Memory.C4RAM, local_cx4_data, 8192); + #else + memcpy(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; + if (local_st010) + UnfreezeStructFromCopy(&ST010, SnapST010, COUNT(SnapST010), local_st010, version); - 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; - } - } + if (local_obc1) + UnfreezeStructFromCopy(&OBC1, SnapOBC1, COUNT(SnapOBC1), local_obc1, version); - // 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); + if (local_obc1_data) + memcpy(Memory.OBC1RAM, local_obc1_data, 8192); - IPPU.ColorsChanged = TRUE; - IPPU.OBJChanged = TRUE; + 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_bsx_data) + 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(); + + for (int d = 0; d < 8; d++) + DMA[d] = dma_snap.dma[d]; 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 - 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); + S9xFixColourBrightness(); + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; uint8 hdma_byte = Memory.FillRAM[0x420c]; S9xSetCPU(hdma_byte, 0x420c); - 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; + S9xControlPostLoadState(&ctl_snap); + + printf("unfreezing 4...\n"); - // 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(); - } - - ICPU.ShiftedPB = Registers.PB << 16; - ICPU.ShiftedDB = Registers.DB << 16; - S9xSetPCBase (Registers.PBPC); - S9xUnpackStatus (); - S9xFixCycles (); -// S9xReschedule (); // <-- this causes desync when recording or playing movies - -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostLoadState (); -#endif - - S9xSRTCPostLoadState (); - if (Settings.SDD1) - S9xSDD1PostLoadState (); - - if (version < 5) + #ifndef ZSNES_FX + if (local_superfx) { - // 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; + GSU.pfPlot = fx_PlotTable[GSU.vMode]; + GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; + + // 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]; + + if (GSU.pvDreg < &GSU.avReg[0] || GSU.pvDreg >= ((uint32 *) &GSU.avReg[0]) + 16) + GSU.pvDreg = &GSU.avReg[0]; } + #else + if (Settings.SuperFX) + S9xSuperFXPostLoadState(); + #endif + + if (local_sa1 && local_sa1_registers) + { + SA1.Flags |= sa1_old_flags & TRACE_FLAG; + S9xSA1PostLoadState(); + } + + if (Settings.SDD1) + S9xSDD1PostLoadState(); + + if (local_spc7110) + S9xSPC7110PostLoadState(version); + + if (local_srtc) + S9xSRTCPostLoadState(version); + + if (local_bsx_data) + S9xBSXPostLoadState(); + + 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; + } + + 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"); } - - 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; - + 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"); return (result); } - -/*****************************************************************/ - -int FreezeSize (int size, int type) +static int FreezeSize (int size, int type) { - 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); - } + 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); + } } -void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, - int num_fields) +static void FreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields) { - // Work out the size of the required block - int len = 0; - int i; - int j; + int len = 0; + int i, j; - for (i = 0; i < num_fields; i++) - { - if(fields[i].debuted_in > SNAPSHOT_VERSION) + for (i = 0; i < num_fields; i++) + { + if (SNAPSHOT_VERSION < fields[i].debuted_in) { - 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 || SNAPSHOT_VERSION < fields[i].debuted_in) + continue; - // 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; + } + break; - 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_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++) @@ -1850,876 +1961,321 @@ void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, *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; - } - } - //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; -} + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + } -void FreezeBlock (STREAM stream, char *name, uint8 *block, int size) -{ - char buffer [512]; - - 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) - { - FreezeStruct (s,"BSX", &BSX, SnapBSX, COUNT (SnapBSX)); - } - - // DSP1 chip - if(Settings.DSP1Master) - { - S9xPreSaveDSP1(); - FreezeStruct (s, "DSP", &DSP1, SnapDSP1, COUNT (SnapDSP1)); - } - - 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 -} - -#endif - -/*****************************************************************/ - -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: - fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer); - 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(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); - } - } - - return (SUCCESS); -#else - return NGCUnFreezeBlock(name, block, size); -#endif -} - -int UnfreezeBlockCopy (STREAM stream, char *name, uint8** block, int size) -{ - *block = new uint8 [size]; - int result; - - if ((result = UnfreezeBlock (stream, name, *block, size)) != SUCCESS) - { - delete [] (*block); - *block = NULL; - return (result); - } - - return (result); -} - -int UnfreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, - int num_fields, int version) -{ - 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; -} - -int UnfreezeStructCopy (STREAM stream, char *name, uint8** block, FreezeData *fields, int num_fields, int version) -{ - // Work out the size of the required block - int len = 0; - int i; - - for (i = 0; i < num_fields; i++) - { - if (version>=fields[i].debuted_in && version=fields[i].deleted_in) continue; - base = (SNAPSHOT_VERSION>=fields[i].deleted_in)?((void *)&Obsolete):sbase; - - 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)); - - 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) - { - int relativeAddr = (int)*((pint*)((uint8 *) base + fields[i].offset)); - uint8* relativeTo = (uint8*)*((pint*)((uint8 *) base + fields[i].offset2)); - *((pint *) (addr)) = (pint)(relativeTo + relativeAddr); + break; } } - //fprintf(stderr, "%p: Unfroze %d bytes\n", fields, ptr-block); + + FreezeBlock(stream, name, block, len); + delete [] block; } +static void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer[20]; -/*****************************************************************/ + // 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 + { + // 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); + } -extern uint8 spc_dump_dsp[0x100]; + buffer[11] = 0; + + WRITE_STREAM(buffer, 11, stream); + WRITE_STREAM(block, size, stream); +} + +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); + + size_t l = READ_STREAM(buffer, 11, stream); + buffer[l] = 0; + + 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); + 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 (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); + } + } + + return (SUCCESS); +} + +static int UnfreezeBlockCopy (STREAM stream, const char *name, uint8 **block, int size) +{ + int result; + + *block = new uint8[size]; + + result = UnfreezeBlock(stream, name, *block, size); + if (result != SUCCESS) + { + delete [] (*block); + *block = NULL; + return (result); + } + + return (SUCCESS); +} + +static int UnfreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields, int version) +{ + int result; + uint8 *block = NULL; + + 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 len = 0; + + 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); + } + + return (UnfreezeBlockCopy(stream, name, block, len)); +} + +static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fields, uint8 *block, int version) +{ + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + uint8 *addr; + void *base; + int relativeAddr; + int i, j; + + for (i = 0; i < num_fields; i++) + { + if (version < fields[i].debuted_in || version >= fields[i].deleted_in) + continue; + + base = (SNAPSHOT_VERSION >= fields[i].deleted_in) ? ((void *) &Obsolete) : sbase; + addr = (uint8 *) base + fields[i].offset; + + 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)); + + 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; + } + + 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); + } + } +} bool8 S9xSPCDump (const char *filename) { - 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 - }; + FILE *fs; + uint8 buf[SNES_SPC::spc_file_size]; - FILE *fs; - - if (!(fs = fopen (filename, "wb"))) + fs = fopen(filename, "wb"); + if (!fs) return (FALSE); - S9xSetSoundMute (TRUE); + S9xSetSoundMute(TRUE); - // 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 + spc_core->init_header(buf); + spc_core->save_spc(buf); - 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); + fwrite(buf, SNES_SPC::spc_file_size, 1, fs); + + fclose(fs); + + 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 05ad989..74b2dfe 100644 --- a/source/snes9x/snapshot.h +++ b/source/snes9x/snapshot.h @@ -159,34 +159,25 @@ **********************************************************************************/ - #ifndef _SNAPSHOT_H_ #define _SNAPSHOT_H_ -#include -#include "snes9x.h" +#define SNAPSHOT_MAGIC "#!s9xsnp" +#define SNAPSHOT_VERSION 6 -#define SNAPSHOT_MAGIC "#!snes9x" -#define SNAPSHOT_VERSION 5 +#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 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 S9xResetSaveTimer (bool8); +bool8 S9xFreezeGame (const char *); +bool8 S9xUnfreezeGame (const char *); void S9xFreezeToStream (STREAM); -int S9xUnfreezeFromStream (STREAM); -END_EXTERN_C +int S9xUnfreezeFromStream (STREAM); +bool8 S9xSPCDump (const char *); #endif - diff --git a/source/snes9x/snes9x.cpp b/source/snes9x/snes9x.cpp deleted file mode 100644 index 440d75d..0000000 --- a/source/snes9x/snes9x.cpp +++ /dev/null @@ -1,1264 +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 -#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 18d3e0e..c34195f 100644 --- a/source/snes9x/snes9x.h +++ b/source/snes9x/snes9x.h @@ -159,62 +159,42 @@ **********************************************************************************/ - #ifndef _SNES9X_H_ #define _SNES9X_H_ -#define VERSION "1.51" - -#include -#include - -#ifdef __WIN32__ -#include -#ifdef ZLIB -#include +#ifndef VERSION +#define VERSION "1.52" #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" -#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) +#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) +#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 @@ -248,88 +228,62 @@ #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_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_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) -#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 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) -struct SCPUState{ - uint32 Flags; - bool8 BranchSkip; - bool8 NMIActive; - bool8 IRQActive; - bool8 WaitingForInterrupt; - bool8 InDMAorHDMA; - bool8 InWRAMDMAorHDMA; - uint8 WhichEvent; - uint8 *PCBase; - uint32 PBPCAtOpcodeStart; - uint32 WaitAddress; - uint32 WaitCounter; +#define ROM_NAME_LEN 23 +#define AUTO_FRAMERATE 200 + +struct SCPUState +{ int32 Cycles; - int32 NextEvent; + int32 PrevCycles; int32 V_Counter; + uint32 Flags; + uint8 *PCBase; + bool8 IRQActive; + int32 IRQPending; int32 MemSpeed; int32 MemSpeedx2; int32 FastROMSpeed; - uint32 AutoSaveTimer; - bool8 SRAMModified; - bool8 BRKTriggered; - bool8 TriedInterleavedMode2; - int32 IRQPending; bool8 InDMA; bool8 InHDMA; + bool8 InDMAorHDMA; + bool8 InWRAMDMAorHDMA; uint8 HDMARanInDMA; - int32 PrevCycles; + int32 CurrentDMAorHDMAChannel; + uint8 WhichEvent; + int32 NextEvent; + bool8 WaitingForInterrupt; + uint32 WaitAddress; + uint32 WaitCounter; + uint32 PBPCAtOpcodeStart; + uint32 AutoSaveTimer; + bool8 SRAMModified; }; -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 { +enum +{ HC_HBLANK_START_EVENT = 1, HC_IRQ_1_3_EVENT = 2, HC_HDMA_START_EVENT = 3, @@ -344,187 +298,164 @@ enum { HC_IRQ_A_1_EVENT = 12 }; -struct SSettings{ - /* CPU options */ - bool8 APUEnabled; - bool8 Shutdown; - uint8 SoundSkipMethod; - int32 HDMATimingHack; - bool8 DisableIRQ; - bool8 Paused; - bool8 ForcedPause; - bool8 StopEmulation; - bool8 FrameAdvance; +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; +}; - /* Tracing options */ - bool8 TraceDMA; - bool8 TraceHDMA; - bool8 TraceVRAM; - bool8 TraceUnknownRegisters; - bool8 TraceDSP; +struct SSettings +{ + bool8 TraceDMA; + bool8 TraceHDMA; + bool8 TraceVRAM; + bool8 TraceUnknownRegisters; + bool8 TraceDSP; + bool8 TraceHCEvent; - /* Joystick options */ - bool8 JoystickEnabled; + 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; - /* ROM timing options (see also H_Max above) */ - bool8 ForcePAL; - bool8 ForceNTSC; - bool8 PAL; - uint32 FrameTimePAL; - uint32 FrameTimeNTSC; - uint32 FrameTime; - uint32 SkipFrames; + 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 image options */ - bool8 ForceLoROM; - bool8 ForceHiROM; - bool8 ForceHeader; - bool8 ForceNoHeader; - bool8 ForceInterleaved; - bool8 ForceInterleaved2; - bool8 ForceNotInterleaved; + bool8 SoundSync; + bool8 SixteenBitSound; + uint32 SoundPlaybackRate; + uint32 SoundInputRate; + bool8 Stereo; + bool8 ReverseStereo; + bool8 Mute; - /* 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 SupportHiRes; + bool8 Transparency; + uint8 BG_Forced; + bool8 DisableGraphicWindows; - 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 DisplayFrameRate; + bool8 DisplayWatchedAddresses; + bool8 DisplayPressedKeys; + bool8 DisplayMovieFrame; + bool8 AutoDisplayMessages; + uint32 InitialInfoStringTimeout; + uint16 DisplayColor; - /* 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 Multi; + char CartAName[PATH_MAX + 1]; + char CartBName[PATH_MAX + 1]; - /* SNES graphics options */ - bool8 BGLayering; - bool8 DisableGraphicWindows; - bool8 ForceTransparency; - bool8 ForceNoTransparency; - bool8 DisableHDMA; - bool8 DisplayFrameRate; - bool8 DisableRangeTimeOver; /* XXX: unused */ - bool8 DisplayWatchedAddresses; + bool8 DisableGameSpecificHacks; + bool8 ShutdownMaster; + bool8 Shutdown; + bool8 BlockInvalidVRAMAccessMaster; + bool8 BlockInvalidVRAMAccess; + bool8 DisableIRQ; + bool8 DisableHDMA; + int32 HDMATimingHack; - /* Multi ROMs */ - bool8 Multi; - char CartAName[_MAX_PATH + 1]; - char CartBName[_MAX_PATH + 1]; + bool8 ForcedPause; + bool8 Paused; + bool8 StopEmulation; - /* 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; + uint32 SkipFrames; + uint32 TurboSkipFrames; + uint32 AutoMaxSkipFrames; + bool8 TurboMode; + uint32 HighSpeedSeek; + bool8 FrameAdvance; -/* 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; + 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; }; struct SSNESGameFixes { - uint8 APU_OutPorts_ReturnValueFix; - uint8 SRAMInitialValue; - uint8 Uniracers; + uint8 SRAMInitialValue; + uint8 Uniracers; }; -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) +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 mask); -void S9xClearPause (uint32 mask); + +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]; #endif - diff --git a/source/snes9x/soundux.cpp b/source/snes9x/soundux.cpp deleted file mode 100644 index 3247e91..0000000 --- a/source/snes9x/soundux.cpp +++ /dev/null @@ -1,2442 +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 __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 deleted file mode 100644 index 1357061..0000000 --- a/source/snes9x/soundux.h +++ /dev/null @@ -1,352 +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 _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 deleted file mode 100644 index abbf360..0000000 --- a/source/snes9x/spc700.cpp +++ /dev/null @@ -1,2650 +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 "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/spc7110.cpp b/source/snes9x/spc7110.cpp index 36b4747..2e19c0c 100644 --- a/source/snes9x/spc7110.cpp +++ b/source/snes9x/spc7110.cpp @@ -158,2201 +158,60 @@ 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 -//#define SPC7110_DEBUG - -#include "spc7110.h" +#include "snes9x.h" #include "memmap.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 "srtc.h" #include "display.h" -#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 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 -//not much headroom, but FEOEZ has 41 tables, I think, and SPL4 has 38. -#define MAX_TABLES 48 +#define _SPC7110EMU_CPP_ -//default to using 5 megs of RAM for method 3 caching. -uint16 cacheMegs=5; +#include +#include "port.h" -//using function pointers to initialize cache management -void (*CleanUp7110)(void)=NULL; -void (*LoadUp7110)(char*)=&SPC7110Load; -void (*Copy7110)(void)=NULL; +#include "spc7110emu.h" +#include "spc7110emu.cpp" + +SPC7110 s7emu; static void SetSPC7110SRAMMap (uint8); -//size and offset of the pack data -//offset and size of reads from pack -typedef struct SPC7110DecompressionLocationStruct + +void S9xInitSPC7110 (void) { - 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); + s7emu.power(); + memset(RTCData.reg, 0, 20); } - -//full cache decompression routine (memcpy) Method 1 -void MovePackData() +void S9xResetSPC7110 (void) { - //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); - } - } + s7emu.reset(); } static void SetSPC7110SRAMMap (uint8 newstate) @@ -2373,63 +232,241 @@ static void SetSPC7110SRAMMap (uint8 newstate) } } -bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9) +uint8 * S9xGetBasePointerSPC7110 (uint32 address) { - 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++) + uint32 i; + + switch (address & 0xf00000) { - fread(&(rtc_f9->reg[i]),1,1,fp); + 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; } - 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); + + i += address & 0x0f0000; - 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); + return (&Memory.ROM[i]); } +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 7d12b78..0592030 100644 --- a/source/snes9x/spc7110.h +++ b/source/snes9x/spc7110.h @@ -159,111 +159,101 @@ **********************************************************************************/ +#ifndef _SPC7110_H_ +#define _SPC7110_H_ -#ifndef _spc7110_h -#define _spc7110_h -#include "port.h" +#define SPC7110_DECOMP_BUFFER_SIZE 64 -#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 +// for snapshot only +struct SSPC7110Snapshot { - unsigned char reg[16]; - short index; - uint8 control; - bool init; - time_t last_used; -} S7RTC; + uint8 r4801; + uint8 r4802; + uint8 r4803; + uint8 r4804; + uint8 r4805; + uint8 r4806; + uint8 r4807; + uint8 r4808; + uint8 r4809; + uint8 r480a; + uint8 r480b; + uint8 r480c; -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 r4811; + uint8 r4812; + uint8 r4813; + uint8 r4814; + uint8 r4815; + uint8 r4816; + uint8 r4817; + uint8 r4818; -} SPC7110Regs; -extern SPC7110Regs s7r; -extern S7RTC rtc_f9; -// These are defined in spc7110.cpp -bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9); -bool8 S9xLoadSPC7110RTC (S7RTC *rtc_f9); + 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); #endif - diff --git a/source/snes9x/spc7110dec.cpp b/source/snes9x/spc7110dec.cpp new file mode 100644 index 0000000..d4b495d --- /dev/null +++ b/source/snes9x/spc7110dec.cpp @@ -0,0 +1,529 @@ +/***** + * 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 new file mode 100644 index 0000000..3a9c7ce --- /dev/null +++ b/source/snes9x/spc7110dec.h @@ -0,0 +1,67 @@ +/***** + * 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 new file mode 100644 index 0000000..156e31c --- /dev/null +++ b/source/snes9x/spc7110emu.cpp @@ -0,0 +1,643 @@ +/***** + * 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 new file mode 100644 index 0000000..5f66fec --- /dev/null +++ b/source/snes9x/spc7110emu.h @@ -0,0 +1,136 @@ +/***** + * 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 9dd76e4..51531ff 100644 --- a/source/snes9x/srtc.cpp +++ b/source/snes9x/srtc.cpp @@ -158,494 +158,71 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ +/***** + * S-RTC emulation code + * Copyright (c) byuu + *****/ +#include -#include #include "snes9x.h" -#include "srtc.h" #include "memmap.h" +#include "srtc.h" +#include "display.h" -/*** The format of the rtc_data structure is: +#define memory_cartrtc_read(a) RTCData.reg[(a)] +#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } +#define cpu_regs_mdr OpenBus -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 () +static inline unsigned max (unsigned a, unsigned b) { - rtc.index = -1; - rtc.mode = MODE_READ; + return ((a > b) ? a : b); } -void S9xHardResetSRTC () +static inline unsigned min (unsigned a, unsigned 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); + return ((a < b) ? a : b); } -/**********************************************************************************************/ -/* S9xSRTCComputeDayOfWeek() */ -/* Return 0-6 for Sunday-Saturday */ -/**********************************************************************************************/ -unsigned int S9xSRTCComputeDayOfWeek () +#define _SRTCEMU_CPP_ + +#include "srtcemu.h" +#include "srtcemu.cpp" + +static SRTC srtcemu; + + +void S9xInitSRTC (void) { - 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; + srtcemu.power(); + memset(RTCData.reg, 0, 20); } - -/**********************************************************************************************/ -/* S9xSRTCDaysInMonth() */ -/* Return the number of days in a specific month for a certain year */ -/**********************************************************************************************/ -int S9xSRTCDaysInMmonth( int month, int year ) +void S9xResetSRTC (void) { - 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; + srtcemu.reset(); } - -#define DAYTICKS (60*60*24) -#define HOURTICKS (60*60) -#define MINUTETICKS 60 - - -/**********************************************************************************************/ -/* S9xUpdateSrtcTime() */ -/* Advance the S-RTC time if counting is enabled */ -/**********************************************************************************************/ -void S9xUpdateSrtcTime () +void S9xSetSRTC (uint8 data, uint16 address) { - 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; - } - } + srtcemu.mmio_write(address, data); } - -/**********************************************************************************************/ -/* S9xSetSRTC() */ -/* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ -/**********************************************************************************************/ -void S9xSetSRTC (uint8 data, uint16 Address) +uint8 S9xGetSRTC (uint16 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? - } - } + return (srtcemu.mmio_read(address)); } -/**********************************************************************************************/ -/* S9xGetSRTC() */ -/* This function retrieves data from the S-RTC */ -/**********************************************************************************************/ -uint8 S9xGetSRTC (uint16 Address) +void S9xSRTCPreSaveState (void) { - 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; - } + srtcsnap.rtc_mode = (int32) srtcemu.rtc_mode; + srtcsnap.rtc_index = (int32) srtcemu.rtc_index; } -void S9xSRTCPreSaveState () +void S9xSRTCPostLoadState (int) { - if (Settings.SRTC) - { - S9xUpdateSrtcTime (); + srtcemu.rtc_mode = (SRTC::RTC_Mode) srtcsnap.rtc_mode; + srtcemu.rtc_index = (signed) srtcsnap.rtc_index; - 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 - } + srtcemu.update_time(); } - -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 895e233..adda665 100644 --- a/source/snes9x/srtc.h +++ b/source/snes9x/srtc.h @@ -159,73 +159,29 @@ **********************************************************************************/ +#ifndef _SRTC_H_ +#define _SRTC_H_ -#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 +struct SRTCData { - bool8 needs_init; - bool8 count_enable; // Does RTC mark time or is it frozen - uint8 data [MAX_RTC_INDEX+1]; - int8 index; - uint8 mode; + uint8 reg[20]; +}; - time_t system_timestamp; // Of latest RTC load time - uint32 pad; -} SRTC_DATA; +// for snapshot only +struct SSRTCSnapshot +{ + int32 rtc_mode; // enum RTC_Mode + int32 rtc_index; // signed +}; -extern SRTC_DATA rtc; +extern struct SRTCData RTCData; +extern struct SSRTCSnapshot srtcsnap; -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 +void S9xInitSRTC (void); +void S9xResetSRTC (void); +void S9xSRTCPreSaveState (void); +void S9xSRTCPostLoadState (int); +void S9xSetSRTC (uint8, uint16); +uint8 S9xGetSRTC (uint16); +#endif diff --git a/source/snes9x/srtcemu.cpp b/source/snes9x/srtcemu.cpp new file mode 100644 index 0000000..969b966 --- /dev/null +++ b/source/snes9x/srtcemu.cpp @@ -0,0 +1,225 @@ +/***** + * 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 new file mode 100644 index 0000000..fc1af24 --- /dev/null +++ b/source/snes9x/srtcemu.h @@ -0,0 +1,30 @@ +/***** + * 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 71f3c21..00c7572 100644 --- a/source/snes9x/tile.cpp +++ b/source/snes9x/tile.cpp @@ -159,569 +159,663 @@ **********************************************************************************/ +// 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. -// 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 +#ifndef _NEWTILE_CPP #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; - for(i=0; i<16; i++) { - register uint32 b = 0; +void S9xInitTileRenderer (void) +{ + register int i; -#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 + for (i = 0; i < 16; i++) + { + register uint32 b = 0; - 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(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 (!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(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 (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; + } - 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 (sub) + hires = FALSE; - 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]; + 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]; } -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 renderers -/*===========================================================================*/ +#ifndef NAME1 // First-level: Get all the 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 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 NOMATH(Op, Main, Sub, SD) \ + (Main) -/*****************************************************************************/ -// 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 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 -#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 +#define NAME1 DrawTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount + +// Second-level include: Get the DrawTile16 renderers. -// Second-level include: Get the DrawTile16 renderers #include "tile.cpp" #undef NAME1 @@ -730,86 +824,105 @@ 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 +#define NAME1 DrawClippedTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount + +// Second-level include: Get the DrawClippedTile16 renderers. -// Second-level include: Get the DrawClippedTile16 renderers #include "tile.cpp" #undef NAME1 @@ -818,39 +931,44 @@ 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. +// 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 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 +#define NAME1 DrawMosaicPixel16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount + +// Second-level include: Get the DrawMosaicPixel16 renderers. -// Second-level include: Get the DrawMosaicPixel16 renderers #include "tile.cpp" #undef NAME1 @@ -859,32 +977,33 @@ 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. +// 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 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; 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> 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)); \ - } \ - } \ - } + 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 < 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)); \ + } \ + } \ + } #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> 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; \ - } + 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; \ + } -#define DRAW_TILE() DRAW_TILE_NORMAL() -#define NAME1 DrawMode7BG1 -#define ARGS uint32 Left, uint32 Right, int D +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define NAME1 DrawMode7BG1 +#define ARGS uint32 Left, uint32 Right, int D + +// Second-level include: Get the DrawMode7BG1 renderers. -// Second-level include: Get the DrawMode7BG1 renderers #include "tile.cpp" #undef NAME1 #undef DRAW_TILE -#define DRAW_TILE() DRAW_TILE_MOSAIC() -#define NAME1 DrawMode7MosaicBG1 -// Second-level include: Get the DrawMode7MosaicBG1 renderers +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG1 + +// Second-level include: Get the DrawMode7MosaicBG1 renderers. + #include "tile.cpp" #undef DRAW_TILE @@ -1127,23 +1299,26 @@ 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 +#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. -// Second-level include: Get the DrawMode7BG2 renderers #include "tile.cpp" #undef NAME1 #undef DRAW_TILE -#define DRAW_TILE() DRAW_TILE_MOSAIC() -#define NAME1 DrawMode7MosaicBG2 -// Second-level include: Get the DrawMode7MosaicBG2 renderers +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG2 + +// Second-level include: Get the DrawMode7MosaicBG2 renderers. + #include "tile.cpp" #undef MASK @@ -1158,159 +1333,179 @@ extern struct SLineMatrixData LineMatrixData [240]; #undef Z2 #undef NO_INTERLACE -/*===========================================================================*/ -#else // Second-level: Get all NAME1 renderers -#ifndef NAME2 -/*===========================================================================*/ +/*****************************************************************************/ +#else +#ifndef NAME2 // Second-level: Get all the NAME1 renderers. +/*****************************************************************************/ -#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) 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 +// 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. + #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 /* NO_INTERLACE */ +#endif #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 8b6d20c..ddd67fc 100644 --- a/source/snes9x/tile.h +++ b/source/snes9x/tile.h @@ -159,12 +159,11 @@ **********************************************************************************/ - #ifndef _TILE_H_ #define _TILE_H_ -void S9xInitTileRenderer(void); -void S9xSelectTileRenderers(int BGMode, bool8 sub, bool8 obj); -void S9xSelectTileConverter(int depth, bool8 hires, bool8 sub, bool8 mosaic); +void S9xInitTileRenderer (void); +void S9xSelectTileRenderers (int, bool8, bool8); +void S9xSelectTileConverter (int, bool8, bool8, bool8); #endif