From a6dc7abc9b8cc3986eda5a84141da7dc9e4e8f1a Mon Sep 17 00:00:00 2001 From: aliaspider Date: Wed, 29 Oct 2014 05:36:07 +0100 Subject: start moving everything to C --- Makefile | 38 +- libretro.c | 877 ++++++++ libretro.cpp | 877 -------- source/apu.c | 772 +++++++ source/apu.cpp | 772 ------- source/c4.c | 237 +++ source/c4.cpp | 237 --- source/c4emu.c | 889 +++++++++ source/c4emu.cpp | 889 --------- source/cheats.c | 442 ++++ source/cheats.cpp | 442 ---- source/cheats2.c | 285 +++ source/cheats2.cpp | 285 --- source/clip.c | 767 +++++++ source/clip.cpp | 767 ------- source/cpu.c | 239 +++ source/cpu.cpp | 239 --- source/cpuexec.c | 843 ++++++++ source/cpuexec.cpp | 843 -------- source/cpuops.c | 5307 +++++++++++++++++++++++++++++++++++++++++++++++++ source/cpuops.cpp | 5307 ------------------------------------------------- source/data.c | 539 +++++ source/data.cpp | 539 ----- source/dma.c | 1100 ++++++++++ source/dma.cpp | 1100 ---------- source/dsp1.c | 1440 ++++++++++++++ source/dsp1.cpp | 1440 -------------- source/dsp4emu.c | 1483 ++++++++++++++ source/dsp4emu.cpp | 1483 -------------- source/fxdbg.c | 409 ++++ source/fxdbg.cpp | 409 ---- source/fxemu.c | 726 +++++++ source/fxemu.cpp | 726 ------- source/fxinst.c | 1916 ++++++++++++++++++ source/fxinst.cpp | 1916 ------------------ source/gfx.c | 3933 ++++++++++++++++++++++++++++++++++++ source/gfx.cpp | 3933 ------------------------------------ source/globals.c | 349 ++++ source/globals.cpp | 349 ---- source/memmap.c | 4448 +++++++++++++++++++++++++++++++++++++++++ source/memmap.cpp | 4448 ----------------------------------------- source/obc1.c | 204 ++ source/obc1.cpp | 204 -- source/ppu.c | 3132 +++++++++++++++++++++++++++++ source/ppu.cpp | 3132 ----------------------------- source/sa1.c | 936 +++++++++ source/sa1.cpp | 936 --------- source/sa1cpu.c | 245 +++ source/sa1cpu.cpp | 245 --- source/screenshot.c | 235 +++ source/screenshot.cpp | 235 --- source/sdd1.c | 181 ++ source/sdd1.cpp | 181 -- source/sdd1emu.c | 414 ++++ source/sdd1emu.cpp | 414 ---- source/seta.c | 105 + source/seta.cpp | 105 - source/seta010.c | 750 +++++++ source/seta010.cpp | 750 ------- source/seta011.c | 232 +++ source/seta011.cpp | 232 --- source/seta018.c | 254 +++ source/seta018.cpp | 254 --- source/snaporig.c | 469 +++++ source/snaporig.cpp | 469 ----- source/snapshot.c | 1789 +++++++++++++++++ source/snapshot.cpp | 1789 ----------------- source/soundux.c | 1714 ++++++++++++++++ source/soundux.cpp | 1714 ---------------- source/spc700.c | 2548 ++++++++++++++++++++++++ source/spc700.cpp | 2548 ------------------------ source/spc7110.c | 2285 +++++++++++++++++++++ source/spc7110.cpp | 2285 --------------------- source/srtc.c | 581 ++++++ source/srtc.cpp | 581 ------ source/tile.c | 1065 ++++++++++ source/tile.cpp | 1065 ---------- 77 files changed, 44160 insertions(+), 44158 deletions(-) create mode 100644 libretro.c delete mode 100644 libretro.cpp create mode 100644 source/apu.c delete mode 100644 source/apu.cpp create mode 100644 source/c4.c delete mode 100644 source/c4.cpp create mode 100644 source/c4emu.c delete mode 100644 source/c4emu.cpp create mode 100644 source/cheats.c delete mode 100644 source/cheats.cpp create mode 100644 source/cheats2.c delete mode 100644 source/cheats2.cpp create mode 100644 source/clip.c delete mode 100644 source/clip.cpp create mode 100644 source/cpu.c delete mode 100644 source/cpu.cpp create mode 100644 source/cpuexec.c delete mode 100644 source/cpuexec.cpp create mode 100644 source/cpuops.c delete mode 100644 source/cpuops.cpp create mode 100644 source/data.c delete mode 100644 source/data.cpp create mode 100644 source/dma.c delete mode 100644 source/dma.cpp create mode 100644 source/dsp1.c delete mode 100644 source/dsp1.cpp create mode 100644 source/dsp4emu.c delete mode 100644 source/dsp4emu.cpp create mode 100644 source/fxdbg.c delete mode 100644 source/fxdbg.cpp create mode 100644 source/fxemu.c delete mode 100644 source/fxemu.cpp create mode 100644 source/fxinst.c delete mode 100644 source/fxinst.cpp create mode 100644 source/gfx.c delete mode 100644 source/gfx.cpp create mode 100644 source/globals.c delete mode 100644 source/globals.cpp create mode 100644 source/memmap.c delete mode 100644 source/memmap.cpp create mode 100644 source/obc1.c delete mode 100644 source/obc1.cpp create mode 100644 source/ppu.c delete mode 100644 source/ppu.cpp create mode 100644 source/sa1.c delete mode 100644 source/sa1.cpp create mode 100644 source/sa1cpu.c delete mode 100644 source/sa1cpu.cpp create mode 100644 source/screenshot.c delete mode 100644 source/screenshot.cpp create mode 100644 source/sdd1.c delete mode 100644 source/sdd1.cpp create mode 100644 source/sdd1emu.c delete mode 100644 source/sdd1emu.cpp create mode 100644 source/seta.c delete mode 100644 source/seta.cpp create mode 100644 source/seta010.c delete mode 100644 source/seta010.cpp create mode 100644 source/seta011.c delete mode 100644 source/seta011.cpp create mode 100644 source/seta018.c delete mode 100644 source/seta018.cpp create mode 100644 source/snaporig.c delete mode 100644 source/snaporig.cpp create mode 100644 source/snapshot.c delete mode 100644 source/snapshot.cpp create mode 100644 source/soundux.c delete mode 100644 source/soundux.cpp create mode 100644 source/spc700.c delete mode 100644 source/spc700.cpp create mode 100644 source/spc7110.c delete mode 100644 source/spc7110.cpp create mode 100644 source/srtc.c delete mode 100644 source/srtc.cpp create mode 100644 source/tile.c delete mode 100644 source/tile.cpp diff --git a/Makefile b/Makefile index b6ede7c..c813e55 100644 --- a/Makefile +++ b/Makefile @@ -48,24 +48,26 @@ NM = $(CROSS)nm OBJDUMP = $(CROSS)objdump #C_SOURCES = libretro.c -CPP_SOURCES = source/apu.cpp source/c4.cpp \ - source/c4emu.cpp source/cheats2.cpp source/cheats.cpp \ - source/clip.cpp source/cpu.cpp source/cpuexec.cpp \ - source/cpuops.cpp source/data.cpp\ - source/dma.cpp source/dsp1.cpp \ - source/fxdbg.cpp source/fxemu.cpp source/fxinst.cpp \ - source/gfx.cpp source/globals.cpp \ - source/memmap.cpp \ - source/obc1.cpp source/ppu.cpp \ - source/sa1.cpp source/sa1cpu.cpp source/screenshot.cpp \ - source/sdd1.cpp source/sdd1emu.cpp \ - source/seta010.cpp source/seta011.cpp source/seta018.cpp \ - source/seta.cpp source/snaporig.cpp source/snapshot.cpp \ - source/soundux.cpp \ - source/spc700.cpp source/spc7110.cpp \ - source/srtc.cpp \ - source/tile.cpp \ - libretro.cpp +C_SOURCES = source/apu.c source/c4.c \ + source/c4emu.c source/cheats2.c source/cheats.c \ + source/clip.c source/cpu.c source/cpuexec.c \ + source/cpuops.c source/data.c\ + source/dma.c source/dsp1.c \ + source/fxdbg.c source/fxemu.c source/fxinst.c \ + source/gfx.c source/globals.c \ + source/memmap.c \ + source/obc1.c source/ppu.c \ + source/sa1.c source/sa1cpu.c source/screenshot.c \ + source/sdd1.c source/sdd1emu.c \ + source/seta010.c source/seta011.c source/seta018.c \ + source/seta.c source/snaporig.c source/snapshot.c \ + source/soundux.c \ + source/spc700.c source/spc7110.c \ + source/srtc.c \ + source/tile.c \ + libretro.c + +CPP_SOURCES = SOURCES = $(C_SOURCES) $(CPP_SOURCES) C_OBJECTS = $(C_SOURCES:.c=.o) diff --git a/libretro.c b/libretro.c new file mode 100644 index 0000000..ded3dc9 --- /dev/null +++ b/libretro.c @@ -0,0 +1,877 @@ + +#include + +#include "snes9x.h" +#include "soundux.h" +#include "memmap.h" +#include "apu.h" +#include "cheats.h" +#include "snapshot.h" +#include "display.h" +#include "gfx.h" +#include "cpuexec.h" +#include "spc7110.h" + +#ifdef PSP +#include +#else +#ifndef PSP_LEGACY_TYPES_DEFINED +#define PSP_LEGACY_TYPES_DEFINED +typedef uint8_t u8; +typedef uint16_t u16; + +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; + +typedef int32_t s32; +typedef int64_t s64; +#endif +#endif + +#include + +static retro_log_printf_t log_cb = NULL; +static retro_video_refresh_t video_cb = NULL; +static retro_input_poll_t poll_cb = NULL; +static retro_input_state_t input_cb = NULL; +static retro_audio_sample_batch_t audio_batch_cb = NULL; +static retro_environment_t environ_cb = NULL; + + +struct retro_perf_callback perf_cb; + +void retro_set_environment(retro_environment_t cb) +{ + struct retro_log_callback log; + + environ_cb = cb; + + if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) + log_cb = log.log; + else + log_cb = NULL; + + environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb); + +} + + +void retro_set_video_refresh(retro_video_refresh_t cb) +{ + video_cb = cb; +} + +void retro_set_audio_sample(retro_audio_sample_t cb) +{} + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +{ + audio_batch_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) +{ + poll_cb = cb; +} + +void retro_set_input_state(retro_input_state_t cb) +{ + input_cb = cb; +} + +void retro_set_controller_port_device(unsigned port, unsigned device) {} + +unsigned retro_api_version() { return RETRO_API_VERSION; } + + + +void S9xProcessSound (unsigned int); + +char *rom_filename = NULL; +char *SDD1_pack = NULL; + +/* + * It is only safe to manipulate saved states between frames. + */ +static bool8 LoadStateNeeded = FALSE; +static bool8 SaveStateNeeded = FALSE; + +static u8 Buf[MAX_BUFFER_SIZE]; + +#define FIXED_POINT 0x10000 +#define FIXED_POINT_SHIFT 16 +#define FIXED_POINT_REMAINDER 0xffff + +void S9xMessage (int /*type*/, int /*number*/, const char *message) +{ +#if 1 +#define MAX_MESSAGE_LEN (36 * 3) + + static char buffer [MAX_MESSAGE_LEN + 1]; + + printf ("%s\n", message); + strncpy (buffer, message, MAX_MESSAGE_LEN); + buffer [MAX_MESSAGE_LEN] = 0; + S9xSetInfoString (buffer); +#endif +} + +void S9xExtraUsage () +{ + /*empty*/ +} + +/* +* Release display device +*/ +void S9xDeinitDisplay (void) +{ +#ifdef DS2_DMA + if(GFX.Screen) AlignedFree(GFX.Screen, PtrAdj.GFXScreen); +#else + if(GFX.Screen) free(GFX.Screen); +#endif + if(GFX.SubScreen) free(GFX.SubScreen); + if(GFX.ZBuffer) free(GFX.ZBuffer); + if(GFX.SubZBuffer) free(GFX.SubZBuffer); +} + +void S9xInitDisplay (void) +{ + int h = IMAGE_HEIGHT; + + GFX.Pitch = IMAGE_WIDTH * 2; +#ifdef DS2_DMA + GFX.Screen = (unsigned char*) AlignedMalloc (GFX.Pitch * h, 32, &PtrAdj.GFXScreen); +#else + GFX.Screen = (unsigned char*) malloc (GFX.Pitch * h); +#endif + GFX.SubScreen = (unsigned char*) malloc (GFX.Pitch * h); + GFX.ZBuffer = (unsigned char*) malloc ((GFX.Pitch >> 1) * h); + GFX.SubZBuffer =(unsigned char*) malloc ((GFX.Pitch >> 1) * h); + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; +} + +void S9xParseArg (char **argv, int &i, int argc) +{ +} + +void S9xParseDisplayArg (char **argv, int &ind, int) +{ +} + +void S9xExit () +{ +// if(Settings.SPC7110) +// (*CleanUp7110)(); + +// S9xSetSoundMute (TRUE); +// S9xDeinitDisplay (); +// Memory.SaveSRAM (S9xGetFilename (".srm")); +// // S9xSaveCheatFile (S9xGetFilename (".chb")); // cheat binary file +// // Do this when loading a cheat file! +// Memory.Deinit (); +// S9xDeinitAPU (); + +// exit(0); +} + +const char *S9xBasename (const char *f) +{ + const char *p; + if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) + return (p + 1); + + return (f); +} + +bool8 S9xInitUpdate () +{ +// IPPU.RenderThisFrame = 0; +// video_cb(dummy_frame,256,224,512); +// return (FALSE); + + return (TRUE); +} + + +extern void NDSSFCDrawFrameAntialiased(void* screen_addr); + +#ifdef PSP +#include +#include +void S9xDeinitUpdate (int width, int height, bool8 /*sixteen_bit*/) +{ + static unsigned int __attribute__((aligned(16))) d_list[32]; + void* const texture_vram_p = (void*) (0x44200000 - (512 * 512)); // max VRAM address - frame size + + sceKernelDcacheWritebackRange(GFX.Screen, GFX.Pitch*height); + + sceGuStart(GU_DIRECT, d_list); + + sceGuCopyImage(GU_PSM_4444, 0, 0, width, height, GFX.Pitch>>1, GFX.Screen, 0, 0, 512, texture_vram_p); + + sceGuTexSync(); + sceGuTexImage(0, 512, 512, 512, texture_vram_p); + sceGuTexMode(GU_PSM_5551, 0, 0, GU_FALSE); + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); + sceGuDisable(GU_BLEND); + + sceGuFinish(); + + + video_cb(texture_vram_p, width, height, GFX.Pitch); +} + +#else +void S9xDeinitUpdate (int width, int height) +{ + video_cb(GFX.Screen, width, height, GFX.Pitch); +} + +#endif + +void _makepath (char *path, const char *, const char *dir, + const char *fname, const char *ext) +{ + if (dir && *dir) + { + strcpy (path, dir); + strcat (path, "/"); + } + else + *path = 0; + strcat (path, fname); + if (ext && *ext) + { + strcat (path, "."); + strcat (path, ext); + } +} + +void _splitpath (const char *path, char *drive, char *dir, char *fname, + char *ext) +{ + *drive = 0; + + char *slash = strrchr ((char*)path, '/'); + if (!slash) + slash = strrchr ((char*)path, '\\'); + + char *dot = strrchr ((char*)path, '.'); + + if (dot && slash && dot < slash) + dot = NULL; + + if (!slash) + { + strcpy (dir, ""); + strcpy (fname, path); + if (dot) + { + *(fname + (dot - path)) = 0; + strcpy (ext, dot + 1); + } + else + strcpy (ext, ""); + } + else + { + strcpy (dir, path); + *(dir + (slash - path)) = 0; + strcpy (fname, slash + 1); + if (dot) + { + *(fname + (dot - slash) - 1) = 0; + strcpy (ext, dot + 1); + } + else + strcpy (ext, ""); + } +} + +void S9xProcessEvents (bool8 block) +{ + +} + +void OutOfMemory () +{ +} + + +const char *S9xGetROMDirectory () +{ + return "./"; +} + + +const char *S9xGetSnapshotDirectory () +{ + return "./"; +} + +const char *S9xGetFilename (const char *ex) +{ + static char filename [PATH_MAX + 1]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy (filename, S9xGetSnapshotDirectory ()); + strcat (filename, SLASH_STR); + strcat (filename, fname); + strcat (filename, ex); + + return (filename); +} + +const char *S9xGetFilenameInc (const char *e) +{ + return e; +#if 0 + static char filename [_MAX_PATH + 1]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char *ptr; + struct stat buf; + + if (strlen (S9xGetSnapshotDirectory())) + { + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy (filename, S9xGetSnapshotDirectory()); + strcat (filename, "/"); + strcat (filename, fname); + ptr = filename + strlen (filename); + strcat (filename, "00/"); + strcat (filename, e); + } + else + { + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcat (fname, "00/"); + _makepath (filename, drive, dir, fname, e); + ptr = strstr (filename, "00/"); + } + + do + { + if (++*(ptr + 2) > '9') + { + *(ptr + 2) = '0'; + if (++*(ptr + 1) > '9') + { + *(ptr + 1) = '0'; + if (++*ptr > '9') + break; + } + } + } while( stat(filename, &buf) == 0 ); + + return (filename); +#endif +} + +void S9xInitInputDevices () +{ +#ifdef JOYSTICK_SUPPORT + InitJoysticks (); +#endif +} + + +void init_sfc_setting(void) +{ + ZeroMemory (&Settings, sizeof (Settings)); +#ifdef JOYSTICK_SUPPORT + Settings.JoystickEnabled = TRUE; +#else + Settings.JoystickEnabled = FALSE; +#endif + + Settings.SoundPlaybackRate = 44100; // -> ds2sound.h for defs + Settings.SoundBufferSize = 512; + Settings.CyclesPercentage = 100; + Settings.DisableSoundEcho = FALSE; + //sound settings + Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; + // Settings.FixFrequency = 1; + + Settings.H_Max = SNES_CYCLES_PER_SCANLINE; + Settings.SkipFrames = AUTO_FRAMERATE; + Settings.ShutdownMaster = TRUE; + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + Settings.DisableMasterVolume = FALSE; + Settings.Mouse = TRUE; + Settings.SuperScope = TRUE; + Settings.MultiPlayer5 = TRUE; + Settings.ControllerOption = SNES_JOYPAD; + + Settings.Transparency = TRUE; + Settings.SupportHiRes = FALSE; + Settings.ThreadSound = FALSE; + Settings.SoundSync = TRUE; + Settings.ApplyCheats = TRUE; + Settings.StretchScreenshots = 1; + + Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; +} + +void S9xAutoSaveSRAM () +{ + Memory.SaveSRAM (S9xGetFilename (".srm")); +} + +int game_load_state(char* file) +{ + int flag; + + flag = 0; + if(S9xUnfreezeGame(file) == FALSE) + flag = -1; + + return flag; +} + +int game_save_state(char* file) +{ + int flag; + + flag = 0; + if(S9xFreezeGame(file) == FALSE) + flag = -1; + + S9xAutoSaveSRAM (); + + return flag; +} + +void game_restart(void) +{ + CPU.Flags = 0; + S9xReset (); +} + +int load_gamepak(const char* file) +{ + CPU.Flags = 0; + // mdelay(50); // Delete this delay + if (!Memory.LoadROM (file)) + return -1; + S9xReset (); + + Settings.FrameTime = (Settings.PAL ? Settings.FrameTimePAL : Settings.FrameTimeNTSC); + + Memory.LoadSRAM (S9xGetFilename (".srm")); + S9xLoadCheatFile (S9xGetFilename (".chb")); // cheat binary file, as opposed to text + + return 0; +} + +extern "C" void sfc_main(void); + +void retro_init (void) +{ + struct retro_log_callback log; + enum retro_pixel_format rgb565; + + if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) + log_cb = log.log; + else + log_cb = NULL; + + rgb565 = RETRO_PIXEL_FORMAT_RGB565; + if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb) + log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); + + init_sfc_setting(); + + if (!Memory.Init () || !S9xInitAPU()) + OutOfMemory (); + + S9xInitDisplay (); + if (!S9xGraphicsInit()) + OutOfMemory (); + + S9xInitSound (Settings.SoundPlaybackRate, + TRUE, + Settings.SoundBufferSize); + +#ifdef JOYSTICK_SUPPORT + uint32 JoypadSkip = 0; +#endif + + +} + + +uint32 S9xReadJoypad (int port) +{ + static const uint32 snes_lut[] = { + SNES_B_MASK, + SNES_Y_MASK, + SNES_SELECT_MASK, + SNES_START_MASK, + SNES_UP_MASK, + SNES_DOWN_MASK, + SNES_LEFT_MASK, + SNES_RIGHT_MASK, + SNES_A_MASK, + SNES_X_MASK, + SNES_TL_MASK, + SNES_TR_MASK + }; + + int i; + uint32 joypad = 0; + + for ( i = RETRO_DEVICE_ID_JOYPAD_B; i <= RETRO_DEVICE_ID_JOYPAD_R; i++) + if (input_cb(port, RETRO_DEVICE_JOYPAD, 0, i)) + joypad |= snes_lut[i]; + + return joypad; +} + +//#define FRAMESKIP +void retro_run (void) +{ + int i, port; + +// IPPU.RenderThisFrame = FALSE; +// video_cb(GFX.Screen, 256, 224, 512); + + poll_cb(); + + S9xSetPlaybackRate(32040); + so.mute_sound = FALSE; + SoundData.echo_enable = FALSE; + + S9xMainLoop(); + + static s16 audio_buf[534 << 1]; + S9xMixSamples ((uint8*)audio_buf, 534 << 1); + audio_batch_cb(audio_buf, 534); + + +#ifdef FRAMESKIP + if (IPPU.RenderThisFrame) + IPPU.RenderThisFrame = false; + else + { + video_cb(NULL, 256, 224, GFX.Pitch); + IPPU.RenderThisFrame = true; + } +#endif + +// if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) +// check_variables(); + +} + + +static unsigned int sync_last= 0; +static unsigned int sync_next = 0; + +static unsigned int skip_rate= 0; + +void S9xSyncSpeed () +{ +} + +bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) +{ + return (TRUE); +} + +void S9xGenerateSound () +{ +// static s16 audio_buf[855 << 1]; +// S9xMixSamples ((uint8*)audio_buf, 855 << 1); +// audio_batch_cb(audio_buf, 855); + + + +} + +void S9xGenerateSound0 () +{ + int bytes_so_far = so.samples_mixed_so_far << 1; + + if (bytes_so_far >= so.buffer_size) + return; + + so.err_counter += so.err_rate; + if (so.err_counter >= FIXED_POINT) + { + // Write this many samples overall + int samples_to_write = so.err_counter >> FIXED_POINT_SHIFT; + samples_to_write <<= 1; + int byte_offset = (bytes_so_far + so.play_position) & SOUND_BUFFER_SIZE_MASK; + + so.err_counter &= FIXED_POINT_REMAINDER; + + do + { + int bytes_this_run = samples_to_write; + bytes_this_run <<= 1; + + if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE) + { + bytes_this_run = SOUND_BUFFER_SIZE - byte_offset; + } + + if (bytes_so_far + bytes_this_run > so.buffer_size) + { + bytes_this_run = so.buffer_size - bytes_so_far; + if (bytes_this_run == 0) + break; + } + + int samples_this_run = bytes_this_run; + samples_this_run >>= 1; + + S9xMixSamples (Buf + byte_offset, samples_this_run); + so.samples_mixed_so_far += samples_this_run; + samples_to_write -= samples_this_run; + bytes_so_far += samples_this_run << 1; + byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK; + } while (samples_to_write > 0); + } +} + +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +#define TRUE_SOUND_EMISSION_INTERVAL ((((double) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) +#define SOUND_EMISSION_INTERVAL_ERROR ((int) ((TRUE_SOUND_EMISSION_INTERVAL - SOUND_EMISSION_INTERVAL) * FIXED_POINT)) +static unsigned int LastSoundEmissionTime = 0; + +/* + * Accumulated error in the sound emission time. The unit is as follows: + * FIXED_POINT = 42.667 microseconds. + * As the error goes past FIXED_POINT, the new target for sound emission + * becomes 42.667 microseconds LATER. This helps with sound buffer overruns, + * correctly dealing with the fact that 42.667 microseconds does not fit + * an integer number of times in 1/32000 second (or whatever sampling rate). + */ +static unsigned int SoundEmissionTimeError = 0; + +void S9xProcessSound (unsigned int) +{ + +} + +/* +const unsigned int keymap[12] = { + 0x80, //KEY_A + 0x8000, //KEY_B + 0x2000, //KEY_SELECT + 0x1000, //KEY_START + 0x100, //KEY_RIGHT + 0x200, //KEY_LEFT + 0x800, //KEY_UP + 0x400, //KEY_DOWN + 0x10, //KEY_R + 0x20, //KEY_L + 0x40, //KEY_X + 0x4000 //KEY_Y + }; +*/ + +static bool8 SoundToggleWasHeld = FALSE; +static bool8 LoadStateWasHeld = FALSE; +static bool8 SaveStateWasHeld = FALSE; +static bool8 ToggleFullScreenWasHeld = FALSE; + +#ifdef ACCUMULATE_JOYPAD +// These are kept as DS key bitfields until it's time to send them to Snes9x. +static uint32 PreviousControls = 0x00000000; +static uint32 ControlsPressed = 0x00000000; +static uint32 ControlsReleased = 0x00000000; + +void NDSSFCAccumulateJoypad () +{ + struct key_buf inputdata; + ds2_getrawInput(&inputdata); + + ControlsPressed |= inputdata.key & ~PreviousControls; + ControlsReleased |= PreviousControls & ~inputdata.key; +} +#endif // ACCUMULATE_JOYPAD + +static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) +{ + return (*(uint32 *) p1 - *(uint32 *) p2); +} + +void S9xLoadSDD1Data () +{ + +} + +bool8 S9xReadMousePosition (int which1, int &x, int &y, uint32 &buttons) +{ + return (FALSE); +} + +bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons) +{ + return (TRUE); +} + +bool JustifierOffscreen() +{ + return (FALSE); +} + +void JustifierButtons(uint32& justifiers) +{ +} + +START_EXTERN_C +char* osd_GetPackDir() +{ + static char filename[_MAX_PATH]; + memset(filename, 0, _MAX_PATH); + + if(strlen(S9xGetSnapshotDirectory())!=0) + strcpy (filename, S9xGetSnapshotDirectory()); + else + { + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char name [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + _splitpath(Memory.ROMFilename, drive, dir, name, ext); + _makepath(filename, drive, dir, NULL, NULL); + } + + if(!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21)) + { + if (getenv("SPL4PACK")) + return getenv("SPL4PACK"); + else + strcat(filename, "/SPL4-SP7"); + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ",21)) + { + if (getenv("MDHPACK")) + return getenv("MDHPACK"); + else + strcat(filename, "/SMHT-SP7"); + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21)) + { + if (getenv("FEOEZPACK")) + return getenv("FEOEZPACK"); + else + strcat(filename, "/FEOEZSP7"); + } + else if(!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO",21)) + { + if (getenv("SJNSPACK")) + return getenv("SJNSPACK"); + else + strcat(filename, "/SJUMPSP7"); + } else strcat(filename, "/MISC-SP7"); + return filename; +} +END_EXTERN_C + + +void retro_deinit (void) +{ +} +unsigned retro_get_region (void) +{ + return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; +} +void retro_get_system_info(struct retro_system_info *info) +{ + info->need_fullpath = true; + info->valid_extensions = "smc|fig|sfc|gd3|gd7|dx2|bsx|swc"; + info->library_version = "v1.4"; + info->library_name = "SNES9x(CATSFC)"; + info->block_extract = false; +} +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + info->geometry.base_width = 256; + info->geometry.base_height = 224; + info->geometry.max_width = 512; + info->geometry.max_height = 512; + info->geometry.aspect_ratio = 4.0 / 3.0; +// if (!Settings.PAL) +// info->timing.fps = 21477272.0 / 357366.0; +// else +// info->timing.fps = 21281370.0 / 425568.0; +// info->timing.sample_rate = 32040.5; + + + info->timing.fps = 60.0; + info->timing.sample_rate = 32040.0; +} + +void retro_reset(void) +{ + +} + + +size_t retro_serialize_size(void) +{ + return 0; +} + +bool retro_serialize(void *data, size_t size) +{ + return false; +} +bool retro_unserialize(const void *data, size_t size) +{ + return false; +} + +void retro_cheat_reset(void) +{ + +} +void retro_cheat_set(unsigned index, bool enabled, const char *code) +{ + +} + +bool retro_load_game(const struct retro_game_info *game) + +{ + Memory.LoadROM(game->path); + return true; +} + +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +) +{ + return false; +} +void retro_unload_game(void) +{ + +} + +void *retro_get_memory_data(unsigned id) +{ + return NULL; +} + +size_t retro_get_memory_size(unsigned id) +{ + return 0; +} diff --git a/libretro.cpp b/libretro.cpp deleted file mode 100644 index ded3dc9..0000000 --- a/libretro.cpp +++ /dev/null @@ -1,877 +0,0 @@ - -#include - -#include "snes9x.h" -#include "soundux.h" -#include "memmap.h" -#include "apu.h" -#include "cheats.h" -#include "snapshot.h" -#include "display.h" -#include "gfx.h" -#include "cpuexec.h" -#include "spc7110.h" - -#ifdef PSP -#include -#else -#ifndef PSP_LEGACY_TYPES_DEFINED -#define PSP_LEGACY_TYPES_DEFINED -typedef uint8_t u8; -typedef uint16_t u16; - -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; -typedef int16_t s16; - -typedef int32_t s32; -typedef int64_t s64; -#endif -#endif - -#include - -static retro_log_printf_t log_cb = NULL; -static retro_video_refresh_t video_cb = NULL; -static retro_input_poll_t poll_cb = NULL; -static retro_input_state_t input_cb = NULL; -static retro_audio_sample_batch_t audio_batch_cb = NULL; -static retro_environment_t environ_cb = NULL; - - -struct retro_perf_callback perf_cb; - -void retro_set_environment(retro_environment_t cb) -{ - struct retro_log_callback log; - - environ_cb = cb; - - if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) - log_cb = log.log; - else - log_cb = NULL; - - environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb); - -} - - -void retro_set_video_refresh(retro_video_refresh_t cb) -{ - video_cb = cb; -} - -void retro_set_audio_sample(retro_audio_sample_t cb) -{} - -void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) -{ - audio_batch_cb = cb; -} - -void retro_set_input_poll(retro_input_poll_t cb) -{ - poll_cb = cb; -} - -void retro_set_input_state(retro_input_state_t cb) -{ - input_cb = cb; -} - -void retro_set_controller_port_device(unsigned port, unsigned device) {} - -unsigned retro_api_version() { return RETRO_API_VERSION; } - - - -void S9xProcessSound (unsigned int); - -char *rom_filename = NULL; -char *SDD1_pack = NULL; - -/* - * It is only safe to manipulate saved states between frames. - */ -static bool8 LoadStateNeeded = FALSE; -static bool8 SaveStateNeeded = FALSE; - -static u8 Buf[MAX_BUFFER_SIZE]; - -#define FIXED_POINT 0x10000 -#define FIXED_POINT_SHIFT 16 -#define FIXED_POINT_REMAINDER 0xffff - -void S9xMessage (int /*type*/, int /*number*/, const char *message) -{ -#if 1 -#define MAX_MESSAGE_LEN (36 * 3) - - static char buffer [MAX_MESSAGE_LEN + 1]; - - printf ("%s\n", message); - strncpy (buffer, message, MAX_MESSAGE_LEN); - buffer [MAX_MESSAGE_LEN] = 0; - S9xSetInfoString (buffer); -#endif -} - -void S9xExtraUsage () -{ - /*empty*/ -} - -/* -* Release display device -*/ -void S9xDeinitDisplay (void) -{ -#ifdef DS2_DMA - if(GFX.Screen) AlignedFree(GFX.Screen, PtrAdj.GFXScreen); -#else - if(GFX.Screen) free(GFX.Screen); -#endif - if(GFX.SubScreen) free(GFX.SubScreen); - if(GFX.ZBuffer) free(GFX.ZBuffer); - if(GFX.SubZBuffer) free(GFX.SubZBuffer); -} - -void S9xInitDisplay (void) -{ - int h = IMAGE_HEIGHT; - - GFX.Pitch = IMAGE_WIDTH * 2; -#ifdef DS2_DMA - GFX.Screen = (unsigned char*) AlignedMalloc (GFX.Pitch * h, 32, &PtrAdj.GFXScreen); -#else - GFX.Screen = (unsigned char*) malloc (GFX.Pitch * h); -#endif - GFX.SubScreen = (unsigned char*) malloc (GFX.Pitch * h); - GFX.ZBuffer = (unsigned char*) malloc ((GFX.Pitch >> 1) * h); - GFX.SubZBuffer =(unsigned char*) malloc ((GFX.Pitch >> 1) * h); - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; -} - -void S9xParseArg (char **argv, int &i, int argc) -{ -} - -void S9xParseDisplayArg (char **argv, int &ind, int) -{ -} - -void S9xExit () -{ -// if(Settings.SPC7110) -// (*CleanUp7110)(); - -// S9xSetSoundMute (TRUE); -// S9xDeinitDisplay (); -// Memory.SaveSRAM (S9xGetFilename (".srm")); -// // S9xSaveCheatFile (S9xGetFilename (".chb")); // cheat binary file -// // Do this when loading a cheat file! -// Memory.Deinit (); -// S9xDeinitAPU (); - -// exit(0); -} - -const char *S9xBasename (const char *f) -{ - const char *p; - if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) - return (p + 1); - - return (f); -} - -bool8 S9xInitUpdate () -{ -// IPPU.RenderThisFrame = 0; -// video_cb(dummy_frame,256,224,512); -// return (FALSE); - - return (TRUE); -} - - -extern void NDSSFCDrawFrameAntialiased(void* screen_addr); - -#ifdef PSP -#include -#include -void S9xDeinitUpdate (int width, int height, bool8 /*sixteen_bit*/) -{ - static unsigned int __attribute__((aligned(16))) d_list[32]; - void* const texture_vram_p = (void*) (0x44200000 - (512 * 512)); // max VRAM address - frame size - - sceKernelDcacheWritebackRange(GFX.Screen, GFX.Pitch*height); - - sceGuStart(GU_DIRECT, d_list); - - sceGuCopyImage(GU_PSM_4444, 0, 0, width, height, GFX.Pitch>>1, GFX.Screen, 0, 0, 512, texture_vram_p); - - sceGuTexSync(); - sceGuTexImage(0, 512, 512, 512, texture_vram_p); - sceGuTexMode(GU_PSM_5551, 0, 0, GU_FALSE); - sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); - sceGuDisable(GU_BLEND); - - sceGuFinish(); - - - video_cb(texture_vram_p, width, height, GFX.Pitch); -} - -#else -void S9xDeinitUpdate (int width, int height) -{ - video_cb(GFX.Screen, width, height, GFX.Pitch); -} - -#endif - -void _makepath (char *path, const char *, const char *dir, - const char *fname, const char *ext) -{ - if (dir && *dir) - { - strcpy (path, dir); - strcat (path, "/"); - } - else - *path = 0; - strcat (path, fname); - if (ext && *ext) - { - strcat (path, "."); - strcat (path, ext); - } -} - -void _splitpath (const char *path, char *drive, char *dir, char *fname, - char *ext) -{ - *drive = 0; - - char *slash = strrchr ((char*)path, '/'); - if (!slash) - slash = strrchr ((char*)path, '\\'); - - char *dot = strrchr ((char*)path, '.'); - - if (dot && slash && dot < slash) - dot = NULL; - - if (!slash) - { - strcpy (dir, ""); - strcpy (fname, path); - if (dot) - { - *(fname + (dot - path)) = 0; - strcpy (ext, dot + 1); - } - else - strcpy (ext, ""); - } - else - { - strcpy (dir, path); - *(dir + (slash - path)) = 0; - strcpy (fname, slash + 1); - if (dot) - { - *(fname + (dot - slash) - 1) = 0; - strcpy (ext, dot + 1); - } - else - strcpy (ext, ""); - } -} - -void S9xProcessEvents (bool8 block) -{ - -} - -void OutOfMemory () -{ -} - - -const char *S9xGetROMDirectory () -{ - return "./"; -} - - -const char *S9xGetSnapshotDirectory () -{ - return "./"; -} - -const char *S9xGetFilename (const char *ex) -{ - static char filename [PATH_MAX + 1]; - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1]; - char fname [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - - _splitpath (Memory.ROMFilename, drive, dir, fname, ext); - strcpy (filename, S9xGetSnapshotDirectory ()); - strcat (filename, SLASH_STR); - strcat (filename, fname); - strcat (filename, ex); - - return (filename); -} - -const char *S9xGetFilenameInc (const char *e) -{ - return e; -#if 0 - static char filename [_MAX_PATH + 1]; - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1]; - char fname [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char *ptr; - struct stat buf; - - if (strlen (S9xGetSnapshotDirectory())) - { - _splitpath (Memory.ROMFilename, drive, dir, fname, ext); - strcpy (filename, S9xGetSnapshotDirectory()); - strcat (filename, "/"); - strcat (filename, fname); - ptr = filename + strlen (filename); - strcat (filename, "00/"); - strcat (filename, e); - } - else - { - _splitpath (Memory.ROMFilename, drive, dir, fname, ext); - strcat (fname, "00/"); - _makepath (filename, drive, dir, fname, e); - ptr = strstr (filename, "00/"); - } - - do - { - if (++*(ptr + 2) > '9') - { - *(ptr + 2) = '0'; - if (++*(ptr + 1) > '9') - { - *(ptr + 1) = '0'; - if (++*ptr > '9') - break; - } - } - } while( stat(filename, &buf) == 0 ); - - return (filename); -#endif -} - -void S9xInitInputDevices () -{ -#ifdef JOYSTICK_SUPPORT - InitJoysticks (); -#endif -} - - -void init_sfc_setting(void) -{ - ZeroMemory (&Settings, sizeof (Settings)); -#ifdef JOYSTICK_SUPPORT - Settings.JoystickEnabled = TRUE; -#else - Settings.JoystickEnabled = FALSE; -#endif - - Settings.SoundPlaybackRate = 44100; // -> ds2sound.h for defs - Settings.SoundBufferSize = 512; - Settings.CyclesPercentage = 100; - Settings.DisableSoundEcho = FALSE; - //sound settings - Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; - // Settings.FixFrequency = 1; - - Settings.H_Max = SNES_CYCLES_PER_SCANLINE; - Settings.SkipFrames = AUTO_FRAMERATE; - Settings.ShutdownMaster = TRUE; - Settings.FrameTimePAL = 20000; - Settings.FrameTimeNTSC = 16667; - Settings.DisableMasterVolume = FALSE; - Settings.Mouse = TRUE; - Settings.SuperScope = TRUE; - Settings.MultiPlayer5 = TRUE; - Settings.ControllerOption = SNES_JOYPAD; - - Settings.Transparency = TRUE; - Settings.SupportHiRes = FALSE; - Settings.ThreadSound = FALSE; - Settings.SoundSync = TRUE; - Settings.ApplyCheats = TRUE; - Settings.StretchScreenshots = 1; - - Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; -} - -void S9xAutoSaveSRAM () -{ - Memory.SaveSRAM (S9xGetFilename (".srm")); -} - -int game_load_state(char* file) -{ - int flag; - - flag = 0; - if(S9xUnfreezeGame(file) == FALSE) - flag = -1; - - return flag; -} - -int game_save_state(char* file) -{ - int flag; - - flag = 0; - if(S9xFreezeGame(file) == FALSE) - flag = -1; - - S9xAutoSaveSRAM (); - - return flag; -} - -void game_restart(void) -{ - CPU.Flags = 0; - S9xReset (); -} - -int load_gamepak(const char* file) -{ - CPU.Flags = 0; - // mdelay(50); // Delete this delay - if (!Memory.LoadROM (file)) - return -1; - S9xReset (); - - Settings.FrameTime = (Settings.PAL ? Settings.FrameTimePAL : Settings.FrameTimeNTSC); - - Memory.LoadSRAM (S9xGetFilename (".srm")); - S9xLoadCheatFile (S9xGetFilename (".chb")); // cheat binary file, as opposed to text - - return 0; -} - -extern "C" void sfc_main(void); - -void retro_init (void) -{ - struct retro_log_callback log; - enum retro_pixel_format rgb565; - - if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) - log_cb = log.log; - else - log_cb = NULL; - - rgb565 = RETRO_PIXEL_FORMAT_RGB565; - if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb) - log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); - - init_sfc_setting(); - - if (!Memory.Init () || !S9xInitAPU()) - OutOfMemory (); - - S9xInitDisplay (); - if (!S9xGraphicsInit()) - OutOfMemory (); - - S9xInitSound (Settings.SoundPlaybackRate, - TRUE, - Settings.SoundBufferSize); - -#ifdef JOYSTICK_SUPPORT - uint32 JoypadSkip = 0; -#endif - - -} - - -uint32 S9xReadJoypad (int port) -{ - static const uint32 snes_lut[] = { - SNES_B_MASK, - SNES_Y_MASK, - SNES_SELECT_MASK, - SNES_START_MASK, - SNES_UP_MASK, - SNES_DOWN_MASK, - SNES_LEFT_MASK, - SNES_RIGHT_MASK, - SNES_A_MASK, - SNES_X_MASK, - SNES_TL_MASK, - SNES_TR_MASK - }; - - int i; - uint32 joypad = 0; - - for ( i = RETRO_DEVICE_ID_JOYPAD_B; i <= RETRO_DEVICE_ID_JOYPAD_R; i++) - if (input_cb(port, RETRO_DEVICE_JOYPAD, 0, i)) - joypad |= snes_lut[i]; - - return joypad; -} - -//#define FRAMESKIP -void retro_run (void) -{ - int i, port; - -// IPPU.RenderThisFrame = FALSE; -// video_cb(GFX.Screen, 256, 224, 512); - - poll_cb(); - - S9xSetPlaybackRate(32040); - so.mute_sound = FALSE; - SoundData.echo_enable = FALSE; - - S9xMainLoop(); - - static s16 audio_buf[534 << 1]; - S9xMixSamples ((uint8*)audio_buf, 534 << 1); - audio_batch_cb(audio_buf, 534); - - -#ifdef FRAMESKIP - if (IPPU.RenderThisFrame) - IPPU.RenderThisFrame = false; - else - { - video_cb(NULL, 256, 224, GFX.Pitch); - IPPU.RenderThisFrame = true; - } -#endif - -// if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) -// check_variables(); - -} - - -static unsigned int sync_last= 0; -static unsigned int sync_next = 0; - -static unsigned int skip_rate= 0; - -void S9xSyncSpeed () -{ -} - -bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) -{ - return (TRUE); -} - -void S9xGenerateSound () -{ -// static s16 audio_buf[855 << 1]; -// S9xMixSamples ((uint8*)audio_buf, 855 << 1); -// audio_batch_cb(audio_buf, 855); - - - -} - -void S9xGenerateSound0 () -{ - int bytes_so_far = so.samples_mixed_so_far << 1; - - if (bytes_so_far >= so.buffer_size) - return; - - so.err_counter += so.err_rate; - if (so.err_counter >= FIXED_POINT) - { - // Write this many samples overall - int samples_to_write = so.err_counter >> FIXED_POINT_SHIFT; - samples_to_write <<= 1; - int byte_offset = (bytes_so_far + so.play_position) & SOUND_BUFFER_SIZE_MASK; - - so.err_counter &= FIXED_POINT_REMAINDER; - - do - { - int bytes_this_run = samples_to_write; - bytes_this_run <<= 1; - - if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE) - { - bytes_this_run = SOUND_BUFFER_SIZE - byte_offset; - } - - if (bytes_so_far + bytes_this_run > so.buffer_size) - { - bytes_this_run = so.buffer_size - bytes_so_far; - if (bytes_this_run == 0) - break; - } - - int samples_this_run = bytes_this_run; - samples_this_run >>= 1; - - S9xMixSamples (Buf + byte_offset, samples_this_run); - so.samples_mixed_so_far += samples_this_run; - samples_to_write -= samples_this_run; - bytes_so_far += samples_this_run << 1; - byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK; - } while (samples_to_write > 0); - } -} - -#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) -#define TRUE_SOUND_EMISSION_INTERVAL ((((double) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) -#define SOUND_EMISSION_INTERVAL_ERROR ((int) ((TRUE_SOUND_EMISSION_INTERVAL - SOUND_EMISSION_INTERVAL) * FIXED_POINT)) -static unsigned int LastSoundEmissionTime = 0; - -/* - * Accumulated error in the sound emission time. The unit is as follows: - * FIXED_POINT = 42.667 microseconds. - * As the error goes past FIXED_POINT, the new target for sound emission - * becomes 42.667 microseconds LATER. This helps with sound buffer overruns, - * correctly dealing with the fact that 42.667 microseconds does not fit - * an integer number of times in 1/32000 second (or whatever sampling rate). - */ -static unsigned int SoundEmissionTimeError = 0; - -void S9xProcessSound (unsigned int) -{ - -} - -/* -const unsigned int keymap[12] = { - 0x80, //KEY_A - 0x8000, //KEY_B - 0x2000, //KEY_SELECT - 0x1000, //KEY_START - 0x100, //KEY_RIGHT - 0x200, //KEY_LEFT - 0x800, //KEY_UP - 0x400, //KEY_DOWN - 0x10, //KEY_R - 0x20, //KEY_L - 0x40, //KEY_X - 0x4000 //KEY_Y - }; -*/ - -static bool8 SoundToggleWasHeld = FALSE; -static bool8 LoadStateWasHeld = FALSE; -static bool8 SaveStateWasHeld = FALSE; -static bool8 ToggleFullScreenWasHeld = FALSE; - -#ifdef ACCUMULATE_JOYPAD -// These are kept as DS key bitfields until it's time to send them to Snes9x. -static uint32 PreviousControls = 0x00000000; -static uint32 ControlsPressed = 0x00000000; -static uint32 ControlsReleased = 0x00000000; - -void NDSSFCAccumulateJoypad () -{ - struct key_buf inputdata; - ds2_getrawInput(&inputdata); - - ControlsPressed |= inputdata.key & ~PreviousControls; - ControlsReleased |= PreviousControls & ~inputdata.key; -} -#endif // ACCUMULATE_JOYPAD - -static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) -{ - return (*(uint32 *) p1 - *(uint32 *) p2); -} - -void S9xLoadSDD1Data () -{ - -} - -bool8 S9xReadMousePosition (int which1, int &x, int &y, uint32 &buttons) -{ - return (FALSE); -} - -bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons) -{ - return (TRUE); -} - -bool JustifierOffscreen() -{ - return (FALSE); -} - -void JustifierButtons(uint32& justifiers) -{ -} - -START_EXTERN_C -char* osd_GetPackDir() -{ - static char filename[_MAX_PATH]; - memset(filename, 0, _MAX_PATH); - - if(strlen(S9xGetSnapshotDirectory())!=0) - strcpy (filename, S9xGetSnapshotDirectory()); - else - { - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - _splitpath(Memory.ROMFilename, drive, dir, name, ext); - _makepath(filename, drive, dir, NULL, NULL); - } - - if(!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21)) - { - if (getenv("SPL4PACK")) - return getenv("SPL4PACK"); - else - strcat(filename, "/SPL4-SP7"); - } - else if(!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ",21)) - { - if (getenv("MDHPACK")) - return getenv("MDHPACK"); - else - strcat(filename, "/SMHT-SP7"); - } - else if(!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21)) - { - if (getenv("FEOEZPACK")) - return getenv("FEOEZPACK"); - else - strcat(filename, "/FEOEZSP7"); - } - else if(!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO",21)) - { - if (getenv("SJNSPACK")) - return getenv("SJNSPACK"); - else - strcat(filename, "/SJUMPSP7"); - } else strcat(filename, "/MISC-SP7"); - return filename; -} -END_EXTERN_C - - -void retro_deinit (void) -{ -} -unsigned retro_get_region (void) -{ - return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; -} -void retro_get_system_info(struct retro_system_info *info) -{ - info->need_fullpath = true; - info->valid_extensions = "smc|fig|sfc|gd3|gd7|dx2|bsx|swc"; - info->library_version = "v1.4"; - info->library_name = "SNES9x(CATSFC)"; - info->block_extract = false; -} -void retro_get_system_av_info(struct retro_system_av_info *info) -{ - info->geometry.base_width = 256; - info->geometry.base_height = 224; - info->geometry.max_width = 512; - info->geometry.max_height = 512; - info->geometry.aspect_ratio = 4.0 / 3.0; -// if (!Settings.PAL) -// info->timing.fps = 21477272.0 / 357366.0; -// else -// info->timing.fps = 21281370.0 / 425568.0; -// info->timing.sample_rate = 32040.5; - - - info->timing.fps = 60.0; - info->timing.sample_rate = 32040.0; -} - -void retro_reset(void) -{ - -} - - -size_t retro_serialize_size(void) -{ - return 0; -} - -bool retro_serialize(void *data, size_t size) -{ - return false; -} -bool retro_unserialize(const void *data, size_t size) -{ - return false; -} - -void retro_cheat_reset(void) -{ - -} -void retro_cheat_set(unsigned index, bool enabled, const char *code) -{ - -} - -bool retro_load_game(const struct retro_game_info *game) - -{ - Memory.LoadROM(game->path); - return true; -} - -bool retro_load_game_special( - unsigned game_type, - const struct retro_game_info *info, size_t num_info -) -{ - return false; -} -void retro_unload_game(void) -{ - -} - -void *retro_get_memory_data(unsigned id) -{ - return NULL; -} - -size_t retro_get_memory_size(unsigned id) -{ - return 0; -} diff --git a/source/apu.c b/source/apu.c new file mode 100644 index 0000000..ee41096 --- /dev/null +++ b/source/apu.c @@ -0,0 +1,772 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#ifdef __DJGPP +#include +#undef TRUE +#endif + +#include "snes9x.h" +#include "spc700.h" +#include "apu.h" +#include "soundux.h" +#include "cpuexec.h" + +/* For note-triggered SPC dump support */ +#include "snapshot.h" + +extern "C" {const char *S9xGetFilenameInc (const char *);} + +int spc_is_dumping=0; +int spc_is_dumping_temp; +uint8 spc_dump_dsp[0x100]; + +extern int NoiseFreq [32]; + +bool8 S9xInitAPU () +{ + IAPU.RAM = (uint8 *) malloc (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; + + 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 converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (APU.ExtraRAM, APUROM, sizeof (APUROM)); + IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); + APU.Cycles = 0; + IAPU.Registers.YA.W = 0; + IAPU.Registers.X = 0; + IAPU.Registers.S = 0xff; + IAPU.Registers.P = 0; + S9xAPUUnpackStatus (); + IAPU.Registers.PC = 0; + IAPU.APUExecuting = Settings.APUEnabled; +#ifdef SPC700_SHUTDOWN + IAPU.WaitAddress1 = NULL; + IAPU.WaitAddress2 = NULL; + IAPU.WaitCounter = 0; +#endif + 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); +} + +void S9xSetAPUDSP (uint8 byte) +{ + uint8 reg = IAPU.RAM [0xf2]; + static uint8 KeyOn; + static uint8 KeyOnPrev; + int i; + + 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); + + // Kill sound + S9xResetSound (FALSE); + } + else + { + S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED)); + if (byte & APU_MUTE) + { + S9xSetSoundMute (TRUE); + } + else + S9xSetSoundMute (FALSE); + + SoundData.noise_hertz = NoiseFreq [byte & 0x1f]; + for (i = 0; i < 8; i++) + { + if (SoundData.channels [i].type == SOUND_NOISE) + S9xSetSoundFrequency (i, SoundData.noise_hertz); + } + } + break; + case APU_NON: + if (byte != APU.DSP [APU_NON]) + { + uint8 mask = 1; + for (int c = 0; c < 8; c++, mask <<= 1) + { + int type; + + if (byte & mask) + type = SOUND_NOISE; + else + type = SOUND_SAMPLE; + + S9xSetSoundType (c, type); + } + } + break; + case APU_MVOL_LEFT: + if (byte != APU.DSP [APU_MVOL_LEFT]) + { + S9xSetMasterVolume ((signed char) byte, + (signed char) APU.DSP [APU_MVOL_RIGHT]); + } + break; + case APU_MVOL_RIGHT: + if (byte != APU.DSP [APU_MVOL_RIGHT]) + { + S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT], + (signed char) byte); + } + break; + case APU_EVOL_LEFT: + if (byte != APU.DSP [APU_EVOL_LEFT]) + { + S9xSetEchoVolume ((signed char) byte, + (signed char) APU.DSP [APU_EVOL_RIGHT]); + } + break; + case APU_EVOL_RIGHT: + if (byte != APU.DSP [APU_EVOL_RIGHT]) + { + S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT], + (signed char) byte); + } + break; + case APU_ENDX: + byte = 0; + break; + + case APU_KOFF: + // if (byte) + { + uint8 mask = 1; + for (int c = 0; c < 8; c++, mask <<= 1) + { + if ((byte & mask) != 0) + { + 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); + } + } + } + //KeyOnPrev=0; + APU.DSP [APU_KOFF] = byte; + return; + case APU_KON: + if (spc_is_dumping) + { + if (byte & ~spc_is_dumping_temp) + { + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus(); + S9xSPCDump (".spc"); + spc_is_dumping = 0; + } + } + if (byte) + { + uint8 mask = 1; + for (int c = 0; c < 8; c++, mask <<= 1) + { + if ((byte & mask) != 0) + { + // 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; + } + } + } + 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]) + { + 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]) + { + 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: + 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: + 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: + if (byte != APU.DSP [reg]) + { + S9xSetSoundSample (reg >> 4, byte); + } + 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]) + { + { + 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]) + { + { + 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]) + { + { + 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: + break; + + case APU_PMON: + if (byte != APU.DSP [APU_PMON]) + { + S9xSetFrequencyModulationEnable (byte); + } + break; + + case APU_EON: + if (byte != APU.DSP [APU_EON]) + { + 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) + { + // ADSR mode + static unsigned long AttackRate [16] = { + 4100, 2600, 1500, 1000, 640, 380, 260, 160, + 96, 64, 40, 24, 16, 10, 6, 1 + }; + static unsigned long DecayRate [8] = { + 1200, 740, 440, 290, 180, 110, 74, 37 + }; + static unsigned long SustainRate [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 + }; + // XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/ + // DECREASE mode? And if so, what stage of the sequence does it start + // at? + if (S9xSetSoundMode (channel, MODE_ADSR)) + { + // Hack for ROMs that use a very short attack rate, key on a + // channel, then switch to decay mode. e.g. Final Fantasy II. + + int attack = AttackRate [adsr1 & 0xf]; + + if (attack == 1 && (!Settings.SoundSync +#ifdef __WIN32__ + || Settings.SoundDriver != WIN_SNES9X_DIRECT_SOUND_DRIVER +#endif + )) + attack = 0; + + S9xSetSoundADSR (channel, attack, + DecayRate [(adsr1 >> 4) & 7], + SustainRate [adsr2 & 0x1f], + (adsr2 >> 5) & 7, 8); + } + } + else + { + // Gain mode + if ((gain & 0x80) == 0) + { + if (S9xSetSoundMode (channel, MODE_GAIN)) + { + S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f); + S9xSetEnvelopeHeight (channel, gain & 0x7f); + } + } + else + { + static unsigned long IncreaseRate [32] = { + ~0, 4100, 3100, 2600, 2000, 1500, 1300, 1000, + 770, 640, 510, 380, 320, 260, 190, 160, + 130, 96, 80, 64, 48, 40, 32, 24, + 20, 16, 12, 10, 8, 6, 4, 2 + }; + static unsigned long DecreaseRateExp [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 + }; + if (gain & 0x40) + { + // Increase mode + if (S9xSetSoundMode (channel, (gain & 0x20) ? +MODE_INCREASE_BENT_LINE : + MODE_INCREASE_LINEAR)) + { + S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], + 1, 127); + } + } + else + { + uint32 rate = (gain & 0x20) ? DecreaseRateExp [gain & 0x1f] / 2 : + IncreaseRate [gain & 0x1f]; + int mode = (gain & 0x20) ? MODE_DECREASE_EXPONENTIAL + : MODE_DECREASE_LINEAR; + + if (S9xSetSoundMode (channel, mode)) + S9xSetEnvelopeRate (channel, rate, -1, 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 converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + APU.ShowROM = TRUE; + } + } + else + { + if (APU.ShowROM) + { + APU.ShowROM = FALSE; + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (&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; + } +} + +uint8 S9xGetAPUDSP () +{ + uint8 reg = IAPU.RAM [0xf2] & 0x7f; + uint8 byte = APU.DSP [reg]; + + switch (reg) + { + case APU_KON: + break; + case APU_KOFF: + 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: + if (SoundData.channels [reg >> 4].state == SOUND_SILENT) + return (0); + return ((SoundData.channels [reg >> 4].sample >> 8) | + (SoundData.channels [reg >> 4].sample & 0xff)); + + 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: + return ((uint8) S9xGetEnvelopeHeight (reg >> 4)); + + case APU_ENDX: + // To fix speech in Magical Drop 2 6/11/00 + // APU.DSP [APU_ENDX] = 0; + break; + default: + break; + } + return (byte); +} + diff --git a/source/apu.cpp b/source/apu.cpp deleted file mode 100644 index ee41096..0000000 --- a/source/apu.cpp +++ /dev/null @@ -1,772 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#ifdef __DJGPP -#include -#undef TRUE -#endif - -#include "snes9x.h" -#include "spc700.h" -#include "apu.h" -#include "soundux.h" -#include "cpuexec.h" - -/* For note-triggered SPC dump support */ -#include "snapshot.h" - -extern "C" {const char *S9xGetFilenameInc (const char *);} - -int spc_is_dumping=0; -int spc_is_dumping_temp; -uint8 spc_dump_dsp[0x100]; - -extern int NoiseFreq [32]; - -bool8 S9xInitAPU () -{ - IAPU.RAM = (uint8 *) malloc (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; - - 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 converted: Different mallocs [Neb] - // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] - memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); - // memmove converted: Different mallocs [Neb] - // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] - memcpy (APU.ExtraRAM, APUROM, sizeof (APUROM)); - IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); - APU.Cycles = 0; - IAPU.Registers.YA.W = 0; - IAPU.Registers.X = 0; - IAPU.Registers.S = 0xff; - IAPU.Registers.P = 0; - S9xAPUUnpackStatus (); - IAPU.Registers.PC = 0; - IAPU.APUExecuting = Settings.APUEnabled; -#ifdef SPC700_SHUTDOWN - IAPU.WaitAddress1 = NULL; - IAPU.WaitAddress2 = NULL; - IAPU.WaitCounter = 0; -#endif - 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); -} - -void S9xSetAPUDSP (uint8 byte) -{ - uint8 reg = IAPU.RAM [0xf2]; - static uint8 KeyOn; - static uint8 KeyOnPrev; - int i; - - 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); - - // Kill sound - S9xResetSound (FALSE); - } - else - { - S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED)); - if (byte & APU_MUTE) - { - S9xSetSoundMute (TRUE); - } - else - S9xSetSoundMute (FALSE); - - SoundData.noise_hertz = NoiseFreq [byte & 0x1f]; - for (i = 0; i < 8; i++) - { - if (SoundData.channels [i].type == SOUND_NOISE) - S9xSetSoundFrequency (i, SoundData.noise_hertz); - } - } - break; - case APU_NON: - if (byte != APU.DSP [APU_NON]) - { - uint8 mask = 1; - for (int c = 0; c < 8; c++, mask <<= 1) - { - int type; - - if (byte & mask) - type = SOUND_NOISE; - else - type = SOUND_SAMPLE; - - S9xSetSoundType (c, type); - } - } - break; - case APU_MVOL_LEFT: - if (byte != APU.DSP [APU_MVOL_LEFT]) - { - S9xSetMasterVolume ((signed char) byte, - (signed char) APU.DSP [APU_MVOL_RIGHT]); - } - break; - case APU_MVOL_RIGHT: - if (byte != APU.DSP [APU_MVOL_RIGHT]) - { - S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT], - (signed char) byte); - } - break; - case APU_EVOL_LEFT: - if (byte != APU.DSP [APU_EVOL_LEFT]) - { - S9xSetEchoVolume ((signed char) byte, - (signed char) APU.DSP [APU_EVOL_RIGHT]); - } - break; - case APU_EVOL_RIGHT: - if (byte != APU.DSP [APU_EVOL_RIGHT]) - { - S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT], - (signed char) byte); - } - break; - case APU_ENDX: - byte = 0; - break; - - case APU_KOFF: - // if (byte) - { - uint8 mask = 1; - for (int c = 0; c < 8; c++, mask <<= 1) - { - if ((byte & mask) != 0) - { - 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); - } - } - } - //KeyOnPrev=0; - APU.DSP [APU_KOFF] = byte; - return; - case APU_KON: - if (spc_is_dumping) - { - if (byte & ~spc_is_dumping_temp) - { - IAPU.Registers.PC = IAPU.PC - IAPU.RAM; - S9xAPUPackStatus(); - S9xSPCDump (".spc"); - spc_is_dumping = 0; - } - } - if (byte) - { - uint8 mask = 1; - for (int c = 0; c < 8; c++, mask <<= 1) - { - if ((byte & mask) != 0) - { - // 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; - } - } - } - 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]) - { - 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]) - { - 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: - 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: - 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: - if (byte != APU.DSP [reg]) - { - S9xSetSoundSample (reg >> 4, byte); - } - 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]) - { - { - 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]) - { - { - 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]) - { - { - 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: - break; - - case APU_PMON: - if (byte != APU.DSP [APU_PMON]) - { - S9xSetFrequencyModulationEnable (byte); - } - break; - - case APU_EON: - if (byte != APU.DSP [APU_EON]) - { - 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) - { - // ADSR mode - static unsigned long AttackRate [16] = { - 4100, 2600, 1500, 1000, 640, 380, 260, 160, - 96, 64, 40, 24, 16, 10, 6, 1 - }; - static unsigned long DecayRate [8] = { - 1200, 740, 440, 290, 180, 110, 74, 37 - }; - static unsigned long SustainRate [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 - }; - // XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/ - // DECREASE mode? And if so, what stage of the sequence does it start - // at? - if (S9xSetSoundMode (channel, MODE_ADSR)) - { - // Hack for ROMs that use a very short attack rate, key on a - // channel, then switch to decay mode. e.g. Final Fantasy II. - - int attack = AttackRate [adsr1 & 0xf]; - - if (attack == 1 && (!Settings.SoundSync -#ifdef __WIN32__ - || Settings.SoundDriver != WIN_SNES9X_DIRECT_SOUND_DRIVER -#endif - )) - attack = 0; - - S9xSetSoundADSR (channel, attack, - DecayRate [(adsr1 >> 4) & 7], - SustainRate [adsr2 & 0x1f], - (adsr2 >> 5) & 7, 8); - } - } - else - { - // Gain mode - if ((gain & 0x80) == 0) - { - if (S9xSetSoundMode (channel, MODE_GAIN)) - { - S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f); - S9xSetEnvelopeHeight (channel, gain & 0x7f); - } - } - else - { - static unsigned long IncreaseRate [32] = { - ~0, 4100, 3100, 2600, 2000, 1500, 1300, 1000, - 770, 640, 510, 380, 320, 260, 190, 160, - 130, 96, 80, 64, 48, 40, 32, 24, - 20, 16, 12, 10, 8, 6, 4, 2 - }; - static unsigned long DecreaseRateExp [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 - }; - if (gain & 0x40) - { - // Increase mode - if (S9xSetSoundMode (channel, (gain & 0x20) ? -MODE_INCREASE_BENT_LINE : - MODE_INCREASE_LINEAR)) - { - S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], - 1, 127); - } - } - else - { - uint32 rate = (gain & 0x20) ? DecreaseRateExp [gain & 0x1f] / 2 : - IncreaseRate [gain & 0x1f]; - int mode = (gain & 0x20) ? MODE_DECREASE_EXPONENTIAL - : MODE_DECREASE_LINEAR; - - if (S9xSetSoundMode (channel, mode)) - S9xSetEnvelopeRate (channel, rate, -1, 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 converted: Different mallocs [Neb] - // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] - memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); - APU.ShowROM = TRUE; - } - } - else - { - if (APU.ShowROM) - { - APU.ShowROM = FALSE; - // memmove converted: Different mallocs [Neb] - // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] - memcpy (&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; - } -} - -uint8 S9xGetAPUDSP () -{ - uint8 reg = IAPU.RAM [0xf2] & 0x7f; - uint8 byte = APU.DSP [reg]; - - switch (reg) - { - case APU_KON: - break; - case APU_KOFF: - 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: - if (SoundData.channels [reg >> 4].state == SOUND_SILENT) - return (0); - return ((SoundData.channels [reg >> 4].sample >> 8) | - (SoundData.channels [reg >> 4].sample & 0xff)); - - 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: - return ((uint8) S9xGetEnvelopeHeight (reg >> 4)); - - case APU_ENDX: - // To fix speech in Magical Drop 2 6/11/00 - // APU.DSP [APU_ENDX] = 0; - break; - default: - break; - } - return (byte); -} - diff --git a/source/c4.c b/source/c4.c new file mode 100644 index 0000000..8774f46 --- /dev/null +++ b/source/c4.c @@ -0,0 +1,237 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#include +#include "c4.h" +#include "memmap.h" +extern "C" { + +short C4WFXVal; +short C4WFYVal; +short C4WFZVal; +short C4WFX2Val; +short C4WFY2Val; +short C4WFDist; +short C4WFScale; + +static double tanval; +static double c4x, c4y, c4z; +static double c4x2, c4y2, c4z2; + +void C4TransfWireFrame () +{ + 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 Y + tanval = -(double)C4WFY2Val*3.14159265*2/128; + c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); + c4z = c4x * - sin (tanval) + c4z2 * cos (tanval); + + // Rotate Z + tanval = -(double) C4WFDist * 3.14159265*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); +} + +void C4TransfWireFrame2 () +{ + 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 Y + tanval = -(double) C4WFY2Val * 3.14159265 * 2 / 128; + c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); + c4z = c4x * -sin (tanval) + c4z2 * cos (tanval); + + // Rotate Z + tanval = -(double)C4WFDist * 3.14159265 * 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); +} + +void C4CalcWireFrame () +{ + 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; + } +} + +short C41FXVal; +short C41FYVal; +short C41FAngleRes; +short C41FDist; +short C41FDistVal; + +void C4Op1F () +{ + if (C41FXVal == 0) + { + if (C41FYVal > 0) + C41FAngleRes = 0x80; + else + C41FAngleRes = 0x180; + } + else + { + tanval = (double) C41FYVal / C41FXVal; + C41FAngleRes = (short) (atan (tanval) / (3.141592675 * 2) * 512); + C41FAngleRes = C41FAngleRes; + if (C41FXVal< 0) + C41FAngleRes += 0x100; + C41FAngleRes &= 0x1FF; + } +} + +void C4Op15() +{ + tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + C41FDist = (short) tanval; +} + +void C4Op0D() +{ + tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (short) (C41FYVal * tanval * 0.99); + C41FXVal = (short) (C41FXVal * tanval * 0.98); +} + +#ifdef ZSNES_C4 +void C4LoaDMem(char *C4RAM) +{ + memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), + S9xGetMemPointer(READ_3WORD(C4RAM+0x1f40)), + READ_WORD(C4RAM+0x1f43)); +} +#endif +}//end extern C + diff --git a/source/c4.cpp b/source/c4.cpp deleted file mode 100644 index 8774f46..0000000 --- a/source/c4.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#include -#include "c4.h" -#include "memmap.h" -extern "C" { - -short C4WFXVal; -short C4WFYVal; -short C4WFZVal; -short C4WFX2Val; -short C4WFY2Val; -short C4WFDist; -short C4WFScale; - -static double tanval; -static double c4x, c4y, c4z; -static double c4x2, c4y2, c4z2; - -void C4TransfWireFrame () -{ - 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 Y - tanval = -(double)C4WFY2Val*3.14159265*2/128; - c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); - c4z = c4x * - sin (tanval) + c4z2 * cos (tanval); - - // Rotate Z - tanval = -(double) C4WFDist * 3.14159265*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); -} - -void C4TransfWireFrame2 () -{ - 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 Y - tanval = -(double) C4WFY2Val * 3.14159265 * 2 / 128; - c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); - c4z = c4x * -sin (tanval) + c4z2 * cos (tanval); - - // Rotate Z - tanval = -(double)C4WFDist * 3.14159265 * 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); -} - -void C4CalcWireFrame () -{ - 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; - } -} - -short C41FXVal; -short C41FYVal; -short C41FAngleRes; -short C41FDist; -short C41FDistVal; - -void C4Op1F () -{ - if (C41FXVal == 0) - { - if (C41FYVal > 0) - C41FAngleRes = 0x80; - else - C41FAngleRes = 0x180; - } - else - { - tanval = (double) C41FYVal / C41FXVal; - C41FAngleRes = (short) (atan (tanval) / (3.141592675 * 2) * 512); - C41FAngleRes = C41FAngleRes; - if (C41FXVal< 0) - C41FAngleRes += 0x100; - C41FAngleRes &= 0x1FF; - } -} - -void C4Op15() -{ - tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - C41FDist = (short) tanval; -} - -void C4Op0D() -{ - tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - tanval = C41FDistVal / tanval; - C41FYVal = (short) (C41FYVal * tanval * 0.99); - C41FXVal = (short) (C41FXVal * tanval * 0.98); -} - -#ifdef ZSNES_C4 -void C4LoaDMem(char *C4RAM) -{ - memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), - S9xGetMemPointer(READ_3WORD(C4RAM+0x1f40)), - READ_WORD(C4RAM+0x1f43)); -} -#endif -}//end extern C - diff --git a/source/c4emu.c b/source/c4emu.c new file mode 100644 index 0000000..f188853 --- /dev/null +++ b/source/c4emu.c @@ -0,0 +1,889 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#ifdef HAVE_CONFIG_H + #include +#endif +#include +#include "snes9x.h" +#include "sar.h" +#include "memmap.h" +#include "ppu.h" +#include "c4.h" + +void S9xInitC4 () +{ + // 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) +{ + return (Memory.C4RAM [Address-0x6000]); +} + +static uint8 C4TestPattern [12 * 4] = +{ + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, + 0x80, 0xff, 0xff, 0x7f, + 0x00, 0x80, 0x00, 0xff, + 0x7f, 0x00, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0xff, + 0x00, 0x00, 0x01, 0xff, + 0xff, 0xfe, 0x00, 0x01, + 0x00, 0xff, 0xfe, 0x00 +}; + + +static void C4ConvOAM(void){ + uint8 *OAMptr=Memory.C4RAM+(Memory.C4RAM[0x626]<<2); + for(uint8 *i=Memory.C4RAM+0x1fd; i>OAMptr; i-=4){ + // Clear OAM-to-be + *i=0xe0; + } + + uint16 globalX, globalY; + uint8 *OAMptr2; + int16 SprX, SprY; + uint8 SprName, SprAttr; + uint8 SprCount; + + globalX=READ_WORD(Memory.C4RAM+0x0621); + globalY=READ_WORD(Memory.C4RAM+0x0623); + OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2); + + if(Memory.C4RAM[0x0620]!=0){ + SprCount=128-Memory.C4RAM[0x626]; + uint8 offset=(Memory.C4RAM[0x626]&3)*2; + for(int prio=0x30; prio>=0; prio-=0x10){ + uint8 *srcptr=Memory.C4RAM+0x220; + for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ + if((srcptr[4]&0x30)!=prio) continue; + SprX=READ_WORD(srcptr)-globalX; + SprY=READ_WORD(srcptr+2)-globalY; + SprName=srcptr[5]; + SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? + + uint8 *sprptr=S9xGetMemPointer(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){ + 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=S9xGetMemPointer(READ_3WORD(Memory.C4RAM+0x1f80)); + uint8 *point1, *point2; + int16 X1, Y1, Z1; + int16 X2, Y2, Z2; + uint8 Color; + + for(int i=Memory.C4RAM[0x0295]; i>0; i--, line+=5){ + if(line[0]==0xff && line[1]==0xff){ + uint8 *tmp=line-5; + while(line[2]==0xff && line[3]==0xff) tmp-=5; + point1=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (tmp[2]<<8) | tmp[3]); + } else { + point1=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[0]<<8) | line[1]); + } + point2=S9xGetMemPointer((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]; + + // 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; + + 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); + + 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 + C4ConvOAM(); + break; + + case 0x03: // Scale/Rotate + C4DoScaleRotate(0); + break; + + case 0x05: // Transform Lines + C4TransformLines(); + break; + + case 0x07: // Scale/Rotate + C4DoScaleRotate(64); + break; + + case 0x08: // Draw wireframe + C4DrawWireFrame(); + break; + + case 0x0b: // Disintegrate + C4SprDisintegrate(); + break; + + case 0x0c: // Wave + C4BitPlaneWave(); + break; + + default: + break; + } +} + +void S9xSetC4 (uint8 byte, uint16 Address) +{ + int i; + Memory.C4RAM [Address-0x6000] = byte; + if (Address == 0x7f4f) + { + if(Memory.C4RAM[0x1f4d]==0x0e && byte<0x40 && (byte&3)==0) + { + Memory.C4RAM[0x1f80]=byte>>2; + } + else + { + switch (byte) + { + case 0x00: // Sprite + S9xC4ProcessSprites(); + break; + + case 0x01: // Draw wireframe + memset(Memory.C4RAM+0x300, 0, 16*12*3*4); + C4DrawWireFrame(); + break; + + case 0x05: // Propulsion (?) + { + 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 0x0d: // Set vector length + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C41FDistVal=READ_WORD(Memory.C4RAM+0x1f86); + C4Op0D(); + WRITE_WORD(Memory.C4RAM+0x1f89, C41FXVal); + WRITE_WORD(Memory.C4RAM+0x1f8c, C41FYVal); + break; + + case 0x10: // Polar to rectangluar + { + 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 0x13: // Polar to rectangluar + { + 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 0x15: // Pythagorean + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C41FDist=(int16)sqrt((double)C41FXVal*C41FXVal + (double)C41FYVal*C41FYVal); + WRITE_WORD(Memory.C4RAM+0x1f80, C41FDist); + break; + + case 0x1f: // atan + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C4Op1F(); + WRITE_WORD(Memory.C4RAM+0x1f86, C41FAngleRes); + break; + + case 0x22: // Trapezoid + { + int16 angle1=READ_WORD(Memory.C4RAM+0x1f8c)&0x1ff; + int16 angle2=READ_WORD(Memory.C4RAM+0x1f8f)&0x1ff; + 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); + + 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 0x25: // Multiply + { + 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 + 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 + { + uint16 sum=0; + for(int i=0; i<0x800; sum+=Memory.C4RAM[i++]); + WRITE_WORD(Memory.C4RAM+0x1f80, sum); + } + break; + + case 0x54: // Square + { + 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 + for (i = 0; i < 12 * 4; i++) + Memory.C4RAM [i] = C4TestPattern [i]; + break; + + case 0x89: // Immediate ROM + Memory.C4RAM [0x1f80] = 0x36; + Memory.C4RAM [0x1f81] = 0x43; + Memory.C4RAM [0x1f82] = 0x05; + break; + + default: + break; + } + } + } else if (Address == 0x7f47) { + // memmove required: Can overlap arbitrarily [Neb] + memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), + S9xGetMemPointer(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 +}; + diff --git a/source/c4emu.cpp b/source/c4emu.cpp deleted file mode 100644 index f188853..0000000 --- a/source/c4emu.cpp +++ /dev/null @@ -1,889 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#ifdef HAVE_CONFIG_H - #include -#endif -#include -#include "snes9x.h" -#include "sar.h" -#include "memmap.h" -#include "ppu.h" -#include "c4.h" - -void S9xInitC4 () -{ - // 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) -{ - return (Memory.C4RAM [Address-0x6000]); -} - -static uint8 C4TestPattern [12 * 4] = -{ - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x00, - 0x80, 0xff, 0xff, 0x7f, - 0x00, 0x80, 0x00, 0xff, - 0x7f, 0x00, 0xff, 0x7f, - 0xff, 0x7f, 0xff, 0xff, - 0x00, 0x00, 0x01, 0xff, - 0xff, 0xfe, 0x00, 0x01, - 0x00, 0xff, 0xfe, 0x00 -}; - - -static void C4ConvOAM(void){ - uint8 *OAMptr=Memory.C4RAM+(Memory.C4RAM[0x626]<<2); - for(uint8 *i=Memory.C4RAM+0x1fd; i>OAMptr; i-=4){ - // Clear OAM-to-be - *i=0xe0; - } - - uint16 globalX, globalY; - uint8 *OAMptr2; - int16 SprX, SprY; - uint8 SprName, SprAttr; - uint8 SprCount; - - globalX=READ_WORD(Memory.C4RAM+0x0621); - globalY=READ_WORD(Memory.C4RAM+0x0623); - OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2); - - if(Memory.C4RAM[0x0620]!=0){ - SprCount=128-Memory.C4RAM[0x626]; - uint8 offset=(Memory.C4RAM[0x626]&3)*2; - for(int prio=0x30; prio>=0; prio-=0x10){ - uint8 *srcptr=Memory.C4RAM+0x220; - for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ - if((srcptr[4]&0x30)!=prio) continue; - SprX=READ_WORD(srcptr)-globalX; - SprY=READ_WORD(srcptr+2)-globalY; - SprName=srcptr[5]; - SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? - - uint8 *sprptr=S9xGetMemPointer(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){ - 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=S9xGetMemPointer(READ_3WORD(Memory.C4RAM+0x1f80)); - uint8 *point1, *point2; - int16 X1, Y1, Z1; - int16 X2, Y2, Z2; - uint8 Color; - - for(int i=Memory.C4RAM[0x0295]; i>0; i--, line+=5){ - if(line[0]==0xff && line[1]==0xff){ - uint8 *tmp=line-5; - while(line[2]==0xff && line[3]==0xff) tmp-=5; - point1=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (tmp[2]<<8) | tmp[3]); - } else { - point1=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[0]<<8) | line[1]); - } - point2=S9xGetMemPointer((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]; - - // 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; - - 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); - - 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 - C4ConvOAM(); - break; - - case 0x03: // Scale/Rotate - C4DoScaleRotate(0); - break; - - case 0x05: // Transform Lines - C4TransformLines(); - break; - - case 0x07: // Scale/Rotate - C4DoScaleRotate(64); - break; - - case 0x08: // Draw wireframe - C4DrawWireFrame(); - break; - - case 0x0b: // Disintegrate - C4SprDisintegrate(); - break; - - case 0x0c: // Wave - C4BitPlaneWave(); - break; - - default: - break; - } -} - -void S9xSetC4 (uint8 byte, uint16 Address) -{ - int i; - Memory.C4RAM [Address-0x6000] = byte; - if (Address == 0x7f4f) - { - if(Memory.C4RAM[0x1f4d]==0x0e && byte<0x40 && (byte&3)==0) - { - Memory.C4RAM[0x1f80]=byte>>2; - } - else - { - switch (byte) - { - case 0x00: // Sprite - S9xC4ProcessSprites(); - break; - - case 0x01: // Draw wireframe - memset(Memory.C4RAM+0x300, 0, 16*12*3*4); - C4DrawWireFrame(); - break; - - case 0x05: // Propulsion (?) - { - 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 0x0d: // Set vector length - C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); - C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); - C41FDistVal=READ_WORD(Memory.C4RAM+0x1f86); - C4Op0D(); - WRITE_WORD(Memory.C4RAM+0x1f89, C41FXVal); - WRITE_WORD(Memory.C4RAM+0x1f8c, C41FYVal); - break; - - case 0x10: // Polar to rectangluar - { - 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 0x13: // Polar to rectangluar - { - 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 0x15: // Pythagorean - C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); - C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); - C41FDist=(int16)sqrt((double)C41FXVal*C41FXVal + (double)C41FYVal*C41FYVal); - WRITE_WORD(Memory.C4RAM+0x1f80, C41FDist); - break; - - case 0x1f: // atan - C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); - C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); - C4Op1F(); - WRITE_WORD(Memory.C4RAM+0x1f86, C41FAngleRes); - break; - - case 0x22: // Trapezoid - { - int16 angle1=READ_WORD(Memory.C4RAM+0x1f8c)&0x1ff; - int16 angle2=READ_WORD(Memory.C4RAM+0x1f8f)&0x1ff; - 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); - - 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 0x25: // Multiply - { - 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 - 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 - { - uint16 sum=0; - for(int i=0; i<0x800; sum+=Memory.C4RAM[i++]); - WRITE_WORD(Memory.C4RAM+0x1f80, sum); - } - break; - - case 0x54: // Square - { - 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 - for (i = 0; i < 12 * 4; i++) - Memory.C4RAM [i] = C4TestPattern [i]; - break; - - case 0x89: // Immediate ROM - Memory.C4RAM [0x1f80] = 0x36; - Memory.C4RAM [0x1f81] = 0x43; - Memory.C4RAM [0x1f82] = 0x05; - break; - - default: - break; - } - } - } else if (Address == 0x7f47) { - // memmove required: Can overlap arbitrarily [Neb] - memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), - S9xGetMemPointer(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 -}; - diff --git a/source/cheats.c b/source/cheats.c new file mode 100644 index 0000000..9c4a8f2 --- /dev/null +++ b/source/cheats.c @@ -0,0 +1,442 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#include +#include +#include "snes9x.h" +#include "cheats.h" +#include "memmap.h" + +static bool8 S9xAllHex (const char *code, int len) +{ + for (int i = 0; i < len; i++) + if ((code [i] < '0' || code [i] > '9') && + (code [i] < 'a' || code [i] > 'f') && + (code [i] < 'A' || code [i] > 'F')) + return (FALSE); + + return (TRUE); +} + +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."); + + *address = data >> 8; + *byte = (uint8) data; + return (NULL); +} + +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."); + + strncpy (tmp, code, 5); + tmp [5] = 0; + if (sscanf (tmp, "%x", address) != 1) + return ("Invalid Gold Finger code."); + + int i; + for (i = 0; i < 3; i++) + { + strncpy (tmp, code + 5 + i * 2, 2); + tmp [2] = 0; + int byte; + 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 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++) + { + 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 & 0x003c00) << 10) + + ((data & 0x00003c) << 14) + + ((data & 0xf00000) >> 8) + + ((data & 0x000003) << 10) + + ((data & 0x00c000) >> 6) + + ((data & 0x0f0000) >> 12) + + ((data & 0x0003c0) >> 6); + + return (NULL); +} + +void S9xStartCheatSearch (SCheatData *d) +{ + // memmove may be required: Source is usually a different malloc, but could be pointed to d->CWRAM [Neb] + memmove (d->CWRAM, d->RAM, 0x20000); + // memmove may be required: Source is usually a different malloc, but could be pointed to d->CSRAM [Neb] + memmove (d->CSRAM, d->SRAM, 0x10000); + // memmove may be required: Source is usually a different malloc, but could be pointed to d->CIRAM [Neb] + memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); + memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3); + memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3); + memset ((char *) d->IRAM_BITS, 0xff, 0x2000 >> 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))) + +#define _C(c,a,b) \ +((c) == S9X_LESS_THAN ? (a) < (b) : \ + (c) == S9X_GREATER_THAN ? (a) > (b) : \ + (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ + (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ + (c) == S9X_EQUAL ? (a) == (b) : \ + (a) != (b)) + +#define _D(s,m,o) \ +((s) == S9X_8_BITS ? (uint8) (*((m) + (o))) : \ + (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ +((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +#define _DS(s,m,o) \ +((s) == S9X_8_BITS ? ((int8) *((m) + (o))) : \ + (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ + ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, bool8 is_signed, bool8 update) +{ + int l; + + 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); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i))) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i))) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i))) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i))) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _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); + } + } +} + +void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, + bool8 is_signed, bool8 update) +{ + int l; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + 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), (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) && + _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) && + _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) && + _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) && + _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); + } + } +} + +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]); + } + + 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/cheats.cpp b/source/cheats.cpp deleted file mode 100644 index 9c4a8f2..0000000 --- a/source/cheats.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#include -#include -#include "snes9x.h" -#include "cheats.h" -#include "memmap.h" - -static bool8 S9xAllHex (const char *code, int len) -{ - for (int i = 0; i < len; i++) - if ((code [i] < '0' || code [i] > '9') && - (code [i] < 'a' || code [i] > 'f') && - (code [i] < 'A' || code [i] > 'F')) - return (FALSE); - - return (TRUE); -} - -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."); - - *address = data >> 8; - *byte = (uint8) data; - return (NULL); -} - -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."); - - strncpy (tmp, code, 5); - tmp [5] = 0; - if (sscanf (tmp, "%x", address) != 1) - return ("Invalid Gold Finger code."); - - int i; - for (i = 0; i < 3; i++) - { - strncpy (tmp, code + 5 + i * 2, 2); - tmp [2] = 0; - int byte; - 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 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++) - { - 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 & 0x003c00) << 10) + - ((data & 0x00003c) << 14) + - ((data & 0xf00000) >> 8) + - ((data & 0x000003) << 10) + - ((data & 0x00c000) >> 6) + - ((data & 0x0f0000) >> 12) + - ((data & 0x0003c0) >> 6); - - return (NULL); -} - -void S9xStartCheatSearch (SCheatData *d) -{ - // memmove may be required: Source is usually a different malloc, but could be pointed to d->CWRAM [Neb] - memmove (d->CWRAM, d->RAM, 0x20000); - // memmove may be required: Source is usually a different malloc, but could be pointed to d->CSRAM [Neb] - memmove (d->CSRAM, d->SRAM, 0x10000); - // memmove may be required: Source is usually a different malloc, but could be pointed to d->CIRAM [Neb] - memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); - memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3); - memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3); - memset ((char *) d->IRAM_BITS, 0xff, 0x2000 >> 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))) - -#define _C(c,a,b) \ -((c) == S9X_LESS_THAN ? (a) < (b) : \ - (c) == S9X_GREATER_THAN ? (a) > (b) : \ - (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ - (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ - (c) == S9X_EQUAL ? (a) == (b) : \ - (a) != (b)) - -#define _D(s,m,o) \ -((s) == S9X_8_BITS ? (uint8) (*((m) + (o))) : \ - (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ -((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -#define _DS(s,m,o) \ -((s) == S9X_8_BITS ? ((int8) *((m) + (o))) : \ - (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ - ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, bool8 is_signed, bool8 update) -{ - int l; - - 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); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT (d->SRAM_BITS, i) && - _C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i))) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR (d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT (d->IRAM_BITS, i) && - _C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i))) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR (d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT (d->WRAM_BITS, i) && - _C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i))) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR (d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT (d->SRAM_BITS, i) && - _C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i))) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR (d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT (d->IRAM_BITS, i) && - _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); - } - } -} - -void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, uint32 value, - bool8 is_signed, bool8 update) -{ - int l; - - switch (size) - { - case S9X_8_BITS: l = 0; break; - case S9X_16_BITS: l = 1; break; - case S9X_24_BITS: l = 2; break; - default: - case S9X_32_BITS: l = 3; break; - } - - 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), (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) && - _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) && - _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) && - _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) && - _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); - } - } -} - -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]); - } - - 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/cheats2.c b/source/cheats2.c new file mode 100644 index 0000000..59855b9 --- /dev/null +++ b/source/cheats2.c @@ -0,0 +1,285 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#include +#include +#include "snes9x.h" +#include "cheats.h" +#include "memmap.h" + +extern SCheatData Cheat; + +void S9xInitCheatData () +{ + Cheat.RAM = Memory.RAM; + Cheat.SRAM = ::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].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 = S9xGetByte (address); + Cheat.c [Cheat.num_cheats].saved = TRUE; + } + Cheat.num_cheats++; + if (enable) + S9xApplyCheat(Cheat.num_cheats - 1); + } +} + +void S9xDeleteCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats) + { + if (Cheat.c [which1].enabled) + S9xRemoveCheat (which1); + + // memmove required: Overlapping addresses [Neb] + memmove (&Cheat.c [which1], &Cheat.c [which1 + 1], + sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1)); + Cheat.num_cheats--; //MK: This used to set it to 0?? + } +} + +void S9xDeleteCheats () +{ + 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; + } +} + +void S9xRemoveCheat (uint32 which1) +{ + if (Cheat.c [which1].saved) + { + uint32 address = Cheat.c [which1].address; + + int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; + 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); + // Unsave the address for the next call to S9xRemoveCheat. + Cheat.c [which1].saved = FALSE; + } +} + +void S9xApplyCheat (uint32 which1) +{ + uint32 address = Cheat.c [which1].address; + + if (!Cheat.c [which1].saved) + Cheat.c [which1].saved_byte = S9xGetByte (address); + + int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; + 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; +} + +void S9xApplyCheats () +{ + if (Settings.ApplyCheats) + { + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c [i].enabled) + S9xApplyCheat (i); + } +} + +void S9xRemoveCheats () +{ + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c [i].enabled) + S9xRemoveCheat (i); +} + +bool8 S9xLoadCheatFile (const char *filename) +{ + Cheat.num_cheats = 0; + + FILE *fs = fopen (filename, "rb"); + uint8 data [8 + MAX_SFCCHEAT_NAME]; + + if (!fs) + return (FALSE); + + while (fread ((void *) data, 1, 8 + MAX_SFCCHEAT_NAME, fs) == 8 + MAX_SFCCHEAT_NAME) + { + if (data[6] != 254 || data[7] != 252) { + fclose (fs); + return (FALSE); + } + 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; + memcpy (Cheat.c [Cheat.num_cheats].name, &data [8], MAX_SFCCHEAT_NAME - 1); + Cheat.c [Cheat.num_cheats++].name [MAX_SFCCHEAT_NAME - 1] = 0; + } + 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 [8 + MAX_SFCCHEAT_NAME]; + + if (!fs) + return (FALSE); + + uint32 i; + for (i = 0; i < Cheat.num_cheats; i++) + { + memset (data, 0, 8 + MAX_SFCCHEAT_NAME); + 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; + data [3] = (uint8) (Cheat.c [i].address >> 8); + data [4] = (uint8) (Cheat.c [i].address >> 16); + data [5] = Cheat.c [i].saved_byte; + + memcpy (&data [8], Cheat.c [i].name, MAX_SFCCHEAT_NAME - 1); + if (fwrite (data, 8 + MAX_SFCCHEAT_NAME, 1, fs) != 1) + { + fclose (fs); + return (FALSE); + } + } + + fclose (fs); + return (TRUE); +} diff --git a/source/cheats2.cpp b/source/cheats2.cpp deleted file mode 100644 index 59855b9..0000000 --- a/source/cheats2.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#include -#include -#include "snes9x.h" -#include "cheats.h" -#include "memmap.h" - -extern SCheatData Cheat; - -void S9xInitCheatData () -{ - Cheat.RAM = Memory.RAM; - Cheat.SRAM = ::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].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 = S9xGetByte (address); - Cheat.c [Cheat.num_cheats].saved = TRUE; - } - Cheat.num_cheats++; - if (enable) - S9xApplyCheat(Cheat.num_cheats - 1); - } -} - -void S9xDeleteCheat (uint32 which1) -{ - if (which1 < Cheat.num_cheats) - { - if (Cheat.c [which1].enabled) - S9xRemoveCheat (which1); - - // memmove required: Overlapping addresses [Neb] - memmove (&Cheat.c [which1], &Cheat.c [which1 + 1], - sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1)); - Cheat.num_cheats--; //MK: This used to set it to 0?? - } -} - -void S9xDeleteCheats () -{ - 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; - } -} - -void S9xRemoveCheat (uint32 which1) -{ - if (Cheat.c [which1].saved) - { - uint32 address = Cheat.c [which1].address; - - int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; - 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); - // Unsave the address for the next call to S9xRemoveCheat. - Cheat.c [which1].saved = FALSE; - } -} - -void S9xApplyCheat (uint32 which1) -{ - uint32 address = Cheat.c [which1].address; - - if (!Cheat.c [which1].saved) - Cheat.c [which1].saved_byte = S9xGetByte (address); - - int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; - 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; -} - -void S9xApplyCheats () -{ - if (Settings.ApplyCheats) - { - for (uint32 i = 0; i < Cheat.num_cheats; i++) - if (Cheat.c [i].enabled) - S9xApplyCheat (i); - } -} - -void S9xRemoveCheats () -{ - for (uint32 i = 0; i < Cheat.num_cheats; i++) - if (Cheat.c [i].enabled) - S9xRemoveCheat (i); -} - -bool8 S9xLoadCheatFile (const char *filename) -{ - Cheat.num_cheats = 0; - - FILE *fs = fopen (filename, "rb"); - uint8 data [8 + MAX_SFCCHEAT_NAME]; - - if (!fs) - return (FALSE); - - while (fread ((void *) data, 1, 8 + MAX_SFCCHEAT_NAME, fs) == 8 + MAX_SFCCHEAT_NAME) - { - if (data[6] != 254 || data[7] != 252) { - fclose (fs); - return (FALSE); - } - 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; - memcpy (Cheat.c [Cheat.num_cheats].name, &data [8], MAX_SFCCHEAT_NAME - 1); - Cheat.c [Cheat.num_cheats++].name [MAX_SFCCHEAT_NAME - 1] = 0; - } - 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 [8 + MAX_SFCCHEAT_NAME]; - - if (!fs) - return (FALSE); - - uint32 i; - for (i = 0; i < Cheat.num_cheats; i++) - { - memset (data, 0, 8 + MAX_SFCCHEAT_NAME); - 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; - data [3] = (uint8) (Cheat.c [i].address >> 8); - data [4] = (uint8) (Cheat.c [i].address >> 16); - data [5] = Cheat.c [i].saved_byte; - - memcpy (&data [8], Cheat.c [i].name, MAX_SFCCHEAT_NAME - 1); - if (fwrite (data, 8 + MAX_SFCCHEAT_NAME, 1, fs) != 1) - { - fclose (fs); - return (FALSE); - } - } - - fclose (fs); - return (TRUE); -} diff --git a/source/clip.c b/source/clip.c new file mode 100644 index 0000000..7147abf --- /dev/null +++ b/source/clip.c @@ -0,0 +1,767 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" + +struct Band +{ + uint32 Left; + uint32 Right; +}; + +#undef MIN +#undef MAX +#define MIN(A,B) ((A) < (B) ? (A) : (B)) +#define MAX(A,B) ((A) > (B) ? (A) : (B)) +#define BAND_EMPTY(B) (B.Left >= B.Right) +#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || \ + (B.Left >= A.Left && B.Left < A.Right)) +#define OR_BANDS(R,A,B) {\ + R.Left = MIN(A.Left, B.Left); \ + R.Right = MAX(A.Right, B.Right);} + +#define AND_BANDS(R,A,B) {\ + R.Left = MAX(A.Left, B.Left); \ + R.Right = MIN(A.Right, B.Right);} + +static int IntCompare (const void *d1, const void *d2) +{ + if (*(uint32 *) d1 > *(uint32 *) d2) + return (1); + else + if (*(uint32 *) d1 < *(uint32 *) d2) + return (-1); + return (0); +} + +static int BandCompare (const void *d1, const void *d2) +{ + if (((struct Band *) d1)->Left > ((struct Band *) d2)->Left) + return (1); + else + if (((struct Band *) d1)->Left < ((struct Band *) d2)->Left) + return (-1); + return (0); +} + +void ComputeClipWindows () +{ + struct ClipData *pClip = &IPPU.Clip [0]; + + // Loop around the main screen then the sub-screen. + for (int c = 0; c < 2; c++, pClip++) + { + // Loop around the colour window then a clip window for each of the + // background layers. + for (int w = 5; w >= 0; w--) + { + pClip->Count[w] = 0; + + if (w == 5) // The colour window... + { + if (c == 0) // ... on the main screen + { + if ((Memory.FillRAM [0x2130] & 0xc0) == 0xc0) + { + // The whole of the main screen is switched off, + // completely clip everything. + for (int i = 0; i < 6; i++) + { + IPPU.Clip [c].Count [i] = 1; + IPPU.Clip [c].Left [0][i] = 1; + IPPU.Clip [c].Right [0][i] = 0; + } + continue; + } + else if ((Memory.FillRAM [0x2130] & 0xc0) == 0x00) + continue; + } + else + { + // .. colour window on the sub-screen. + if ((Memory.FillRAM [0x2130] & 0x30) == 0x30) + { + // The sub-screen is switched off, completely + // clip everything. + for (int i = 0; i < 6; i++) + { + IPPU.Clip [1].Count [i] = 1; + IPPU.Clip [1].Left [0][i] = 1; + IPPU.Clip [1].Right [0][i] = 0; + } + return; + } + else if ((Memory.FillRAM [0x2130] & 0x30) == 0x00) + continue; + } + } + +// if (!Settings.DisableGraphicWindows) + { + if (w == 5 || pClip->Count [5] || + (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) + { + struct Band Win1[3]; + struct Band Win2[3]; + uint32 Window1Enabled = 0; + uint32 Window2Enabled = 0; + bool8 invert = (w == 5 && + ((c == 1 && (Memory.FillRAM [0x2130] & 0x30) == 0x10) || + (c == 0 && (Memory.FillRAM [0x2130] & 0xc0) == 0x40))); + + if (w == 5 || + (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) + { + if (PPU.ClipWindow1Enable [w]) + { + if (!PPU.ClipWindow1Inside [w]) + { + Win1[Window1Enabled].Left = PPU.Window1Left; + Win1[Window1Enabled++].Right = PPU.Window1Right + 1; + } + else + { + if (PPU.Window1Left <= PPU.Window1Right) + { + if (PPU.Window1Left > 0) + { + Win1[Window1Enabled].Left = 0; + Win1[Window1Enabled++].Right = PPU.Window1Left; + } + if (PPU.Window1Right < 255) + { + Win1[Window1Enabled].Left = PPU.Window1Right + 1; + Win1[Window1Enabled++].Right = 256; + } + if (Window1Enabled == 0) + { + Win1[Window1Enabled].Left = 1; + Win1[Window1Enabled++].Right = 0; + } + } + else + { + // 'outside' a window with no range - + // appears to be the whole screen. + Win1[Window1Enabled].Left = 0; + Win1[Window1Enabled++].Right = 256; + } + } + } + if (PPU.ClipWindow2Enable [w]) + { + if (!PPU.ClipWindow2Inside [w]) + { + Win2[Window2Enabled].Left = PPU.Window2Left; + Win2[Window2Enabled++].Right = PPU.Window2Right + 1; + } + else + { + if (PPU.Window2Left <= PPU.Window2Right) + { + if (PPU.Window2Left > 0) + { + Win2[Window2Enabled].Left = 0; + Win2[Window2Enabled++].Right = PPU.Window2Left; + } + if (PPU.Window2Right < 255) + { + Win2[Window2Enabled].Left = PPU.Window2Right + 1; + Win2[Window2Enabled++].Right = 256; + } + if (Window2Enabled == 0) + { + Win2[Window2Enabled].Left = 1; + Win2[Window2Enabled++].Right = 0; + } + } + else + { + Win2[Window2Enabled].Left = 0; + Win2[Window2Enabled++].Right = 256; + } + } + } + } + if (Window1Enabled && Window2Enabled) + { + // Overlap logic + // + // Each window will be in one of three states: + // 1. (Left > Right. One band) + // 2. | ---------------- | (Left >= 0, Right <= 255, Left <= Right. One band) + // 3. |------------ ----------| (Left1 == 0, Right1 < Left2; Left2 > Right1, Right2 == 255. Two bands) + + struct Band Bands [6]; + int B = 0; + switch (PPU.ClipWindowOverlapLogic [w] ^ 1) + { + case CLIP_OR: + if (Window1Enabled == 1) + { + if (BAND_EMPTY(Win1[0])) + { + B = Window2Enabled; + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win2, + sizeof(Win2[0]) * Window2Enabled); + } + else + { + if (Window2Enabled == 1) + { + if (BAND_EMPTY (Win2[0])) + Bands[B++] = Win1[0]; + else + { + if (BANDS_INTERSECT (Win1[0], Win2[0])) + { + OR_BANDS(Bands[0],Win1[0], Win2[0]) + B = 1; + } + else + { + Bands[B++] = Win1[0]; + Bands[B++] = Win2[0]; + } + } + } + else + { + if (BANDS_INTERSECT(Win1[0], Win2[0])) + { + OR_BANDS(Bands[0], Win1[0], Win2[0]) + if (BANDS_INTERSECT(Win1[0], Win2[1])) + OR_BANDS(Bands[1], Win1[0], Win2[1]) + else + Bands[1] = Win2[1]; + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + else + if (BANDS_INTERSECT(Win1[0], Win2[1])) + { + Bands[B++] = Win2[0]; + OR_BANDS(Bands[B], Win1[0], Win2[1]); + B++; + } + else + { + Bands[0] = Win2[0]; + Bands[1] = Win1[0]; + Bands[2] = Win2[1]; + B = 3; + } + } + } + } + else + if (Window2Enabled == 1) + { + if (BAND_EMPTY(Win2[0])) + { + // Window 2 defines an empty range - just + // use window 1 as the clipping (which + // could also be empty). + B = Window1Enabled; + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win1, + sizeof(Win1[0]) * Window1Enabled); + } + else + { + // Window 1 has two bands and Window 2 has one. + // Neither is an empty region. + if (BANDS_INTERSECT(Win2[0], Win1[0])) + { + OR_BANDS(Bands[0], Win2[0], Win1[0]) + if (BANDS_INTERSECT(Win2[0], Win1[1])) + OR_BANDS(Bands[1], Win2[0], Win1[1]) + else + Bands[1] = Win1[1]; + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + else + if (BANDS_INTERSECT(Win2[0], Win1[1])) + { + Bands[B++] = Win1[0]; + OR_BANDS(Bands[B], Win2[0], Win1[1]); + B++; + } + else + { + Bands[0] = Win1[0]; + Bands[1] = Win2[0]; + Bands[2] = Win1[1]; + B = 3; + } + } + } + else + { + // Both windows have two bands + OR_BANDS(Bands[0], Win1[0], Win2[0]); + OR_BANDS(Bands[1], Win1[1], Win2[1]); + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + break; + + case CLIP_AND: + if (Window1Enabled == 1) + { + // Window 1 has one band + if (BAND_EMPTY(Win1[0])) + Bands [B++] = Win1[0]; + else + if (Window2Enabled == 1) + { + if (BAND_EMPTY (Win2[0])) + Bands [B++] = Win2[0]; + else + { + AND_BANDS(Bands[0], Win1[0], Win2[0]); + B = 1; + } + } + else + { + AND_BANDS(Bands[0], Win1[0], Win2[0]); + AND_BANDS(Bands[1], Win1[0], Win2[1]); + B = 2; + } + } + else + if (Window2Enabled == 1) + { + if (BAND_EMPTY(Win2[0])) + Bands[B++] = Win2[0]; + else + { + // Window 1 has two bands. + AND_BANDS(Bands[0], Win1[0], Win2[0]); + AND_BANDS(Bands[1], Win1[1], Win2[0]); + B = 2; + } + } + else + { + // Both windows have two bands. + AND_BANDS(Bands[0], Win1[0], Win2[0]); + AND_BANDS(Bands[1], Win1[1], Win2[1]); + B = 2; + if (BANDS_INTERSECT(Win1[0], Win2[1])) + { + AND_BANDS(Bands[2], Win1[0], Win2[1]); + B = 3; + } + else + if (BANDS_INTERSECT(Win1[1], Win2[0])) + { + AND_BANDS(Bands[2], Win1[1], Win2[0]); + B = 3; + } + } + break; + case CLIP_XNOR: + invert = !invert; + // Fall... + + case CLIP_XOR: + if (Window1Enabled == 1 && BAND_EMPTY(Win1[0])) + { + B = Window2Enabled; + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win2, + sizeof(Win2[0]) * Window2Enabled); + } + else + if (Window2Enabled == 1 && BAND_EMPTY(Win2[0])) + { + B = Window1Enabled; + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win1, + sizeof(Win1[0]) * Window1Enabled); + } + else + { + uint32 p = 0; + uint32 points [10]; + uint32 i; + + invert = !invert; + // Build an array of points (window edges) + points [p++] = 0; + for (i = 0; i < Window1Enabled; i++) + { + points [p++] = Win1[i].Left; + points [p++] = Win1[i].Right; + } + for (i = 0; i < Window2Enabled; i++) + { + points [p++] = Win2[i].Left; + points [p++] = Win2[i].Right; + } + points [p++] = 256; + // Sort them + qsort ((void *) points, p, sizeof (points [0]), + IntCompare); + for (i = 0; i < p; i += 2) + { + if (points [i] == points [i + 1]) + continue; + Bands [B].Left = points [i]; + while (i + 2 < p && + points [i + 1] == points [i + 2]) + { + i += 2; + } + Bands [B++].Right = points [i + 1]; + } + } + break; + } + if (invert) + { + int b; + int j = 0; + int empty_band_count = 0; + + // First remove all empty bands from the list. + for (b = 0; b < B; b++) + { + if (!BAND_EMPTY(Bands[b])) + { + if (b != j) + Bands[j] = Bands[b]; + j++; + } + else + empty_band_count++; + } + + if (j > 0) + { + if (j == 1) + { + j = 0; + // Easy case to deal with, so special case it. + + if (Bands[0].Left > 0) + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = Bands[0].Left + 1; + } + if (Bands[0].Right < 256) + { + pClip->Left[j][w] = Bands[0].Right; + pClip->Right[j++][w] = 256; + } + if (j == 0) + { + pClip->Left[j][w] = 1; + pClip->Right[j++][w] = 0; + } + } + else + { + // Now sort the bands into order + B = j; + qsort ((void *) Bands, B, + sizeof (Bands [0]), BandCompare); + + // Now invert the area the bands cover + j = 0; + for (b = 0; b < B; b++) + { + if (b == 0 && Bands[b].Left > 0) + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = Bands[b].Left + 1; + } + else + if (b == B - 1 && Bands[b].Right < 256) + { + pClip->Left[j][w] = Bands[b].Right; + pClip->Right[j++][w] = 256; + } + if (b < B - 1) + { + pClip->Left[j][w] = Bands[b].Right; + pClip->Right[j++][w] = Bands[b + 1].Left + 1; + } + } + } + } + else + { + // Inverting a window that consisted of only + // empty bands is the whole width of the screen. + // Needed for Mario Kart's rear-view mirror display. + if (empty_band_count) + { + pClip->Left[j][w] = 0; + pClip->Right[j][w] = 256; + j++; + } + } + pClip->Count[w] = j; + } + else + { + for (int j = 0; j < B; j++) + { + pClip->Left[j][w] = Bands[j].Left; + pClip->Right[j][w] = Bands[j].Right; + } + pClip->Count [w] = B; + } + } + else + { + // Only one window enabled so no need to perform + // complex overlap logic... + + if (Window1Enabled) + { + if (invert) + { + int j = 0; + + if (Window1Enabled == 1) + { + if (Win1[0].Left <= Win1[0].Right) + { + if (Win1[0].Left > 0) + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = Win1[0].Left; + } + if (Win1[0].Right < 256) + { + pClip->Left[j][w] = Win1[0].Right; + pClip->Right[j++][w] = 256; + } + if (j == 0) + { + pClip->Left[j][w] = 1; + pClip->Right[j++][w] = 0; + } + } + else + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = 256; + } + } + else + { + pClip->Left [j][w] = Win1[0].Right; + pClip->Right[j++][w] = Win1[1].Left; + } + pClip->Count [w] = j; + } + else + { + for (uint32 j = 0; j < Window1Enabled; j++) + { + pClip->Left [j][w] = Win1[j].Left; + pClip->Right [j][w] = Win1[j].Right; + } + pClip->Count [w] = Window1Enabled; + } + } + else + if (Window2Enabled) + { + if (invert) + { + int j = 0; + if (Window2Enabled == 1) + { + if (Win2[0].Left <= Win2[0].Right) + { + if (Win2[0].Left > 0) + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = Win2[0].Left; + } + if (Win2[0].Right < 256) + { + pClip->Left[j][w] = Win2[0].Right; + pClip->Right[j++][w] = 256; + } + if (j == 0) + { + pClip->Left[j][w] = 1; + pClip->Right[j++][w] = 0; + } + } + else + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = 256; + } + } + else + { + pClip->Left [j][w] = Win2[0].Right; + pClip->Right[j++][w] = Win2[1].Left + 1; + } + pClip->Count [w] = j; + } + else + { + for (uint32 j = 0; j < Window2Enabled; j++) + { + pClip->Left [j][w] = Win2[j].Left; + pClip->Right [j][w] = Win2[j].Right; + } + pClip->Count [w] = Window2Enabled; + } + } + } + + if (w != 5 && pClip->Count [5]) + { + // Colour window enabled. Set the + // clip windows for all remaining backgrounds to be + // the same as the colour window. + if (pClip->Count [w] == 0) + { + pClip->Count [w] = pClip->Count [5]; + for (uint32 i = 0; i < pClip->Count [w]; i++) + { + pClip->Left [i][w] = pClip->Left [i][5]; + pClip->Right [i][w] = pClip->Right [i][5]; + } + } + else + { + // Intersect the colour window with the bg's + // own clip window. + for (uint32 i = 0; i < pClip->Count [w]; i++) + { + uint32 j; + for (j = 0; j < pClip->Count [5]; j++) + { + if((pClip->Left[i][w] >= pClip->Left[j][5] && pClip->Left[i][w] < pClip->Right[j][5]) || (pClip->Left[j][5] >= pClip->Left[i][w] && pClip->Left[j][5] < pClip->Right[i][w])){ + // Found an intersection! + pClip->Left[i][w]=MAX(pClip->Left[i][w], pClip->Left[j][5]); + pClip->Right[i][w]=MIN(pClip->Right[i][w], pClip->Right[j][5]); + goto Clip_ok; + } + } + // no intersection, nullify it + pClip->Left[i][w]=1; + pClip->Right[i][w]=0; +Clip_ok: + j=0; // dummy statement + } + } + } + } // if (w == 5 | ... + } // if (!Settings.DisableGraphicWindows) + } // for (int w... + } // for (int c... +} + diff --git a/source/clip.cpp b/source/clip.cpp deleted file mode 100644 index 7147abf..0000000 --- a/source/clip.cpp +++ /dev/null @@ -1,767 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include - -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" - -struct Band -{ - uint32 Left; - uint32 Right; -}; - -#undef MIN -#undef MAX -#define MIN(A,B) ((A) < (B) ? (A) : (B)) -#define MAX(A,B) ((A) > (B) ? (A) : (B)) -#define BAND_EMPTY(B) (B.Left >= B.Right) -#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || \ - (B.Left >= A.Left && B.Left < A.Right)) -#define OR_BANDS(R,A,B) {\ - R.Left = MIN(A.Left, B.Left); \ - R.Right = MAX(A.Right, B.Right);} - -#define AND_BANDS(R,A,B) {\ - R.Left = MAX(A.Left, B.Left); \ - R.Right = MIN(A.Right, B.Right);} - -static int IntCompare (const void *d1, const void *d2) -{ - if (*(uint32 *) d1 > *(uint32 *) d2) - return (1); - else - if (*(uint32 *) d1 < *(uint32 *) d2) - return (-1); - return (0); -} - -static int BandCompare (const void *d1, const void *d2) -{ - if (((struct Band *) d1)->Left > ((struct Band *) d2)->Left) - return (1); - else - if (((struct Band *) d1)->Left < ((struct Band *) d2)->Left) - return (-1); - return (0); -} - -void ComputeClipWindows () -{ - struct ClipData *pClip = &IPPU.Clip [0]; - - // Loop around the main screen then the sub-screen. - for (int c = 0; c < 2; c++, pClip++) - { - // Loop around the colour window then a clip window for each of the - // background layers. - for (int w = 5; w >= 0; w--) - { - pClip->Count[w] = 0; - - if (w == 5) // The colour window... - { - if (c == 0) // ... on the main screen - { - if ((Memory.FillRAM [0x2130] & 0xc0) == 0xc0) - { - // The whole of the main screen is switched off, - // completely clip everything. - for (int i = 0; i < 6; i++) - { - IPPU.Clip [c].Count [i] = 1; - IPPU.Clip [c].Left [0][i] = 1; - IPPU.Clip [c].Right [0][i] = 0; - } - continue; - } - else if ((Memory.FillRAM [0x2130] & 0xc0) == 0x00) - continue; - } - else - { - // .. colour window on the sub-screen. - if ((Memory.FillRAM [0x2130] & 0x30) == 0x30) - { - // The sub-screen is switched off, completely - // clip everything. - for (int i = 0; i < 6; i++) - { - IPPU.Clip [1].Count [i] = 1; - IPPU.Clip [1].Left [0][i] = 1; - IPPU.Clip [1].Right [0][i] = 0; - } - return; - } - else if ((Memory.FillRAM [0x2130] & 0x30) == 0x00) - continue; - } - } - -// if (!Settings.DisableGraphicWindows) - { - if (w == 5 || pClip->Count [5] || - (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) - { - struct Band Win1[3]; - struct Band Win2[3]; - uint32 Window1Enabled = 0; - uint32 Window2Enabled = 0; - bool8 invert = (w == 5 && - ((c == 1 && (Memory.FillRAM [0x2130] & 0x30) == 0x10) || - (c == 0 && (Memory.FillRAM [0x2130] & 0xc0) == 0x40))); - - if (w == 5 || - (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) - { - if (PPU.ClipWindow1Enable [w]) - { - if (!PPU.ClipWindow1Inside [w]) - { - Win1[Window1Enabled].Left = PPU.Window1Left; - Win1[Window1Enabled++].Right = PPU.Window1Right + 1; - } - else - { - if (PPU.Window1Left <= PPU.Window1Right) - { - if (PPU.Window1Left > 0) - { - Win1[Window1Enabled].Left = 0; - Win1[Window1Enabled++].Right = PPU.Window1Left; - } - if (PPU.Window1Right < 255) - { - Win1[Window1Enabled].Left = PPU.Window1Right + 1; - Win1[Window1Enabled++].Right = 256; - } - if (Window1Enabled == 0) - { - Win1[Window1Enabled].Left = 1; - Win1[Window1Enabled++].Right = 0; - } - } - else - { - // 'outside' a window with no range - - // appears to be the whole screen. - Win1[Window1Enabled].Left = 0; - Win1[Window1Enabled++].Right = 256; - } - } - } - if (PPU.ClipWindow2Enable [w]) - { - if (!PPU.ClipWindow2Inside [w]) - { - Win2[Window2Enabled].Left = PPU.Window2Left; - Win2[Window2Enabled++].Right = PPU.Window2Right + 1; - } - else - { - if (PPU.Window2Left <= PPU.Window2Right) - { - if (PPU.Window2Left > 0) - { - Win2[Window2Enabled].Left = 0; - Win2[Window2Enabled++].Right = PPU.Window2Left; - } - if (PPU.Window2Right < 255) - { - Win2[Window2Enabled].Left = PPU.Window2Right + 1; - Win2[Window2Enabled++].Right = 256; - } - if (Window2Enabled == 0) - { - Win2[Window2Enabled].Left = 1; - Win2[Window2Enabled++].Right = 0; - } - } - else - { - Win2[Window2Enabled].Left = 0; - Win2[Window2Enabled++].Right = 256; - } - } - } - } - if (Window1Enabled && Window2Enabled) - { - // Overlap logic - // - // Each window will be in one of three states: - // 1. (Left > Right. One band) - // 2. | ---------------- | (Left >= 0, Right <= 255, Left <= Right. One band) - // 3. |------------ ----------| (Left1 == 0, Right1 < Left2; Left2 > Right1, Right2 == 255. Two bands) - - struct Band Bands [6]; - int B = 0; - switch (PPU.ClipWindowOverlapLogic [w] ^ 1) - { - case CLIP_OR: - if (Window1Enabled == 1) - { - if (BAND_EMPTY(Win1[0])) - { - B = Window2Enabled; - // memmove converted: Different stack allocations [Neb] - memcpy (Bands, Win2, - sizeof(Win2[0]) * Window2Enabled); - } - else - { - if (Window2Enabled == 1) - { - if (BAND_EMPTY (Win2[0])) - Bands[B++] = Win1[0]; - else - { - if (BANDS_INTERSECT (Win1[0], Win2[0])) - { - OR_BANDS(Bands[0],Win1[0], Win2[0]) - B = 1; - } - else - { - Bands[B++] = Win1[0]; - Bands[B++] = Win2[0]; - } - } - } - else - { - if (BANDS_INTERSECT(Win1[0], Win2[0])) - { - OR_BANDS(Bands[0], Win1[0], Win2[0]) - if (BANDS_INTERSECT(Win1[0], Win2[1])) - OR_BANDS(Bands[1], Win1[0], Win2[1]) - else - Bands[1] = Win2[1]; - B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; - } - else - if (BANDS_INTERSECT(Win1[0], Win2[1])) - { - Bands[B++] = Win2[0]; - OR_BANDS(Bands[B], Win1[0], Win2[1]); - B++; - } - else - { - Bands[0] = Win2[0]; - Bands[1] = Win1[0]; - Bands[2] = Win2[1]; - B = 3; - } - } - } - } - else - if (Window2Enabled == 1) - { - if (BAND_EMPTY(Win2[0])) - { - // Window 2 defines an empty range - just - // use window 1 as the clipping (which - // could also be empty). - B = Window1Enabled; - // memmove converted: Different stack allocations [Neb] - memcpy (Bands, Win1, - sizeof(Win1[0]) * Window1Enabled); - } - else - { - // Window 1 has two bands and Window 2 has one. - // Neither is an empty region. - if (BANDS_INTERSECT(Win2[0], Win1[0])) - { - OR_BANDS(Bands[0], Win2[0], Win1[0]) - if (BANDS_INTERSECT(Win2[0], Win1[1])) - OR_BANDS(Bands[1], Win2[0], Win1[1]) - else - Bands[1] = Win1[1]; - B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; - } - else - if (BANDS_INTERSECT(Win2[0], Win1[1])) - { - Bands[B++] = Win1[0]; - OR_BANDS(Bands[B], Win2[0], Win1[1]); - B++; - } - else - { - Bands[0] = Win1[0]; - Bands[1] = Win2[0]; - Bands[2] = Win1[1]; - B = 3; - } - } - } - else - { - // Both windows have two bands - OR_BANDS(Bands[0], Win1[0], Win2[0]); - OR_BANDS(Bands[1], Win1[1], Win2[1]); - B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; - } - break; - - case CLIP_AND: - if (Window1Enabled == 1) - { - // Window 1 has one band - if (BAND_EMPTY(Win1[0])) - Bands [B++] = Win1[0]; - else - if (Window2Enabled == 1) - { - if (BAND_EMPTY (Win2[0])) - Bands [B++] = Win2[0]; - else - { - AND_BANDS(Bands[0], Win1[0], Win2[0]); - B = 1; - } - } - else - { - AND_BANDS(Bands[0], Win1[0], Win2[0]); - AND_BANDS(Bands[1], Win1[0], Win2[1]); - B = 2; - } - } - else - if (Window2Enabled == 1) - { - if (BAND_EMPTY(Win2[0])) - Bands[B++] = Win2[0]; - else - { - // Window 1 has two bands. - AND_BANDS(Bands[0], Win1[0], Win2[0]); - AND_BANDS(Bands[1], Win1[1], Win2[0]); - B = 2; - } - } - else - { - // Both windows have two bands. - AND_BANDS(Bands[0], Win1[0], Win2[0]); - AND_BANDS(Bands[1], Win1[1], Win2[1]); - B = 2; - if (BANDS_INTERSECT(Win1[0], Win2[1])) - { - AND_BANDS(Bands[2], Win1[0], Win2[1]); - B = 3; - } - else - if (BANDS_INTERSECT(Win1[1], Win2[0])) - { - AND_BANDS(Bands[2], Win1[1], Win2[0]); - B = 3; - } - } - break; - case CLIP_XNOR: - invert = !invert; - // Fall... - - case CLIP_XOR: - if (Window1Enabled == 1 && BAND_EMPTY(Win1[0])) - { - B = Window2Enabled; - // memmove converted: Different stack allocations [Neb] - memcpy (Bands, Win2, - sizeof(Win2[0]) * Window2Enabled); - } - else - if (Window2Enabled == 1 && BAND_EMPTY(Win2[0])) - { - B = Window1Enabled; - // memmove converted: Different stack allocations [Neb] - memcpy (Bands, Win1, - sizeof(Win1[0]) * Window1Enabled); - } - else - { - uint32 p = 0; - uint32 points [10]; - uint32 i; - - invert = !invert; - // Build an array of points (window edges) - points [p++] = 0; - for (i = 0; i < Window1Enabled; i++) - { - points [p++] = Win1[i].Left; - points [p++] = Win1[i].Right; - } - for (i = 0; i < Window2Enabled; i++) - { - points [p++] = Win2[i].Left; - points [p++] = Win2[i].Right; - } - points [p++] = 256; - // Sort them - qsort ((void *) points, p, sizeof (points [0]), - IntCompare); - for (i = 0; i < p; i += 2) - { - if (points [i] == points [i + 1]) - continue; - Bands [B].Left = points [i]; - while (i + 2 < p && - points [i + 1] == points [i + 2]) - { - i += 2; - } - Bands [B++].Right = points [i + 1]; - } - } - break; - } - if (invert) - { - int b; - int j = 0; - int empty_band_count = 0; - - // First remove all empty bands from the list. - for (b = 0; b < B; b++) - { - if (!BAND_EMPTY(Bands[b])) - { - if (b != j) - Bands[j] = Bands[b]; - j++; - } - else - empty_band_count++; - } - - if (j > 0) - { - if (j == 1) - { - j = 0; - // Easy case to deal with, so special case it. - - if (Bands[0].Left > 0) - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = Bands[0].Left + 1; - } - if (Bands[0].Right < 256) - { - pClip->Left[j][w] = Bands[0].Right; - pClip->Right[j++][w] = 256; - } - if (j == 0) - { - pClip->Left[j][w] = 1; - pClip->Right[j++][w] = 0; - } - } - else - { - // Now sort the bands into order - B = j; - qsort ((void *) Bands, B, - sizeof (Bands [0]), BandCompare); - - // Now invert the area the bands cover - j = 0; - for (b = 0; b < B; b++) - { - if (b == 0 && Bands[b].Left > 0) - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = Bands[b].Left + 1; - } - else - if (b == B - 1 && Bands[b].Right < 256) - { - pClip->Left[j][w] = Bands[b].Right; - pClip->Right[j++][w] = 256; - } - if (b < B - 1) - { - pClip->Left[j][w] = Bands[b].Right; - pClip->Right[j++][w] = Bands[b + 1].Left + 1; - } - } - } - } - else - { - // Inverting a window that consisted of only - // empty bands is the whole width of the screen. - // Needed for Mario Kart's rear-view mirror display. - if (empty_band_count) - { - pClip->Left[j][w] = 0; - pClip->Right[j][w] = 256; - j++; - } - } - pClip->Count[w] = j; - } - else - { - for (int j = 0; j < B; j++) - { - pClip->Left[j][w] = Bands[j].Left; - pClip->Right[j][w] = Bands[j].Right; - } - pClip->Count [w] = B; - } - } - else - { - // Only one window enabled so no need to perform - // complex overlap logic... - - if (Window1Enabled) - { - if (invert) - { - int j = 0; - - if (Window1Enabled == 1) - { - if (Win1[0].Left <= Win1[0].Right) - { - if (Win1[0].Left > 0) - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = Win1[0].Left; - } - if (Win1[0].Right < 256) - { - pClip->Left[j][w] = Win1[0].Right; - pClip->Right[j++][w] = 256; - } - if (j == 0) - { - pClip->Left[j][w] = 1; - pClip->Right[j++][w] = 0; - } - } - else - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = 256; - } - } - else - { - pClip->Left [j][w] = Win1[0].Right; - pClip->Right[j++][w] = Win1[1].Left; - } - pClip->Count [w] = j; - } - else - { - for (uint32 j = 0; j < Window1Enabled; j++) - { - pClip->Left [j][w] = Win1[j].Left; - pClip->Right [j][w] = Win1[j].Right; - } - pClip->Count [w] = Window1Enabled; - } - } - else - if (Window2Enabled) - { - if (invert) - { - int j = 0; - if (Window2Enabled == 1) - { - if (Win2[0].Left <= Win2[0].Right) - { - if (Win2[0].Left > 0) - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = Win2[0].Left; - } - if (Win2[0].Right < 256) - { - pClip->Left[j][w] = Win2[0].Right; - pClip->Right[j++][w] = 256; - } - if (j == 0) - { - pClip->Left[j][w] = 1; - pClip->Right[j++][w] = 0; - } - } - else - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = 256; - } - } - else - { - pClip->Left [j][w] = Win2[0].Right; - pClip->Right[j++][w] = Win2[1].Left + 1; - } - pClip->Count [w] = j; - } - else - { - for (uint32 j = 0; j < Window2Enabled; j++) - { - pClip->Left [j][w] = Win2[j].Left; - pClip->Right [j][w] = Win2[j].Right; - } - pClip->Count [w] = Window2Enabled; - } - } - } - - if (w != 5 && pClip->Count [5]) - { - // Colour window enabled. Set the - // clip windows for all remaining backgrounds to be - // the same as the colour window. - if (pClip->Count [w] == 0) - { - pClip->Count [w] = pClip->Count [5]; - for (uint32 i = 0; i < pClip->Count [w]; i++) - { - pClip->Left [i][w] = pClip->Left [i][5]; - pClip->Right [i][w] = pClip->Right [i][5]; - } - } - else - { - // Intersect the colour window with the bg's - // own clip window. - for (uint32 i = 0; i < pClip->Count [w]; i++) - { - uint32 j; - for (j = 0; j < pClip->Count [5]; j++) - { - if((pClip->Left[i][w] >= pClip->Left[j][5] && pClip->Left[i][w] < pClip->Right[j][5]) || (pClip->Left[j][5] >= pClip->Left[i][w] && pClip->Left[j][5] < pClip->Right[i][w])){ - // Found an intersection! - pClip->Left[i][w]=MAX(pClip->Left[i][w], pClip->Left[j][5]); - pClip->Right[i][w]=MIN(pClip->Right[i][w], pClip->Right[j][5]); - goto Clip_ok; - } - } - // no intersection, nullify it - pClip->Left[i][w]=1; - pClip->Right[i][w]=0; -Clip_ok: - j=0; // dummy statement - } - } - } - } // if (w == 5 | ... - } // if (!Settings.DisableGraphicWindows) - } // for (int w... - } // for (int c... -} - diff --git a/source/cpu.c b/source/cpu.c new file mode 100644 index 0000000..2f9b4ae --- /dev/null +++ b/source/cpu.c @@ -0,0 +1,239 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "dsp1.h" +#include "cpuexec.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" + + +#ifndef ZSNES_FX +#include "fxemu.h" + +extern struct FxInit_s SuperFX; + +void S9xResetSuperFX () +{ + SuperFX.vFlags = 0; //FX_FLAG_ROM_BUFFER;// | FX_FLAG_ADDRESS_CHECKING; + FxReset (&SuperFX); +} +#endif + +void S9xResetCPU () +{ + ICPU.Registers.PB = 0; + ICPU.Registers.PC = S9xGetWord (0xFFFC); + ICPU.Registers.D.W = 0; + ICPU.Registers.DB = 0; + ICPU.Registers.SH = 1; + ICPU.Registers.SL = 0xFF; + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + ICPU.Registers.P.W = 0; + + ICPU.ShiftedPB = 0; + ICPU.ShiftedDB = 0; + SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags (Decimal); + + CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + CPU.BranchSkip = FALSE; + CPU.NMIActive = FALSE; + CPU.IRQActive = FALSE; + CPU.WaitingForInterrupt = FALSE; + CPU.InDMA = FALSE; + CPU.WhichEvent = HBLANK_START_EVENT; + CPU.PC = NULL; + CPU.PCBase = NULL; + CPU.PCAtOpcodeStart = NULL; + CPU.WaitAddress = NULL; + CPU.WaitCounter = 0; + CPU.Cycles = 0; + CPU.NextEvent = Settings.HBlankStart; + 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.NMITriggerPoint = 4; // Set when ROM image loaded + CPU.BRKTriggered = FALSE; + //CPU.TriedInterleavedMode2 = FALSE; // Reset when ROM image loaded + CPU.NMICycleCount = 0; + CPU.IRQCycleCount = 0; + S9xSetPCBase (ICPU.Registers.PC); + + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.CPUExecuting = TRUE; + + S9xUnpackStatus(); +} + +#ifdef ZSNES_FX +START_EXTERN_C +void S9xResetSuperFX (); +bool8 WinterGold = 0; +extern uint8 *C4Ram; +END_EXTERN_C +#endif + +void S9xReset (void) +{ + 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(); + S9xResetCPU (); + S9xResetPPU (); + S9xResetSRTC (); + if (Settings.SDD1) + S9xResetSDD1 (); + + S9xResetDMA (); + S9xResetAPU (); + S9xResetDSP1 (); + S9xSA1Init (); + if (Settings.C4) + S9xInitC4 (); + S9xInitCheatData (); + if(Settings.OBC1) + ResetOBC1(); + +// Settings.Paused = FALSE; +} +void S9xSoftReset (void) +{ + 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(); + S9xResetCPU (); + S9xSoftResetPPU (); + S9xResetSRTC (); + if (Settings.SDD1) + S9xResetSDD1 (); + + S9xResetDMA (); + S9xResetAPU (); + S9xResetDSP1 (); + if(Settings.OBC1) + ResetOBC1(); + S9xSA1Init (); + if (Settings.C4) + S9xInitC4 (); + S9xInitCheatData (); + +// Settings.Paused = FALSE; +} + diff --git a/source/cpu.cpp b/source/cpu.cpp deleted file mode 100644 index 2f9b4ae..0000000 --- a/source/cpu.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "dsp1.h" -#include "cpuexec.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" - - -#ifndef ZSNES_FX -#include "fxemu.h" - -extern struct FxInit_s SuperFX; - -void S9xResetSuperFX () -{ - SuperFX.vFlags = 0; //FX_FLAG_ROM_BUFFER;// | FX_FLAG_ADDRESS_CHECKING; - FxReset (&SuperFX); -} -#endif - -void S9xResetCPU () -{ - ICPU.Registers.PB = 0; - ICPU.Registers.PC = S9xGetWord (0xFFFC); - ICPU.Registers.D.W = 0; - ICPU.Registers.DB = 0; - ICPU.Registers.SH = 1; - ICPU.Registers.SL = 0xFF; - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - ICPU.Registers.P.W = 0; - - ICPU.ShiftedPB = 0; - ICPU.ShiftedDB = 0; - SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); - ClearFlags (Decimal); - - CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); - CPU.BranchSkip = FALSE; - CPU.NMIActive = FALSE; - CPU.IRQActive = FALSE; - CPU.WaitingForInterrupt = FALSE; - CPU.InDMA = FALSE; - CPU.WhichEvent = HBLANK_START_EVENT; - CPU.PC = NULL; - CPU.PCBase = NULL; - CPU.PCAtOpcodeStart = NULL; - CPU.WaitAddress = NULL; - CPU.WaitCounter = 0; - CPU.Cycles = 0; - CPU.NextEvent = Settings.HBlankStart; - 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.NMITriggerPoint = 4; // Set when ROM image loaded - CPU.BRKTriggered = FALSE; - //CPU.TriedInterleavedMode2 = FALSE; // Reset when ROM image loaded - CPU.NMICycleCount = 0; - CPU.IRQCycleCount = 0; - S9xSetPCBase (ICPU.Registers.PC); - - ICPU.S9xOpcodes = S9xOpcodesE1; - ICPU.CPUExecuting = TRUE; - - S9xUnpackStatus(); -} - -#ifdef ZSNES_FX -START_EXTERN_C -void S9xResetSuperFX (); -bool8 WinterGold = 0; -extern uint8 *C4Ram; -END_EXTERN_C -#endif - -void S9xReset (void) -{ - 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(); - S9xResetCPU (); - S9xResetPPU (); - S9xResetSRTC (); - if (Settings.SDD1) - S9xResetSDD1 (); - - S9xResetDMA (); - S9xResetAPU (); - S9xResetDSP1 (); - S9xSA1Init (); - if (Settings.C4) - S9xInitC4 (); - S9xInitCheatData (); - if(Settings.OBC1) - ResetOBC1(); - -// Settings.Paused = FALSE; -} -void S9xSoftReset (void) -{ - 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(); - S9xResetCPU (); - S9xSoftResetPPU (); - S9xResetSRTC (); - if (Settings.SDD1) - S9xResetSDD1 (); - - S9xResetDMA (); - S9xResetAPU (); - S9xResetDSP1 (); - if(Settings.OBC1) - ResetOBC1(); - S9xSA1Init (); - if (Settings.C4) - S9xInitC4 (); - S9xInitCheatData (); - -// Settings.Paused = FALSE; -} - diff --git a/source/cpuexec.c b/source/cpuexec.c new file mode 100644 index 0000000..02c4edd --- /dev/null +++ b/source/cpuexec.c @@ -0,0 +1,843 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +//#include "ds2_timer.h" +//#include "ds2_cpu.h" +//#include "ds2io.h" + +#include "snes9x.h" +#include "memmap.h" +#include "cpuops.h" +#include "ppu.h" +#include "cpuexec.h" +#include "snapshot.h" +#include "gfx.h" +#include "missing.h" +#include "apu.h" +#include "dma.h" +#include "fxemu.h" +#include "sa1.h" +#include "spc7110.h" + +#ifdef ACCUMULATE_JOYPAD +#include "display.h" +#endif + +extern void S9xProcessSound (unsigned int); + +void S9xMainLoop_SA1_SFX (void); +void S9xMainLoop_SA1_NoSFX (void); +void S9xMainLoop_NoSA1_SFX (void); +void S9xMainLoop_NoSA1_NoSFX (void); + +/* + * This is a CATSFC modification inspired by a Snes9x-Euphoria modification. + * The emulator selects a main loop based on the chips used in an entire + * frame. This avoids the constant SA1.Executing and Settings.SuperFX checks. + * + * The original version of S9xMainLoop is S9xMainLoop_SA1_SFX below. Remember + * to propagate modifications to the SA1_NoSFX, NoSA1_SFX and NoSA1_NoSFX + * versions. + */ +void S9xMainLoop (void) +{ + if (Settings.SA1) + { + if (Settings.SuperFX) S9xMainLoop_SA1_SFX (); + else /* if (!Settings.SuperFX) */ S9xMainLoop_SA1_NoSFX (); + } + else /* if (!Settings.SA1) */ + { + if (Settings.SuperFX) S9xMainLoop_NoSA1_SFX (); + else /* if (!Settings.SuperFX) */ S9xMainLoop_NoSA1_NoSFX (); + } +} + +void S9xMainLoop_SA1_SFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + if (SA1.Executing) + S9xSA1MainLoop (); + DO_HBLANK_CHECK_SFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } + +#ifdef DETECT_NASTY_FX_INTERLEAVE + if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) + { + CPU.TriedInterleavedMode2 = TRUE; + CPU.BRKTriggered = FALSE; + S9xDeinterleaveMode2 (); + } +#endif +} + +void S9xMainLoop_SA1_NoSFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + if (SA1.Executing) + S9xSA1MainLoop (); + DO_HBLANK_CHECK_NoSFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + +void S9xMainLoop_NoSA1_SFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + DO_HBLANK_CHECK_SFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } + +#ifdef DETECT_NASTY_FX_INTERLEAVE + if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) + { + CPU.TriedInterleavedMode2 = TRUE; + CPU.BRKTriggered = FALSE; + S9xDeinterleaveMode2 (); + } +#endif +} + +void S9xMainLoop_NoSA1_NoSFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + DO_HBLANK_CHECK_NoSFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + +void S9xSetIRQ (uint32 source) +{ + CPU.IRQActive |= source; + CPU.Flags |= IRQ_PENDING_FLAG; + CPU.IRQCycleCount = 3; + if (CPU.WaitingForInterrupt) + { + // Force IRQ to trigger immediately after WAI - + // Final Fantasy Mystic Quest crashes without this. + CPU.IRQCycleCount = 0; + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } +} + +void S9xClearIRQ (uint32 source) +{ + CLEAR_IRQ_SOURCE (source); +} + +/* + * This is a CATSFC modification inspired by a Snes9x-Euphoria modification. + * The emulator selects an HBlank processor based on the chips used in an + * entire frame. This avoids the constant Settings.SuperFX checks. + * + * The original version of S9xDoHBlankProcessing is S9xDoHBlankProcessing_SFX + * below. Remember to propagate modifications to the NoSFX version. + */ +void S9xDoHBlankProcessing_SFX () +{ +#ifdef CPU_SHUTDOWN + CPU.WaitCounter++; +#endif + switch (CPU.WhichEvent) + { + case HBLANK_START_EVENT: +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + if ((CPU.V_Counter & 0xF) == 0) + NDSSFCAccumulateJoypad (); +#endif + if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); + + break; + + case HBLANK_END_EVENT: + S9xSuperFXExec (); + +#ifndef STORM + if (Settings.SoundSync) + S9xGenerateSound (); +#endif + + CPU.Cycles -= Settings.H_Max; + if (IAPU.APUExecuting) + { + APU.Cycles -= Settings.H_Max; +#ifdef MK_APU + S9xCatchupCount(); +#endif + } + else + APU.Cycles = 0; + + CPU.NextEvent = -1; + ICPU.Scanline++; + + if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) + { + CPU.V_Counter = 0; + Memory.FillRAM[0x213F]^=0x80; + PPU.RangeTimeOver = 0; + CPU.NMIActive = FALSE; + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + S9xStartHDMA (); + } + + S9xProcessSound (0); + + if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) + { + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + // Start of V-blank + S9xEndScreenRefresh (); + IPPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + missing.dma_this_frame = 0; + IPPU.MaxBrightness = PPU.Brightness; + PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; + + if(!PPU.ForcedBlanking) + { + 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; + } + + Memory.FillRAM[0x4210] = 0x80 |Model->_5A22; + if (Memory.FillRAM[0x4200] & 0x80) + { + CPU.NMIActive = TRUE; + CPU.Flags |= NMI_FLAG; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } + +#ifdef OLD_SNAPSHOT_CODE + if (CPU.Flags & SAVE_SNAPSHOT_FLAG) + { + CPU.Flags &= ~SAVE_SNAPSHOT_FLAG; + Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + S9xAPUPackStatus (); + Snapshot (NULL); + } +#endif + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) + S9xUpdateJoypads (); + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) + { + Memory.FillRAM[0x4210] = Model->_5A22; + CPU.Flags &= ~NMI_FLAG; + S9xStartScreenRefresh (); + } + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && + CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); + } + // Use TimerErrorCounter to skip update of SPC700 timers once + // every 128 updates. Needed because this section of code is called + // once every emulated 63.5 microseconds, which coresponds to + // 15.750KHz, but the SPC700 timers need to be updated at multiples + // of 8KHz, hence the error correction. +// IAPU.TimerErrorCounter++; +// if (IAPU.TimerErrorCounter >= ) +// IAPU.TimerErrorCounter = 0; +// else + { + if (APU.TimerEnabled [2]) + { + APU.Timer [2] += 4; + while (APU.Timer [2] >= APU.TimerTarget [2]) + { + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] -= APU.TimerTarget [2]; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; +#endif + } + } + if (CPU.V_Counter & 1) + { + 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 + } + } + } + } + break; + + case HTIMER_BEFORE_EVENT: + case HTIMER_AFTER_EVENT: + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) + { + S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); + } + break; + } + + S9xReschedule (); +} +void S9xDoHBlankProcessing_NoSFX () +{ +#ifdef CPU_SHUTDOWN + CPU.WaitCounter++; +#endif + switch (CPU.WhichEvent) + { + case HBLANK_START_EVENT: +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif + if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); + + break; + + case HBLANK_END_EVENT: + +#ifndef STORM + if (Settings.SoundSync) + S9xGenerateSound (); +#endif + + CPU.Cycles -= Settings.H_Max; + if (IAPU.APUExecuting) + { + APU.Cycles -= Settings.H_Max; +#ifdef MK_APU + S9xCatchupCount(); +#endif + } + else + APU.Cycles = 0; + + CPU.NextEvent = -1; + ICPU.Scanline++; + + if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) + { + CPU.V_Counter = 0; + Memory.FillRAM[0x213F]^=0x80; + PPU.RangeTimeOver = 0; + CPU.NMIActive = FALSE; + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + S9xStartHDMA (); + } + + S9xProcessSound (0); + + if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) + { + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + // Start of V-blank + S9xEndScreenRefresh (); + IPPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + missing.dma_this_frame = 0; + IPPU.MaxBrightness = PPU.Brightness; + PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; + + if(!PPU.ForcedBlanking) + { + 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; + } + + Memory.FillRAM[0x4210] = 0x80 |Model->_5A22; + if (Memory.FillRAM[0x4200] & 0x80) + { + CPU.NMIActive = TRUE; + CPU.Flags |= NMI_FLAG; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } + +#ifdef OLD_SNAPSHOT_CODE + if (CPU.Flags & SAVE_SNAPSHOT_FLAG) + { + CPU.Flags &= ~SAVE_SNAPSHOT_FLAG; + Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + S9xAPUPackStatus (); + Snapshot (NULL); + } +#endif + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) + S9xUpdateJoypads (); + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) + { + Memory.FillRAM[0x4210] = Model->_5A22; + CPU.Flags &= ~NMI_FLAG; + S9xStartScreenRefresh (); + } + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && + CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); + } + // Use TimerErrorCounter to skip update of SPC700 timers once + // every 128 updates. Needed because this section of code is called + // once every emulated 63.5 microseconds, which coresponds to + // 15.750KHz, but the SPC700 timers need to be updated at multiples + // of 8KHz, hence the error correction. +// IAPU.TimerErrorCounter++; +// if (IAPU.TimerErrorCounter >= ) +// IAPU.TimerErrorCounter = 0; +// else + { + if (APU.TimerEnabled [2]) + { + APU.Timer [2] += 4; + while (APU.Timer [2] >= APU.TimerTarget [2]) + { + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] -= APU.TimerTarget [2]; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; +#endif + } + } + if (CPU.V_Counter & 1) + { + 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 + } + } + } + } + break; + + case HTIMER_BEFORE_EVENT: + case HTIMER_AFTER_EVENT: + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) + { + S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); + } + break; + } + + S9xReschedule (); +} + diff --git a/source/cpuexec.cpp b/source/cpuexec.cpp deleted file mode 100644 index 02c4edd..0000000 --- a/source/cpuexec.cpp +++ /dev/null @@ -1,843 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -//#include "ds2_timer.h" -//#include "ds2_cpu.h" -//#include "ds2io.h" - -#include "snes9x.h" -#include "memmap.h" -#include "cpuops.h" -#include "ppu.h" -#include "cpuexec.h" -#include "snapshot.h" -#include "gfx.h" -#include "missing.h" -#include "apu.h" -#include "dma.h" -#include "fxemu.h" -#include "sa1.h" -#include "spc7110.h" - -#ifdef ACCUMULATE_JOYPAD -#include "display.h" -#endif - -extern void S9xProcessSound (unsigned int); - -void S9xMainLoop_SA1_SFX (void); -void S9xMainLoop_SA1_NoSFX (void); -void S9xMainLoop_NoSA1_SFX (void); -void S9xMainLoop_NoSA1_NoSFX (void); - -/* - * This is a CATSFC modification inspired by a Snes9x-Euphoria modification. - * The emulator selects a main loop based on the chips used in an entire - * frame. This avoids the constant SA1.Executing and Settings.SuperFX checks. - * - * The original version of S9xMainLoop is S9xMainLoop_SA1_SFX below. Remember - * to propagate modifications to the SA1_NoSFX, NoSA1_SFX and NoSA1_NoSFX - * versions. - */ -void S9xMainLoop (void) -{ - if (Settings.SA1) - { - if (Settings.SuperFX) S9xMainLoop_SA1_SFX (); - else /* if (!Settings.SuperFX) */ S9xMainLoop_SA1_NoSFX (); - } - else /* if (!Settings.SA1) */ - { - if (Settings.SuperFX) S9xMainLoop_NoSA1_SFX (); - else /* if (!Settings.SuperFX) */ S9xMainLoop_NoSA1_NoSFX (); - } -} - -void S9xMainLoop_SA1_SFX (void) -{ - for (;;) - { - APU_EXECUTE (); - - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - S9xOpcode_NMI (); - } - } - - CHECK_SOUND (); - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - { - if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) - CPU.IRQCycleCount=1; - } - } - - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif - CPU.Cycles += CPU.MemSpeed; - - (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); - - if (SA1.Executing) - S9xSA1MainLoop (); - DO_HBLANK_CHECK_SFX(); - } - - ICPU.Registers.PC = CPU.PC - CPU.PCBase; - S9xPackStatus (); - IAPU.Registers.PC = IAPU.PC - IAPU.RAM; - S9xAPUPackStatus (); - if (CPU.Flags & SCAN_KEYS_FLAG) - { - S9xSyncSpeed (); - CPU.Flags &= ~SCAN_KEYS_FLAG; - } - -#ifdef DETECT_NASTY_FX_INTERLEAVE - if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) - { - CPU.TriedInterleavedMode2 = TRUE; - CPU.BRKTriggered = FALSE; - S9xDeinterleaveMode2 (); - } -#endif -} - -void S9xMainLoop_SA1_NoSFX (void) -{ - for (;;) - { - APU_EXECUTE (); - - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - S9xOpcode_NMI (); - } - } - - CHECK_SOUND (); - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - { - if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) - CPU.IRQCycleCount=1; - } - } - - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif - CPU.Cycles += CPU.MemSpeed; - - (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); - - if (SA1.Executing) - S9xSA1MainLoop (); - DO_HBLANK_CHECK_NoSFX(); - } - - ICPU.Registers.PC = CPU.PC - CPU.PCBase; - S9xPackStatus (); - IAPU.Registers.PC = IAPU.PC - IAPU.RAM; - S9xAPUPackStatus (); - if (CPU.Flags & SCAN_KEYS_FLAG) - { - S9xSyncSpeed (); - CPU.Flags &= ~SCAN_KEYS_FLAG; - } -} - -void S9xMainLoop_NoSA1_SFX (void) -{ - for (;;) - { - APU_EXECUTE (); - - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - S9xOpcode_NMI (); - } - } - - CHECK_SOUND (); - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - { - if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) - CPU.IRQCycleCount=1; - } - } - - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif - CPU.Cycles += CPU.MemSpeed; - - (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); - - DO_HBLANK_CHECK_SFX(); - } - - ICPU.Registers.PC = CPU.PC - CPU.PCBase; - S9xPackStatus (); - IAPU.Registers.PC = IAPU.PC - IAPU.RAM; - S9xAPUPackStatus (); - if (CPU.Flags & SCAN_KEYS_FLAG) - { - S9xSyncSpeed (); - CPU.Flags &= ~SCAN_KEYS_FLAG; - } - -#ifdef DETECT_NASTY_FX_INTERLEAVE - if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) - { - CPU.TriedInterleavedMode2 = TRUE; - CPU.BRKTriggered = FALSE; - S9xDeinterleaveMode2 (); - } -#endif -} - -void S9xMainLoop_NoSA1_NoSFX (void) -{ - for (;;) - { - APU_EXECUTE (); - - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - S9xOpcode_NMI (); - } - } - - CHECK_SOUND (); - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - { - if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) - CPU.IRQCycleCount=1; - } - } - - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif - CPU.Cycles += CPU.MemSpeed; - - (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); - - DO_HBLANK_CHECK_NoSFX(); - } - - ICPU.Registers.PC = CPU.PC - CPU.PCBase; - S9xPackStatus (); - IAPU.Registers.PC = IAPU.PC - IAPU.RAM; - S9xAPUPackStatus (); - if (CPU.Flags & SCAN_KEYS_FLAG) - { - S9xSyncSpeed (); - CPU.Flags &= ~SCAN_KEYS_FLAG; - } -} - -void S9xSetIRQ (uint32 source) -{ - CPU.IRQActive |= source; - CPU.Flags |= IRQ_PENDING_FLAG; - CPU.IRQCycleCount = 3; - if (CPU.WaitingForInterrupt) - { - // Force IRQ to trigger immediately after WAI - - // Final Fantasy Mystic Quest crashes without this. - CPU.IRQCycleCount = 0; - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } -} - -void S9xClearIRQ (uint32 source) -{ - CLEAR_IRQ_SOURCE (source); -} - -/* - * This is a CATSFC modification inspired by a Snes9x-Euphoria modification. - * The emulator selects an HBlank processor based on the chips used in an - * entire frame. This avoids the constant Settings.SuperFX checks. - * - * The original version of S9xDoHBlankProcessing is S9xDoHBlankProcessing_SFX - * below. Remember to propagate modifications to the NoSFX version. - */ -void S9xDoHBlankProcessing_SFX () -{ -#ifdef CPU_SHUTDOWN - CPU.WaitCounter++; -#endif - switch (CPU.WhichEvent) - { - case HBLANK_START_EVENT: -#ifdef ACCUMULATE_JOYPAD -/* - * This call allows NDSSFC to synchronise the DS controller more often. - * If porting a later version of Snes9x into NDSSFC, it is essential to - * preserve it. - */ - if ((CPU.V_Counter & 0xF) == 0) - NDSSFCAccumulateJoypad (); -#endif - if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) - IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); - - break; - - case HBLANK_END_EVENT: - S9xSuperFXExec (); - -#ifndef STORM - if (Settings.SoundSync) - S9xGenerateSound (); -#endif - - CPU.Cycles -= Settings.H_Max; - if (IAPU.APUExecuting) - { - APU.Cycles -= Settings.H_Max; -#ifdef MK_APU - S9xCatchupCount(); -#endif - } - else - APU.Cycles = 0; - - CPU.NextEvent = -1; - ICPU.Scanline++; - - if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) - { - CPU.V_Counter = 0; - Memory.FillRAM[0x213F]^=0x80; - PPU.RangeTimeOver = 0; - CPU.NMIActive = FALSE; - ICPU.Frame++; - PPU.HVBeamCounterLatched = 0; - CPU.Flags |= SCAN_KEYS_FLAG; - S9xStartHDMA (); - } - - S9xProcessSound (0); - - if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) - { - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - - if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - // Start of V-blank - S9xEndScreenRefresh (); - IPPU.HDMA = 0; - // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. - missing.dma_this_frame = 0; - IPPU.MaxBrightness = PPU.Brightness; - PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; - - if(!PPU.ForcedBlanking) - { - 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; - } - - Memory.FillRAM[0x4210] = 0x80 |Model->_5A22; - if (Memory.FillRAM[0x4200] & 0x80) - { - CPU.NMIActive = TRUE; - CPU.Flags |= NMI_FLAG; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } - -#ifdef OLD_SNAPSHOT_CODE - if (CPU.Flags & SAVE_SNAPSHOT_FLAG) - { - CPU.Flags &= ~SAVE_SNAPSHOT_FLAG; - Registers.PC = CPU.PC - CPU.PCBase; - S9xPackStatus (); - S9xAPUPackStatus (); - Snapshot (NULL); - } -#endif - } - - if (CPU.V_Counter == PPU.ScreenHeight + 3) - S9xUpdateJoypads (); - - if (CPU.V_Counter == FIRST_VISIBLE_LINE) - { - Memory.FillRAM[0x4210] = Model->_5A22; - CPU.Flags &= ~NMI_FLAG; - S9xStartScreenRefresh (); - } - if (CPU.V_Counter >= FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); - } - // Use TimerErrorCounter to skip update of SPC700 timers once - // every 128 updates. Needed because this section of code is called - // once every emulated 63.5 microseconds, which coresponds to - // 15.750KHz, but the SPC700 timers need to be updated at multiples - // of 8KHz, hence the error correction. -// IAPU.TimerErrorCounter++; -// if (IAPU.TimerErrorCounter >= ) -// IAPU.TimerErrorCounter = 0; -// else - { - if (APU.TimerEnabled [2]) - { - APU.Timer [2] += 4; - while (APU.Timer [2] >= APU.TimerTarget [2]) - { - IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; - APU.Timer [2] -= APU.TimerTarget [2]; -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; - IAPU.APUExecuting = TRUE; -#endif - } - } - if (CPU.V_Counter & 1) - { - 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 - } - } - } - } - break; - - case HTIMER_BEFORE_EVENT: - case HTIMER_AFTER_EVENT: - if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) - { - S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); - } - break; - } - - S9xReschedule (); -} -void S9xDoHBlankProcessing_NoSFX () -{ -#ifdef CPU_SHUTDOWN - CPU.WaitCounter++; -#endif - switch (CPU.WhichEvent) - { - case HBLANK_START_EVENT: -#ifdef ACCUMULATE_JOYPAD -/* - * This call allows NDSSFC to synchronise the DS controller more often. - * If porting a later version of Snes9x into NDSSFC, it is essential to - * preserve it. - */ - NDSSFCAccumulateJoypad (); -#endif - if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) - IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); - - break; - - case HBLANK_END_EVENT: - -#ifndef STORM - if (Settings.SoundSync) - S9xGenerateSound (); -#endif - - CPU.Cycles -= Settings.H_Max; - if (IAPU.APUExecuting) - { - APU.Cycles -= Settings.H_Max; -#ifdef MK_APU - S9xCatchupCount(); -#endif - } - else - APU.Cycles = 0; - - CPU.NextEvent = -1; - ICPU.Scanline++; - - if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) - { - CPU.V_Counter = 0; - Memory.FillRAM[0x213F]^=0x80; - PPU.RangeTimeOver = 0; - CPU.NMIActive = FALSE; - ICPU.Frame++; - PPU.HVBeamCounterLatched = 0; - CPU.Flags |= SCAN_KEYS_FLAG; - S9xStartHDMA (); - } - - S9xProcessSound (0); - - if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) - { - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - - if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - // Start of V-blank - S9xEndScreenRefresh (); - IPPU.HDMA = 0; - // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. - missing.dma_this_frame = 0; - IPPU.MaxBrightness = PPU.Brightness; - PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; - - if(!PPU.ForcedBlanking) - { - 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; - } - - Memory.FillRAM[0x4210] = 0x80 |Model->_5A22; - if (Memory.FillRAM[0x4200] & 0x80) - { - CPU.NMIActive = TRUE; - CPU.Flags |= NMI_FLAG; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } - -#ifdef OLD_SNAPSHOT_CODE - if (CPU.Flags & SAVE_SNAPSHOT_FLAG) - { - CPU.Flags &= ~SAVE_SNAPSHOT_FLAG; - Registers.PC = CPU.PC - CPU.PCBase; - S9xPackStatus (); - S9xAPUPackStatus (); - Snapshot (NULL); - } -#endif - } - - if (CPU.V_Counter == PPU.ScreenHeight + 3) - S9xUpdateJoypads (); - - if (CPU.V_Counter == FIRST_VISIBLE_LINE) - { - Memory.FillRAM[0x4210] = Model->_5A22; - CPU.Flags &= ~NMI_FLAG; - S9xStartScreenRefresh (); - } - if (CPU.V_Counter >= FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); - } - // Use TimerErrorCounter to skip update of SPC700 timers once - // every 128 updates. Needed because this section of code is called - // once every emulated 63.5 microseconds, which coresponds to - // 15.750KHz, but the SPC700 timers need to be updated at multiples - // of 8KHz, hence the error correction. -// IAPU.TimerErrorCounter++; -// if (IAPU.TimerErrorCounter >= ) -// IAPU.TimerErrorCounter = 0; -// else - { - if (APU.TimerEnabled [2]) - { - APU.Timer [2] += 4; - while (APU.Timer [2] >= APU.TimerTarget [2]) - { - IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; - APU.Timer [2] -= APU.TimerTarget [2]; -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; - IAPU.APUExecuting = TRUE; -#endif - } - } - if (CPU.V_Counter & 1) - { - 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 - } - } - } - } - break; - - case HTIMER_BEFORE_EVENT: - case HTIMER_AFTER_EVENT: - if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) - { - S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); - } - break; - } - - S9xReschedule (); -} - diff --git a/source/cpuops.c b/source/cpuops.c new file mode 100644 index 0000000..9dc7f0c --- /dev/null +++ b/source/cpuops.c @@ -0,0 +1,5307 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +/*****************************************************************************/ +/* CPU-S9xOpcodes.CPP */ +/* This file contains all the opcodes */ +/*****************************************************************************/ + +#include "snes9x.h" +#include "memmap.h" +#include "missing.h" +#include "apu.h" +#include "sa1.h" +#include "spc7110.h" + +#include "cpuexec.h" +#include "cpuaddr.h" +#include "cpuops.h" +#include "cpumacro.h" +#include "apu.h" + +EXTERN_C long OpAddress; + +// For use with the opcodes whose functions here examine the OpAddress. +static void OpAddressPassthrough (long Addr) +{ + OpAddress = Addr; +} + +/* ADC *************************************************************************************** */ +static void Op69M1 (void) +{ + Immediate8 (READ, ADC8); +} + +static void Op69M0 (void) +{ + Immediate16 (READ, ADC16); +} + +static void Op65M1 (void) +{ + Direct (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op65M0 (void) +{ + Direct (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op75M1 (void) +{ + DirectIndexedX (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op75M0 (void) +{ + DirectIndexedX (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op72M1 (void) +{ + DirectIndirect (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op72M0 (void) +{ + DirectIndirect (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op61M1 (void) +{ + DirectIndexedIndirect (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op61M0 (void) +{ + DirectIndexedIndirect (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op71M1 (void) +{ + DirectIndirectIndexed (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op71M0 (void) +{ + DirectIndirectIndexed (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op67M1 (void) +{ + DirectIndirectLong (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op67M0 (void) +{ + DirectIndirectLong (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op77M1 (void) +{ + DirectIndirectIndexedLong (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op77M0 (void) +{ + DirectIndirectIndexedLong (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op6DM1 (void) +{ + Absolute (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op6DM0 (void) +{ + Absolute (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op7DM1 (void) +{ + AbsoluteIndexedX (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op7DM0 (void) +{ + AbsoluteIndexedX (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op79M1 (void) +{ + AbsoluteIndexedY (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op79M0 (void) +{ + AbsoluteIndexedY (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op6FM1 (void) +{ + AbsoluteLong (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op6FM0 (void) +{ + AbsoluteLong (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op7FM1 (void) +{ + AbsoluteLongIndexedX (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op7FM0 (void) +{ + AbsoluteLongIndexedX (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op63M1 (void) +{ + StackRelative (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op63M0 (void) +{ + StackRelative (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op73M1 (void) +{ + StackRelativeIndirectIndexed (READ, ADC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void Op73M0 (void) +{ + StackRelativeIndirectIndexed (READ, ADC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +/**********************************************************************************************/ + +/* AND *************************************************************************************** */ +static void Op29M1 (void) +{ + ICPU.Registers.AL &= *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (ICPU.Registers.AL); +} + +static void Op29M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU.Registers.A.W &= *(uint16 *) CPU.PC; +#else + ICPU.Registers.A.W &= *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (ICPU.Registers.A.W); +} + +static void Op25M1 (void) +{ + Direct (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op25M0 (void) +{ + Direct (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op35M1 (void) +{ + DirectIndexedX (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op35M0 (void) +{ + DirectIndexedX (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op32M1 (void) +{ + DirectIndirect (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op32M0 (void) +{ + DirectIndirect (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op21M1 (void) +{ + DirectIndexedIndirect (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op21M0 (void) +{ + DirectIndexedIndirect (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op31M1 (void) +{ + DirectIndirectIndexed (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op31M0 (void) +{ + DirectIndirectIndexed (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op27M1 (void) +{ + DirectIndirectLong (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op27M0 (void) +{ + DirectIndirectLong (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op37M1 (void) +{ + DirectIndirectIndexedLong (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op37M0 (void) +{ + DirectIndirectIndexedLong (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op2DM1 (void) +{ + Absolute (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op2DM0 (void) +{ + Absolute (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op3DM1 (void) +{ + AbsoluteIndexedX (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op3DM0 (void) +{ + AbsoluteIndexedX (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op39M1 (void) +{ + AbsoluteIndexedY (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op39M0 (void) +{ + AbsoluteIndexedY (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op2FM1 (void) +{ + AbsoluteLong (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op2FM0 (void) +{ + AbsoluteLong (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op3FM1 (void) +{ + AbsoluteLongIndexedX (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op3FM0 (void) +{ + AbsoluteLongIndexedX (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op23M1 (void) +{ + StackRelative (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op23M0 (void) +{ + StackRelative (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op33M1 (void) +{ + StackRelativeIndirectIndexed (READ, AND8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void Op33M0 (void) +{ + StackRelativeIndirectIndexed (READ, AND16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* ASL *************************************************************************************** */ +static void Op0AM1 (void) +{ + A_ASL8 (); +} + +static void Op0AM0 (void) +{ + A_ASL16 (); +} + +static void Op06M1 (void) +{ + Direct (MODIFY, ASL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op06M0 (void) +{ + Direct (MODIFY, ASL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op16M1 (void) +{ + DirectIndexedX (MODIFY, ASL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op16M0 (void) +{ + DirectIndexedX (MODIFY, ASL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op0EM1 (void) +{ + Absolute (MODIFY, ASL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op0EM0 (void) +{ + Absolute (MODIFY, ASL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op1EM1 (void) +{ + AbsoluteIndexedX (MODIFY, ASL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op1EM0 (void) +{ + AbsoluteIndexedX (MODIFY, ASL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} +/**********************************************************************************************/ + +/* BIT *************************************************************************************** */ +static void Op89M1 (void) +{ + ICPU._Zero = ICPU.Registers.AL & *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op89M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU._Zero = (ICPU.Registers.A.W & *(uint16 *) CPU.PC) != 0; +#else + ICPU._Zero = (ICPU.Registers.A.W & (*CPU.PC + (*(CPU.PC + 1) << 8))) != 0; +#endif +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + CPU.PC += 2; +} + +static void Op24M1 (void) +{ + Direct (READ, BIT8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op24M0 (void) +{ + Direct (READ, BIT16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op34M1 (void) +{ + DirectIndexedX (READ, BIT8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op34M0 (void) +{ + DirectIndexedX (READ, BIT16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op2CM1 (void) +{ + Absolute (READ, BIT8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op2CM0 (void) +{ + Absolute (READ, BIT16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op3CM1 (void) +{ + AbsoluteIndexedX (READ, BIT8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op3CM0 (void) +{ + AbsoluteIndexedX (READ, BIT16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} +/**********************************************************************************************/ + +/* CMP *************************************************************************************** */ +static void OpC9M1 (void) +{ + int32 Int32 = (int) ICPU.Registers.AL - (intptr_t) *CPU.PC++; + ICPU._Carry = Int32 >= 0; + SetZN8 ((uint8) Int32); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC9M0 (void) +{ + int32 Int32; +#ifdef FAST_LSB_WORD_ACCESS + Int32 = (long) ICPU.Registers.A.W - (long) *(uint16 *) CPU.PC; +#else + Int32 = (long) ICPU.Registers.A.W - + (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); +#endif + ICPU._Carry = Int32 >= 0; + SetZN16 ((uint16) Int32); + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpC5M1 (void) +{ + Direct (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC5M0 (void) +{ + Direct (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpD5M1 (void) +{ + DirectIndexedX (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpD5M0 (void) +{ + DirectIndexedX (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpD2M1 (void) +{ + DirectIndirect (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpD2M0 (void) +{ + DirectIndirect (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC1M1 (void) +{ + DirectIndexedIndirect (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC1M0 (void) +{ + DirectIndexedIndirect (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpD1M1 (void) +{ + DirectIndirectIndexed (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpD1M0 (void) +{ + DirectIndirectIndexed (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC7M1 (void) +{ + DirectIndirectLong (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC7M0 (void) +{ + DirectIndirectLong (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpD7M1 (void) +{ + DirectIndirectIndexedLong (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpD7M0 (void) +{ + DirectIndirectIndexedLong (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpCDM1 (void) +{ + Absolute (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpCDM0 (void) +{ + Absolute (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpDDM1 (void) +{ + AbsoluteIndexedX (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpDDM0 (void) +{ + AbsoluteIndexedX (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpD9M1 (void) +{ + AbsoluteIndexedY (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpD9M0 (void) +{ + AbsoluteIndexedY (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpCFM1 (void) +{ + AbsoluteLong (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpCFM0 (void) +{ + AbsoluteLong (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpDFM1 (void) +{ + AbsoluteLongIndexedX (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpDFM0 (void) +{ + AbsoluteLongIndexedX (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpC3M1 (void) +{ + StackRelative (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void OpC3M0 (void) +{ + StackRelative (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void OpD3M1 (void) +{ + StackRelativeIndirectIndexed (READ, CMP8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void OpD3M0 (void) +{ + StackRelativeIndirectIndexed (READ, CMP16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +/**********************************************************************************************/ + +/* CMX *************************************************************************************** */ +static void OpE0X1 (void) +{ + int32 Int32 = (int) ICPU.Registers.XL - (intptr_t) *CPU.PC++; + ICPU._Carry = Int32 >= 0; + SetZN8 ((uint8) Int32); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE0X0 (void) +{ + int32 Int32; +#ifdef FAST_LSB_WORD_ACCESS + Int32 = (long) ICPU.Registers.X.W - (long) *(uint16 *) CPU.PC; +#else + Int32 = (long) ICPU.Registers.X.W - + (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); +#endif + ICPU._Carry = Int32 >= 0; + SetZN16 ((uint16) Int32); + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpE4X1 (void) +{ + Direct (READ, CMX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE4X0 (void) +{ + Direct (READ, CMX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpECX1 (void) +{ + Absolute (READ, CMX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpECX0 (void) +{ + Absolute (READ, CMX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +/**********************************************************************************************/ + +/* CMY *************************************************************************************** */ +static void OpC0X1 (void) +{ + int32 Int32 = (int) ICPU.Registers.YL - (intptr_t) *CPU.PC++; + ICPU._Carry = Int32 >= 0; + SetZN8 ((uint8) Int32); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC0X0 (void) +{ + int32 Int32; +#ifdef FAST_LSB_WORD_ACCESS + Int32 = (long) ICPU.Registers.Y.W - (long) *(uint16 *) CPU.PC; +#else + Int32 = (long) ICPU.Registers.Y.W - + (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); +#endif + ICPU._Carry = Int32 >= 0; + SetZN16 ((uint16) Int32); + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpC4X1 (void) +{ + Direct (READ, CMY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC4X0 (void) +{ + Direct (READ, CMY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpCCX1 (void) +{ + Absolute (READ, CMY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpCCX0 (void) +{ + Absolute (READ, CMY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +/**********************************************************************************************/ + +/* DEC *************************************************************************************** */ +static void Op3AM1 (void) +{ + A_DEC8 (); +} + +static void Op3AM0 (void) +{ + A_DEC16 (); +} + +static void OpC6M1 (void) +{ + Direct (MODIFY, DEC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpC6M0 (void) +{ + Direct (MODIFY, DEC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpD6M1 (void) +{ + DirectIndexedX (MODIFY, DEC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpD6M0 (void) +{ + DirectIndexedX (MODIFY, DEC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpCEM1 (void) +{ + Absolute (MODIFY, DEC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpCEM0 (void) +{ + Absolute (MODIFY, DEC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpDEM1 (void) +{ + AbsoluteIndexedX (MODIFY, DEC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpDEM0 (void) +{ + AbsoluteIndexedX (MODIFY, DEC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +/**********************************************************************************************/ + +/* EOR *************************************************************************************** */ +static void Op49M1 (void) +{ + ICPU.Registers.AL ^= *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (ICPU.Registers.AL); +} + +static void Op49M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU.Registers.A.W ^= *(uint16 *) CPU.PC; +#else + ICPU.Registers.A.W ^= *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (ICPU.Registers.A.W); +} + +static void Op45M1 (void) +{ + Direct (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op45M0 (void) +{ + Direct (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op55M1 (void) +{ + DirectIndexedX (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op55M0 (void) +{ + DirectIndexedX (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op52M1 (void) +{ + DirectIndirect (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op52M0 (void) +{ + DirectIndirect (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op41M1 (void) +{ + DirectIndexedIndirect (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op41M0 (void) +{ + DirectIndexedIndirect (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op51M1 (void) +{ + DirectIndirectIndexed (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op51M0 (void) +{ + DirectIndirectIndexed (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op47M1 (void) +{ + DirectIndirectLong (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op47M0 (void) +{ + DirectIndirectLong (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op57M1 (void) +{ + DirectIndirectIndexedLong (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op57M0 (void) +{ + DirectIndirectIndexedLong (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op4DM1 (void) +{ + Absolute (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op4DM0 (void) +{ + Absolute (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op5DM1 (void) +{ + AbsoluteIndexedX (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op5DM0 (void) +{ + AbsoluteIndexedX (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op59M1 (void) +{ + AbsoluteIndexedY (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op59M0 (void) +{ + AbsoluteIndexedY (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op4FM1 (void) +{ + AbsoluteLong (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op4FM0 (void) +{ + AbsoluteLong (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op5FM1 (void) +{ + AbsoluteLongIndexedX (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op5FM0 (void) +{ + AbsoluteLongIndexedX (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op43M1 (void) +{ + StackRelative (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op43M0 (void) +{ + StackRelative (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op53M1 (void) +{ + StackRelativeIndirectIndexed (READ, EOR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void Op53M0 (void) +{ + StackRelativeIndirectIndexed (READ, EOR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +/**********************************************************************************************/ + +/* INC *************************************************************************************** */ +static void Op1AM1 (void) +{ + A_INC8 (); +} + +static void Op1AM0 (void) +{ + A_INC16 (); +} + +static void OpE6M1 (void) +{ + Direct (MODIFY, INC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpE6M0 (void) +{ + Direct (MODIFY, INC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpF6M1 (void) +{ + DirectIndexedX (MODIFY, INC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpF6M0 (void) +{ + DirectIndexedX (MODIFY, INC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpEEM1 (void) +{ + Absolute (MODIFY, INC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpEEM0 (void) +{ + Absolute (MODIFY, INC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpFEM1 (void) +{ + AbsoluteIndexedX (MODIFY, INC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void OpFEM0 (void) +{ + AbsoluteIndexedX (MODIFY, INC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +/**********************************************************************************************/ +/* LDA *************************************************************************************** */ +static void OpA9M1 (void) +{ + ICPU.Registers.AL = *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (ICPU.Registers.AL); +} + +static void OpA9M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU.Registers.A.W = *(uint16 *) CPU.PC; +#else + ICPU.Registers.A.W = *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (ICPU.Registers.A.W); +} + +static void OpA5M1 (void) +{ + Direct (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA5M0 (void) +{ + Direct (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB5M1 (void) +{ + DirectIndexedX (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpB5M0 (void) +{ + DirectIndexedX (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpB2M1 (void) +{ + DirectIndirect (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB2M0 (void) +{ + DirectIndirect (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA1M1 (void) +{ + DirectIndexedIndirect (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA1M0 (void) +{ + DirectIndexedIndirect (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB1M1 (void) +{ + DirectIndirectIndexed (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB1M0 (void) +{ + DirectIndirectIndexed (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA7M1 (void) +{ + DirectIndirectLong (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA7M0 (void) +{ + DirectIndirectLong (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB7M1 (void) +{ + DirectIndirectIndexedLong (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB7M0 (void) +{ + DirectIndirectIndexedLong (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpADM1 (void) +{ + Absolute (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpADM0 (void) +{ + Absolute (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpBDM1 (void) +{ + AbsoluteIndexedX (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpBDM0 (void) +{ + AbsoluteIndexedX (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpB9M1 (void) +{ + AbsoluteIndexedY (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpB9M0 (void) +{ + AbsoluteIndexedY (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpAFM1 (void) +{ + AbsoluteLong (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpAFM0 (void) +{ + AbsoluteLong (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpBFM1 (void) +{ + AbsoluteLongIndexedX (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpBFM0 (void) +{ + AbsoluteLongIndexedX (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpA3M1 (void) +{ + StackRelative (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void OpA3M0 (void) +{ + StackRelative (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void OpB3M1 (void) +{ + StackRelativeIndirectIndexed (READ, LDA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void OpB3M0 (void) +{ + StackRelativeIndirectIndexed (READ, LDA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +/**********************************************************************************************/ + +/* LDX *************************************************************************************** */ +static void OpA2X1 (void) +{ + ICPU.Registers.XL = *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (ICPU.Registers.XL); +} + +static void OpA2X0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU.Registers.X.W = *(uint16 *) CPU.PC; +#else + ICPU.Registers.X.W = *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (ICPU.Registers.X.W); +} + +static void OpA6X1 (void) +{ + Direct (READ, LDX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA6X0 (void) +{ + Direct (READ, LDX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB6X1 (void) +{ + DirectIndexedY (READ, LDX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpB6X0 (void) +{ + DirectIndexedY (READ, LDX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpAEX1 (void) +{ + Absolute (READ, LDX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpAEX0 (void) +{ + Absolute (READ, LDX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpBEX1 (void) +{ + AbsoluteIndexedY (READ, LDX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpBEX0 (void) +{ + AbsoluteIndexedY (READ, LDX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} +/**********************************************************************************************/ + +/* LDY *************************************************************************************** */ +static void OpA0X1 (void) +{ + ICPU.Registers.YL = *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (ICPU.Registers.YL); +} + +static void OpA0X0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU.Registers.Y.W = *(uint16 *) CPU.PC; +#else + ICPU.Registers.Y.W = *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (ICPU.Registers.Y.W); +} + +static void OpA4X1 (void) +{ + Direct (READ, LDY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpA4X0 (void) +{ + Direct (READ, LDY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpB4X1 (void) +{ + DirectIndexedX (READ, LDY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpB4X0 (void) +{ + DirectIndexedX (READ, LDY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpACX1 (void) +{ + Absolute (READ, LDY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpACX0 (void) +{ + Absolute (READ, LDY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpBCX1 (void) +{ + AbsoluteIndexedX (READ, LDY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpBCX0 (void) +{ + AbsoluteIndexedX (READ, LDY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} +/**********************************************************************************************/ + +/* LSR *************************************************************************************** */ +static void Op4AM1 (void) +{ + A_LSR8 (); +} + +static void Op4AM0 (void) +{ + A_LSR16 (); +} + +static void Op46M1 (void) +{ + Direct (MODIFY, LSR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op46M0 (void) +{ + Direct (MODIFY, LSR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op56M1 (void) +{ + DirectIndexedX (MODIFY, LSR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op56M0 (void) +{ + DirectIndexedX (MODIFY, LSR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op4EM1 (void) +{ + Absolute (MODIFY, LSR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op4EM0 (void) +{ + Absolute (MODIFY, LSR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op5EM1 (void) +{ + AbsoluteIndexedX (MODIFY, LSR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op5EM0 (void) +{ + AbsoluteIndexedX (MODIFY, LSR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +/**********************************************************************************************/ + +/* ORA *************************************************************************************** */ +static void Op09M1 (void) +{ + ICPU.Registers.AL |= *CPU.PC++; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (ICPU.Registers.AL); +} + +static void Op09M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU.Registers.A.W |= *(uint16 *) CPU.PC; +#else + ICPU.Registers.A.W |= *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (ICPU.Registers.A.W); +} + +static void Op05M1 (void) +{ + Direct (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op05M0 (void) +{ + Direct (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op15M1 (void) +{ + DirectIndexedX (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op15M0 (void) +{ + DirectIndexedX (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op12M1 (void) +{ + DirectIndirect (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op12M0 (void) +{ + DirectIndirect (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op01M1 (void) +{ + DirectIndexedIndirect (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op01M0 (void) +{ + DirectIndexedIndirect (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op11M1 (void) +{ + DirectIndirectIndexed (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op11M0 (void) +{ + DirectIndirectIndexed (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op07M1 (void) +{ + DirectIndirectLong (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op07M0 (void) +{ + DirectIndirectLong (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op17M1 (void) +{ + DirectIndirectIndexedLong (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op17M0 (void) +{ + DirectIndirectIndexedLong (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op0DM1 (void) +{ + Absolute (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op0DM0 (void) +{ + Absolute (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op1DM1 (void) +{ + AbsoluteIndexedX (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op1DM0 (void) +{ + AbsoluteIndexedX (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op19M1 (void) +{ + AbsoluteIndexedY (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op19M0 (void) +{ + AbsoluteIndexedY (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op0FM1 (void) +{ + AbsoluteLong (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op0FM0 (void) +{ + AbsoluteLong (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op1FM1 (void) +{ + AbsoluteLongIndexedX (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op1FM0 (void) +{ + AbsoluteLongIndexedX (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op03M1 (void) +{ + StackRelative (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op03M0 (void) +{ + StackRelative (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op13M1 (void) +{ + StackRelativeIndirectIndexed (READ, ORA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void Op13M0 (void) +{ + StackRelativeIndirectIndexed (READ, ORA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +/**********************************************************************************************/ + +/* ROL *************************************************************************************** */ +static void Op2AM1 (void) +{ + A_ROL8 (); +} + +static void Op2AM0 (void) +{ + A_ROL16 (); +} + +static void Op26M1 (void) +{ + Direct (MODIFY, ROL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op26M0 (void) +{ + Direct (MODIFY, ROL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op36M1 (void) +{ + DirectIndexedX (MODIFY, ROL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op36M0 (void) +{ + DirectIndexedX (MODIFY, ROL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op2EM1 (void) +{ + Absolute (MODIFY, ROL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op2EM0 (void) +{ + Absolute (MODIFY, ROL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op3EM1 (void) +{ + AbsoluteIndexedX (MODIFY, ROL8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op3EM0 (void) +{ + AbsoluteIndexedX (MODIFY, ROL16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} +/**********************************************************************************************/ + +/* ROR *************************************************************************************** */ +static void Op6AM1 (void) +{ + A_ROR8 (); +} + +static void Op6AM0 (void) +{ + A_ROR16 (); +} + +static void Op66M1 (void) +{ + Direct (MODIFY, ROR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op66M0 (void) +{ + Direct (MODIFY, ROR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op76M1 (void) +{ + DirectIndexedX (MODIFY, ROR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op76M0 (void) +{ + DirectIndexedX (MODIFY, ROR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op6EM1 (void) +{ + Absolute (MODIFY, ROR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op6EM0 (void) +{ + Absolute (MODIFY, ROR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op7EM1 (void) +{ + AbsoluteIndexedX (MODIFY, ROR8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op7EM0 (void) +{ + AbsoluteIndexedX (MODIFY, ROR16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} +/**********************************************************************************************/ + +/* SBC *************************************************************************************** */ +static void OpE9M1 (void) +{ + Immediate8 (READ, SBC8); +} + +static void OpE9M0 (void) +{ + Immediate16 (READ, SBC16); +} + +static void OpE5M1 (void) +{ + Direct (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE5M0 (void) +{ + Direct (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpF5M1 (void) +{ + DirectIndexedX (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpF5M0 (void) +{ + DirectIndexedX (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpF2M1 (void) +{ + DirectIndirect (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpF2M0 (void) +{ + DirectIndirect (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE1M1 (void) +{ + DirectIndexedIndirect (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE1M0 (void) +{ + DirectIndexedIndirect (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpF1M1 (void) +{ + DirectIndirectIndexed (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpF1M0 (void) +{ + DirectIndirectIndexed (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE7M1 (void) +{ + DirectIndirectLong (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE7M0 (void) +{ + DirectIndirectLong (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpF7M1 (void) +{ + DirectIndirectIndexedLong (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpF7M0 (void) +{ + DirectIndirectIndexedLong (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpEDM1 (void) +{ + Absolute (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpEDM0 (void) +{ + Absolute (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpFDM1 (void) +{ + AbsoluteIndexedX (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpFDM0 (void) +{ + AbsoluteIndexedX (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpF9M1 (void) +{ + AbsoluteIndexedY (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpF9M0 (void) +{ + AbsoluteIndexedY (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpEFM1 (void) +{ + AbsoluteLong (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpEFM0 (void) +{ + AbsoluteLong (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpFFM1 (void) +{ + AbsoluteLongIndexedX (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpFFM0 (void) +{ + AbsoluteLongIndexedX (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void OpE3M1 (void) +{ + StackRelative (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void OpE3M0 (void) +{ + StackRelative (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void OpF3M1 (void) +{ + StackRelativeIndirectIndexed (READ, SBC8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void OpF3M0 (void) +{ + StackRelativeIndirectIndexed (READ, SBC16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* STA *************************************************************************************** */ +static void Op85M1 (void) +{ + Direct (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op85M0 (void) +{ + Direct (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op95M1 (void) +{ + DirectIndexedX (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op95M0 (void) +{ + DirectIndexedX (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op92M1 (void) +{ + DirectIndirect (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op92M0 (void) +{ + DirectIndirect (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op81M1 (void) +{ + DirectIndexedIndirect (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +#ifdef noVAR_CYCLES + if (CheckIndex ()) + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op81M0 (void) +{ + DirectIndexedIndirect (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +#ifdef noVAR_CYCLES + if (CheckIndex ()) + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op91M1 (void) +{ + DirectIndirectIndexed (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op91M0 (void) +{ + DirectIndirectIndexed (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op87M1 (void) +{ + DirectIndirectLong (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op87M0 (void) +{ + DirectIndirectLong (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op97M1 (void) +{ + DirectIndirectIndexedLong (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op97M0 (void) +{ + DirectIndirectIndexedLong (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op8DM1 (void) +{ + Absolute (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op8DM0 (void) +{ + Absolute (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op9DM1 (void) +{ + AbsoluteIndexedX (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op9DM0 (void) +{ + AbsoluteIndexedX (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op99M1 (void) +{ + AbsoluteIndexedY (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op99M0 (void) +{ + AbsoluteIndexedY (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op8FM1 (void) +{ + AbsoluteLong (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op8FM0 (void) +{ + AbsoluteLong (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op9FM1 (void) +{ + AbsoluteLongIndexedX (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op9FM0 (void) +{ + AbsoluteLongIndexedX (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif +} + +static void Op83M1 (void) +{ + StackRelative (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op83M0 (void) +{ + StackRelative (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif +} + +static void Op93M1 (void) +{ + StackRelativeIndirectIndexed (WRITE, STA8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} + +static void Op93M0 (void) +{ + StackRelativeIndirectIndexed (WRITE, STA16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* STX *************************************************************************************** */ +static void Op86X1 (void) +{ + Direct (WRITE, STX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op86X0 (void) +{ + Direct (WRITE, STX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op96X1 (void) +{ + DirectIndexedY (WRITE, STX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op96X0 (void) +{ + DirectIndexedY (WRITE, STX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op8EX1 (void) +{ + Absolute (WRITE, STX8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op8EX0 (void) +{ + Absolute (WRITE, STX16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} +/**********************************************************************************************/ + +/* STY *************************************************************************************** */ +static void Op84X1 (void) +{ + Direct (WRITE, STY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op84X0 (void) +{ + Direct (WRITE, STY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op94X1 (void) +{ + DirectIndexedX (WRITE, STY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op94X0 (void) +{ + DirectIndexedX (WRITE, STY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op8CX1 (void) +{ + Absolute (WRITE, STY8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op8CX0 (void) +{ + Absolute (WRITE, STY16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} +/**********************************************************************************************/ + +/* STZ *************************************************************************************** */ +static void Op64M1 (void) +{ + Direct (WRITE, STZ8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op64M0 (void) +{ + Direct (WRITE, STZ16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op74M1 (void) +{ + DirectIndexedX (WRITE, STZ8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op74M0 (void) +{ + DirectIndexedX (WRITE, STZ16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +// if (ICPU.Registers.DL != 0) +// CPU.Cycles += TWO_CYCLES; +// else +// CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op9CM1 (void) +{ + Absolute (WRITE, STZ8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op9CM0 (void) +{ + Absolute (WRITE, STZ16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op9EM1 (void) +{ + AbsoluteIndexedX (WRITE, STZ8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void Op9EM0 (void) +{ + AbsoluteIndexedX (WRITE, STZ16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +/**********************************************************************************************/ + +/* TRB *************************************************************************************** */ +static void Op14M1 (void) +{ + Direct (MODIFY, TRB8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op14M0 (void) +{ + Direct (MODIFY, TRB16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op1CM1 (void) +{ + Absolute (MODIFY, TRB8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op1CM0 (void) +{ + Absolute (MODIFY, TRB16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} +/**********************************************************************************************/ + +/* TSB *************************************************************************************** */ +static void Op04M1 (void) +{ + Direct (MODIFY, TSB8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op04M0 (void) +{ + Direct (MODIFY, TSB16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op0CM1 (void) +{ + Absolute (MODIFY, TSB8); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +static void Op0CM0 (void) +{ + Absolute (MODIFY, TSB16); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; +#endif +} + +/**********************************************************************************************/ + +/* Branch Instructions *********************************************************************** */ +#ifndef SA1_OPCODES +#define BranchCheck0()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod)\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + } + +#define BranchCheck1()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) {\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + } else \ + if (Settings.SoundSkipMethod == 1)\ + return;\ + if (Settings.SoundSkipMethod == 3)\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + else\ + CPU.PC = CPU.PCBase + OpAddress;\ + } + +#define BranchCheck2()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) {\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + } else \ + if (Settings.SoundSkipMethod == 1)\ + CPU.PC = CPU.PCBase + OpAddress;\ + if (Settings.SoundSkipMethod == 3)\ + if (CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + else\ + CPU.PC = CPU.PCBase + OpAddress;\ + } +#else +#define BranchCheck0() +#define BranchCheck1() +#define BranchCheck2() +#endif + +#ifdef CPU_SHUTDOWN +#ifndef SA1_OPCODES +inline void CPUShutdown() +{ + if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) + { + // Don't skip cycles with a pending NMI or IRQ - could cause delayed + // interrupt. Interrupts are delayed for a few cycles already, but + // the delay could allow the shutdown code to cycle skip again. + // Was causing screen flashing on Top Gear 3000. + + if (CPU.WaitCounter == 0 && + !(CPU.Flags & (IRQ_PENDING_FLAG | NMI_FLAG))) + { + CPU.WaitAddress = NULL; + if (Settings.SA1) + S9xSA1ExecuteDuringSleep (); + CPU.Cycles = CPU.NextEvent; + if (IAPU.APUExecuting) + { + ICPU.CPUExecuting = FALSE; + do + { + APU_EXECUTE1(); + } while (APU.Cycles < CPU.NextEvent); + ICPU.CPUExecuting = TRUE; + } + } + else + if (CPU.WaitCounter >= 2) + CPU.WaitCounter = 1; + else + CPU.WaitCounter--; + } +} +#else +inline void CPUShutdown() +{ + if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) + { + if (CPU.WaitCounter >= 1) + { + SA1.Executing = FALSE; + SA1.CPUExecuting = FALSE; + } + else + CPU.WaitCounter++; + } +} +#endif +#else +#define CPUShutdown() +#endif + +/* BCC */ +static void Op90 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck0 (); + if (!CheckCarry ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown(); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BCS */ +static void OpB0 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck0 (); + if (CheckCarry ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BEQ */ +static void OpF0 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck2 (); + if (CheckZero ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BMI */ +static void Op30 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck1 (); + if (CheckNegative ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BNE */ +static void OpD0 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck1 (); + if (!CheckZero ()) + { + CPU.PC = CPU.PCBase + OpAddress; + +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BPL */ +static void Op10 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck1 (); + if (!CheckNegative ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BRA */ +static void Op80 (void) +{ + Relative (JUMP, OpAddressPassthrough); + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); +} + +/* BVC */ +static void Op50 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck0 (); + if (!CheckOverflow ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} + +/* BVS */ +static void Op70 (void) +{ + Relative (JUMP, OpAddressPassthrough); + BranchCheck0 (); + if (CheckOverflow ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + CPUShutdown (); + } +#ifndef SA1_OPCODES + else + { + CPU.Cycles += CPU.MemSpeed; + } +#endif +} +/**********************************************************************************************/ + +/* ClearFlag Instructions ******************************************************************** */ +/* CLC */ +static void Op18 (void) +{ + ClearCarry (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +/* CLD */ +static void OpD8 (void) +{ + ClearDecimal (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +/* CLI */ +static void Op58 (void) +{ + ClearIRQ (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +/* CHECK_FOR_IRQ(); */ +} + +/* CLV */ +static void OpB8 (void) +{ + ClearOverflow (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* DEX/DEY *********************************************************************************** */ +static void OpCAX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.XL--; + SetZN8 (ICPU.Registers.XL); +} + +static void OpCAX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.X.W--; + SetZN16 (ICPU.Registers.X.W); +} + +static void Op88X1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.YL--; + SetZN8 (ICPU.Registers.YL); +} + +static void Op88X0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.Y.W--; + SetZN16 (ICPU.Registers.Y.W); +} +/**********************************************************************************************/ + +/* INX/INY *********************************************************************************** */ +static void OpE8X1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.XL++; + SetZN8 (ICPU.Registers.XL); +} + +static void OpE8X0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.X.W++; + SetZN16 (ICPU.Registers.X.W); +} + +static void OpC8X1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.YL++; + SetZN8 (ICPU.Registers.YL); +} + +static void OpC8X0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + ICPU.Registers.Y.W++; + SetZN16 (ICPU.Registers.Y.W); +} + +/**********************************************************************************************/ + +/* NOP *************************************************************************************** */ +static void OpEA (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* PUSH Instructions ************************************************************************* */ +/* #define PushW(w) \ + * S9xSetWord (w, ICPU.Registers.S.W - 1);\ + * ICPU.Registers.S.W -= 2; + */ +#define PushB(b)\ + S9xSetByte (b, ICPU.Registers.S.W--); + +#define PushBE(b)\ + S9xSetByte (b, ICPU.Registers.S.W--);\ + ICPU.Registers.SH=0x01; + + +#define PushW(w) \ + S9xSetByte ((w)>>8, ICPU.Registers.S.W);\ + S9xSetByte ((w)&0xff, (ICPU.Registers.S.W - 1)&0xFFFF);\ + ICPU.Registers.S.W -= 2; + +#define PushWE(w) \ + S9xSetByte ((w)>>8, ICPU.Registers.S.W--);\ + ICPU.Registers.SH=0x01;\ + S9xSetByte ((w)&0xff, (ICPU.Registers.S.W--)&0xFFFF);\ + ICPU.Registers.SH = 0x01; + +#define PushWENew(w) \ + S9xSetByte ((w)>>8, ICPU.Registers.S.W--);\ + S9xSetByte ((w)&0xff, (ICPU.Registers.S.W--)&0xFFFF);\ + ICPU.Registers.SH = 0x01; + +//PEA NL +static void OpF4E1 (void) +{ + Absolute (NONE, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + PushWENew ((unsigned short)OpAddress); +} + +static void OpF4 (void) +{ + Absolute (NONE, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + PushW ((unsigned short)OpAddress); +} + +//PEI NL +static void OpD4E1 (void) +{ + DirectIndirect (NONE, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + PushWENew ((unsigned short)OpAddress); +} + +static void OpD4 (void) +{ + DirectIndirect (NONE, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed; +#endif + PushW ((unsigned short)OpAddress); +} + +//PER NL +static void Op62E1 (void) +{ + RelativeLong (NONE, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + PushWENew ((unsigned short)OpAddress); +} + +static void Op62 (void) +{ + RelativeLong (NONE, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + PushW ((unsigned short)OpAddress); +} + + +//PHA +static void Op48E1 (void) +{ + PushBE (ICPU.Registers.AL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op48M1 (void) +{ + PushB (ICPU.Registers.AL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op48M0 (void) +{ + PushW (ICPU.Registers.A.W); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +//PHB +static void Op8BE1 (void) +{ + PushBE (ICPU.Registers.DB); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} +static void Op8B (void) +{ + PushB (ICPU.Registers.DB); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +//PHD NL +static void Op0BE1 (void) +{ + PushWENew (ICPU.Registers.D.W); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op0B (void) +{ + PushW (ICPU.Registers.D.W); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +//PHK +static void Op4BE1 (void) +{ + PushBE (ICPU.Registers.PB); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op4B (void) +{ + PushB (ICPU.Registers.PB); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +//PHP +static void Op08E1 (void) +{ + S9xPackStatus (); + PushBE (ICPU.Registers.PL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op08 (void) +{ + S9xPackStatus (); + PushB (ICPU.Registers.PL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +//PHX +static void OpDAE1 (void) +{ + PushBE (ICPU.Registers.XL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpDAX1 (void) +{ + PushB (ICPU.Registers.XL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpDAX0 (void) +{ + PushW (ICPU.Registers.X.W); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +//PHY +static void Op5AE1 (void) +{ + PushBE (ICPU.Registers.YL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op5AX1 (void) +{ + PushB (ICPU.Registers.YL); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op5AX0 (void) +{ + PushW (ICPU.Registers.Y.W); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* PULL Instructions ************************************************************************* */ +#define PullW(w) \ + w = S9xGetByte (++ICPU.Registers.S.W); \ + w |= (S9xGetByte (++ICPU.Registers.S.W)<<8); + +/* w = S9xGetWord (ICPU.Registers.S.W + 1); \ + ICPU.Registers.S.W += 2; +*/ + +#define PullB(b)\ + b = S9xGetByte (++ICPU.Registers.S.W); + +#define PullBE(b)\ + ICPU.Registers.S.W++;\ + ICPU.Registers.SH=0x01;\ + b = S9xGetByte (ICPU.Registers.S.W); + +#define PullWE(w) \ + ICPU.Registers.S.W++;\ + ICPU.Registers.SH=0x01;\ + w = S9xGetByte (ICPU.Registers.S.W); \ + ICPU.Registers.S.W++; \ + ICPU.Registers.SH=0x01;\ + w |= (S9xGetByte (ICPU.Registers.S.W)<<8); + +#define PullWENew(w) \ + PullW(w);\ + ICPU.Registers.SH=0x01; + +//PLA +static void Op68E1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullBE (ICPU.Registers.AL); + SetZN8 (ICPU.Registers.AL); +} + +static void Op68M1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (ICPU.Registers.AL); + SetZN8 (ICPU.Registers.AL); +} + +static void Op68M0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (ICPU.Registers.A.W); + SetZN16 (ICPU.Registers.A.W); +} + +//PLB +static void OpABE1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullBE (ICPU.Registers.DB); + SetZN8 (ICPU.Registers.DB); + ICPU.ShiftedDB = ICPU.Registers.DB << 16; +} + +static void OpAB (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (ICPU.Registers.DB); + SetZN8 (ICPU.Registers.DB); + ICPU.ShiftedDB = ICPU.Registers.DB << 16; +} + +/* PHP */ +//PLD NL +static void Op2BE1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullWENew (ICPU.Registers.D.W); + SetZN16 (ICPU.Registers.D.W); +} + +static void Op2B (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (ICPU.Registers.D.W); + SetZN16 (ICPU.Registers.D.W); +} + +/* PLP */ +static void Op28E1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullBE (ICPU.Registers.PL); + S9xUnpackStatus (); + + if (CheckIndex ()) + { + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ();*/ +} + +static void Op28 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (ICPU.Registers.PL); + S9xUnpackStatus (); + + if (CheckIndex ()) + { + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ();*/ +} + +//PLX +static void OpFAE1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullBE (ICPU.Registers.XL); + SetZN8 (ICPU.Registers.XL); +} + +static void OpFAX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (ICPU.Registers.XL); + SetZN8 (ICPU.Registers.XL); +} + +static void OpFAX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (ICPU.Registers.X.W); + SetZN16 (ICPU.Registers.X.W); +} + +//PLY +static void Op7AE1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullBE (ICPU.Registers.YL); + SetZN8 (ICPU.Registers.YL); +} + +static void Op7AX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (ICPU.Registers.YL); + SetZN8 (ICPU.Registers.YL); +} + +static void Op7AX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (ICPU.Registers.Y.W); + SetZN16 (ICPU.Registers.Y.W); +} + +/**********************************************************************************************/ + +/* SetFlag Instructions ********************************************************************** */ +/* SEC */ +static void Op38 (void) +{ + SetCarry (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} + +/* SED */ +static void OpF8 (void) +{ + SetDecimal (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + missing.decimal_mode = 1; +} + +/* SEI */ +static void Op78 (void) +{ + SetIRQ (); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* Transfer Instructions ********************************************************************* */ +/* TAX8 */ +static void OpAAX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.XL = ICPU.Registers.AL; + SetZN8 (ICPU.Registers.XL); +} + +/* TAX16 */ +static void OpAAX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.X.W = ICPU.Registers.A.W; + SetZN16 (ICPU.Registers.X.W); +} + +/* TAY8 */ +static void OpA8X1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.YL = ICPU.Registers.AL; + SetZN8 (ICPU.Registers.YL); +} + +/* TAY16 */ +static void OpA8X0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.Y.W = ICPU.Registers.A.W; + SetZN16 (ICPU.Registers.Y.W); +} + +static void Op5B (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.D.W = ICPU.Registers.A.W; + SetZN16 (ICPU.Registers.D.W); +} + +static void Op1B (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.S.W = ICPU.Registers.A.W; + if (CheckEmulation()) + ICPU.Registers.SH = 1; +} + +static void Op7B (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.A.W = ICPU.Registers.D.W; + SetZN16 (ICPU.Registers.A.W); +} + +static void Op3B (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.A.W = ICPU.Registers.S.W; + SetZN16 (ICPU.Registers.A.W); +} + +static void OpBAX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.XL = ICPU.Registers.SL; + SetZN8 (ICPU.Registers.XL); +} + +static void OpBAX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.X.W = ICPU.Registers.S.W; + SetZN16 (ICPU.Registers.X.W); +} + +static void Op8AM1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.AL = ICPU.Registers.XL; + SetZN8 (ICPU.Registers.AL); +} + +static void Op8AM0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.A.W = ICPU.Registers.X.W; + SetZN16 (ICPU.Registers.A.W); +} + +static void Op9A (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.S.W = ICPU.Registers.X.W; + if (CheckEmulation()) + ICPU.Registers.SH = 1; +} + +static void Op9BX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.YL = ICPU.Registers.XL; + SetZN8 (ICPU.Registers.YL); +} + +static void Op9BX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.Y.W = ICPU.Registers.X.W; + SetZN16 (ICPU.Registers.Y.W); +} + +static void Op98M1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.AL = ICPU.Registers.YL; + SetZN8 (ICPU.Registers.AL); +} + +static void Op98M0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.A.W = ICPU.Registers.Y.W; + SetZN16 (ICPU.Registers.A.W); +} + +static void OpBBX1 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.XL = ICPU.Registers.YL; + SetZN8 (ICPU.Registers.XL); +} + +static void OpBBX0 (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + ICPU.Registers.X.W = ICPU.Registers.Y.W; + SetZN16 (ICPU.Registers.X.W); +} + +/**********************************************************************************************/ + +/* XCE *************************************************************************************** */ +static void OpFB (void) +{ +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + + uint8 A1 = ICPU._Carry; + uint8 A2 = ICPU.Registers.PH; + ICPU._Carry = A2 & 1; + ICPU.Registers.PH = A1; + + if (CheckEmulation()) + { + SetFlags (MemoryFlag | IndexFlag); + ICPU.Registers.SH = 1; + missing.emulate6502 = 1; + } + if (CheckIndex ()) + { + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + } + S9xFixCycles(); +} +/**********************************************************************************************/ + +/* BRK *************************************************************************************** */ +static void Op00 (void) +{ +#ifndef SA1_OPCODES + CPU.BRKTriggered = TRUE; +#endif + + if (!CheckEmulation()) + { + PushB (ICPU.Registers.PB); + PushW (CPU.PC - CPU.PCBase + 1); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFE6)); +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFFE)); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + } +} +/**********************************************************************************************/ + +/* BRL ************************************************************************************** */ +static void Op82 (void) +{ + RelativeLong (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +} +/**********************************************************************************************/ + +/* IRQ *************************************************************************************** */ +void S9xOpcode_IRQ (void) +{ + if (!CheckEmulation()) + { + PushB (ICPU.Registers.PB); + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2207] | + (Memory.FillRAM [0x2208] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFEE)); + CPU.Cycles += TWO_CYCLES; +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2207] | + (Memory.FillRAM [0x2208] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFFE)); + CPU.Cycles += ONE_CYCLE; +#endif + } +} + +/**********************************************************************************************/ + +/* NMI *************************************************************************************** */ +void S9xOpcode_NMI (void) +{ + if (!CheckEmulation()) + { + PushB (ICPU.Registers.PB); + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2205] | + (Memory.FillRAM [0x2206] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFEA)); + CPU.Cycles += TWO_CYCLES; +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2205] | + (Memory.FillRAM [0x2206] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFFA)); + CPU.Cycles += ONE_CYCLE; +#endif + } +} +/**********************************************************************************************/ + +/* COP *************************************************************************************** */ +static void Op02 (void) +{ + if (!CheckEmulation()) + { + PushB (ICPU.Registers.PB); + PushW (CPU.PC - CPU.PCBase + 1); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFE4)); +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (ICPU.Registers.PL); + OpenBus = ICPU.Registers.PL; + ClearDecimal (); + SetIRQ (); + + ICPU.Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFF4)); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE; +#endif + } +} +/**********************************************************************************************/ + +/* JML *************************************************************************************** */ +static void OpDC (void) +{ + AbsoluteIndirectLong (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + ICPU.Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +} + +static void Op5C (void) +{ + AbsoluteLong (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif + ICPU.Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +} +/**********************************************************************************************/ + +/* JMP *************************************************************************************** */ +static void Op4C (void) +{ + Absolute (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); +#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) + CPUShutdown (); +#endif +} + +static void Op6C (void) +{ + AbsoluteIndirect (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2; +#endif + S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); +} + +static void Op7C (void) +{ + AbsoluteIndexedIndirect (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +} +/**********************************************************************************************/ + +/* JSL/RTL *********************************************************************************** */ +static void Op22E1 (void) +{ + AbsoluteLong (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif + PushB (ICPU.Registers.PB); + PushWENew (CPU.PC - CPU.PCBase - 1); + ICPU.Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +} + +static void Op22 (void) +{ + AbsoluteLong (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; +#endif + PushB (ICPU.Registers.PB); + PushW (CPU.PC - CPU.PCBase - 1); + ICPU.Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +} + +static void Op6BE1 (void) +{ + PullWENew (ICPU.Registers.PC); + PullB (ICPU.Registers.PB); + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + S9xSetPCBase (ICPU.ShiftedPB + ((ICPU.Registers.PC + 1) & 0xffff)); +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif +} + +static void Op6B (void) +{ + PullW (ICPU.Registers.PC); + PullB (ICPU.Registers.PB); + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + S9xSetPCBase (ICPU.ShiftedPB + ((ICPU.Registers.PC + 1) & 0xffff)); +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* JSR/RTS *********************************************************************************** */ +static void Op20 (void) +{ + Absolute (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + PushW (CPU.PC - CPU.PCBase - 1); + S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); +} + +//JSR a,x +static void OpFCE1 (void) +{ + AbsoluteIndexedIndirect (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + PushWENew (CPU.PC - CPU.PCBase - 1); + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +} + +static void OpFC (void) +{ + AbsoluteIndexedIndirect (JUMP, OpAddressPassthrough); +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; +#endif + PushW (CPU.PC - CPU.PCBase - 1); + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +} + +static void Op60 (void) +{ + PullW (ICPU.Registers.PC); + S9xSetPCBase (ICPU.ShiftedPB + ((ICPU.Registers.PC + 1) & 0xffff)); +#ifndef SA1_OPCODES + CPU.Cycles += ONE_CYCLE * 3; +#endif +} + +/**********************************************************************************************/ + +/* MVN/MVP *********************************************************************************** */ +static void Op54X1 (void) +{ + uint32 SrcBank; + +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + + ICPU.Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + OpenBus = SrcBank = *CPU.PC++; + + S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), + ICPU.ShiftedDB + ICPU.Registers.Y.W); + + ICPU.Registers.XL++; + ICPU.Registers.YL++; + ICPU.Registers.A.W--; + if (ICPU.Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +static void Op54X0 (void) +{ + uint32 SrcBank; + +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + + ICPU.Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + OpenBus = SrcBank = *CPU.PC++; + + S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), + ICPU.ShiftedDB + ICPU.Registers.Y.W); + + ICPU.Registers.X.W++; + ICPU.Registers.Y.W++; + ICPU.Registers.A.W--; + if (ICPU.Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +static void Op44X1 (void) +{ + uint32 SrcBank; + +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + ICPU.Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + OpenBus = SrcBank = *CPU.PC++; + S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), + ICPU.ShiftedDB + ICPU.Registers.Y.W); + + ICPU.Registers.XL--; + ICPU.Registers.YL--; + ICPU.Registers.A.W--; + if (ICPU.Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +static void Op44X0 (void) +{ + uint32 SrcBank; + +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + ICPU.Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + OpenBus = SrcBank = *CPU.PC++; + S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), + ICPU.ShiftedDB + ICPU.Registers.Y.W); + + ICPU.Registers.X.W--; + ICPU.Registers.Y.W--; + ICPU.Registers.A.W--; + if (ICPU.Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +/**********************************************************************************************/ + +/* REP/SEP *********************************************************************************** */ +static void OpC2 (void) +{ + uint8 Work8 = ~*CPU.PC++; + ICPU.Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + if (CheckEmulation()) + { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) + { + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ +} + +static void OpE2 (void) +{ + uint8 Work8 = *CPU.PC++; + ICPU.Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; +#ifndef SA1_OPCODES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + if (CheckEmulation()) + { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) + { + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + } + S9xFixCycles(); +} +/**********************************************************************************************/ + +/* XBA *************************************************************************************** */ +static void OpEB (void) +{ + uint8 Work8 = ICPU.Registers.AL; + ICPU.Registers.AL = ICPU.Registers.AH; + ICPU.Registers.AH = Work8; + + SetZN8 (ICPU.Registers.AL); +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* RTI *************************************************************************************** */ +static void Op40 (void) +{ + PullB (ICPU.Registers.PL); + S9xUnpackStatus (); + PullW (ICPU.Registers.PC); + if (!CheckEmulation()) + { + PullB (ICPU.Registers.PB); + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + } + else + { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); + if (CheckIndex ()) + { + ICPU.Registers.XH = 0; + ICPU.Registers.YH = 0; + } +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ +} + +/**********************************************************************************************/ + +/* STP/WAI/DB ******************************************************************************** */ +// WAI +static void OpCB (void) +{ + +// Ok, let's just C-ify the ASM versions separately. +#ifdef SA1_OPCODES + SA1.WaitingForInterrupt = TRUE; + SA1.PC--; +#if 0 +// XXX: FIXME + if(Settings.Shutdown){ + SA1.Cycles = SA1.NextEvent; + if (IAPU.APUExecuting) + { + SA1.Executing = FALSE; + do + { + APU_EXECUTE1 (, } while (APU.Cycles < SA1.NextEvent, SA1.Executing = TRUE; + } + } +#endif +#else // SA1_OPCODES +#if 0 + + + if (CPU.IRQActive) + { +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + } + else +#endif + { + CPU.WaitingForInterrupt = TRUE; + CPU.PC--; +#ifdef CPU_SHUTDOWN + if (Settings.Shutdown) + { + CPU.Cycles = CPU.NextEvent; + if (IAPU.APUExecuting) + { + ICPU.CPUExecuting = FALSE; + do + { + APU_EXECUTE1 (); + } while (APU.Cycles < CPU.NextEvent); + ICPU.CPUExecuting = TRUE; + } + } + else + { +#ifndef SA1_OPCODES + CPU.Cycles += TWO_CYCLES; +#endif + } +#endif + } +#endif // SA1_OPCODES +} + +// STP +static void OpDB (void) +{ + CPU.PC--; + CPU.Flags |= DEBUG_MODE_FLAG; +} + +// Reserved S9xOpcode +static void Op42 (void) +{ +} + +/*****************************************************************************/ + +/*****************************************************************************/ +/* CPU-S9xOpcodes Definitions */ +/*****************************************************************************/ +struct SOpcodes S9xOpcodesM1X1[256] = +{ + {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, + {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, + {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, + {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, + {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, + {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, + {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, + {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, + {Op41M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, + {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X1}, + {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, + {Op5AX1}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, + {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, + {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, + {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, + {Op78}, {Op79M1}, {Op7AX1}, {Op7B}, {Op7C}, + {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, + {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, + {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8B}, + {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90}, + {Op91M1}, {Op92M1}, {Op93M1}, {Op94X1}, {Op95M1}, + {Op96X1}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, + {Op9BX1}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, + {OpA0X1}, {OpA1M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, + {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, + {OpAAX1}, {OpAB}, {OpACX1}, {OpADM1}, {OpAEX1}, + {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, + {OpB4X1}, {OpB5M1}, {OpB6X1}, {OpB7M1}, {OpB8}, + {OpB9M1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1}, + {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1M1}, {OpC2}, + {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, + {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, + {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX1}, {OpDB}, + {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X1}, + {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, + {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, + {OpFAX1}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, + {OpFFM1} +}; + +struct SOpcodes S9xOpcodesE1[256] = +{ + {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08E1}, {Op09M1}, + {Op0AM1}, {Op0BE1}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, + {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, + {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, + {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22E1}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28}, {Op29M1}, {Op2AM1}, {Op2BE1}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, + {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, + {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, + {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, + {Op41M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48E1}, {Op49M1}, {Op4AM1}, + {Op4BE1}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X1}, + {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, + {Op5AE1}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, + {Op5FM1}, {Op60}, {Op61M1}, {Op62E1}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68E1}, + {Op69M1}, {Op6AM1}, {Op6BE1}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, + {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, + {Op78}, {Op79M1}, {Op7AE1}, {Op7B}, {Op7C}, + {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, + {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, + {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8BE1}, + {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90}, + {Op91M1}, {Op92M1}, {Op93M1}, {Op94X1}, {Op95M1}, + {Op96X1}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, + {Op9BX1}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, + {OpA0X1}, {OpA1M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, + {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, + {OpAAX1}, {OpABE1}, {OpACX1}, {OpADM1}, {OpAEX1}, + {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, + {OpB4X1}, {OpB5M1}, {OpB6X1}, {OpB7M1}, {OpB8}, + {OpB9M1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1}, + {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1M1}, {OpC2}, + {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, + {OpD2M1}, {OpD3M1}, {OpD4E1}, {OpD5M1}, {OpD6M1}, + {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAE1}, {OpDB}, + {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X1}, + {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4E1}, + {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, + {OpFAE1}, {OpFB}, {OpFCE1}, {OpFDM1}, {OpFEM1}, + {OpFFM1} +}; + +struct SOpcodes S9xOpcodesM1X0[256] = +{ + {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, + {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, + {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, + {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, + {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, + {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, + {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, + {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, + {Op41M1}, {Op42}, {Op43M1}, {Op44X0}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, + {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X0}, + {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, + {Op5AX0}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, + {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, + {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, + {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, + {Op78}, {Op79M1}, {Op7AX0}, {Op7B}, {Op7C}, + {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, + {Op82}, {Op83M1}, {Op84X0}, {Op85M1}, {Op86X0}, + {Op87M1}, {Op88X0}, {Op89M1}, {Op8AM1}, {Op8B}, + {Op8CX0}, {Op8DM1}, {Op8EX0}, {Op8FM1}, {Op90}, + {Op91M1}, {Op92M1}, {Op93M1}, {Op94X0}, {Op95M1}, + {Op96X0}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, + {Op9BX0}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, + {OpA0X0}, {OpA1M1}, {OpA2X0}, {OpA3M1}, {OpA4X0}, + {OpA5M1}, {OpA6X0}, {OpA7M1}, {OpA8X0}, {OpA9M1}, + {OpAAX0}, {OpAB}, {OpACX0}, {OpADM1}, {OpAEX0}, + {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, + {OpB4X0}, {OpB5M1}, {OpB6X0}, {OpB7M1}, {OpB8}, + {OpB9M1}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM1}, + {OpBEX0}, {OpBFM1}, {OpC0X0}, {OpC1M1}, {OpC2}, + {OpC3M1}, {OpC4X0}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X0}, {OpC9M1}, {OpCAX0}, {OpCB}, {OpCCX0}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, + {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, + {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX0}, {OpDB}, + {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X0}, + {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X0}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X0}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX0}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, + {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, + {OpFAX0}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, + {OpFFM1} +}; + +struct SOpcodes S9xOpcodesM0X0[256] = +{ + {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, + {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, + {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, + {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, + {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, + {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, + {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, + {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, + {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, + {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, + {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, + {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, + {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, + {Op41M0}, {Op42}, {Op43M0}, {Op44X0}, {Op45M0}, + {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, + {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, + {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X0}, + {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, + {Op5AX0}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, + {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, + {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, + {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, + {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, + {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, + {Op78}, {Op79M0}, {Op7AX0}, {Op7B}, {Op7C}, + {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, + {Op82}, {Op83M0}, {Op84X0}, {Op85M0}, {Op86X0}, + {Op87M0}, {Op88X0}, {Op89M0}, {Op8AM0}, {Op8B}, + {Op8CX0}, {Op8DM0}, {Op8EX0}, {Op8FM0}, {Op90}, + {Op91M0}, {Op92M0}, {Op93M0}, {Op94X0}, {Op95M0}, + {Op96X0}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, + {Op9BX0}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, + {OpA0X0}, {OpA1M0}, {OpA2X0}, {OpA3M0}, {OpA4X0}, + {OpA5M0}, {OpA6X0}, {OpA7M0}, {OpA8X0}, {OpA9M0}, + {OpAAX0}, {OpAB}, {OpACX0}, {OpADM0}, {OpAEX0}, + {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, + {OpB4X0}, {OpB5M0}, {OpB6X0}, {OpB7M0}, {OpB8}, + {OpB9M0}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM0}, + {OpBEX0}, {OpBFM0}, {OpC0X0}, {OpC1M0}, {OpC2}, + {OpC3M0}, {OpC4X0}, {OpC5M0}, {OpC6M0}, {OpC7M0}, + {OpC8X0}, {OpC9M0}, {OpCAX0}, {OpCB}, {OpCCX0}, + {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, + {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, + {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX0}, {OpDB}, + {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X0}, + {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X0}, {OpE5M0}, + {OpE6M0}, {OpE7M0}, {OpE8X0}, {OpE9M0}, {OpEA}, + {OpEB}, {OpECX0}, {OpEDM0}, {OpEEM0}, {OpEFM0}, + {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, + {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, + {OpFAX0}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, + {OpFFM0} +}; + +struct SOpcodes S9xOpcodesM0X1[256] = +{ + {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, + {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, + {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, + {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, + {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, + {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, + {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, + {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, + {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, + {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, + {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, + {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, + {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, + {Op41M0}, {Op42}, {Op43M0}, {Op44X1}, {Op45M0}, + {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, + {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, + {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X1}, + {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, + {Op5AX1}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, + {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, + {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, + {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, + {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, + {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, + {Op78}, {Op79M0}, {Op7AX1}, {Op7B}, {Op7C}, + {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, + {Op82}, {Op83M0}, {Op84X1}, {Op85M0}, {Op86X1}, + {Op87M0}, {Op88X1}, {Op89M0}, {Op8AM0}, {Op8B}, + {Op8CX1}, {Op8DM0}, {Op8EX1}, {Op8FM0}, {Op90}, + {Op91M0}, {Op92M0}, {Op93M0}, {Op94X1}, {Op95M0}, + {Op96X1}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, + {Op9BX1}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, + {OpA0X1}, {OpA1M0}, {OpA2X1}, {OpA3M0}, {OpA4X1}, + {OpA5M0}, {OpA6X1}, {OpA7M0}, {OpA8X1}, {OpA9M0}, + {OpAAX1}, {OpAB}, {OpACX1}, {OpADM0}, {OpAEX1}, + {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, + {OpB4X1}, {OpB5M0}, {OpB6X1}, {OpB7M0}, {OpB8}, + {OpB9M0}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM0}, + {OpBEX1}, {OpBFM0}, {OpC0X1}, {OpC1M0}, {OpC2}, + {OpC3M0}, {OpC4X1}, {OpC5M0}, {OpC6M0}, {OpC7M0}, + {OpC8X1}, {OpC9M0}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, + {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, + {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX1}, {OpDB}, + {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X1}, + {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X1}, {OpE5M0}, + {OpE6M0}, {OpE7M0}, {OpE8X1}, {OpE9M0}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM0}, {OpEEM0}, {OpEFM0}, + {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, + {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, + {OpFAX1}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, + {OpFFM0} +}; + diff --git a/source/cpuops.cpp b/source/cpuops.cpp deleted file mode 100644 index 9dc7f0c..0000000 --- a/source/cpuops.cpp +++ /dev/null @@ -1,5307 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -/*****************************************************************************/ -/* CPU-S9xOpcodes.CPP */ -/* This file contains all the opcodes */ -/*****************************************************************************/ - -#include "snes9x.h" -#include "memmap.h" -#include "missing.h" -#include "apu.h" -#include "sa1.h" -#include "spc7110.h" - -#include "cpuexec.h" -#include "cpuaddr.h" -#include "cpuops.h" -#include "cpumacro.h" -#include "apu.h" - -EXTERN_C long OpAddress; - -// For use with the opcodes whose functions here examine the OpAddress. -static void OpAddressPassthrough (long Addr) -{ - OpAddress = Addr; -} - -/* ADC *************************************************************************************** */ -static void Op69M1 (void) -{ - Immediate8 (READ, ADC8); -} - -static void Op69M0 (void) -{ - Immediate16 (READ, ADC16); -} - -static void Op65M1 (void) -{ - Direct (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op65M0 (void) -{ - Direct (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op75M1 (void) -{ - DirectIndexedX (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op75M0 (void) -{ - DirectIndexedX (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op72M1 (void) -{ - DirectIndirect (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op72M0 (void) -{ - DirectIndirect (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op61M1 (void) -{ - DirectIndexedIndirect (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op61M0 (void) -{ - DirectIndexedIndirect (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op71M1 (void) -{ - DirectIndirectIndexed (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op71M0 (void) -{ - DirectIndirectIndexed (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op67M1 (void) -{ - DirectIndirectLong (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op67M0 (void) -{ - DirectIndirectLong (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op77M1 (void) -{ - DirectIndirectIndexedLong (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op77M0 (void) -{ - DirectIndirectIndexedLong (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op6DM1 (void) -{ - Absolute (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op6DM0 (void) -{ - Absolute (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op7DM1 (void) -{ - AbsoluteIndexedX (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op7DM0 (void) -{ - AbsoluteIndexedX (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op79M1 (void) -{ - AbsoluteIndexedY (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op79M0 (void) -{ - AbsoluteIndexedY (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op6FM1 (void) -{ - AbsoluteLong (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op6FM0 (void) -{ - AbsoluteLong (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op7FM1 (void) -{ - AbsoluteLongIndexedX (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op7FM0 (void) -{ - AbsoluteLongIndexedX (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op63M1 (void) -{ - StackRelative (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op63M0 (void) -{ - StackRelative (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op73M1 (void) -{ - StackRelativeIndirectIndexed (READ, ADC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void Op73M0 (void) -{ - StackRelativeIndirectIndexed (READ, ADC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -/**********************************************************************************************/ - -/* AND *************************************************************************************** */ -static void Op29M1 (void) -{ - ICPU.Registers.AL &= *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (ICPU.Registers.AL); -} - -static void Op29M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU.Registers.A.W &= *(uint16 *) CPU.PC; -#else - ICPU.Registers.A.W &= *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (ICPU.Registers.A.W); -} - -static void Op25M1 (void) -{ - Direct (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op25M0 (void) -{ - Direct (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op35M1 (void) -{ - DirectIndexedX (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op35M0 (void) -{ - DirectIndexedX (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op32M1 (void) -{ - DirectIndirect (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op32M0 (void) -{ - DirectIndirect (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op21M1 (void) -{ - DirectIndexedIndirect (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op21M0 (void) -{ - DirectIndexedIndirect (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op31M1 (void) -{ - DirectIndirectIndexed (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op31M0 (void) -{ - DirectIndirectIndexed (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op27M1 (void) -{ - DirectIndirectLong (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op27M0 (void) -{ - DirectIndirectLong (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op37M1 (void) -{ - DirectIndirectIndexedLong (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op37M0 (void) -{ - DirectIndirectIndexedLong (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op2DM1 (void) -{ - Absolute (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op2DM0 (void) -{ - Absolute (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op3DM1 (void) -{ - AbsoluteIndexedX (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op3DM0 (void) -{ - AbsoluteIndexedX (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op39M1 (void) -{ - AbsoluteIndexedY (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op39M0 (void) -{ - AbsoluteIndexedY (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op2FM1 (void) -{ - AbsoluteLong (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op2FM0 (void) -{ - AbsoluteLong (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op3FM1 (void) -{ - AbsoluteLongIndexedX (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op3FM0 (void) -{ - AbsoluteLongIndexedX (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op23M1 (void) -{ - StackRelative (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op23M0 (void) -{ - StackRelative (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op33M1 (void) -{ - StackRelativeIndirectIndexed (READ, AND8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void Op33M0 (void) -{ - StackRelativeIndirectIndexed (READ, AND16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* ASL *************************************************************************************** */ -static void Op0AM1 (void) -{ - A_ASL8 (); -} - -static void Op0AM0 (void) -{ - A_ASL16 (); -} - -static void Op06M1 (void) -{ - Direct (MODIFY, ASL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op06M0 (void) -{ - Direct (MODIFY, ASL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op16M1 (void) -{ - DirectIndexedX (MODIFY, ASL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op16M0 (void) -{ - DirectIndexedX (MODIFY, ASL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op0EM1 (void) -{ - Absolute (MODIFY, ASL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op0EM0 (void) -{ - Absolute (MODIFY, ASL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op1EM1 (void) -{ - AbsoluteIndexedX (MODIFY, ASL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op1EM0 (void) -{ - AbsoluteIndexedX (MODIFY, ASL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} -/**********************************************************************************************/ - -/* BIT *************************************************************************************** */ -static void Op89M1 (void) -{ - ICPU._Zero = ICPU.Registers.AL & *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op89M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU._Zero = (ICPU.Registers.A.W & *(uint16 *) CPU.PC) != 0; -#else - ICPU._Zero = (ICPU.Registers.A.W & (*CPU.PC + (*(CPU.PC + 1) << 8))) != 0; -#endif -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - CPU.PC += 2; -} - -static void Op24M1 (void) -{ - Direct (READ, BIT8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op24M0 (void) -{ - Direct (READ, BIT16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op34M1 (void) -{ - DirectIndexedX (READ, BIT8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op34M0 (void) -{ - DirectIndexedX (READ, BIT16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op2CM1 (void) -{ - Absolute (READ, BIT8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op2CM0 (void) -{ - Absolute (READ, BIT16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op3CM1 (void) -{ - AbsoluteIndexedX (READ, BIT8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op3CM0 (void) -{ - AbsoluteIndexedX (READ, BIT16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} -/**********************************************************************************************/ - -/* CMP *************************************************************************************** */ -static void OpC9M1 (void) -{ - int32 Int32 = (int) ICPU.Registers.AL - (intptr_t) *CPU.PC++; - ICPU._Carry = Int32 >= 0; - SetZN8 ((uint8) Int32); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC9M0 (void) -{ - int32 Int32; -#ifdef FAST_LSB_WORD_ACCESS - Int32 = (long) ICPU.Registers.A.W - (long) *(uint16 *) CPU.PC; -#else - Int32 = (long) ICPU.Registers.A.W - - (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); -#endif - ICPU._Carry = Int32 >= 0; - SetZN16 ((uint16) Int32); - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpC5M1 (void) -{ - Direct (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC5M0 (void) -{ - Direct (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpD5M1 (void) -{ - DirectIndexedX (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpD5M0 (void) -{ - DirectIndexedX (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpD2M1 (void) -{ - DirectIndirect (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpD2M0 (void) -{ - DirectIndirect (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC1M1 (void) -{ - DirectIndexedIndirect (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC1M0 (void) -{ - DirectIndexedIndirect (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpD1M1 (void) -{ - DirectIndirectIndexed (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpD1M0 (void) -{ - DirectIndirectIndexed (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC7M1 (void) -{ - DirectIndirectLong (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC7M0 (void) -{ - DirectIndirectLong (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpD7M1 (void) -{ - DirectIndirectIndexedLong (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpD7M0 (void) -{ - DirectIndirectIndexedLong (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpCDM1 (void) -{ - Absolute (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpCDM0 (void) -{ - Absolute (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpDDM1 (void) -{ - AbsoluteIndexedX (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpDDM0 (void) -{ - AbsoluteIndexedX (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpD9M1 (void) -{ - AbsoluteIndexedY (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpD9M0 (void) -{ - AbsoluteIndexedY (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpCFM1 (void) -{ - AbsoluteLong (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpCFM0 (void) -{ - AbsoluteLong (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpDFM1 (void) -{ - AbsoluteLongIndexedX (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpDFM0 (void) -{ - AbsoluteLongIndexedX (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpC3M1 (void) -{ - StackRelative (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void OpC3M0 (void) -{ - StackRelative (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void OpD3M1 (void) -{ - StackRelativeIndirectIndexed (READ, CMP8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void OpD3M0 (void) -{ - StackRelativeIndirectIndexed (READ, CMP16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -/**********************************************************************************************/ - -/* CMX *************************************************************************************** */ -static void OpE0X1 (void) -{ - int32 Int32 = (int) ICPU.Registers.XL - (intptr_t) *CPU.PC++; - ICPU._Carry = Int32 >= 0; - SetZN8 ((uint8) Int32); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE0X0 (void) -{ - int32 Int32; -#ifdef FAST_LSB_WORD_ACCESS - Int32 = (long) ICPU.Registers.X.W - (long) *(uint16 *) CPU.PC; -#else - Int32 = (long) ICPU.Registers.X.W - - (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); -#endif - ICPU._Carry = Int32 >= 0; - SetZN16 ((uint16) Int32); - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpE4X1 (void) -{ - Direct (READ, CMX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE4X0 (void) -{ - Direct (READ, CMX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpECX1 (void) -{ - Absolute (READ, CMX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpECX0 (void) -{ - Absolute (READ, CMX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -/**********************************************************************************************/ - -/* CMY *************************************************************************************** */ -static void OpC0X1 (void) -{ - int32 Int32 = (int) ICPU.Registers.YL - (intptr_t) *CPU.PC++; - ICPU._Carry = Int32 >= 0; - SetZN8 ((uint8) Int32); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC0X0 (void) -{ - int32 Int32; -#ifdef FAST_LSB_WORD_ACCESS - Int32 = (long) ICPU.Registers.Y.W - (long) *(uint16 *) CPU.PC; -#else - Int32 = (long) ICPU.Registers.Y.W - - (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); -#endif - ICPU._Carry = Int32 >= 0; - SetZN16 ((uint16) Int32); - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpC4X1 (void) -{ - Direct (READ, CMY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC4X0 (void) -{ - Direct (READ, CMY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpCCX1 (void) -{ - Absolute (READ, CMY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpCCX0 (void) -{ - Absolute (READ, CMY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -/**********************************************************************************************/ - -/* DEC *************************************************************************************** */ -static void Op3AM1 (void) -{ - A_DEC8 (); -} - -static void Op3AM0 (void) -{ - A_DEC16 (); -} - -static void OpC6M1 (void) -{ - Direct (MODIFY, DEC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpC6M0 (void) -{ - Direct (MODIFY, DEC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpD6M1 (void) -{ - DirectIndexedX (MODIFY, DEC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpD6M0 (void) -{ - DirectIndexedX (MODIFY, DEC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpCEM1 (void) -{ - Absolute (MODIFY, DEC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpCEM0 (void) -{ - Absolute (MODIFY, DEC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpDEM1 (void) -{ - AbsoluteIndexedX (MODIFY, DEC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpDEM0 (void) -{ - AbsoluteIndexedX (MODIFY, DEC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -/**********************************************************************************************/ - -/* EOR *************************************************************************************** */ -static void Op49M1 (void) -{ - ICPU.Registers.AL ^= *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (ICPU.Registers.AL); -} - -static void Op49M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU.Registers.A.W ^= *(uint16 *) CPU.PC; -#else - ICPU.Registers.A.W ^= *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (ICPU.Registers.A.W); -} - -static void Op45M1 (void) -{ - Direct (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op45M0 (void) -{ - Direct (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op55M1 (void) -{ - DirectIndexedX (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op55M0 (void) -{ - DirectIndexedX (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op52M1 (void) -{ - DirectIndirect (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op52M0 (void) -{ - DirectIndirect (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op41M1 (void) -{ - DirectIndexedIndirect (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op41M0 (void) -{ - DirectIndexedIndirect (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op51M1 (void) -{ - DirectIndirectIndexed (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op51M0 (void) -{ - DirectIndirectIndexed (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op47M1 (void) -{ - DirectIndirectLong (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op47M0 (void) -{ - DirectIndirectLong (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op57M1 (void) -{ - DirectIndirectIndexedLong (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op57M0 (void) -{ - DirectIndirectIndexedLong (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op4DM1 (void) -{ - Absolute (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op4DM0 (void) -{ - Absolute (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op5DM1 (void) -{ - AbsoluteIndexedX (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op5DM0 (void) -{ - AbsoluteIndexedX (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op59M1 (void) -{ - AbsoluteIndexedY (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op59M0 (void) -{ - AbsoluteIndexedY (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op4FM1 (void) -{ - AbsoluteLong (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op4FM0 (void) -{ - AbsoluteLong (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op5FM1 (void) -{ - AbsoluteLongIndexedX (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op5FM0 (void) -{ - AbsoluteLongIndexedX (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op43M1 (void) -{ - StackRelative (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op43M0 (void) -{ - StackRelative (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op53M1 (void) -{ - StackRelativeIndirectIndexed (READ, EOR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void Op53M0 (void) -{ - StackRelativeIndirectIndexed (READ, EOR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -/**********************************************************************************************/ - -/* INC *************************************************************************************** */ -static void Op1AM1 (void) -{ - A_INC8 (); -} - -static void Op1AM0 (void) -{ - A_INC16 (); -} - -static void OpE6M1 (void) -{ - Direct (MODIFY, INC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpE6M0 (void) -{ - Direct (MODIFY, INC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpF6M1 (void) -{ - DirectIndexedX (MODIFY, INC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpF6M0 (void) -{ - DirectIndexedX (MODIFY, INC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpEEM1 (void) -{ - Absolute (MODIFY, INC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpEEM0 (void) -{ - Absolute (MODIFY, INC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpFEM1 (void) -{ - AbsoluteIndexedX (MODIFY, INC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void OpFEM0 (void) -{ - AbsoluteIndexedX (MODIFY, INC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -/**********************************************************************************************/ -/* LDA *************************************************************************************** */ -static void OpA9M1 (void) -{ - ICPU.Registers.AL = *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (ICPU.Registers.AL); -} - -static void OpA9M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU.Registers.A.W = *(uint16 *) CPU.PC; -#else - ICPU.Registers.A.W = *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (ICPU.Registers.A.W); -} - -static void OpA5M1 (void) -{ - Direct (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA5M0 (void) -{ - Direct (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB5M1 (void) -{ - DirectIndexedX (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpB5M0 (void) -{ - DirectIndexedX (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpB2M1 (void) -{ - DirectIndirect (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB2M0 (void) -{ - DirectIndirect (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA1M1 (void) -{ - DirectIndexedIndirect (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA1M0 (void) -{ - DirectIndexedIndirect (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB1M1 (void) -{ - DirectIndirectIndexed (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB1M0 (void) -{ - DirectIndirectIndexed (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA7M1 (void) -{ - DirectIndirectLong (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA7M0 (void) -{ - DirectIndirectLong (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB7M1 (void) -{ - DirectIndirectIndexedLong (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB7M0 (void) -{ - DirectIndirectIndexedLong (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpADM1 (void) -{ - Absolute (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpADM0 (void) -{ - Absolute (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpBDM1 (void) -{ - AbsoluteIndexedX (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpBDM0 (void) -{ - AbsoluteIndexedX (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpB9M1 (void) -{ - AbsoluteIndexedY (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpB9M0 (void) -{ - AbsoluteIndexedY (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpAFM1 (void) -{ - AbsoluteLong (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpAFM0 (void) -{ - AbsoluteLong (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpBFM1 (void) -{ - AbsoluteLongIndexedX (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpBFM0 (void) -{ - AbsoluteLongIndexedX (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpA3M1 (void) -{ - StackRelative (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void OpA3M0 (void) -{ - StackRelative (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void OpB3M1 (void) -{ - StackRelativeIndirectIndexed (READ, LDA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void OpB3M0 (void) -{ - StackRelativeIndirectIndexed (READ, LDA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -/**********************************************************************************************/ - -/* LDX *************************************************************************************** */ -static void OpA2X1 (void) -{ - ICPU.Registers.XL = *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (ICPU.Registers.XL); -} - -static void OpA2X0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU.Registers.X.W = *(uint16 *) CPU.PC; -#else - ICPU.Registers.X.W = *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (ICPU.Registers.X.W); -} - -static void OpA6X1 (void) -{ - Direct (READ, LDX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA6X0 (void) -{ - Direct (READ, LDX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB6X1 (void) -{ - DirectIndexedY (READ, LDX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpB6X0 (void) -{ - DirectIndexedY (READ, LDX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpAEX1 (void) -{ - Absolute (READ, LDX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpAEX0 (void) -{ - Absolute (READ, LDX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpBEX1 (void) -{ - AbsoluteIndexedY (READ, LDX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpBEX0 (void) -{ - AbsoluteIndexedY (READ, LDX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} -/**********************************************************************************************/ - -/* LDY *************************************************************************************** */ -static void OpA0X1 (void) -{ - ICPU.Registers.YL = *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (ICPU.Registers.YL); -} - -static void OpA0X0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU.Registers.Y.W = *(uint16 *) CPU.PC; -#else - ICPU.Registers.Y.W = *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (ICPU.Registers.Y.W); -} - -static void OpA4X1 (void) -{ - Direct (READ, LDY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpA4X0 (void) -{ - Direct (READ, LDY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpB4X1 (void) -{ - DirectIndexedX (READ, LDY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpB4X0 (void) -{ - DirectIndexedX (READ, LDY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpACX1 (void) -{ - Absolute (READ, LDY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpACX0 (void) -{ - Absolute (READ, LDY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpBCX1 (void) -{ - AbsoluteIndexedX (READ, LDY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpBCX0 (void) -{ - AbsoluteIndexedX (READ, LDY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} -/**********************************************************************************************/ - -/* LSR *************************************************************************************** */ -static void Op4AM1 (void) -{ - A_LSR8 (); -} - -static void Op4AM0 (void) -{ - A_LSR16 (); -} - -static void Op46M1 (void) -{ - Direct (MODIFY, LSR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op46M0 (void) -{ - Direct (MODIFY, LSR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op56M1 (void) -{ - DirectIndexedX (MODIFY, LSR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op56M0 (void) -{ - DirectIndexedX (MODIFY, LSR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op4EM1 (void) -{ - Absolute (MODIFY, LSR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op4EM0 (void) -{ - Absolute (MODIFY, LSR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op5EM1 (void) -{ - AbsoluteIndexedX (MODIFY, LSR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op5EM0 (void) -{ - AbsoluteIndexedX (MODIFY, LSR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -/**********************************************************************************************/ - -/* ORA *************************************************************************************** */ -static void Op09M1 (void) -{ - ICPU.Registers.AL |= *CPU.PC++; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (ICPU.Registers.AL); -} - -static void Op09M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU.Registers.A.W |= *(uint16 *) CPU.PC; -#else - ICPU.Registers.A.W |= *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (ICPU.Registers.A.W); -} - -static void Op05M1 (void) -{ - Direct (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op05M0 (void) -{ - Direct (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op15M1 (void) -{ - DirectIndexedX (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op15M0 (void) -{ - DirectIndexedX (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op12M1 (void) -{ - DirectIndirect (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op12M0 (void) -{ - DirectIndirect (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op01M1 (void) -{ - DirectIndexedIndirect (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op01M0 (void) -{ - DirectIndexedIndirect (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op11M1 (void) -{ - DirectIndirectIndexed (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op11M0 (void) -{ - DirectIndirectIndexed (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op07M1 (void) -{ - DirectIndirectLong (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op07M0 (void) -{ - DirectIndirectLong (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op17M1 (void) -{ - DirectIndirectIndexedLong (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op17M0 (void) -{ - DirectIndirectIndexedLong (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op0DM1 (void) -{ - Absolute (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op0DM0 (void) -{ - Absolute (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op1DM1 (void) -{ - AbsoluteIndexedX (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op1DM0 (void) -{ - AbsoluteIndexedX (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op19M1 (void) -{ - AbsoluteIndexedY (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op19M0 (void) -{ - AbsoluteIndexedY (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op0FM1 (void) -{ - AbsoluteLong (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op0FM0 (void) -{ - AbsoluteLong (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op1FM1 (void) -{ - AbsoluteLongIndexedX (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op1FM0 (void) -{ - AbsoluteLongIndexedX (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op03M1 (void) -{ - StackRelative (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op03M0 (void) -{ - StackRelative (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op13M1 (void) -{ - StackRelativeIndirectIndexed (READ, ORA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void Op13M0 (void) -{ - StackRelativeIndirectIndexed (READ, ORA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -/**********************************************************************************************/ - -/* ROL *************************************************************************************** */ -static void Op2AM1 (void) -{ - A_ROL8 (); -} - -static void Op2AM0 (void) -{ - A_ROL16 (); -} - -static void Op26M1 (void) -{ - Direct (MODIFY, ROL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op26M0 (void) -{ - Direct (MODIFY, ROL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op36M1 (void) -{ - DirectIndexedX (MODIFY, ROL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op36M0 (void) -{ - DirectIndexedX (MODIFY, ROL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op2EM1 (void) -{ - Absolute (MODIFY, ROL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op2EM0 (void) -{ - Absolute (MODIFY, ROL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op3EM1 (void) -{ - AbsoluteIndexedX (MODIFY, ROL8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op3EM0 (void) -{ - AbsoluteIndexedX (MODIFY, ROL16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} -/**********************************************************************************************/ - -/* ROR *************************************************************************************** */ -static void Op6AM1 (void) -{ - A_ROR8 (); -} - -static void Op6AM0 (void) -{ - A_ROR16 (); -} - -static void Op66M1 (void) -{ - Direct (MODIFY, ROR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op66M0 (void) -{ - Direct (MODIFY, ROR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op76M1 (void) -{ - DirectIndexedX (MODIFY, ROR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op76M0 (void) -{ - DirectIndexedX (MODIFY, ROR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE /* memory */ + ONE_CYCLE /* opcode */; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op6EM1 (void) -{ - Absolute (MODIFY, ROR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op6EM0 (void) -{ - Absolute (MODIFY, ROR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op7EM1 (void) -{ - AbsoluteIndexedX (MODIFY, ROR8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op7EM0 (void) -{ - AbsoluteIndexedX (MODIFY, ROR16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} -/**********************************************************************************************/ - -/* SBC *************************************************************************************** */ -static void OpE9M1 (void) -{ - Immediate8 (READ, SBC8); -} - -static void OpE9M0 (void) -{ - Immediate16 (READ, SBC16); -} - -static void OpE5M1 (void) -{ - Direct (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE5M0 (void) -{ - Direct (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpF5M1 (void) -{ - DirectIndexedX (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpF5M0 (void) -{ - DirectIndexedX (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpF2M1 (void) -{ - DirectIndirect (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpF2M0 (void) -{ - DirectIndirect (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE1M1 (void) -{ - DirectIndexedIndirect (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE1M0 (void) -{ - DirectIndexedIndirect (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpF1M1 (void) -{ - DirectIndirectIndexed (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpF1M0 (void) -{ - DirectIndirectIndexed (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE7M1 (void) -{ - DirectIndirectLong (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE7M0 (void) -{ - DirectIndirectLong (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpF7M1 (void) -{ - DirectIndirectIndexedLong (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpF7M0 (void) -{ - DirectIndirectIndexedLong (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpEDM1 (void) -{ - Absolute (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpEDM0 (void) -{ - Absolute (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpFDM1 (void) -{ - AbsoluteIndexedX (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpFDM0 (void) -{ - AbsoluteIndexedX (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpF9M1 (void) -{ - AbsoluteIndexedY (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpF9M0 (void) -{ - AbsoluteIndexedY (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpEFM1 (void) -{ - AbsoluteLong (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpEFM0 (void) -{ - AbsoluteLong (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpFFM1 (void) -{ - AbsoluteLongIndexedX (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpFFM0 (void) -{ - AbsoluteLongIndexedX (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void OpE3M1 (void) -{ - StackRelative (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void OpE3M0 (void) -{ - StackRelative (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void OpF3M1 (void) -{ - StackRelativeIndirectIndexed (READ, SBC8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void OpF3M0 (void) -{ - StackRelativeIndirectIndexed (READ, SBC16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* STA *************************************************************************************** */ -static void Op85M1 (void) -{ - Direct (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op85M0 (void) -{ - Direct (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op95M1 (void) -{ - DirectIndexedX (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op95M0 (void) -{ - DirectIndexedX (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op92M1 (void) -{ - DirectIndirect (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op92M0 (void) -{ - DirectIndirect (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op81M1 (void) -{ - DirectIndexedIndirect (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -#ifdef noVAR_CYCLES - if (CheckIndex ()) - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op81M0 (void) -{ - DirectIndexedIndirect (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -#ifdef noVAR_CYCLES - if (CheckIndex ()) - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op91M1 (void) -{ - DirectIndirectIndexed (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op91M0 (void) -{ - DirectIndirectIndexed (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op87M1 (void) -{ - DirectIndirectLong (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op87M0 (void) -{ - DirectIndirectLong (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op97M1 (void) -{ - DirectIndirectIndexedLong (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op97M0 (void) -{ - DirectIndirectIndexedLong (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op8DM1 (void) -{ - Absolute (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op8DM0 (void) -{ - Absolute (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op9DM1 (void) -{ - AbsoluteIndexedX (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op9DM0 (void) -{ - AbsoluteIndexedX (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op99M1 (void) -{ - AbsoluteIndexedY (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op99M0 (void) -{ - AbsoluteIndexedY (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op8FM1 (void) -{ - AbsoluteLong (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op8FM0 (void) -{ - AbsoluteLong (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op9FM1 (void) -{ - AbsoluteLongIndexedX (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op9FM0 (void) -{ - AbsoluteLongIndexedX (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif -} - -static void Op83M1 (void) -{ - StackRelative (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op83M0 (void) -{ - StackRelative (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif -} - -static void Op93M1 (void) -{ - StackRelativeIndirectIndexed (WRITE, STA8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} - -static void Op93M0 (void) -{ - StackRelativeIndirectIndexed (WRITE, STA16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* STX *************************************************************************************** */ -static void Op86X1 (void) -{ - Direct (WRITE, STX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op86X0 (void) -{ - Direct (WRITE, STX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op96X1 (void) -{ - DirectIndexedY (WRITE, STX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op96X0 (void) -{ - DirectIndexedY (WRITE, STX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op8EX1 (void) -{ - Absolute (WRITE, STX8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op8EX0 (void) -{ - Absolute (WRITE, STX16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} -/**********************************************************************************************/ - -/* STY *************************************************************************************** */ -static void Op84X1 (void) -{ - Direct (WRITE, STY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op84X0 (void) -{ - Direct (WRITE, STY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op94X1 (void) -{ - DirectIndexedX (WRITE, STY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op94X0 (void) -{ - DirectIndexedX (WRITE, STY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op8CX1 (void) -{ - Absolute (WRITE, STY8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op8CX0 (void) -{ - Absolute (WRITE, STY16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} -/**********************************************************************************************/ - -/* STZ *************************************************************************************** */ -static void Op64M1 (void) -{ - Direct (WRITE, STZ8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op64M0 (void) -{ - Direct (WRITE, STZ16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op74M1 (void) -{ - DirectIndexedX (WRITE, STZ8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op74M0 (void) -{ - DirectIndexedX (WRITE, STZ16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -// if (ICPU.Registers.DL != 0) -// CPU.Cycles += TWO_CYCLES; -// else -// CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op9CM1 (void) -{ - Absolute (WRITE, STZ8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op9CM0 (void) -{ - Absolute (WRITE, STZ16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op9EM1 (void) -{ - AbsoluteIndexedX (WRITE, STZ8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void Op9EM0 (void) -{ - AbsoluteIndexedX (WRITE, STZ16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -/**********************************************************************************************/ - -/* TRB *************************************************************************************** */ -static void Op14M1 (void) -{ - Direct (MODIFY, TRB8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op14M0 (void) -{ - Direct (MODIFY, TRB16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op1CM1 (void) -{ - Absolute (MODIFY, TRB8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op1CM0 (void) -{ - Absolute (MODIFY, TRB16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} -/**********************************************************************************************/ - -/* TSB *************************************************************************************** */ -static void Op04M1 (void) -{ - Direct (MODIFY, TSB8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op04M0 (void) -{ - Direct (MODIFY, TSB16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op0CM1 (void) -{ - Absolute (MODIFY, TSB8); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -static void Op0CM0 (void) -{ - Absolute (MODIFY, TSB16); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 /* memory */ + ONE_CYCLE /* opcode */; -#endif -} - -/**********************************************************************************************/ - -/* Branch Instructions *********************************************************************** */ -#ifndef SA1_OPCODES -#define BranchCheck0()\ - if( CPU.BranchSkip)\ - {\ - CPU.BranchSkip = FALSE;\ - if (!Settings.SoundSkipMethod)\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - } - -#define BranchCheck1()\ - if( CPU.BranchSkip)\ - {\ - CPU.BranchSkip = FALSE;\ - if (!Settings.SoundSkipMethod) {\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - } else \ - if (Settings.SoundSkipMethod == 1)\ - return;\ - if (Settings.SoundSkipMethod == 3)\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - else\ - CPU.PC = CPU.PCBase + OpAddress;\ - } - -#define BranchCheck2()\ - if( CPU.BranchSkip)\ - {\ - CPU.BranchSkip = FALSE;\ - if (!Settings.SoundSkipMethod) {\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - } else \ - if (Settings.SoundSkipMethod == 1)\ - CPU.PC = CPU.PCBase + OpAddress;\ - if (Settings.SoundSkipMethod == 3)\ - if (CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - else\ - CPU.PC = CPU.PCBase + OpAddress;\ - } -#else -#define BranchCheck0() -#define BranchCheck1() -#define BranchCheck2() -#endif - -#ifdef CPU_SHUTDOWN -#ifndef SA1_OPCODES -inline void CPUShutdown() -{ - if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) - { - // Don't skip cycles with a pending NMI or IRQ - could cause delayed - // interrupt. Interrupts are delayed for a few cycles already, but - // the delay could allow the shutdown code to cycle skip again. - // Was causing screen flashing on Top Gear 3000. - - if (CPU.WaitCounter == 0 && - !(CPU.Flags & (IRQ_PENDING_FLAG | NMI_FLAG))) - { - CPU.WaitAddress = NULL; - if (Settings.SA1) - S9xSA1ExecuteDuringSleep (); - CPU.Cycles = CPU.NextEvent; - if (IAPU.APUExecuting) - { - ICPU.CPUExecuting = FALSE; - do - { - APU_EXECUTE1(); - } while (APU.Cycles < CPU.NextEvent); - ICPU.CPUExecuting = TRUE; - } - } - else - if (CPU.WaitCounter >= 2) - CPU.WaitCounter = 1; - else - CPU.WaitCounter--; - } -} -#else -inline void CPUShutdown() -{ - if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) - { - if (CPU.WaitCounter >= 1) - { - SA1.Executing = FALSE; - SA1.CPUExecuting = FALSE; - } - else - CPU.WaitCounter++; - } -} -#endif -#else -#define CPUShutdown() -#endif - -/* BCC */ -static void Op90 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck0 (); - if (!CheckCarry ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown(); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BCS */ -static void OpB0 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck0 (); - if (CheckCarry ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BEQ */ -static void OpF0 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck2 (); - if (CheckZero ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BMI */ -static void Op30 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck1 (); - if (CheckNegative ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BNE */ -static void OpD0 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck1 (); - if (!CheckZero ()) - { - CPU.PC = CPU.PCBase + OpAddress; - -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BPL */ -static void Op10 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck1 (); - if (!CheckNegative ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BRA */ -static void Op80 (void) -{ - Relative (JUMP, OpAddressPassthrough); - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); -} - -/* BVC */ -static void Op50 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck0 (); - if (!CheckOverflow ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} - -/* BVS */ -static void Op70 (void) -{ - Relative (JUMP, OpAddressPassthrough); - BranchCheck0 (); - if (CheckOverflow ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - CPUShutdown (); - } -#ifndef SA1_OPCODES - else - { - CPU.Cycles += CPU.MemSpeed; - } -#endif -} -/**********************************************************************************************/ - -/* ClearFlag Instructions ******************************************************************** */ -/* CLC */ -static void Op18 (void) -{ - ClearCarry (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -/* CLD */ -static void OpD8 (void) -{ - ClearDecimal (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -/* CLI */ -static void Op58 (void) -{ - ClearIRQ (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -/* CHECK_FOR_IRQ(); */ -} - -/* CLV */ -static void OpB8 (void) -{ - ClearOverflow (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* DEX/DEY *********************************************************************************** */ -static void OpCAX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.XL--; - SetZN8 (ICPU.Registers.XL); -} - -static void OpCAX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.X.W--; - SetZN16 (ICPU.Registers.X.W); -} - -static void Op88X1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.YL--; - SetZN8 (ICPU.Registers.YL); -} - -static void Op88X0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.Y.W--; - SetZN16 (ICPU.Registers.Y.W); -} -/**********************************************************************************************/ - -/* INX/INY *********************************************************************************** */ -static void OpE8X1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.XL++; - SetZN8 (ICPU.Registers.XL); -} - -static void OpE8X0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.X.W++; - SetZN16 (ICPU.Registers.X.W); -} - -static void OpC8X1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.YL++; - SetZN8 (ICPU.Registers.YL); -} - -static void OpC8X0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - ICPU.Registers.Y.W++; - SetZN16 (ICPU.Registers.Y.W); -} - -/**********************************************************************************************/ - -/* NOP *************************************************************************************** */ -static void OpEA (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* PUSH Instructions ************************************************************************* */ -/* #define PushW(w) \ - * S9xSetWord (w, ICPU.Registers.S.W - 1);\ - * ICPU.Registers.S.W -= 2; - */ -#define PushB(b)\ - S9xSetByte (b, ICPU.Registers.S.W--); - -#define PushBE(b)\ - S9xSetByte (b, ICPU.Registers.S.W--);\ - ICPU.Registers.SH=0x01; - - -#define PushW(w) \ - S9xSetByte ((w)>>8, ICPU.Registers.S.W);\ - S9xSetByte ((w)&0xff, (ICPU.Registers.S.W - 1)&0xFFFF);\ - ICPU.Registers.S.W -= 2; - -#define PushWE(w) \ - S9xSetByte ((w)>>8, ICPU.Registers.S.W--);\ - ICPU.Registers.SH=0x01;\ - S9xSetByte ((w)&0xff, (ICPU.Registers.S.W--)&0xFFFF);\ - ICPU.Registers.SH = 0x01; - -#define PushWENew(w) \ - S9xSetByte ((w)>>8, ICPU.Registers.S.W--);\ - S9xSetByte ((w)&0xff, (ICPU.Registers.S.W--)&0xFFFF);\ - ICPU.Registers.SH = 0x01; - -//PEA NL -static void OpF4E1 (void) -{ - Absolute (NONE, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - PushWENew ((unsigned short)OpAddress); -} - -static void OpF4 (void) -{ - Absolute (NONE, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - PushW ((unsigned short)OpAddress); -} - -//PEI NL -static void OpD4E1 (void) -{ - DirectIndirect (NONE, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - PushWENew ((unsigned short)OpAddress); -} - -static void OpD4 (void) -{ - DirectIndirect (NONE, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed; -#endif - PushW ((unsigned short)OpAddress); -} - -//PER NL -static void Op62E1 (void) -{ - RelativeLong (NONE, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - PushWENew ((unsigned short)OpAddress); -} - -static void Op62 (void) -{ - RelativeLong (NONE, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - PushW ((unsigned short)OpAddress); -} - - -//PHA -static void Op48E1 (void) -{ - PushBE (ICPU.Registers.AL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op48M1 (void) -{ - PushB (ICPU.Registers.AL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op48M0 (void) -{ - PushW (ICPU.Registers.A.W); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -//PHB -static void Op8BE1 (void) -{ - PushBE (ICPU.Registers.DB); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} -static void Op8B (void) -{ - PushB (ICPU.Registers.DB); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -//PHD NL -static void Op0BE1 (void) -{ - PushWENew (ICPU.Registers.D.W); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op0B (void) -{ - PushW (ICPU.Registers.D.W); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -//PHK -static void Op4BE1 (void) -{ - PushBE (ICPU.Registers.PB); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op4B (void) -{ - PushB (ICPU.Registers.PB); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -//PHP -static void Op08E1 (void) -{ - S9xPackStatus (); - PushBE (ICPU.Registers.PL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op08 (void) -{ - S9xPackStatus (); - PushB (ICPU.Registers.PL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -//PHX -static void OpDAE1 (void) -{ - PushBE (ICPU.Registers.XL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpDAX1 (void) -{ - PushB (ICPU.Registers.XL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpDAX0 (void) -{ - PushW (ICPU.Registers.X.W); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -//PHY -static void Op5AE1 (void) -{ - PushBE (ICPU.Registers.YL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op5AX1 (void) -{ - PushB (ICPU.Registers.YL); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op5AX0 (void) -{ - PushW (ICPU.Registers.Y.W); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* PULL Instructions ************************************************************************* */ -#define PullW(w) \ - w = S9xGetByte (++ICPU.Registers.S.W); \ - w |= (S9xGetByte (++ICPU.Registers.S.W)<<8); - -/* w = S9xGetWord (ICPU.Registers.S.W + 1); \ - ICPU.Registers.S.W += 2; -*/ - -#define PullB(b)\ - b = S9xGetByte (++ICPU.Registers.S.W); - -#define PullBE(b)\ - ICPU.Registers.S.W++;\ - ICPU.Registers.SH=0x01;\ - b = S9xGetByte (ICPU.Registers.S.W); - -#define PullWE(w) \ - ICPU.Registers.S.W++;\ - ICPU.Registers.SH=0x01;\ - w = S9xGetByte (ICPU.Registers.S.W); \ - ICPU.Registers.S.W++; \ - ICPU.Registers.SH=0x01;\ - w |= (S9xGetByte (ICPU.Registers.S.W)<<8); - -#define PullWENew(w) \ - PullW(w);\ - ICPU.Registers.SH=0x01; - -//PLA -static void Op68E1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullBE (ICPU.Registers.AL); - SetZN8 (ICPU.Registers.AL); -} - -static void Op68M1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (ICPU.Registers.AL); - SetZN8 (ICPU.Registers.AL); -} - -static void Op68M0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (ICPU.Registers.A.W); - SetZN16 (ICPU.Registers.A.W); -} - -//PLB -static void OpABE1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullBE (ICPU.Registers.DB); - SetZN8 (ICPU.Registers.DB); - ICPU.ShiftedDB = ICPU.Registers.DB << 16; -} - -static void OpAB (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (ICPU.Registers.DB); - SetZN8 (ICPU.Registers.DB); - ICPU.ShiftedDB = ICPU.Registers.DB << 16; -} - -/* PHP */ -//PLD NL -static void Op2BE1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullWENew (ICPU.Registers.D.W); - SetZN16 (ICPU.Registers.D.W); -} - -static void Op2B (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (ICPU.Registers.D.W); - SetZN16 (ICPU.Registers.D.W); -} - -/* PLP */ -static void Op28E1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullBE (ICPU.Registers.PL); - S9xUnpackStatus (); - - if (CheckIndex ()) - { - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ();*/ -} - -static void Op28 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (ICPU.Registers.PL); - S9xUnpackStatus (); - - if (CheckIndex ()) - { - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ();*/ -} - -//PLX -static void OpFAE1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullBE (ICPU.Registers.XL); - SetZN8 (ICPU.Registers.XL); -} - -static void OpFAX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (ICPU.Registers.XL); - SetZN8 (ICPU.Registers.XL); -} - -static void OpFAX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (ICPU.Registers.X.W); - SetZN16 (ICPU.Registers.X.W); -} - -//PLY -static void Op7AE1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullBE (ICPU.Registers.YL); - SetZN8 (ICPU.Registers.YL); -} - -static void Op7AX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (ICPU.Registers.YL); - SetZN8 (ICPU.Registers.YL); -} - -static void Op7AX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (ICPU.Registers.Y.W); - SetZN16 (ICPU.Registers.Y.W); -} - -/**********************************************************************************************/ - -/* SetFlag Instructions ********************************************************************** */ -/* SEC */ -static void Op38 (void) -{ - SetCarry (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} - -/* SED */ -static void OpF8 (void) -{ - SetDecimal (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - missing.decimal_mode = 1; -} - -/* SEI */ -static void Op78 (void) -{ - SetIRQ (); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* Transfer Instructions ********************************************************************* */ -/* TAX8 */ -static void OpAAX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.XL = ICPU.Registers.AL; - SetZN8 (ICPU.Registers.XL); -} - -/* TAX16 */ -static void OpAAX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.X.W = ICPU.Registers.A.W; - SetZN16 (ICPU.Registers.X.W); -} - -/* TAY8 */ -static void OpA8X1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.YL = ICPU.Registers.AL; - SetZN8 (ICPU.Registers.YL); -} - -/* TAY16 */ -static void OpA8X0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.Y.W = ICPU.Registers.A.W; - SetZN16 (ICPU.Registers.Y.W); -} - -static void Op5B (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.D.W = ICPU.Registers.A.W; - SetZN16 (ICPU.Registers.D.W); -} - -static void Op1B (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.S.W = ICPU.Registers.A.W; - if (CheckEmulation()) - ICPU.Registers.SH = 1; -} - -static void Op7B (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.A.W = ICPU.Registers.D.W; - SetZN16 (ICPU.Registers.A.W); -} - -static void Op3B (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.A.W = ICPU.Registers.S.W; - SetZN16 (ICPU.Registers.A.W); -} - -static void OpBAX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.XL = ICPU.Registers.SL; - SetZN8 (ICPU.Registers.XL); -} - -static void OpBAX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.X.W = ICPU.Registers.S.W; - SetZN16 (ICPU.Registers.X.W); -} - -static void Op8AM1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.AL = ICPU.Registers.XL; - SetZN8 (ICPU.Registers.AL); -} - -static void Op8AM0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.A.W = ICPU.Registers.X.W; - SetZN16 (ICPU.Registers.A.W); -} - -static void Op9A (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.S.W = ICPU.Registers.X.W; - if (CheckEmulation()) - ICPU.Registers.SH = 1; -} - -static void Op9BX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.YL = ICPU.Registers.XL; - SetZN8 (ICPU.Registers.YL); -} - -static void Op9BX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.Y.W = ICPU.Registers.X.W; - SetZN16 (ICPU.Registers.Y.W); -} - -static void Op98M1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.AL = ICPU.Registers.YL; - SetZN8 (ICPU.Registers.AL); -} - -static void Op98M0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.A.W = ICPU.Registers.Y.W; - SetZN16 (ICPU.Registers.A.W); -} - -static void OpBBX1 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.XL = ICPU.Registers.YL; - SetZN8 (ICPU.Registers.XL); -} - -static void OpBBX0 (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - ICPU.Registers.X.W = ICPU.Registers.Y.W; - SetZN16 (ICPU.Registers.X.W); -} - -/**********************************************************************************************/ - -/* XCE *************************************************************************************** */ -static void OpFB (void) -{ -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - - uint8 A1 = ICPU._Carry; - uint8 A2 = ICPU.Registers.PH; - ICPU._Carry = A2 & 1; - ICPU.Registers.PH = A1; - - if (CheckEmulation()) - { - SetFlags (MemoryFlag | IndexFlag); - ICPU.Registers.SH = 1; - missing.emulate6502 = 1; - } - if (CheckIndex ()) - { - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - } - S9xFixCycles(); -} -/**********************************************************************************************/ - -/* BRK *************************************************************************************** */ -static void Op00 (void) -{ -#ifndef SA1_OPCODES - CPU.BRKTriggered = TRUE; -#endif - - if (!CheckEmulation()) - { - PushB (ICPU.Registers.PB); - PushW (CPU.PC - CPU.PCBase + 1); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFE6)); -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFFE)); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - } -} -/**********************************************************************************************/ - -/* BRL ************************************************************************************** */ -static void Op82 (void) -{ - RelativeLong (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -} -/**********************************************************************************************/ - -/* IRQ *************************************************************************************** */ -void S9xOpcode_IRQ (void) -{ - if (!CheckEmulation()) - { - PushB (ICPU.Registers.PB); - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2207] | - (Memory.FillRAM [0x2208] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase (Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFEE)); - CPU.Cycles += TWO_CYCLES; -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2207] | - (Memory.FillRAM [0x2208] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase (Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFFE)); - CPU.Cycles += ONE_CYCLE; -#endif - } -} - -/**********************************************************************************************/ - -/* NMI *************************************************************************************** */ -void S9xOpcode_NMI (void) -{ - if (!CheckEmulation()) - { - PushB (ICPU.Registers.PB); - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2205] | - (Memory.FillRAM [0x2206] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase (Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFEA)); - CPU.Cycles += TWO_CYCLES; -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2205] | - (Memory.FillRAM [0x2206] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase (Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFFA)); - CPU.Cycles += ONE_CYCLE; -#endif - } -} -/**********************************************************************************************/ - -/* COP *************************************************************************************** */ -static void Op02 (void) -{ - if (!CheckEmulation()) - { - PushB (ICPU.Registers.PB); - PushW (CPU.PC - CPU.PCBase + 1); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFE4)); -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (ICPU.Registers.PL); - OpenBus = ICPU.Registers.PL; - ClearDecimal (); - SetIRQ (); - - ICPU.Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFF4)); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE; -#endif - } -} -/**********************************************************************************************/ - -/* JML *************************************************************************************** */ -static void OpDC (void) -{ - AbsoluteIndirectLong (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - ICPU.Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -} - -static void Op5C (void) -{ - AbsoluteLong (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif - ICPU.Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -} -/**********************************************************************************************/ - -/* JMP *************************************************************************************** */ -static void Op4C (void) -{ - Absolute (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); -#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) - CPUShutdown (); -#endif -} - -static void Op6C (void) -{ - AbsoluteIndirect (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2; -#endif - S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); -} - -static void Op7C (void) -{ - AbsoluteIndexedIndirect (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -} -/**********************************************************************************************/ - -/* JSL/RTL *********************************************************************************** */ -static void Op22E1 (void) -{ - AbsoluteLong (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif - PushB (ICPU.Registers.PB); - PushWENew (CPU.PC - CPU.PCBase - 1); - ICPU.Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -} - -static void Op22 (void) -{ - AbsoluteLong (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed; -#endif - PushB (ICPU.Registers.PB); - PushW (CPU.PC - CPU.PCBase - 1); - ICPU.Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -} - -static void Op6BE1 (void) -{ - PullWENew (ICPU.Registers.PC); - PullB (ICPU.Registers.PB); - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - S9xSetPCBase (ICPU.ShiftedPB + ((ICPU.Registers.PC + 1) & 0xffff)); -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif -} - -static void Op6B (void) -{ - PullW (ICPU.Registers.PC); - PullB (ICPU.Registers.PB); - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - S9xSetPCBase (ICPU.ShiftedPB + ((ICPU.Registers.PC + 1) & 0xffff)); -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* JSR/RTS *********************************************************************************** */ -static void Op20 (void) -{ - Absolute (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - PushW (CPU.PC - CPU.PCBase - 1); - S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); -} - -//JSR a,x -static void OpFCE1 (void) -{ - AbsoluteIndexedIndirect (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - PushWENew (CPU.PC - CPU.PCBase - 1); - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -} - -static void OpFC (void) -{ - AbsoluteIndexedIndirect (JUMP, OpAddressPassthrough); -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE; -#endif - PushW (CPU.PC - CPU.PCBase - 1); - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -} - -static void Op60 (void) -{ - PullW (ICPU.Registers.PC); - S9xSetPCBase (ICPU.ShiftedPB + ((ICPU.Registers.PC + 1) & 0xffff)); -#ifndef SA1_OPCODES - CPU.Cycles += ONE_CYCLE * 3; -#endif -} - -/**********************************************************************************************/ - -/* MVN/MVP *********************************************************************************** */ -static void Op54X1 (void) -{ - uint32 SrcBank; - -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - - ICPU.Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - OpenBus = SrcBank = *CPU.PC++; - - S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), - ICPU.ShiftedDB + ICPU.Registers.Y.W); - - ICPU.Registers.XL++; - ICPU.Registers.YL++; - ICPU.Registers.A.W--; - if (ICPU.Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -static void Op54X0 (void) -{ - uint32 SrcBank; - -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - - ICPU.Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - OpenBus = SrcBank = *CPU.PC++; - - S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), - ICPU.ShiftedDB + ICPU.Registers.Y.W); - - ICPU.Registers.X.W++; - ICPU.Registers.Y.W++; - ICPU.Registers.A.W--; - if (ICPU.Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -static void Op44X1 (void) -{ - uint32 SrcBank; - -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - ICPU.Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - OpenBus = SrcBank = *CPU.PC++; - S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), - ICPU.ShiftedDB + ICPU.Registers.Y.W); - - ICPU.Registers.XL--; - ICPU.Registers.YL--; - ICPU.Registers.A.W--; - if (ICPU.Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -static void Op44X0 (void) -{ - uint32 SrcBank; - -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - ICPU.Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - OpenBus = SrcBank = *CPU.PC++; - S9xSetByte (S9xGetByte ((SrcBank << 16) + ICPU.Registers.X.W), - ICPU.ShiftedDB + ICPU.Registers.Y.W); - - ICPU.Registers.X.W--; - ICPU.Registers.Y.W--; - ICPU.Registers.A.W--; - if (ICPU.Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -/**********************************************************************************************/ - -/* REP/SEP *********************************************************************************** */ -static void OpC2 (void) -{ - uint8 Work8 = ~*CPU.PC++; - ICPU.Registers.PL &= Work8; - ICPU._Carry &= Work8; - ICPU._Overflow &= (Work8 >> 6); - ICPU._Negative &= Work8; - ICPU._Zero |= ~Work8 & Zero; - -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - if (CheckEmulation()) - { - SetFlags (MemoryFlag | IndexFlag); - missing.emulate6502 = 1; - } - if (CheckIndex ()) - { - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ(); */ -} - -static void OpE2 (void) -{ - uint8 Work8 = *CPU.PC++; - ICPU.Registers.PL |= Work8; - ICPU._Carry |= Work8 & 1; - ICPU._Overflow |= (Work8 >> 6) & 1; - ICPU._Negative |= Work8; - if (Work8 & Zero) - ICPU._Zero = 0; -#ifndef SA1_OPCODES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - if (CheckEmulation()) - { - SetFlags (MemoryFlag | IndexFlag); - missing.emulate6502 = 1; - } - if (CheckIndex ()) - { - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - } - S9xFixCycles(); -} -/**********************************************************************************************/ - -/* XBA *************************************************************************************** */ -static void OpEB (void) -{ - uint8 Work8 = ICPU.Registers.AL; - ICPU.Registers.AL = ICPU.Registers.AH; - ICPU.Registers.AH = Work8; - - SetZN8 (ICPU.Registers.AL); -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* RTI *************************************************************************************** */ -static void Op40 (void) -{ - PullB (ICPU.Registers.PL); - S9xUnpackStatus (); - PullW (ICPU.Registers.PC); - if (!CheckEmulation()) - { - PullB (ICPU.Registers.PB); - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - } - else - { - SetFlags (MemoryFlag | IndexFlag); - missing.emulate6502 = 1; - } - S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); - if (CheckIndex ()) - { - ICPU.Registers.XH = 0; - ICPU.Registers.YH = 0; - } -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - S9xFixCycles(); -/* CHECK_FOR_IRQ(); */ -} - -/**********************************************************************************************/ - -/* STP/WAI/DB ******************************************************************************** */ -// WAI -static void OpCB (void) -{ - -// Ok, let's just C-ify the ASM versions separately. -#ifdef SA1_OPCODES - SA1.WaitingForInterrupt = TRUE; - SA1.PC--; -#if 0 -// XXX: FIXME - if(Settings.Shutdown){ - SA1.Cycles = SA1.NextEvent; - if (IAPU.APUExecuting) - { - SA1.Executing = FALSE; - do - { - APU_EXECUTE1 (, } while (APU.Cycles < SA1.NextEvent, SA1.Executing = TRUE; - } - } -#endif -#else // SA1_OPCODES -#if 0 - - - if (CPU.IRQActive) - { -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - } - else -#endif - { - CPU.WaitingForInterrupt = TRUE; - CPU.PC--; -#ifdef CPU_SHUTDOWN - if (Settings.Shutdown) - { - CPU.Cycles = CPU.NextEvent; - if (IAPU.APUExecuting) - { - ICPU.CPUExecuting = FALSE; - do - { - APU_EXECUTE1 (); - } while (APU.Cycles < CPU.NextEvent); - ICPU.CPUExecuting = TRUE; - } - } - else - { -#ifndef SA1_OPCODES - CPU.Cycles += TWO_CYCLES; -#endif - } -#endif - } -#endif // SA1_OPCODES -} - -// STP -static void OpDB (void) -{ - CPU.PC--; - CPU.Flags |= DEBUG_MODE_FLAG; -} - -// Reserved S9xOpcode -static void Op42 (void) -{ -} - -/*****************************************************************************/ - -/*****************************************************************************/ -/* CPU-S9xOpcodes Definitions */ -/*****************************************************************************/ -struct SOpcodes S9xOpcodesM1X1[256] = -{ - {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, - {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, - {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, - {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, - {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, - {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, - {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, - {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, - {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, - {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, - {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, - {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, - {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, - {Op41M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, - {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, - {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, - {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X1}, - {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, - {Op5AX1}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, - {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, - {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, - {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, - {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, - {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, - {Op78}, {Op79M1}, {Op7AX1}, {Op7B}, {Op7C}, - {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, - {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, - {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8B}, - {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90}, - {Op91M1}, {Op92M1}, {Op93M1}, {Op94X1}, {Op95M1}, - {Op96X1}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, - {Op9BX1}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, - {OpA0X1}, {OpA1M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, - {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, - {OpAAX1}, {OpAB}, {OpACX1}, {OpADM1}, {OpAEX1}, - {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, - {OpB4X1}, {OpB5M1}, {OpB6X1}, {OpB7M1}, {OpB8}, - {OpB9M1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1}, - {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1M1}, {OpC2}, - {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, - {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, - {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, - {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, - {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX1}, {OpDB}, - {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X1}, - {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, - {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, - {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, - {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, - {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, - {OpFAX1}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, - {OpFFM1} -}; - -struct SOpcodes S9xOpcodesE1[256] = -{ - {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, - {Op05M1}, {Op06M1}, {Op07M1}, {Op08E1}, {Op09M1}, - {Op0AM1}, {Op0BE1}, {Op0CM1}, {Op0DM1}, {Op0EM1}, - {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, - {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, - {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, - {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22E1}, - {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, - {Op28}, {Op29M1}, {Op2AM1}, {Op2BE1}, {Op2CM1}, - {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, - {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, - {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, - {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, - {Op41M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, - {Op46M1}, {Op47M1}, {Op48E1}, {Op49M1}, {Op4AM1}, - {Op4BE1}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, - {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X1}, - {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, - {Op5AE1}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, - {Op5FM1}, {Op60}, {Op61M1}, {Op62E1}, {Op63M1}, - {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68E1}, - {Op69M1}, {Op6AM1}, {Op6BE1}, {Op6C}, {Op6DM1}, - {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, - {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, - {Op78}, {Op79M1}, {Op7AE1}, {Op7B}, {Op7C}, - {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, - {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, - {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8BE1}, - {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90}, - {Op91M1}, {Op92M1}, {Op93M1}, {Op94X1}, {Op95M1}, - {Op96X1}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, - {Op9BX1}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, - {OpA0X1}, {OpA1M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, - {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, - {OpAAX1}, {OpABE1}, {OpACX1}, {OpADM1}, {OpAEX1}, - {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, - {OpB4X1}, {OpB5M1}, {OpB6X1}, {OpB7M1}, {OpB8}, - {OpB9M1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1}, - {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1M1}, {OpC2}, - {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, - {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, - {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, - {OpD2M1}, {OpD3M1}, {OpD4E1}, {OpD5M1}, {OpD6M1}, - {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAE1}, {OpDB}, - {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X1}, - {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, - {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, - {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, - {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4E1}, - {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, - {OpFAE1}, {OpFB}, {OpFCE1}, {OpFDM1}, {OpFEM1}, - {OpFFM1} -}; - -struct SOpcodes S9xOpcodesM1X0[256] = -{ - {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, - {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, - {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, - {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, - {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, - {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, - {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, - {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, - {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, - {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, - {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, - {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, - {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, - {Op41M1}, {Op42}, {Op43M1}, {Op44X0}, {Op45M1}, - {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, - {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, - {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X0}, - {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, - {Op5AX0}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, - {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, - {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, - {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, - {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, - {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, - {Op78}, {Op79M1}, {Op7AX0}, {Op7B}, {Op7C}, - {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, - {Op82}, {Op83M1}, {Op84X0}, {Op85M1}, {Op86X0}, - {Op87M1}, {Op88X0}, {Op89M1}, {Op8AM1}, {Op8B}, - {Op8CX0}, {Op8DM1}, {Op8EX0}, {Op8FM1}, {Op90}, - {Op91M1}, {Op92M1}, {Op93M1}, {Op94X0}, {Op95M1}, - {Op96X0}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, - {Op9BX0}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, - {OpA0X0}, {OpA1M1}, {OpA2X0}, {OpA3M1}, {OpA4X0}, - {OpA5M1}, {OpA6X0}, {OpA7M1}, {OpA8X0}, {OpA9M1}, - {OpAAX0}, {OpAB}, {OpACX0}, {OpADM1}, {OpAEX0}, - {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, - {OpB4X0}, {OpB5M1}, {OpB6X0}, {OpB7M1}, {OpB8}, - {OpB9M1}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM1}, - {OpBEX0}, {OpBFM1}, {OpC0X0}, {OpC1M1}, {OpC2}, - {OpC3M1}, {OpC4X0}, {OpC5M1}, {OpC6M1}, {OpC7M1}, - {OpC8X0}, {OpC9M1}, {OpCAX0}, {OpCB}, {OpCCX0}, - {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, - {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, - {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX0}, {OpDB}, - {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X0}, - {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X0}, {OpE5M1}, - {OpE6M1}, {OpE7M1}, {OpE8X0}, {OpE9M1}, {OpEA}, - {OpEB}, {OpECX0}, {OpEDM1}, {OpEEM1}, {OpEFM1}, - {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, - {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, - {OpFAX0}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, - {OpFFM1} -}; - -struct SOpcodes S9xOpcodesM0X0[256] = -{ - {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, - {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, - {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, - {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, - {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, - {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, - {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, - {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, - {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, - {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, - {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, - {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, - {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, - {Op41M0}, {Op42}, {Op43M0}, {Op44X0}, {Op45M0}, - {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, - {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, - {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X0}, - {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, - {Op5AX0}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, - {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, - {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, - {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, - {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, - {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, - {Op78}, {Op79M0}, {Op7AX0}, {Op7B}, {Op7C}, - {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, - {Op82}, {Op83M0}, {Op84X0}, {Op85M0}, {Op86X0}, - {Op87M0}, {Op88X0}, {Op89M0}, {Op8AM0}, {Op8B}, - {Op8CX0}, {Op8DM0}, {Op8EX0}, {Op8FM0}, {Op90}, - {Op91M0}, {Op92M0}, {Op93M0}, {Op94X0}, {Op95M0}, - {Op96X0}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, - {Op9BX0}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, - {OpA0X0}, {OpA1M0}, {OpA2X0}, {OpA3M0}, {OpA4X0}, - {OpA5M0}, {OpA6X0}, {OpA7M0}, {OpA8X0}, {OpA9M0}, - {OpAAX0}, {OpAB}, {OpACX0}, {OpADM0}, {OpAEX0}, - {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, - {OpB4X0}, {OpB5M0}, {OpB6X0}, {OpB7M0}, {OpB8}, - {OpB9M0}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM0}, - {OpBEX0}, {OpBFM0}, {OpC0X0}, {OpC1M0}, {OpC2}, - {OpC3M0}, {OpC4X0}, {OpC5M0}, {OpC6M0}, {OpC7M0}, - {OpC8X0}, {OpC9M0}, {OpCAX0}, {OpCB}, {OpCCX0}, - {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, - {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, - {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX0}, {OpDB}, - {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X0}, - {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X0}, {OpE5M0}, - {OpE6M0}, {OpE7M0}, {OpE8X0}, {OpE9M0}, {OpEA}, - {OpEB}, {OpECX0}, {OpEDM0}, {OpEEM0}, {OpEFM0}, - {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, - {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, - {OpFAX0}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, - {OpFFM0} -}; - -struct SOpcodes S9xOpcodesM0X1[256] = -{ - {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, - {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, - {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, - {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, - {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, - {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, - {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, - {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, - {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, - {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, - {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, - {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, - {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, - {Op41M0}, {Op42}, {Op43M0}, {Op44X1}, {Op45M0}, - {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, - {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, - {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X1}, - {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, - {Op5AX1}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, - {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, - {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, - {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, - {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, - {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, - {Op78}, {Op79M0}, {Op7AX1}, {Op7B}, {Op7C}, - {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, - {Op82}, {Op83M0}, {Op84X1}, {Op85M0}, {Op86X1}, - {Op87M0}, {Op88X1}, {Op89M0}, {Op8AM0}, {Op8B}, - {Op8CX1}, {Op8DM0}, {Op8EX1}, {Op8FM0}, {Op90}, - {Op91M0}, {Op92M0}, {Op93M0}, {Op94X1}, {Op95M0}, - {Op96X1}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, - {Op9BX1}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, - {OpA0X1}, {OpA1M0}, {OpA2X1}, {OpA3M0}, {OpA4X1}, - {OpA5M0}, {OpA6X1}, {OpA7M0}, {OpA8X1}, {OpA9M0}, - {OpAAX1}, {OpAB}, {OpACX1}, {OpADM0}, {OpAEX1}, - {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, - {OpB4X1}, {OpB5M0}, {OpB6X1}, {OpB7M0}, {OpB8}, - {OpB9M0}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM0}, - {OpBEX1}, {OpBFM0}, {OpC0X1}, {OpC1M0}, {OpC2}, - {OpC3M0}, {OpC4X1}, {OpC5M0}, {OpC6M0}, {OpC7M0}, - {OpC8X1}, {OpC9M0}, {OpCAX1}, {OpCB}, {OpCCX1}, - {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, - {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, - {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX1}, {OpDB}, - {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X1}, - {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X1}, {OpE5M0}, - {OpE6M0}, {OpE7M0}, {OpE8X1}, {OpE9M0}, {OpEA}, - {OpEB}, {OpECX1}, {OpEDM0}, {OpEEM0}, {OpEFM0}, - {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, - {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, - {OpFAX1}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, - {OpFFM0} -}; - diff --git a/source/data.c b/source/data.c new file mode 100644 index 0000000..0854ed4 --- /dev/null +++ b/source/data.c @@ -0,0 +1,539 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#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/data.cpp b/source/data.cpp deleted file mode 100644 index 0854ed4..0000000 --- a/source/data.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#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/dma.c b/source/dma.c new file mode 100644 index 0000000..71f8e03 --- /dev/null +++ b/source/dma.c @@ -0,0 +1,1100 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#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" + +#ifdef SDD1_DECOMP +#include "sdd1emu.h" +#endif + +#ifdef SDD1_DECOMP +uint8 buffer[0x10000]; +#endif + +extern int HDMA_ModeByteCounts [8]; +extern uint8 *HDMAMemPointers [8]; +extern uint8 *HDMABasePointers [8]; + +// #define SETA010_HDMA_FROM_CART + +#ifdef SETA010_HDMA_FROM_CART +uint32 HDMARawPointers[8]; // Cart address space pointer +#endif + +#if defined(__linux__) || defined(__WIN32__) +static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) +{ + return (*(uint32 *) p1 - *(uint32 *) p2); +} +#endif + +/**********************************************************************************************/ +/* S9xDoDMA() */ +/* This function preforms the general dma transfer */ +/**********************************************************************************************/ + +void S9xDoDMA (uint8 Channel) +{ + uint8 Work; + + if (Channel > 7 || CPU.InDMA) + return; + + CPU.InDMA = TRUE; + bool8 in_sa1_dma = FALSE; + uint8 *in_sdd1_dma = NULL; + uint8 *spc7110_dma=NULL; + bool s7_wrap=false; + SDMA *d = &DMA[Channel]; + + + int count = d->TransferBytes; + + if (count == 0) + count = 0x10000; + + int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); + + if((d->ABank==0x7E||d->ABank==0x7F)&&d->BAddress==0x80) + { + d->AAddress+= d->TransferBytes; + //does an invalid DMA actually take time? + // I'd say yes, since 'invalid' is probably just the WRAM chip + // not being able to read and write itself at the same time + CPU.Cycles+=(d->TransferBytes+1)*SLOW_ONE_CYCLE; + goto update_address; + } + switch (d->BAddress) + { + case 0x18: + case 0x19: + if (IPPU.RenderThisFrame) + FLUSH_REDRAW (); + break; + } + if (Settings.SDD1) + { + if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) + { + // Hacky support for pre-decompressed S-DD1 data + inc = !d->AAddressDecrement ? 1 : -1; + uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; + + address |= Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)]; + +#ifdef SDD1_DECOMP + if(Settings.SDD1Pack) + { + uint8* in_ptr=GetBasePointer(((d->ABank << 16) | d->AAddress)); + in_ptr+=d->AAddress; + + SDD1_decompress(buffer,in_ptr,d->TransferBytes); + in_sdd1_dma=buffer; +#ifdef SDD1_VERIFY + void *ptr = bsearch (&address, Memory.SDD1Index, + Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); + if(memcmp(buffer, ptr, d->TransferBytes)) + { + 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 == 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; + } + } + if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) + { + int j=0; + while(ptr[j]==buffer[j]) + j++; + + *p = d->ABank; + *(p + 1) = d->AAddress >> 8; + *(p + 2) = d->AAddress & 0xff; + *(p + 3) = j&0xFF; + *(p + 4) = (j>>8)&0xFF; + *(p + 7) = SDD1Bank; + Memory.SDD1LoggedDataCount += 1; + } + } +#endif + } + + else + { +#endif +#if defined(__linux__) || defined (__WIN32__) + void *ptr = bsearch (&address, Memory.SDD1Index, + Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); + if (ptr) + in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; +#else + uint8 *ptr = Memory.SDD1Index; + + for (uint32 e = 0; e < Memory.SDD1Entries; e++, ptr += 12) + { + if (address == *(uint32 *) ptr) + { + in_sdd1_dma = *(uint32 *) (ptr + 4) + Memory.SDD1Data; + break; + } + } +#endif + + 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 == 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 = 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; + } + } + } +#ifdef SDD1_DECOMP + } +#endif + + Memory.FillRAM [0x4801] = 0; + } + if(Settings.SPC7110&&(d->AAddress==0x4800||d->ABank==0x50)) + { + uint32 i,j; + i=(s7r.reg4805|(s7r.reg4806<<8)); + i*=s7r.AlignBy; + i+=s7r.bank50Internal; + i%=DECOMP_BUFFER_SIZE; + j=0; + if((i+d->TransferBytes)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; + } + int icount=s7r.reg4809|(s7r.reg480A<<8); + icount-=d->TransferBytes; + s7r.reg4809=0x00ff&icount; + s7r.reg480A=(0xff00&icount)>>8; + + s7r.bank50Internal+=d->TransferBytes; + s7r.bank50Internal%=DECOMP_BUFFER_SIZE; + inc=1; + d->AAddress-=count; + } + if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40) + { + // Perform packed bitmap to PPU character format conversion on the + // data before transmitting it to V-RAM via-DMA. + int num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7); + int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : + (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; + + int bytes_per_char = 8 * depth; + int bytes_per_line = depth * num_chars; + int 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) + addr; + uint8 *buffer = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; + uint8 *p = buffer; + uint32 inc = char_line_bytes - (d->AAddress % char_line_bytes); + uint32 char_count = inc / bytes_per_char; + + in_sa1_dma = TRUE; + + //printf ("%08x,", base); fflush (stdout); + //printf ("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", + //depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); + int i; + + switch (depth) + { + case 2: + for (i = 0; i < count; i += inc, base += char_line_bytes, + inc = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 2; + for (uint32 j = 0; j < char_count && p - buffer < count; + j++, line += 2) + { + uint8 *q = line; + for (int l = 0; l < 8; l++, q += bytes_per_line) + { + for (int 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; + } + } + } + break; + case 4: + for (i = 0; i < count; i += inc, base += char_line_bytes, + inc = 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 (int l = 0; l < 8; l++, q += bytes_per_line) + { + for (int 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 (i = 0; i < count; i += inc, base += char_line_bytes, + inc = 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 (int l = 0; l < 8; l++, q += bytes_per_line) + { + 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; + } + p += 64 - 16; + } + } + break; + } + } + + if (!d->TransferDirection) + { + /* XXX: DMA is potentially broken here for cases where we DMA across + * XXX: memmap boundries. A possible solution would be to re-call + * XXX: GetBasePointer whenever we cross a boundry, and when + * XXX: GetBasePointer returns (0) to take the 'slow path' and use + * XXX: S9xGetByte instead of *base. GetBasePointer() would want to + * XXX: return (0) for MAP_PPU and whatever else is a register range + * XXX: rather than a RAM/ROM block, and we'd want to detect MAP_PPU + * XXX: (or specifically, Address Bus B addresses $2100-$21FF in + * XXX: banks $00-$3F) specially and treat it as MAP_NONE (since + * XXX: PPU->PPU transfers don't work). + */ + + //reflects extra cycle used by DMA + CPU.Cycles += SLOW_ONE_CYCLE * (count+1); + + uint8 *base = GetBasePointer ((d->ABank << 16) + d->AAddress); + uint16 p = d->AAddress; + + if (!base) + base = Memory.ROM; + + if (in_sa1_dma) + { + base = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; + p = 0; + } + + if (in_sdd1_dma) + { + base = in_sdd1_dma; + p = 0; + } + if(spc7110_dma) + { + base=spc7110_dma; + p = 0; + } + if (inc > 0) + d->AAddress += count; + else + if (inc < 0) + d->AAddress -= count; + + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + switch (d->BAddress) + { + case 0x04: + do + { + Work = *(base + p); + REGISTER_2104(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + case 0x18: +#ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; +#endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2118_linear(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2118_tile(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + break; + case 0x19: +#ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; +#endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2119_linear(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2119_tile(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + break; + case 0x22: + do + { + Work = *(base + p); + REGISTER_2122(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + case 0x80: + do + { + Work = *(base + p); + REGISTER_2180(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + default: + do + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + } + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + if (d->BAddress == 0x18) + { + // Write to V-RAM +#ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; +#endif + if (!PPU.VMA.FullGraphicCount) + { + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + p += inc; + + Work = *(base + p); + REGISTER_2119_linear(Work); + p += inc; + CHECK_SOUND(); + count -= 2; + } + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + p += inc; + } + } + else + { + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + p += inc; + + Work = *(base + p); + REGISTER_2119_tile(Work); + p += inc; + CHECK_SOUND(); + count -= 2; + } + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + p += inc; + } + } + } + else + { + // DMA mode 1 general case + while (count > 1) + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + CHECK_SOUND(); + count -= 2; + } + if (count == 1) + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + } + } + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + do + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + if (count <= 1) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + if (count <= 2) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + if (count <= 3) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + CHECK_SOUND(); + count -= 4; + } while (count > 0); + } + else + if (d->TransferMode == 4) + { + do + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + if (count <= 1) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + if (count <= 2) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2102 + d->BAddress); + p += inc; + if (count <= 3) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2103 + d->BAddress); + p += inc; + CHECK_SOUND(); + count -= 4; + } while (count > 0); + } + } + else + { + /* XXX: DMA is potentially broken here for cases where the dest is + * XXX: in the Address Bus B range. Note that this bad dest may not + * XXX: cover the whole range of the DMA though, if we transfer + * XXX: 65536 bytes only 256 of them may be Address Bus B. + */ + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + --count; + break; + + case 1: + case 5: + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + count--; + break; + + case 3: + case 7: + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + count--; + break; + + case 4: + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2102 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2103 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + count--; + break; + + default: + count = 0; + break; + } + CHECK_SOUND(); + } while (count); + } + +#ifdef SPC700_C + IAPU.APUExecuting = Settings.APUEnabled; + APU_EXECUTE (); +#endif + if (Settings.SuperFX) + while (CPU.Cycles > CPU.NextEvent) + S9xDoHBlankProcessing_SFX (); + else /* if (!Settings.SuperFX) */ + while (CPU.Cycles > CPU.NextEvent) + S9xDoHBlankProcessing_NoSFX (); + + if(Settings.SPC7110&&spc7110_dma) + { + if(spc7110_dma&&s7_wrap) + delete [] spc7110_dma; + } + +update_address: + // Super Punch-Out requires that the A-BUS address be updated after the + // DMA transfer. + Memory.FillRAM[0x4302 + (Channel << 4)] = (uint8) d->AAddress; + Memory.FillRAM[0x4303 + (Channel << 4)] = d->AAddress >> 8; + + // Secret of the Mana requires that the DMA bytes transfer count be set to + // zero when DMA has completed. + Memory.FillRAM [0x4305 + (Channel << 4)] = 0; + Memory.FillRAM [0x4306 + (Channel << 4)] = 0; + + DMA[Channel].IndirectAddress = 0; + d->TransferBytes = 0; + + CPU.InDMA = FALSE; + + +} + +void S9xStartHDMA () +{ + if (Settings.DisableHDMA) + IPPU.HDMA = 0; + else + missing.hdma_this_frame = IPPU.HDMA = Memory.FillRAM [0x420c]; + + //per anomie timing post + if(IPPU.HDMA!=0) + CPU.Cycles+=ONE_CYCLE*3; + + IPPU.HDMAStarted = TRUE; + + for (uint8 i = 0; i < 8; i++) + { + if (IPPU.HDMA & (1 << i)) + { + CPU.Cycles+=SLOW_ONE_CYCLE ; + DMA [i].LineCount = 0; + DMA [i].FirstLine = TRUE; + DMA [i].Address = DMA [i].AAddress; + if(DMA[i].HDMAIndirectAddressing) + CPU.Cycles+=(SLOW_ONE_CYCLE <<2); + } + HDMAMemPointers [i] = NULL; +#ifdef SETA010_HDMA_FROM_CART + HDMARawPointers [i] = 0; +#endif + } +} + +uint8 S9xDoHDMA (uint8 byte) +{ + struct SDMA *p = &DMA [0]; + + int d = 0; + + CPU.InDMA = TRUE; + CPU.Cycles+=ONE_CYCLE*3; + for (uint8 mask = 1; mask; mask <<= 1, p++, d++) + { + if (byte & mask) + { + if (!p->LineCount) + { + //remember, InDMA is set. + //Get/Set incur no charges! + CPU.Cycles+=SLOW_ONE_CYCLE; + uint8 line = S9xGetByte ((p->ABank << 16) + p->Address); + if (line == 0x80) + { + p->Repeat = TRUE; + p->LineCount = 128; + } + else + { + p->Repeat = !(line & 0x80); + p->LineCount = line & 0x7f; + } + + // Disable H-DMA'ing into V-RAM (register 2118) for Hook + /* XXX: instead of p->BAddress == 0x18, make S9xSetPPU fail + * XXX: writes to $2118/9 when appropriate + */ +#ifdef SETA010_HDMA_FROM_CART + if (!p->LineCount) +#else + if (!p->LineCount || p->BAddress == 0x18) +#endif + { + byte &= ~mask; + p->IndirectAddress += HDMAMemPointers [d] - HDMABasePointers [d]; + Memory.FillRAM [0x4305 + (d << 4)] = (uint8) p->IndirectAddress; + Memory.FillRAM [0x4306 + (d << 4)] = p->IndirectAddress >> 8; + continue; + } + + p->Address++; + p->FirstLine = 1; + if (p->HDMAIndirectAddressing) + { + p->IndirectBank = Memory.FillRAM [0x4307 + (d << 4)]; + //again, no cycle charges while InDMA is set! + CPU.Cycles+=SLOW_ONE_CYCLE<<2; + p->IndirectAddress = S9xGetWord ((p->ABank << 16) + p->Address); + p->Address += 2; + } + else + { + p->IndirectBank = p->ABank; + p->IndirectAddress = p->Address; + } + HDMABasePointers [d] = HDMAMemPointers [d] = + S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress); +#ifdef SETA010_HDMA_FROM_CART + HDMARawPointers [d] = (p->IndirectBank << 16) + p->IndirectAddress; +#endif + } + else + { + CPU.Cycles += SLOW_ONE_CYCLE; + } + + if (!HDMAMemPointers [d]) + { + if (!p->HDMAIndirectAddressing) + { + p->IndirectBank = p->ABank; + p->IndirectAddress = p->Address; + } +#ifdef SETA010_HDMA_FROM_CART + HDMARawPointers [d] = (p->IndirectBank << 16) + p->IndirectAddress; +#endif + if (!(HDMABasePointers [d] = HDMAMemPointers [d] = + S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress))) + { + /* XXX: Instead of this, goto a slow path that first + * XXX: verifies src!=Address Bus B, then uses + * XXX: S9xGetByte(). Or make S9xGetByte return OpenBus + * XXX: (probably?) for Address Bus B while inDMA. + */ + byte &= ~mask; + continue; + } + // Uncommenting the following line breaks Punchout - it starts + // H-DMA during the frame. + //p->FirstLine = TRUE; + } + if (p->Repeat && !p->FirstLine) + { + p->LineCount--; + continue; + } + + if (p->BAddress == 0x04){ + if(SNESGameFixes.Uniracers){ + PPU.OAMAddr = 0x10c; + PPU.OAMFlip=0; + } + } + + switch (p->TransferMode) + { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; +#ifdef SETA010_HDMA_FROM_CART + S9xSetPPU (S9xGetByte (HDMARawPointers [d]++), 0x2100 + p->BAddress); + HDMAMemPointers [d]++; +#else + S9xSetPPU (*HDMAMemPointers [d]++, 0x2100 + p->BAddress); +#endif + break; + case 5: + CPU.Cycles += 2*SLOW_ONE_CYCLE; +#ifdef SETA010_HDMA_FROM_CART + S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2101 + p->BAddress); + HDMARawPointers [d] += 2; +#else + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); +#endif + HDMAMemPointers [d] += 2; + /* fall through */ + case 1: + CPU.Cycles += 2*SLOW_ONE_CYCLE; +#ifdef SETA010_HDMA_FROM_CART + S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2101 + p->BAddress); + HDMARawPointers [d] += 2; +#else + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); +#endif + HDMAMemPointers [d] += 2; + break; + case 2: + case 6: + CPU.Cycles += 2*SLOW_ONE_CYCLE; +#ifdef SETA010_HDMA_FROM_CART + S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2100 + p->BAddress); + HDMARawPointers [d] += 2; +#else + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); +#endif + HDMAMemPointers [d] += 2; + break; + case 3: + case 7: + CPU.Cycles += 4*SLOW_ONE_CYCLE; +#ifdef SETA010_HDMA_FROM_CART + S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 2), 0x2101 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 3), 0x2101 + p->BAddress); + HDMARawPointers [d] += 4; +#else + 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); +#endif + HDMAMemPointers [d] += 4; + break; + case 4: + CPU.Cycles += 4*SLOW_ONE_CYCLE; +#ifdef SETA010_HDMA_FROM_CART + S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2101 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 2), 0x2102 + p->BAddress); + S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 3), 0x2103 + p->BAddress); + HDMARawPointers [d] += 4; +#else + 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); +#endif + HDMAMemPointers [d] += 4; + break; + } + if (!p->HDMAIndirectAddressing) + p->Address += HDMA_ModeByteCounts [p->TransferMode]; + p->IndirectAddress += HDMA_ModeByteCounts [p->TransferMode]; + /* XXX: Check for p->IndirectAddress crossing a mapping boundry, + * XXX: and invalidate HDMAMemPointers[d] + */ + p->FirstLine = FALSE; + p->LineCount--; + } + } + CPU.InDMA=FALSE; + return (byte); +} + +void S9xResetDMA () +{ + int d; + for (d = 0; d < 8; d++) + { + DMA [d].TransferDirection = FALSE; + DMA [d].HDMAIndirectAddressing = FALSE; + DMA [d].AAddressFixed = TRUE; + DMA [d].AAddressDecrement = FALSE; + DMA [d].TransferMode = 0xff; + DMA [d].ABank = 0xff; + DMA [d].AAddress = 0xffff; + DMA [d].Address = 0xffff; + DMA [d].BAddress = 0xff; + DMA [d].TransferBytes = 0xffff; + } + for (int c = 0x4300; c < 0x4380; c += 0x10) + { + for (d = c; d < c + 12; d++) + Memory.FillRAM [d] = 0xff; + + Memory.FillRAM [c + 0xf] = 0xff; + } +} diff --git a/source/dma.cpp b/source/dma.cpp deleted file mode 100644 index 71f8e03..0000000 --- a/source/dma.cpp +++ /dev/null @@ -1,1100 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#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" - -#ifdef SDD1_DECOMP -#include "sdd1emu.h" -#endif - -#ifdef SDD1_DECOMP -uint8 buffer[0x10000]; -#endif - -extern int HDMA_ModeByteCounts [8]; -extern uint8 *HDMAMemPointers [8]; -extern uint8 *HDMABasePointers [8]; - -// #define SETA010_HDMA_FROM_CART - -#ifdef SETA010_HDMA_FROM_CART -uint32 HDMARawPointers[8]; // Cart address space pointer -#endif - -#if defined(__linux__) || defined(__WIN32__) -static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) -{ - return (*(uint32 *) p1 - *(uint32 *) p2); -} -#endif - -/**********************************************************************************************/ -/* S9xDoDMA() */ -/* This function preforms the general dma transfer */ -/**********************************************************************************************/ - -void S9xDoDMA (uint8 Channel) -{ - uint8 Work; - - if (Channel > 7 || CPU.InDMA) - return; - - CPU.InDMA = TRUE; - bool8 in_sa1_dma = FALSE; - uint8 *in_sdd1_dma = NULL; - uint8 *spc7110_dma=NULL; - bool s7_wrap=false; - SDMA *d = &DMA[Channel]; - - - int count = d->TransferBytes; - - if (count == 0) - count = 0x10000; - - int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); - - if((d->ABank==0x7E||d->ABank==0x7F)&&d->BAddress==0x80) - { - d->AAddress+= d->TransferBytes; - //does an invalid DMA actually take time? - // I'd say yes, since 'invalid' is probably just the WRAM chip - // not being able to read and write itself at the same time - CPU.Cycles+=(d->TransferBytes+1)*SLOW_ONE_CYCLE; - goto update_address; - } - switch (d->BAddress) - { - case 0x18: - case 0x19: - if (IPPU.RenderThisFrame) - FLUSH_REDRAW (); - break; - } - if (Settings.SDD1) - { - if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) - { - // Hacky support for pre-decompressed S-DD1 data - inc = !d->AAddressDecrement ? 1 : -1; - uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; - - address |= Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)]; - -#ifdef SDD1_DECOMP - if(Settings.SDD1Pack) - { - uint8* in_ptr=GetBasePointer(((d->ABank << 16) | d->AAddress)); - in_ptr+=d->AAddress; - - SDD1_decompress(buffer,in_ptr,d->TransferBytes); - in_sdd1_dma=buffer; -#ifdef SDD1_VERIFY - void *ptr = bsearch (&address, Memory.SDD1Index, - Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); - if(memcmp(buffer, ptr, d->TransferBytes)) - { - 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 == 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; - } - } - if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) - { - int j=0; - while(ptr[j]==buffer[j]) - j++; - - *p = d->ABank; - *(p + 1) = d->AAddress >> 8; - *(p + 2) = d->AAddress & 0xff; - *(p + 3) = j&0xFF; - *(p + 4) = (j>>8)&0xFF; - *(p + 7) = SDD1Bank; - Memory.SDD1LoggedDataCount += 1; - } - } -#endif - } - - else - { -#endif -#if defined(__linux__) || defined (__WIN32__) - void *ptr = bsearch (&address, Memory.SDD1Index, - Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); - if (ptr) - in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; -#else - uint8 *ptr = Memory.SDD1Index; - - for (uint32 e = 0; e < Memory.SDD1Entries; e++, ptr += 12) - { - if (address == *(uint32 *) ptr) - { - in_sdd1_dma = *(uint32 *) (ptr + 4) + Memory.SDD1Data; - break; - } - } -#endif - - 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 == 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 = 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; - } - } - } -#ifdef SDD1_DECOMP - } -#endif - - Memory.FillRAM [0x4801] = 0; - } - if(Settings.SPC7110&&(d->AAddress==0x4800||d->ABank==0x50)) - { - uint32 i,j; - i=(s7r.reg4805|(s7r.reg4806<<8)); - i*=s7r.AlignBy; - i+=s7r.bank50Internal; - i%=DECOMP_BUFFER_SIZE; - j=0; - if((i+d->TransferBytes)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; - } - int icount=s7r.reg4809|(s7r.reg480A<<8); - icount-=d->TransferBytes; - s7r.reg4809=0x00ff&icount; - s7r.reg480A=(0xff00&icount)>>8; - - s7r.bank50Internal+=d->TransferBytes; - s7r.bank50Internal%=DECOMP_BUFFER_SIZE; - inc=1; - d->AAddress-=count; - } - if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40) - { - // Perform packed bitmap to PPU character format conversion on the - // data before transmitting it to V-RAM via-DMA. - int num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7); - int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : - (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; - - int bytes_per_char = 8 * depth; - int bytes_per_line = depth * num_chars; - int 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) + addr; - uint8 *buffer = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; - uint8 *p = buffer; - uint32 inc = char_line_bytes - (d->AAddress % char_line_bytes); - uint32 char_count = inc / bytes_per_char; - - in_sa1_dma = TRUE; - - //printf ("%08x,", base); fflush (stdout); - //printf ("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", - //depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); - int i; - - switch (depth) - { - case 2: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 2; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 2) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int 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; - } - } - } - break; - case 4: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = 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 (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int 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 (i = 0; i < count; i += inc, base += char_line_bytes, - inc = 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 (int l = 0; l < 8; l++, q += bytes_per_line) - { - 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; - } - p += 64 - 16; - } - } - break; - } - } - - if (!d->TransferDirection) - { - /* XXX: DMA is potentially broken here for cases where we DMA across - * XXX: memmap boundries. A possible solution would be to re-call - * XXX: GetBasePointer whenever we cross a boundry, and when - * XXX: GetBasePointer returns (0) to take the 'slow path' and use - * XXX: S9xGetByte instead of *base. GetBasePointer() would want to - * XXX: return (0) for MAP_PPU and whatever else is a register range - * XXX: rather than a RAM/ROM block, and we'd want to detect MAP_PPU - * XXX: (or specifically, Address Bus B addresses $2100-$21FF in - * XXX: banks $00-$3F) specially and treat it as MAP_NONE (since - * XXX: PPU->PPU transfers don't work). - */ - - //reflects extra cycle used by DMA - CPU.Cycles += SLOW_ONE_CYCLE * (count+1); - - uint8 *base = GetBasePointer ((d->ABank << 16) + d->AAddress); - uint16 p = d->AAddress; - - if (!base) - base = Memory.ROM; - - if (in_sa1_dma) - { - base = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; - p = 0; - } - - if (in_sdd1_dma) - { - base = in_sdd1_dma; - p = 0; - } - if(spc7110_dma) - { - base=spc7110_dma; - p = 0; - } - if (inc > 0) - d->AAddress += count; - else - if (inc < 0) - d->AAddress -= count; - - if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) - { - switch (d->BAddress) - { - case 0x04: - do - { - Work = *(base + p); - REGISTER_2104(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - case 0x18: -#ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; -#endif - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - break; - case 0x19: -#ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; -#endif - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2119_linear(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2119_tile(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - break; - case 0x22: - do - { - Work = *(base + p); - REGISTER_2122(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - case 0x80: - do - { - Work = *(base + p); - REGISTER_2180(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - default: - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - } - } - else - if (d->TransferMode == 1 || d->TransferMode == 5) - { - if (d->BAddress == 0x18) - { - // Write to V-RAM -#ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; -#endif - if (!PPU.VMA.FullGraphicCount) - { - while (count > 1) - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - - Work = *(base + p); - REGISTER_2119_linear(Work); - p += inc; - CHECK_SOUND(); - count -= 2; - } - if (count == 1) - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - } - } - else - { - while (count > 1) - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - - Work = *(base + p); - REGISTER_2119_tile(Work); - p += inc; - CHECK_SOUND(); - count -= 2; - } - if (count == 1) - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - } - } - } - else - { - // DMA mode 1 general case - while (count > 1) - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - count -= 2; - } - if (count == 1) - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - } - } - } - else - if (d->TransferMode == 3 || d->TransferMode == 7) - { - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (count <= 1) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (count <= 2) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (count <= 3) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - count -= 4; - } while (count > 0); - } - else - if (d->TransferMode == 4) - { - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (count <= 1) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (count <= 2) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2102 + d->BAddress); - p += inc; - if (count <= 3) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2103 + d->BAddress); - p += inc; - CHECK_SOUND(); - count -= 4; - } while (count > 0); - } - } - else - { - /* XXX: DMA is potentially broken here for cases where the dest is - * XXX: in the Address Bus B range. Note that this bad dest may not - * XXX: cover the whole range of the DMA though, if we transfer - * XXX: 65536 bytes only 256 of them may be Address Bus B. - */ - do - { - switch (d->TransferMode) - { - case 0: - case 2: - case 6: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - --count; - break; - - case 1: - case 5: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; - - case 3: - case 7: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; - - case 4: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2102 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2103 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; - - default: - count = 0; - break; - } - CHECK_SOUND(); - } while (count); - } - -#ifdef SPC700_C - IAPU.APUExecuting = Settings.APUEnabled; - APU_EXECUTE (); -#endif - if (Settings.SuperFX) - while (CPU.Cycles > CPU.NextEvent) - S9xDoHBlankProcessing_SFX (); - else /* if (!Settings.SuperFX) */ - while (CPU.Cycles > CPU.NextEvent) - S9xDoHBlankProcessing_NoSFX (); - - if(Settings.SPC7110&&spc7110_dma) - { - if(spc7110_dma&&s7_wrap) - delete [] spc7110_dma; - } - -update_address: - // Super Punch-Out requires that the A-BUS address be updated after the - // DMA transfer. - Memory.FillRAM[0x4302 + (Channel << 4)] = (uint8) d->AAddress; - Memory.FillRAM[0x4303 + (Channel << 4)] = d->AAddress >> 8; - - // Secret of the Mana requires that the DMA bytes transfer count be set to - // zero when DMA has completed. - Memory.FillRAM [0x4305 + (Channel << 4)] = 0; - Memory.FillRAM [0x4306 + (Channel << 4)] = 0; - - DMA[Channel].IndirectAddress = 0; - d->TransferBytes = 0; - - CPU.InDMA = FALSE; - - -} - -void S9xStartHDMA () -{ - if (Settings.DisableHDMA) - IPPU.HDMA = 0; - else - missing.hdma_this_frame = IPPU.HDMA = Memory.FillRAM [0x420c]; - - //per anomie timing post - if(IPPU.HDMA!=0) - CPU.Cycles+=ONE_CYCLE*3; - - IPPU.HDMAStarted = TRUE; - - for (uint8 i = 0; i < 8; i++) - { - if (IPPU.HDMA & (1 << i)) - { - CPU.Cycles+=SLOW_ONE_CYCLE ; - DMA [i].LineCount = 0; - DMA [i].FirstLine = TRUE; - DMA [i].Address = DMA [i].AAddress; - if(DMA[i].HDMAIndirectAddressing) - CPU.Cycles+=(SLOW_ONE_CYCLE <<2); - } - HDMAMemPointers [i] = NULL; -#ifdef SETA010_HDMA_FROM_CART - HDMARawPointers [i] = 0; -#endif - } -} - -uint8 S9xDoHDMA (uint8 byte) -{ - struct SDMA *p = &DMA [0]; - - int d = 0; - - CPU.InDMA = TRUE; - CPU.Cycles+=ONE_CYCLE*3; - for (uint8 mask = 1; mask; mask <<= 1, p++, d++) - { - if (byte & mask) - { - if (!p->LineCount) - { - //remember, InDMA is set. - //Get/Set incur no charges! - CPU.Cycles+=SLOW_ONE_CYCLE; - uint8 line = S9xGetByte ((p->ABank << 16) + p->Address); - if (line == 0x80) - { - p->Repeat = TRUE; - p->LineCount = 128; - } - else - { - p->Repeat = !(line & 0x80); - p->LineCount = line & 0x7f; - } - - // Disable H-DMA'ing into V-RAM (register 2118) for Hook - /* XXX: instead of p->BAddress == 0x18, make S9xSetPPU fail - * XXX: writes to $2118/9 when appropriate - */ -#ifdef SETA010_HDMA_FROM_CART - if (!p->LineCount) -#else - if (!p->LineCount || p->BAddress == 0x18) -#endif - { - byte &= ~mask; - p->IndirectAddress += HDMAMemPointers [d] - HDMABasePointers [d]; - Memory.FillRAM [0x4305 + (d << 4)] = (uint8) p->IndirectAddress; - Memory.FillRAM [0x4306 + (d << 4)] = p->IndirectAddress >> 8; - continue; - } - - p->Address++; - p->FirstLine = 1; - if (p->HDMAIndirectAddressing) - { - p->IndirectBank = Memory.FillRAM [0x4307 + (d << 4)]; - //again, no cycle charges while InDMA is set! - CPU.Cycles+=SLOW_ONE_CYCLE<<2; - p->IndirectAddress = S9xGetWord ((p->ABank << 16) + p->Address); - p->Address += 2; - } - else - { - p->IndirectBank = p->ABank; - p->IndirectAddress = p->Address; - } - HDMABasePointers [d] = HDMAMemPointers [d] = - S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress); -#ifdef SETA010_HDMA_FROM_CART - HDMARawPointers [d] = (p->IndirectBank << 16) + p->IndirectAddress; -#endif - } - else - { - CPU.Cycles += SLOW_ONE_CYCLE; - } - - if (!HDMAMemPointers [d]) - { - if (!p->HDMAIndirectAddressing) - { - p->IndirectBank = p->ABank; - p->IndirectAddress = p->Address; - } -#ifdef SETA010_HDMA_FROM_CART - HDMARawPointers [d] = (p->IndirectBank << 16) + p->IndirectAddress; -#endif - if (!(HDMABasePointers [d] = HDMAMemPointers [d] = - S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress))) - { - /* XXX: Instead of this, goto a slow path that first - * XXX: verifies src!=Address Bus B, then uses - * XXX: S9xGetByte(). Or make S9xGetByte return OpenBus - * XXX: (probably?) for Address Bus B while inDMA. - */ - byte &= ~mask; - continue; - } - // Uncommenting the following line breaks Punchout - it starts - // H-DMA during the frame. - //p->FirstLine = TRUE; - } - if (p->Repeat && !p->FirstLine) - { - p->LineCount--; - continue; - } - - if (p->BAddress == 0x04){ - if(SNESGameFixes.Uniracers){ - PPU.OAMAddr = 0x10c; - PPU.OAMFlip=0; - } - } - - switch (p->TransferMode) - { - case 0: - CPU.Cycles += SLOW_ONE_CYCLE; -#ifdef SETA010_HDMA_FROM_CART - S9xSetPPU (S9xGetByte (HDMARawPointers [d]++), 0x2100 + p->BAddress); - HDMAMemPointers [d]++; -#else - S9xSetPPU (*HDMAMemPointers [d]++, 0x2100 + p->BAddress); -#endif - break; - case 5: - CPU.Cycles += 2*SLOW_ONE_CYCLE; -#ifdef SETA010_HDMA_FROM_CART - S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2101 + p->BAddress); - HDMARawPointers [d] += 2; -#else - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); -#endif - HDMAMemPointers [d] += 2; - /* fall through */ - case 1: - CPU.Cycles += 2*SLOW_ONE_CYCLE; -#ifdef SETA010_HDMA_FROM_CART - S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2101 + p->BAddress); - HDMARawPointers [d] += 2; -#else - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); -#endif - HDMAMemPointers [d] += 2; - break; - case 2: - case 6: - CPU.Cycles += 2*SLOW_ONE_CYCLE; -#ifdef SETA010_HDMA_FROM_CART - S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2100 + p->BAddress); - HDMARawPointers [d] += 2; -#else - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); -#endif - HDMAMemPointers [d] += 2; - break; - case 3: - case 7: - CPU.Cycles += 4*SLOW_ONE_CYCLE; -#ifdef SETA010_HDMA_FROM_CART - S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2100 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 2), 0x2101 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 3), 0x2101 + p->BAddress); - HDMARawPointers [d] += 4; -#else - 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); -#endif - HDMAMemPointers [d] += 4; - break; - case 4: - CPU.Cycles += 4*SLOW_ONE_CYCLE; -#ifdef SETA010_HDMA_FROM_CART - S9xSetPPU (S9xGetByte (HDMARawPointers [d]), 0x2100 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 1), 0x2101 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 2), 0x2102 + p->BAddress); - S9xSetPPU (S9xGetByte (HDMARawPointers [d] + 3), 0x2103 + p->BAddress); - HDMARawPointers [d] += 4; -#else - 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); -#endif - HDMAMemPointers [d] += 4; - break; - } - if (!p->HDMAIndirectAddressing) - p->Address += HDMA_ModeByteCounts [p->TransferMode]; - p->IndirectAddress += HDMA_ModeByteCounts [p->TransferMode]; - /* XXX: Check for p->IndirectAddress crossing a mapping boundry, - * XXX: and invalidate HDMAMemPointers[d] - */ - p->FirstLine = FALSE; - p->LineCount--; - } - } - CPU.InDMA=FALSE; - return (byte); -} - -void S9xResetDMA () -{ - int d; - for (d = 0; d < 8; d++) - { - DMA [d].TransferDirection = FALSE; - DMA [d].HDMAIndirectAddressing = FALSE; - DMA [d].AAddressFixed = TRUE; - DMA [d].AAddressDecrement = FALSE; - DMA [d].TransferMode = 0xff; - DMA [d].ABank = 0xff; - DMA [d].AAddress = 0xffff; - DMA [d].Address = 0xffff; - DMA [d].BAddress = 0xff; - DMA [d].TransferBytes = 0xffff; - } - for (int c = 0x4300; c < 0x4380; c += 0x10) - { - for (d = c; d < c + 12; d++) - Memory.FillRAM [d] = 0xff; - - Memory.FillRAM [c + 0xf] = 0xff; - } -} diff --git a/source/dsp1.c b/source/dsp1.c new file mode 100644 index 0000000..4e32a54 --- /dev/null +++ b/source/dsp1.c @@ -0,0 +1,1440 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include "snes9x.h" +#include "dsp1.h" +#include "missing.h" +#include "memmap.h" +#include + +#include "dsp1emu.c" +#include "dsp2emu.c" + +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; +} + +uint8 S9xGetDSP (uint16 address) +{ + uint8 t; + + t=(*GetDSP)(address); + //DSP1GetByte(address); + return (t); +} + +void S9xSetDSP (uint8 byte, uint16 address) +{ + (*SetDSP)(byte, address); + //DSP1SetByte(byte, address); +} + +void DSP1SetByte(uint8 byte, uint16 address) +{ + if( (address & 0xf000) == 0x6000 || (address & 0x7fff) < 0x4000 ) + { +// if ((address & 1) == 0) +// { + if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) + { + DSP1.out_count--; + DSP1.out_index++; + return; + } + else if (DSP1.waiting4command) + { + 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 + 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; + } + DSP1.in_count<<=1; + } + else + { + DSP1.parameters [DSP1.in_index] = byte; + DSP1.first_parameter = FALSE; + DSP1.in_index++; + } + + 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.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; + 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)); + + 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) (Op06S&0xFF); + DSP1.output [5] = (uint8) ((Op06S>>8)&0xFF); + break; + + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: // Target + Op0EH = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0EV = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp0E (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op0EX&0xFF); + DSP1.output [1] = (uint8) ((Op0EX>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0EY&0xFF); + DSP1.output [3] = (uint8) ((Op0EY>>8)&0xFF); + break; + + // Extra commands used by Pilot Wings + case 0x05: + case 0x35: + case 0x31: + case 0x01: // Set attitude matrix A + Op01m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op01Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op01Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op01Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp01 (); + break; + + case 0x15: + case 0x11: // Set attitude matrix B + Op11m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op11Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op11Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op11Xr = (int16) (DSP1.parameters [7]|(DSP1.parameters[7]<<8)); + + DSPOp11 (); + break; + + case 0x25: + case 0x21: // Set attitude matrix C + Op21m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op21Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op21Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op21Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp21 (); + break; + + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: // Objective matrix A + Op0DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op0DF&0xFF); + DSP1.output [1] = (uint8) ((Op0DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0DL&0xFF); + DSP1.output [3] = (uint8) ((Op0DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op0DU&0xFF); + DSP1.output [5] = (uint8) ((Op0DU>>8)&0xFF); + break; + + case 0x19: + case 0x1d: // Objective matrix B + Op1DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op1DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp1D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op1DF&0xFF); + DSP1.output [1] = (uint8) ((Op1DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op1DL&0xFF); + DSP1.output [3] = (uint8) ((Op1DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op1DU&0xFF); + DSP1.output [5] = (uint8) ((Op1DU>>8)&0xFF); + break; + + case 0x29: + case 0x2d: // Objective matrix C + Op2DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op2DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op2DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp2D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op2DF&0xFF); + DSP1.output [1] = (uint8) ((Op2DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op2DL&0xFF); + DSP1.output [3] = (uint8) ((Op2DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op2DU&0xFF); + DSP1.output [5] = (uint8) ((Op2DU>>8)&0xFF); + break; + + case 0x33: + case 0x03: // Subjective matrix A + Op03F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op03L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op03U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp03 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op03X&0xFF); + DSP1.output [1] = (uint8) ((Op03X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op03Y&0xFF); + DSP1.output [3] = (uint8) ((Op03Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op03Z&0xFF); + DSP1.output [5] = (uint8) ((Op03Z>>8)&0xFF); + break; + + case 0x13: // Subjective matrix B + Op13F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op13L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op13U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp13 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op13X&0xFF); + DSP1.output [1] = (uint8) ((Op13X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op13Y&0xFF); + DSP1.output [3] = (uint8) ((Op13Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op13Z&0xFF); + DSP1.output [5] = (uint8) ((Op13Z>>8)&0xFF); + break; + + case 0x23: // Subjective matrix C + Op23F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op23L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op23U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp23 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op23X&0xFF); + DSP1.output [1] = (uint8) ((Op23X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op23Y&0xFF); + DSP1.output [3] = (uint8) ((Op23Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op23Z&0xFF); + DSP1.output [5] = (uint8) ((Op23Z>>8)&0xFF); + break; + + case 0x3b: + case 0x0b: + Op0BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op0BS&0xFF); + DSP1.output [1] = (uint8) ((Op0BS>>8)&0xFF); + break; + + case 0x1b: + Op1BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op1BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp1B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op1BS&0xFF); + DSP1.output [1] = (uint8) ((Op1BS>>8)&0xFF); + break; + + case 0x2b: + Op2BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op2BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op2BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp2B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op2BS&0xFF); + DSP1.output [1] = (uint8) ((Op2BS>>8)&0xFF); + break; + + case 0x34: + case 0x14: + Op14Zr = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op14Xr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op14Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op14U = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op14F = (int16) (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op14L = (int16) (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + + DSPOp14 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op14Zrr&0xFF); + DSP1.output [1] = (uint8) ((Op14Zrr>>8)&0xFF); + DSP1.output [2] = (uint8) (Op14Xrr&0xFF); + DSP1.output [3] = (uint8) ((Op14Xrr>>8)&0xFF); + DSP1.output [4] = (uint8) (Op14Yrr&0xFF); + DSP1.output [5] = (uint8) ((Op14Yrr>>8)&0xFF); + break; + + case 0x27: + case 0x2F: + Op2FUnknown = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp2F (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8)(Op2FSize&0xFF); + DSP1.output [1] = (uint8)((Op2FSize>>8)&0xFF); + break; + + + case 0x07: + case 0x0F: + Op0FRamsize = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp0F (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8)(Op0FPass&0xFF); + DSP1.output [1] = (uint8)((Op0FPass>>8)&0xFF); + break; + + default: + break; + } + } + } + } + } +} + +uint8 DSP1GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || +// (address >= 0x8000 && address < 0xc000)) + (address&0x7fff) < 0x4000) + { + 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 t; + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP1.out_count) + { + t = (uint8) DSP1.output [DSP1.out_index]; + DSP1.out_index++; + if(DSP1.out_count==DSP1.out_index) + DSP1.out_count=0; + } + else + { + t = 0xff; + } + } + else t = 0x80; + return t; +} + +//Disable non-working chips? +#ifdef DSP_DUMMY_LOOPS +//static const uint16 DSP1ROM[1024] from SNES9X v1.53 +uint16 Dsp3Rom[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 + +}; + +void DSP3SetByte(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 0x2F:DSP1.in_count=2;break; + case 0x1F:DSP1.in_count=2;break; + case 0x0F:DSP1.in_count=2;break; + case 0x38:DSP1.in_count=4;break; + default: +// printf("Op%02X\n",byte); + 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 0x2F:DSP1.out_count=2;break; + case 0x1F:DSP1.out_count=2048;break; + case 0x0F:DSP1.out_count=2; + DSP1.output[0]=0; + DSP1.output[1]=0; + break; + case 0x38: + { + DSP1.out_count=2; + // 176B + DSP1.output[0]=0; + DSP1.output[1]=0x80; + + break; + } + default: + break; + } + } + } +} + +uint8 DSP3GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if(DSP1.command==0x38&&DSP1.out_index==1) + { + t=4; + } + + if (DSP1.out_count) + { + if(DSP1.command==0x1f) + { + if((DSP1.out_index%2)!=0) + { + t=(uint8)Dsp3Rom[DSP1.out_index>>1]; + } + else + { + t=Dsp3Rom[DSP1.out_index>>1]>>8; + } +// t=Dsp3Rom[DSP1.out_index]; + DSP1.out_index++; + } + else + { + t = (uint8) DSP1.output [DSP1.out_index]; + DSP1.out_index++; + DSP1.out_index%=512; + if(DSP1.out_count==DSP1.out_index) + DSP1.out_count=0; + } + } + else + { + t = 0xff; + } + } + else + { + t = 0x80; +/* if(DSP1.command=0x38&&DSP1.out_count==0) + { + t=0xC0; + static int Op38c; + if(Op38c==14) + { + Op38c=0; + t=0x80; + DSP1.in_count=4; + } + Op38c++; + }*/ + } + return t; +} + +#endif + +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]; +}; + +SDSP4 DSP4; + +#include "dsp4emu.cpp" + +bool DSP4_init=FALSE; + +void DSP4SetByte(uint8 byte, uint16 address) +{ + if(!DSP4_init) + { + // bootup + DSP4.waiting4command=1; + DSP4_init=TRUE; + } + + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if(DSP4.out_index>16); + } + break; + + // unknown: horizontal mapping command + case 0x0011: + { + int16 a,b,c,d,m; + + a = DSP4_READ_WORD(6); + b = DSP4_READ_WORD(4); + c = DSP4_READ_WORD(2); + d = DSP4_READ_WORD(0); + + DSP4_UnknownOP11(a,b,c,d,m); + + DSP4.out_count = 2; + DSP4_WRITE_WORD(0,m); + break; + } + + // track projection + case 0x0001: DSP4_Op01(); break; + + // track projection (pass 2) + case 0x0007: DSP4_Op07(); break; + + // zone projections (fuel/repair/lap/teleport/...) + case 0x0008: DSP4_Op08(); break; + + // sprite transformation + case 0x0009: DSP4_Op09(); break; + + // fast track projection + case 0x000D: DSP4_Op0D(); break; + + // internal memory management (01) + case 0x0003: + { + // reset op09 data + op09_mode = 0; + break; + } + + // internal memory management (06) + case 0x0005: + { + // clear OAM tables + op06_index = 0; + op06_offset = 0; + for( int lcv=0; lcv<32; lcv++ ) + op06_OAM[lcv] = 0; + break; + } + + // internal memory management (0D) + case 0x000E: + { + // reset op09 data + op09_mode = 1; + break; + } + + // sprite OAM post-table data + case 0x0006: + { + DSP4.out_count = 32; + for( int lcv=0; lcv<32; lcv++ ) + DSP4.output[lcv] = op06_OAM[lcv]; + } + break; + + // unknown + case 0x000A: + { + int16 in1a = DSP4_READ_WORD(0); + int16 in2a = DSP4_READ_WORD(2); + int16 in3a = DSP4_READ_WORD(4); + int16 out1a,out2a; + + out1a=(short)0xff40; + out2a=(short)0x00c0; + + DSP4.out_count=8; + + DSP4_WRITE_WORD(0,out1a); + DSP4_WRITE_WORD(2,out2a); + DSP4_WRITE_WORD(4,out1a); + DSP4_WRITE_WORD(6,out2a); + } + break; + + // render player positions around track + case 0x000B: + { + int16 sp_x = DSP4_READ_WORD(0); + int16 sp_y = DSP4_READ_WORD(2); + int16 oam = DSP4_READ_WORD(4); + + // Only allow 1p/1p-split to yield output (???) + if(!op09_mode) + { + // yield OAM output + DSP4.out_count = 6; + DSP4_WRITE_WORD(0,1); + + // pack OAM data: x,y,name,attr + DSP4.output[2] = sp_x & 0xff; + DSP4.output[3] = sp_y & 0xff; + DSP4_WRITE_WORD(4,oam); + + // OAM: size,msb data + DSP4_Op06(0,0); + } + // 4p mode + else + { + // no OAM available + DSP4.out_count=0; + DSP4_WRITE_WORD(0,0); + } + } + break; + + default: break; + } + } + } +} + +uint8 DSP4GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP4.out_count) + { + t = (uint8) DSP4.output [DSP4.out_index]; + DSP4.out_index++; + if(DSP4.out_count==DSP4.out_index) + DSP4.out_count=0; + } + else + t = 0xff; + } + else + { + t = 0x80; + } + + return t; +} + diff --git a/source/dsp1.cpp b/source/dsp1.cpp deleted file mode 100644 index 4e32a54..0000000 --- a/source/dsp1.cpp +++ /dev/null @@ -1,1440 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include "snes9x.h" -#include "dsp1.h" -#include "missing.h" -#include "memmap.h" -#include - -#include "dsp1emu.c" -#include "dsp2emu.c" - -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; -} - -uint8 S9xGetDSP (uint16 address) -{ - uint8 t; - - t=(*GetDSP)(address); - //DSP1GetByte(address); - return (t); -} - -void S9xSetDSP (uint8 byte, uint16 address) -{ - (*SetDSP)(byte, address); - //DSP1SetByte(byte, address); -} - -void DSP1SetByte(uint8 byte, uint16 address) -{ - if( (address & 0xf000) == 0x6000 || (address & 0x7fff) < 0x4000 ) - { -// if ((address & 1) == 0) -// { - if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) - { - DSP1.out_count--; - DSP1.out_index++; - return; - } - else if (DSP1.waiting4command) - { - 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 - 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; - } - DSP1.in_count<<=1; - } - else - { - DSP1.parameters [DSP1.in_index] = byte; - DSP1.first_parameter = FALSE; - DSP1.in_index++; - } - - 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.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; - 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)); - - 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) (Op06S&0xFF); - DSP1.output [5] = (uint8) ((Op06S>>8)&0xFF); - break; - - case 0x1e: - case 0x2e: - case 0x3e: - case 0x0e: // Target - Op0EH = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0EV = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - - DSPOp0E (); - - DSP1.out_count = 4; - DSP1.output [0] = (uint8) (Op0EX&0xFF); - DSP1.output [1] = (uint8) ((Op0EX>>8)&0xFF); - DSP1.output [2] = (uint8) (Op0EY&0xFF); - DSP1.output [3] = (uint8) ((Op0EY>>8)&0xFF); - break; - - // Extra commands used by Pilot Wings - case 0x05: - case 0x35: - case 0x31: - case 0x01: // Set attitude matrix A - Op01m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op01Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op01Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op01Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - - DSPOp01 (); - break; - - case 0x15: - case 0x11: // Set attitude matrix B - Op11m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op11Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op11Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op11Xr = (int16) (DSP1.parameters [7]|(DSP1.parameters[7]<<8)); - - DSPOp11 (); - break; - - case 0x25: - case 0x21: // Set attitude matrix C - Op21m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op21Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op21Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op21Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - - DSPOp21 (); - break; - - case 0x09: - case 0x39: - case 0x3d: - case 0x0d: // Objective matrix A - Op0DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op0DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp0D (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op0DF&0xFF); - DSP1.output [1] = (uint8) ((Op0DF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op0DL&0xFF); - DSP1.output [3] = (uint8) ((Op0DL>>8)&0xFF); - DSP1.output [4] = (uint8) (Op0DU&0xFF); - DSP1.output [5] = (uint8) ((Op0DU>>8)&0xFF); - break; - - case 0x19: - case 0x1d: // Objective matrix B - Op1DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op1DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op1DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp1D (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op1DF&0xFF); - DSP1.output [1] = (uint8) ((Op1DF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op1DL&0xFF); - DSP1.output [3] = (uint8) ((Op1DL>>8)&0xFF); - DSP1.output [4] = (uint8) (Op1DU&0xFF); - DSP1.output [5] = (uint8) ((Op1DU>>8)&0xFF); - break; - - case 0x29: - case 0x2d: // Objective matrix C - Op2DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op2DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op2DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp2D (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op2DF&0xFF); - DSP1.output [1] = (uint8) ((Op2DF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op2DL&0xFF); - DSP1.output [3] = (uint8) ((Op2DL>>8)&0xFF); - DSP1.output [4] = (uint8) (Op2DU&0xFF); - DSP1.output [5] = (uint8) ((Op2DU>>8)&0xFF); - break; - - case 0x33: - case 0x03: // Subjective matrix A - Op03F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op03L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op03U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp03 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op03X&0xFF); - DSP1.output [1] = (uint8) ((Op03X>>8)&0xFF); - DSP1.output [2] = (uint8) (Op03Y&0xFF); - DSP1.output [3] = (uint8) ((Op03Y>>8)&0xFF); - DSP1.output [4] = (uint8) (Op03Z&0xFF); - DSP1.output [5] = (uint8) ((Op03Z>>8)&0xFF); - break; - - case 0x13: // Subjective matrix B - Op13F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op13L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op13U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp13 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op13X&0xFF); - DSP1.output [1] = (uint8) ((Op13X>>8)&0xFF); - DSP1.output [2] = (uint8) (Op13Y&0xFF); - DSP1.output [3] = (uint8) ((Op13Y>>8)&0xFF); - DSP1.output [4] = (uint8) (Op13Z&0xFF); - DSP1.output [5] = (uint8) ((Op13Z>>8)&0xFF); - break; - - case 0x23: // Subjective matrix C - Op23F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op23L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op23U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp23 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op23X&0xFF); - DSP1.output [1] = (uint8) ((Op23X>>8)&0xFF); - DSP1.output [2] = (uint8) (Op23Y&0xFF); - DSP1.output [3] = (uint8) ((Op23Y>>8)&0xFF); - DSP1.output [4] = (uint8) (Op23Z&0xFF); - DSP1.output [5] = (uint8) ((Op23Z>>8)&0xFF); - break; - - case 0x3b: - case 0x0b: - Op0BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op0BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp0B (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op0BS&0xFF); - DSP1.output [1] = (uint8) ((Op0BS>>8)&0xFF); - break; - - case 0x1b: - Op1BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op1BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op1BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp1B (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op1BS&0xFF); - DSP1.output [1] = (uint8) ((Op1BS>>8)&0xFF); - break; - - case 0x2b: - Op2BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op2BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op2BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp2B (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op2BS&0xFF); - DSP1.output [1] = (uint8) ((Op2BS>>8)&0xFF); - break; - - case 0x34: - case 0x14: - Op14Zr = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op14Xr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op14Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op14U = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - Op14F = (int16) (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); - Op14L = (int16) (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); - - DSPOp14 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op14Zrr&0xFF); - DSP1.output [1] = (uint8) ((Op14Zrr>>8)&0xFF); - DSP1.output [2] = (uint8) (Op14Xrr&0xFF); - DSP1.output [3] = (uint8) ((Op14Xrr>>8)&0xFF); - DSP1.output [4] = (uint8) (Op14Yrr&0xFF); - DSP1.output [5] = (uint8) ((Op14Yrr>>8)&0xFF); - break; - - case 0x27: - case 0x2F: - Op2FUnknown = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - - DSPOp2F (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8)(Op2FSize&0xFF); - DSP1.output [1] = (uint8)((Op2FSize>>8)&0xFF); - break; - - - case 0x07: - case 0x0F: - Op0FRamsize = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - - DSPOp0F (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8)(Op0FPass&0xFF); - DSP1.output [1] = (uint8)((Op0FPass>>8)&0xFF); - break; - - default: - break; - } - } - } - } - } -} - -uint8 DSP1GetByte(uint16 address) -{ - uint8 t; - if ((address & 0xf000) == 0x6000 || -// (address >= 0x8000 && address < 0xc000)) - (address&0x7fff) < 0x4000) - { - 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 t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if (DSP1.out_count) - { - t = (uint8) DSP1.output [DSP1.out_index]; - DSP1.out_index++; - if(DSP1.out_count==DSP1.out_index) - DSP1.out_count=0; - } - else - { - t = 0xff; - } - } - else t = 0x80; - return t; -} - -//Disable non-working chips? -#ifdef DSP_DUMMY_LOOPS -//static const uint16 DSP1ROM[1024] from SNES9X v1.53 -uint16 Dsp3Rom[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 - -}; - -void DSP3SetByte(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 0x2F:DSP1.in_count=2;break; - case 0x1F:DSP1.in_count=2;break; - case 0x0F:DSP1.in_count=2;break; - case 0x38:DSP1.in_count=4;break; - default: -// printf("Op%02X\n",byte); - 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 0x2F:DSP1.out_count=2;break; - case 0x1F:DSP1.out_count=2048;break; - case 0x0F:DSP1.out_count=2; - DSP1.output[0]=0; - DSP1.output[1]=0; - break; - case 0x38: - { - DSP1.out_count=2; - // 176B - DSP1.output[0]=0; - DSP1.output[1]=0x80; - - break; - } - default: - break; - } - } - } -} - -uint8 DSP3GetByte(uint16 address) -{ - uint8 t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if(DSP1.command==0x38&&DSP1.out_index==1) - { - t=4; - } - - if (DSP1.out_count) - { - if(DSP1.command==0x1f) - { - if((DSP1.out_index%2)!=0) - { - t=(uint8)Dsp3Rom[DSP1.out_index>>1]; - } - else - { - t=Dsp3Rom[DSP1.out_index>>1]>>8; - } -// t=Dsp3Rom[DSP1.out_index]; - DSP1.out_index++; - } - else - { - t = (uint8) DSP1.output [DSP1.out_index]; - DSP1.out_index++; - DSP1.out_index%=512; - if(DSP1.out_count==DSP1.out_index) - DSP1.out_count=0; - } - } - else - { - t = 0xff; - } - } - else - { - t = 0x80; -/* if(DSP1.command=0x38&&DSP1.out_count==0) - { - t=0xC0; - static int Op38c; - if(Op38c==14) - { - Op38c=0; - t=0x80; - DSP1.in_count=4; - } - Op38c++; - }*/ - } - return t; -} - -#endif - -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]; -}; - -SDSP4 DSP4; - -#include "dsp4emu.cpp" - -bool DSP4_init=FALSE; - -void DSP4SetByte(uint8 byte, uint16 address) -{ - if(!DSP4_init) - { - // bootup - DSP4.waiting4command=1; - DSP4_init=TRUE; - } - - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if(DSP4.out_index>16); - } - break; - - // unknown: horizontal mapping command - case 0x0011: - { - int16 a,b,c,d,m; - - a = DSP4_READ_WORD(6); - b = DSP4_READ_WORD(4); - c = DSP4_READ_WORD(2); - d = DSP4_READ_WORD(0); - - DSP4_UnknownOP11(a,b,c,d,m); - - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,m); - break; - } - - // track projection - case 0x0001: DSP4_Op01(); break; - - // track projection (pass 2) - case 0x0007: DSP4_Op07(); break; - - // zone projections (fuel/repair/lap/teleport/...) - case 0x0008: DSP4_Op08(); break; - - // sprite transformation - case 0x0009: DSP4_Op09(); break; - - // fast track projection - case 0x000D: DSP4_Op0D(); break; - - // internal memory management (01) - case 0x0003: - { - // reset op09 data - op09_mode = 0; - break; - } - - // internal memory management (06) - case 0x0005: - { - // clear OAM tables - op06_index = 0; - op06_offset = 0; - for( int lcv=0; lcv<32; lcv++ ) - op06_OAM[lcv] = 0; - break; - } - - // internal memory management (0D) - case 0x000E: - { - // reset op09 data - op09_mode = 1; - break; - } - - // sprite OAM post-table data - case 0x0006: - { - DSP4.out_count = 32; - for( int lcv=0; lcv<32; lcv++ ) - DSP4.output[lcv] = op06_OAM[lcv]; - } - break; - - // unknown - case 0x000A: - { - int16 in1a = DSP4_READ_WORD(0); - int16 in2a = DSP4_READ_WORD(2); - int16 in3a = DSP4_READ_WORD(4); - int16 out1a,out2a; - - out1a=(short)0xff40; - out2a=(short)0x00c0; - - DSP4.out_count=8; - - DSP4_WRITE_WORD(0,out1a); - DSP4_WRITE_WORD(2,out2a); - DSP4_WRITE_WORD(4,out1a); - DSP4_WRITE_WORD(6,out2a); - } - break; - - // render player positions around track - case 0x000B: - { - int16 sp_x = DSP4_READ_WORD(0); - int16 sp_y = DSP4_READ_WORD(2); - int16 oam = DSP4_READ_WORD(4); - - // Only allow 1p/1p-split to yield output (???) - if(!op09_mode) - { - // yield OAM output - DSP4.out_count = 6; - DSP4_WRITE_WORD(0,1); - - // pack OAM data: x,y,name,attr - DSP4.output[2] = sp_x & 0xff; - DSP4.output[3] = sp_y & 0xff; - DSP4_WRITE_WORD(4,oam); - - // OAM: size,msb data - DSP4_Op06(0,0); - } - // 4p mode - else - { - // no OAM available - DSP4.out_count=0; - DSP4_WRITE_WORD(0,0); - } - } - break; - - default: break; - } - } - } -} - -uint8 DSP4GetByte(uint16 address) -{ - uint8 t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if (DSP4.out_count) - { - t = (uint8) DSP4.output [DSP4.out_index]; - DSP4.out_index++; - if(DSP4.out_count==DSP4.out_index) - DSP4.out_count=0; - } - else - t = 0xff; - } - else - { - t = 0x80; - } - - return t; -} - diff --git a/source/dsp4emu.c b/source/dsp4emu.c new file mode 100644 index 0000000..b36cadb --- /dev/null +++ b/source/dsp4emu.c @@ -0,0 +1,1483 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "dsp4.h" + +#define DSP4_READ_WORD(x) \ + READ_WORD(DSP4.parameters+x) + +#define DSP4_WRITE_WORD(x,d) \ + WRITE_WORD(DSP4.output+x,d); + +// used to wait for dsp i/o +#define DSP4_WAIT(x) \ + DSP4_Logic = x; return; + +////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////// + +void DSP4_Multiply(short Multiplicand, short Multiplier, int &Product) +{ + Product = Multiplicand * Multiplier; +} + +void DSP4_UnknownOP11(short A, short B, short C, short D, short &M) +{ + M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | + ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); +} + +////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////// + +void DSP4_Op06(bool8 size, bool8 msb) +{ + // save post-oam table data for future retrieval + op06_OAM[op06_index] |= (msb<<(op06_offset+0)); + op06_OAM[op06_index] |= (size<<(op06_offset+1)); + op06_offset += 2; + + if(op06_offset==8) + { + // move to next byte in buffer + op06_offset=0; + op06_index++; + } +} + +#if OP==0x0001 +#define PRINT +#endif + +void DSP4_Op01() +{ + uint16 command; + + DSP4.waiting4command = FALSE; + + // op flow control + switch(DSP4_Logic) { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + // 0x00 = DSP4_READ_WORD(0x00); + project_focaly = DSP4_READ_WORD(0x02); + raster = DSP4_READ_WORD(0x04); + viewport_top = DSP4_READ_WORD(0x06); + project_y = DSP4_READ_WORD(0x08); + viewport_bottom = DSP4_READ_WORD(0x0a); + project_x1low = DSP4_READ_WORD(0x0c); + project_focalx = DSP4_READ_WORD(0x0e); + project_centerx = DSP4_READ_WORD(0x10); + project_ptr = DSP4_READ_WORD(0x12); + // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); + project_pitchylow = DSP4_READ_WORD(0x16); + project_pitchy = DSP4_READ_WORD(0x18); + project_pitchxlow = DSP4_READ_WORD(0x1a); + project_pitchx = DSP4_READ_WORD(0x1c); + far_plane = DSP4_READ_WORD(0x1e); + // ? = DSP4_READ_WORD(0x20); + project_y1low = DSP4_READ_WORD(0x22); + + // pre-compute + view_plane = PLANE_START; + + // find starting projection points + project_x1 = project_focalx; + project_y -= viewport_bottom; + project_x = project_centerx + project_x1; + + // multi-op storage + multi_index1 = 0; + multi_index2 = 0; + + // debug + block=0; + + //////////////////////////////////////////////////// + // command check + + do { + // scan next command + DSP4.in_count = 2; + + DSP4_WAIT(1) resume1: + + // inspect input + command = DSP4_READ_WORD(0); + + // check for termination + if(command == 0x8000) break; + + // already have 2 bytes in queue + DSP4.in_index = 2; + DSP4.in_count = 8; + + DSP4_WAIT(2) resume2: + + //////////////////////////////////////////////////// + // process one iteration of projection + + // inspect inputs + int16 plane = DSP4_READ_WORD(0); + int16 index, lcv; + int16 py_dy=0, px_dx=0; + int16 y_out, x_out; + + // ignore invalid data + if((uint16) plane == 0x8001) continue; + + // one-time init + if(far_plane) + { + // setup final parameters + project_focalx += plane; + project_x1 = project_focalx; + project_y1 = project_focaly; + plane = far_plane; + far_plane = 0; + } + + // use proportional triangles to project new coords + project_x2 = project_focalx * plane / view_plane; + project_y2 = project_focaly * plane / view_plane; + + // quadratic regression (rough) + if(project_focaly>=-0x0f) + py_dy = (short) (project_focaly * project_focaly * -0.20533553 + - 1.08330005 * project_focaly - 69.61094639); + else + py_dy = (short) (project_focaly * project_focaly * -0.000657035759 + - 1.07629051 * project_focaly - 65.69315963); + + // approximate # of raster lines + segments = abs(project_y2-project_y1); + + // prevent overdraw + if(project_y2>=raster) segments=0; + else raster=project_y2; + + // don't draw outside the window + if(project_y20) + { + // interpolate between projected points + px_dx = ((project_x2-project_x1)<<8)/segments; + } + + // debug + ++block; +#ifdef PRINT + printf("(line %d) Op01 check %02X, plane %04X, focal_y %04X, y2 %04X\n",c,(uint16)segments,(uint16)(plane),(uint16)project_focaly,(uint16)project_y2); +#endif + + // prepare output + DSP4.out_count=8+2+6*segments; + + // pre-block data + DSP4_WRITE_WORD(0,project_focalx); + DSP4_WRITE_WORD(2,project_x2); + DSP4_WRITE_WORD(4,project_focaly); + DSP4_WRITE_WORD(6,project_y2); + DSP4_WRITE_WORD(8,segments); + +#if 0 + DSP4_WRITE_WORD(0,-1); + DSP4_WRITE_WORD(2,-1); + DSP4_WRITE_WORD(4,-1); + DSP4_WRITE_WORD(6,-1); + DSP4_WRITE_WORD(8,-1); +#endif + + index=10; + + // iterate through each point + for( lcv=0; lcv>8); + x_out = project_x+((px_dx*lcv)>>8); + +#if 0 + project_ptr=-1; + y_out=-1; + x_out=-1; +#endif + + // data + DSP4_WRITE_WORD(index+0,project_ptr); + DSP4_WRITE_WORD(index+2,y_out); + DSP4_WRITE_WORD(index+4,x_out); + index += 6; + + // post-update + project_ptr -= 4; + } + + // post-update + project_y += ((py_dy*lcv)>>8); + project_x += ((px_dx*lcv)>>8); + + // new positions + if(segments>0) + { + project_x1 = project_x2; + project_y1 = project_y2; + + // multi-op storage + multi_focaly[multi_index2++] = project_focaly; + multi_farplane[1] = plane; + multi_raster[1] = project_y1-1; + } + + // update projection points + project_pitchy += (int8)DSP4.parameters[3]; + project_pitchx += (int8)DSP4.parameters[5]; + + project_focaly += project_pitchy; + project_focalx += project_pitchx; + } while (1); + + // terminate op + DSP4.waiting4command = TRUE; + DSP4.out_count = 0; +} + +#undef PRINT + +#if OP==0x0007 +#define PRINT +#endif + +void DSP4_Op07() +{ + uint16 command; + + DSP4.waiting4command = FALSE; + + // op flow control + switch(DSP4_Logic) { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + // 0x00 = DSP4_READ_WORD(0x00); + project_focaly = DSP4_READ_WORD(0x02); + raster = DSP4_READ_WORD(0x04); + viewport_top = DSP4_READ_WORD(0x06); + project_y = DSP4_READ_WORD(0x08); + viewport_bottom = DSP4_READ_WORD(0x0a); + project_x1low = DSP4_READ_WORD(0x0c); + project_x1 = DSP4_READ_WORD(0x0e); + project_centerx = DSP4_READ_WORD(0x10); + project_ptr = DSP4_READ_WORD(0x12); + // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); + + // pre-compute + view_plane = PLANE_START; + + // find projection targets + project_y1 = project_focaly; + project_y -= viewport_bottom; + project_x = project_centerx + project_x1; + + // multi-op storage + multi_index2 = 0; + + // debug + block=0; + +#ifdef PRINT + printf("(line %d) Op07 data %04X\n",c,(uint16)project_y1); +#endif + + //////////////////////////////////////////////////// + // command check + + do { + // scan next command + DSP4.in_count = 2; + + DSP4_WAIT(1) resume1: + + // inspect input + command = DSP4_READ_WORD(0); + + // check for opcode termination + if(command == 0x8000) break; + + // already have 2 bytes in queue + DSP4.in_index = 2; + DSP4.in_count = 12; + + DSP4_WAIT(2) resume2: + + //////////////////////////////////////////////////// + // process one loop of projection + + int16 plane; + int16 index,lcv; + int16 y_out,x_out; + int16 py_dy=0,px_dx=0; + + // debug + ++block; + + // inspect inputs + plane = DSP4_READ_WORD(0); + project_y2 = DSP4_READ_WORD(2); + // ? = DSP4_READ_WORD(4); + project_x2 = DSP4_READ_WORD(6); + + // ignore invalid data + if((uint16) plane == 0x8001) continue; + + // multi-op storage + project_focaly = multi_focaly[multi_index2]; + + // quadratic regression (rough) + if(project_focaly>=-0x0f) + py_dy = (short) (project_focaly * project_focaly * -0.20533553 + - 1.08330005 * project_focaly - 69.61094639); + else + py_dy = (short) (project_focaly * project_focaly * -0.000657035759 + - 1.07629051 * project_focaly - 65.69315963); + + // approximate # of raster lines + segments = abs(project_y2-project_y1); + + // prevent overdraw + if(project_y2>=raster) segments=0; + else raster=project_y2; + + // don't draw outside the window + if(project_y20) + { + // interpolate between projected points + px_dx = ((project_x2-project_x1)<<8)/segments; + } + +#ifdef PRINT + printf("(line %d) Op07 block %d, loc %04X, out %02X, project_x2 %04X\n",c,block,plane,segments,(uint16)project_x2); +#endif + + // prepare pre-output + DSP4.out_count=4+2+6*segments; + + DSP4_WRITE_WORD(0,project_x2); + DSP4_WRITE_WORD(2,project_y2); + DSP4_WRITE_WORD(4,segments); + +#if 0 + DSP4_WRITE_WORD(0,-1); + DSP4_WRITE_WORD(2,-1); + DSP4_WRITE_WORD(4,-1); +#endif + + index=6; + for( lcv=0; lcv>8); + x_out = project_x+((px_dx*lcv)>>8); + +#if 0 + project_ptr = -1; + //y_out = -1; + x_out = -1; +#endif + + // data + DSP4_WRITE_WORD(index+0,project_ptr); + DSP4_WRITE_WORD(index+2,y_out); + DSP4_WRITE_WORD(index+4,x_out); + index += 6; + + // post-update + project_ptr -= 4; + } + + // update internal variables + project_y += ((py_dy*lcv)>>8); + project_x += ((px_dx*lcv)>>8); + + // new positions + if(segments>0) + { + project_x1 = project_x2; + project_y1 = project_y2; + + // multi-op storage + multi_index2++; + } + } while(1); + + DSP4.waiting4command = TRUE; + DSP4.out_count = 0; +} + +#undef PRINT + +#if OP==0x0008 +#define PRINT +#endif + +void DSP4_Op08() +{ + uint16 command; + + DSP4.waiting4command = FALSE; + + // op flow control + switch(DSP4_Logic) { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // clip values + path_clipRight[0] = DSP4_READ_WORD(0x00); + path_clipRight[1] = DSP4_READ_WORD(0x02); + path_clipRight[2] = DSP4_READ_WORD(0x04); + path_clipRight[3] = DSP4_READ_WORD(0x06); + + path_clipLeft[0] = DSP4_READ_WORD(0x08); + path_clipLeft[1] = DSP4_READ_WORD(0x0a); + path_clipLeft[2] = DSP4_READ_WORD(0x0c); + path_clipLeft[3] = DSP4_READ_WORD(0x0e); + + // unknown (constant) + // unknown (constant) + + // path positions + path_pos[0] = DSP4_READ_WORD(0x20); + path_pos[1] = DSP4_READ_WORD(0x22); + path_pos[2] = DSP4_READ_WORD(0x24); + path_pos[3] = DSP4_READ_WORD(0x26); + + // data locations + path_ptr[0] = DSP4_READ_WORD(0x28); + path_ptr[1] = DSP4_READ_WORD(0x2a); + path_ptr[2] = DSP4_READ_WORD(0x2c); + path_ptr[3] = DSP4_READ_WORD(0x2e); + + // project_y1 lines + path_raster[0] = DSP4_READ_WORD(0x30); + path_raster[1] = DSP4_READ_WORD(0x32); + path_raster[2] = DSP4_READ_WORD(0x34); + path_raster[3] = DSP4_READ_WORD(0x36); + + // viewport_top + path_top[0] = DSP4_READ_WORD(0x38); + path_top[1] = DSP4_READ_WORD(0x3a); + path_top[2] = DSP4_READ_WORD(0x3c); + path_top[3] = DSP4_READ_WORD(0x3e); + + // unknown (constants) + + view_plane = PLANE_START; + + // debug + block=0; + + //////////////////////////////////////////////////// + // command check + + do { + // scan next command + DSP4.in_count = 2; + + DSP4_WAIT(1) resume1: + + // inspect input + command = DSP4_READ_WORD(0); + + // terminate op + if(command == 0x8000) break; + + // already have 2 bytes in queue + DSP4.in_index = 2; + DSP4.in_count = 18; + + DSP4_WAIT(2) resume2: + + //////////////////////////////////////////////////// + // projection begins + + // debug + ++block; + + // used in envelope shaping + int16 x1_final; + int16 x2_final; + + // look at guidelines + int16 plane = DSP4_READ_WORD(0x00); + int16 x_left = DSP4_READ_WORD(0x02); + int16 y_left = DSP4_READ_WORD(0x04); + int16 x_right = DSP4_READ_WORD(0x06); + int16 y_right = DSP4_READ_WORD(0x08); + + // envelope guidelines (one frame only) + int16 envelope1 = DSP4_READ_WORD(0x0a); + int16 envelope2 = DSP4_READ_WORD(0x0c); + + // ignore invalid data + if((uint16) plane == 0x8001) continue; + + // first init + if(plane == 0x7fff) + { + int pos1,pos2; + + // initialize projection + path_x[0] = x_left; + path_x[1] = x_right; + + path_y[0] = y_left; + path_y[1] = y_right; + + // update coordinates + path_pos[0]-=x_left; + path_pos[1]-=x_left; + path_pos[2]-=x_right; + path_pos[3]-=x_right; + + pos1 = path_pos[0]+envelope1; + pos2 = path_pos[1]+envelope2; + + // clip offscreen data + if(pos1path_clipRight[0]) pos1 = path_clipRight[0]; + if(pos2path_clipRight[1]) pos2 = path_clipRight[1]; + +#if 0 + pos1=-1; + //pos2=-1; +#endif + + path_plane[0] = plane; + path_plane[1] = plane; + + // initial output + DSP4.out_count = 2; + DSP4.output[0]=pos1&0xFF; + DSP4.output[1]=pos2&0xFF; + +#ifdef PRINT + printf("(line %d) Op08 x_left %04X\n",c,(uint16)x_left); +#endif + } + // proceed with projection + else + { + int16 index=0, lcv; + int16 left_inc=0,right_inc=0; + int16 dx1=0,dx2=0,dx3,dx4; + + // # segments to traverse + segments = abs(y_left - path_y[0]); + + // prevent overdraw + if(y_left>=path_raster[0]) segments=0; + else path_raster[0]=y_left; + + // don't draw outside the window + if(path_raster[0]0) + { + // use previous data + dx1 = (envelope1 * path_plane[0] / view_plane); + dx2 = (envelope2 * path_plane[0] / view_plane); + + // use temporary envelope pitch (this frame only) + dx3 = (envelope1 * plane / view_plane); + dx4 = (envelope2 * plane / view_plane); + + // project new shapes (left side) + x1_final = x_left+dx1; + x2_final = path_x[0]+dx3; + + // interpolate between projected points with shaping + left_inc = ((x2_final-x1_final)<<8)/segments; + + // project new shapes (right side) + x1_final = x_left+dx2; + x2_final = path_x[0]+dx4; + + // interpolate between projected points with shaping + right_inc = ((x2_final-x1_final)<<8)/segments; + + path_plane[0] = plane; + } + +#ifdef PRINT + printf("(line %d) Op08 block %d, out %02X, raster %02X\n",c,block,segments,(uint16)y_left); +#endif + + // zone 1 + DSP4.out_count = (2+4*segments); + DSP4_WRITE_WORD(index,segments); index+=2; + + for( lcv=1; lcv<=segments; lcv++ ) + { + int16 pos1,pos2; + + // pre-compute + pos1 = path_pos[0]+((left_inc*lcv)>>8)+dx1; + pos2 = path_pos[1]+((right_inc*lcv)>>8)+dx2; + + // clip offscreen data + if(pos1path_clipRight[0]) pos1 = path_clipRight[0]; + if(pos2path_clipRight[1]) pos2 = path_clipRight[1]; + +#if 0 + if(pos1==0x00ff) pos1=0; + if(pos2==0x00ff) pos2=0; + path_ptr[0] = -1; + pos1 = -1; + pos2 = -1; +#endif + + // data + DSP4_WRITE_WORD(index,path_ptr[0]); index+=2; + DSP4.output[index++]=pos1&0xFF; + DSP4.output[index++]=pos2&0xFF; + + // post-update + path_ptr[0] -= 4; + path_ptr[1] -= 4; + } + lcv--; + + if(segments>0) + { + // project points w/out the envelopes + int16 inc = ((path_x[0]-x_left)<<8)/segments; + + // post-store + path_pos[0] += ((inc*lcv)>>8); + path_pos[1] += ((inc*lcv)>>8); + + path_x[0] = x_left; + path_y[0] = y_left; + } + + ////////////////////////////////////////////// + // zone 2 + segments = abs(y_right - path_y[1]); + + // prevent overdraw + if(y_right>=path_raster[2]) segments=0; + else path_raster[2]=y_right; + + // don't draw outside the window + if(path_raster[2]0) + { + // use previous data + dx1 = (envelope1 * path_plane[1] / view_plane); + dx2 = (envelope2 * path_plane[1] / view_plane); + + // use temporary envelope pitch (this frame only) + dx3 = (envelope1 * plane / view_plane); + dx4 = (envelope2 * plane / view_plane); + + // project new shapes (left side) + x1_final = x_left+dx1; + x2_final = path_x[1]+dx3; + + // interpolate between projected points with shaping + left_inc = ((x2_final-x1_final)<<8)/segments; + + // project new shapes (right side) + x1_final = x_left+dx2; + x2_final = path_x[1]+dx4; + + // interpolate between projected points with shaping + right_inc = ((x2_final-x1_final)<<8)/segments; + + path_plane[1] = plane; + } + + // write out results + DSP4.out_count += (2+4*segments); + DSP4_WRITE_WORD(index,segments); index+=2; + + for( lcv=1; lcv<=segments; lcv++ ) + { + int16 pos1,pos2; + + // pre-compute + pos1 = path_pos[2]+((left_inc*lcv)>>8)+dx1; + pos2 = path_pos[3]+((right_inc*lcv)>>8)+dx2; + + // clip offscreen data + if(pos1path_clipRight[2]) pos1 = path_clipRight[2]; + if(pos2path_clipRight[3]) pos2 = path_clipRight[3]; + +#if 0 + if(pos1==0x00ff) pos1=0; + if(pos2==0x00ff) pos2=0; + path_ptr[2] = -1; + //pos1 = -1; + pos2 = -1; +#endif + + // data + DSP4_WRITE_WORD(index,path_ptr[2]); index+=2; + DSP4.output[index++]=pos1&0xFF; + DSP4.output[index++]=pos2&0xFF; + + // post-update + path_ptr[2] -= 4; + path_ptr[3] -= 4; + } + lcv--; + + if(segments>0) + { + // project points w/out the envelopes + int16 inc = ((path_x[1]-x_right)<<8)/segments; + + // post-store + path_pos[2] += ((inc*lcv)>>8); + path_pos[3] += ((inc*lcv)>>8); + + path_x[1] = x_right; + path_y[1] = y_right; + } + } + } while(1); + + DSP4.waiting4command = TRUE; + DSP4.out_count = 2; + DSP4_WRITE_WORD(0,0); +} + +#undef PRINT + +#if OP==0x000D +#define PRINT +#endif + +void DSP4_Op0D() +{ + uint16 command; + + DSP4.waiting4command = FALSE; + + // op flow control + switch(DSP4_Logic) { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + // 0x00 = DSP4_READ_WORD(0x00); + project_focaly = DSP4_READ_WORD(0x02); + raster = DSP4_READ_WORD(0x04); + viewport_top = DSP4_READ_WORD(0x06); + project_y = DSP4_READ_WORD(0x08); + viewport_bottom = DSP4_READ_WORD(0x0a); + project_x1low = DSP4_READ_WORD(0x0c); + project_x1 = DSP4_READ_WORD(0x0e); + project_focalx = DSP4_READ_WORD(0x0e); + project_centerx = DSP4_READ_WORD(0x10); + project_ptr = DSP4_READ_WORD(0x12); + // 0xc0 = DSP4_READ_WORD(0x14); + project_pitchylow = DSP4_READ_WORD(0x16); + project_pitchy = DSP4_READ_WORD(0x18); + project_pitchxlow = DSP4_READ_WORD(0x1a); + project_pitchx = DSP4_READ_WORD(0x1c); + far_plane = DSP4_READ_WORD(0x1e); + // ? = DSP4_READ_WORD(0x20); + + // multi-op storage + multi_index1++; + multi_index1%=4; + + // remap 0D->09 window data ahead of time + // index starts at 1-3,0 + // + // Op0D: BL,TL,BR,TR + // Op09: TL,TR,BL,BR (1,2,3,0) + switch(multi_index1) + { + case 1: multi_index2=3; break; + case 2: multi_index2=1; break; + case 3: multi_index2=0; break; + case 0: multi_index2=2; break; + } + + // pre-compute + view_plane = PLANE_START; + + // figure out projection data + project_y -= viewport_bottom; + project_x = project_centerx + project_x1; + + // debug + block=0; + + //////////////////////////////////////////////////// + // command check + + do { + // scan next command + DSP4.in_count = 2; + + DSP4_WAIT(1) resume1: + + // inspect input + command = DSP4_READ_WORD(0); + + // terminate op + if(command == 0x8000) break; + + // already have 2 bytes in queue + DSP4.in_index = 2; + DSP4.in_count = 8; + + DSP4_WAIT(2) resume2: + + //////////////////////////////////////////////////// + // project section of the track + + // inspect inputs + int16 plane = DSP4_READ_WORD(0); + int16 index, lcv; + int16 py_dy=0, px_dx=0; + int16 y_out, x_out; + + // ignore invalid data + if((uint16) plane == 0x8001) continue; + + // one-time init + if(far_plane) + { + // setup final data + // low16=plane + project_x1 = project_focalx; + project_y1 = project_focaly; + plane = far_plane; + far_plane = 0; + } + + // use proportional triangles to project new coords + project_x2 = project_focalx * plane / view_plane; + project_y2 = project_focaly * plane / view_plane; + + // quadratic regression (rough) + if(project_focaly>=-0x0f) + py_dy = (short) (project_focaly * project_focaly * -0.20533553 + - 1.08330005 * project_focaly - 69.61094639); + else + py_dy = (short) (project_focaly * project_focaly * -0.000657035759 + - 1.07629051 * project_focaly - 65.69315963); + + // approximate # of raster lines + segments = abs(project_y2-project_y1); + + // prevent overdraw + if(project_y2>=raster) segments=0; + else raster=project_y2; + + // don't draw outside the window + if(project_y20) + { + // interpolate between projected points + px_dx = ((project_x2-project_x1)<<8)/segments; + } + + // debug + ++block; + +#ifdef PRINT + printf("(line %d) Op0D check %02X, plane %04X\n",c,(uint16)segments,(uint16)(plane)); +#endif + + // prepare output + DSP4.out_count=8+2+6*segments; + + DSP4_WRITE_WORD(0,project_focalx); + DSP4_WRITE_WORD(2,project_x2); + DSP4_WRITE_WORD(4,project_focaly); + DSP4_WRITE_WORD(6,project_y2); + DSP4_WRITE_WORD(8,segments); +#if 0 + DSP4_WRITE_WORD(0,-1); + DSP4_WRITE_WORD(2,-1); + DSP4_WRITE_WORD(4,-1); + DSP4_WRITE_WORD(6,-1); + DSP4_WRITE_WORD(8,-1); +#endif + + index=10; + + // iterate through each point + for( lcv=0; lcv>8); + x_out = project_x+((px_dx*lcv)>>8); + +#if 0 + project_ptr=-1; + //y_out=-1; + x_out=-1; +#endif + + // data + DSP4_WRITE_WORD(index+0,project_ptr); + DSP4_WRITE_WORD(index+2,y_out); + DSP4_WRITE_WORD(index+4,x_out); + index += 6; + + // post-update + project_ptr -= 4; + } + + // post-update + project_y += ((py_dy*lcv)>>8); + project_x += ((px_dx*lcv)>>8); + + if(segments > 0) + { + project_x1 = project_x2; + project_y1 = project_y2; + + // multi-op storage + multi_farplane[multi_index2] = plane; + multi_raster[multi_index2] = project_y1; + } + + // update focal projection points + project_pitchy += (int8)DSP4.parameters[3]; + project_pitchx += (int8)DSP4.parameters[5]; + + project_focaly += project_pitchy; + project_focalx += project_pitchx; + } while(1); + + DSP4.waiting4command = TRUE; + DSP4.out_count = 0; +} + +#undef PRINT + +#if OP==0x0009 +#define PRINT +#endif + +#if OP==0x0006 +#define PRINT +#endif + +void DSP4_Op09() +{ + uint16 command; + + 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; + case 7: goto resume7; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // debug + block=0; + + // grab screen information + view_plane = PLANE_START; + center_x = DSP4_READ_WORD(0x00); + center_y = DSP4_READ_WORD(0x02); + // 0x00 = DSP4_READ_WORD(0x04); + viewport_left = DSP4_READ_WORD(0x06); + viewport_right = DSP4_READ_WORD(0x08); + viewport_top = DSP4_READ_WORD(0x0a); + viewport_bottom = DSP4_READ_WORD(0x0c); + +#ifdef PRINT2 + printf("Window: (%04X,%04X) (%04X,%04X)\n", + viewport_left,viewport_right,viewport_top,viewport_bottom); +#endif + + // expand viewport dimensions + viewport_left -= 8; + + // cycle through viewport window data + multi_index1++; + multi_index1%=4; + +#if 1 + // convert track line to the window region + project_y2 = center_y + multi_raster[multi_index1] * + (viewport_bottom-center_y)/(0x33-0); + if(op09_mode==0) project_y2 -= 2; +#endif + + goto no_sprite; + + do { + //////////////////////////////////////////////////// + // check for new sprites + + do { + uint16 second; + + DSP4.in_count = 4; + DSP4.in_index = 2; + + DSP4_WAIT(1) resume1: + + // try to classify sprite + second = DSP4_READ_WORD(2); + + // op termination + if(second == 0x8000) goto terminate; + + second >>= 8; + sprite_type = 0; + + // vehicle sprite + if(second == 0x90) + { + sprite_type = 1; + break; + } + // terrain sprite + else if(second != 0) + { + sprite_type = 2; + break; + } + +no_sprite: + // no sprite. try again + + DSP4.in_count = 2; + + DSP4_WAIT(2) resume2: + ; + } while (1); + + //////////////////////////////////////////////////// + // process projection information + +sprite_found: + // vehicle sprite + if(sprite_type == 1) + { + int16 plane; + int16 car_left, car_right, car_left_a; + int16 focal_back, focal_front; + uint8 distance, id; + + // we already have 4 bytes we want + DSP4.in_count = 6+12; + DSP4.in_index = 4; + + DSP4_WAIT(3) resume3: + + // filter inputs + project_y1 = DSP4_READ_WORD(0x00); + // 0x9000 = DSP4_READ_WORD(0x02); + id = DSP4.parameters[0x04]; + distance = DSP4.parameters[0x05]; + focal_back = DSP4_READ_WORD(0x06); + focal_front = DSP4_READ_WORD(0x08); + car_left_a = DSP4_READ_WORD(0x0a); + car_left = DSP4_READ_WORD(0x0c); + plane = DSP4_READ_WORD(0x0e); + car_right = DSP4_READ_WORD(0x10); + + // calculate car's x-center + project_focalx = car_right-car_left; + + // determine how far into the screen to project + project_focaly = focal_back; + project_x = project_focalx * plane / view_plane; + segments = 0x33 - project_focaly * plane / view_plane; + far_plane = plane; + + // prepare memory + sprite_x = center_x+project_x; + sprite_y = viewport_bottom-segments; + far_plane = plane; + + // debug + ++block; +#ifdef PRINT + printf("(line %d) Op09 vehicle block %d, Loop %04X\n",c,block,(uint16)project_y1); + //printf("%04X %04X %04X %04X / ",focal_back,focal_front,car_left_a,car_left); + //printf("%02X %02X ", distance, id); +#endif + + // make the car's x-center available + DSP4.out_count = 2; + DSP4_WRITE_WORD(0,project_focalx); + +#if 0 + DSP4_WRITE_WORD(0,-1); +#endif + + // grab a few remaining vehicle values + DSP4.in_count = 4; + + DSP4_WAIT(4) resume4: + + // store final values + int height = DSP4_READ_WORD(0); + sprite_offset = DSP4_READ_WORD(2); + + // vertical lift factor + sprite_y += height; + +#ifdef PRINT_09 + printf("%04X\n",sprite_offset); +#endif + } + // terrain sprite + else if(sprite_type == 2) + { + int16 plane; + + // we already have 4 bytes we want + DSP4.in_count = 6+6+2; + DSP4.in_index = 4; + + DSP4_WAIT(5) resume5: + + // sort loop inputs + project_y1 = DSP4_READ_WORD(0x00); + plane = DSP4_READ_WORD(0x02); + project_centerx = DSP4_READ_WORD(0x04); + //project_y1 = DSP4_READ_WORD(0x06); + project_focalx = DSP4_READ_WORD(0x08); + project_focaly = DSP4_READ_WORD(0x0a); + sprite_offset = DSP4_READ_WORD(0x0c); + + // determine distances into virtual world + segments = 0x33 - project_y1; + project_x = project_focalx * plane / view_plane; + project_y = project_focaly * plane / view_plane; + + // prepare memory + sprite_x = center_x+project_x-project_centerx; + sprite_y = viewport_bottom-segments+project_y; + far_plane = plane; + + // debug + ++block; +#ifdef PRINT + printf("(line %d) Op09 terrain block %d, Loop %04X\n",c,block,(uint16)project_y1); +#endif + } + + // default sprite size: 16x16 + sprite_size = 1; + + //////////////////////////////////////////////////// + // convert tile data to OAM + + do { + DSP4.in_count = 2; + + DSP4_WAIT(6) resume6: + + command = DSP4_READ_WORD(0); + + // opcode termination + if(command == 0x8000) goto terminate; + + // toggle sprite size + if(command == 0x0000) + { + sprite_size = !sprite_size; +#ifdef PRINT + printf("TOGGLE=%02X\n",(uint8)sprite_size); +#endif + continue; + } + + // new sprite information + command >>= 8; + if(command != 0x20 && command != 0x40 && + command != 0x60 && command != 0xa0 && + command != 0xc0 && command != 0xe0) + break; + + DSP4.in_count = 6; + DSP4.in_index = 2; + + DSP4_WAIT(7) resume7: + + ///////////////////////////////////// + // process tile data + + bool8 clip; + int16 sp_x, sp_y, sp_oam, sp_msb; + int16 sp_dx, sp_dy; + + // sprite deltas + sp_dy = DSP4_READ_WORD(2); + sp_dx = DSP4_READ_WORD(4); + + // update coordinates + sp_y = sprite_y + sp_dy; + sp_x = sprite_x + sp_dx; + + // reject points outside the clipping window + clip = FALSE; + if(sp_x < viewport_left || sp_x > viewport_right) clip=TRUE; + if(sp_y < viewport_top || sp_y > viewport_bottom) clip=TRUE; + + // track depth sorting + if(far_plane <= multi_farplane[multi_index1] && + sp_y >= project_y2) clip=TRUE; + +#ifdef PRINT2 + printf("(line %d) %04X, %04X, %04X / %04X %04X\n",line, + (uint16)sp_x,(uint16)sp_y,(uint16)far_plane,(uint16)multi_farplane[multi_index1],(uint16)project_y2); +#endif + + // don't draw offscreen coordinates + DSP4.out_count = 0; + if(!clip) + { + int16 out_index = 0; + int16 offset = DSP4_READ_WORD(0); + + // update sprite nametable/attribute information + sp_oam = sprite_offset + offset; + sp_msb = (sp_x<0 || sp_x>255); + +#ifdef PRINT + printf("(line %d) %04X, %04X, %04X, %04X, %04X\n",line, + (uint16)sp_oam,(uint16)sprite_offset,(uint16)offset, + (uint16)sp_x,(uint16)sp_y); +#endif + + // emit transparency information + if( + (sprite_offset&0x08) && + ((sprite_type==1 && sp_y>=0xcc) || + (sprite_type==2 && sp_y>=0xbb)) + ) + { + DSP4.out_count = 6; + + // one block of OAM data + DSP4_WRITE_WORD(0,1); + + // OAM: x,y,tile,no attr + DSP4.output[2] = sp_x&0xFF; + DSP4.output[3] = (sp_y+6)&0xFF; + DSP4_WRITE_WORD(4,0xEE); + + out_index = 6; + + // OAM: size,msb data + DSP4_Op06(sprite_size,(char) sp_msb); + } + + // normal data + DSP4.out_count += 8; + + // one block of OAM data + DSP4_WRITE_WORD(out_index+0,1); + + // OAM: x,y,tile,attr + DSP4.output[out_index+2] = sp_x&0xFF; + DSP4.output[out_index+3] = sp_y&0xFF; + DSP4_WRITE_WORD(out_index+4,sp_oam); + + // no following OAM data + DSP4_WRITE_WORD(out_index+6,0); + + // OAM: size,msb data + DSP4_Op06(sprite_size, (char) sp_msb); + +#if 0 + DSP4_WRITE_WORD(0,-1); + DSP4_WRITE_WORD(2,-1); + DSP4_WRITE_WORD(4,-1); + DSP4_WRITE_WORD(6,-1); + DSP4_WRITE_WORD(8,-1); + DSP4_WRITE_WORD(10,-1); + DSP4_WRITE_WORD(12,-1); +#endif + } + + // no sprite information + if(DSP4.out_count == 0) + { + DSP4.out_count = 2; + DSP4_WRITE_WORD(0,0); + } + } while (1); + + ///////////////////////////////////// + // special cases: plane == 0x0000 + + // special vehicle case + if(command == 0x90) + { + sprite_type = 1; + + // shift bytes + DSP4.parameters[2] = DSP4.parameters[0]; + DSP4.parameters[3] = DSP4.parameters[1]; + DSP4.parameters[0] = 0; + DSP4.parameters[1] = 0; + + goto sprite_found; + } + // special terrain case + else if(command != 0x00 && command != 0xff) + { + sprite_type = 2; + + // shift bytes + DSP4.parameters[2] = DSP4.parameters[0]; + DSP4.parameters[3] = DSP4.parameters[1]; + DSP4.parameters[0] = 0; + DSP4.parameters[1] = 0; + + goto sprite_found; + } + } while (1); + +terminate: + DSP4.waiting4command = TRUE; + DSP4.out_count=0; +} + +#undef PRINT + diff --git a/source/dsp4emu.cpp b/source/dsp4emu.cpp deleted file mode 100644 index b36cadb..0000000 --- a/source/dsp4emu.cpp +++ /dev/null @@ -1,1483 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "dsp4.h" - -#define DSP4_READ_WORD(x) \ - READ_WORD(DSP4.parameters+x) - -#define DSP4_WRITE_WORD(x,d) \ - WRITE_WORD(DSP4.output+x,d); - -// used to wait for dsp i/o -#define DSP4_WAIT(x) \ - DSP4_Logic = x; return; - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - -void DSP4_Multiply(short Multiplicand, short Multiplier, int &Product) -{ - Product = Multiplicand * Multiplier; -} - -void DSP4_UnknownOP11(short A, short B, short C, short D, short &M) -{ - M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | - ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); -} - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - -void DSP4_Op06(bool8 size, bool8 msb) -{ - // save post-oam table data for future retrieval - op06_OAM[op06_index] |= (msb<<(op06_offset+0)); - op06_OAM[op06_index] |= (size<<(op06_offset+1)); - op06_offset += 2; - - if(op06_offset==8) - { - // move to next byte in buffer - op06_offset=0; - op06_index++; - } -} - -#if OP==0x0001 -#define PRINT -#endif - -void DSP4_Op01() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - // 0x00 = DSP4_READ_WORD(0x00); - project_focaly = DSP4_READ_WORD(0x02); - raster = DSP4_READ_WORD(0x04); - viewport_top = DSP4_READ_WORD(0x06); - project_y = DSP4_READ_WORD(0x08); - viewport_bottom = DSP4_READ_WORD(0x0a); - project_x1low = DSP4_READ_WORD(0x0c); - project_focalx = DSP4_READ_WORD(0x0e); - project_centerx = DSP4_READ_WORD(0x10); - project_ptr = DSP4_READ_WORD(0x12); - // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); - project_pitchylow = DSP4_READ_WORD(0x16); - project_pitchy = DSP4_READ_WORD(0x18); - project_pitchxlow = DSP4_READ_WORD(0x1a); - project_pitchx = DSP4_READ_WORD(0x1c); - far_plane = DSP4_READ_WORD(0x1e); - // ? = DSP4_READ_WORD(0x20); - project_y1low = DSP4_READ_WORD(0x22); - - // pre-compute - view_plane = PLANE_START; - - // find starting projection points - project_x1 = project_focalx; - project_y -= viewport_bottom; - project_x = project_centerx + project_x1; - - // multi-op storage - multi_index1 = 0; - multi_index2 = 0; - - // debug - block=0; - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // check for termination - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 8; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // process one iteration of projection - - // inspect inputs - int16 plane = DSP4_READ_WORD(0); - int16 index, lcv; - int16 py_dy=0, px_dx=0; - int16 y_out, x_out; - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // one-time init - if(far_plane) - { - // setup final parameters - project_focalx += plane; - project_x1 = project_focalx; - project_y1 = project_focaly; - plane = far_plane; - far_plane = 0; - } - - // use proportional triangles to project new coords - project_x2 = project_focalx * plane / view_plane; - project_y2 = project_focaly * plane / view_plane; - - // quadratic regression (rough) - if(project_focaly>=-0x0f) - py_dy = (short) (project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (short) (project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); - - // approximate # of raster lines - segments = abs(project_y2-project_y1); - - // prevent overdraw - if(project_y2>=raster) segments=0; - else raster=project_y2; - - // don't draw outside the window - if(project_y20) - { - // interpolate between projected points - px_dx = ((project_x2-project_x1)<<8)/segments; - } - - // debug - ++block; -#ifdef PRINT - printf("(line %d) Op01 check %02X, plane %04X, focal_y %04X, y2 %04X\n",c,(uint16)segments,(uint16)(plane),(uint16)project_focaly,(uint16)project_y2); -#endif - - // prepare output - DSP4.out_count=8+2+6*segments; - - // pre-block data - DSP4_WRITE_WORD(0,project_focalx); - DSP4_WRITE_WORD(2,project_x2); - DSP4_WRITE_WORD(4,project_focaly); - DSP4_WRITE_WORD(6,project_y2); - DSP4_WRITE_WORD(8,segments); - -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); - DSP4_WRITE_WORD(6,-1); - DSP4_WRITE_WORD(8,-1); -#endif - - index=10; - - // iterate through each point - for( lcv=0; lcv>8); - x_out = project_x+((px_dx*lcv)>>8); - -#if 0 - project_ptr=-1; - y_out=-1; - x_out=-1; -#endif - - // data - DSP4_WRITE_WORD(index+0,project_ptr); - DSP4_WRITE_WORD(index+2,y_out); - DSP4_WRITE_WORD(index+4,x_out); - index += 6; - - // post-update - project_ptr -= 4; - } - - // post-update - project_y += ((py_dy*lcv)>>8); - project_x += ((px_dx*lcv)>>8); - - // new positions - if(segments>0) - { - project_x1 = project_x2; - project_y1 = project_y2; - - // multi-op storage - multi_focaly[multi_index2++] = project_focaly; - multi_farplane[1] = plane; - multi_raster[1] = project_y1-1; - } - - // update projection points - project_pitchy += (int8)DSP4.parameters[3]; - project_pitchx += (int8)DSP4.parameters[5]; - - project_focaly += project_pitchy; - project_focalx += project_pitchx; - } while (1); - - // terminate op - DSP4.waiting4command = TRUE; - DSP4.out_count = 0; -} - -#undef PRINT - -#if OP==0x0007 -#define PRINT -#endif - -void DSP4_Op07() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - // 0x00 = DSP4_READ_WORD(0x00); - project_focaly = DSP4_READ_WORD(0x02); - raster = DSP4_READ_WORD(0x04); - viewport_top = DSP4_READ_WORD(0x06); - project_y = DSP4_READ_WORD(0x08); - viewport_bottom = DSP4_READ_WORD(0x0a); - project_x1low = DSP4_READ_WORD(0x0c); - project_x1 = DSP4_READ_WORD(0x0e); - project_centerx = DSP4_READ_WORD(0x10); - project_ptr = DSP4_READ_WORD(0x12); - // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); - - // pre-compute - view_plane = PLANE_START; - - // find projection targets - project_y1 = project_focaly; - project_y -= viewport_bottom; - project_x = project_centerx + project_x1; - - // multi-op storage - multi_index2 = 0; - - // debug - block=0; - -#ifdef PRINT - printf("(line %d) Op07 data %04X\n",c,(uint16)project_y1); -#endif - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // check for opcode termination - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 12; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // process one loop of projection - - int16 plane; - int16 index,lcv; - int16 y_out,x_out; - int16 py_dy=0,px_dx=0; - - // debug - ++block; - - // inspect inputs - plane = DSP4_READ_WORD(0); - project_y2 = DSP4_READ_WORD(2); - // ? = DSP4_READ_WORD(4); - project_x2 = DSP4_READ_WORD(6); - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // multi-op storage - project_focaly = multi_focaly[multi_index2]; - - // quadratic regression (rough) - if(project_focaly>=-0x0f) - py_dy = (short) (project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (short) (project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); - - // approximate # of raster lines - segments = abs(project_y2-project_y1); - - // prevent overdraw - if(project_y2>=raster) segments=0; - else raster=project_y2; - - // don't draw outside the window - if(project_y20) - { - // interpolate between projected points - px_dx = ((project_x2-project_x1)<<8)/segments; - } - -#ifdef PRINT - printf("(line %d) Op07 block %d, loc %04X, out %02X, project_x2 %04X\n",c,block,plane,segments,(uint16)project_x2); -#endif - - // prepare pre-output - DSP4.out_count=4+2+6*segments; - - DSP4_WRITE_WORD(0,project_x2); - DSP4_WRITE_WORD(2,project_y2); - DSP4_WRITE_WORD(4,segments); - -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); -#endif - - index=6; - for( lcv=0; lcv>8); - x_out = project_x+((px_dx*lcv)>>8); - -#if 0 - project_ptr = -1; - //y_out = -1; - x_out = -1; -#endif - - // data - DSP4_WRITE_WORD(index+0,project_ptr); - DSP4_WRITE_WORD(index+2,y_out); - DSP4_WRITE_WORD(index+4,x_out); - index += 6; - - // post-update - project_ptr -= 4; - } - - // update internal variables - project_y += ((py_dy*lcv)>>8); - project_x += ((px_dx*lcv)>>8); - - // new positions - if(segments>0) - { - project_x1 = project_x2; - project_y1 = project_y2; - - // multi-op storage - multi_index2++; - } - } while(1); - - DSP4.waiting4command = TRUE; - DSP4.out_count = 0; -} - -#undef PRINT - -#if OP==0x0008 -#define PRINT -#endif - -void DSP4_Op08() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // clip values - path_clipRight[0] = DSP4_READ_WORD(0x00); - path_clipRight[1] = DSP4_READ_WORD(0x02); - path_clipRight[2] = DSP4_READ_WORD(0x04); - path_clipRight[3] = DSP4_READ_WORD(0x06); - - path_clipLeft[0] = DSP4_READ_WORD(0x08); - path_clipLeft[1] = DSP4_READ_WORD(0x0a); - path_clipLeft[2] = DSP4_READ_WORD(0x0c); - path_clipLeft[3] = DSP4_READ_WORD(0x0e); - - // unknown (constant) - // unknown (constant) - - // path positions - path_pos[0] = DSP4_READ_WORD(0x20); - path_pos[1] = DSP4_READ_WORD(0x22); - path_pos[2] = DSP4_READ_WORD(0x24); - path_pos[3] = DSP4_READ_WORD(0x26); - - // data locations - path_ptr[0] = DSP4_READ_WORD(0x28); - path_ptr[1] = DSP4_READ_WORD(0x2a); - path_ptr[2] = DSP4_READ_WORD(0x2c); - path_ptr[3] = DSP4_READ_WORD(0x2e); - - // project_y1 lines - path_raster[0] = DSP4_READ_WORD(0x30); - path_raster[1] = DSP4_READ_WORD(0x32); - path_raster[2] = DSP4_READ_WORD(0x34); - path_raster[3] = DSP4_READ_WORD(0x36); - - // viewport_top - path_top[0] = DSP4_READ_WORD(0x38); - path_top[1] = DSP4_READ_WORD(0x3a); - path_top[2] = DSP4_READ_WORD(0x3c); - path_top[3] = DSP4_READ_WORD(0x3e); - - // unknown (constants) - - view_plane = PLANE_START; - - // debug - block=0; - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // terminate op - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 18; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // projection begins - - // debug - ++block; - - // used in envelope shaping - int16 x1_final; - int16 x2_final; - - // look at guidelines - int16 plane = DSP4_READ_WORD(0x00); - int16 x_left = DSP4_READ_WORD(0x02); - int16 y_left = DSP4_READ_WORD(0x04); - int16 x_right = DSP4_READ_WORD(0x06); - int16 y_right = DSP4_READ_WORD(0x08); - - // envelope guidelines (one frame only) - int16 envelope1 = DSP4_READ_WORD(0x0a); - int16 envelope2 = DSP4_READ_WORD(0x0c); - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // first init - if(plane == 0x7fff) - { - int pos1,pos2; - - // initialize projection - path_x[0] = x_left; - path_x[1] = x_right; - - path_y[0] = y_left; - path_y[1] = y_right; - - // update coordinates - path_pos[0]-=x_left; - path_pos[1]-=x_left; - path_pos[2]-=x_right; - path_pos[3]-=x_right; - - pos1 = path_pos[0]+envelope1; - pos2 = path_pos[1]+envelope2; - - // clip offscreen data - if(pos1path_clipRight[0]) pos1 = path_clipRight[0]; - if(pos2path_clipRight[1]) pos2 = path_clipRight[1]; - -#if 0 - pos1=-1; - //pos2=-1; -#endif - - path_plane[0] = plane; - path_plane[1] = plane; - - // initial output - DSP4.out_count = 2; - DSP4.output[0]=pos1&0xFF; - DSP4.output[1]=pos2&0xFF; - -#ifdef PRINT - printf("(line %d) Op08 x_left %04X\n",c,(uint16)x_left); -#endif - } - // proceed with projection - else - { - int16 index=0, lcv; - int16 left_inc=0,right_inc=0; - int16 dx1=0,dx2=0,dx3,dx4; - - // # segments to traverse - segments = abs(y_left - path_y[0]); - - // prevent overdraw - if(y_left>=path_raster[0]) segments=0; - else path_raster[0]=y_left; - - // don't draw outside the window - if(path_raster[0]0) - { - // use previous data - dx1 = (envelope1 * path_plane[0] / view_plane); - dx2 = (envelope2 * path_plane[0] / view_plane); - - // use temporary envelope pitch (this frame only) - dx3 = (envelope1 * plane / view_plane); - dx4 = (envelope2 * plane / view_plane); - - // project new shapes (left side) - x1_final = x_left+dx1; - x2_final = path_x[0]+dx3; - - // interpolate between projected points with shaping - left_inc = ((x2_final-x1_final)<<8)/segments; - - // project new shapes (right side) - x1_final = x_left+dx2; - x2_final = path_x[0]+dx4; - - // interpolate between projected points with shaping - right_inc = ((x2_final-x1_final)<<8)/segments; - - path_plane[0] = plane; - } - -#ifdef PRINT - printf("(line %d) Op08 block %d, out %02X, raster %02X\n",c,block,segments,(uint16)y_left); -#endif - - // zone 1 - DSP4.out_count = (2+4*segments); - DSP4_WRITE_WORD(index,segments); index+=2; - - for( lcv=1; lcv<=segments; lcv++ ) - { - int16 pos1,pos2; - - // pre-compute - pos1 = path_pos[0]+((left_inc*lcv)>>8)+dx1; - pos2 = path_pos[1]+((right_inc*lcv)>>8)+dx2; - - // clip offscreen data - if(pos1path_clipRight[0]) pos1 = path_clipRight[0]; - if(pos2path_clipRight[1]) pos2 = path_clipRight[1]; - -#if 0 - if(pos1==0x00ff) pos1=0; - if(pos2==0x00ff) pos2=0; - path_ptr[0] = -1; - pos1 = -1; - pos2 = -1; -#endif - - // data - DSP4_WRITE_WORD(index,path_ptr[0]); index+=2; - DSP4.output[index++]=pos1&0xFF; - DSP4.output[index++]=pos2&0xFF; - - // post-update - path_ptr[0] -= 4; - path_ptr[1] -= 4; - } - lcv--; - - if(segments>0) - { - // project points w/out the envelopes - int16 inc = ((path_x[0]-x_left)<<8)/segments; - - // post-store - path_pos[0] += ((inc*lcv)>>8); - path_pos[1] += ((inc*lcv)>>8); - - path_x[0] = x_left; - path_y[0] = y_left; - } - - ////////////////////////////////////////////// - // zone 2 - segments = abs(y_right - path_y[1]); - - // prevent overdraw - if(y_right>=path_raster[2]) segments=0; - else path_raster[2]=y_right; - - // don't draw outside the window - if(path_raster[2]0) - { - // use previous data - dx1 = (envelope1 * path_plane[1] / view_plane); - dx2 = (envelope2 * path_plane[1] / view_plane); - - // use temporary envelope pitch (this frame only) - dx3 = (envelope1 * plane / view_plane); - dx4 = (envelope2 * plane / view_plane); - - // project new shapes (left side) - x1_final = x_left+dx1; - x2_final = path_x[1]+dx3; - - // interpolate between projected points with shaping - left_inc = ((x2_final-x1_final)<<8)/segments; - - // project new shapes (right side) - x1_final = x_left+dx2; - x2_final = path_x[1]+dx4; - - // interpolate between projected points with shaping - right_inc = ((x2_final-x1_final)<<8)/segments; - - path_plane[1] = plane; - } - - // write out results - DSP4.out_count += (2+4*segments); - DSP4_WRITE_WORD(index,segments); index+=2; - - for( lcv=1; lcv<=segments; lcv++ ) - { - int16 pos1,pos2; - - // pre-compute - pos1 = path_pos[2]+((left_inc*lcv)>>8)+dx1; - pos2 = path_pos[3]+((right_inc*lcv)>>8)+dx2; - - // clip offscreen data - if(pos1path_clipRight[2]) pos1 = path_clipRight[2]; - if(pos2path_clipRight[3]) pos2 = path_clipRight[3]; - -#if 0 - if(pos1==0x00ff) pos1=0; - if(pos2==0x00ff) pos2=0; - path_ptr[2] = -1; - //pos1 = -1; - pos2 = -1; -#endif - - // data - DSP4_WRITE_WORD(index,path_ptr[2]); index+=2; - DSP4.output[index++]=pos1&0xFF; - DSP4.output[index++]=pos2&0xFF; - - // post-update - path_ptr[2] -= 4; - path_ptr[3] -= 4; - } - lcv--; - - if(segments>0) - { - // project points w/out the envelopes - int16 inc = ((path_x[1]-x_right)<<8)/segments; - - // post-store - path_pos[2] += ((inc*lcv)>>8); - path_pos[3] += ((inc*lcv)>>8); - - path_x[1] = x_right; - path_y[1] = y_right; - } - } - } while(1); - - DSP4.waiting4command = TRUE; - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,0); -} - -#undef PRINT - -#if OP==0x000D -#define PRINT -#endif - -void DSP4_Op0D() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - // 0x00 = DSP4_READ_WORD(0x00); - project_focaly = DSP4_READ_WORD(0x02); - raster = DSP4_READ_WORD(0x04); - viewport_top = DSP4_READ_WORD(0x06); - project_y = DSP4_READ_WORD(0x08); - viewport_bottom = DSP4_READ_WORD(0x0a); - project_x1low = DSP4_READ_WORD(0x0c); - project_x1 = DSP4_READ_WORD(0x0e); - project_focalx = DSP4_READ_WORD(0x0e); - project_centerx = DSP4_READ_WORD(0x10); - project_ptr = DSP4_READ_WORD(0x12); - // 0xc0 = DSP4_READ_WORD(0x14); - project_pitchylow = DSP4_READ_WORD(0x16); - project_pitchy = DSP4_READ_WORD(0x18); - project_pitchxlow = DSP4_READ_WORD(0x1a); - project_pitchx = DSP4_READ_WORD(0x1c); - far_plane = DSP4_READ_WORD(0x1e); - // ? = DSP4_READ_WORD(0x20); - - // multi-op storage - multi_index1++; - multi_index1%=4; - - // remap 0D->09 window data ahead of time - // index starts at 1-3,0 - // - // Op0D: BL,TL,BR,TR - // Op09: TL,TR,BL,BR (1,2,3,0) - switch(multi_index1) - { - case 1: multi_index2=3; break; - case 2: multi_index2=1; break; - case 3: multi_index2=0; break; - case 0: multi_index2=2; break; - } - - // pre-compute - view_plane = PLANE_START; - - // figure out projection data - project_y -= viewport_bottom; - project_x = project_centerx + project_x1; - - // debug - block=0; - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // terminate op - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 8; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // project section of the track - - // inspect inputs - int16 plane = DSP4_READ_WORD(0); - int16 index, lcv; - int16 py_dy=0, px_dx=0; - int16 y_out, x_out; - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // one-time init - if(far_plane) - { - // setup final data - // low16=plane - project_x1 = project_focalx; - project_y1 = project_focaly; - plane = far_plane; - far_plane = 0; - } - - // use proportional triangles to project new coords - project_x2 = project_focalx * plane / view_plane; - project_y2 = project_focaly * plane / view_plane; - - // quadratic regression (rough) - if(project_focaly>=-0x0f) - py_dy = (short) (project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (short) (project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); - - // approximate # of raster lines - segments = abs(project_y2-project_y1); - - // prevent overdraw - if(project_y2>=raster) segments=0; - else raster=project_y2; - - // don't draw outside the window - if(project_y20) - { - // interpolate between projected points - px_dx = ((project_x2-project_x1)<<8)/segments; - } - - // debug - ++block; - -#ifdef PRINT - printf("(line %d) Op0D check %02X, plane %04X\n",c,(uint16)segments,(uint16)(plane)); -#endif - - // prepare output - DSP4.out_count=8+2+6*segments; - - DSP4_WRITE_WORD(0,project_focalx); - DSP4_WRITE_WORD(2,project_x2); - DSP4_WRITE_WORD(4,project_focaly); - DSP4_WRITE_WORD(6,project_y2); - DSP4_WRITE_WORD(8,segments); -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); - DSP4_WRITE_WORD(6,-1); - DSP4_WRITE_WORD(8,-1); -#endif - - index=10; - - // iterate through each point - for( lcv=0; lcv>8); - x_out = project_x+((px_dx*lcv)>>8); - -#if 0 - project_ptr=-1; - //y_out=-1; - x_out=-1; -#endif - - // data - DSP4_WRITE_WORD(index+0,project_ptr); - DSP4_WRITE_WORD(index+2,y_out); - DSP4_WRITE_WORD(index+4,x_out); - index += 6; - - // post-update - project_ptr -= 4; - } - - // post-update - project_y += ((py_dy*lcv)>>8); - project_x += ((px_dx*lcv)>>8); - - if(segments > 0) - { - project_x1 = project_x2; - project_y1 = project_y2; - - // multi-op storage - multi_farplane[multi_index2] = plane; - multi_raster[multi_index2] = project_y1; - } - - // update focal projection points - project_pitchy += (int8)DSP4.parameters[3]; - project_pitchx += (int8)DSP4.parameters[5]; - - project_focaly += project_pitchy; - project_focalx += project_pitchx; - } while(1); - - DSP4.waiting4command = TRUE; - DSP4.out_count = 0; -} - -#undef PRINT - -#if OP==0x0009 -#define PRINT -#endif - -#if OP==0x0006 -#define PRINT -#endif - -void DSP4_Op09() -{ - uint16 command; - - 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; - case 7: goto resume7; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // debug - block=0; - - // grab screen information - view_plane = PLANE_START; - center_x = DSP4_READ_WORD(0x00); - center_y = DSP4_READ_WORD(0x02); - // 0x00 = DSP4_READ_WORD(0x04); - viewport_left = DSP4_READ_WORD(0x06); - viewport_right = DSP4_READ_WORD(0x08); - viewport_top = DSP4_READ_WORD(0x0a); - viewport_bottom = DSP4_READ_WORD(0x0c); - -#ifdef PRINT2 - printf("Window: (%04X,%04X) (%04X,%04X)\n", - viewport_left,viewport_right,viewport_top,viewport_bottom); -#endif - - // expand viewport dimensions - viewport_left -= 8; - - // cycle through viewport window data - multi_index1++; - multi_index1%=4; - -#if 1 - // convert track line to the window region - project_y2 = center_y + multi_raster[multi_index1] * - (viewport_bottom-center_y)/(0x33-0); - if(op09_mode==0) project_y2 -= 2; -#endif - - goto no_sprite; - - do { - //////////////////////////////////////////////////// - // check for new sprites - - do { - uint16 second; - - DSP4.in_count = 4; - DSP4.in_index = 2; - - DSP4_WAIT(1) resume1: - - // try to classify sprite - second = DSP4_READ_WORD(2); - - // op termination - if(second == 0x8000) goto terminate; - - second >>= 8; - sprite_type = 0; - - // vehicle sprite - if(second == 0x90) - { - sprite_type = 1; - break; - } - // terrain sprite - else if(second != 0) - { - sprite_type = 2; - break; - } - -no_sprite: - // no sprite. try again - - DSP4.in_count = 2; - - DSP4_WAIT(2) resume2: - ; - } while (1); - - //////////////////////////////////////////////////// - // process projection information - -sprite_found: - // vehicle sprite - if(sprite_type == 1) - { - int16 plane; - int16 car_left, car_right, car_left_a; - int16 focal_back, focal_front; - uint8 distance, id; - - // we already have 4 bytes we want - DSP4.in_count = 6+12; - DSP4.in_index = 4; - - DSP4_WAIT(3) resume3: - - // filter inputs - project_y1 = DSP4_READ_WORD(0x00); - // 0x9000 = DSP4_READ_WORD(0x02); - id = DSP4.parameters[0x04]; - distance = DSP4.parameters[0x05]; - focal_back = DSP4_READ_WORD(0x06); - focal_front = DSP4_READ_WORD(0x08); - car_left_a = DSP4_READ_WORD(0x0a); - car_left = DSP4_READ_WORD(0x0c); - plane = DSP4_READ_WORD(0x0e); - car_right = DSP4_READ_WORD(0x10); - - // calculate car's x-center - project_focalx = car_right-car_left; - - // determine how far into the screen to project - project_focaly = focal_back; - project_x = project_focalx * plane / view_plane; - segments = 0x33 - project_focaly * plane / view_plane; - far_plane = plane; - - // prepare memory - sprite_x = center_x+project_x; - sprite_y = viewport_bottom-segments; - far_plane = plane; - - // debug - ++block; -#ifdef PRINT - printf("(line %d) Op09 vehicle block %d, Loop %04X\n",c,block,(uint16)project_y1); - //printf("%04X %04X %04X %04X / ",focal_back,focal_front,car_left_a,car_left); - //printf("%02X %02X ", distance, id); -#endif - - // make the car's x-center available - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,project_focalx); - -#if 0 - DSP4_WRITE_WORD(0,-1); -#endif - - // grab a few remaining vehicle values - DSP4.in_count = 4; - - DSP4_WAIT(4) resume4: - - // store final values - int height = DSP4_READ_WORD(0); - sprite_offset = DSP4_READ_WORD(2); - - // vertical lift factor - sprite_y += height; - -#ifdef PRINT_09 - printf("%04X\n",sprite_offset); -#endif - } - // terrain sprite - else if(sprite_type == 2) - { - int16 plane; - - // we already have 4 bytes we want - DSP4.in_count = 6+6+2; - DSP4.in_index = 4; - - DSP4_WAIT(5) resume5: - - // sort loop inputs - project_y1 = DSP4_READ_WORD(0x00); - plane = DSP4_READ_WORD(0x02); - project_centerx = DSP4_READ_WORD(0x04); - //project_y1 = DSP4_READ_WORD(0x06); - project_focalx = DSP4_READ_WORD(0x08); - project_focaly = DSP4_READ_WORD(0x0a); - sprite_offset = DSP4_READ_WORD(0x0c); - - // determine distances into virtual world - segments = 0x33 - project_y1; - project_x = project_focalx * plane / view_plane; - project_y = project_focaly * plane / view_plane; - - // prepare memory - sprite_x = center_x+project_x-project_centerx; - sprite_y = viewport_bottom-segments+project_y; - far_plane = plane; - - // debug - ++block; -#ifdef PRINT - printf("(line %d) Op09 terrain block %d, Loop %04X\n",c,block,(uint16)project_y1); -#endif - } - - // default sprite size: 16x16 - sprite_size = 1; - - //////////////////////////////////////////////////// - // convert tile data to OAM - - do { - DSP4.in_count = 2; - - DSP4_WAIT(6) resume6: - - command = DSP4_READ_WORD(0); - - // opcode termination - if(command == 0x8000) goto terminate; - - // toggle sprite size - if(command == 0x0000) - { - sprite_size = !sprite_size; -#ifdef PRINT - printf("TOGGLE=%02X\n",(uint8)sprite_size); -#endif - continue; - } - - // new sprite information - command >>= 8; - if(command != 0x20 && command != 0x40 && - command != 0x60 && command != 0xa0 && - command != 0xc0 && command != 0xe0) - break; - - DSP4.in_count = 6; - DSP4.in_index = 2; - - DSP4_WAIT(7) resume7: - - ///////////////////////////////////// - // process tile data - - bool8 clip; - int16 sp_x, sp_y, sp_oam, sp_msb; - int16 sp_dx, sp_dy; - - // sprite deltas - sp_dy = DSP4_READ_WORD(2); - sp_dx = DSP4_READ_WORD(4); - - // update coordinates - sp_y = sprite_y + sp_dy; - sp_x = sprite_x + sp_dx; - - // reject points outside the clipping window - clip = FALSE; - if(sp_x < viewport_left || sp_x > viewport_right) clip=TRUE; - if(sp_y < viewport_top || sp_y > viewport_bottom) clip=TRUE; - - // track depth sorting - if(far_plane <= multi_farplane[multi_index1] && - sp_y >= project_y2) clip=TRUE; - -#ifdef PRINT2 - printf("(line %d) %04X, %04X, %04X / %04X %04X\n",line, - (uint16)sp_x,(uint16)sp_y,(uint16)far_plane,(uint16)multi_farplane[multi_index1],(uint16)project_y2); -#endif - - // don't draw offscreen coordinates - DSP4.out_count = 0; - if(!clip) - { - int16 out_index = 0; - int16 offset = DSP4_READ_WORD(0); - - // update sprite nametable/attribute information - sp_oam = sprite_offset + offset; - sp_msb = (sp_x<0 || sp_x>255); - -#ifdef PRINT - printf("(line %d) %04X, %04X, %04X, %04X, %04X\n",line, - (uint16)sp_oam,(uint16)sprite_offset,(uint16)offset, - (uint16)sp_x,(uint16)sp_y); -#endif - - // emit transparency information - if( - (sprite_offset&0x08) && - ((sprite_type==1 && sp_y>=0xcc) || - (sprite_type==2 && sp_y>=0xbb)) - ) - { - DSP4.out_count = 6; - - // one block of OAM data - DSP4_WRITE_WORD(0,1); - - // OAM: x,y,tile,no attr - DSP4.output[2] = sp_x&0xFF; - DSP4.output[3] = (sp_y+6)&0xFF; - DSP4_WRITE_WORD(4,0xEE); - - out_index = 6; - - // OAM: size,msb data - DSP4_Op06(sprite_size,(char) sp_msb); - } - - // normal data - DSP4.out_count += 8; - - // one block of OAM data - DSP4_WRITE_WORD(out_index+0,1); - - // OAM: x,y,tile,attr - DSP4.output[out_index+2] = sp_x&0xFF; - DSP4.output[out_index+3] = sp_y&0xFF; - DSP4_WRITE_WORD(out_index+4,sp_oam); - - // no following OAM data - DSP4_WRITE_WORD(out_index+6,0); - - // OAM: size,msb data - DSP4_Op06(sprite_size, (char) sp_msb); - -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); - DSP4_WRITE_WORD(6,-1); - DSP4_WRITE_WORD(8,-1); - DSP4_WRITE_WORD(10,-1); - DSP4_WRITE_WORD(12,-1); -#endif - } - - // no sprite information - if(DSP4.out_count == 0) - { - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,0); - } - } while (1); - - ///////////////////////////////////// - // special cases: plane == 0x0000 - - // special vehicle case - if(command == 0x90) - { - sprite_type = 1; - - // shift bytes - DSP4.parameters[2] = DSP4.parameters[0]; - DSP4.parameters[3] = DSP4.parameters[1]; - DSP4.parameters[0] = 0; - DSP4.parameters[1] = 0; - - goto sprite_found; - } - // special terrain case - else if(command != 0x00 && command != 0xff) - { - sprite_type = 2; - - // shift bytes - DSP4.parameters[2] = DSP4.parameters[0]; - DSP4.parameters[3] = DSP4.parameters[1]; - DSP4.parameters[0] = 0; - DSP4.parameters[1] = 0; - - goto sprite_found; - } - } while (1); - -terminate: - DSP4.waiting4command = TRUE; - DSP4.out_count=0; -} - -#undef PRINT - diff --git a/source/fxdbg.c b/source/fxdbg.c new file mode 100644 index 0000000..3479db1 --- /dev/null +++ b/source/fxdbg.c @@ -0,0 +1,409 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "fxemu.h" +#include "fxinst.h" +#include +#include + +extern const char *fx_apvMnemonicTable[]; +extern struct FxRegs_s GSU; + + +/* + When printing a line from the pipe, it could look like this: + + 01:8006 f4 fb 86 iwt r4,#$86fb + + The values are: + 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) + + */ +void FxPipeString(char * pvString) +{ + char *p; + uint32 vOpcode = (GSU.vStatusReg & 0x300) | ((uint32)PIPE); + const char *m = fx_apvMnemonicTable[vOpcode]; + uint8 vPipe1,vPipe2,vByte1,vByte2; + uint8 vPipeBank = GSU.vPipeAdr >> 16; + + /* The next two bytes after the pipe's address */ + vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+1)]; + vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+2)]; + + /* The actual next two bytes to be read */ + vByte1 = PRGBANK(USEX16(R15)); + vByte2 = PRGBANK(USEX16(R15+1)); + + /* Print ROM address of the pipe */ + sprintf(pvString, "%02x:%04x %02x ", + USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); + p = &pvString[strlen(pvString)]; + + /* Check if it's a branch instruction */ + if( PIPE >= 0x05 && PIPE <= 0x0f ) + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); +#ifdef BRANCH_DELAY_RELATIVE + sprintf(p, m, USEX16(R15 + SEX8(vByte1) + 1 ) ); +#else + sprintf(p, m, USEX16(R15 + SEX8(vByte1) - 1 ) ); +#endif + } + /* Check for 'move' instruction */ + else if( PIPE >= 0x10 && PIPE <= 0x1f && TF(B) ) + sprintf(p, "move r%d,r%d", USEX8(PIPE & 0x0f), 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", GSU.pvDreg - GSU.avReg, USEX8(PIPE & 0x0f) ); + /* Check for 'iwt', 'lm' or 'sm' */ + else if( PIPE >= 0xf0 ) + { + sprintf(&pvString[11], "%02x %02x ", USEX8(vPipe1), USEX8(vPipe2)); + sprintf(p, m, USEX8(vByte1) | (USEX16(vByte2)<<8) ); + } + /* Normal instruction */ + else + strcpy(p, m); +} + +const char *fx_apvMnemonicTable[] = +{ + /* + * ALT0 Table + */ + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", + "stw (r8)","stw (r9)","stw (r10)","stw (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldw (r0)","ldw (r1)","ldw (r2)", "ldw (r3)", "ldw (r4)", "ldw (r5)", "ldw (r6)", "ldw (r7)", + "ldw (r8)","ldw (r9)","ldw (r10)","ldw (r11)","plot", "swap", "color", "not", + /* 50 - 5f */ + "add r0", "add r1", "add r2", "add r3", "add r4", "add r5", "add r6", "add r7", + "add r8", "add r9", "add r10", "add r11", "add r12", "add r13", "add r14", "add r15", + /* 60 - 6f */ + "sub r0", "sub r1", "sub r2", "sub r3", "sub r4", "sub r5", "sub r6", "sub r7", + "sub r8", "sub r9", "sub r10", "sub r11", "sub r12", "sub r13", "sub r14", "sub r15", + /* 70 - 7f */ + "merge", "and r1", "and r2", "and r3", "and r4", "and r5", "and r6", "and r7", + "and r8", "and r9", "and r10", "and r11", "and r12", "and r13", "and r14", "and r15", + /* 80 - 8f */ + "mult r0", "mult r1", "mult r2", "mult r3", "mult r4", "mult r5", "mult r6", "mult r7", + "mult r8", "mult r9", "mult r10", "mult r11", "mult r12", "mult r13", "mult r14", "mult r15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "asr", "ror", + "jmp (r8)","jmp (r9)","jmp (r10)","jmp (r11)","jmp (r12)","jmp (r13)","lob", "fmult", + /* a0 - af */ + "ibt r0,#$%02x", "ibt r1,#$%02x", "ibt r2,#$%02x", "ibt r3,#$%02x", + "ibt r4,#$%02x", "ibt r5,#$%02x", "ibt r6,#$%02x", "ibt r7,#$%02x", + "ibt r8,#$%02x", "ibt r9,#$%02x", "ibt r10,#$%02x", "ibt r11,#$%02x", + "ibt r12,#$%02x", "ibt r13,#$%02x", "ibt r14,#$%02x", "ibt r15,#$%02x", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "or r1", "or r2", "or r3", "or r4", "or r5", "or r6", "or r7", + "or r8", "or r9", "or r10", "or r11", "or r12", "or r13", "or r14", "or r15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "getc", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getb", + /* f0 - ff */ + "iwt r0,#$%04x", "iwt r1,#$%04x", "iwt r2,#$%04x", "iwt r3,#$%04x", + "iwt r4,#$%04x", "iwt r5,#$%04x", "iwt r6,#$%04x", "iwt r7,#$%04x", + "iwt r8,#$%04x", "iwt r9,#$%04x", "iwt r10,#$%04x", "iwt r11,#$%04x", + "iwt r12,#$%04x", "iwt r13,#$%04x", "iwt r14,#$%04x", "iwt r15,#$%04x", + + /* + * ALT1 Table + */ + + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", + "stb (r8)","stb (r9)","stb (r10)","stb (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldb (r0)","ldb (r1)","ldb (r2)", "ldb (r3)", "ldb (r4)", "ldb (r5)", "ldb (r6)", "ldb (r7)", + "ldb (r8)","ldb (r9)","ldb (r10)","ldb (r11)","rpix", "swap", "cmode", "not", + /* 50 - 5f */ + "adc r0", "adc r1", "adc r2", "adc r3", "adc r4", "adc r5", "adc r6", "adc r7", + "adc r8", "adc r9", "adc r10", "adc r11", "adc r12", "adc r13", "adc r14", "adc r15", + /* 60 - 6f */ + "sbc r0", "sbc r1", "sbc r2", "sbc r3", "sbc r4", "sbc r5", "sbc r6", "sbc r7", + "sbc r8", "sbc r9", "sbc r10", "sbc r11", "sbc r12", "sbc r13", "sbc r14", "sbc r15", + /* 70 - 7f */ + "merge", "bic r1", "bic r2", "bic r3", "bic r4", "bic r5", "bic r6", "bic r7", + "bic r8", "bic r9", "bic r10", "bic r11", "bic r12", "bic r13", "bic r14", "bic r15", + /* 80 - 8f */ + "umult r0","umult r1","umult r2", "umult r3", "umult r4", "umult r5", "umult r6", "umult r7", + "umult r8","umult r9","umult r10","umult r11","umult r12","umult r13","umult r14","umult r15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "div2", "ror", + "ljmp (r8)","ljmp (r9)","ljmp (r10)","ljmp (r11)", "ljmp (r12)", "ljmp (r13)", "lob", "lmult", + /* a0 - af */ + "lms r0,($%04x)", "lms r1,($%04x)", "lms r2,($%04x)", "lms r3,($%04x)", + "lms r4,($%04x)", "lms r5,($%04x)", "lms r6,($%04x)", "lms r7,($%04x)", + "lms r8,($%04x)", "lms r9,($%04x)", "lms r10,($%04x)", "lms r11,($%04x)", + "lms r12,($%04x)", "lms r13,($%04x)", "lms r14,($%04x)", "lms r15,($%04x)", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "xor r1", "xor r2", "xor r3", "xor r4", "xor r5", "xor r6", "xor r7", + "xor r8", "xor r9", "xor r10", "xor r11", "xor r12", "xor r13", "xor r14", "xor r15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "getc", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbh", + /* f0 - ff */ + "lm r0,($%04x)", "lm r1,($%04x)", "lm r2,($%04x)", "lm r3,($%04x)", + "lm r4,($%04x)", "lm r5,($%04x)", "lm r6,($%04x)", "lm r7,($%04x)", + "lm r8,($%04x)", "lm r9,($%04x)", "lm r10,($%04x)", "lm r11,($%04x)", + "lm r12,($%04x)", "lm r13,($%04x)", "lm r14,($%04x)", "lm r15,($%04x)", + + /* + * ALT2 Table + */ + + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", + "stw (r8)","stw (r9)","stw (r10)","stw (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldw (r0)","ldw (r1)","ldw (r2)", "ldw (r3)", "ldw (r4)", "ldw (r5)", "ldw (r6)", "ldw (r7)", + "ldw (r8)","ldw (r9)","ldw (r10)","ldw (r11)","plot", "swap", "color", "not", + /* 50 - 5f */ + "add #0", "add #1", "add #2", "add #3", "add #4", "add #5", "add #6", "add #7", + "add #8", "add #9", "add #10", "add #11", "add #12", "add #13", "add #14", "add #15", + /* 60 - 6f */ + "sub #0", "sub #1", "sub #2", "sub #3", "sub #4", "sub #5", "sub #6", "sub #7", + "sub #8", "sub #9", "sub #10", "sub #11", "sub #12", "sub #13", "sub #14", "sub #15", + /* 70 - 7f */ + "merge", "and #1", "and #2", "and #3", "and #4", "and #5", "and #6", "and #7", + "and #8", "and #9", "and #10", "and #11", "and #12", "and #13", "and #14", "and #15", + /* 80 - 8f */ + "mult #0", "mult #1", "mult #2", "mult #3", "mult #4", "mult #5", "mult #6", "mult #7", + "mult #8", "mult #9", "mult #10", "mult #11", "mult #12", "mult #13", "mult #14", "mult #15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "asr", "ror", + "jmp (r8)","jmp (r9)","jmp (r10)","jmp (r11)","jmp (r12)","jmp (r13)","lob", "fmult", + /* a0 - af */ + "sms ($%04x),r0", "sms ($%04x),r1", "sms ($%04x),r2", "sms ($%04x),r3", + "sms ($%04x),r4", "sms ($%04x),r5", "sms ($%04x),r6", "sms ($%04x),r7", + "sms ($%04x),r8", "sms ($%04x),r9", "sms ($%04x),r10", "sms ($%04x),r11", + "sms ($%04x),r12", "sms ($%04x),r13", "sms ($%04x),r14", "sms ($%04x),r15", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "or #1", "or #2", "or #3", "or #4", "or #5", "or #6", "or #7", + "or #8", "or #9", "or #10", "or #11", "or #12", "or #13", "or #14", "or #15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "ramb", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbl", + /* f0 - ff */ + "sm ($%04x),r0", "sm ($%04x),r1", "sm ($%04x),r2", "sm ($%04x),r3", + "sm ($%04x),r4", "sm ($%04x),r5", "sm ($%04x),r6", "sm ($%04x),r7", + "sm ($%04x),r8", "sm ($%04x),r9", "sm ($%04x),r10", "sm ($%04x),r11", + "sm ($%04x),r12", "sm ($%04x),r13", "sm ($%04x),r14", "sm ($%04x),r15", + + /* + * ALT3 Table + */ + + /* 00 - 0f */ + "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", + "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", + /* 10 - 1f */ + "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", + "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", + /* 20 - 2f */ + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", + /* 30 - 3f */ + "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", + "stb (r8)","stb (r9)","stb (r10)","stb (r11)","loop", "alt1", "alt2", "alt3", + /* 40 - 4f */ + "ldb (r0)","ldb (r1)","ldb (r2)", "ldb (r3)", "ldb (r4)", "ldb (r5)", "ldb (r6)", "ldb (r7)", + "ldb (r8)","ldb (r9)","ldb (r10)","ldb (r11)","rpix", "swap", "cmode", "not", + /* 50 - 5f */ + "adc #0", "adc #1", "adc #2", "adc #3", "adc #4", "adc #5", "adc #6", "adc #7", + "adc #8", "adc #9", "adc #10", "adc #11", "adc #12", "adc #13", "adc #14", "adc #15", + /* 60 - 6f */ + "cmp r0", "cmp r1", "cmp r2", "cmp r3", "cmp r4", "cmp r5", "cmp r6", "cmp r7", + "cmp r8", "cmp r9", "cmp r10", "cmp r11", "cmp r12", "cmp r13", "cmp r14", "cmp r15", + /* 70 - 7f */ + "merge", "bic #1", "bic #2", "bic #3", "bic #4", "bic #5", "bic #6", "bic #7", + "bic #8", "bic #9", "bic #10", "bic #11", "bic #12", "bic #13", "bic #14", "bic #15", + /* 80 - 8f */ + "umult #0","umult #1","umult #2", "umult #3", "umult #4", "umult #5", "umult #6", "umult #7", + "umult #8","umult #9","umult #10","umult #11","umult #12","umult #13","umult #14","umult #15", + /* 90 - 9f */ + "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "div2", "ror", + "ljmp (r8)","ljmp (r9)","ljmp (r10)","ljmp (r11)", "ljmp (r12)", "ljmp (r13)", "lob", "lmult", + /* a0 - af */ + "lms r0,($%04x)", "lms r1,($%04x)", "lms r2,($%04x)", "lms r3,($%04x)", + "lms r4,($%04x)", "lms r5,($%04x)", "lms r6,($%04x)", "lms r7,($%04x)", + "lms r8,($%04x)", "lms r9,($%04x)", "lms r10,($%04x)", "lms r11,($%04x)", + "lms r12,($%04x)", "lms r13,($%04x)", "lms r14,($%04x)", "lms r15,($%04x)", + /* b0 - bf */ + "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", + "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", + /* c0 - cf */ + "hib", "xor #1", "xor #2", "xor #3", "xor #4", "xor #5", "xor #6", "xor #7", + "xor #8", "xor #9", "xor #10", "xor #11", "xor #12", "xor #13", "xor #14", "xor #15", + /* d0 - df */ + "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", + "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "romb", + /* e0 - ef */ + "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", + "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbs", + /* f0 - ff */ + "lm r0,($%04x)", "lm r1,($%04x)", "lm r2,($%04x)", "lm r3,($%04x)", + "lm r4,($%04x)", "lm r5,($%04x)", "lm r6,($%04x)", "lm r7,($%04x)", + "lm r8,($%04x)", "lm r9,($%04x)", "lm r10,($%04x)", "lm r11,($%04x)", + "lm r12,($%04x)", "lm r13,($%04x)", "lm r14,($%04x)", "lm r15,($%04x)", +}; + diff --git a/source/fxdbg.cpp b/source/fxdbg.cpp deleted file mode 100644 index 3479db1..0000000 --- a/source/fxdbg.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "fxemu.h" -#include "fxinst.h" -#include -#include - -extern const char *fx_apvMnemonicTable[]; -extern struct FxRegs_s GSU; - - -/* - When printing a line from the pipe, it could look like this: - - 01:8006 f4 fb 86 iwt r4,#$86fb - - The values are: - 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) - - */ -void FxPipeString(char * pvString) -{ - char *p; - uint32 vOpcode = (GSU.vStatusReg & 0x300) | ((uint32)PIPE); - const char *m = fx_apvMnemonicTable[vOpcode]; - uint8 vPipe1,vPipe2,vByte1,vByte2; - uint8 vPipeBank = GSU.vPipeAdr >> 16; - - /* The next two bytes after the pipe's address */ - vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+1)]; - vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+2)]; - - /* The actual next two bytes to be read */ - vByte1 = PRGBANK(USEX16(R15)); - vByte2 = PRGBANK(USEX16(R15+1)); - - /* Print ROM address of the pipe */ - sprintf(pvString, "%02x:%04x %02x ", - USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); - p = &pvString[strlen(pvString)]; - - /* Check if it's a branch instruction */ - if( PIPE >= 0x05 && PIPE <= 0x0f ) - { - sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); -#ifdef BRANCH_DELAY_RELATIVE - sprintf(p, m, USEX16(R15 + SEX8(vByte1) + 1 ) ); -#else - sprintf(p, m, USEX16(R15 + SEX8(vByte1) - 1 ) ); -#endif - } - /* Check for 'move' instruction */ - else if( PIPE >= 0x10 && PIPE <= 0x1f && TF(B) ) - sprintf(p, "move r%d,r%d", USEX8(PIPE & 0x0f), 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", GSU.pvDreg - GSU.avReg, USEX8(PIPE & 0x0f) ); - /* Check for 'iwt', 'lm' or 'sm' */ - else if( PIPE >= 0xf0 ) - { - sprintf(&pvString[11], "%02x %02x ", USEX8(vPipe1), USEX8(vPipe2)); - sprintf(p, m, USEX8(vByte1) | (USEX16(vByte2)<<8) ); - } - /* Normal instruction */ - else - strcpy(p, m); -} - -const char *fx_apvMnemonicTable[] = -{ - /* - * ALT0 Table - */ - /* 00 - 0f */ - "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", - "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", - /* 10 - 1f */ - "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", - "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", - /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", - "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", - /* 30 - 3f */ - "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", - "stw (r8)","stw (r9)","stw (r10)","stw (r11)","loop", "alt1", "alt2", "alt3", - /* 40 - 4f */ - "ldw (r0)","ldw (r1)","ldw (r2)", "ldw (r3)", "ldw (r4)", "ldw (r5)", "ldw (r6)", "ldw (r7)", - "ldw (r8)","ldw (r9)","ldw (r10)","ldw (r11)","plot", "swap", "color", "not", - /* 50 - 5f */ - "add r0", "add r1", "add r2", "add r3", "add r4", "add r5", "add r6", "add r7", - "add r8", "add r9", "add r10", "add r11", "add r12", "add r13", "add r14", "add r15", - /* 60 - 6f */ - "sub r0", "sub r1", "sub r2", "sub r3", "sub r4", "sub r5", "sub r6", "sub r7", - "sub r8", "sub r9", "sub r10", "sub r11", "sub r12", "sub r13", "sub r14", "sub r15", - /* 70 - 7f */ - "merge", "and r1", "and r2", "and r3", "and r4", "and r5", "and r6", "and r7", - "and r8", "and r9", "and r10", "and r11", "and r12", "and r13", "and r14", "and r15", - /* 80 - 8f */ - "mult r0", "mult r1", "mult r2", "mult r3", "mult r4", "mult r5", "mult r6", "mult r7", - "mult r8", "mult r9", "mult r10", "mult r11", "mult r12", "mult r13", "mult r14", "mult r15", - /* 90 - 9f */ - "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "asr", "ror", - "jmp (r8)","jmp (r9)","jmp (r10)","jmp (r11)","jmp (r12)","jmp (r13)","lob", "fmult", - /* a0 - af */ - "ibt r0,#$%02x", "ibt r1,#$%02x", "ibt r2,#$%02x", "ibt r3,#$%02x", - "ibt r4,#$%02x", "ibt r5,#$%02x", "ibt r6,#$%02x", "ibt r7,#$%02x", - "ibt r8,#$%02x", "ibt r9,#$%02x", "ibt r10,#$%02x", "ibt r11,#$%02x", - "ibt r12,#$%02x", "ibt r13,#$%02x", "ibt r14,#$%02x", "ibt r15,#$%02x", - /* b0 - bf */ - "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", - "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", - /* c0 - cf */ - "hib", "or r1", "or r2", "or r3", "or r4", "or r5", "or r6", "or r7", - "or r8", "or r9", "or r10", "or r11", "or r12", "or r13", "or r14", "or r15", - /* d0 - df */ - "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", - "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "getc", - /* e0 - ef */ - "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", - "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getb", - /* f0 - ff */ - "iwt r0,#$%04x", "iwt r1,#$%04x", "iwt r2,#$%04x", "iwt r3,#$%04x", - "iwt r4,#$%04x", "iwt r5,#$%04x", "iwt r6,#$%04x", "iwt r7,#$%04x", - "iwt r8,#$%04x", "iwt r9,#$%04x", "iwt r10,#$%04x", "iwt r11,#$%04x", - "iwt r12,#$%04x", "iwt r13,#$%04x", "iwt r14,#$%04x", "iwt r15,#$%04x", - - /* - * ALT1 Table - */ - - /* 00 - 0f */ - "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", - "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", - /* 10 - 1f */ - "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", - "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", - /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", - "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", - /* 30 - 3f */ - "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", - "stb (r8)","stb (r9)","stb (r10)","stb (r11)","loop", "alt1", "alt2", "alt3", - /* 40 - 4f */ - "ldb (r0)","ldb (r1)","ldb (r2)", "ldb (r3)", "ldb (r4)", "ldb (r5)", "ldb (r6)", "ldb (r7)", - "ldb (r8)","ldb (r9)","ldb (r10)","ldb (r11)","rpix", "swap", "cmode", "not", - /* 50 - 5f */ - "adc r0", "adc r1", "adc r2", "adc r3", "adc r4", "adc r5", "adc r6", "adc r7", - "adc r8", "adc r9", "adc r10", "adc r11", "adc r12", "adc r13", "adc r14", "adc r15", - /* 60 - 6f */ - "sbc r0", "sbc r1", "sbc r2", "sbc r3", "sbc r4", "sbc r5", "sbc r6", "sbc r7", - "sbc r8", "sbc r9", "sbc r10", "sbc r11", "sbc r12", "sbc r13", "sbc r14", "sbc r15", - /* 70 - 7f */ - "merge", "bic r1", "bic r2", "bic r3", "bic r4", "bic r5", "bic r6", "bic r7", - "bic r8", "bic r9", "bic r10", "bic r11", "bic r12", "bic r13", "bic r14", "bic r15", - /* 80 - 8f */ - "umult r0","umult r1","umult r2", "umult r3", "umult r4", "umult r5", "umult r6", "umult r7", - "umult r8","umult r9","umult r10","umult r11","umult r12","umult r13","umult r14","umult r15", - /* 90 - 9f */ - "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "div2", "ror", - "ljmp (r8)","ljmp (r9)","ljmp (r10)","ljmp (r11)", "ljmp (r12)", "ljmp (r13)", "lob", "lmult", - /* a0 - af */ - "lms r0,($%04x)", "lms r1,($%04x)", "lms r2,($%04x)", "lms r3,($%04x)", - "lms r4,($%04x)", "lms r5,($%04x)", "lms r6,($%04x)", "lms r7,($%04x)", - "lms r8,($%04x)", "lms r9,($%04x)", "lms r10,($%04x)", "lms r11,($%04x)", - "lms r12,($%04x)", "lms r13,($%04x)", "lms r14,($%04x)", "lms r15,($%04x)", - /* b0 - bf */ - "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", - "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", - /* c0 - cf */ - "hib", "xor r1", "xor r2", "xor r3", "xor r4", "xor r5", "xor r6", "xor r7", - "xor r8", "xor r9", "xor r10", "xor r11", "xor r12", "xor r13", "xor r14", "xor r15", - /* d0 - df */ - "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", - "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "getc", - /* e0 - ef */ - "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", - "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbh", - /* f0 - ff */ - "lm r0,($%04x)", "lm r1,($%04x)", "lm r2,($%04x)", "lm r3,($%04x)", - "lm r4,($%04x)", "lm r5,($%04x)", "lm r6,($%04x)", "lm r7,($%04x)", - "lm r8,($%04x)", "lm r9,($%04x)", "lm r10,($%04x)", "lm r11,($%04x)", - "lm r12,($%04x)", "lm r13,($%04x)", "lm r14,($%04x)", "lm r15,($%04x)", - - /* - * ALT2 Table - */ - - /* 00 - 0f */ - "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", - "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", - /* 10 - 1f */ - "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", - "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", - /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", - "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", - /* 30 - 3f */ - "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", - "stw (r8)","stw (r9)","stw (r10)","stw (r11)","loop", "alt1", "alt2", "alt3", - /* 40 - 4f */ - "ldw (r0)","ldw (r1)","ldw (r2)", "ldw (r3)", "ldw (r4)", "ldw (r5)", "ldw (r6)", "ldw (r7)", - "ldw (r8)","ldw (r9)","ldw (r10)","ldw (r11)","plot", "swap", "color", "not", - /* 50 - 5f */ - "add #0", "add #1", "add #2", "add #3", "add #4", "add #5", "add #6", "add #7", - "add #8", "add #9", "add #10", "add #11", "add #12", "add #13", "add #14", "add #15", - /* 60 - 6f */ - "sub #0", "sub #1", "sub #2", "sub #3", "sub #4", "sub #5", "sub #6", "sub #7", - "sub #8", "sub #9", "sub #10", "sub #11", "sub #12", "sub #13", "sub #14", "sub #15", - /* 70 - 7f */ - "merge", "and #1", "and #2", "and #3", "and #4", "and #5", "and #6", "and #7", - "and #8", "and #9", "and #10", "and #11", "and #12", "and #13", "and #14", "and #15", - /* 80 - 8f */ - "mult #0", "mult #1", "mult #2", "mult #3", "mult #4", "mult #5", "mult #6", "mult #7", - "mult #8", "mult #9", "mult #10", "mult #11", "mult #12", "mult #13", "mult #14", "mult #15", - /* 90 - 9f */ - "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "asr", "ror", - "jmp (r8)","jmp (r9)","jmp (r10)","jmp (r11)","jmp (r12)","jmp (r13)","lob", "fmult", - /* a0 - af */ - "sms ($%04x),r0", "sms ($%04x),r1", "sms ($%04x),r2", "sms ($%04x),r3", - "sms ($%04x),r4", "sms ($%04x),r5", "sms ($%04x),r6", "sms ($%04x),r7", - "sms ($%04x),r8", "sms ($%04x),r9", "sms ($%04x),r10", "sms ($%04x),r11", - "sms ($%04x),r12", "sms ($%04x),r13", "sms ($%04x),r14", "sms ($%04x),r15", - /* b0 - bf */ - "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", - "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", - /* c0 - cf */ - "hib", "or #1", "or #2", "or #3", "or #4", "or #5", "or #6", "or #7", - "or #8", "or #9", "or #10", "or #11", "or #12", "or #13", "or #14", "or #15", - /* d0 - df */ - "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", - "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "ramb", - /* e0 - ef */ - "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", - "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbl", - /* f0 - ff */ - "sm ($%04x),r0", "sm ($%04x),r1", "sm ($%04x),r2", "sm ($%04x),r3", - "sm ($%04x),r4", "sm ($%04x),r5", "sm ($%04x),r6", "sm ($%04x),r7", - "sm ($%04x),r8", "sm ($%04x),r9", "sm ($%04x),r10", "sm ($%04x),r11", - "sm ($%04x),r12", "sm ($%04x),r13", "sm ($%04x),r14", "sm ($%04x),r15", - - /* - * ALT3 Table - */ - - /* 00 - 0f */ - "stop", "nop", "cache", "lsr", "rol", "bra $%04x","blt $%04x","bge $%04x", - "bne $%04x","beq $%04x","bpl $%04x","bmi $%04x","bcc $%04x","bcs $%04x","bvc $%04x","bvs $%04x", - /* 10 - 1f */ - "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", - "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", - /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", - "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", - /* 30 - 3f */ - "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", - "stb (r8)","stb (r9)","stb (r10)","stb (r11)","loop", "alt1", "alt2", "alt3", - /* 40 - 4f */ - "ldb (r0)","ldb (r1)","ldb (r2)", "ldb (r3)", "ldb (r4)", "ldb (r5)", "ldb (r6)", "ldb (r7)", - "ldb (r8)","ldb (r9)","ldb (r10)","ldb (r11)","rpix", "swap", "cmode", "not", - /* 50 - 5f */ - "adc #0", "adc #1", "adc #2", "adc #3", "adc #4", "adc #5", "adc #6", "adc #7", - "adc #8", "adc #9", "adc #10", "adc #11", "adc #12", "adc #13", "adc #14", "adc #15", - /* 60 - 6f */ - "cmp r0", "cmp r1", "cmp r2", "cmp r3", "cmp r4", "cmp r5", "cmp r6", "cmp r7", - "cmp r8", "cmp r9", "cmp r10", "cmp r11", "cmp r12", "cmp r13", "cmp r14", "cmp r15", - /* 70 - 7f */ - "merge", "bic #1", "bic #2", "bic #3", "bic #4", "bic #5", "bic #6", "bic #7", - "bic #8", "bic #9", "bic #10", "bic #11", "bic #12", "bic #13", "bic #14", "bic #15", - /* 80 - 8f */ - "umult #0","umult #1","umult #2", "umult #3", "umult #4", "umult #5", "umult #6", "umult #7", - "umult #8","umult #9","umult #10","umult #11","umult #12","umult #13","umult #14","umult #15", - /* 90 - 9f */ - "sbk", "link #1", "link #2", "link #3", "link #4", "sex", "div2", "ror", - "ljmp (r8)","ljmp (r9)","ljmp (r10)","ljmp (r11)", "ljmp (r12)", "ljmp (r13)", "lob", "lmult", - /* a0 - af */ - "lms r0,($%04x)", "lms r1,($%04x)", "lms r2,($%04x)", "lms r3,($%04x)", - "lms r4,($%04x)", "lms r5,($%04x)", "lms r6,($%04x)", "lms r7,($%04x)", - "lms r8,($%04x)", "lms r9,($%04x)", "lms r10,($%04x)", "lms r11,($%04x)", - "lms r12,($%04x)", "lms r13,($%04x)", "lms r14,($%04x)", "lms r15,($%04x)", - /* b0 - bf */ - "from r0", "from r1", "from r2", "from r3", "from r4", "from r5", "from r6", "from r7", - "from r8", "from r9", "from r10", "from r11", "from r12", "from r13", "from r14", "from r15", - /* c0 - cf */ - "hib", "xor #1", "xor #2", "xor #3", "xor #4", "xor #5", "xor #6", "xor #7", - "xor #8", "xor #9", "xor #10", "xor #11", "xor #12", "xor #13", "xor #14", "xor #15", - /* d0 - df */ - "inc r0", "inc r1", "inc r2", "inc r3", "inc r4", "inc r5", "inc r6", "inc r7", - "inc r8", "inc r9", "inc r10", "inc r11", "inc r12", "inc r13", "inc r14", "romb", - /* e0 - ef */ - "dec r0", "dec r1", "dec r2", "dec r3", "dec r4", "dec r5", "dec r6", "dec r7", - "dec r8", "dec r9", "dec r10", "dec r11", "dec r12", "dec r13", "dec r14", "getbs", - /* f0 - ff */ - "lm r0,($%04x)", "lm r1,($%04x)", "lm r2,($%04x)", "lm r3,($%04x)", - "lm r4,($%04x)", "lm r5,($%04x)", "lm r6,($%04x)", "lm r7,($%04x)", - "lm r8,($%04x)", "lm r9,($%04x)", "lm r10,($%04x)", "lm r11,($%04x)", - "lm r12,($%04x)", "lm r13,($%04x)", "lm r14,($%04x)", "lm r15,($%04x)", -}; - diff --git a/source/fxemu.c b/source/fxemu.c new file mode 100644 index 0000000..8dd7a15 --- /dev/null +++ b/source/fxemu.c @@ -0,0 +1,726 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include "fxemu.h" +#include "fxinst.h" +#include +#include +#include + +/* The FxChip Emulator's internal variables */ +struct FxRegs_s GSU = FxRegs_s_null; + +uint32 (**fx_ppfFunctionTable)(uint32) = 0; +void (**fx_ppfPlotTable)() = 0; +void (**fx_ppfOpcodeTable)() = 0; + +#if 0 +void fx_setCache() +{ + 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); +} + +void FxFlushCache() +{ + GSU.vCacheFlags = 0; + GSU.vCacheBaseReg = 0; + GSU.bCacheActive = FALSE; +// GSU.vPipe = 0x1; +} + +static void fx_backupCache() +{ +#if 0 + uint32 i; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + if(v) + for(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; + uint8 * t2; + uint32 a = 0x10000 - c; + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(&GSU.avCacheBackup[i<<4],t1,a); + memcpy(t1,&GSU.pvCache[i<<4],a); + memcpy(&GSU.avCacheBackup[(i<<4)+a],t2,16-a); + memcpy(t2,&GSU.pvCache[(i<<4)+a],16-a); + } + } + c = USEX16(c+16); + v >>= 1; + } +#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++) + { + 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; + } +#endif +} + +void fx_flushCache() +{ + fx_restoreCache(); + GSU.vCacheFlags = 0; + GSU.bCacheActive = FALSE; +} + + +void fx_updateRamBank(uint8 Byte) +{ + // Update BankReg and Bank pointer + 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() +{ + GSU.vSCBRDirty = TRUE; +} + +void fx_computeScreenPointers () +{ + if (GSU.vMode != GSU.vPrevMode || + GSU.vPrevScreenHeight != GSU.vScreenHeight || + GSU.vSCBRDirty) + { + int i; + + GSU.vSCBRDirty = FALSE; + + /* Make a list of pointers to the start of each screen column */ + switch (GSU.vScreenHeight) + { + 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; + } + GSU.vPrevMode = GSU.vMode; + GSU.vPrevScreenHeight = GSU.vScreenHeight; + } +} + +static void fx_writeRegisterSpace() +{ + 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.nRomBanks > 1) + b %= GSU.nRomBanks; + else + b &= 1; + + GSU.apvRomBank[i] = &GSU.pvRom[ b << 16 ]; + } + else + { + b %= GSU.nRomBanks * 2; + GSU.apvRomBank[i] = &GSU.pvRom[ (b << 16) + 0x200000]; + } + } + + /* Make RAM bank table */ + for(i=0; i<4; i++) + { + GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; + GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; + } + + /* Start with a nop in the pipe */ + GSU.vPipe = 0x01; + + /* Set pointer to GSU cache */ + GSU.pvCache = &GSU.pvRegisters[0x100]; + + fx_readRegisterSpace(); +} + +static uint8 fx_checkStartAddress() +{ + /* Check if we start inside the cache */ + if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) + return TRUE; + + /* Check if we're in an unused area */ + if(GSU.vPrgBankReg < 0x40 && R15 < 0x8000) + return FALSE; + if(GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) + return FALSE; + if(GSU.vPrgBankReg >= 0x74) + return FALSE; + + /* Check if we're in RAM and the RAN flag is not set */ + if(GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR&(1<<3)) ) + return FALSE; + + /* If not, we're in ROM, so check if the RON flag is set */ + if(!(SCMR&(1<<4))) + return FALSE; + + return TRUE; +} + +/* Execute until the next stop instruction */ +int FxEmulate(uint32 nInstructions) +{ + uint32 vCount; + + /* Read registers and initialize GSU session */ + fx_readRegisterSpace(); + + /* Check if the start address is valid */ + if(!fx_checkStartAddress()) + { + CF(G); + fx_writeRegisterSpace(); +#if 0 + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return FX_ERROR_ILLEGAL_ADDRESS; +#else + return 0; +#endif + } + + /* 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; +} + +/* Breakpoints */ +void FxBreakPointSet(uint32 vAddress) +{ + GSU.bBreakPoint = TRUE; + GSU.vBreakPoint = USEX16(vAddress); +} +void FxBreakPointClear() +{ + GSU.bBreakPoint = FALSE; +} + +/* Step by step execution */ +int FxStepOver(uint32 nInstructions) +{ + 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; +} + +/* Errors */ +int FxGetErrorCode() +{ + return GSU.vErrorCode; +} + +int FxGetIllegalAddress() +{ + return GSU.vIllegalAddress; +} + +/* Access to internal registers */ +uint32 FxGetColorRegister() +{ + return GSU.vColorReg & 0xff; +} + +uint32 FxGetPlotOptionRegister() +{ + return GSU.vPlotOptionReg & 0x1f; +} + +uint32 FxGetSourceRegisterIndex() +{ + return GSU.pvSreg - GSU.avReg; +} + +uint32 FxGetDestinationRegisterIndex() +{ + return GSU.pvDreg - GSU.avReg; +} + +uint8 FxPipe() +{ + return GSU.vPipe; +} + diff --git a/source/fxemu.cpp b/source/fxemu.cpp deleted file mode 100644 index 8dd7a15..0000000 --- a/source/fxemu.cpp +++ /dev/null @@ -1,726 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include "fxemu.h" -#include "fxinst.h" -#include -#include -#include - -/* The FxChip Emulator's internal variables */ -struct FxRegs_s GSU = FxRegs_s_null; - -uint32 (**fx_ppfFunctionTable)(uint32) = 0; -void (**fx_ppfPlotTable)() = 0; -void (**fx_ppfOpcodeTable)() = 0; - -#if 0 -void fx_setCache() -{ - 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); -} - -void FxFlushCache() -{ - GSU.vCacheFlags = 0; - GSU.vCacheBaseReg = 0; - GSU.bCacheActive = FALSE; -// GSU.vPipe = 0x1; -} - -static void fx_backupCache() -{ -#if 0 - uint32 i; - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - if(v) - for(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; - uint8 * t2; - uint32 a = 0x10000 - c; - t1 = &GSU.pvPrgBank[c]; - t2 = &GSU.pvPrgBank[0]; - memcpy(&GSU.avCacheBackup[i<<4],t1,a); - memcpy(t1,&GSU.pvCache[i<<4],a); - memcpy(&GSU.avCacheBackup[(i<<4)+a],t2,16-a); - memcpy(t2,&GSU.pvCache[(i<<4)+a],16-a); - } - } - c = USEX16(c+16); - v >>= 1; - } -#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++) - { - 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; - } -#endif -} - -void fx_flushCache() -{ - fx_restoreCache(); - GSU.vCacheFlags = 0; - GSU.bCacheActive = FALSE; -} - - -void fx_updateRamBank(uint8 Byte) -{ - // Update BankReg and Bank pointer - 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() -{ - GSU.vSCBRDirty = TRUE; -} - -void fx_computeScreenPointers () -{ - if (GSU.vMode != GSU.vPrevMode || - GSU.vPrevScreenHeight != GSU.vScreenHeight || - GSU.vSCBRDirty) - { - int i; - - GSU.vSCBRDirty = FALSE; - - /* Make a list of pointers to the start of each screen column */ - switch (GSU.vScreenHeight) - { - 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; - } - GSU.vPrevMode = GSU.vMode; - GSU.vPrevScreenHeight = GSU.vScreenHeight; - } -} - -static void fx_writeRegisterSpace() -{ - 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.nRomBanks > 1) - b %= GSU.nRomBanks; - else - b &= 1; - - GSU.apvRomBank[i] = &GSU.pvRom[ b << 16 ]; - } - else - { - b %= GSU.nRomBanks * 2; - GSU.apvRomBank[i] = &GSU.pvRom[ (b << 16) + 0x200000]; - } - } - - /* Make RAM bank table */ - for(i=0; i<4; i++) - { - GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; - GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; - } - - /* Start with a nop in the pipe */ - GSU.vPipe = 0x01; - - /* Set pointer to GSU cache */ - GSU.pvCache = &GSU.pvRegisters[0x100]; - - fx_readRegisterSpace(); -} - -static uint8 fx_checkStartAddress() -{ - /* Check if we start inside the cache */ - if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) - return TRUE; - - /* Check if we're in an unused area */ - if(GSU.vPrgBankReg < 0x40 && R15 < 0x8000) - return FALSE; - if(GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) - return FALSE; - if(GSU.vPrgBankReg >= 0x74) - return FALSE; - - /* Check if we're in RAM and the RAN flag is not set */ - if(GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR&(1<<3)) ) - return FALSE; - - /* If not, we're in ROM, so check if the RON flag is set */ - if(!(SCMR&(1<<4))) - return FALSE; - - return TRUE; -} - -/* Execute until the next stop instruction */ -int FxEmulate(uint32 nInstructions) -{ - uint32 vCount; - - /* Read registers and initialize GSU session */ - fx_readRegisterSpace(); - - /* Check if the start address is valid */ - if(!fx_checkStartAddress()) - { - CF(G); - fx_writeRegisterSpace(); -#if 0 - GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; - return FX_ERROR_ILLEGAL_ADDRESS; -#else - return 0; -#endif - } - - /* 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; -} - -/* Breakpoints */ -void FxBreakPointSet(uint32 vAddress) -{ - GSU.bBreakPoint = TRUE; - GSU.vBreakPoint = USEX16(vAddress); -} -void FxBreakPointClear() -{ - GSU.bBreakPoint = FALSE; -} - -/* Step by step execution */ -int FxStepOver(uint32 nInstructions) -{ - 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; -} - -/* Errors */ -int FxGetErrorCode() -{ - return GSU.vErrorCode; -} - -int FxGetIllegalAddress() -{ - return GSU.vIllegalAddress; -} - -/* Access to internal registers */ -uint32 FxGetColorRegister() -{ - return GSU.vColorReg & 0xff; -} - -uint32 FxGetPlotOptionRegister() -{ - return GSU.vPlotOptionReg & 0x1f; -} - -uint32 FxGetSourceRegisterIndex() -{ - return GSU.pvSreg - GSU.avReg; -} - -uint32 FxGetDestinationRegisterIndex() -{ - return GSU.pvDreg - GSU.avReg; -} - -uint8 FxPipe() -{ - return GSU.vPipe; -} - diff --git a/source/fxinst.c b/source/fxinst.c new file mode 100644 index 0000000..a5cdf01 --- /dev/null +++ b/source/fxinst.c @@ -0,0 +1,1916 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#define FX_DO_ROMBUFFER + +#include "fxemu.h" +#include "fxinst.h" +#include +#include + +extern struct FxRegs_s GSU; +int gsu_bank [512] = {0}; + +/* Set this define if you wish the plot instruction to check for y-pos limits */ +/* (I don't think it's nessecary) */ +#define CHECK_LIMITS + +/* Codes used: + * + * rn = a GSU register (r0-r15) + * #n = 4 bit immediate value + * #pp = 8 bit immediate value + * (yy) = 8 bit word address (0x0000 - 0x01fe) + * #xx = 16 bit immediate value + * (xx) = 16 bit address (0x0000 - 0xffff) + * + */ + +/* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ +static void fx_stop() +{ + 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); + + 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() +{ + uint32 c = R15 & 0xfff0; + if(GSU.vCacheBaseReg != c || !GSU.bCacheActive) + { + fx_flushCache(); + GSU.vCacheBaseReg = c; + GSU.bCacheActive = TRUE; +#if 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 + } + R15++; + CLRFLAGS; +} + +/* 03 - lsr - logic shift right */ +static void fx_lsr() +{ + uint32 v; + GSU.vCarry = SREG & 1; + v = USEX16(SREG) >> 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 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++; + +#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; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + DREG = 0; + DREG |= ((uint32)((a[0] & v) != 0)) << 0; + DREG |= ((uint32)((a[1] & v) != 0)) << 1; + TESTR14; +} + +/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_4bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#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() +{ + 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; +} + +/* 8c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_8bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,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; +} + +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static void fx_rpix_8bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + DREG = 0; + DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; + DREG |= ((uint32)((a[0x20] & v) != 0)) << 4; + DREG |= ((uint32)((a[0x21] & v) != 0)) << 5; + DREG |= ((uint32)((a[0x30] & v) != 0)) << 6; + DREG |= ((uint32)((a[0x31] & v) != 0)) << 7; + GSU.vZero = DREG; + TESTR14; +} + +/* 4o - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static void fx_plot_obj() +{ + printf ("ERROR fx_plot_obj called\n"); +} + +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static void fx_rpix_obj() +{ + printf ("ERROR fx_rpix_obj called\n"); +} + +/* 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 */ +#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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) */ +static void fx_merge() +{ + 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 90 - sbk - store word to last accessed RAM address */ +static void fx_sbk() +{ + 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() { 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() +{ + 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() +{ + 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() +{ + 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() +{ + 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); } + +/* 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); } + +/* 9e - lob - set upper byte to zero (keep low byte) */ +static void fx_lob() +{ + 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() +{ + 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() +{ + 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); } + +/* 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); } + +/* a0-af(ALT2) - sms (yy),rn - store word in RAM (short address) */ +/* If rn == r15, is the value of r15 before or after the extra byte is read? */ +#define FX_SMS(reg) \ +uint32 v = GSU.avReg[reg]; \ +GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ +R15++; FETCHPIPE; \ +RAM(GSU.vLastRamAdr) = (uint8)v; \ +RAM(GSU.vLastRamAdr+1) = (uint8)(v>>8); \ +CLRFLAGS; R15++; +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); } + +/* 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); } + +/* c0 - hib - move high-byte to low-byte */ +static void fx_hib() +{ + 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); } + +/* 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); } + +/* 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); } + +/* 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); } + +/* 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; } + +/* df - getc - transfer ROM buffer to color register */ +static void fx_getc() +{ +#ifndef FX_DO_ROMBUFFER + uint8 c; + c = ROM(R14); +#else + 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++; +} + +/* df(ALT2) - ramb - set current RAM bank */ +static void fx_ramb() +{ + GSU.vRamBankReg = SREG & (FX_RAM_BANKS-1); + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + CLRFLAGS; + R15++; +} + +/* df(ALT3) - romb - set current ROM bank */ +static void fx_romb() +{ + GSU.vRomBankReg = USEX8(SREG) & 0x7f; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + CLRFLAGS; + R15++; +} + +/* 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; } + +/* ef - getb - get byte from ROM at address R14 */ +static void fx_getb() +{ + 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() +{ + 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; +} + +/* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ +static void fx_getbl() +{ + 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; +} + +/* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ +static void fx_getbs() +{ + 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); } + +/* 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); } + +/* f0-ff(ALT2) - sm (xx),rn - store word in RAM */ +/* If rn == r15, is the value of r15 before or after the extra bytes are read? */ +#define FX_SM(reg) \ +uint32 v = GSU.avReg[reg]; \ +GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ +GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; \ +RAM(GSU.vLastRamAdr) = (uint8)v; \ +RAM(GSU.vLastRamAdr^1) = (uint8)(v>>8); \ +CLRFLAGS; R15++; +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); } + +/*** GSU executions functions ***/ + +static uint32 fx_run(uint32 nInstructions) +{ + 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); +} + +static uint32 fx_run_to_breakpoint(uint32 nInstructions) +{ + uint32 vCounter = 0; + while(TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + if(USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + } + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return vCounter; +} + +static uint32 fx_step_over(uint32 nInstructions) +{ + uint32 vCounter = 0; + while(TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + if(USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + if(USEX16(R15) == GSU.vStepPoint) + break; + } + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return vCounter; +} + +#ifdef FX_FUNCTION_TABLE +uint32 (*FX_FUNCTION_TABLE[])(uint32) = +#else +uint32 (*fx_apfFunctionTable[])(uint32) = +#endif +{ + &fx_run, + &fx_run_to_breakpoint, + &fx_step_over, +}; + +/*** Special table for the different plot configurations ***/ + +#ifdef FX_PLOT_TABLE +void (*FX_PLOT_TABLE[])() = +#else +void (*fx_apfPlotTable[])() = +#endif +{ + &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, + &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj, +}; + +/*** Opcode table ***/ + +#ifdef FX_OPCODE_TABLE +void (*FX_OPCODE_TABLE[])() = +#else +void (*fx_apfOpcodeTable[])() = +#endif +{ + /* + * ALT0 Table + */ + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, + /* 50 - 5f */ + &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, + &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, + /* 60 - 6f */ + &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, + &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, + /* 70 - 7f */ + &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, + &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, + /* 80 - 8f */ + &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, + &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + /* a0 - af */ + &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, + &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, + &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, + /* f0 - ff */ + &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, + &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, + + /* + * ALT1 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, + /* 50 - 5f */ + &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, + &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, + /* 60 - 6f */ + &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, + &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, + /* 70 - 7f */ + &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, + &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, + /* 80 - 8f */ + &fx_umult_r0,&fx_umult_r1,&fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, + &fx_umult_r8,&fx_umult_r9,&fx_umult_r10,&fx_umult_r11,&fx_umult_r12,&fx_umult_r13,&fx_umult_r14,&fx_umult_r15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + /* a0 - af */ + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, + &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, + /* f0 - ff */ + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, + + /* + * ALT2 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, + /* 50 - 5f */ + &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, + &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, + /* 60 - 6f */ + &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, + &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, + /* 70 - 7f */ + &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, + &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, + /* 80 - 8f */ + &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, + &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + /* a0 - af */ + &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, + &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, + &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, + /* f0 - ff */ + &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, + &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, + + /* + * ALT3 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, + /* 50 - 5f */ + &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, + &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, + /* 60 - 6f */ + &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, + &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, + /* 70 - 7f */ + &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, + &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, + /* 80 - 8f */ + &fx_umult_i0,&fx_umult_i1,&fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, + &fx_umult_i8,&fx_umult_i9,&fx_umult_i10,&fx_umult_i11,&fx_umult_i12,&fx_umult_i13,&fx_umult_i14,&fx_umult_i15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + /* a0 - af */ + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, + &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, + /* f0 - ff */ + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, +}; + diff --git a/source/fxinst.cpp b/source/fxinst.cpp deleted file mode 100644 index a5cdf01..0000000 --- a/source/fxinst.cpp +++ /dev/null @@ -1,1916 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#define FX_DO_ROMBUFFER - -#include "fxemu.h" -#include "fxinst.h" -#include -#include - -extern struct FxRegs_s GSU; -int gsu_bank [512] = {0}; - -/* Set this define if you wish the plot instruction to check for y-pos limits */ -/* (I don't think it's nessecary) */ -#define CHECK_LIMITS - -/* Codes used: - * - * rn = a GSU register (r0-r15) - * #n = 4 bit immediate value - * #pp = 8 bit immediate value - * (yy) = 8 bit word address (0x0000 - 0x01fe) - * #xx = 16 bit immediate value - * (xx) = 16 bit address (0x0000 - 0xffff) - * - */ - -/* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ -static void fx_stop() -{ - 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); - - 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() -{ - uint32 c = R15 & 0xfff0; - if(GSU.vCacheBaseReg != c || !GSU.bCacheActive) - { - fx_flushCache(); - GSU.vCacheBaseReg = c; - GSU.bCacheActive = TRUE; -#if 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 - } - R15++; - CLRFLAGS; -} - -/* 03 - lsr - logic shift right */ -static void fx_lsr() -{ - uint32 v; - GSU.vCarry = SREG & 1; - v = USEX16(SREG) >> 1; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 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++; - -#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; -#endif - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - DREG = 0; - DREG |= ((uint32)((a[0] & v) != 0)) << 0; - DREG |= ((uint32)((a[1] & v) != 0)) << 1; - TESTR14; -} - -/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static void fx_plot_4bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#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() -{ - 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; -} - -/* 8c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static void fx_plot_8bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,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; -} - -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static void fx_rpix_8bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; - - R15++; - CLRFLAGS; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - DREG = 0; - DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; - DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; - DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; - DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; - DREG |= ((uint32)((a[0x20] & v) != 0)) << 4; - DREG |= ((uint32)((a[0x21] & v) != 0)) << 5; - DREG |= ((uint32)((a[0x30] & v) != 0)) << 6; - DREG |= ((uint32)((a[0x31] & v) != 0)) << 7; - GSU.vZero = DREG; - TESTR14; -} - -/* 4o - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static void fx_plot_obj() -{ - printf ("ERROR fx_plot_obj called\n"); -} - -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static void fx_rpix_obj() -{ - printf ("ERROR fx_rpix_obj called\n"); -} - -/* 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 */ -#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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) */ -static void fx_merge() -{ - 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 90 - sbk - store word to last accessed RAM address */ -static void fx_sbk() -{ - 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() { 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() -{ - 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() -{ - 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() -{ - 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() -{ - 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); } - -/* 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); } - -/* 9e - lob - set upper byte to zero (keep low byte) */ -static void fx_lob() -{ - 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() -{ - 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() -{ - 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); } - -/* 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); } - -/* a0-af(ALT2) - sms (yy),rn - store word in RAM (short address) */ -/* If rn == r15, is the value of r15 before or after the extra byte is read? */ -#define FX_SMS(reg) \ -uint32 v = GSU.avReg[reg]; \ -GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ -R15++; FETCHPIPE; \ -RAM(GSU.vLastRamAdr) = (uint8)v; \ -RAM(GSU.vLastRamAdr+1) = (uint8)(v>>8); \ -CLRFLAGS; R15++; -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); } - -/* 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); } - -/* c0 - hib - move high-byte to low-byte */ -static void fx_hib() -{ - 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); } - -/* 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); } - -/* 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); } - -/* 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); } - -/* 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; } - -/* df - getc - transfer ROM buffer to color register */ -static void fx_getc() -{ -#ifndef FX_DO_ROMBUFFER - uint8 c; - c = ROM(R14); -#else - 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++; -} - -/* df(ALT2) - ramb - set current RAM bank */ -static void fx_ramb() -{ - GSU.vRamBankReg = SREG & (FX_RAM_BANKS-1); - GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; - CLRFLAGS; - R15++; -} - -/* df(ALT3) - romb - set current ROM bank */ -static void fx_romb() -{ - GSU.vRomBankReg = USEX8(SREG) & 0x7f; - GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; - CLRFLAGS; - R15++; -} - -/* 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; } - -/* ef - getb - get byte from ROM at address R14 */ -static void fx_getb() -{ - 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() -{ - 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; -} - -/* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ -static void fx_getbl() -{ - 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; -} - -/* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ -static void fx_getbs() -{ - 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); } - -/* 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); } - -/* f0-ff(ALT2) - sm (xx),rn - store word in RAM */ -/* If rn == r15, is the value of r15 before or after the extra bytes are read? */ -#define FX_SM(reg) \ -uint32 v = GSU.avReg[reg]; \ -GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ -GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; \ -RAM(GSU.vLastRamAdr) = (uint8)v; \ -RAM(GSU.vLastRamAdr^1) = (uint8)(v>>8); \ -CLRFLAGS; R15++; -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); } - -/*** GSU executions functions ***/ - -static uint32 fx_run(uint32 nInstructions) -{ - 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); -} - -static uint32 fx_run_to_breakpoint(uint32 nInstructions) -{ - uint32 vCounter = 0; - while(TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - if(USEX16(R15) == GSU.vBreakPoint) - { - GSU.vErrorCode = FX_BREAKPOINT; - break; - } - } - /* -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); -#endif -*/ - return vCounter; -} - -static uint32 fx_step_over(uint32 nInstructions) -{ - uint32 vCounter = 0; - while(TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - if(USEX16(R15) == GSU.vBreakPoint) - { - GSU.vErrorCode = FX_BREAKPOINT; - break; - } - if(USEX16(R15) == GSU.vStepPoint) - break; - } - /* -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); -#endif -*/ - return vCounter; -} - -#ifdef FX_FUNCTION_TABLE -uint32 (*FX_FUNCTION_TABLE[])(uint32) = -#else -uint32 (*fx_apfFunctionTable[])(uint32) = -#endif -{ - &fx_run, - &fx_run_to_breakpoint, - &fx_step_over, -}; - -/*** Special table for the different plot configurations ***/ - -#ifdef FX_PLOT_TABLE -void (*FX_PLOT_TABLE[])() = -#else -void (*fx_apfPlotTable[])() = -#endif -{ - &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, - &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj, -}; - -/*** Opcode table ***/ - -#ifdef FX_OPCODE_TABLE -void (*FX_OPCODE_TABLE[])() = -#else -void (*fx_apfOpcodeTable[])() = -#endif -{ - /* - * ALT0 Table - */ - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, - &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, - &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, - /* 50 - 5f */ - &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, - &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, - /* 60 - 6f */ - &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, - &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, - /* 70 - 7f */ - &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, - &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, - /* 80 - 8f */ - &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, - &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, - &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, - /* a0 - af */ - &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, - &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, - &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, - /* f0 - ff */ - &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, - &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, - - /* - * ALT1 Table - */ - - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, - &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, - &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, - /* 50 - 5f */ - &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, - &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, - /* 60 - 6f */ - &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, - &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, - /* 70 - 7f */ - &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, - &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, - /* 80 - 8f */ - &fx_umult_r0,&fx_umult_r1,&fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, - &fx_umult_r8,&fx_umult_r9,&fx_umult_r10,&fx_umult_r11,&fx_umult_r12,&fx_umult_r13,&fx_umult_r14,&fx_umult_r15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, - &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, - /* a0 - af */ - &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, - &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, - &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, - /* f0 - ff */ - &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, - &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, - - /* - * ALT2 Table - */ - - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, - &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, - &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, - /* 50 - 5f */ - &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, - &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, - /* 60 - 6f */ - &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, - &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, - /* 70 - 7f */ - &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, - &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, - /* 80 - 8f */ - &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, - &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, - &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, - /* a0 - af */ - &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, - &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, - &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, - /* f0 - ff */ - &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, - &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, - - /* - * ALT3 Table - */ - - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, - &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, - &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, - /* 50 - 5f */ - &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, - &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, - /* 60 - 6f */ - &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, - &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, - /* 70 - 7f */ - &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, - &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, - /* 80 - 8f */ - &fx_umult_i0,&fx_umult_i1,&fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, - &fx_umult_i8,&fx_umult_i9,&fx_umult_i10,&fx_umult_i11,&fx_umult_i12,&fx_umult_i13,&fx_umult_i14,&fx_umult_i15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, - &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, - /* a0 - af */ - &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, - &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, - &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, - /* f0 - ff */ - &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, - &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, -}; - diff --git a/source/gfx.c b/source/gfx.c new file mode 100644 index 0000000..34fb235 --- /dev/null +++ b/source/gfx.c @@ -0,0 +1,3933 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "gfx.h" +#include "apu.h" +#include "cheats.h" +#include "screenshot.h" + +#define M7 19 +#define M8 19 + +void output_png(); +void ComputeClipWindows (); +static void S9xDisplayFrameRate (); +static void S9xDisplayString (const char *string); + +extern uint8 BitShifts[8][4]; +extern uint8 TileShifts[8][4]; +extern uint8 PaletteShifts[8][4]; +extern uint8 PaletteMasks[8][4]; +extern uint8 Depths[8][4]; +extern uint8 BGSizes [2]; + +extern NormalTileRenderer DrawTilePtr; +extern ClippedTileRenderer DrawClippedTilePtr; +extern NormalTileRenderer DrawHiResTilePtr; +extern ClippedTileRenderer DrawHiResClippedTilePtr; +extern LargePixelRenderer DrawLargePixelPtr; + +extern struct SBG BG; + +extern struct SLineData LineData[240]; +extern struct SLineMatrixData LineMatrixData [240]; + +extern uint8 Mode7Depths [2]; + +#define CLIP_10_BIT_SIGNED(a) \ + ((a) & ((1 << 10) - 1)) + (((((a) & (1 << 13)) ^ (1 << 13)) - (1 << 13)) >> 3) + +#define ON_MAIN(N) \ +(GFX.r212c & (1 << (N)) && \ + !(PPU.BG_Forced & (1 << (N)))) + +#define SUB_OR_ADD(N) \ +(GFX.r2131 & (1 << (N))) + +#define ON_SUB(N) \ +((GFX.r2130 & 0x30) != 0x30 && \ + (GFX.r2130 & 2) && \ + (GFX.r212d & (1 << N)) && \ + !(PPU.BG_Forced & (1 << (N)))) + +#define ANYTHING_ON_SUB \ +((GFX.r2130 & 0x30) != 0x30 && \ + (GFX.r2130 & 2) && \ + (GFX.r212d & 0x1f)) + +#define ADD_OR_SUB_ON_ANYTHING \ +(GFX.r2131 & 0x3f) + +#define FIX_INTERLACE(SCREEN, DO_DEPTH, DEPTH) \ + if (IPPU.DoubleHeightPixels && ((PPU.BGMode != 5 && PPU.BGMode != 6) || !IPPU.Interlace)) \ + for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) \ + { \ + /* memmove converted: Same malloc, non-overlapping addresses [Neb] */ \ + memcpy (SCREEN + (y * 2 + 1) * GFX.Pitch2, \ + SCREEN + y * 2 * GFX.Pitch2, \ + GFX.Pitch2); \ + if(DO_DEPTH){ \ + /* memmove required: Same malloc, potentially overlapping addresses [Neb] */ \ + memmove (DEPTH + (y * 2 + 1) * (GFX.PPLx2>>1), \ + DEPTH + y * GFX.PPL, \ + GFX.PPLx2>>1); \ + } \ + } + + +#define BLACK BUILD_PIXEL(0,0,0) + +void DrawTile16 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16HalfWidth (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16HalfWidth (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16x2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16x2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16x2x2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16x2x2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawLargePixel16 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); +void DrawLargePixel16HalfWidth (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Add (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Add (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Add1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Add1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16FixedAdd1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16FixedAdd1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Sub (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Sub (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Sub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Sub1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16FixedSub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16FixedSub1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Add (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Add1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Sub (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Sub1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +bool8 S9xGraphicsInit () +{ + register uint32 PixelOdd = 1; + register uint32 PixelEven = 2; + + for (uint8 bitshift = 0; bitshift < 4; bitshift++) + { + for (register int i = 0; i < 16; i++) + { + register uint32 h = 0; + register uint32 l = 0; + +#if defined(LSB_FIRST) + if (i & 8) + h |= PixelOdd; + if (i & 4) + h |= PixelOdd << 8; + if (i & 2) + h |= PixelOdd << 16; + if (i & 1) + h |= PixelOdd << 24; + if (i & 8) + l |= PixelOdd; + if (i & 4) + l |= PixelOdd << 8; + if (i & 2) + l |= PixelOdd << 16; + if (i & 1) + l |= PixelOdd << 24; +#else + if (i & 8) + h |= (PixelOdd << 24); + if (i & 4) + h |= (PixelOdd << 16); + if (i & 2) + h |= (PixelOdd << 8); + if (i & 1) + h |= PixelOdd; + if (i & 8) + l |= (PixelOdd << 24); + if (i & 4) + l |= (PixelOdd << 16); + if (i & 2) + l |= (PixelOdd << 8); + if (i & 1) + l |= PixelOdd; +#endif + + odd_high[bitshift][i] = h; + odd_low[bitshift][i] = l; + h = l = 0; + +#if defined(LSB_FIRST) + if (i & 8) + h |= PixelEven; + if (i & 4) + h |= PixelEven << 8; + if (i & 2) + h |= PixelEven << 16; + if (i & 1) + h |= PixelEven << 24; + if (i & 8) + l |= PixelEven; + if (i & 4) + l |= PixelEven << 8; + if (i & 2) + l |= PixelEven << 16; + if (i & 1) + l |= PixelEven << 24; +#else + if (i & 8) + h |= (PixelEven << 24); + if (i & 4) + h |= (PixelEven << 16); + if (i & 2) + h |= (PixelEven << 8); + if (i & 1) + h |= PixelEven; + if (i & 8) + l |= (PixelEven << 24); + if (i & 4) + l |= (PixelEven << 16); + if (i & 2) + l |= (PixelEven << 8); + if (i & 1) + l |= PixelEven; +#endif + + even_high[bitshift][i] = h; + even_low[bitshift][i] = l; + } + PixelEven <<= 2; + PixelOdd <<= 2; + } + + GFX.RealPitch = GFX.Pitch2 = GFX.Pitch; + GFX.ZPitch = GFX.Pitch; + GFX.ZPitch >>= 1; + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; + GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; + //GFX.InfoStringTimeout = 0; + //GFX.InfoString = NULL; + + PPU.BG_Forced = 0; + IPPU.OBJChanged = TRUE; + + IPPU.DirectColourMapsNeedRebuild = TRUE; + GFX.PixSize = 1; + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + DrawLargePixelPtr = DrawLargePixel16; + if (Settings.SupportHiRes) + { + DrawHiResTilePtr= DrawTile16; + DrawHiResClippedTilePtr = DrawClippedTile16; + } + else + { + DrawHiResTilePtr= DrawTile16HalfWidth; + DrawHiResClippedTilePtr = DrawClippedTile16HalfWidth; + } + GFX.PPL = GFX.Pitch >> 1; + GFX.PPLx2 = GFX.Pitch; + S9xFixColourBrightness (); + + if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000))) + return (FALSE); + + if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) || + !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000))) + { + if (GFX.ZERO_OR_X2) + { + free ((char *) GFX.ZERO_OR_X2); + GFX.ZERO_OR_X2 = NULL; + } + if (GFX.X2) + { + free ((char *) GFX.X2); + GFX.X2 = NULL; + } + return (FALSE); + } + uint32 r, g, b; + + // Build a lookup table that multiplies a packed RGB value by 2 with + // saturation. + 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); + } + } + } + ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16)); + ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16)); + // Build a lookup table that if the top bit of the color value is zero + // then the value is zero, otherwise multiply the value by 2. Used by + // the color subtraction code. + +#if defined(OLD_COLOUR_BLENDING) + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 = (r2 << 1) & MAX_RED; + + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 = (g2 << 1) & MAX_GREEN; + + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 = (b2 << 1) & MAX_BLUE; + + 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); + } + } + } +#else + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 = (r2 << 1) & MAX_RED; + + if (r2 == 0) + r2 = 1; + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 = (g2 << 1) & MAX_GREEN; + + if (g2 == 0) + g2 = 1; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 = (b2 << 1) & MAX_BLUE; + + if (b2 == 0) + b2 = 1; + 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 + + // Build a lookup table that if the top bit of the color value is zero + // then the value is zero, otherwise its just the value. + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 &= ~0x10; + + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 &= ~GREEN_HI_BIT; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 &= ~0x10; + + 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) +{ + // Free any memory allocated in S9xGraphicsInit + if (GFX.X2) + { + free ((char *) GFX.X2); + GFX.X2 = NULL; + } + if (GFX.ZERO_OR_X2) + { + free ((char *) GFX.ZERO_OR_X2); + GFX.ZERO_OR_X2 = NULL; + } + if (GFX.ZERO) + { + free ((char *) GFX.ZERO); + GFX.ZERO = NULL; + } +} + +void S9xBuildDirectColourMaps () +{ + for (uint32 p = 0; p < 8; p++) + { + for (uint32 c = 0; c < 256; c++) + { +// XXX: Brightness + DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), + ((c & 0x38) >> 1) | (p & 2), + ((c & 0xc0) >> 3) | (p & 4)); + } + } + IPPU.DirectColourMapsNeedRebuild = FALSE; +} + +void S9xStartScreenRefresh () +{ + if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0) + GFX.InfoString = NULL; + + if (IPPU.RenderThisFrame) + { + if (!S9xInitUpdate ()) + { + IPPU.RenderThisFrame = FALSE; + return; + } + + IPPU.RenderedFramesCount++; + IPPU.PreviousLine = IPPU.CurrentLine = 0; + IPPU.MaxBrightness = PPU.Brightness; + IPPU.LatchedBlanking = PPU.ForcedBlanking; + + if(PPU.BGMode == 5 || PPU.BGMode == 6) + IPPU.Interlace = (Memory.FillRAM[0x2133] & 1); + if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace)) + { + IPPU.RenderedScreenWidth = 512; + IPPU.DoubleWidthPixels = TRUE; + IPPU.HalfWidthPixels = FALSE; + + if (IPPU.Interlace) + { + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + IPPU.DoubleHeightPixels = TRUE; + GFX.Pitch2 = GFX.RealPitch; + GFX.Pitch = GFX.RealPitch * 2; + GFX.PPL = GFX.PPLx2 = GFX.RealPitch; + } + else + { + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + GFX.Pitch2 = GFX.Pitch = GFX.RealPitch; + IPPU.DoubleHeightPixels = FALSE; + GFX.PPL = GFX.Pitch >> 1; + GFX.PPLx2 = GFX.PPL << 1; + } + } + else if (!Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace)) + { + IPPU.RenderedScreenWidth = 256; + IPPU.DoubleWidthPixels = FALSE; + // Secret of Mana displays menus with mode 5. + // Make them readable. + IPPU.HalfWidthPixels = TRUE; + } + else + { + IPPU.RenderedScreenWidth = 256; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + IPPU.DoubleWidthPixels = FALSE; + IPPU.HalfWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + { + GFX.Pitch2 = GFX.Pitch = GFX.RealPitch; + GFX.PPL = GFX.PPLx2 >> 1; + GFX.ZPitch = GFX.RealPitch; + GFX.ZPitch >>= 1; + } + } + + PPU.RecomputeClipWindows = TRUE; + GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; + } + + if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) + { + IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; + IPPU.RenderedFramesCount = 0; + IPPU.FrameCount = 0; + } +} + +void RenderLine (uint8 C) +{ + if (IPPU.RenderThisFrame) + { + LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; + LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; + LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; + LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; + + if (PPU.BGMode == 7) + { + struct SLineMatrixData *p = &LineMatrixData [C]; + p->MatrixA = PPU.MatrixA; + p->MatrixB = PPU.MatrixB; + p->MatrixC = PPU.MatrixC; + p->MatrixD = PPU.MatrixD; + p->CentreX = PPU.CentreX; + p->CentreY = PPU.CentreY; + } + else + { + if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && + PPU.BG[2].HOffset == 0xe000) + { + LineData[C].BG[2].VOffset = 0xe1; + LineData[C].BG[2].HOffset = 0; + } + 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; + } +} + +void S9xEndScreenRefresh () +{ + IPPU.HDMAStarted = FALSE; + if (IPPU.RenderThisFrame) + { + FLUSH_REDRAW (); + if (IPPU.ColorsChanged) + { + uint32 saved = PPU.CGDATA[0]; + IPPU.ColorsChanged = FALSE; + PPU.CGDATA[0] = saved; + } + + GFX.Pitch = GFX.Pitch2 = GFX.RealPitch; + GFX.PPL = GFX.PPLx2 >> 1; + S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } + + S9xApplyCheats (); + + if (CPU.SRAMModified) + { + S9xAutoSaveSRAM (); + CPU.SRAMModified = FALSE; + } + +} + +void S9xSetInfoString (const char *string) +{ + GFX.InfoString = string; + GFX.InfoStringTimeout = 120; +} + +inline void SelectTileRenderer (bool8 normal) +{ + if (normal) + { + if (IPPU.HalfWidthPixels) + { + DrawTilePtr = DrawTile16HalfWidth; + DrawClippedTilePtr = DrawClippedTile16HalfWidth; + DrawLargePixelPtr = DrawLargePixel16HalfWidth; + } + else + { + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + DrawLargePixelPtr = DrawLargePixel16; + } + } + else + { + switch (GFX.r2131 & 0xC0) + { + case 0x00: + DrawTilePtr = DrawTile16Add; + DrawClippedTilePtr = DrawClippedTile16Add; + DrawLargePixelPtr = DrawLargePixel16Add; + break; + case 0x40: + if (GFX.r2130 & 2) + { + DrawTilePtr = DrawTile16Add1_2; + DrawClippedTilePtr = DrawClippedTile16Add1_2; + } + else + { + // Fixed colour addition + DrawTilePtr = DrawTile16FixedAdd1_2; + DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2; + } + DrawLargePixelPtr = DrawLargePixel16Add1_2; + break; + case 0x80: + DrawTilePtr = DrawTile16Sub; + DrawClippedTilePtr = DrawClippedTile16Sub; + DrawLargePixelPtr = DrawLargePixel16Sub; + break; + case 0xC0: + if (GFX.r2130 & 2) + { + DrawTilePtr = DrawTile16Sub1_2; + DrawClippedTilePtr = DrawClippedTile16Sub1_2; + } + else + { + // Fixed colour substraction + DrawTilePtr = DrawTile16FixedSub1_2; + DrawClippedTilePtr = DrawClippedTile16FixedSub1_2; + } + DrawLargePixelPtr = DrawLargePixel16Sub1_2; + break; + } + } +} + +void S9xSetupOBJ () +{ +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "Entering SetupOBJS()\n"); +#endif + int SmallWidth, SmallHeight; + int LargeWidth, LargeHeight; + + switch (PPU.OBJSizeSelect) + { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + 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; + } + if(IPPU.InterlaceSprites) + { + SmallHeight>>=1; LargeHeight>>=1; + } +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "Sizes are %dx%d and %dx%d\n", SmallWidth, SmallHeight, LargeWidth, LargeHeight); +#endif + + /* OK, we have three cases here. Either there's no priority, priority is + * normal FirstSprite, or priority is FirstSprite+Y. The first two are + * easy, the last is somewhat more ... interesting. So we split them up. */ + + int Height; + uint8 S; + +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "Priority rotation=%d, OAMAddr=%d -> ", PPU.OAMPriorityRotation, PPU.OAMAddr*2 | (PPU.OAMFlip&1)); +#endif + if(!PPU.OAMPriorityRotation || !(PPU.OAMFlip&PPU.OAMAddr&1)){ +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "normal FirstSprite = %02x\n", PPU.FirstSprite); +#endif + /* 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]>=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(LineOBJ[Y]>=32){ + GFX.OBJLines[Y].RTOFlags|=0x40; +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S); +#endif + 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 = 0; Y < SNES_HEIGHT_EXTENDED; Y++) { + if (LineOBJ[Y] < 32) // Add the sentinel + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = -1; + } + 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 (!AnyOBJOnLine[Y]) { + memset(OBJOnLine[Y], 0, 128); + AnyOBJOnLine[Y] = TRUE; + } + 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=32){ + GFX.OBJLines[Y].RTOFlags|=0x40; + #ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S); + #endif + 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; + } + } + +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) { + fprintf(stderr, "Sprites per line:\n"); + for(int xxx=0; xxx=0; j++){ + fprintf(stderr, " %02x.%d", GFX.OBJLines[xxx].OBJ[j].Sprite, GFX.OBJLines[xxx].OBJ[j].Line); + } + fprintf(stderr, "\n"); + } + + fprintf(stderr, "Exiting SetupObj()\n"); + } +#endif + + IPPU.OBJChanged = FALSE; +} + +static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0) +{ +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "Entering DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY); +#endif + CHECK_SOUND(); + + BG.BitShift = 4; + BG.TileShift = 5; + BG.TileAddress = PPU.OBJNameBase; + BG.StartPalette = 128; + BG.PaletteShift = 4; + BG.PaletteMask = 7; + BG.Buffer = IPPU.TileCache [TILE_4BIT]; + BG.Buffered = IPPU.TileCached [TILE_4BIT]; + BG.NameSelect = PPU.OBJNameSelect; + BG.DirectColourMode = FALSE; + + GFX.PixSize = 1; + + struct { + uint16 Pos; + bool8 Value; + } Windows[7]; + int clipcount = GFX.pCurrentClip->Count [4]; + if (!clipcount){ + Windows[0].Pos=0; + Windows[0].Value=TRUE; + Windows[1].Pos=256; + Windows[1].Value=FALSE; + Windows[2].Pos=1000; + Windows[2].Value=FALSE; + } else { + Windows[0].Pos=1000; + Windows[0].Value=FALSE; + for(int clip=0, i=1; clipRight[clip][4]<=GFX.pCurrentClip->Left[clip][4]) continue; + int j; + for(j=0; jLeft[clip][4]; j++); + if(jLeft[clip][4]){ + Windows[j].Value = TRUE; + } else { + // memmove required: Overlapping addresses [Neb] + if(jLeft[clip][4]; + Windows[j].Value = TRUE; + i++; + } + for(j=0; jRight[clip][4]; j++); + if(j>=i || Windows[j].Pos!=GFX.pCurrentClip->Right[clip][4]){ + // memmove required: Overlapping addresses [Neb] + if(jRight[clip][4]; + Windows[j].Value = FALSE; + i++; + } + } + } + +#ifdef MK_DEBUG_RTO +if(Settings.BGLayering) { + fprintf(stderr, "Windows:\n"); + for(int xxx=0; xxx<6; xxx++){ fprintf(stderr, "%d: %d = %d\n", xxx, Windows[xxx].Pos, Windows[xxx].Value); } +} +#endif + + if (Settings.SupportHiRes) + { + if (PPU.BGMode == 5 || PPU.BGMode == 6) + { + // Bah, OnMain is never used except to determine if calling + // SelectTileRenderer is necessary. So let's hack it to false here + // to stop SelectTileRenderer from being called when it causes + // problems. + OnMain = FALSE; + GFX.PixSize = 2; + if (IPPU.DoubleHeightPixels) + { + DrawTilePtr = DrawTile16x2x2; + DrawClippedTilePtr = DrawClippedTile16x2x2; + } + else + { + DrawTilePtr = DrawTile16x2; + DrawClippedTilePtr = DrawClippedTile16x2; + } + } + else + { + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + } + } + else // if (!Settings.SupportHiRes) + { + if (PPU.BGMode == 5 || PPU.BGMode == 6) + { + // Bah, OnMain is never used except to determine if calling + // SelectTileRenderer is necessary. So let's hack it to false here + // to stop SelectTileRenderer from being called when it causes + // problems. + OnMain = FALSE; + } + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + } + GFX.Z1 = D + 2; + + for(uint32 Y=GFX.StartY, Offset=Y*GFX.PPL; Y<=GFX.EndY; Y++, Offset+=GFX.PPL){ +#ifdef MK_DEBUG_RTO + bool8 Flag=0; +#endif + int I = 0; +#ifdef MK_DISABLE_TIME_OVER + int tiles=0; +#else + int tiles=GFX.OBJLines[Y].Tiles; +#endif + 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){ +#ifdef MK_DEBUG_RTO +if(Settings.BGLayering) { + if(!Flag){ Flag=1; fprintf(stderr, "Line %d:", Y); } + fprintf(stderr, " [%02x]", S); +} +#endif + continue; + } + +#ifdef MK_DEBUG_RTO +if(Settings.BGLayering) { + if(!Flag){ Flag=1; fprintf(stderr, "Line %d:", Y); } + fprintf(stderr, " %02x", S); +} +#endif + + if (OnMain && SUB_OR_ADD(4)) + { + SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4); + } + + 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; + int TileInc = 1; + + if (PPU.OBJ[S].HFlip) + { + TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; + BaseTile |= H_FLIP; + TileInc = -1; + } + + GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; + + bool8 WinStat=TRUE; + int WinIdx=0, NextPos=-1000; + int X=PPU.OBJ[S].HPos; if(X==-256) X=256; + for(int t=tiles, O=Offset+X*GFX.PixSize; X<=256 && X=NextPos){ + for(; WinIdx<7 && Windows[WinIdx].Pos<=X; WinIdx++); + if(WinIdx==0) WinStat=FALSE; + else WinStat=Windows[WinIdx-1].Value; + NextPos=(WinIdx<7)?Windows[WinIdx].Pos:1000; + } + + if(X+8X+8) NextPos=X+8; + } + } + } + } +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) if(Flag) fprintf(stderr, "\n"); +#endif + } +#ifdef MK_DEBUG_RTO + if(Settings.BGLayering) fprintf(stderr, "Exiting DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY); +#endif +} + +static void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint8 depths [2] = {Z1, Z2}; + + if (BGMode == 0) + BG.StartPalette = bg << 5; + else + BG.StartPalette = 0; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(((uint8*)SC1-Memory.VRAM)>=0x10000) + SC1-=0x08000; + + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + uint32 Lines; + uint32 OffsetMask; + uint32 OffsetShift; + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + int m5 = (BGMode == 5 || BGMode == 6) ? 1 : 0; + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) + { + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + uint32 MosaicOffset = Y % PPU.Mosaic; + + for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + uint32 MosaicLine = VOffset + Y - MosaicOffset; + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY + 1 - Y; + uint32 VirtAlign = (MosaicLine & 7) << 3; + + uint16 *b1; + uint16 *b2; + + uint32 ScreenLine = MosaicLine >> OffsetShift; + uint32 Rem16 = MosaicLine & 15; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + uint16 *t; + uint32 Left = 0; + uint32 Right = 256 << m5; + + HOffset <<= m5; + + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; + uint32 HPos = HOffset; + uint32 PixWidth = (PPU.Mosaic << m5); + + + if (!ClipCount) + ClipCount = 1; + + for (uint32 clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [bg]) + { + Left = GFX.pCurrentClip->Left [clip][bg] << m5; + Right = GFX.pCurrentClip->Right [clip][bg] << m5; + + uint32 r = Left % (PPU.Mosaic << m5); + HPos = HOffset + Left; + PixWidth = (PPU.Mosaic << m5) - r; + } + uint32 s = Y * GFX.PPL + Left * GFX.PixSize; + for (uint32 x = Left; x < Right; x += PixWidth, + s += (IPPU.HalfWidthPixels ? PixWidth >> 1 : PixWidth) * GFX.PixSize, + HPos += PixWidth, PixWidth = (PPU.Mosaic << m5)) + { + uint32 Quot = (HPos & OffsetMask) >> 3; + + if (x + PixWidth >= Right) + PixWidth = Right - x; + + if (BG.TileSize == 8 && !m5) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + Tile = READ_2BYTES (t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + // Draw tile... + if (BG.TileSize != 8) + { + if (Tile & H_FLIP) + { + // Horizontal flip, but what about vertical flip ? + if (Tile & V_FLIP) + { + // Both horzontal & vertical flip + if (Rem16 < 8) + { + (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + else + { + // Horizontal flip only + if (Rem16 > 7) + { + (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } + else + { + // No horizontal flip, but is there a vertical flip ? + if (Tile & V_FLIP) + { + // Vertical flip only + if (Rem16 < 8) + { + (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + else + { + // Normal unflipped + if (Rem16 > 7) + { + (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } + } + else + (*DrawLargePixelPtr) (Tile + (Quot & 1) * m5, s, HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } +} + +static void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint16 *BPS0; + uint16 *BPS1; + uint16 *BPS2; + uint16 *BPS3; + uint32 Width; + int VOffsetOffset = BGMode == 4 ? 0 : 32; + uint8 depths [2] = {Z1, Z2}; + + BG.StartPalette = 0; + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + + if (PPU.BG[2].SCSize & 1) + BPS1 = BPS0 + 1024; + else + BPS1 = BPS0; + + if (PPU.BG[2].SCSize & 2) + BPS2 = BPS1 + 1024; + else + BPS2 = BPS0; + + if (PPU.BG[2].SCSize & 1) + BPS3 = BPS2 + 1024; + else + BPS3 = BPS2; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(((uint8*)SC1-Memory.VRAM)>=0x10000) + SC1-=0x08000; + + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + + static const int Lines = 1; + int OffsetMask; + int OffsetShift; + int OffsetEnableMask = 1 << (bg + 13); + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) + { + uint32 VOff = LineData [Y].BG[2].VOffset - 1; +// uint32 VOff = LineData [Y].BG[2].VOffset; + uint32 HOff = LineData [Y].BG[2].HOffset; + + int VirtAlign; + int ScreenLine = VOff >> 3; + int t1; + int t2; + uint16 *s0; + uint16 *s1; + uint16 *s2; + + if (ScreenLine & 0x20) + s1 = BPS2, s2 = BPS3; + else + s1 = BPS0, s2 = BPS1; + + s1 += (ScreenLine & 0x1f) << 5; + s2 += (ScreenLine & 0x1f) << 5; + + if(BGMode != 4) + { + if((ScreenLine & 0x1f) == 0x1f) + { + if(ScreenLine & 0x20) + VOffsetOffset = BPS0 - BPS2 - 0x1f*32; + else + VOffsetOffset = BPS2 - BPS0 - 0x1f*32; + } + else + { + VOffsetOffset = 32; + } + } + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + + for (int clip = 0; clip < clipcount; clip++) + { + uint32 Left; + uint32 Right; + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 256; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) + continue; + } + + uint32 VOffset; + uint32 HOffset; + //added: + uint32 LineHOffset=LineData [Y].BG[bg].HOffset; + + uint32 Offset; + uint32 HPos; + uint32 Quot; + uint32 Count; + uint16 *t; + uint32 Quot2; + uint32 VCellOffset; + uint32 HCellOffset; + uint16 *b1; + uint16 *b2; + uint32 TotalCount = 0; + uint32 MaxCount = 8; + + uint32 s = Left * GFX.PixSize + Y * GFX.PPL; + bool8 left_hand_edge = (Left == 0); + Width = Right - Left; + + if (Left & 7) + MaxCount = 8 - (Left & 7); + + while (Left < Right) + { + if (left_hand_edge) + { + // The SNES offset-per-tile background mode has a + // hardware limitation that the offsets cannot be set + // for the tile at the left-hand edge of the screen. + VOffset = LineData [Y].BG[bg].VOffset; + + //MKendora; use temp var to reduce memory accesses + //HOffset = LineData [Y].BG[bg].HOffset; + + HOffset = LineHOffset; + //End MK + + left_hand_edge = FALSE; + } + else + + { + // All subsequent offset tile data is shifted left by one, + // hence the - 1 below. + + Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3; + + if (Quot2 > 31) + s0 = s2 + (Quot2 & 0x1f); + else + s0 = s1 + Quot2; + + HCellOffset = READ_2BYTES (s0); + + if (BGMode == 4) + { + VOffset = LineData [Y].BG[bg].VOffset; + + //MKendora another mem access hack + //HOffset = LineData [Y].BG[bg].HOffset; + HOffset=LineHOffset; + //end MK + + if ((HCellOffset & OffsetEnableMask)) + { + if (HCellOffset & 0x8000) + VOffset = HCellOffset + 1; + else + HOffset = HCellOffset; + } + } + else + { + VCellOffset = READ_2BYTES (s0 + VOffsetOffset); + if ((VCellOffset & OffsetEnableMask)) + VOffset = VCellOffset + 1; + else + VOffset = LineData [Y].BG[bg].VOffset; + + //MKendora Strike Gunner fix + if ((HCellOffset & OffsetEnableMask)) + { + //HOffset= HCellOffset; + + HOffset = (HCellOffset & ~7)|(LineHOffset&7); + //HOffset |= LineData [Y].BG[bg].HOffset&7; + } + else + HOffset=LineHOffset; + //HOffset = LineData [Y].BG[bg].HOffset - + //Settings.StrikeGunnerOffsetHack; + //HOffset &= (~7); + //end MK + } + } + VirtAlign = ((Y + VOffset) & 7) << 3; + ScreenLine = (VOffset + Y) >> OffsetShift; + + if (((VOffset + Y) & 15) > 7) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + HPos = (HOffset + Left) & OffsetMask; + + Quot = HPos >> 3; + + if (BG.TileSize == 8) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + if (MaxCount + TotalCount > Width) + MaxCount = Width - TotalCount; + + Offset = HPos & 7; + + //Count =1; + Count = 8 - Offset; + if (Count > MaxCount) + Count = MaxCount; + + s -= (IPPU.HalfWidthPixels ? Offset >> 1 : Offset) * GFX.PixSize; + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize == 8) + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + + Left += Count; + TotalCount += Count; + s += (IPPU.HalfWidthPixels ? (Offset + Count) >> 1 : (Offset + Count)) * GFX.PixSize; + MaxCount = 8; + } + } + } +} + +static void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2) +{ + CHECK_SOUND(); + + if(IPPU.Interlace) + { + GFX.Pitch = GFX.RealPitch; + GFX.PPL = GFX.PPLx2 >> 1; + } + GFX.PixSize = 1; + uint8 depths [2] = {Z1, Z2}; + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 Width; + + BG.StartPalette = 0; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if ((PPU.BG[bg].SCSize & 1)) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if((SC1-(unsigned short*)Memory.VRAM)>0x10000) + SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000]; + + if ((PPU.BG[bg].SCSize & 2)) + SC2 = SC1 + 1024; + else SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + + if ((PPU.BG[bg].SCSize & 1)) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + + + int Lines; + int VOffsetMask; + int VOffsetShift; + + if (BG.TileSize == 16) + { + VOffsetMask = 0x3ff; + VOffsetShift = 4; + } + else + { + VOffsetMask = 0x1ff; + VOffsetShift = 3; + } + int endy = IPPU.Interlace ? 1 + (GFX.EndY << 1) : GFX.EndY; + + for (int Y = IPPU.Interlace ? GFX.StartY << 1 : GFX.StartY; Y <= endy; Y += Lines) + { + int y = IPPU.Interlace ? (Y >> 1) : Y; + uint32 VOffset = LineData [y].BG[bg].VOffset; + uint32 HOffset = LineData [y].BG[bg].HOffset; + int VirtAlign = (Y + VOffset) & 7; + + for (Lines = 1; Lines < 8 - VirtAlign; Lines++) + if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || + (HOffset != LineData [y + Lines].BG[bg].HOffset)) + break; + + HOffset <<= 1; + if (Y + Lines > endy) + Lines = endy + 1 - Y; + VirtAlign <<= 3; + + int ScreenLine = (VOffset + Y) >> VOffsetShift; + int t1; + int t2; + if (((VOffset + Y) & 15) > 7) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + for (int clip = 0; clip < clipcount; clip++) + { + int Left; + int Right; + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 512; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg] * 2; + Right = GFX.pCurrentClip->Right [clip][bg] * 2; + + if (Right <= Left) + continue; + } + + uint32 s = (IPPU.HalfWidthPixels ? Left >> 1 : Left) * GFX.PixSize + Y * GFX.PPL; + uint32 HPos = (HOffset + Left * GFX.PixSize) & 0x3ff; + + uint32 Quot = HPos >> 3; + uint32 Count = 0; + + uint16 *t; + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + + Width = Right - Left; + // Left hand edge clipped tile + if (HPos & 7) + { + int Offset = (HPos & 7); + Count = 8 - Offset; + if (Count > Width) + Count = Width; + s -= (IPPU.HalfWidthPixels ? Offset >> 1 : Offset); + Tile = READ_2BYTES (t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + + t += Quot & 1; + if (Quot == 63) + t = b2; + else if (Quot == 127) + t = b1; + Quot++; + s += (IPPU.HalfWidthPixels ? 4 : 8); + } + + // Middle, unclipped tiles + Count = Width - Count; + int Middle = Count >> 3; + Count &= 7; + for (int C = Middle; C > 0; s += (IPPU.HalfWidthPixels ? 4 : 8), Quot++, C--) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResTilePtr) (Tile + (Quot & 1), + s, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1), + s, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1), + s, VirtAlign, Lines); + } + } + + t += Quot & 1; + if (Quot == 63) + t = b2; + else + if (Quot == 127) + t = b1; + } + + // Right-hand edge clipped tiles + if (Count) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + } + } + } + GFX.Pitch = IPPU.DoubleHeightPixels ? GFX.RealPitch * 2 : GFX.RealPitch; + GFX.PPL = IPPU.DoubleHeightPixels ? GFX.PPLx2 : (GFX.PPLx2 >> 1); + +} + +static void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif + GFX.PixSize = 1; + + BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; + BG.BitShift = BitShifts[BGMode][bg]; + BG.TileShift = TileShifts[BGMode][bg]; + BG.TileAddress = PPU.BG[bg].NameBase << 1; + BG.NameSelect = 0; + BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]]; + BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; + BG.PaletteShift = PaletteShifts[BGMode][bg]; + BG.PaletteMask = PaletteMasks[BGMode][bg]; + BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && + (GFX.r2130 & 1); + + if (PPU.BGMosaic [bg] && PPU.Mosaic > 1) + { + DrawBackgroundMosaic (BGMode, bg, Z1, Z2); + return; + + } + switch (BGMode) + { + case 2: + case 4: // Used by Puzzle Bobble + DrawBackgroundOffset (BGMode, bg, Z1, Z2); + return; + + case 5: + case 6: // XXX: is also offset per tile. +// if (Settings.SupportHiRes) +// { + if (!Settings.SupportHiRes) + SelectTileRenderer(TRUE /* normal */); + DrawBackgroundMode5 (BGMode, bg, Z1, Z2); + return; +// } + break; + } + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 Width; + uint8 depths [2] = {Z1, Z2}; + + if (BGMode == 0) + BG.StartPalette = bg << 5; + else BG.StartPalette = 0; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(SC1>=(unsigned short*)(Memory.VRAM+0x10000)) + SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000]; + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + + + int Lines; + int OffsetMask; + int OffsetShift; + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) + { + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + int VirtAlign = (Y + VOffset) & 7; + + for (Lines = 1; Lines < 8 - VirtAlign; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY + 1 - Y; + + VirtAlign <<= 3; + + uint32 ScreenLine = (VOffset + Y) >> OffsetShift; + uint32 t1; + uint32 t2; + if (((VOffset + Y) & 15) > 7) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + for (int clip = 0; clip < clipcount; clip++) + { + uint32 Left; + uint32 Right; + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 256; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) + continue; + } + + uint32 s = Left * GFX.PixSize + Y * GFX.PPL; + uint32 HPos = (HOffset + Left) & OffsetMask; + + uint32 Quot = HPos >> 3; + uint32 Count = 0; + + uint16 *t; + if (BG.TileSize == 8) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + Width = Right - Left; + // Left hand edge clipped tile + if (HPos & 7) + { + uint32 Offset = (HPos & 7); + Count = 8 - Offset; + if (Count > Width) + Count = Width; + s -= Offset * GFX.PixSize; + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize == 8) + { + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, + Lines); + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s, + Offset, Count, VirtAlign, Lines); + } + } + + if (BG.TileSize == 8) + { + t++; + if (Quot == 31) + t = b2; + else if (Quot == 63) + t = b1; + } + else + { + t += Quot & 1; + if (Quot == 63) + t = b2; + else if (Quot == 127) + t = b1; + } + Quot++; + s += (IPPU.HalfWidthPixels ? 4 : 8) * GFX.PixSize; + } + + // Middle, unclipped tiles + Count = Width - Count; + int Middle = Count >> 3; + Count &= 7; + for (int C = Middle; C > 0; s += (IPPU.HalfWidthPixels ? 4 : 8) * GFX.PixSize, Quot++, C--) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize != 8) + { + if (Tile & H_FLIP) + { + // Horizontal flip, but what about vertical flip ? + if (Tile & V_FLIP) + { + // Both horzontal & vertical flip + (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s, + VirtAlign, Lines); + } + else + { + // Horizontal flip only + (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s, + VirtAlign, Lines); + } + } + else + { + // No horizontal flip, but is there a vertical flip ? + if (Tile & V_FLIP) + { + // Vertical flip only + (*DrawTilePtr) (Tile + t2 + (Quot & 1), s, + VirtAlign, Lines); + } + else + { + // Normal unflipped + (*DrawTilePtr) (Tile + t1 + (Quot & 1), s, + VirtAlign, Lines); + } + } + } + else + { + (*DrawTilePtr) (Tile, s, VirtAlign, Lines); + } + + if (BG.TileSize == 8) + { + t++; + if (Quot == 31) + t = b2; + else + if (Quot == 63) + t = b1; + } + else + { + t += Quot & 1; + if (Quot == 63) + t = b2; + else + if (Quot == 127) + t = b1; + } + } + // Right-hand edge clipped tiles + if (Count) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize == 8) + (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign, + Lines); + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, 0, + Count, VirtAlign, Lines); + } + else if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, + Lines); + } + else + { + // H flip only + (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, + Lines); + } + } + else + { + // V flip only + (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), + s, 0, Count, VirtAlign, + Lines); + } + } + } + } + } +} + +#define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \ + uint16 *ScreenColors; \ + CHECK_SOUND(); \ +\ + uint8 *VRAM1 = Memory.VRAM + 1; \ + if (GFX.r2130 & 1) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps (); \ + ScreenColors = DirectColourMaps [0]; \ + } \ + else \ + ScreenColors = IPPU.ScreenColors; \ +\ + int aa, cc; \ + int dir; \ + int startx, endx; \ + uint32 Left = 0; \ + uint32 Right = 256; \ + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ +\ + if (!ClipCount) \ + ClipCount = 1; \ +\ + Screen += GFX.StartY * GFX.Pitch; \ + uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ +\ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \ + { \ + int yy; \ +\ + int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ + int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ +\ + int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ + int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ +\ + if (PPU.Mode7VFlip) \ + yy = 255 - (int) Line; \ + else \ + yy = Line; \ +\ + yy += CLIP_10_BIT_SIGNED(VOffset - CentreY); \ +\ + int BB = l->MatrixB * yy + (CentreX << 8); \ + int DD = l->MatrixD * yy + (CentreY << 8); \ +\ + for (uint32 clip = 0; clip < ClipCount; clip++) \ + { \ + if (GFX.pCurrentClip->Count [bg]) \ + { \ + Left = GFX.pCurrentClip->Left [clip][bg]; \ + Right = GFX.pCurrentClip->Right [clip][bg]; \ + if (Right <= Left) \ + continue; \ + } \ + TYPE *p = (TYPE *) Screen + Left; \ + uint8 *d = Depth + Left; \ +\ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + endx = Left - 1; \ + dir = -1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + endx = Right; \ + dir = 1; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ +\ + int xx = startx + CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA * xx; \ + int CC = l->MatrixC * xx; \ +\ + if (!PPU.Mode7Repeat) \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + *p = (FUNC); \ + *d = GFX.Z1; \ + } \ + } \ + } \ + else \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ +\ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + *p = (FUNC); \ + *d = GFX.Z1; \ + } \ + } \ + else \ + { \ + if (PPU.Mode7Repeat == 3) \ + { \ + X = (x + HOffset) & 7; \ + Y = (yy + CentreY) & 7; \ + uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + *p = (FUNC); \ + *d = GFX.Z1; \ + } \ + } \ + } \ + } \ + } \ + } \ + } + +static void DrawBGMode7Background (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (uint8, (uint8) (b & GFX.Mode7Mask)) +} + +static void DrawBGMode7Background16 (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (uint16, ScreenColors [b & GFX.Mode7Mask]); +} + +static void DrawBGMode7Background16Add (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD (ScreenColors [b & GFX.Mode7Mask], + p [GFX.Delta]) : + COLOR_ADD (ScreenColors [b & GFX.Mode7Mask], + GFX.FixedColour)) : + ScreenColors [b & GFX.Mode7Mask]); +} + +static void DrawBGMode7Background16Add1_2 (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD1_2 (ScreenColors [b & GFX.Mode7Mask], + p [GFX.Delta]) : + COLOR_ADD (ScreenColors [b & GFX.Mode7Mask], + GFX.FixedColour)) : + ScreenColors [b & GFX.Mode7Mask]); +} + +static void DrawBGMode7Background16Sub (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB (ScreenColors [b & GFX.Mode7Mask], + p [GFX.Delta]) : + COLOR_SUB (ScreenColors [b & GFX.Mode7Mask], + GFX.FixedColour)) : + ScreenColors [b & GFX.Mode7Mask]); +} + +static void DrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB1_2 (ScreenColors [b & GFX.Mode7Mask], + p [GFX.Delta]) : + COLOR_SUB (ScreenColors [b & GFX.Mode7Mask], + GFX.FixedColour)) : + ScreenColors [b & GFX.Mode7Mask]); +} + +#define RENDER_BACKGROUND_MODE7_i(TYPE,FUNC,COLORFUNC) \ + uint16 *ScreenColors; \ + CHECK_SOUND(); \ +\ + uint8 *VRAM1 = Memory.VRAM + 1; \ + if (GFX.r2130 & 1) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps (); \ + ScreenColors = DirectColourMaps [0]; \ + } \ + else \ + ScreenColors = IPPU.ScreenColors; \ + \ + int aa, cc; \ + int dir; \ + int startx, endx; \ + uint32 Left = 0; \ + uint32 Right = 256; \ + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ + \ + if (!ClipCount) \ + ClipCount = 1; \ + \ + Screen += GFX.StartY * GFX.Pitch; \ + uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ + bool8 allowSimpleCase = FALSE; \ + if (!l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100) \ + && !LineMatrixData[GFX.EndY].MatrixB && !LineMatrixData[GFX.EndY].MatrixC \ + && (LineMatrixData[GFX.EndY].MatrixA == 0x0100) && (LineMatrixData[GFX.EndY].MatrixD == 0x0100) \ + ) \ + allowSimpleCase = TRUE; \ + \ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \ + { \ + int yy; \ + \ + int HOffset = ((int) LineData [Line].BG[0].HOffset << M7) >> M7; \ + int VOffset = ((int) LineData [Line].BG[0].VOffset << M7) >> M7; \ + \ + int CentreX = ((int) l->CentreX << M7) >> M7; \ + int CentreY = ((int) l->CentreY << M7) >> M7; \ + \ + if (PPU.Mode7VFlip) \ + yy = 255 - (int) Line; \ + else \ + yy = Line; \ + \ + \ + yy += CLIP_10_BIT_SIGNED(VOffset - CentreY); \ + bool8 simpleCase = FALSE; \ + int BB; \ + int DD; \ + /* Make a special case for the identity matrix, since it's a common case and */ \ + /* can be done much more quickly without special effects */ \ + if (allowSimpleCase && !l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100)) \ + { \ + BB = CentreX << 8; \ + DD = (yy + CentreY) << 8; \ + simpleCase = TRUE; \ + } \ + else \ + { \ + BB = l->MatrixB * yy + (CentreX << 8); \ + DD = l->MatrixD * yy + (CentreY << 8); \ + } \ + \ + for (uint32 clip = 0; clip < ClipCount; clip++) \ + { \ + if (GFX.pCurrentClip->Count [bg]) \ + { \ + Left = GFX.pCurrentClip->Left [clip][bg]; \ + Right = GFX.pCurrentClip->Right [clip][bg]; \ + if (Right <= Left) \ + continue; \ + } \ + TYPE *p = (TYPE *) Screen + Left; \ + uint8 *d = Depth + Left; \ + \ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + endx = Left - 1; \ + dir = -1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + endx = Right; \ + dir = 1; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + int xx; \ + \ + xx = startx + CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA, CC = 0; \ + if (simpleCase) \ + { \ + AA = xx << 8; \ + } \ + else \ + { \ + AA = l->MatrixA * xx; \ + CC = l->MatrixC * xx; \ + } \ + if (simpleCase) \ + { \ + if (!PPU.Mode7Repeat) \ + { \ + int x = startx; \ + do \ + { \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = (DD >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + TYPE theColor = COLORFUNC; \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + AA += aa, p++, d++; \ + x += dir; \ + } while (x != endx); \ + } \ + else \ + { \ + int x = startx; \ + do { \ + int X = (AA + BB) >> 8; \ + int Y = DD >> 8; \ +\ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + TYPE theColor = COLORFUNC; \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + } \ + else if (PPU.Mode7Repeat == 3) \ + { \ + X = (x + HOffset) & 7; \ + Y = (yy + CentreY) & 7; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + TYPE theColor = COLORFUNC; \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + } \ + AA += aa; p++; d++; \ + x += dir; \ + } while (x != endx); \ + } \ + } \ + else if (!PPU.Mode7Repeat) \ + { \ + /* The bilinear interpolator: get the colors at the four points surrounding */ \ + /* the location of one point in the _sampled_ image, and weight them according */ \ + /* to their (city block) distance. It's very smooth, but blurry with "close up" */ \ + /* points. */ \ + \ + /* 460 (slightly less than 2 source pixels per displayed pixel) is an educated */ \ + /* guess for where bilinear filtering will become a poor method for averaging. */ \ + /* (When reducing the image, the weighting used by a bilinear filter becomes */ \ + /* arbitrary, and a simple mean is a better way to represent the source image.) */ \ + /* You can think of this as a kind of mipmapping. */ \ + if ((aa < 460 && aa > -460) && (cc < 460 && cc > -460)) \ + {\ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + uint32 xPos = AA + BB; \ + uint32 xPix = xPos >> 8; \ + uint32 yPos = CC + DD; \ + uint32 yPix = yPos >> 8; \ + uint32 X = xPix & 0x3ff; \ + uint32 Y = yPix & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \ + uint32 X10 = (xPix + dir) & 0x3ff; \ + uint32 Y01 = (yPix + (PPU.Mode7VFlip?-1:1)) & 0x3ff; \ + uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ + uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ + uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 p1 = COLORFUNC; \ + p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \ + b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \ + uint32 p2 = COLORFUNC; \ + p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \ + b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \ + uint32 p4 = COLORFUNC; \ + p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \ + b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \ + uint32 p3 = COLORFUNC; \ + p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \ + /* Xdel, Ydel: position (in 1/32nds) between the points */ \ + uint32 Xdel = (xPos >> 3) & 0x1F; \ + uint32 Ydel = (yPos >> 3) & 0x1F; \ + uint32 XY = (Xdel*Ydel) >> 5; \ + uint32 area1 = 0x20 + XY - Xdel - Ydel; \ + uint32 area2 = Xdel - XY; \ + uint32 area3 = Ydel - XY; \ + uint32 area4 = XY; \ + if(PPU.Mode7HFlip){ \ + uint32 tmp=area1; area1=area2; area2=tmp; \ + tmp=area3; area3=area4; area4=tmp; \ + } \ + if(PPU.Mode7VFlip){ \ + uint32 tmp=area1; area1=area3; area3=tmp; \ + tmp=area2; area2=area4; area4=tmp; \ + } \ + uint32 tempColor = ((area1 * p1) + \ + (area2 * p2) + \ + (area3 * p3) + \ + (area4 * p4)) >> 5; \ + TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + } \ + } \ + else \ + /* The oversampling method: get the colors at four corners of a square */ \ + /* in the _displayed_ image, and average them. It's sharp and clean, but */ \ + /* gives the usual huge pixels when the source image gets "close." */ \ + { \ + /* Find the dimensions of the square in the source image whose corners will be examined. */ \ + uint32 aaDelX = aa >> 1; \ + uint32 ccDelX = cc >> 1; \ + uint32 bbDelY = l->MatrixB >> 1; \ + uint32 ddDelY = l->MatrixD >> 1; \ + /* Offset the location within the source image so that the four sampled points */ \ + /* center around where the single point would otherwise have been drawn. */ \ + BB -= (bbDelY >> 1); \ + DD -= (ddDelY >> 1); \ + AA -= (aaDelX >> 1); \ + CC -= (ccDelX >> 1); \ + uint32 BB10 = BB + aaDelX; \ + uint32 BB01 = BB + bbDelY; \ + uint32 BB11 = BB + aaDelX + bbDelY; \ + uint32 DD10 = DD + ccDelX; \ + uint32 DD01 = DD + ddDelY; \ + uint32 DD11 = DD + ccDelX + ddDelY; \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + uint32 X = ((AA + BB) >> 8) & 0x3ff; \ + uint32 Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + /* X, Y, X10, Y10, etc. are the coordinates of the four pixels within the */ \ + /* source image that we're going to examine. */ \ + uint32 X10 = ((AA + BB10) >> 8) & 0x3ff; \ + uint32 Y10 = ((CC + DD10) >> 8) & 0x3ff; \ + uint32 X01 = ((AA + BB01) >> 8) & 0x3ff; \ + uint32 Y01 = ((CC + DD01) >> 8) & 0x3ff; \ + uint32 X11 = ((AA + BB11) >> 8) & 0x3ff; \ + uint32 Y11 = ((CC + DD11) >> 8) & 0x3ff; \ + uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y10 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ + uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X01 >> 2) & ~1)] << 7); \ + uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y11 & ~7) << 5) + ((X11 >> 2) & ~1)] << 7); \ + TYPE p1 = COLORFUNC; \ + b = *(TileData10 + ((Y10 & 7) << 4) + ((X10 & 7) << 1)); \ + TYPE p2 = COLORFUNC; \ + b = *(TileData01 + ((Y01 & 7) << 4) + ((X01 & 7) << 1)); \ + TYPE p3 = COLORFUNC; \ + b = *(TileData11 + ((Y11 & 7) << 4) + ((X11 & 7) << 1)); \ + TYPE p4 = COLORFUNC; \ + TYPE theColor = Q_INTERPOLATE(p1, p2, p3, p4); \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + } \ + } \ + } \ + else \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + uint32 xPos = AA + BB; \ + uint32 xPix = xPos >> 8; \ + uint32 yPos = CC + DD; \ + uint32 yPix = yPos >> 8; \ + uint32 X = xPix; \ + uint32 Y = yPix; \ + \ +\ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \ + uint32 X10 = (xPix + dir) & 0x3ff; \ + uint32 Y01 = (yPix + dir) & 0x3ff; \ + uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ + uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ + uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 p1 = COLORFUNC; \ + p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \ + b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \ + uint32 p2 = COLORFUNC; \ + p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \ + b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \ + uint32 p4 = COLORFUNC; \ + p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \ + b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \ + uint32 p3 = COLORFUNC; \ + p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \ + /* Xdel, Ydel: position (in 1/32nds) between the points */ \ + uint32 Xdel = (xPos >> 3) & 0x1F; \ + uint32 Ydel = (yPos >> 3) & 0x1F; \ + uint32 XY = (Xdel*Ydel) >> 5; \ + uint32 area1 = 0x20 + XY - Xdel - Ydel; \ + uint32 area2 = Xdel - XY; \ + uint32 area3 = Ydel - XY; \ + uint32 area4 = XY; \ + uint32 tempColor = ((area1 * p1) + \ + (area2 * p2) + \ + (area3 * p3) + \ + (area4 * p4)) >> 5; \ + TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + } \ + else \ + { \ + if (PPU.Mode7Repeat == 3) \ + { \ + X = (x + HOffset) & 7; \ + Y = (yy + CentreY) & 7; \ + uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ + if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ + { \ + TYPE theColor = COLORFUNC; \ + *p = (FUNC) | ALPHA_BITS_MASK; \ + *d = GFX.Z1; \ + } \ + } \ + } \ + } \ + } \ + } \ + } + +STATIC uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D) +{ + register uint32 x = ((A >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + + ((B >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + + ((C >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + + ((D >> 2) & HIGH_BITS_SHIFTED_TWO_MASK); + register uint32 y = (A & TWO_LOW_BITS_MASK) + + (B & TWO_LOW_BITS_MASK) + + (C & TWO_LOW_BITS_MASK) + + (D & TWO_LOW_BITS_MASK); + y = (y>>2) & TWO_LOW_BITS_MASK; + return x+y; +} + +static void DrawBGMode7Background16_i (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7_i (uint16, theColor, (ScreenColors[b & GFX.Mode7Mask])); +} + +static void DrawBGMode7Background16Add_i (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + (COLOR_ADD (theColor, + p [GFX.Delta])) : + (COLOR_ADD (theColor, + GFX.FixedColour))) : + theColor, (ScreenColors[b & GFX.Mode7Mask])); +} + +static void DrawBGMode7Background16Add1_2_i (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD1_2 (theColor, + p [GFX.Delta]) : + COLOR_ADD (theColor, + GFX.FixedColour)) : + theColor, (ScreenColors[b & GFX.Mode7Mask])); +} + +static void DrawBGMode7Background16Sub_i (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB (theColor, + p [GFX.Delta]) : + COLOR_SUB (theColor, + GFX.FixedColour)) : + theColor, (ScreenColors[b & GFX.Mode7Mask])); +} + +static void DrawBGMode7Background16Sub1_2_i (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB1_2 (theColor, + p [GFX.Delta]) : + COLOR_SUB (theColor, + GFX.FixedColour)) : + theColor, (ScreenColors[b & GFX.Mode7Mask])); +} + +#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); + +static void RenderScreen (uint8 *Screen, bool8 sub, bool8 force_no_add, uint8 D) +{ + bool8 BG0; + bool8 BG1; + bool8 BG2; + bool8 BG3; + bool8 OB; + + GFX.S = Screen; + + if (!sub) + { + GFX.pCurrentClip = &IPPU.Clip [0]; + BG0 = ON_MAIN (0); + BG1 = ON_MAIN (1); + BG2 = ON_MAIN (2); + BG3 = ON_MAIN (3); + OB = ON_MAIN (4); + } + else + { + GFX.pCurrentClip = &IPPU.Clip [1]; + BG0 = ON_SUB (0); + BG1 = ON_SUB (1); + BG2 = ON_SUB (2); + BG3 = ON_SUB (3); + OB = ON_SUB (4); + } + + sub |= force_no_add; + + switch (PPU.BGMode) { + case 0: + case 1: + if (OB) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4)); + DrawOBJS (!sub, D); + } + if (BG0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(0)); + DrawBackground (PPU.BGMode, 0, D + 10, D + 14); + } + if (BG1) + { + SelectTileRenderer (sub || !SUB_OR_ADD(1)); + DrawBackground (PPU.BGMode, 1, D + 9, D + 13); + } + if (BG2) + { + SelectTileRenderer (sub || !SUB_OR_ADD(2)); + DrawBackground (PPU.BGMode, 2, D + 3, + PPU.BG3Priority ? D + 17 : D + 6); + } + if (BG3 && PPU.BGMode == 0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(3)); + DrawBackground (PPU.BGMode, 3, D + 2, D + 5); + } + break; + case 2: + case 3: + case 4: + case 5: + case 6: + if (OB) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4)); + DrawOBJS (!sub, D); + } + if (BG0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(0)); + DrawBackground (PPU.BGMode, 0, D + 5, D + 13); + } + if (BG1 && PPU.BGMode != 6) + { + SelectTileRenderer (sub || !SUB_OR_ADD(1)); + DrawBackground (PPU.BGMode, 1, D + 2, D + 9); + } + break; + case 7: + if (OB) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4)); + DrawOBJS (!sub, D); + } + if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1)) + { + int bg; + + if ((Memory.FillRAM [0x2133] & 0x40)&&BG1) + { + GFX.Mode7Mask = 0x7f; + GFX.Mode7PriorityMask = 0x80; + Mode7Depths [0] = (BG0?5:1) + D; + Mode7Depths [1] = 9 + D; + bg = 1; + } + else + { + GFX.Mode7Mask = 0xff; + GFX.Mode7PriorityMask = 0; + Mode7Depths [0] = 5 + D; + Mode7Depths [1] = 5 + D; + bg = 0; + } + if (sub || !SUB_OR_ADD(0)) + { + if (!Settings.Mode7Interpolate) + DrawBGMode7Background16 (Screen, bg); + else + DrawBGMode7Background16_i (Screen, bg); + } + else + { + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + if (!Settings.Mode7Interpolate) + DrawBGMode7Background16Sub1_2 (Screen, bg); + else + DrawBGMode7Background16Sub1_2_i (Screen, bg); + } + else + { + if (!Settings.Mode7Interpolate) + DrawBGMode7Background16Sub (Screen, bg); + else + DrawBGMode7Background16Sub_i (Screen, bg); + } + } + else + { + if (GFX.r2131 & 0x40) + { + if (!Settings.Mode7Interpolate) + DrawBGMode7Background16Add1_2 (Screen, bg); + else + DrawBGMode7Background16Add1_2_i (Screen, bg); + } + else + { + if (!Settings.Mode7Interpolate) + DrawBGMode7Background16Add (Screen, bg); + else + DrawBGMode7Background16Add_i (Screen, bg); + } + } + } + } + break; + default: + break; + } +} + +#include "font.h" + +void DisplayChar (uint8 *Screen, uint8 c) +{ + int line = (((c & 0x7f) - 32) >> 4) * font_height; + int offset = (((c & 0x7f) - 32) & 15) * font_width; + int h, w; + uint16 *s = (uint16 *) Screen; + for (h = 0; h < font_height; h++, line++, + s += GFX.PPL - font_width) + { + for (w = 0; w < font_width; w++, s++) + { + uint8 p = font [line][offset + w]; + + if (p == '#') + { + /* + if(Memory.Hacked) + *s= BUILD_PIXEL(31,0,0); + else if(Memory.Iffy) + *s= BUILD_PIXEL(31,31,0); + else if(Memory.Iformat==1) + *s= BUILD_PIXEL(0,31,0); + else if(Memory.Iformat==2) + *s= BUILD_PIXEL(0,31,31); + else *s = 0xffff; + */ + *s=Settings.DisplayColor; + } + else + if (p == '.') + *s = BLACK; + } + } +} + +static void S9xDisplayFrameRate () +{ + uint8 *Screen = GFX.Screen + 2 + + (IPPU.RenderedScreenHeight - font_height - 1) * GFX.Pitch2; + char string [10]; + int len = 5; + + sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, + (int) Memory.ROMFramesPerSecond); + + int i; + for (i = 0; i < len; i++) + { + DisplayChar (Screen, string [i]); + Screen += (font_width - 1) * sizeof (uint16); + } +} + +static void S9xDisplayString (const char *string) +{ + uint8 *Screen = GFX.Screen + 2 + + (IPPU.RenderedScreenHeight - font_height * 5) * GFX.Pitch2; + int len = strlen (string); + int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); + int char_count = 0; + int i; + + for (i = 0; i < len; i++, char_count++) + { + if (char_count >= max_chars || string [i] < 32) + { + Screen -= (font_width - 1) * max_chars * sizeof (uint16); + Screen += font_height * GFX.Pitch; + if (Screen >= GFX.Screen + GFX.Pitch * IPPU.RenderedScreenHeight) + break; + char_count -= max_chars; + } + if (string [i] < 32) + continue; + DisplayChar (Screen, string [i]); + Screen += (font_width - 1) * sizeof (uint16); + } +} + +void S9xUpdateScreen () +{ + int32 x2 = 1; + + GFX.S = GFX.Screen; + GFX.r2131 = Memory.FillRAM [0x2131]; + GFX.r212c = Memory.FillRAM [0x212c]; + GFX.r212d = Memory.FillRAM [0x212d]; + GFX.r2130 = Memory.FillRAM [0x2130]; + +#ifdef JP_FIX + + GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 && + (GFX.r212c & 15) != (GFX.r212d & 15) && + (GFX.r2131 == 0x3f); + +#else + + GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 && + (GFX.r212c & 15) != (GFX.r212d & 15) && + (GFX.r2131 & 0x3f) == 0; + +#endif + + if (IPPU.OBJChanged) + S9xSetupOBJ (); + + if (PPU.RecomputeClipWindows) + { + ComputeClipWindows (); + PPU.RecomputeClipWindows = FALSE; + } + + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) + GFX.EndY = PPU.ScreenHeight - 1; + + // XXX: Check ForceBlank? Or anything else? + PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags; + + uint32 starty = GFX.StartY; + uint32 endy = GFX.EndY; + + if (Settings.SupportHiRes && + (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace || IPPU.DoubleHeightPixels)) + { + if (PPU.BGMode == 5 || PPU.BGMode == 6|| IPPU.Interlace) + { + IPPU.RenderedScreenWidth = 512; + x2 = 2; + } + + if (IPPU.DoubleHeightPixels) + { + starty = GFX.StartY * 2; + endy = GFX.EndY * 2 + 1; + } + + if ((PPU.BGMode == 5 || PPU.BGMode == 6) && !IPPU.DoubleWidthPixels) + { + // The game has switched from lo-res to hi-res mode part way down + // the screen. Scale any existing lo-res pixels on screen + for (register uint32 y = 0; y < starty; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255; + register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510; + + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + IPPU.DoubleWidthPixels = TRUE; + IPPU.HalfWidthPixels = FALSE; + } + // BJ: And we have to change the height if Interlace gets set, + // too. + if (IPPU.Interlace && !IPPU.DoubleHeightPixels) + { + starty = GFX.StartY * 2; + endy = GFX.EndY * 2 + 1; + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + IPPU.DoubleHeightPixels = TRUE; + GFX.Pitch2 = GFX.RealPitch; + GFX.Pitch = GFX.RealPitch * 2; + GFX.PPL = GFX.PPLx2 = GFX.RealPitch; + + + // The game has switched from non-interlaced to interlaced mode + // part way down the screen. Scale everything. + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) + { + // memmove converted: Same malloc, different addresses, and identical addresses at line 0 [Neb] + // DS2 DMA notes: This code path is unused [Neb] + memcpy (GFX.Screen + y * 2 * GFX.Pitch2, + GFX.Screen + y * GFX.Pitch2, + GFX.Pitch2); + // memmove converted: Same malloc, different addresses [Neb] + memcpy (GFX.Screen + (y * 2 + 1) * GFX.Pitch2, + GFX.Screen + y * GFX.Pitch2, + GFX.Pitch2); + } + } + } + else if (!Settings.SupportHiRes) + { + if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace) + { + if (!IPPU.HalfWidthPixels) + { + // The game has switched from lo-res to hi-res mode part way down + // the screen. Hi-res pixels must now be drawn at half width. + IPPU.HalfWidthPixels = TRUE; + } + } + else + { + if (IPPU.HalfWidthPixels) + { + // The game has switched from hi-res to lo-res mode part way down + // the screen. Lo-res pixels must now be drawn at FULL width. + IPPU.HalfWidthPixels = FALSE; + } + } + } + + uint32 black = BLACK | (BLACK << 16); + + if (Settings.Transparency) + { + if (GFX.Pseudo) + { + GFX.r2131 = 0x5f; + GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0); + GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f); + GFX.r2130 |= 2; + } + + if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && + (GFX.r2130 & 0x30) != 0x30 && + !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) + { + struct ClipData *pClip; + + GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed], + IPPU.XB [PPU.FixedColourGreen], + IPPU.XB [PPU.FixedColourBlue]); + + // Clear the z-buffer, marking areas 'covered' by the fixed + // colour as depth 1. + pClip = &IPPU.Clip [1]; + + // Clear the z-buffer + if (pClip->Count [5]) + { + // Colour window enabled. + for (uint32 y = starty; y <= endy; y++) + { + ZeroMemory (GFX.SubZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); + ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); + + if (IPPU.Clip [0].Count [5]) + { + uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2); + uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); + while (p < q) + *p++ = black; + } + + for (uint32 c = 0; c < pClip->Count [5]; c++) + { + if (pClip->Right [c][5] > pClip->Left [c][5]) + { + memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2, + 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); + + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + + uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX.Pitch2); + uint16 *q = p + pClip->Right [c][5] * x2; + p += pClip->Left [c][5] * x2; + + while (p < q) + *p++ = (uint16) GFX.FixedColour; + } + } + } + } + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); + memset (GFX.SubZBuffer + y * GFX.ZPitch, 1, IPPU.RenderedScreenWidth); + + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + + uint32 b = GFX.FixedColour | (GFX.FixedColour << 16); + uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2); + uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); + + while (p < q) + *p++ = b; + } + } + } + + if (ANYTHING_ON_SUB) + { + GFX.DB = GFX.SubZBuffer; + RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH); + } + + if (IPPU.Clip [0].Count [5]) + { + for (uint32 y = starty; y <= endy; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); + register uint8 *d = GFX.SubZBuffer + y * GFX.ZPitch; + register uint8 *e = d + IPPU.RenderedScreenWidth; + + while (d < e) + { + if (*d > 1) + *p = *(p + GFX.Delta); + else + *p = BLACK; + d++; + p++; + } + } + } + + GFX.DB = GFX.ZBuffer; + RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH); + + if (SUB_OR_ADD(5)) + { + uint32 back = IPPU.ScreenColors [0]; + uint32 Left = 0; + uint32 Right = 256; + uint32 Count; + + pClip = &IPPU.Clip [0]; + for (uint32 y = starty; y <= endy; y++) + { + if (!(Count = pClip->Count [5])) + { + Left = 0; + Right = 256 * x2; + Count = 1; + } + + for (uint32 b = 0; b < Count; b++) + { + if (pClip->Count [5]) + { + Left = pClip->Left [b][5] * x2; + Right = pClip->Right [b][5] * x2; + if (Right <= Left) + continue; + } + + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + // Subtract, halving the result. + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); + + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_SUB1_2 (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + else + { + // Subtract + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; + register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); + + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_SUB (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + } + else if (GFX.r2131 & 0x40) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_ADD1_2 (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + else if (back != 0) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_ADD (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + else + { + if (!pClip->Count [5]) + { + // The backdrop has not been cleared yet - so + // copy the sub-screen to the main screen + // or fill it with the back-drop colour if the + // sub-screen is clear. + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + register uint8 *e = d + Right; + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = *(p + GFX.Delta); + else + *p = GFX.FixedColour; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + } + } + } + } // --if (SUB_OR_ADD(5)) + else + { + // Subscreen not being added to back + uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + pClip = &IPPU.Clip [0]; + + if (pClip->Count [5]) + { + for (uint32 y = starty; y <= endy; y++) + { + for (uint32 b = 0; b < pClip->Count [5]; b++) + { + uint32 Left = pClip->Left [b][5] * x2; + uint32 Right = pClip->Right [b][5] * x2; + uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; + uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + uint8 *e = d + Right; + d += Left; + + while (d < e) + { + if (*d == 0) + *p = (int16) back; + d++; + p++; + } + } + } + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); + uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; + uint8 *e = d + 256 * x2; + + while (d < e) + { + if (*d == 0) + *p = (int16) back; + d++; + p++; + } + } + } + } + } //force blanking + else + { + // 16bit and transparency but currently no transparency effects in + // operation. + + uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + + if (PPU.ForcedBlanking) + back = black; + + if (IPPU.Clip [0].Count[5]) + { + for (uint32 y = starty; y <= endy; y++) + { + uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2); + uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); + + while (p < q) + *p++ = black; + + for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) + { + if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) + { + uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); + uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2; + p += IPPU.Clip [0].Left [c][5] * x2; + + while (p < q) + *p++ = (uint16) back; + } + } + } + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2); + uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); + while (p < q) + *p++ = back; + } + } + + if (!PPU.ForcedBlanking) + { + for (uint32 y = starty; y <= endy; y++) + { + ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); + } + GFX.DB = GFX.ZBuffer; + RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH); + } + } + } + else + { + } + + if (Settings.SupportHiRes) + { + if (PPU.BGMode != 5 && PPU.BGMode != 6 && IPPU.DoubleWidthPixels) + { + // Mixure of background modes used on screen - scale width + // of all non-mode 5 and 6 pixels. + for (register uint32 y = starty; y <= endy; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255; + register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510; + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + } + + // Double the height of the pixels just drawn + FIX_INTERLACE(GFX.Screen, FALSE, GFX.ZBuffer); + } + + IPPU.PreviousLine = IPPU.CurrentLine; +} + + diff --git a/source/gfx.cpp b/source/gfx.cpp deleted file mode 100644 index 34fb235..0000000 --- a/source/gfx.cpp +++ /dev/null @@ -1,3933 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "gfx.h" -#include "apu.h" -#include "cheats.h" -#include "screenshot.h" - -#define M7 19 -#define M8 19 - -void output_png(); -void ComputeClipWindows (); -static void S9xDisplayFrameRate (); -static void S9xDisplayString (const char *string); - -extern uint8 BitShifts[8][4]; -extern uint8 TileShifts[8][4]; -extern uint8 PaletteShifts[8][4]; -extern uint8 PaletteMasks[8][4]; -extern uint8 Depths[8][4]; -extern uint8 BGSizes [2]; - -extern NormalTileRenderer DrawTilePtr; -extern ClippedTileRenderer DrawClippedTilePtr; -extern NormalTileRenderer DrawHiResTilePtr; -extern ClippedTileRenderer DrawHiResClippedTilePtr; -extern LargePixelRenderer DrawLargePixelPtr; - -extern struct SBG BG; - -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; - -extern uint8 Mode7Depths [2]; - -#define CLIP_10_BIT_SIGNED(a) \ - ((a) & ((1 << 10) - 1)) + (((((a) & (1 << 13)) ^ (1 << 13)) - (1 << 13)) >> 3) - -#define ON_MAIN(N) \ -(GFX.r212c & (1 << (N)) && \ - !(PPU.BG_Forced & (1 << (N)))) - -#define SUB_OR_ADD(N) \ -(GFX.r2131 & (1 << (N))) - -#define ON_SUB(N) \ -((GFX.r2130 & 0x30) != 0x30 && \ - (GFX.r2130 & 2) && \ - (GFX.r212d & (1 << N)) && \ - !(PPU.BG_Forced & (1 << (N)))) - -#define ANYTHING_ON_SUB \ -((GFX.r2130 & 0x30) != 0x30 && \ - (GFX.r2130 & 2) && \ - (GFX.r212d & 0x1f)) - -#define ADD_OR_SUB_ON_ANYTHING \ -(GFX.r2131 & 0x3f) - -#define FIX_INTERLACE(SCREEN, DO_DEPTH, DEPTH) \ - if (IPPU.DoubleHeightPixels && ((PPU.BGMode != 5 && PPU.BGMode != 6) || !IPPU.Interlace)) \ - for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) \ - { \ - /* memmove converted: Same malloc, non-overlapping addresses [Neb] */ \ - memcpy (SCREEN + (y * 2 + 1) * GFX.Pitch2, \ - SCREEN + y * 2 * GFX.Pitch2, \ - GFX.Pitch2); \ - if(DO_DEPTH){ \ - /* memmove required: Same malloc, potentially overlapping addresses [Neb] */ \ - memmove (DEPTH + (y * 2 + 1) * (GFX.PPLx2>>1), \ - DEPTH + y * GFX.PPL, \ - GFX.PPLx2>>1); \ - } \ - } - - -#define BLACK BUILD_PIXEL(0,0,0) - -void DrawTile16 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16HalfWidth (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16HalfWidth (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16x2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16x2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16x2x2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16x2x2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawLargePixel16 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); -void DrawLargePixel16HalfWidth (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Add (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Add (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Add1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Add1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16FixedAdd1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16FixedAdd1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Sub (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Sub (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Sub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Sub1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16FixedSub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16FixedSub1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Add (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Add1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Sub (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Sub1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -bool8 S9xGraphicsInit () -{ - register uint32 PixelOdd = 1; - register uint32 PixelEven = 2; - - for (uint8 bitshift = 0; bitshift < 4; bitshift++) - { - for (register int i = 0; i < 16; i++) - { - register uint32 h = 0; - register uint32 l = 0; - -#if defined(LSB_FIRST) - if (i & 8) - h |= PixelOdd; - if (i & 4) - h |= PixelOdd << 8; - if (i & 2) - h |= PixelOdd << 16; - if (i & 1) - h |= PixelOdd << 24; - if (i & 8) - l |= PixelOdd; - if (i & 4) - l |= PixelOdd << 8; - if (i & 2) - l |= PixelOdd << 16; - if (i & 1) - l |= PixelOdd << 24; -#else - if (i & 8) - h |= (PixelOdd << 24); - if (i & 4) - h |= (PixelOdd << 16); - if (i & 2) - h |= (PixelOdd << 8); - if (i & 1) - h |= PixelOdd; - if (i & 8) - l |= (PixelOdd << 24); - if (i & 4) - l |= (PixelOdd << 16); - if (i & 2) - l |= (PixelOdd << 8); - if (i & 1) - l |= PixelOdd; -#endif - - odd_high[bitshift][i] = h; - odd_low[bitshift][i] = l; - h = l = 0; - -#if defined(LSB_FIRST) - if (i & 8) - h |= PixelEven; - if (i & 4) - h |= PixelEven << 8; - if (i & 2) - h |= PixelEven << 16; - if (i & 1) - h |= PixelEven << 24; - if (i & 8) - l |= PixelEven; - if (i & 4) - l |= PixelEven << 8; - if (i & 2) - l |= PixelEven << 16; - if (i & 1) - l |= PixelEven << 24; -#else - if (i & 8) - h |= (PixelEven << 24); - if (i & 4) - h |= (PixelEven << 16); - if (i & 2) - h |= (PixelEven << 8); - if (i & 1) - h |= PixelEven; - if (i & 8) - l |= (PixelEven << 24); - if (i & 4) - l |= (PixelEven << 16); - if (i & 2) - l |= (PixelEven << 8); - if (i & 1) - l |= PixelEven; -#endif - - even_high[bitshift][i] = h; - even_low[bitshift][i] = l; - } - PixelEven <<= 2; - PixelOdd <<= 2; - } - - GFX.RealPitch = GFX.Pitch2 = GFX.Pitch; - GFX.ZPitch = GFX.Pitch; - GFX.ZPitch >>= 1; - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; - GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; - //GFX.InfoStringTimeout = 0; - //GFX.InfoString = NULL; - - PPU.BG_Forced = 0; - IPPU.OBJChanged = TRUE; - - IPPU.DirectColourMapsNeedRebuild = TRUE; - GFX.PixSize = 1; - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - DrawLargePixelPtr = DrawLargePixel16; - if (Settings.SupportHiRes) - { - DrawHiResTilePtr= DrawTile16; - DrawHiResClippedTilePtr = DrawClippedTile16; - } - else - { - DrawHiResTilePtr= DrawTile16HalfWidth; - DrawHiResClippedTilePtr = DrawClippedTile16HalfWidth; - } - GFX.PPL = GFX.Pitch >> 1; - GFX.PPLx2 = GFX.Pitch; - S9xFixColourBrightness (); - - if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000))) - return (FALSE); - - if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) || - !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000))) - { - if (GFX.ZERO_OR_X2) - { - free ((char *) GFX.ZERO_OR_X2); - GFX.ZERO_OR_X2 = NULL; - } - if (GFX.X2) - { - free ((char *) GFX.X2); - GFX.X2 = NULL; - } - return (FALSE); - } - uint32 r, g, b; - - // Build a lookup table that multiplies a packed RGB value by 2 with - // saturation. - 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); - } - } - } - ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16)); - ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16)); - // Build a lookup table that if the top bit of the color value is zero - // then the value is zero, otherwise multiply the value by 2. Used by - // the color subtraction code. - -#if defined(OLD_COLOUR_BLENDING) - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 = (r2 << 1) & MAX_RED; - - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 = (g2 << 1) & MAX_GREEN; - - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 = (b2 << 1) & MAX_BLUE; - - 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); - } - } - } -#else - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 = (r2 << 1) & MAX_RED; - - if (r2 == 0) - r2 = 1; - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 = (g2 << 1) & MAX_GREEN; - - if (g2 == 0) - g2 = 1; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 = (b2 << 1) & MAX_BLUE; - - if (b2 == 0) - b2 = 1; - 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 - - // Build a lookup table that if the top bit of the color value is zero - // then the value is zero, otherwise its just the value. - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 &= ~0x10; - - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 &= ~GREEN_HI_BIT; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 &= ~0x10; - - 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) -{ - // Free any memory allocated in S9xGraphicsInit - if (GFX.X2) - { - free ((char *) GFX.X2); - GFX.X2 = NULL; - } - if (GFX.ZERO_OR_X2) - { - free ((char *) GFX.ZERO_OR_X2); - GFX.ZERO_OR_X2 = NULL; - } - if (GFX.ZERO) - { - free ((char *) GFX.ZERO); - GFX.ZERO = NULL; - } -} - -void S9xBuildDirectColourMaps () -{ - for (uint32 p = 0; p < 8; p++) - { - for (uint32 c = 0; c < 256; c++) - { -// XXX: Brightness - DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), - ((c & 0x38) >> 1) | (p & 2), - ((c & 0xc0) >> 3) | (p & 4)); - } - } - IPPU.DirectColourMapsNeedRebuild = FALSE; -} - -void S9xStartScreenRefresh () -{ - if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0) - GFX.InfoString = NULL; - - if (IPPU.RenderThisFrame) - { - if (!S9xInitUpdate ()) - { - IPPU.RenderThisFrame = FALSE; - return; - } - - IPPU.RenderedFramesCount++; - IPPU.PreviousLine = IPPU.CurrentLine = 0; - IPPU.MaxBrightness = PPU.Brightness; - IPPU.LatchedBlanking = PPU.ForcedBlanking; - - if(PPU.BGMode == 5 || PPU.BGMode == 6) - IPPU.Interlace = (Memory.FillRAM[0x2133] & 1); - if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace)) - { - IPPU.RenderedScreenWidth = 512; - IPPU.DoubleWidthPixels = TRUE; - IPPU.HalfWidthPixels = FALSE; - - if (IPPU.Interlace) - { - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - IPPU.DoubleHeightPixels = TRUE; - GFX.Pitch2 = GFX.RealPitch; - GFX.Pitch = GFX.RealPitch * 2; - GFX.PPL = GFX.PPLx2 = GFX.RealPitch; - } - else - { - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - GFX.Pitch2 = GFX.Pitch = GFX.RealPitch; - IPPU.DoubleHeightPixels = FALSE; - GFX.PPL = GFX.Pitch >> 1; - GFX.PPLx2 = GFX.PPL << 1; - } - } - else if (!Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace)) - { - IPPU.RenderedScreenWidth = 256; - IPPU.DoubleWidthPixels = FALSE; - // Secret of Mana displays menus with mode 5. - // Make them readable. - IPPU.HalfWidthPixels = TRUE; - } - else - { - IPPU.RenderedScreenWidth = 256; - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - IPPU.DoubleWidthPixels = FALSE; - IPPU.HalfWidthPixels = FALSE; - IPPU.DoubleHeightPixels = FALSE; - { - GFX.Pitch2 = GFX.Pitch = GFX.RealPitch; - GFX.PPL = GFX.PPLx2 >> 1; - GFX.ZPitch = GFX.RealPitch; - GFX.ZPitch >>= 1; - } - } - - PPU.RecomputeClipWindows = TRUE; - GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; - } - - if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) - { - IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; - IPPU.RenderedFramesCount = 0; - IPPU.FrameCount = 0; - } -} - -void RenderLine (uint8 C) -{ - if (IPPU.RenderThisFrame) - { - LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; - LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; - LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; - LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; - - if (PPU.BGMode == 7) - { - struct SLineMatrixData *p = &LineMatrixData [C]; - p->MatrixA = PPU.MatrixA; - p->MatrixB = PPU.MatrixB; - p->MatrixC = PPU.MatrixC; - p->MatrixD = PPU.MatrixD; - p->CentreX = PPU.CentreX; - p->CentreY = PPU.CentreY; - } - else - { - if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && - PPU.BG[2].HOffset == 0xe000) - { - LineData[C].BG[2].VOffset = 0xe1; - LineData[C].BG[2].HOffset = 0; - } - 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; - } -} - -void S9xEndScreenRefresh () -{ - IPPU.HDMAStarted = FALSE; - if (IPPU.RenderThisFrame) - { - FLUSH_REDRAW (); - if (IPPU.ColorsChanged) - { - uint32 saved = PPU.CGDATA[0]; - IPPU.ColorsChanged = FALSE; - PPU.CGDATA[0] = saved; - } - - GFX.Pitch = GFX.Pitch2 = GFX.RealPitch; - GFX.PPL = GFX.PPLx2 >> 1; - S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); - } - - S9xApplyCheats (); - - if (CPU.SRAMModified) - { - S9xAutoSaveSRAM (); - CPU.SRAMModified = FALSE; - } - -} - -void S9xSetInfoString (const char *string) -{ - GFX.InfoString = string; - GFX.InfoStringTimeout = 120; -} - -inline void SelectTileRenderer (bool8 normal) -{ - if (normal) - { - if (IPPU.HalfWidthPixels) - { - DrawTilePtr = DrawTile16HalfWidth; - DrawClippedTilePtr = DrawClippedTile16HalfWidth; - DrawLargePixelPtr = DrawLargePixel16HalfWidth; - } - else - { - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - DrawLargePixelPtr = DrawLargePixel16; - } - } - else - { - switch (GFX.r2131 & 0xC0) - { - case 0x00: - DrawTilePtr = DrawTile16Add; - DrawClippedTilePtr = DrawClippedTile16Add; - DrawLargePixelPtr = DrawLargePixel16Add; - break; - case 0x40: - if (GFX.r2130 & 2) - { - DrawTilePtr = DrawTile16Add1_2; - DrawClippedTilePtr = DrawClippedTile16Add1_2; - } - else - { - // Fixed colour addition - DrawTilePtr = DrawTile16FixedAdd1_2; - DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2; - } - DrawLargePixelPtr = DrawLargePixel16Add1_2; - break; - case 0x80: - DrawTilePtr = DrawTile16Sub; - DrawClippedTilePtr = DrawClippedTile16Sub; - DrawLargePixelPtr = DrawLargePixel16Sub; - break; - case 0xC0: - if (GFX.r2130 & 2) - { - DrawTilePtr = DrawTile16Sub1_2; - DrawClippedTilePtr = DrawClippedTile16Sub1_2; - } - else - { - // Fixed colour substraction - DrawTilePtr = DrawTile16FixedSub1_2; - DrawClippedTilePtr = DrawClippedTile16FixedSub1_2; - } - DrawLargePixelPtr = DrawLargePixel16Sub1_2; - break; - } - } -} - -void S9xSetupOBJ () -{ -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "Entering SetupOBJS()\n"); -#endif - int SmallWidth, SmallHeight; - int LargeWidth, LargeHeight; - - switch (PPU.OBJSizeSelect) - { - case 0: - SmallWidth = SmallHeight = 8; - LargeWidth = LargeHeight = 16; - break; - case 1: - SmallWidth = SmallHeight = 8; - LargeWidth = LargeHeight = 32; - break; - case 2: - SmallWidth = SmallHeight = 8; - LargeWidth = LargeHeight = 64; - break; - case 3: - SmallWidth = SmallHeight = 16; - LargeWidth = LargeHeight = 32; - break; - case 4: - SmallWidth = SmallHeight = 16; - LargeWidth = LargeHeight = 64; - break; - 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; - } - if(IPPU.InterlaceSprites) - { - SmallHeight>>=1; LargeHeight>>=1; - } -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "Sizes are %dx%d and %dx%d\n", SmallWidth, SmallHeight, LargeWidth, LargeHeight); -#endif - - /* OK, we have three cases here. Either there's no priority, priority is - * normal FirstSprite, or priority is FirstSprite+Y. The first two are - * easy, the last is somewhat more ... interesting. So we split them up. */ - - int Height; - uint8 S; - -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "Priority rotation=%d, OAMAddr=%d -> ", PPU.OAMPriorityRotation, PPU.OAMAddr*2 | (PPU.OAMFlip&1)); -#endif - if(!PPU.OAMPriorityRotation || !(PPU.OAMFlip&PPU.OAMAddr&1)){ -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "normal FirstSprite = %02x\n", PPU.FirstSprite); -#endif - /* 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]>=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(LineOBJ[Y]>=32){ - GFX.OBJLines[Y].RTOFlags|=0x40; -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S); -#endif - 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 = 0; Y < SNES_HEIGHT_EXTENDED; Y++) { - if (LineOBJ[Y] < 32) // Add the sentinel - GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = -1; - } - 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 (!AnyOBJOnLine[Y]) { - memset(OBJOnLine[Y], 0, 128); - AnyOBJOnLine[Y] = TRUE; - } - 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=32){ - GFX.OBJLines[Y].RTOFlags|=0x40; - #ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S); - #endif - 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; - } - } - -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) { - fprintf(stderr, "Sprites per line:\n"); - for(int xxx=0; xxx=0; j++){ - fprintf(stderr, " %02x.%d", GFX.OBJLines[xxx].OBJ[j].Sprite, GFX.OBJLines[xxx].OBJ[j].Line); - } - fprintf(stderr, "\n"); - } - - fprintf(stderr, "Exiting SetupObj()\n"); - } -#endif - - IPPU.OBJChanged = FALSE; -} - -static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0) -{ -#ifdef ACCUMULATE_JOYPAD -/* - * This call allows NDSSFC to synchronise the DS controller more often. - * If porting a later version of Snes9x into NDSSFC, it is essential to - * preserve it. - */ - NDSSFCAccumulateJoypad (); -#endif -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "Entering DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY); -#endif - CHECK_SOUND(); - - BG.BitShift = 4; - BG.TileShift = 5; - BG.TileAddress = PPU.OBJNameBase; - BG.StartPalette = 128; - BG.PaletteShift = 4; - BG.PaletteMask = 7; - BG.Buffer = IPPU.TileCache [TILE_4BIT]; - BG.Buffered = IPPU.TileCached [TILE_4BIT]; - BG.NameSelect = PPU.OBJNameSelect; - BG.DirectColourMode = FALSE; - - GFX.PixSize = 1; - - struct { - uint16 Pos; - bool8 Value; - } Windows[7]; - int clipcount = GFX.pCurrentClip->Count [4]; - if (!clipcount){ - Windows[0].Pos=0; - Windows[0].Value=TRUE; - Windows[1].Pos=256; - Windows[1].Value=FALSE; - Windows[2].Pos=1000; - Windows[2].Value=FALSE; - } else { - Windows[0].Pos=1000; - Windows[0].Value=FALSE; - for(int clip=0, i=1; clipRight[clip][4]<=GFX.pCurrentClip->Left[clip][4]) continue; - int j; - for(j=0; jLeft[clip][4]; j++); - if(jLeft[clip][4]){ - Windows[j].Value = TRUE; - } else { - // memmove required: Overlapping addresses [Neb] - if(jLeft[clip][4]; - Windows[j].Value = TRUE; - i++; - } - for(j=0; jRight[clip][4]; j++); - if(j>=i || Windows[j].Pos!=GFX.pCurrentClip->Right[clip][4]){ - // memmove required: Overlapping addresses [Neb] - if(jRight[clip][4]; - Windows[j].Value = FALSE; - i++; - } - } - } - -#ifdef MK_DEBUG_RTO -if(Settings.BGLayering) { - fprintf(stderr, "Windows:\n"); - for(int xxx=0; xxx<6; xxx++){ fprintf(stderr, "%d: %d = %d\n", xxx, Windows[xxx].Pos, Windows[xxx].Value); } -} -#endif - - if (Settings.SupportHiRes) - { - if (PPU.BGMode == 5 || PPU.BGMode == 6) - { - // Bah, OnMain is never used except to determine if calling - // SelectTileRenderer is necessary. So let's hack it to false here - // to stop SelectTileRenderer from being called when it causes - // problems. - OnMain = FALSE; - GFX.PixSize = 2; - if (IPPU.DoubleHeightPixels) - { - DrawTilePtr = DrawTile16x2x2; - DrawClippedTilePtr = DrawClippedTile16x2x2; - } - else - { - DrawTilePtr = DrawTile16x2; - DrawClippedTilePtr = DrawClippedTile16x2; - } - } - else - { - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - } - } - else // if (!Settings.SupportHiRes) - { - if (PPU.BGMode == 5 || PPU.BGMode == 6) - { - // Bah, OnMain is never used except to determine if calling - // SelectTileRenderer is necessary. So let's hack it to false here - // to stop SelectTileRenderer from being called when it causes - // problems. - OnMain = FALSE; - } - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - } - GFX.Z1 = D + 2; - - for(uint32 Y=GFX.StartY, Offset=Y*GFX.PPL; Y<=GFX.EndY; Y++, Offset+=GFX.PPL){ -#ifdef MK_DEBUG_RTO - bool8 Flag=0; -#endif - int I = 0; -#ifdef MK_DISABLE_TIME_OVER - int tiles=0; -#else - int tiles=GFX.OBJLines[Y].Tiles; -#endif - 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){ -#ifdef MK_DEBUG_RTO -if(Settings.BGLayering) { - if(!Flag){ Flag=1; fprintf(stderr, "Line %d:", Y); } - fprintf(stderr, " [%02x]", S); -} -#endif - continue; - } - -#ifdef MK_DEBUG_RTO -if(Settings.BGLayering) { - if(!Flag){ Flag=1; fprintf(stderr, "Line %d:", Y); } - fprintf(stderr, " %02x", S); -} -#endif - - if (OnMain && SUB_OR_ADD(4)) - { - SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4); - } - - 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; - int TileInc = 1; - - if (PPU.OBJ[S].HFlip) - { - TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; - BaseTile |= H_FLIP; - TileInc = -1; - } - - GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; - - bool8 WinStat=TRUE; - int WinIdx=0, NextPos=-1000; - int X=PPU.OBJ[S].HPos; if(X==-256) X=256; - for(int t=tiles, O=Offset+X*GFX.PixSize; X<=256 && X=NextPos){ - for(; WinIdx<7 && Windows[WinIdx].Pos<=X; WinIdx++); - if(WinIdx==0) WinStat=FALSE; - else WinStat=Windows[WinIdx-1].Value; - NextPos=(WinIdx<7)?Windows[WinIdx].Pos:1000; - } - - if(X+8X+8) NextPos=X+8; - } - } - } - } -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) if(Flag) fprintf(stderr, "\n"); -#endif - } -#ifdef MK_DEBUG_RTO - if(Settings.BGLayering) fprintf(stderr, "Exiting DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY); -#endif -} - -static void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint8 depths [2] = {Z1, Z2}; - - if (BGMode == 0) - BG.StartPalette = bg << 5; - else - BG.StartPalette = 0; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(((uint8*)SC1-Memory.VRAM)>=0x10000) - SC1-=0x08000; - - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - uint32 Lines; - uint32 OffsetMask; - uint32 OffsetShift; - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - int m5 = (BGMode == 5 || BGMode == 6) ? 1 : 0; - - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) - { - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - uint32 MosaicOffset = Y % PPU.Mosaic; - - for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - uint32 MosaicLine = VOffset + Y - MosaicOffset; - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY + 1 - Y; - uint32 VirtAlign = (MosaicLine & 7) << 3; - - uint16 *b1; - uint16 *b2; - - uint32 ScreenLine = MosaicLine >> OffsetShift; - uint32 Rem16 = MosaicLine & 15; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - uint16 *t; - uint32 Left = 0; - uint32 Right = 256 << m5; - - HOffset <<= m5; - - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; - uint32 HPos = HOffset; - uint32 PixWidth = (PPU.Mosaic << m5); - - - if (!ClipCount) - ClipCount = 1; - - for (uint32 clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [bg]) - { - Left = GFX.pCurrentClip->Left [clip][bg] << m5; - Right = GFX.pCurrentClip->Right [clip][bg] << m5; - - uint32 r = Left % (PPU.Mosaic << m5); - HPos = HOffset + Left; - PixWidth = (PPU.Mosaic << m5) - r; - } - uint32 s = Y * GFX.PPL + Left * GFX.PixSize; - for (uint32 x = Left; x < Right; x += PixWidth, - s += (IPPU.HalfWidthPixels ? PixWidth >> 1 : PixWidth) * GFX.PixSize, - HPos += PixWidth, PixWidth = (PPU.Mosaic << m5)) - { - uint32 Quot = (HPos & OffsetMask) >> 3; - - if (x + PixWidth >= Right) - PixWidth = Right - x; - - if (BG.TileSize == 8 && !m5) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - Tile = READ_2BYTES (t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - // Draw tile... - if (BG.TileSize != 8) - { - if (Tile & H_FLIP) - { - // Horizontal flip, but what about vertical flip ? - if (Tile & V_FLIP) - { - // Both horzontal & vertical flip - if (Rem16 < 8) - { - (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - else - { - // Horizontal flip only - if (Rem16 > 7) - { - (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } - else - { - // No horizontal flip, but is there a vertical flip ? - if (Tile & V_FLIP) - { - // Vertical flip only - if (Rem16 < 8) - { - (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - else - { - // Normal unflipped - if (Rem16 > 7) - { - (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } - } - else - (*DrawLargePixelPtr) (Tile + (Quot & 1) * m5, s, HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } -} - -static void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint16 *BPS0; - uint16 *BPS1; - uint16 *BPS2; - uint16 *BPS3; - uint32 Width; - int VOffsetOffset = BGMode == 4 ? 0 : 32; - uint8 depths [2] = {Z1, Z2}; - - BG.StartPalette = 0; - - BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; - - if (PPU.BG[2].SCSize & 1) - BPS1 = BPS0 + 1024; - else - BPS1 = BPS0; - - if (PPU.BG[2].SCSize & 2) - BPS2 = BPS1 + 1024; - else - BPS2 = BPS0; - - if (PPU.BG[2].SCSize & 1) - BPS3 = BPS2 + 1024; - else - BPS3 = BPS2; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(((uint8*)SC1-Memory.VRAM)>=0x10000) - SC1-=0x08000; - - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - - static const int Lines = 1; - int OffsetMask; - int OffsetShift; - int OffsetEnableMask = 1 << (bg + 13); - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) - { - uint32 VOff = LineData [Y].BG[2].VOffset - 1; -// uint32 VOff = LineData [Y].BG[2].VOffset; - uint32 HOff = LineData [Y].BG[2].HOffset; - - int VirtAlign; - int ScreenLine = VOff >> 3; - int t1; - int t2; - uint16 *s0; - uint16 *s1; - uint16 *s2; - - if (ScreenLine & 0x20) - s1 = BPS2, s2 = BPS3; - else - s1 = BPS0, s2 = BPS1; - - s1 += (ScreenLine & 0x1f) << 5; - s2 += (ScreenLine & 0x1f) << 5; - - if(BGMode != 4) - { - if((ScreenLine & 0x1f) == 0x1f) - { - if(ScreenLine & 0x20) - VOffsetOffset = BPS0 - BPS2 - 0x1f*32; - else - VOffsetOffset = BPS2 - BPS0 - 0x1f*32; - } - else - { - VOffsetOffset = 32; - } - } - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - - for (int clip = 0; clip < clipcount; clip++) - { - uint32 Left; - uint32 Right; - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 256; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) - continue; - } - - uint32 VOffset; - uint32 HOffset; - //added: - uint32 LineHOffset=LineData [Y].BG[bg].HOffset; - - uint32 Offset; - uint32 HPos; - uint32 Quot; - uint32 Count; - uint16 *t; - uint32 Quot2; - uint32 VCellOffset; - uint32 HCellOffset; - uint16 *b1; - uint16 *b2; - uint32 TotalCount = 0; - uint32 MaxCount = 8; - - uint32 s = Left * GFX.PixSize + Y * GFX.PPL; - bool8 left_hand_edge = (Left == 0); - Width = Right - Left; - - if (Left & 7) - MaxCount = 8 - (Left & 7); - - while (Left < Right) - { - if (left_hand_edge) - { - // The SNES offset-per-tile background mode has a - // hardware limitation that the offsets cannot be set - // for the tile at the left-hand edge of the screen. - VOffset = LineData [Y].BG[bg].VOffset; - - //MKendora; use temp var to reduce memory accesses - //HOffset = LineData [Y].BG[bg].HOffset; - - HOffset = LineHOffset; - //End MK - - left_hand_edge = FALSE; - } - else - - { - // All subsequent offset tile data is shifted left by one, - // hence the - 1 below. - - Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3; - - if (Quot2 > 31) - s0 = s2 + (Quot2 & 0x1f); - else - s0 = s1 + Quot2; - - HCellOffset = READ_2BYTES (s0); - - if (BGMode == 4) - { - VOffset = LineData [Y].BG[bg].VOffset; - - //MKendora another mem access hack - //HOffset = LineData [Y].BG[bg].HOffset; - HOffset=LineHOffset; - //end MK - - if ((HCellOffset & OffsetEnableMask)) - { - if (HCellOffset & 0x8000) - VOffset = HCellOffset + 1; - else - HOffset = HCellOffset; - } - } - else - { - VCellOffset = READ_2BYTES (s0 + VOffsetOffset); - if ((VCellOffset & OffsetEnableMask)) - VOffset = VCellOffset + 1; - else - VOffset = LineData [Y].BG[bg].VOffset; - - //MKendora Strike Gunner fix - if ((HCellOffset & OffsetEnableMask)) - { - //HOffset= HCellOffset; - - HOffset = (HCellOffset & ~7)|(LineHOffset&7); - //HOffset |= LineData [Y].BG[bg].HOffset&7; - } - else - HOffset=LineHOffset; - //HOffset = LineData [Y].BG[bg].HOffset - - //Settings.StrikeGunnerOffsetHack; - //HOffset &= (~7); - //end MK - } - } - VirtAlign = ((Y + VOffset) & 7) << 3; - ScreenLine = (VOffset + Y) >> OffsetShift; - - if (((VOffset + Y) & 15) > 7) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - HPos = (HOffset + Left) & OffsetMask; - - Quot = HPos >> 3; - - if (BG.TileSize == 8) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - if (MaxCount + TotalCount > Width) - MaxCount = Width - TotalCount; - - Offset = HPos & 7; - - //Count =1; - Count = 8 - Offset; - if (Count > MaxCount) - Count = MaxCount; - - s -= (IPPU.HalfWidthPixels ? Offset >> 1 : Offset) * GFX.PixSize; - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize == 8) - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - - Left += Count; - TotalCount += Count; - s += (IPPU.HalfWidthPixels ? (Offset + Count) >> 1 : (Offset + Count)) * GFX.PixSize; - MaxCount = 8; - } - } - } -} - -static void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2) -{ - CHECK_SOUND(); - - if(IPPU.Interlace) - { - GFX.Pitch = GFX.RealPitch; - GFX.PPL = GFX.PPLx2 >> 1; - } - GFX.PixSize = 1; - uint8 depths [2] = {Z1, Z2}; - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 Width; - - BG.StartPalette = 0; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if ((PPU.BG[bg].SCSize & 1)) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if((SC1-(unsigned short*)Memory.VRAM)>0x10000) - SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000]; - - if ((PPU.BG[bg].SCSize & 2)) - SC2 = SC1 + 1024; - else SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - - if ((PPU.BG[bg].SCSize & 1)) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - - - int Lines; - int VOffsetMask; - int VOffsetShift; - - if (BG.TileSize == 16) - { - VOffsetMask = 0x3ff; - VOffsetShift = 4; - } - else - { - VOffsetMask = 0x1ff; - VOffsetShift = 3; - } - int endy = IPPU.Interlace ? 1 + (GFX.EndY << 1) : GFX.EndY; - - for (int Y = IPPU.Interlace ? GFX.StartY << 1 : GFX.StartY; Y <= endy; Y += Lines) - { - int y = IPPU.Interlace ? (Y >> 1) : Y; - uint32 VOffset = LineData [y].BG[bg].VOffset; - uint32 HOffset = LineData [y].BG[bg].HOffset; - int VirtAlign = (Y + VOffset) & 7; - - for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || - (HOffset != LineData [y + Lines].BG[bg].HOffset)) - break; - - HOffset <<= 1; - if (Y + Lines > endy) - Lines = endy + 1 - Y; - VirtAlign <<= 3; - - int ScreenLine = (VOffset + Y) >> VOffsetShift; - int t1; - int t2; - if (((VOffset + Y) & 15) > 7) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - for (int clip = 0; clip < clipcount; clip++) - { - int Left; - int Right; - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 512; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg] * 2; - Right = GFX.pCurrentClip->Right [clip][bg] * 2; - - if (Right <= Left) - continue; - } - - uint32 s = (IPPU.HalfWidthPixels ? Left >> 1 : Left) * GFX.PixSize + Y * GFX.PPL; - uint32 HPos = (HOffset + Left * GFX.PixSize) & 0x3ff; - - uint32 Quot = HPos >> 3; - uint32 Count = 0; - - uint16 *t; - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - - Width = Right - Left; - // Left hand edge clipped tile - if (HPos & 7) - { - int Offset = (HPos & 7); - Count = 8 - Offset; - if (Count > Width) - Count = Width; - s -= (IPPU.HalfWidthPixels ? Offset >> 1 : Offset); - Tile = READ_2BYTES (t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - - t += Quot & 1; - if (Quot == 63) - t = b2; - else if (Quot == 127) - t = b1; - Quot++; - s += (IPPU.HalfWidthPixels ? 4 : 8); - } - - // Middle, unclipped tiles - Count = Width - Count; - int Middle = Count >> 3; - Count &= 7; - for (int C = Middle; C > 0; s += (IPPU.HalfWidthPixels ? 4 : 8), Quot++, C--) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResTilePtr) (Tile + (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1), - s, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1), - s, VirtAlign, Lines); - } - } - - t += Quot & 1; - if (Quot == 63) - t = b2; - else - if (Quot == 127) - t = b1; - } - - // Right-hand edge clipped tiles - if (Count) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - } - } - } - GFX.Pitch = IPPU.DoubleHeightPixels ? GFX.RealPitch * 2 : GFX.RealPitch; - GFX.PPL = IPPU.DoubleHeightPixels ? GFX.PPLx2 : (GFX.PPLx2 >> 1); - -} - -static void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -#ifdef ACCUMULATE_JOYPAD -/* - * This call allows NDSSFC to synchronise the DS controller more often. - * If porting a later version of Snes9x into NDSSFC, it is essential to - * preserve it. - */ - NDSSFCAccumulateJoypad (); -#endif - GFX.PixSize = 1; - - BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; - BG.BitShift = BitShifts[BGMode][bg]; - BG.TileShift = TileShifts[BGMode][bg]; - BG.TileAddress = PPU.BG[bg].NameBase << 1; - BG.NameSelect = 0; - BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]]; - BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; - BG.PaletteShift = PaletteShifts[BGMode][bg]; - BG.PaletteMask = PaletteMasks[BGMode][bg]; - BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && - (GFX.r2130 & 1); - - if (PPU.BGMosaic [bg] && PPU.Mosaic > 1) - { - DrawBackgroundMosaic (BGMode, bg, Z1, Z2); - return; - - } - switch (BGMode) - { - case 2: - case 4: // Used by Puzzle Bobble - DrawBackgroundOffset (BGMode, bg, Z1, Z2); - return; - - case 5: - case 6: // XXX: is also offset per tile. -// if (Settings.SupportHiRes) -// { - if (!Settings.SupportHiRes) - SelectTileRenderer(TRUE /* normal */); - DrawBackgroundMode5 (BGMode, bg, Z1, Z2); - return; -// } - break; - } - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 Width; - uint8 depths [2] = {Z1, Z2}; - - if (BGMode == 0) - BG.StartPalette = bg << 5; - else BG.StartPalette = 0; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(SC1>=(unsigned short*)(Memory.VRAM+0x10000)) - SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000]; - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - - - int Lines; - int OffsetMask; - int OffsetShift; - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) - { - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - int VirtAlign = (Y + VOffset) & 7; - - for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY + 1 - Y; - - VirtAlign <<= 3; - - uint32 ScreenLine = (VOffset + Y) >> OffsetShift; - uint32 t1; - uint32 t2; - if (((VOffset + Y) & 15) > 7) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - for (int clip = 0; clip < clipcount; clip++) - { - uint32 Left; - uint32 Right; - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 256; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) - continue; - } - - uint32 s = Left * GFX.PixSize + Y * GFX.PPL; - uint32 HPos = (HOffset + Left) & OffsetMask; - - uint32 Quot = HPos >> 3; - uint32 Count = 0; - - uint16 *t; - if (BG.TileSize == 8) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - Width = Right - Left; - // Left hand edge clipped tile - if (HPos & 7) - { - uint32 Offset = (HPos & 7); - Count = 8 - Offset; - if (Count > Width) - Count = Width; - s -= Offset * GFX.PixSize; - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize == 8) - { - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, - Lines); - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s, - Offset, Count, VirtAlign, Lines); - } - } - - if (BG.TileSize == 8) - { - t++; - if (Quot == 31) - t = b2; - else if (Quot == 63) - t = b1; - } - else - { - t += Quot & 1; - if (Quot == 63) - t = b2; - else if (Quot == 127) - t = b1; - } - Quot++; - s += (IPPU.HalfWidthPixels ? 4 : 8) * GFX.PixSize; - } - - // Middle, unclipped tiles - Count = Width - Count; - int Middle = Count >> 3; - Count &= 7; - for (int C = Middle; C > 0; s += (IPPU.HalfWidthPixels ? 4 : 8) * GFX.PixSize, Quot++, C--) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize != 8) - { - if (Tile & H_FLIP) - { - // Horizontal flip, but what about vertical flip ? - if (Tile & V_FLIP) - { - // Both horzontal & vertical flip - (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s, - VirtAlign, Lines); - } - else - { - // Horizontal flip only - (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s, - VirtAlign, Lines); - } - } - else - { - // No horizontal flip, but is there a vertical flip ? - if (Tile & V_FLIP) - { - // Vertical flip only - (*DrawTilePtr) (Tile + t2 + (Quot & 1), s, - VirtAlign, Lines); - } - else - { - // Normal unflipped - (*DrawTilePtr) (Tile + t1 + (Quot & 1), s, - VirtAlign, Lines); - } - } - } - else - { - (*DrawTilePtr) (Tile, s, VirtAlign, Lines); - } - - if (BG.TileSize == 8) - { - t++; - if (Quot == 31) - t = b2; - else - if (Quot == 63) - t = b1; - } - else - { - t += Quot & 1; - if (Quot == 63) - t = b2; - else - if (Quot == 127) - t = b1; - } - } - // Right-hand edge clipped tiles - if (Count) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize == 8) - (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign, - Lines); - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, 0, - Count, VirtAlign, Lines); - } - else if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, - Lines); - } - else - { - // H flip only - (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, - Lines); - } - } - else - { - // V flip only - (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), - s, 0, Count, VirtAlign, - Lines); - } - } - } - } - } -} - -#define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \ - uint16 *ScreenColors; \ - CHECK_SOUND(); \ -\ - uint8 *VRAM1 = Memory.VRAM + 1; \ - if (GFX.r2130 & 1) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps (); \ - ScreenColors = DirectColourMaps [0]; \ - } \ - else \ - ScreenColors = IPPU.ScreenColors; \ -\ - int aa, cc; \ - int dir; \ - int startx, endx; \ - uint32 Left = 0; \ - uint32 Right = 256; \ - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ -\ - if (!ClipCount) \ - ClipCount = 1; \ -\ - Screen += GFX.StartY * GFX.Pitch; \ - uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \ - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ -\ - for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \ - { \ - int yy; \ -\ - int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ - int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ -\ - int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ - int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ -\ - if (PPU.Mode7VFlip) \ - yy = 255 - (int) Line; \ - else \ - yy = Line; \ -\ - yy += CLIP_10_BIT_SIGNED(VOffset - CentreY); \ -\ - int BB = l->MatrixB * yy + (CentreX << 8); \ - int DD = l->MatrixD * yy + (CentreY << 8); \ -\ - for (uint32 clip = 0; clip < ClipCount; clip++) \ - { \ - if (GFX.pCurrentClip->Count [bg]) \ - { \ - Left = GFX.pCurrentClip->Left [clip][bg]; \ - Right = GFX.pCurrentClip->Right [clip][bg]; \ - if (Right <= Left) \ - continue; \ - } \ - TYPE *p = (TYPE *) Screen + Left; \ - uint8 *d = Depth + Left; \ -\ - if (PPU.Mode7HFlip) \ - { \ - startx = Right - 1; \ - endx = Left - 1; \ - dir = -1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = Left; \ - endx = Right; \ - dir = 1; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ -\ - int xx = startx + CLIP_10_BIT_SIGNED(HOffset - CentreX); \ - int AA = l->MatrixA * xx; \ - int CC = l->MatrixC * xx; \ -\ - if (!PPU.Mode7Repeat) \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - int X = ((AA + BB) >> 8) & 0x3ff; \ - int Y = ((CC + DD) >> 8) & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - *p = (FUNC); \ - *d = GFX.Z1; \ - } \ - } \ - } \ - else \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - int X = ((AA + BB) >> 8); \ - int Y = ((CC + DD) >> 8); \ -\ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - *p = (FUNC); \ - *d = GFX.Z1; \ - } \ - } \ - else \ - { \ - if (PPU.Mode7Repeat == 3) \ - { \ - X = (x + HOffset) & 7; \ - Y = (yy + CentreY) & 7; \ - uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - *p = (FUNC); \ - *d = GFX.Z1; \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -static void DrawBGMode7Background (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (uint8, (uint8) (b & GFX.Mode7Mask)) -} - -static void DrawBGMode7Background16 (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (uint16, ScreenColors [b & GFX.Mode7Mask]); -} - -static void DrawBGMode7Background16Add (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD (ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_ADD (ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); -} - -static void DrawBGMode7Background16Add1_2 (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD1_2 (ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_ADD (ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); -} - -static void DrawBGMode7Background16Sub (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB (ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_SUB (ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); -} - -static void DrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB1_2 (ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_SUB (ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); -} - -#define RENDER_BACKGROUND_MODE7_i(TYPE,FUNC,COLORFUNC) \ - uint16 *ScreenColors; \ - CHECK_SOUND(); \ -\ - uint8 *VRAM1 = Memory.VRAM + 1; \ - if (GFX.r2130 & 1) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps (); \ - ScreenColors = DirectColourMaps [0]; \ - } \ - else \ - ScreenColors = IPPU.ScreenColors; \ - \ - int aa, cc; \ - int dir; \ - int startx, endx; \ - uint32 Left = 0; \ - uint32 Right = 256; \ - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ - \ - if (!ClipCount) \ - ClipCount = 1; \ - \ - Screen += GFX.StartY * GFX.Pitch; \ - uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \ - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ - bool8 allowSimpleCase = FALSE; \ - if (!l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100) \ - && !LineMatrixData[GFX.EndY].MatrixB && !LineMatrixData[GFX.EndY].MatrixC \ - && (LineMatrixData[GFX.EndY].MatrixA == 0x0100) && (LineMatrixData[GFX.EndY].MatrixD == 0x0100) \ - ) \ - allowSimpleCase = TRUE; \ - \ - for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \ - { \ - int yy; \ - \ - int HOffset = ((int) LineData [Line].BG[0].HOffset << M7) >> M7; \ - int VOffset = ((int) LineData [Line].BG[0].VOffset << M7) >> M7; \ - \ - int CentreX = ((int) l->CentreX << M7) >> M7; \ - int CentreY = ((int) l->CentreY << M7) >> M7; \ - \ - if (PPU.Mode7VFlip) \ - yy = 255 - (int) Line; \ - else \ - yy = Line; \ - \ - \ - yy += CLIP_10_BIT_SIGNED(VOffset - CentreY); \ - bool8 simpleCase = FALSE; \ - int BB; \ - int DD; \ - /* Make a special case for the identity matrix, since it's a common case and */ \ - /* can be done much more quickly without special effects */ \ - if (allowSimpleCase && !l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100)) \ - { \ - BB = CentreX << 8; \ - DD = (yy + CentreY) << 8; \ - simpleCase = TRUE; \ - } \ - else \ - { \ - BB = l->MatrixB * yy + (CentreX << 8); \ - DD = l->MatrixD * yy + (CentreY << 8); \ - } \ - \ - for (uint32 clip = 0; clip < ClipCount; clip++) \ - { \ - if (GFX.pCurrentClip->Count [bg]) \ - { \ - Left = GFX.pCurrentClip->Left [clip][bg]; \ - Right = GFX.pCurrentClip->Right [clip][bg]; \ - if (Right <= Left) \ - continue; \ - } \ - TYPE *p = (TYPE *) Screen + Left; \ - uint8 *d = Depth + Left; \ - \ - if (PPU.Mode7HFlip) \ - { \ - startx = Right - 1; \ - endx = Left - 1; \ - dir = -1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = Left; \ - endx = Right; \ - dir = 1; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ - int xx; \ - \ - xx = startx + CLIP_10_BIT_SIGNED(HOffset - CentreX); \ - int AA, CC = 0; \ - if (simpleCase) \ - { \ - AA = xx << 8; \ - } \ - else \ - { \ - AA = l->MatrixA * xx; \ - CC = l->MatrixC * xx; \ - } \ - if (simpleCase) \ - { \ - if (!PPU.Mode7Repeat) \ - { \ - int x = startx; \ - do \ - { \ - int X = ((AA + BB) >> 8) & 0x3ff; \ - int Y = (DD >> 8) & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - TYPE theColor = COLORFUNC; \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - AA += aa, p++, d++; \ - x += dir; \ - } while (x != endx); \ - } \ - else \ - { \ - int x = startx; \ - do { \ - int X = (AA + BB) >> 8; \ - int Y = DD >> 8; \ -\ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - TYPE theColor = COLORFUNC; \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - } \ - else if (PPU.Mode7Repeat == 3) \ - { \ - X = (x + HOffset) & 7; \ - Y = (yy + CentreY) & 7; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - TYPE theColor = COLORFUNC; \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - } \ - AA += aa; p++; d++; \ - x += dir; \ - } while (x != endx); \ - } \ - } \ - else if (!PPU.Mode7Repeat) \ - { \ - /* The bilinear interpolator: get the colors at the four points surrounding */ \ - /* the location of one point in the _sampled_ image, and weight them according */ \ - /* to their (city block) distance. It's very smooth, but blurry with "close up" */ \ - /* points. */ \ - \ - /* 460 (slightly less than 2 source pixels per displayed pixel) is an educated */ \ - /* guess for where bilinear filtering will become a poor method for averaging. */ \ - /* (When reducing the image, the weighting used by a bilinear filter becomes */ \ - /* arbitrary, and a simple mean is a better way to represent the source image.) */ \ - /* You can think of this as a kind of mipmapping. */ \ - if ((aa < 460 && aa > -460) && (cc < 460 && cc > -460)) \ - {\ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - uint32 xPos = AA + BB; \ - uint32 xPix = xPos >> 8; \ - uint32 yPos = CC + DD; \ - uint32 yPix = yPos >> 8; \ - uint32 X = xPix & 0x3ff; \ - uint32 Y = yPix & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \ - uint32 X10 = (xPix + dir) & 0x3ff; \ - uint32 Y01 = (yPix + (PPU.Mode7VFlip?-1:1)) & 0x3ff; \ - uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ - uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ - uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 p1 = COLORFUNC; \ - p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \ - b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \ - uint32 p2 = COLORFUNC; \ - p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \ - b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \ - uint32 p4 = COLORFUNC; \ - p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \ - b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \ - uint32 p3 = COLORFUNC; \ - p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \ - /* Xdel, Ydel: position (in 1/32nds) between the points */ \ - uint32 Xdel = (xPos >> 3) & 0x1F; \ - uint32 Ydel = (yPos >> 3) & 0x1F; \ - uint32 XY = (Xdel*Ydel) >> 5; \ - uint32 area1 = 0x20 + XY - Xdel - Ydel; \ - uint32 area2 = Xdel - XY; \ - uint32 area3 = Ydel - XY; \ - uint32 area4 = XY; \ - if(PPU.Mode7HFlip){ \ - uint32 tmp=area1; area1=area2; area2=tmp; \ - tmp=area3; area3=area4; area4=tmp; \ - } \ - if(PPU.Mode7VFlip){ \ - uint32 tmp=area1; area1=area3; area3=tmp; \ - tmp=area2; area2=area4; area4=tmp; \ - } \ - uint32 tempColor = ((area1 * p1) + \ - (area2 * p2) + \ - (area3 * p3) + \ - (area4 * p4)) >> 5; \ - TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - } \ - } \ - else \ - /* The oversampling method: get the colors at four corners of a square */ \ - /* in the _displayed_ image, and average them. It's sharp and clean, but */ \ - /* gives the usual huge pixels when the source image gets "close." */ \ - { \ - /* Find the dimensions of the square in the source image whose corners will be examined. */ \ - uint32 aaDelX = aa >> 1; \ - uint32 ccDelX = cc >> 1; \ - uint32 bbDelY = l->MatrixB >> 1; \ - uint32 ddDelY = l->MatrixD >> 1; \ - /* Offset the location within the source image so that the four sampled points */ \ - /* center around where the single point would otherwise have been drawn. */ \ - BB -= (bbDelY >> 1); \ - DD -= (ddDelY >> 1); \ - AA -= (aaDelX >> 1); \ - CC -= (ccDelX >> 1); \ - uint32 BB10 = BB + aaDelX; \ - uint32 BB01 = BB + bbDelY; \ - uint32 BB11 = BB + aaDelX + bbDelY; \ - uint32 DD10 = DD + ccDelX; \ - uint32 DD01 = DD + ddDelY; \ - uint32 DD11 = DD + ccDelX + ddDelY; \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - uint32 X = ((AA + BB) >> 8) & 0x3ff; \ - uint32 Y = ((CC + DD) >> 8) & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - /* X, Y, X10, Y10, etc. are the coordinates of the four pixels within the */ \ - /* source image that we're going to examine. */ \ - uint32 X10 = ((AA + BB10) >> 8) & 0x3ff; \ - uint32 Y10 = ((CC + DD10) >> 8) & 0x3ff; \ - uint32 X01 = ((AA + BB01) >> 8) & 0x3ff; \ - uint32 Y01 = ((CC + DD01) >> 8) & 0x3ff; \ - uint32 X11 = ((AA + BB11) >> 8) & 0x3ff; \ - uint32 Y11 = ((CC + DD11) >> 8) & 0x3ff; \ - uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y10 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ - uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X01 >> 2) & ~1)] << 7); \ - uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y11 & ~7) << 5) + ((X11 >> 2) & ~1)] << 7); \ - TYPE p1 = COLORFUNC; \ - b = *(TileData10 + ((Y10 & 7) << 4) + ((X10 & 7) << 1)); \ - TYPE p2 = COLORFUNC; \ - b = *(TileData01 + ((Y01 & 7) << 4) + ((X01 & 7) << 1)); \ - TYPE p3 = COLORFUNC; \ - b = *(TileData11 + ((Y11 & 7) << 4) + ((X11 & 7) << 1)); \ - TYPE p4 = COLORFUNC; \ - TYPE theColor = Q_INTERPOLATE(p1, p2, p3, p4); \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - } \ - } \ - } \ - else \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - uint32 xPos = AA + BB; \ - uint32 xPix = xPos >> 8; \ - uint32 yPos = CC + DD; \ - uint32 yPix = yPos >> 8; \ - uint32 X = xPix; \ - uint32 Y = yPix; \ - \ -\ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \ - uint32 X10 = (xPix + dir) & 0x3ff; \ - uint32 Y01 = (yPix + dir) & 0x3ff; \ - uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ - uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \ - uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 p1 = COLORFUNC; \ - p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \ - b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \ - uint32 p2 = COLORFUNC; \ - p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \ - b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \ - uint32 p4 = COLORFUNC; \ - p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \ - b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \ - uint32 p3 = COLORFUNC; \ - p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \ - /* Xdel, Ydel: position (in 1/32nds) between the points */ \ - uint32 Xdel = (xPos >> 3) & 0x1F; \ - uint32 Ydel = (yPos >> 3) & 0x1F; \ - uint32 XY = (Xdel*Ydel) >> 5; \ - uint32 area1 = 0x20 + XY - Xdel - Ydel; \ - uint32 area2 = Xdel - XY; \ - uint32 area3 = Ydel - XY; \ - uint32 area4 = XY; \ - uint32 tempColor = ((area1 * p1) + \ - (area2 * p2) + \ - (area3 * p3) + \ - (area4 * p4)) >> 5; \ - TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - } \ - else \ - { \ - if (PPU.Mode7Repeat == 3) \ - { \ - X = (x + HOffset) & 7; \ - Y = (yy + CentreY) & 7; \ - uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \ - if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \ - { \ - TYPE theColor = COLORFUNC; \ - *p = (FUNC) | ALPHA_BITS_MASK; \ - *d = GFX.Z1; \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -STATIC uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D) -{ - register uint32 x = ((A >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + - ((B >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + - ((C >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + - ((D >> 2) & HIGH_BITS_SHIFTED_TWO_MASK); - register uint32 y = (A & TWO_LOW_BITS_MASK) + - (B & TWO_LOW_BITS_MASK) + - (C & TWO_LOW_BITS_MASK) + - (D & TWO_LOW_BITS_MASK); - y = (y>>2) & TWO_LOW_BITS_MASK; - return x+y; -} - -static void DrawBGMode7Background16_i (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7_i (uint16, theColor, (ScreenColors[b & GFX.Mode7Mask])); -} - -static void DrawBGMode7Background16Add_i (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - (COLOR_ADD (theColor, - p [GFX.Delta])) : - (COLOR_ADD (theColor, - GFX.FixedColour))) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); -} - -static void DrawBGMode7Background16Add1_2_i (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD1_2 (theColor, - p [GFX.Delta]) : - COLOR_ADD (theColor, - GFX.FixedColour)) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); -} - -static void DrawBGMode7Background16Sub_i (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB (theColor, - p [GFX.Delta]) : - COLOR_SUB (theColor, - GFX.FixedColour)) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); -} - -static void DrawBGMode7Background16Sub1_2_i (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB1_2 (theColor, - p [GFX.Delta]) : - COLOR_SUB (theColor, - GFX.FixedColour)) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); -} - -#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); - -static void RenderScreen (uint8 *Screen, bool8 sub, bool8 force_no_add, uint8 D) -{ - bool8 BG0; - bool8 BG1; - bool8 BG2; - bool8 BG3; - bool8 OB; - - GFX.S = Screen; - - if (!sub) - { - GFX.pCurrentClip = &IPPU.Clip [0]; - BG0 = ON_MAIN (0); - BG1 = ON_MAIN (1); - BG2 = ON_MAIN (2); - BG3 = ON_MAIN (3); - OB = ON_MAIN (4); - } - else - { - GFX.pCurrentClip = &IPPU.Clip [1]; - BG0 = ON_SUB (0); - BG1 = ON_SUB (1); - BG2 = ON_SUB (2); - BG3 = ON_SUB (3); - OB = ON_SUB (4); - } - - sub |= force_no_add; - - switch (PPU.BGMode) { - case 0: - case 1: - if (OB) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - if (BG0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(0)); - DrawBackground (PPU.BGMode, 0, D + 10, D + 14); - } - if (BG1) - { - SelectTileRenderer (sub || !SUB_OR_ADD(1)); - DrawBackground (PPU.BGMode, 1, D + 9, D + 13); - } - if (BG2) - { - SelectTileRenderer (sub || !SUB_OR_ADD(2)); - DrawBackground (PPU.BGMode, 2, D + 3, - PPU.BG3Priority ? D + 17 : D + 6); - } - if (BG3 && PPU.BGMode == 0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(3)); - DrawBackground (PPU.BGMode, 3, D + 2, D + 5); - } - break; - case 2: - case 3: - case 4: - case 5: - case 6: - if (OB) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - if (BG0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(0)); - DrawBackground (PPU.BGMode, 0, D + 5, D + 13); - } - if (BG1 && PPU.BGMode != 6) - { - SelectTileRenderer (sub || !SUB_OR_ADD(1)); - DrawBackground (PPU.BGMode, 1, D + 2, D + 9); - } - break; - case 7: - if (OB) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1)) - { - int bg; - - if ((Memory.FillRAM [0x2133] & 0x40)&&BG1) - { - GFX.Mode7Mask = 0x7f; - GFX.Mode7PriorityMask = 0x80; - Mode7Depths [0] = (BG0?5:1) + D; - Mode7Depths [1] = 9 + D; - bg = 1; - } - else - { - GFX.Mode7Mask = 0xff; - GFX.Mode7PriorityMask = 0; - Mode7Depths [0] = 5 + D; - Mode7Depths [1] = 5 + D; - bg = 0; - } - if (sub || !SUB_OR_ADD(0)) - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16 (Screen, bg); - else - DrawBGMode7Background16_i (Screen, bg); - } - else - { - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Sub1_2 (Screen, bg); - else - DrawBGMode7Background16Sub1_2_i (Screen, bg); - } - else - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Sub (Screen, bg); - else - DrawBGMode7Background16Sub_i (Screen, bg); - } - } - else - { - if (GFX.r2131 & 0x40) - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Add1_2 (Screen, bg); - else - DrawBGMode7Background16Add1_2_i (Screen, bg); - } - else - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Add (Screen, bg); - else - DrawBGMode7Background16Add_i (Screen, bg); - } - } - } - } - break; - default: - break; - } -} - -#include "font.h" - -void DisplayChar (uint8 *Screen, uint8 c) -{ - int line = (((c & 0x7f) - 32) >> 4) * font_height; - int offset = (((c & 0x7f) - 32) & 15) * font_width; - int h, w; - uint16 *s = (uint16 *) Screen; - for (h = 0; h < font_height; h++, line++, - s += GFX.PPL - font_width) - { - for (w = 0; w < font_width; w++, s++) - { - uint8 p = font [line][offset + w]; - - if (p == '#') - { - /* - if(Memory.Hacked) - *s= BUILD_PIXEL(31,0,0); - else if(Memory.Iffy) - *s= BUILD_PIXEL(31,31,0); - else if(Memory.Iformat==1) - *s= BUILD_PIXEL(0,31,0); - else if(Memory.Iformat==2) - *s= BUILD_PIXEL(0,31,31); - else *s = 0xffff; - */ - *s=Settings.DisplayColor; - } - else - if (p == '.') - *s = BLACK; - } - } -} - -static void S9xDisplayFrameRate () -{ - uint8 *Screen = GFX.Screen + 2 + - (IPPU.RenderedScreenHeight - font_height - 1) * GFX.Pitch2; - char string [10]; - int len = 5; - - sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, - (int) Memory.ROMFramesPerSecond); - - int i; - for (i = 0; i < len; i++) - { - DisplayChar (Screen, string [i]); - Screen += (font_width - 1) * sizeof (uint16); - } -} - -static void S9xDisplayString (const char *string) -{ - uint8 *Screen = GFX.Screen + 2 + - (IPPU.RenderedScreenHeight - font_height * 5) * GFX.Pitch2; - int len = strlen (string); - int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); - int char_count = 0; - int i; - - for (i = 0; i < len; i++, char_count++) - { - if (char_count >= max_chars || string [i] < 32) - { - Screen -= (font_width - 1) * max_chars * sizeof (uint16); - Screen += font_height * GFX.Pitch; - if (Screen >= GFX.Screen + GFX.Pitch * IPPU.RenderedScreenHeight) - break; - char_count -= max_chars; - } - if (string [i] < 32) - continue; - DisplayChar (Screen, string [i]); - Screen += (font_width - 1) * sizeof (uint16); - } -} - -void S9xUpdateScreen () -{ - int32 x2 = 1; - - GFX.S = GFX.Screen; - GFX.r2131 = Memory.FillRAM [0x2131]; - GFX.r212c = Memory.FillRAM [0x212c]; - GFX.r212d = Memory.FillRAM [0x212d]; - GFX.r2130 = Memory.FillRAM [0x2130]; - -#ifdef JP_FIX - - GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 && - (GFX.r212c & 15) != (GFX.r212d & 15) && - (GFX.r2131 == 0x3f); - -#else - - GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 && - (GFX.r212c & 15) != (GFX.r212d & 15) && - (GFX.r2131 & 0x3f) == 0; - -#endif - - if (IPPU.OBJChanged) - S9xSetupOBJ (); - - if (PPU.RecomputeClipWindows) - { - ComputeClipWindows (); - PPU.RecomputeClipWindows = FALSE; - } - - GFX.StartY = IPPU.PreviousLine; - if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) - GFX.EndY = PPU.ScreenHeight - 1; - - // XXX: Check ForceBlank? Or anything else? - PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags; - - uint32 starty = GFX.StartY; - uint32 endy = GFX.EndY; - - if (Settings.SupportHiRes && - (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace || IPPU.DoubleHeightPixels)) - { - if (PPU.BGMode == 5 || PPU.BGMode == 6|| IPPU.Interlace) - { - IPPU.RenderedScreenWidth = 512; - x2 = 2; - } - - if (IPPU.DoubleHeightPixels) - { - starty = GFX.StartY * 2; - endy = GFX.EndY * 2 + 1; - } - - if ((PPU.BGMode == 5 || PPU.BGMode == 6) && !IPPU.DoubleWidthPixels) - { - // The game has switched from lo-res to hi-res mode part way down - // the screen. Scale any existing lo-res pixels on screen - for (register uint32 y = 0; y < starty; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255; - register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510; - - for (register int x = 255; x >= 0; x--, p--, q -= 2) - *q = *(q + 1) = *p; - } - IPPU.DoubleWidthPixels = TRUE; - IPPU.HalfWidthPixels = FALSE; - } - // BJ: And we have to change the height if Interlace gets set, - // too. - if (IPPU.Interlace && !IPPU.DoubleHeightPixels) - { - starty = GFX.StartY * 2; - endy = GFX.EndY * 2 + 1; - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - IPPU.DoubleHeightPixels = TRUE; - GFX.Pitch2 = GFX.RealPitch; - GFX.Pitch = GFX.RealPitch * 2; - GFX.PPL = GFX.PPLx2 = GFX.RealPitch; - - - // The game has switched from non-interlaced to interlaced mode - // part way down the screen. Scale everything. - for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) - { - // memmove converted: Same malloc, different addresses, and identical addresses at line 0 [Neb] - // DS2 DMA notes: This code path is unused [Neb] - memcpy (GFX.Screen + y * 2 * GFX.Pitch2, - GFX.Screen + y * GFX.Pitch2, - GFX.Pitch2); - // memmove converted: Same malloc, different addresses [Neb] - memcpy (GFX.Screen + (y * 2 + 1) * GFX.Pitch2, - GFX.Screen + y * GFX.Pitch2, - GFX.Pitch2); - } - } - } - else if (!Settings.SupportHiRes) - { - if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace) - { - if (!IPPU.HalfWidthPixels) - { - // The game has switched from lo-res to hi-res mode part way down - // the screen. Hi-res pixels must now be drawn at half width. - IPPU.HalfWidthPixels = TRUE; - } - } - else - { - if (IPPU.HalfWidthPixels) - { - // The game has switched from hi-res to lo-res mode part way down - // the screen. Lo-res pixels must now be drawn at FULL width. - IPPU.HalfWidthPixels = FALSE; - } - } - } - - uint32 black = BLACK | (BLACK << 16); - - if (Settings.Transparency) - { - if (GFX.Pseudo) - { - GFX.r2131 = 0x5f; - GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0); - GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f); - GFX.r2130 |= 2; - } - - if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && - (GFX.r2130 & 0x30) != 0x30 && - !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) - { - struct ClipData *pClip; - - GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed], - IPPU.XB [PPU.FixedColourGreen], - IPPU.XB [PPU.FixedColourBlue]); - - // Clear the z-buffer, marking areas 'covered' by the fixed - // colour as depth 1. - pClip = &IPPU.Clip [1]; - - // Clear the z-buffer - if (pClip->Count [5]) - { - // Colour window enabled. - for (uint32 y = starty; y <= endy; y++) - { - ZeroMemory (GFX.SubZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); - ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); - - if (IPPU.Clip [0].Count [5]) - { - uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2); - uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); - while (p < q) - *p++ = black; - } - - for (uint32 c = 0; c < pClip->Count [5]; c++) - { - if (pClip->Right [c][5] > pClip->Left [c][5]) - { - memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2, - 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); - - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - - uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX.Pitch2); - uint16 *q = p + pClip->Right [c][5] * x2; - p += pClip->Left [c][5] * x2; - - while (p < q) - *p++ = (uint16) GFX.FixedColour; - } - } - } - } - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); - memset (GFX.SubZBuffer + y * GFX.ZPitch, 1, IPPU.RenderedScreenWidth); - - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - - uint32 b = GFX.FixedColour | (GFX.FixedColour << 16); - uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2); - uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); - - while (p < q) - *p++ = b; - } - } - } - - if (ANYTHING_ON_SUB) - { - GFX.DB = GFX.SubZBuffer; - RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH); - } - - if (IPPU.Clip [0].Count [5]) - { - for (uint32 y = starty; y <= endy; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); - register uint8 *d = GFX.SubZBuffer + y * GFX.ZPitch; - register uint8 *e = d + IPPU.RenderedScreenWidth; - - while (d < e) - { - if (*d > 1) - *p = *(p + GFX.Delta); - else - *p = BLACK; - d++; - p++; - } - } - } - - GFX.DB = GFX.ZBuffer; - RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH); - - if (SUB_OR_ADD(5)) - { - uint32 back = IPPU.ScreenColors [0]; - uint32 Left = 0; - uint32 Right = 256; - uint32 Count; - - pClip = &IPPU.Clip [0]; - for (uint32 y = starty; y <= endy; y++) - { - if (!(Count = pClip->Count [5])) - { - Left = 0; - Right = 256 * x2; - Count = 1; - } - - for (uint32 b = 0; b < Count; b++) - { - if (pClip->Count [5]) - { - Left = pClip->Left [b][5] * x2; - Right = pClip->Right [b][5] * x2; - if (Right <= Left) - continue; - } - - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - // Subtract, halving the result. - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); - - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_SUB1_2 (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - else - { - // Subtract - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; - register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); - - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_SUB (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - } - else if (GFX.r2131 & 0x40) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_ADD1_2 (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - else if (back != 0) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_ADD (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - else - { - if (!pClip->Count [5]) - { - // The backdrop has not been cleared yet - so - // copy the sub-screen to the main screen - // or fill it with the back-drop colour if the - // sub-screen is clear. - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - register uint8 *e = d + Right; - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = *(p + GFX.Delta); - else - *p = GFX.FixedColour; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - } - } - } - } // --if (SUB_OR_ADD(5)) - else - { - // Subscreen not being added to back - uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - pClip = &IPPU.Clip [0]; - - if (pClip->Count [5]) - { - for (uint32 y = starty; y <= endy; y++) - { - for (uint32 b = 0; b < pClip->Count [5]; b++) - { - uint32 Left = pClip->Left [b][5] * x2; - uint32 Right = pClip->Right [b][5] * x2; - uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left; - uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - uint8 *e = d + Right; - d += Left; - - while (d < e) - { - if (*d == 0) - *p = (int16) back; - d++; - p++; - } - } - } - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); - uint8 *d = GFX.ZBuffer + y * GFX.ZPitch; - uint8 *e = d + 256 * x2; - - while (d < e) - { - if (*d == 0) - *p = (int16) back; - d++; - p++; - } - } - } - } - } //force blanking - else - { - // 16bit and transparency but currently no transparency effects in - // operation. - - uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - - if (PPU.ForcedBlanking) - back = black; - - if (IPPU.Clip [0].Count[5]) - { - for (uint32 y = starty; y <= endy; y++) - { - uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2); - uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); - - while (p < q) - *p++ = black; - - for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) - { - if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) - { - uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); - uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2; - p += IPPU.Clip [0].Left [c][5] * x2; - - while (p < q) - *p++ = (uint16) back; - } - } - } - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2); - uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth); - while (p < q) - *p++ = back; - } - } - - if (!PPU.ForcedBlanking) - { - for (uint32 y = starty; y <= endy; y++) - { - ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch, IPPU.RenderedScreenWidth); - } - GFX.DB = GFX.ZBuffer; - RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH); - } - } - } - else - { - } - - if (Settings.SupportHiRes) - { - if (PPU.BGMode != 5 && PPU.BGMode != 6 && IPPU.DoubleWidthPixels) - { - // Mixure of background modes used on screen - scale width - // of all non-mode 5 and 6 pixels. - for (register uint32 y = starty; y <= endy; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255; - register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510; - for (register int x = 255; x >= 0; x--, p--, q -= 2) - *q = *(q + 1) = *p; - } - } - - // Double the height of the pixels just drawn - FIX_INTERLACE(GFX.Screen, FALSE, GFX.ZBuffer); - } - - IPPU.PreviousLine = IPPU.CurrentLine; -} - - diff --git a/source/globals.c b/source/globals.c new file mode 100644 index 0000000..670dc92 --- /dev/null +++ b/source/globals.c @@ -0,0 +1,349 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "dsp1.h" +#include "missing.h" +#include "cpuexec.h" +#include "apu.h" +#include "dma.h" +#include "fxemu.h" +#include "gfx.h" +#include "soundux.h" +#include "cheats.h" +#include "sa1.h" +#include "spc7110.h" + +START_EXTERN_C +char String[513]; + +struct Missing missing; + +struct SICPU ICPU; + +struct SCPUState CPU; + +struct SAPU APU; + +struct SIAPU IAPU; + +struct SSettings Settings; + +struct SDSP1 DSP1; + +struct SSA1 SA1; + +SSoundData SoundData; + +SnesModel M1SNES={1,3,2}; +SnesModel M2SNES={2,4,3}; +SnesModel* Model=&M1SNES; + + +uint8 *SRAM = NULL; +uint8 *ROM = NULL; +uint8 *RegRAM = NULL; +uint8 *C4RAM = NULL; + +long OpAddress = 0; + +CMemory Memory; + +struct SSNESGameFixes SNESGameFixes; + +uint8 OpenBus = 0; + + +END_EXTERN_C + +#ifndef ZSNES_FX +struct FxInit_s SuperFX; +#else +START_EXTERN_C +uint8 *SFXPlotTable = NULL; +END_EXTERN_C +#endif + +struct SPPU PPU; +struct InternalPPU IPPU; + +struct SDMA DMA[8]; + +uint8 *HDMAMemPointers [8]; +uint8 *HDMABasePointers [8]; + +struct SBG BG; + +struct SGFX GFX; +struct SLineData LineData[240]; +struct SLineMatrixData LineMatrixData [240]; + +uint8 Mode7Depths [2]; +NormalTileRenderer DrawTilePtr = NULL; +ClippedTileRenderer DrawClippedTilePtr = NULL; +NormalTileRenderer DrawHiResTilePtr = NULL; +ClippedTileRenderer DrawHiResClippedTilePtr = NULL; +LargePixelRenderer DrawLargePixelPtr = NULL; + +uint32 odd_high[4][16]; +uint32 odd_low[4][16]; +uint32 even_high[4][16]; +uint32 even_low[4][16]; + +struct SCheatData Cheat; + +SoundStatus so; + +int Echo [24000]; +int DummyEchoBuffer [SOUND_BUFFER_SIZE]; +int MixBuffer [SOUND_BUFFER_SIZE]; +int EchoBuffer [SOUND_BUFFER_SIZE]; +int FilterTaps [8]; +unsigned long Z = 0; +int Loop [16]; + +uint16 SignExtend [2] = { + 0x00, 0xff00 +}; + +//modified per anomie Mode 5 findings +int HDMA_ModeByteCounts [8] = { + 1, 2, 2, 4, 4, 4, 2, 4 +}; + +uint8 BitShifts[8][4] = +{ + {2, 2, 2, 2}, // 0 + {4, 4, 2, 0}, // 1 + {4, 4, 0, 0}, // 2 + {8, 4, 0, 0}, // 3 + {8, 2, 0, 0}, // 4 + {4, 2, 0, 0}, // 5 + {4, 0, 0, 0}, // 6 + {8, 0, 0, 0} // 7 +}; +uint8 TileShifts[8][4] = +{ + {4, 4, 4, 4}, // 0 + {5, 5, 4, 0}, // 1 + {5, 5, 0, 0}, // 2 + {6, 5, 0, 0}, // 3 + {6, 4, 0, 0}, // 4 + {5, 4, 0, 0}, // 5 + {5, 0, 0, 0}, // 6 + {6, 0, 0, 0} // 7 +}; +uint8 PaletteShifts[8][4] = +{ + {2, 2, 2, 2}, // 0 + {4, 4, 2, 0}, // 1 + {4, 4, 0, 0}, // 2 + {0, 4, 0, 0}, // 3 + {0, 2, 0, 0}, // 4 + {4, 2, 0, 0}, // 5 + {4, 0, 0, 0}, // 6 + {0, 0, 0, 0} // 7 +}; +uint8 PaletteMasks[8][4] = +{ + {7, 7, 7, 7}, // 0 + {7, 7, 7, 0}, // 1 + {7, 7, 0, 0}, // 2 + {0, 7, 0, 0}, // 3 + {0, 7, 0, 0}, // 4 + {7, 7, 0, 0}, // 5 + {7, 0, 0, 0}, // 6 + {0, 0, 0, 0} // 7 +}; +uint8 Depths[8][4] = +{ + {TILE_2BIT, TILE_2BIT, TILE_2BIT, TILE_2BIT}, // 0 + {TILE_4BIT, TILE_4BIT, TILE_2BIT, 0}, // 1 + {TILE_4BIT, TILE_4BIT, 0, 0}, // 2 + {TILE_8BIT, TILE_4BIT, 0, 0}, // 3 + {TILE_8BIT, TILE_2BIT, 0, 0}, // 4 + {TILE_4BIT, TILE_2BIT, 0, 0}, // 5 + {TILE_4BIT, 0, 0, 0}, // 6 + {0, 0, 0, 0} // 7 +}; +uint8 BGSizes [2] = { + 8, 16 +}; +uint16 DirectColourMaps [8][256]; + +long FilterValues[4][2] = +{ + {0, 0}, + {240, 0}, + {488, -240}, + {460, -208} +}; + +int NoiseFreq [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 +}; + +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] = +{ + 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 +}; + + +// Raw SPC700 instruction cycle lengths +uint16 S9xAPUCycleLengths [256] = +{ + /* 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, 4, 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 +}; + +// Actual data used by CPU emulation, will be scaled by APUReset routine +// to be relative to the 65c816 instruction lengths. +uint16 S9xAPUCycles [256] = +{ + /* 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, 4, 5, 2, 2, 6, 3, + /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, + /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 +}; + +END_EXTERN_C + diff --git a/source/globals.cpp b/source/globals.cpp deleted file mode 100644 index 670dc92..0000000 --- a/source/globals.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "dsp1.h" -#include "missing.h" -#include "cpuexec.h" -#include "apu.h" -#include "dma.h" -#include "fxemu.h" -#include "gfx.h" -#include "soundux.h" -#include "cheats.h" -#include "sa1.h" -#include "spc7110.h" - -START_EXTERN_C -char String[513]; - -struct Missing missing; - -struct SICPU ICPU; - -struct SCPUState CPU; - -struct SAPU APU; - -struct SIAPU IAPU; - -struct SSettings Settings; - -struct SDSP1 DSP1; - -struct SSA1 SA1; - -SSoundData SoundData; - -SnesModel M1SNES={1,3,2}; -SnesModel M2SNES={2,4,3}; -SnesModel* Model=&M1SNES; - - -uint8 *SRAM = NULL; -uint8 *ROM = NULL; -uint8 *RegRAM = NULL; -uint8 *C4RAM = NULL; - -long OpAddress = 0; - -CMemory Memory; - -struct SSNESGameFixes SNESGameFixes; - -uint8 OpenBus = 0; - - -END_EXTERN_C - -#ifndef ZSNES_FX -struct FxInit_s SuperFX; -#else -START_EXTERN_C -uint8 *SFXPlotTable = NULL; -END_EXTERN_C -#endif - -struct SPPU PPU; -struct InternalPPU IPPU; - -struct SDMA DMA[8]; - -uint8 *HDMAMemPointers [8]; -uint8 *HDMABasePointers [8]; - -struct SBG BG; - -struct SGFX GFX; -struct SLineData LineData[240]; -struct SLineMatrixData LineMatrixData [240]; - -uint8 Mode7Depths [2]; -NormalTileRenderer DrawTilePtr = NULL; -ClippedTileRenderer DrawClippedTilePtr = NULL; -NormalTileRenderer DrawHiResTilePtr = NULL; -ClippedTileRenderer DrawHiResClippedTilePtr = NULL; -LargePixelRenderer DrawLargePixelPtr = NULL; - -uint32 odd_high[4][16]; -uint32 odd_low[4][16]; -uint32 even_high[4][16]; -uint32 even_low[4][16]; - -struct SCheatData Cheat; - -SoundStatus so; - -int Echo [24000]; -int DummyEchoBuffer [SOUND_BUFFER_SIZE]; -int MixBuffer [SOUND_BUFFER_SIZE]; -int EchoBuffer [SOUND_BUFFER_SIZE]; -int FilterTaps [8]; -unsigned long Z = 0; -int Loop [16]; - -uint16 SignExtend [2] = { - 0x00, 0xff00 -}; - -//modified per anomie Mode 5 findings -int HDMA_ModeByteCounts [8] = { - 1, 2, 2, 4, 4, 4, 2, 4 -}; - -uint8 BitShifts[8][4] = -{ - {2, 2, 2, 2}, // 0 - {4, 4, 2, 0}, // 1 - {4, 4, 0, 0}, // 2 - {8, 4, 0, 0}, // 3 - {8, 2, 0, 0}, // 4 - {4, 2, 0, 0}, // 5 - {4, 0, 0, 0}, // 6 - {8, 0, 0, 0} // 7 -}; -uint8 TileShifts[8][4] = -{ - {4, 4, 4, 4}, // 0 - {5, 5, 4, 0}, // 1 - {5, 5, 0, 0}, // 2 - {6, 5, 0, 0}, // 3 - {6, 4, 0, 0}, // 4 - {5, 4, 0, 0}, // 5 - {5, 0, 0, 0}, // 6 - {6, 0, 0, 0} // 7 -}; -uint8 PaletteShifts[8][4] = -{ - {2, 2, 2, 2}, // 0 - {4, 4, 2, 0}, // 1 - {4, 4, 0, 0}, // 2 - {0, 4, 0, 0}, // 3 - {0, 2, 0, 0}, // 4 - {4, 2, 0, 0}, // 5 - {4, 0, 0, 0}, // 6 - {0, 0, 0, 0} // 7 -}; -uint8 PaletteMasks[8][4] = -{ - {7, 7, 7, 7}, // 0 - {7, 7, 7, 0}, // 1 - {7, 7, 0, 0}, // 2 - {0, 7, 0, 0}, // 3 - {0, 7, 0, 0}, // 4 - {7, 7, 0, 0}, // 5 - {7, 0, 0, 0}, // 6 - {0, 0, 0, 0} // 7 -}; -uint8 Depths[8][4] = -{ - {TILE_2BIT, TILE_2BIT, TILE_2BIT, TILE_2BIT}, // 0 - {TILE_4BIT, TILE_4BIT, TILE_2BIT, 0}, // 1 - {TILE_4BIT, TILE_4BIT, 0, 0}, // 2 - {TILE_8BIT, TILE_4BIT, 0, 0}, // 3 - {TILE_8BIT, TILE_2BIT, 0, 0}, // 4 - {TILE_4BIT, TILE_2BIT, 0, 0}, // 5 - {TILE_4BIT, 0, 0, 0}, // 6 - {0, 0, 0, 0} // 7 -}; -uint8 BGSizes [2] = { - 8, 16 -}; -uint16 DirectColourMaps [8][256]; - -long FilterValues[4][2] = -{ - {0, 0}, - {240, 0}, - {488, -240}, - {460, -208} -}; - -int NoiseFreq [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 -}; - -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] = -{ - 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 -}; - - -// Raw SPC700 instruction cycle lengths -uint16 S9xAPUCycleLengths [256] = -{ - /* 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, 4, 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 -}; - -// Actual data used by CPU emulation, will be scaled by APUReset routine -// to be relative to the 65c816 instruction lengths. -uint16 S9xAPUCycles [256] = -{ - /* 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, 4, 5, 2, 2, 6, 3, - /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, - /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 -}; - -END_EXTERN_C - diff --git a/source/memmap.c b/source/memmap.c new file mode 100644 index 0000000..c102128 --- /dev/null +++ b/source/memmap.c @@ -0,0 +1,4448 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include + +#ifdef __linux +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "cpuexec.h" +#include "ppu.h" +#include "display.h" +#include "cheats.h" +#include "apu.h" +#include "sa1.h" +#include "dsp1.h" +#include "srtc.h" +#include "sdd1.h" +#include "spc7110.h" +#include "seta.h" + +#ifdef DS2_DMA +//#include "ds2_cpu.h" +//#include "ds2_dma.h" +//#include "dma_adj.h" +#endif + +#ifdef __W32_HEAP +#include +#endif + +#ifndef ZSNES_FX +#include "fxemu.h" +extern struct FxInit_s SuperFX; +#else +START_EXTERN_C +extern uint8 *SFXPlotTable; +END_EXTERN_C +#endif + +#ifndef SET_UI_COLOR +#define SET_UI_COLOR(r,g,b) ; +#endif + +//you would think everyone would have these +//since they're so useful. +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +static int retry_count=0; +static uint8 bytes0x2000 [0x2000]; +int is_bsx(unsigned char *); +int bs_name(unsigned char *); +int check_char(unsigned); +void S9xDeinterleaveType2 (bool8 reset=TRUE); +uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32 = 0xFFFFFFFF); + +extern char *rom_filename; + +const uint32 crc32Table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + + + +void S9xDeinterleaveType1(int TotalFileSize, uint8 * base) +{ + if(Settings.DisplayColor==0xffff) + { + Settings.DisplayColor=BUILD_PIXEL(0,31,0); + SET_UI_COLOR(0,255,0); + } + + int i; + int nblocks = TotalFileSize >> 16; + uint8 blocks [256]; + for (i = 0; i < nblocks; i++) + { + blocks [i * 2] = i + nblocks; + blocks [i * 2 + 1] = i; + } + // DS2 DMA notes: base may or may not be 32-byte aligned + uint8 *tmp = (uint8 *) malloc (0x8000); + if (tmp) + { + for (i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks [j] == i) + { + // memmove converted: Different mallocs [Neb] + memcpy (tmp, &base [blocks [j] * 0x8000], 0x8000); + // memmove converted: Different addresses, or identical for blocks[i] == blocks[j] [Neb] + // DS2 DMA notes: Don't do DMA at all if blocks[i] == blocks[j] + memcpy (&base [blocks [j] * 0x8000], + &base [blocks [i] * 0x8000], 0x8000); + // memmove converted: Different mallocs [Neb] + memcpy (&base [blocks [i] * 0x8000], tmp, 0x8000); + uint8 b = blocks [j]; + blocks [j] = blocks [i]; + blocks [i] = b; + break; + } + } + } + free ((char *) tmp); + } +} + +void S9xDeinterleaveGD24(int TotalFileSize, uint8 * base) +{ + + if(TotalFileSize!=0x300000) + return; + + if(Settings.DisplayColor==0xffff) + { + Settings.DisplayColor=BUILD_PIXEL(0,31,31); + SET_UI_COLOR(0,255,255); + } + + // DS2 DMA notes: base may or may not be 32-byte aligned + uint8 *tmp = (uint8 *) malloc (0x80000); + if (tmp) + { + // memmove converted: Different mallocs [Neb] + memcpy(tmp, &base[0x180000], 0x80000); + // memmove converted: Different addresses [Neb] + memcpy(&base[0x180000], &base[0x200000], 0x80000); + // memmove converted: Different addresses [Neb] + memcpy(&base[0x200000], &base[0x280000], 0x80000); + // memmove converted: Different mallocs [Neb] + memcpy(&base[0x280000], tmp, 0x80000); + free ((char *) tmp); + + S9xDeinterleaveType1(TotalFileSize, base); + } +} + +bool8 CMemory::AllASCII (uint8 *b, int size) +{ + for (int i = 0; i < size; i++) + { + if (b[i] < 32 || b[i] > 126) + return (FALSE); + } + return (TRUE); +} + +int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff) +{ + int score = 0; + int o = skip_header ? 0xff00 + 0x200 : 0xff00; + + o+=romoff; + + if(Memory.ROM [o + 0xd5] & 0x1) + score+=2; + + //Mode23 is SA-1 + if(Memory.ROM [o + 0xd5] == 0x23) + score-=2; + + if(Memory.ROM [o+0xd4] == 0x20) + score +=2; + + if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + + Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) + { + score += 2; + if(0!=(Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) + score++; + } + + if (Memory.ROM [o + 0xda] == 0x33) + score += 2; + if ((Memory.ROM [o + 0xd5] & 0xf) < 4) + score += 2; + if (!(Memory.ROM [o + 0xfd] & 0x80)) + score -= 6; + if ((Memory.ROM [o + 0xfc]|(Memory.ROM [o + 0xfd]<<8))>0xFFB0) + score -= 2; //reduced after looking at a scan by Cowering + if (CalculatedSize > 1024 * 1024 * 3) + score += 4; + if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) +{ + int score = 0; + int o = skip_header ? 0x7f00 + 0x200 : 0x7f00; + + o+=romoff; + + if(!(Memory.ROM [o + 0xd5] & 0x1)) + score+=3; + + //Mode23 is SA-1 + if(Memory.ROM [o + 0xd5] == 0x23) + score+=2; + + if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + + Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) + { + score += 2; + if(0!=(Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) + score++; + } + + if (Memory.ROM [o + 0xda] == 0x33) + score += 2; + if ((Memory.ROM [o + 0xd5] & 0xf) < 4) + score += 2; + if (CalculatedSize <= 1024 * 1024 * 16) + score += 2; + if (!(Memory.ROM [o + 0xfd] & 0x80)) + score -= 6; + if ((Memory.ROM [o + 0xfc]|(Memory.ROM [o + 0xfd]<<8))>0xFFB0) + score -= 2;//reduced per Cowering suggestion + if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +char *CMemory::Safe (const char *s) +{ + static char *safe; + static int safe_len = 0; + + if(s==NULL) + { + if(safe!=NULL) + { + free((char*)safe); + safe = NULL; + } + return NULL; + } + int len = strlen (s); + if (!safe || len + 1 > safe_len) + { + if (safe) + free ((char *) safe); + safe = (char *) malloc (safe_len = len + 1); + } + + for (int i = 0; i < len; i++) + { + if (s [i] >= 32 && s [i] < 127) + safe [i] = s[i]; + else + safe [i] = '?'; + } + safe [len] = 0; + return (safe); +} + +/**********************************************************************************************/ +/* Init() */ +/* This function allocates and zeroes all the memory needed by the emulator */ +/**********************************************************************************************/ +bool8 CMemory::Init () +{ + // DS2 DMA notes: These would do well to be allocated with 32 extra bytes + // so they can be 32-byte aligned. [Neb] + RAM = (uint8 *) malloc (0x20000); + SRAM = (uint8 *) malloc (0x20000); + VRAM = (uint8 *) malloc (0x10000); +#ifdef DS2_DMA + ROM = (uint8 *) AlignedMalloc (MAX_ROM_SIZE + 0x200 + 0x8000, 32, &PtrAdj.ROM); +#else + ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); +#endif + memset (RAM, 0, 0x20000); + memset (SRAM, 0, 0x20000); + memset (VRAM, 0, 0x10000); + // This needs to be initialised with a ROM first anyway, so don't + // bother memsetting. [Neb] + // memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000); + + BSRAM = (uint8 *) malloc (0x80000); + memset (BSRAM, 0, 0x80000); + + FillRAM = NULL; + + IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128); + IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128); + IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128); + + 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); + + if (!RAM || !SRAM || !VRAM || !ROM || !BSRAM || + !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || + !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || + !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT]) + { + Deinit (); + return (FALSE); + } + + // FillRAM uses first 32K of ROM image area, otherwise space just + // wasted. Might be read by the SuperFX code. + + FillRAM = ROM; + + // Add 0x8000 to ROM image pointer to stop SuperFX code accessing + // unallocated memory (can cause crash on some ports). + ROM += 0x8000; // still 32-byte aligned + + C4RAM = ROM + 0x400000 + 8192 * 8; // still 32-byte aligned + ::ROM = ROM; + ::SRAM = SRAM; + ::RegRAM = FillRAM; + +#ifdef ZSNES_FX + SFXPlotTable = ROM + 0x400000; +#else + SuperFX.pvRegisters = &Memory.FillRAM [0x3000]; + SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB, 2=128KB=1024Mb + SuperFX.pvRam = ::SRAM; + SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); + SuperFX.pvRom = (uint8 *) ROM; +#endif + + ZeroMemory (IPPU.TileCache [TILE_2BIT], MAX_2BIT_TILES * 128); + ZeroMemory (IPPU.TileCache [TILE_4BIT], MAX_4BIT_TILES * 128); + ZeroMemory (IPPU.TileCache [TILE_8BIT], MAX_8BIT_TILES * 128); + + ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); + + SDD1Data = NULL; + SDD1Index = NULL; + + return (TRUE); +} + +void CMemory::Deinit () +{ +#ifdef __W32_HEAP + if(_HEAPOK!=_heapchk()) + MessageBox(GUI.hWnd, "CMemory::Deinit", "Heap Corrupt", MB_OK); +#endif + + if (RAM) + { + free ((char *) RAM); + RAM = NULL; + } + if (SRAM) + { + free ((char *) SRAM); + SRAM = NULL; + } + if (VRAM) + { + free ((char *) VRAM); + VRAM = NULL; + } + if (ROM) + { + ROM -= 0x8000; +#ifdef DS2_RAM + AlignedFree ((char *) ROM, PtrAdj.ROM); +#else + free ((char *) ROM); +#endif + ROM = NULL; + } + + if(BSRAM) + { + free((char*) BSRAM); + BSRAM=NULL; + } + + if (IPPU.TileCache [TILE_2BIT]) + { + free ((char *) IPPU.TileCache [TILE_2BIT]); + IPPU.TileCache [TILE_2BIT] = NULL; + } + if (IPPU.TileCache [TILE_4BIT]) + { + free ((char *) IPPU.TileCache [TILE_4BIT]); + IPPU.TileCache [TILE_4BIT] = NULL; + } + if (IPPU.TileCache [TILE_8BIT]) + { + free ((char *) IPPU.TileCache [TILE_8BIT]); + IPPU.TileCache [TILE_8BIT] = NULL; + } + + if (IPPU.TileCached [TILE_2BIT]) + { + free ((char *) IPPU.TileCached [TILE_2BIT]); + IPPU.TileCached [TILE_2BIT] = NULL; + } + if (IPPU.TileCached [TILE_4BIT]) + { + free ((char *) IPPU.TileCached [TILE_4BIT]); + IPPU.TileCached [TILE_4BIT] = NULL; + } + if (IPPU.TileCached [TILE_8BIT]) + { + free ((char *) IPPU.TileCached [TILE_8BIT]); + IPPU.TileCached [TILE_8BIT] = NULL; + } + FreeSDD1Data (); + Safe(NULL); +} + +void CMemory::FreeSDD1Data () +{ + if (SDD1Index) + { + free ((char *) SDD1Index); + SDD1Index = NULL; + } + if (SDD1Data) + { + free ((char *) SDD1Data); + SDD1Data = NULL; + } +} + +/**********************************************************************************************/ +/* LoadROM() */ +/* This function loads a Snes-Backup image */ +/**********************************************************************************************/ + +bool8 CMemory::LoadROM (const char *filename) +{ + int32 TotalFileSize = 0; + bool8 Interleaved = FALSE; + bool8 Tales = FALSE; + + uint8* RomHeader=ROM; + + ExtendedFormat=NOPE; + + + if(CleanUp7110!=NULL) + (*CleanUp7110)(); + + memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + + memset (bytes0x2000, 0, 0x2000); + CPU.TriedInterleavedMode2 = FALSE; + + CalculatedSize = 0; + retry_count =0; + +again: + Settings.DisplayColor=0xffff; + SET_UI_COLOR(255,255,255); + + TotalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); + + if (!TotalFileSize) + return FALSE; // it ends here + else if(!Settings.NoPatch) + CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize); + + //fix hacked games here. + if((strncmp("HONKAKUHA IGO GOSEI", (char*)&ROM[0x7FC0],19)==0)&&(ROM[0x7FD5]!=0x31)) + { + ROM[0x7FD5]=0x31; + ROM[0x7FD6]=0x02; + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); + } + + if((strncmp("HONKAKUHA IGO GOSEI", (char*)&ROM[0xFFC0],19)==0)&&(ROM[0xFFD5]!=0x31)) + { + ROM[0xFFD5]=0x31; + ROM[0xFFD6]=0x02; + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); + } + + if((ROM[0x7FD5]==0x42)&&(ROM[0x7FD6]==0x13)&&(strncmp("METAL COMBAT",(char*)&ROM[0x7FC0],12)==0)) + { + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); + } + + int orig_hi_score, orig_lo_score; + int hi_score, lo_score; + + orig_hi_score = hi_score = ScoreHiROM (FALSE); + orig_lo_score = lo_score = ScoreLoROM (FALSE); + + if (HeaderCount == 0 && !Settings.ForceNoHeader && + ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || + (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) + { +#ifdef DS2_DMA + __dcache_writeback_all(); + { + unsigned int i; + for (i = 0; i < TotalFileSize; i += 512) + { + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, Memory.ROM + i, Memory.ROM + i + 512, 512); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + } + } +#else + // memmove required: Overlapping addresses [Neb] + memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); +#endif + TotalFileSize -= 512; + S9xMessage (S9X_INFO, S9X_HEADER_WARNING, + "Try specifying the -nhd command line option if the game doesn't work\n"); + //modifying ROM, so we need to rescore + orig_hi_score = hi_score = ScoreHiROM (FALSE); + orig_lo_score = lo_score = ScoreLoROM (FALSE); + } + + CalculatedSize = TotalFileSize & ~0x1FFF; // round down to lower 0x2000 + ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize); + + if(CalculatedSize >0x400000&& + !(ROM[0x7FD5]==0x32&&((ROM[0x7FD6]&0xF0)==0x40)) && //exclude S-DD1 + !(ROM[0xFFD5]==0x3A&&((ROM[0xFFD6]&0xF0)==0xF0))) //exclude SPC7110 + { + //you might be a Jumbo! + ExtendedFormat=YEAH; + } + + //If both vectors are invalid, it's type 1 LoROM + + if(ExtendedFormat==NOPE&&((ROM[0x7FFC]|(ROM[0x7FFD]<<8))<0x8000)&&((ROM[0xFFFC]|(ROM[0xFFFD]<<8)) <0x8000)) + { + if(Settings.DisplayColor==0xffff) + { + Settings.DisplayColor=BUILD_PIXEL(0,31,0); + SET_UI_COLOR(0,255,0); + } + if(!Settings.ForceInterleaved) + S9xDeinterleaveType1(TotalFileSize, ROM); + } + + //CalculatedSize is now set, so rescore + orig_hi_score = hi_score = ScoreHiROM (FALSE); + orig_lo_score = lo_score = ScoreLoROM (FALSE); + + if(NOPE!=ExtendedFormat) + { + int loromscore, hiromscore, swappedlorom, swappedhirom; + loromscore=ScoreLoROM(FALSE); + hiromscore=ScoreHiROM(FALSE); + swappedlorom=ScoreLoROM(FALSE, 0x400000); + swappedhirom=ScoreHiROM(FALSE, 0x400000); + + //set swapped here. + + if(max(swappedlorom, swappedhirom) >= max(loromscore, hiromscore)) + { + ExtendedFormat = BIGFIRST; + hi_score=swappedhirom; + lo_score=swappedlorom; + RomHeader=ROM+0x400000; + } + else + { + ExtendedFormat = SMALLFIRST; + lo_score=loromscore; + hi_score=hiromscore; + RomHeader=ROM; + } + + + } + + Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; + if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) + { + LoROM = TRUE; + HiROM = FALSE; + + // Ignore map type byte if not 0x2x or 0x3x + if ((RomHeader [0x7fd5] & 0xf0) == 0x20 || (RomHeader [0x7fd5] & 0xf0) == 0x30) + { + switch (RomHeader [0x7fd5] & 0xf) + { + case 1: + Interleaved = TRUE; + break; + case 5: + Interleaved = TRUE; + Tales = TRUE; + break; + } + } + } + else + { + if ((RomHeader [0xffd5] & 0xf0) == 0x20 || (RomHeader [0xffd5] & 0xf0) == 0x30) + { + switch (RomHeader [0xffd5] & 0xf) + { + case 0: + case 3: + Interleaved = TRUE; + break; + } + } + LoROM = FALSE; + HiROM = TRUE; + } + + // More + if (!Settings.ForceHiROM && !Settings.ForceLoROM && + !Settings.ForceInterleaved && !Settings.ForceInterleaved2 && + !Settings.ForceNotInterleaved && !Settings.ForcePAL && + !Settings.ForceSuperFX && !Settings.ForceDSP1 && + !Settings.ForceSA1 && !Settings.ForceC4 && + !Settings.ForceSDD1) + { + + +#ifdef DETECT_NASTY_FX_INTERLEAVE +//MK: Damn. YI trips a BRK currently. Maybe even on a real cart. + +#ifdef LSB_FIRST + if(strncmp((char *) &ROM [0x7fc0], "YOSHI'S ISLAND", 14) == 0&&(*(uint16*)&ROM[0x7FDE])==57611&&ROM[0x10002]==0xA9) +#else + if(strncmp((char *) &ROM [0x7fc0], "YOSHI'S ISLAND", 14) == 0&&(ROM[0x7FDE]+(ROM[0x7FDF]<<8))==57611&&ROM[0x10002]==0xA9) +#endif + { + Interleaved=true; + Settings.ForceInterleaved2=true; + } +#endif + if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0) + { + LoROM = TRUE; + HiROM = FALSE; + Interleaved = FALSE; + } + } + + if (!Settings.ForceNotInterleaved && Interleaved) + { + CPU.TriedInterleavedMode2 = TRUE; + S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, + "ROM image is in interleaved format - converting..."); + + if (Tales) + { + if(Memory.ExtendedFormat==BIGFIRST) + { + S9xDeinterleaveType1(0x400000, ROM); + S9xDeinterleaveType1(CalculatedSize-0x400000, ROM+0x400000); + } + else + { + S9xDeinterleaveType1(CalculatedSize-0x400000, ROM); + S9xDeinterleaveType1(0x400000, ROM+CalculatedSize-0x400000); + + } + + LoROM = FALSE; + HiROM = TRUE; + + + } + else if (Settings.ForceInterleaved2) + { + S9xDeinterleaveType2(FALSE); + } + else if (Settings.ForceInterleaveGD24 && CalculatedSize ==0x300000) + { + bool8 t = LoROM; + + LoROM = HiROM; + HiROM = t; + S9xDeinterleaveGD24(CalculatedSize, ROM); + } + else + { + if(Settings.DisplayColor==0xffff) + { + Settings.DisplayColor=BUILD_PIXEL(0,31,0); + SET_UI_COLOR(0,255,0); + } + bool8 t = LoROM; + + LoROM = HiROM; + HiROM = t; + + S9xDeinterleaveType1(CalculatedSize, ROM); + } + + hi_score = ScoreHiROM (FALSE); + lo_score = ScoreLoROM (FALSE); + + if ((HiROM && + (lo_score >= hi_score || hi_score < 0)) || + (LoROM && + (hi_score > lo_score || lo_score < 0))) + { + if (retry_count == 0) + { + S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, + "ROM lied about its type! Trying again."); + Settings.ForceNotInterleaved = TRUE; + Settings.ForceInterleaved = FALSE; + retry_count++; + goto again; + } + } + } + + if(ExtendedFormat==SMALLFIRST) + Tales=true; + + FreeSDD1Data (); + InitROM (Tales); + S9xLoadCheatFile (S9xGetFilename(".cht")); + S9xInitCheatData (); + S9xApplyCheats (); + + S9xReset (); + + return (TRUE); +} + +uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) +{ + + + FILE* ROMFile; + int32 TotalFileSize = 0; + int len = 0; + + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char name [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char fname [_MAX_PATH + 1]; + + unsigned long FileSize = 0; + + _splitpath (filename, drive, dir, name, ext); + _makepath (fname, drive, dir, name, ext); + +#ifdef __WIN32__ + // memmove required: Overlapping addresses [Neb] + memmove (&ext [0], &ext[1], 4); +#endif + + if ((ROMFile = fopen(fname, "rb")) == NULL) + return (0); + + strcpy (ROMFilename, fname); + + HeaderCount = 0; + uint8 *ptr = buffer; + bool8 more = FALSE; + + do + { + FileSize = fread (ptr, 1, maxsize + 0x200 - (ptr - ROM), ROMFile); + fclose (ROMFile); + + int calc_size = FileSize & ~0x1FFF; // round to the lower 0x2000 + + if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || + Settings.ForceHeader) + { + // memmove required: Overlapping addresses [Neb] + // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] +#ifdef DS2_DMA + __dcache_writeback_all(); + { + unsigned int i; + for (i = 0; i < calc_size; i += 512) + { + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, ptr + i, ptr + i + 512, 512); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + } + } +#else + memmove (ptr, ptr + 512, calc_size); +#endif + HeaderCount++; + FileSize -= 512; + } + + ptr += FileSize; + TotalFileSize += FileSize; + + + // check for multi file roms + + if ((ptr - ROM) < (maxsize + 0x200) && + (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9')) + { + more = TRUE; + ext [0]++; +#ifdef __WIN32__ + // memmove required: Overlapping addresses [Neb] + memmove (&ext [1], &ext [0], 4); + ext [0] = '.'; +#endif + _makepath (fname, drive, dir, name, ext); + } + else if (ptr - ROM < 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]++; +#ifdef __WIN32__ + // memmove required: Overlapping addresses [Neb] + memmove (&ext [1], &ext [0], 4); + ext [0] = '.'; +#endif + _makepath (fname, drive, dir, name, ext); + } + else + more = FALSE; + + } while (more && (ROMFile = fopen (fname, "rb")) != NULL); + + + + 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 TotalFileSize; + +} + +#if 0 +/**********************************************************************************************/ +/* LoadMulti() */ +/* This function loads a Slotted SNES-Backup image and fills the slot. */ +/**********************************************************************************************/ + +bool8 CMemory::LoadMulti (const char *basename, const char *slot1name, const char *slot2name) +{ + unsigned long FileSize = 0; + + if(*basename=='\0') + return FALSE; + + SufamiTurbo=TRUE; + + int32 offset; + + memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + + memset (bytes0x2000, 0, 0x2000); + + CalculatedSize = 0; + + Settings.DisplayColor=0xffff; + SET_UI_COLOR(255,255,255); + + int32 TotalFileSize = FileLoader(ROM, basename, MAX_ROM_SIZE); + + if(0== TotalFileSize) + return FALSE; + else CheckForIPSPatch (basename, HeaderCount != 0, TotalFileSize); + + CalculatedSize=TotalFileSize; + + for(offset=0; offset0x100000||size <0x80000) + return FALSE; + //probably a minicart + return TRUE; + } + return FALSE; +} + +bool8 SameGameSig(uint8* file, int32 size) +{ + //preheader sig + if(strcmp((char*)(file+0xFFA0),"1995/12/16 10:2018ZS5J")) + return FALSE; + if(size!=0x100000) + return FALSE; + if(0x133E1C5B==caCRC32(file, size)) + return TRUE; + return FALSE; +} +bool8 GNextSig(uint8* file, int32 size) +{ + //preheader sig + if(strcmp((char*)(file+0xFFAA),"GNEXT B2ZX3J")) + return FALSE; + if(size!=0x180000) + return FALSE; + if(0x845E420D==caCRC32(file, size)) + return TRUE; + return FALSE; +} +int MultiType(uint8* file, int32 size) +{ + //check for ST signiture + if(SufamiTurboBIOSSig(file, size)) + return 1; + //check for Same Game signiture + if(SameGameSig(file, size)) + return 2; + //check for G-Next signiture + if(GNextSig(file, size)) + return 3; + return 0; +} + +#endif + +//compatibility wrapper +void S9xDeinterleaveMode2 () +{ + S9xDeinterleaveType2(); +} + +void S9xDeinterleaveType2 (bool8 reset) +{ + if(Settings.DisplayColor==0xffff||Settings.DisplayColor==BUILD_PIXEL(0,31,0)) + { + Settings.DisplayColor=BUILD_PIXEL(31,14,6); + SET_UI_COLOR(255,119,25); + + } + S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, + "ROM image is in interleaved format - converting..."); + + int nblocks = Memory.CalculatedSize >> 16; + int step = 64; + + while (nblocks <= step) + step >>= 1; + + nblocks = step; + uint8 blocks [256]; + int i; + + for (i = 0; i < nblocks * 2; i++) + { + blocks [i] = (i & ~0xF) | ((i & 3) << 2) | + ((i & 12) >> 2); + } + +#ifdef DS2_DMA + unsigned int TmpAdj; + uint8 *tmp = (uint8 *) AlignedMalloc (0x10000, 32, &TmpAdj); +#else + uint8 *tmp = (uint8 *) malloc (0x10000); +#endif + + if (tmp) + { +#ifdef DS2_DMA + __dcache_writeback_all(); +#endif + for (i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks [j] == i) + { +#ifdef DS2_DMA + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [j] * 0x10000], + &Memory.ROM [blocks [i] * 0x10000], 0x10000); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); + ds2_DMA_wait(2); + ds2_DMA_stop(2); +#else + // memmove converted: Different mallocs [Neb] + memcpy (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); + + // memmove converted: Different addresses, or identical if blocks[i] == blocks[j] [Neb] + memcpy (&Memory.ROM [blocks [j] * 0x10000], + &Memory.ROM [blocks [i] * 0x10000], 0x10000); + // memmove converted: Different mallocs [Neb] + memcpy (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); +#endif + uint8 b = blocks [j]; + blocks [j] = blocks [i]; + blocks [i] = b; + break; + } + } + } + free ((char *) tmp); + tmp=NULL; + } + if(reset) + { + Memory.InitROM (FALSE); + S9xReset (); + } +} + +//CRC32 for char arrays +uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32) +{ + for (register uint32 i = 0; i < size; i++) + { + crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; + } + return ~crc32; +} + +void CMemory::InitROM (bool8 Interleaved) +{ +#ifndef ZSNES_FX + SuperFX.nRomBanks = CalculatedSize >> 15; +#endif + Settings.MultiPlayer5Master = Settings.MultiPlayer5; + Settings.MouseMaster = Settings.Mouse; + Settings.SuperScopeMaster = Settings.SuperScope; + Settings.DSP1Master = Settings.ForceDSP1; + Settings.SuperFX = FALSE; + 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; + s7r.DataRomSize = 0; + CalculatedChecksum=0; + uint8* RomHeader; + + RomHeader=ROM+0x7FB0; + + if(ExtendedFormat==BIGFIRST) + RomHeader+=0x400000; + + if(HiROM) + RomHeader+=0x8000; + + if(!Settings.BS) + { + Settings.BS=(-1!=is_bsx(ROM+0x7FC0)); + + if(Settings.BS) + { + Memory.LoROM=TRUE; + Memory.HiROM=FALSE; + } + + else + { + Settings.BS=(-1!=is_bsx(ROM+0xFFC0)); + if(Settings.BS) + { + Memory.HiROM=TRUE; + Memory.LoROM=FALSE; + } + } + } + + ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS); + ZeroMemory (BlockIsROM, MEMMAP_NUM_BLOCKS); + + ::SRAM = SRAM; + memset (ROMId, 0, 5); + memset (CompanyId, 0, 3); + + ParseSNESHeader(RomHeader); + + // Try to auto-detect the DSP1 chip + if (!Settings.ForceNoDSP1 && + (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0) + Settings.DSP1Master = TRUE; + + if (Memory.HiROM) + { + // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2 + Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5; + + if(((ROMSpeed&0x0F)==0x0A)&&((ROMType&0xF0)==0xF0)) + { + Settings.SPC7110=true; + if((ROMType&0x0F)==0x09) + Settings.SPC7110RTC=true; + } + + if (Settings.BS) + BSHiROMMap (); + else if(Settings.SPC7110) + { + SPC7110HiROMMap(); + } + else if ((ROMSpeed & ~0x10) == 0x25) + { + TalesROMMap (Interleaved); + } + else HiROMMap (); + } + else + { + Settings.SuperFX = Settings.ForceSuperFX; + + if(ROMType==0x25) + { + Settings.OBC1=TRUE; + } + + //BS-X BIOS + if(ROMType==0xE5) + { + Settings.BS=TRUE; + } + + if ((ROMType & 0xf0) == 0x10) + Settings.SuperFX = !Settings.ForceNoSuperFX; + + Settings.SDD1 = Settings.ForceSDD1; + if ((ROMType & 0xf0) == 0x40) + Settings.SDD1 = !Settings.ForceNoSDD1; + + if (Settings.SDD1) + S9xLoadSDD1Data (); + + if(((ROMType &0xF0) == 0xF0)&((ROMSpeed&0x0F)!=5)) + { + SRAMSize=2; + SNESGameFixes.SRAMInitialValue = 0x00; + if((ROMType &0x0F)==6) + { + if(ROM[0x7FD7]==0x09) + { + Settings.SETA=ST_011; + SetSETA=&S9xSetST011; + GetSETA=&S9xGetST011; + } + else + { + Settings.SETA=ST_010; + SetSETA=&S9xSetST010; + GetSETA=&S9xGetST010; + } + } + else + { + Settings.SETA=ST_018; + SRAMSize=2; + } + } + Settings.C4 = Settings.ForceC4; + if ((ROMType & 0xf0) == 0xf0 && + (strncmp (ROMName, "MEGAMAN X", 9) == 0 || + strncmp (ROMName, "ROCKMAN X", 9) == 0)) + { + Settings.C4 = !Settings.ForceNoC4; + } + + if(Settings.SETA&&Settings.SETA!=ST_018) + { + SetaDSPMap(); + } + else if (Settings.SuperFX) + { + //::SRAM = ROM + 1024 * 1024 * 4; + SuperFXROMMap (); + Settings.MultiPlayer5Master = FALSE; + //Settings.MouseMaster = FALSE; + //Settings.SuperScopeMaster = FALSE; + Settings.DSP1Master = FALSE; + Settings.SA1 = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + } + else if (Settings.ForceSA1 || + (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && + (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) + { + Settings.SA1 = TRUE; +// Settings.MultiPlayer5Master = FALSE; + //Settings.MouseMaster = FALSE; + //Settings.SuperScopeMaster = FALSE; + Settings.DSP1Master = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + SA1ROMMap (); + } + else if ((ROMSpeed & ~0x10) == 0x25) + TalesROMMap (Interleaved); + else if(ExtendedFormat!=NOPE) + JumboLoROMMap(Interleaved); + else if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || + strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) + { + LoROM24MBSMap (); + Settings.DSP1Master = FALSE; + } + + else if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || + strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) + { + SRAM512KLoROMMap (); + Settings.DSP1Master = FALSE; + } + else if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0) + { + Settings.MultiPlayer5Master = FALSE; + Settings.MouseMaster = FALSE; + Settings.SuperScopeMaster = FALSE; + Settings.DSP1Master = FALSE; + SufamiTurboLoROMMap(); + Memory.SRAMSize = 3; + } + else if ((ROMSpeed & ~0x10) == 0x22 && + strncmp (ROMName, "Super Street Fighter", 20) != 0) + { + AlphaROMMap (); + } + else if (Settings.BS) + BSLoROMMap(); + else LoROMMap (); + } + + if(Settings.BS) + { + ROMRegion=0; + } + + uint32 sum1 = 0; + uint32 sum2 = 0; + if(0==CalculatedChecksum) + { + int power2 = 0; + int size = CalculatedSize; + + while (size >>= 1) + power2++; + + size = 1 << power2; + uint32 remainder = CalculatedSize - size; + + + int i; + + for (i = 0; i < size; i++) + sum1 += ROM [i]; + + for (i = 0; i < (int) remainder; i++) + sum2 += ROM [size + i]; + + int sub = 0; + if (Settings.BS&& ROMType!=0xE5) + { + if (Memory.HiROM) + { + for (i = 0; i < 48; i++) + sub += ROM[0xffb0 + i]; + } + else if (Memory.LoROM) + { + for (i = 0; i < 48; i++) + sub += ROM[0x7fb0 + i]; + } + sum1 -= sub; + } + + + if (remainder) + { + sum1 += sum2 * (size / remainder); + } + + + sum1 &= 0xffff; + Memory.CalculatedChecksum=sum1; + } + //now take a CRC32 + ROMCRC32 = caCRC32(ROM, CalculatedSize); + + if (Settings.ForceNTSC) + Settings.PAL = FALSE; + else if (Settings.ForcePAL) + Settings.PAL = TRUE; + else + { + //Korea refers to South Korea, which uses NTSC + switch(ROMRegion) + { + case 13: + case 1: + case 0: + Settings.PAL=FALSE; + break; + default: Settings.PAL=TRUE; + break; + } + } + if (Settings.PAL) + { + Settings.FrameTime = Settings.FrameTimePAL; + Memory.ROMFramesPerSecond = 50; + } + else + { + Settings.FrameTime = Settings.FrameTimeNTSC; + Memory.ROMFramesPerSecond = 60; + } + + ROMName[ROM_NAME_LEN - 1] = 0; + if (strlen (ROMName)) + { + char *p = ROMName + strlen (ROMName) - 1; + + while (p > ROMName && *(p - 1) == ' ') + p--; + *p = 0; + } + + { + SRAMMask = Memory.SRAMSize ? + ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; + } + if((ROMChecksum + ROMComplementChecksum != 0xffff) || ROMChecksum != CalculatedChecksum || ((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); + } + } + + IAPU.OneCycle = ONE_APU_CYCLE; + Settings.Shutdown = Settings.ShutdownMaster; + + SetDSP=&DSP1SetByte; + GetDSP=&DSP1GetByte; + + ResetSpeedMap(); + ApplyROMFixes (); + 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", + ROMName, + (ROMChecksum + ROMComplementChecksum != 0xffff || + ROMChecksum != CalculatedChecksum) ? "bad checksum" : "checksum ok", + MapType (), + Size (), + KartContents (), + MapMode (), + TVStandard (), + StaticRAMSize (), + ROMId, + CompanyId, + ROMCRC32); + + S9xMessage (S9X_INFO, S9X_ROM_INFO, String); +#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.ForceHeader = Settings.ForceHiROM = Settings.ForceLoROM = + Settings.ForceInterleaved = Settings.ForceNoHeader = Settings.ForceNotInterleaved = + Settings.ForceInterleaved2=false; +} + +bool8 CMemory::LoadSRAM (const char *filename) +{ + int size = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + + memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); + + if (size > 0x20000) + size = 0x20000; + + if (size) + { + FILE *file; + if ((file = fopen (filename, "rb"))) + { + int len = fread ((unsigned char*) ::SRAM, 1, 0x20000, file); + fclose (file); + if (len - size == 512) + { + // S-RAM file has a header - remove it + // memmove required: Overlapping addresses [Neb] + 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); + } + + return (TRUE); + } + S9xHardResetSRTC (); + return (FALSE); + } + if (Settings.SDD1) + S9xSDD1LoadLoggedData (); + + return (TRUE); +} + +bool8 CMemory::SaveSRAM (const char *filename) +{ + if(Settings.SuperFX && Memory.ROMType < 0x15) + return TRUE; + if(Settings.SA1 && Memory.ROMType == 0x34) + return TRUE; + + int size = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (Settings.SRTC) + { + size += SRTC_SRAM_PAD; + S9xSRTCPreSaveState (); + } + + if (Settings.SDD1) + S9xSDD1SaveLoggedData (); + + if (size > 0x20000) + size = 0x20000; + + if (size && *Memory.ROMFilename) + { + + FILE *file= fopen(filename, "w"); + if (file) + { + fwrite((unsigned char *) ::SRAM, size, 1, file); + fclose(file); + if(Settings.SPC7110RTC) + { + S9xSaveSPC7110RTC (&rtc_f9); + } + + return (TRUE); + } + } + return (FALSE); +} + +void CMemory::FixROMSpeed () +{ + int c; + + if(CPU.FastROMSpeed==0) + CPU.FastROMSpeed=SLOW_ONE_CYCLE; + + + for (c = 0x800; c < 0x1000; c++) + { + if (c&0x8 || c&0x400) + MemorySpeed [c] = (uint8) CPU.FastROMSpeed; + } +} + + +void CMemory::ResetSpeedMap() +{ + int i; + memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000); + for(i=0;i<0x400;i+=0x10) + { + MemorySpeed[i+2]=MemorySpeed[0x800+i+2]= ONE_CYCLE; + MemorySpeed[i+3]=MemorySpeed[0x800+i+3]= ONE_CYCLE; + MemorySpeed[i+4]=MemorySpeed[0x800+i+4]= ONE_CYCLE; + MemorySpeed[i+5]=MemorySpeed[0x800+i+5]= ONE_CYCLE; + } + CMemory::FixROMSpeed (); +} + +void CMemory::WriteProtectROM () +{ + // memmove converted: Different mallocs [Neb] + memcpy ((void *) WriteMap, (void *) Map, sizeof (Map)); + for (int c = 0; c < 0x1000; c++) + { + if (BlockIsROM [c]) + WriteMap [c] = (uint8 *) MAP_NONE; + } +} + +void CMemory::MapRAM () +{ + int c; + + if(Memory.LoROM&&!Settings.SDD1) + { + // Banks 70->77, S-RAM + for (c = 0; c < 0x0f; c++) + { + for(int i=0;i<8;i++) + { + Map [(c<<4) + 0xF00+i]=Map [(c<<4) + 0x700+i] = (uint8 *) MAP_LOROM_SRAM; + BlockIsRAM [(c<<4) + 0xF00+i] =BlockIsRAM [(c<<4) + 0x700+i] = TRUE; + BlockIsROM [(c<<4) + 0xF00+i] =BlockIsROM [(c<<4) + 0x700+i] = FALSE; + } + } + } + else if(Memory.LoROM&&Settings.SDD1) + { + // Banks 70->77, S-RAM + for (c = 0; c < 0x0f; c++) + { + for(int i=0;i<8;i++) + { + Map [(c<<4) + 0x700+i] = (uint8 *) MAP_LOROM_SRAM; + BlockIsRAM [(c<<4) + 0x700+i] = TRUE; + BlockIsROM [(c<<4) + 0x700+i] = FALSE; + } + } + } + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + WriteProtectROM (); +} + +void CMemory::MapExtraRAM () +{ + int c; + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 70->73, S-RAM + for (c = 0; c < 16; c++) + { + Map [c + 0x700] = ::SRAM; + Map [c + 0x710] = ::SRAM + 0x8000; + Map [c + 0x720] = ::SRAM + 0x10000; + Map [c + 0x730] = ::SRAM + 0x18000; + + BlockIsRAM [c + 0x700] = TRUE; + BlockIsROM [c + 0x700] = FALSE; + BlockIsRAM [c + 0x710] = TRUE; + BlockIsROM [c + 0x710] = FALSE; + BlockIsRAM [c + 0x720] = TRUE; + BlockIsROM [c + 0x720] = FALSE; + BlockIsRAM [c + 0x730] = TRUE; + BlockIsROM [c + 0x730] = FALSE; + } +} + +void CMemory::LoROMMap () +{ + int c; + int i; + int j; + int mask[4]; + for (j=0; j<4; j++) + mask[j]=0x00ff; + + mask[0]=(CalculatedSize/0x8000)-1; + + int x; + bool foundZeros; + bool pastZeros; + + for(j=0;j<3;j++) + { + x=1; + foundZeros=false; + pastZeros=false; + + mask[j+1]=mask[j]; + + while (x>0x100&&!pastZeros) + { + if(mask[j]&x) + { + x<<=1; + if(foundZeros) + pastZeros=true; + } + else + { + foundZeros=true; + pastZeros=false; + mask[j+1]|=x; + x<<=1; + } + } + } + + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + if(Settings.SETA==ST_018) + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_SETA_RISC; + else Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + if (Settings.DSP1Master) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; + } + else if (Settings.C4) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; + } + else if(Settings.OBC1) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_OBC_RAM; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_OBC_RAM; + } + else + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; + Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; + } + + for (i = c + 8; i < c + 16; i++) + { + int e=3; + int d=c>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + Map [i] = Map [i + 0x800] = ROM + (((d)-1)*0x8000); + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + if (Settings.DSP1Master) + { + // Banks 30->3f and b0->bf + for (c = 0x300; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP; + BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; + } + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize]; + + for (i = c + 8; i < c + 16; i++) + { + int e=3; + int d=(c+0x400)>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + + Map [i + 0x400] = Map [i + 0xc00] = ROM + (((d)-1)*0x8000); + } + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + if (Settings.DSP1Master) + { + for (c = 0; c < 0x100; c++) + { + Map [c + 0xe00] = (uint8 *) MAP_DSP; + BlockIsROM [c + 0xe00] = FALSE; + } + } + + int sum=0, k,l, bankcount; + bankcount=1<<(ROMSize-7);//Mbits + + //safety for corrupt headers + if(bankcount > 128) + bankcount = (CalculatedSize/0x8000)/4; + bankcount*=4;//to banks + bankcount<<=4;//Map banks + bankcount+=0x800;//normalize + for(k=0x800;k<(bankcount);k+=16) + { + uint8* bank=0x8000+Map[k+8]; + for(l=0;l<0x8000;l++) + sum+=bank[l]; + } + CalculatedChecksum=sum&0xFFFF; + + MapRAM (); + WriteProtectROM (); +} + +void CMemory::SetaDSPMap () +{ + int c; + int i; + int j; + int mask[4]; + for (j=0; j<4; j++) + mask[j]=0x00ff; + + mask[0]=(CalculatedSize/0x8000)-1; + + int x; + bool foundZeros; + bool pastZeros; + + for(j=0;j<3;j++) + { + x=1; + foundZeros=false; + pastZeros=false; + + mask[j+1]=mask[j]; + + while (x>0x100&&!pastZeros) + { + if(mask[j]&x) + { + x<<=1; + if(foundZeros) + pastZeros=true; + } + else + { + foundZeros=true; + pastZeros=false; + mask[j+1]|=x; + x<<=1; + } + } + } + + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; + Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; + + for (i = c + 8; i < c + 16; i++) + { + int e=3; + int d=c>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + Map [i] = Map [i + 0x800] = ROM + (((d)-1)*0x8000); + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + int e=3; + int d=(c+0x400)>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + + Map [i + 0x400] = Map [i + 0xc00] = ROM + (((d)-1)*0x8000); + } + + //only upper half is ROM + for (i = c+8; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + memset(SRAM, 0, 0x1000); + for (c=0x600;c<0x680;c+=0x10) + { + for(i=0;i<0x08;i++) + { + //where does the SETA chip access, anyway? + //please confirm this? + Map[c+0x80+i]=(uint8*)MAP_SETA_DSP; + BlockIsROM [c+0x80+i] = FALSE; + BlockIsRAM [c+0x80+i] = TRUE; + } + + for(i=0;i<0x04;i++) + { + //and this! + Map[c+i]=(uint8*)MAP_SETA_DSP; + BlockIsROM [c+i] = FALSE; + } + } + + int sum=0, k,l, bankcount; + bankcount=1<<(ROMSize-7);//Mbits + //safety for corrupt headers + if(bankcount > 128) + bankcount = (CalculatedSize/0x8000)/4; + bankcount*=4;//to banks + bankcount<<=4;//Map banks + bankcount+=0x800;//normalize + for(k=0x800;k<(bankcount);k+=16) + { + uint8* bank=0x8000+Map[k+8]; + for(l=0;l<0x8000;l++) + sum+=bank[l]; + } + CalculatedChecksum=sum&0xFFFF; + + MapRAM (); + WriteProtectROM (); +} + +void CMemory::BSLoROMMap () +{ + int c; + int i; + + if(Settings.BS) + SRAMSize=5; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) RAM; +// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; +BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; + +// Map [c + 6] = Map [c + 0x806] = (uint8 *)MAP_NONE; +// Map [c + 7] = Map [c + 0x807] = (uint8 *)MAP_NONE; + Map [c + 6] = Map [c + 0x806] = (uint8 *) RAM; +// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; +BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) RAM; +// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; +BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [(c << 11) % CalculatedSize] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + for(c=0;c<8;c++) + { + Map[(c<<4)+0x105]=(uint8*)MAP_LOROM_SRAM; + BlockIsROM [(c<<4)+0x105] = FALSE; + BlockIsRAM [(c<<4)+0x105] = TRUE; + } + + + /* // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize]; + + for (i = c + 8; i < c + 16; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [((c << 11) + 0x200000) % CalculatedSize - 0x8000]; + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + */ + for(c=1;c<=4;c++) + { + for(i=0;i<16; i++) + { + Map[0x400+i+(c<<4)]=(uint8*)MAP_LOROM_SRAM; + BlockIsRAM[0x400+i+(c<<4)]=TRUE; + BlockIsROM[0x400+i+(c<<4)]=FALSE; + } + } + + for(i=0;i<0x80;i++) + { + Map[0x700+i]=&BSRAM[0x10000*(i/16)]; + BlockIsRAM[0x700+i]=TRUE; + BlockIsROM[0x700+i]=FALSE; + } + for (i=0; i<8;i++) + { + Map[0x205+(i<<4)]=Map[0x285+(i<<4)]=Map[0x305+(i<<4)]=Map[0x385+(i<<4)]=Map[0x705+(i<<4)]; + BlockIsRAM[0x205+(i<<4)]=BlockIsRAM[0x285+(i<<4)]=BlockIsRAM[0x305+(i<<4)]=BlockIsRAM[0x385+(i<<4)]=TRUE; + BlockIsROM[0x205+(i<<4)]=BlockIsROM[0x285+(i<<4)]=BlockIsROM[0x305+(i<<4)]=BlockIsROM[0x385+(i<<4)]=FALSE; + } + for(c=0;c<8;c++) + { + Map[(c<<4)+0x005]=BSRAM-0x5000; + BlockIsROM [(c<<4)+0x005] = FALSE; + BlockIsRAM [(c<<4)+0x005] = TRUE; + } + MapRAM (); + WriteProtectROM (); + + +} + +void CMemory::HiROMMap () +{ + int i; + int c; + int j; + + int mask[4]; + for (j=0; j<4; j++) + mask[j]=0x00ff; + + mask[0]=(CalculatedSize/0x10000)-1; + + if (Settings.ForceSA1 || + (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && + (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) + { + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + } + + + int x; + bool foundZeros; + bool pastZeros; + + for(j=0;j<3;j++) + { + x=1; + foundZeros=false; + pastZeros=false; + + mask[j+1]=mask[j]; + + while (x>0x100&&!pastZeros) + { + if(mask[j]&x) + { + x<<=1; + if(foundZeros) + pastZeros=true; + } + else + { + foundZeros=true; + pastZeros=false; + mask[j+1]|=x; + x<<=1; + } + } + } + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + + if (Settings.DSP1Master) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; + } + else + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + } + + for (i = c + 8; i < c + 16; i++) + { + int e=3; + int d=c>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + Map [i] = Map [i + 0x800] = ROM + (d*0x10000); + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. + for (c = 0; c < 16; c++) + { + Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + BlockIsRAM [0x306 + (c << 4)] = TRUE; + BlockIsRAM [0x307 + (c << 4)] = TRUE; + BlockIsRAM [0xb06 + (c << 4)] = TRUE; + BlockIsRAM [0xb07 + (c << 4)] = TRUE; + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + int e=3; + int d=(c)>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + Map [i + 0x400] = Map [i + 0xc00] = ROM + (d*0x10000); + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + int bankmax=0x40+ (1<<(ROMSize-6)); + //safety for corrupt headers + if(bankmax > 128) + bankmax = 0x80; + int sum=0; + for(i=0x40;i3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + + //makes more sense to map the range here. + //ToP seems to use sram to skip intro??? + if(c>=0x300) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_HIROM_SRAM; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_HIROM_SRAM; + BlockIsRAM [6 + c] = BlockIsRAM [7 + c] = + BlockIsRAM [0x806 + c]= BlockIsRAM [0x807 + c] = TRUE; + } + else + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + + } + for (i = c + 8; i < c + 16; i++) + { + Map [i] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET0]; + Map [i + 0x800] = &ROM [((c << 12) % 0x400000) + OFFSET2]; + BlockIsROM [i] = TRUE; + BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + { + Map [i + 0x400] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET1]; + Map [i + 0x408] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET1]; + Map [i + 0xc00] = &ROM [((c << 12) %0x400000)+ OFFSET2]; + Map [i + 0xc08] = &ROM [((c << 12) % 0x400000) + OFFSET2]; + BlockIsROM [i + 0x400] = TRUE; + BlockIsROM [i + 0x408] = TRUE; + BlockIsROM [i + 0xc00] = TRUE; + BlockIsROM [i + 0xc08] = TRUE; + } + } + + if((strncmp("TALES",(char*)Map[8]+0xFFC0, 5)==0)) + { + if(((*(Map[8]+0xFFDE))==(*(Map[0x808]+0xFFDE)))) + { + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + } + } + + ROMChecksum = *(Map[8]+0xFFDE) + (*(Map[8]+0xFFDF) << 8); + ROMComplementChecksum = *(Map[8]+0xFFDC) + (*(Map[8]+0xFFDD) << 8); + +int sum=0; +for(i=0x40;i<0x80; i++) +{ + uint8 * bank_low=(uint8*)Map[i<<4]; + uint8 * bank_high=(uint8*)Map[(i<<4)+0x800]; + for (c=0;c<0x10000; c++) + { + sum+=bank_low[c]; + sum+=bank_high[c]; + } +} + +CalculatedChecksum=sum&0xFFFF; + + MapRAM (); + WriteProtectROM (); +} + +void CMemory::AlphaROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = TRUE; + } + } + + // Banks 40->7f and c0->ff + + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize]; + Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapRAM (); + WriteProtectROM (); +} + +void DetectSuperFxRamSize() +{ + if(ROM[0x7FDA]==0x33) + { + Memory.SRAMSize=ROM[0x7FBD]; + } + else + { + if(strncmp(Memory.ROMName, "STAR FOX 2", 10)==0) + { + Memory.SRAMSize=6; + } + else Memory.SRAMSize=5; + } +} + +void CMemory::SuperFXROMMap () +{ + int c; + int i; + + DetectSuperFxRamSize(); + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [0x006 + c] = Map [0x806 + c] = (uint8 *) ::SRAM - 0x6000; + Map [0x007 + c] = Map [0x807 + c] = (uint8 *) ::SRAM - 0x6000; + BlockIsRAM [0x006 + c] = BlockIsRAM [0x007 + c] = BlockIsRAM [0x806 + c] = BlockIsRAM [0x807 + c] = TRUE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 70->71, S-RAM + for (c = 0; c < 32; c++) + { + Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16); + BlockIsRAM [c + 0x700] = TRUE; + BlockIsROM [c + 0x700] = FALSE; + } + + // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K + // block is repeated twice in each 64K block. +#ifdef DS2_DMA + __dcache_writeback_all(); +#endif + for (c = 0; c < 64; c++) + { +#ifdef DS2_DMA + ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + ds2_DMAcopy_32Byte(3 /* channel: emu internal 2 */, &ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + ds2_DMA_wait(2); + ds2_DMA_wait(3); + ds2_DMA_stop(2); + ds2_DMA_stop(3); +#else + // memmove converted: Different addresses [Neb] + memcpy (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + // memmove converted: Different addresses [Neb] + memcpy (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); +#endif + } + + WriteProtectROM (); +} + +void CMemory::SA1ROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = FALSE; + } + } + + // c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i + 0xc00] = TRUE; + } + } + + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + WriteProtectROM (); + + // Now copy the map and correct it for the SA1 CPU. + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map)); + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000]; + SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE; + SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; + SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE; + } + + // Banks 60->6f + for (c = 0; c < 0x100; c++) + SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; + + BWRAM = SRAM; +} + +void CMemory::LoROM24MBSMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x200; c += 16) + { + Map [c + 0x800] = RAM; + Map [c + 0x801] = RAM; + BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000; + BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; + + for (i = c + 8; i < c + 16; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapExtraRAM (); + WriteProtectROM (); +} + +void CMemory::SufamiTurboLoROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; + + for (i = c + 8; i < c + 16; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + if (Settings.DSP1Master) + { + for (c = 0; c < 0x100; c++) + { + Map [c + 0xe00] = (uint8 *) MAP_DSP; + BlockIsROM [c + 0xe00] = FALSE; + } + } + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 60->67, S-RAM + for (c = 0; c < 0x80; c++) + { + Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; + BlockIsRAM [c + 0x600] = TRUE; + BlockIsROM [c + 0x600] = FALSE; + } + + WriteProtectROM (); +} + +#if 0 + +//untested!! +void CMemory::SameGameMap () +{ + int i; + int c; + int j; + + int mask[4]; + int mask2[4]; + for (j=0; j<4; j++) + mask[j]=mask2[j]=0x00ff; + + mask[0]=(CalculatedSize/0x10000)-1; + mask2[0]=(Slot1Size/0x10000)-1; + + int x; + bool foundZeros; + bool pastZeros; + + for(j=0;j<3;j++) + { + x=1; + foundZeros=false; + pastZeros=false; + + mask[j+1]=mask[j]; + + while (x>0x100&&!pastZeros) + { + if(mask[j]&x) + { + x<<=1; + if(foundZeros) + pastZeros=true; + } + else + { + foundZeros=true; + pastZeros=false; + mask[j+1]|=x; + x<<=1; + } + } + } + + for(j=0;j<3;j++) + { + x=1; + foundZeros=false; + pastZeros=false; + + mask2[j+1]=mask2[j]; + + while (x>0x100&&!pastZeros) + { + if(mask2[j]&x) + { + x<<=1; + if(foundZeros) + pastZeros=true; + } + else + { + foundZeros=true; + pastZeros=false; + mask2[j+1]|=x; + x<<=1; + } + } + } + + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + } + + // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. + for (c = 0; c < 16; c++) + { + Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + BlockIsRAM [0x306 + (c << 4)] = TRUE; + BlockIsRAM [0x307 + (c << 4)] = TRUE; + BlockIsRAM [0xb06 + (c << 4)] = TRUE; + BlockIsRAM [0xb07 + (c << 4)] = TRUE; + } + + for c=0; c<0x200; c+=16) + { + for(i=0;i<8;i++) + { + int e=3; + int d=c>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + + int f=3; + int g=c>>4; + while(g>mask2[0]) + { + g&=mask2[f]; + f--; + } + + //stuff in HiROM areas + Map[c+0x400+i]=&ROM[d*0x10000]; + Map[c+0xC00+i]=&ROM[d*0x10000]; + //MINI + Map[c+0x600+i]=&ROMOffset1[g*0x10000]; + Map[c+0xE00+i]=&ROMOffset1[g*0x10000]; + + } + for(i=8;i<16;i++) + { + int e=3; + int d=c>>4; + while(d>mask[0]) + { + d&=mask[e]; + e--; + } + + int f=3; + int g=c>>4; + while(g>mask2[0]) + { + g&=mask2[f]; + f--; + } + + + //all stuff + //BASE + Map[c+i]=&ROM[d*0x10000]; + Map[c+0x800+i]=&ROM[d*0x10000]; + Map[c+0x400+i]=&ROM[d*0x10000]; + Map[c+0xC00+i]=&ROM[d*0x10000]; + //MINI + Map[c+0x200+i]=&ROMOffset1[g*0x10000]; + Map[c+0xA00+i]=&ROMOffset1[g*0x10000]; + Map[c+0x600+i]=&ROMOffset1[g*0x10000]; + Map[c+0xE00+i]=&ROMOffset1[g*0x10000]; + } + + } + + int bankmax=0x40+ (1<<(ROMSize-6)); + //safety for corrupt headers + if(bankmax > 128) + bankmax = 0x80; + int sum=0; + for(i=0x40;i3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + + // Banks 40->4f (was 7f, but SNES docs and GNext overdumping shows nothing here.) + for (c = 0; c < 0x100; c += 16) + { + for (i = c; i < c + 16; i++) + Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = FALSE; + } + } + + for (c = 0; c < 0x100; c += 16) + { + for (i = c; i < c + 16; i++) + Map [i + 0x700] = (uint8 *) &ROMOffset1 [(c << 12) & (Slot1Size-1)]; + } + + // c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i + 0xc00] = TRUE; + } + } + + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + WriteProtectROM (); + + // Now copy the map and correct it for the SA1 CPU. + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map)); + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000]; + SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE; + SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; + SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE; + } + + // Banks 60->6f + for (c = 0; c < 0x100; c++) + SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; + + BWRAM = SRAM; +} + +void CMemory::SufamiTurboAltROMMap () +{ + int c; + int i; + + if(Slot1Size!=0) + Slot1SRAMSize=(1<<((uint8)ROMOffset1[0x32]))*1024; + else Slot1Size=0x8000; + if(Slot2Size!=0) + Slot2SRAMSize=(1<<((uint8)ROMOffset2[0x32]))*1024; +else Slot2Size=0x8000; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + +// for (i = c + 8; i < c + 16; i++) +// { +// Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; +// BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; +// } + + } + + //Map Bios + + for (c=0; c<0x200; c+=16) + { + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [((c>>4)*0x8000)%CalculatedSize] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + + } + + + for (c=0x200; c<0x400; c+=16) + { + for (i = c + 8; i < c + 16; i++) + { + if(Slot1Size!=0) + { + Map [i] = Map [i + 0x800] = &ROMOffset1 [(((c>>4)*0x8000)%Slot1Size)] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; + } + + } + + for (c=0x400; c<0x600; c+=16) + { + for (i = c; i < c + 8; i++) + { + if(Slot2Size!=0) + { + Map [i] = Map [i + 0x800] = &ROMOffset2[(((c>>4)*0x8000)%Slot2Size)]; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; + + } + for (i = c + 8; i < c + 16; i++) + { + if(Slot2Size!=0) + { + Map [i] = Map [i + 0x800] = &ROMOffset2[(((c>>4)*0x8000)%Slot2Size)] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; + + } + + } + + // Banks 60->67 (7F?), S-RAM + if(Slot1SRAMSize!=0) + { + for (c = 0; c < 0x100; c++) + { + Map [c + 0xE00] = Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; + BlockIsRAM [c + 0xE00] = BlockIsRAM [c + 0x600] = TRUE; + BlockIsROM [c + 0xE00] = BlockIsROM [c + 0x600] = FALSE; + } + } + if(Slot2SRAMSize!=0) + { + for (c = 0; c < 0x100; c++) + { + Map [c + 0xF00] = Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; + BlockIsRAM [c + 0xF00] = BlockIsRAM [c + 0x700] = TRUE; + BlockIsROM [c + 0xF00] = BlockIsROM [c + 0x700] = FALSE; + } + } + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Map [c + 0x7e0] = RAM; + Map [c + 0x7f0] = RAM + 0x10000; + BlockIsRAM [c + 0x7e0] = TRUE; + BlockIsRAM [c + 0x7f0] = TRUE; + BlockIsROM [c + 0x7e0] = FALSE; + BlockIsROM [c + 0x7f0] = FALSE; + } + + WriteProtectROM (); +} +#endif + + +void CMemory::SRAM512KLoROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; + + for (i = c + 8; i < c + 16; i++) + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapExtraRAM (); + WriteProtectROM (); +} + +void CMemory::BSHiROMMap () +{ + int c; + int i; + + SRAMSize=5; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + // XXX: How large is SRAM?? + Map [c + 5] = Map [c + 0x805] = (uint8 *) RAM; +// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; + BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; +// Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; +// Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; + + Map [c + 6] = Map [c + 0x806] = (uint8 *) RAM; +// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; +BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; + Map [c + 7] = Map [c + 0x807] = (uint8 *) RAM; +// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; +BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM + // XXX: How large is PSRAM? + + //not adjusted, but The Dumper says "4 Mbits" + for (c = 0x600; c < 0x7e0; c += 16) + { + for (i = c; i < c + 8; i++) + { + Map [i] = &ROM [0x400000 + (c << 11)]; + BlockIsRAM [i] = TRUE; + } + for (i = c + 8; i < c + 16; i++) + { + Map [i] = &ROM [0x400000 + (c << 11) - 0x8000]; + BlockIsRAM [i] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + for(i=0;i<0x80;i++) + { + Map[0x700+i]=&BSRAM[0x10000*(i/16)]; + BlockIsRAM[0x700+i]=TRUE; + BlockIsROM[0x700+i]=FALSE; + } + for (i=0; i<8;i++) + { + Map[0x205+(i<<4)]=Map[0x285+(i<<4)]=Map[0x305+(i<<4)]=Map[0x385+(i<<4)]=Map[0x705+(i<<4)]; + BlockIsRAM[0x205+(i<<4)]=BlockIsRAM[0x285+(i<<4)]=BlockIsRAM[0x305+(i<<4)]=BlockIsRAM[0x385+(i<<4)]=TRUE; + BlockIsROM[0x205+(i<<4)]=BlockIsROM[0x285+(i<<4)]=BlockIsROM[0x305+(i<<4)]=BlockIsROM[0x385+(i<<4)]=FALSE; + } + + MapRAM (); + WriteProtectROM (); +} + +void CMemory::JumboLoROMMap (bool8 Interleaved) +{ + int c; + int i; + + uint32 OFFSET0 = 0x400000; + uint32 OFFSET1 = 0x400000; + uint32 OFFSET2 = 0x000000; + + if (Interleaved) + { + OFFSET0 = 0x000000; + OFFSET1 = 0x000000; + OFFSET2 = CalculatedSize-0x400000; //changed to work with interleaved DKJM2. + } + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + if (Settings.DSP1Master) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; + } + else if (Settings.C4) + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; + Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; + } + else + { + Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; + Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; + } + + for (i = c + 8; i < c + 16; i++) + { + Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0] - 0x8000; + Map [i + 0x800] = &ROM [((c << 11) % (0x400000)) + OFFSET2] - 0x8000; + BlockIsROM [i + 0x800] = BlockIsROM [i] = TRUE; + } + } + + if (Settings.DSP1Master) + { + // Banks 30->3f and b0->bf + for (c = 0x300; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map [i + 0x800] = (uint8 *) MAP_DSP; + BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; + } + } + } + + // Banks 40->7f and c0->ff + for (c = 0x400; c < 0x800; c += 16) + { + //updated mappings to correct A15 mirroring + for (i = c; i < c + 8; i++) + { + Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0]; + Map [i + 0x800] = &ROM [((c << 11) % 0x400000) +OFFSET2]; + } + + for (i = c + 8; i < c + 16; i++) + { + Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0] - 0x8000; + Map [i + 0x800] = &ROM [((c << 11) % 0x400000) + OFFSET2 ] - 0x8000; + } + + for (i = c; i < c + 16; i++) + { + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + //ROM type has to be 64 Mbit header! + int sum=0, k,l; + for(k=0;k<256;k++) + { + uint8* bank=0x8000+Map[8+(k<<4)];//use upper half of the banks, and adjust for LoROM. + for(l=0;l<0x8000;l++) + sum+=bank[l]; + } + CalculatedChecksum=sum&0xFFFF; + + MapRAM (); + WriteProtectROM (); +} + +void CMemory::SPC7110HiROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Map [c + 0] = Map [c + 0x800] = RAM; + BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; + Map [c + 1] = Map [c + 0x801] = RAM; + BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + + Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; + Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; + Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; + Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + + Map [c + 6] /*= Map [c + 0x806]*/ = (uint8 *) MAP_HIROM_SRAM; + Map [c + 7] /*= Map [c + 0x807]*/ = (uint8 *) MAP_HIROM_SRAM; + Map [c + 0x806]=Map [c + 0x807]= (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; + } + } + + // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. + for (c = 0; c < 16; c++) + { + Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Map [0xb06 + (c << 4)] = (uint8 *) MAP_NONE; + Map [0xb07 + (c << 4)] = (uint8 *) MAP_NONE; + BlockIsRAM [0x306 + (c << 4)] = TRUE; + BlockIsRAM [0x307 + (c << 4)] = TRUE; + // BlockIsRAM [0xb06 + (c << 4)] = TRUE; + // BlockIsRAM [0xb07 + (c << 4)] = TRUE; + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; + } + } + + for (c=0;c<0x10;c++) + { + Map [0x500+c]=(uint8 *)MAP_SPC7110_DRAM; + BlockIsROM [0x500+c]=TRUE; + } + + for (c=0;c<0x100;c++) + { + Map [0xD00+c] = (uint8 *) MAP_SPC7110_ROM; + Map [0xE00+c] = (uint8 *) MAP_SPC7110_ROM; + Map [0xF00+c] = (uint8 *) MAP_SPC7110_ROM; + BlockIsROM [0xD00+c] = BlockIsROM [0xE00+c] = BlockIsROM [0xF00+c] = TRUE; + + } + S9xSpc7110Init(); + +int sum=0; +for(i=0;i<(int)CalculatedSize; i++) +{ + sum+=ROM[i]; +} + +if(CalculatedSize==0x300000) + sum<<=1; +CalculatedChecksum=sum&0xFFFF; + + MapRAM (); + WriteProtectROM (); +} +void CMemory::SPC7110Sram(uint8 newstate) +{ + if(newstate&0x80) + { + Memory.Map[6]=(uint8 *)MAP_HIROM_SRAM; + Memory.Map[7]=(uint8 *)MAP_HIROM_SRAM; + Memory.Map[0x306]=(uint8 *)MAP_HIROM_SRAM; + Memory.Map[0x307]=(uint8 *)MAP_HIROM_SRAM; + + + } + else + { + Memory.Map[6]=(uint8 *)MAP_RONLY_SRAM; + Memory.Map[7]=(uint8 *)MAP_RONLY_SRAM; + Memory.Map[0x306]=(uint8 *)MAP_RONLY_SRAM; + Memory.Map[0x307]=(uint8 *)MAP_RONLY_SRAM; + } +} +const char *CMemory::TVStandard () +{ + return (Settings.PAL ? "PAL" : "NTSC"); +} + +const char *CMemory::Speed () +{ + return (ROMSpeed & 0x10 ? "120ns" : "200ns"); +} + +const char *CMemory::MapType () +{ + return (HiROM ? "HiROM" : "LoROM"); +} + +const char *CMemory::StaticRAMSize () +{ + static char tmp [20]; + + if (Memory.SRAMSize > 16) + return ("Corrupt"); + sprintf (tmp, "%dKB", (SRAMMask + 1) / 1024); + return (tmp); +} + +const char *CMemory::Size () +{ + static char tmp [20]; + + if (ROMSize < 7 || ROMSize - 7 > 23) + return ("Corrupt"); + sprintf (tmp, "%dMbits", 1 << (ROMSize - 7)); + return (tmp); +} + +const char *CMemory::KartContents () +{ + static char tmp [30]; + static const char *CoPro [16] = { + "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6", + "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12", + "CoPro#13", "CoPro#14", "CoPro-Custom" + }; + static const char *Contents [3] = { + "ROM", "ROM+RAM", "ROM+RAM+BAT" + }; + if (ROMType == 0&&!Settings.BS) + return ("ROM only"); + + sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]); + + + if(Settings.BS) + sprintf (tmp, "%s+%s", tmp, "BSX"); + else if(Settings.SPC7110&&Settings.SPC7110RTC) + sprintf (tmp, "%s+%s", tmp, "SPC7110+RTC"); + else if(Settings.SPC7110) + sprintf (tmp, "%s+%s", tmp, "SPC7110"); + else if(Settings.SETA!=0) + { + switch(Settings.SETA) + { + case ST_010: + sprintf (tmp, "%s+%s", tmp, "ST-010"); + break; + case ST_011: + sprintf (tmp, "%s+%s", tmp, "ST-011"); + break; + + case ST_018: + sprintf (tmp, "%s+%s", tmp, "ST-018"); + break; + + } + } + else if ((ROMType & 0xf) >= 3) + sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]); + + return (tmp); +} + +const char *CMemory::MapMode () +{ + static char tmp [4]; + sprintf (tmp, "%02x", ROMSpeed & ~0x10); + return (tmp); +} + +const char *CMemory::ROMID () +{ + return (ROMId); +} + +void CMemory::ApplyROMFixes () +{ +#ifdef __W32_HEAP + if(_HEAPOK!=_heapchk()) + MessageBox(GUI.hWnd, "CMemory::ApplyROMFixes", "Heap Corrupt", MB_OK); +#endif + + //don't steal my work! -MK + if(ROMCRC32 == 0x1B4A5616 && strncmp(ROMName, "RUDORA NO HIHOU", 15)==0) + { + strncpy(ROMName, "THIS SCRIPT WAS STOLEN", 22); + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + } + + /* + HACKS NSRT can fix that we hadn't detected before. +[14:25:13] <@Nach> case 0x0c572ef0: //So called Hook (US)(2648) +[14:25:13] <@Nach> case 0x6810aa95: //Bazooka Blitzkreig swapped sizes hack -handled +[14:25:17] <@Nach> case 0x61E29C06: //The Tick region hack +[14:25:19] <@Nach> case 0x1EF90F74: //Jikkyou Keiba Simulation Stable Star PAL hack +[14:25:23] <@Nach> case 0x4ab225b5: //So called Krusty's Super Fun House (E) +[14:25:25] <@Nach> case 0x77fd806a: //Donkey Kong Country 2 (E) v1.1 bad dump -handled +[14:25:27] <@Nach> case 0x340f23e5: //Donkey Kong Country 3 (U) copier hack - handled + */ + + if(ROMCRC32==0x6810aa95 || ROMCRC32==0x340f23e5 || ROMCRC32==0x77fd806a || + strncmp (ROMName, "HIGHWAY BATTLE 2", 16)==0 || + (strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 && ROM[0x7FDA]==0)) + { + Settings.DisplayColor=BUILD_PIXEL(31,0,0); + SET_UI_COLOR(255,0,0); + } + + //Ambiguous chip function pointer assignments + + //DSP switching: + if(strncmp(ROMName, "DUNGEON MASTER", 14)==0) + { + //Set DSP-2 + SetDSP=&DSP2SetByte; + GetDSP=&DSP2GetByte; + } + +#ifdef DSP_DUMMY_LOOPS + if(strncmp(ROMName, "SD\x0b6\x0de\x0dd\x0c0\x0de\x0d1GX", 10)==0) + { + //Set DSP-3 + SetDSP=&DSP3SetByte; + GetDSP=&DSP3GetByte; + } +#endif + + if(strncmp(ROMName, "TOP GEAR 3000", 13)==0 + ||strncmp(ROMName, "PLANETS CHAMP TG3000", 20)==0) + { + //Set DSP-4 + SetDSP=&DSP4SetByte; + GetDSP=&DSP4GetByte; + } + + //memory map corrections + if(strncmp(ROMName, "XBAND",5)==0) + { + for (int c=0xE00;c<0xE10;c++) + { + Map [c] = (uint8 *) MAP_LOROM_SRAM; + BlockIsRAM [c] = TRUE; + BlockIsROM [c] = FALSE; + } + WriteProtectROM (); + } + + //not MAD-1 compliant + if(strcmp (ROMName, "WANDERERS FROM YS") == 0) + { + for(int c=0;c<0xE0;c++) + { + Map[c+0x700]=(uint8*)MAP_LOROM_SRAM; + BlockIsROM[c+0x700]=FALSE; + BlockIsRAM[c+0x700]=TRUE; + } + WriteProtectROM(); + } + + if (strcmp (ROMName, "GOGO ACKMAN3") == 0 || + strcmp (ROMName, "HOME ALONE") == 0) + { + // Banks 00->3f and 80->bf + for (int c = 0; c < 0x400; c += 16) + { + Map [c + 6] = Map [c + 0x806] = SRAM; + Map [c + 7] = Map [c + 0x807] = SRAM; + BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE; + BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE; + BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; + BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; + } + WriteProtectROM (); + } + + if (strcmp (ROMName, "RADICAL DREAMERS") == 0 || + strcmp (ROMName, "TREASURE CONFLIX") == 0) + { + int c; + + for (c = 0; c < 0x80; c++) + { + Map [c + 0x700] = ROM + 0x200000 + 0x1000 * (c & 0xf0); + BlockIsRAM [c + 0x700] = TRUE; + BlockIsROM [c + 0x700] = FALSE; + } + for (c = 0; c < 0x400; c += 16) + { + Map [c + 5] = Map [c + 0x805] = ROM + 0x300000; + BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; + } + WriteProtectROM (); + } + + if(strncmp(ROMName, "WAR 2410", 8)==0) + { + Map [0x005] = (uint8 *) RAM; + BlockIsRAM [0x005] = TRUE; + BlockIsROM [0x005] = FALSE; + } + + if (strcmp (ROMName, "BATMAN--REVENGE JOKER") == 0) + { + Memory.HiROM = FALSE; + Memory.LoROM = TRUE; + LoROMMap (); + } + + + //NMI hacks + CPU.NMITriggerPoint = 4; + if (strcmp (ROMName, "CACOMA KNIGHT") == 0) + CPU.NMITriggerPoint = 25; + + //Disabling a speed-up + // Games which spool sound samples between the SNES and sound CPU using + // H-DMA as the sample is playing. + if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 || + strcmp (ROMName, "PRIMAL RAGE") == 0 || + strcmp (ROMName, "CLAY FIGHTER") == 0 || + strcmp (ROMName, "ClayFighter 2") == 0 || + strncasecmp (ROMName, "MADDEN", 6) == 0 || + strncmp (ROMName, "NHL", 3) == 0 || + strcmp (ROMName, "WeaponLord") == 0|| + strncmp(ROMName, "WAR 2410", 8)==0) + { + Settings.Shutdown = FALSE; + } + + + //APU timing hacks + + // Stunt Racer FX + if (strcmp (ROMId, "CQ ") == 0 || + // Illusion of Gaia + strncmp (ROMId, "JG", 2) == 0 || + strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0) + { + IAPU.OneCycle = 13; + } + + // RENDERING RANGER R2 + if (strcmp (ROMId, "AVCJ") == 0 || + //Mark Davis + strncmp(ROMName, "THE FISHING MASTER", 18)==0 || //needs >= actual APU timing. (21 is .002 Mhz slower) + // Star Ocean + strncmp (ROMId, "ARF", 3) == 0 || + // Tales of Phantasia + strncmp (ROMId, "ATV", 3) == 0 || + // Act Raiser 1 & 2 + strncasecmp (ROMName, "ActRaiser", 9) == 0 || + // Soulblazer + strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 || + strcmp (ROMName, "SOULBLADER - 1") == 0 || + + // Terranigma + strncmp (ROMId, "AQT", 3) == 0 || + // Robotrek + strncmp (ROMId, "E9 ", 3) == 0 || + strcmp (ROMName, "SLAP STICK 1 JPN") == 0 || + // ZENNIHON PURORESU2 + strncmp (ROMId, "APR", 3) == 0 || + // Bomberman 4 + strncmp (ROMId, "A4B", 3) == 0 || + // UFO KAMEN YAKISOBAN + strncmp (ROMId, "Y7 ", 3) == 0 || + strncmp (ROMId, "Y9 ", 3) == 0 || + // Panic Bomber World + strncmp (ROMId, "APB", 3) == 0 || + ((strncmp (ROMName, "Parlor", 6) == 0 || + strcmp (ROMName, "HEIWA Parlor!Mini8") == 0 || + strncmp (ROMName, "SANKYO Fever! ̨°ÊÞ°!", 21) == 0) && + strcmp (CompanyId, "A0") == 0) || + strcmp (ROMName, "DARK KINGDOM") == 0 || + strcmp (ROMName, "ZAN3 SFC") == 0 || + strcmp (ROMName, "HIOUDEN") == 0 || + strcmp (ROMName, "ÃݼɳÀ") == 0 || //Tenshi no Uta + strcmp (ROMName, "FORTUNE QUEST") == 0 || + strcmp (ROMName, "FISHING TO BASSING") == 0 || + strncmp (ROMName, "TokyoDome '95Battle 7", 21) == 0 || + strcmp (ROMName, "OHMONO BLACKBASS") == 0 || + strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 || + strcmp (ROMName, "MASTERS") ==0 || //Augusta 2 J + strcmp (ROMName, "SFC ¶ÒÝײÀÞ°") == 0 || //Kamen Rider + strncmp (ROMName, "LETs PACHINKO(", 14) == 0) //A set of BS games + { + IAPU.OneCycle = 15; + } + + + //Specific game fixes + + Settings.StarfoxHack = strcmp (ROMName, "STAR FOX") == 0 || + strcmp (ROMName, "STAR WING") == 0; + Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 || + strcmp (ROMName, "DIRT RACER") == 0 || + Settings.StarfoxHack; + + + if((strcmp(ROMName, "LEGEND")==0&&!Settings.PAL)|| + strcmp(ROMName, "King Arthurs World")==0) + { + SNESGameFixes.EchoOnlyOutput=TRUE; + } + + + Settings.DaffyDuck = (strcmp (ROMName, "DAFFY DUCK: MARV MISS") == 0) || + (strcmp (ROMName, "ROBOCOP VS THE TERMIN") == 0) || + (strcmp (ROMName, "ROBOCOP VS TERMINATOR") == 0); //ROBOCOP VS THE TERMIN + Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; + + //OAM hacks because we don't fully understand the + //behavior of the SNES. + + //Totally wacky display... + //seems to need a disproven behavior, so + //we're definitely overlooking some other bug? + if(strncmp(ROMName, "UNIRACERS", 9)==0) + SNESGameFixes.Uniracers=true; + + + //is this even useful now? + if (strcmp (ROMName, "ALIENS vs. PREDATOR") == 0) + SNESGameFixes.alienVSpredetorFix = TRUE; + + if (strcmp (ROMName, "½°Ȩ̂߰нÀ") == 0 || //Super Famista + strcmp (ROMName, "½°Ȩ̂߰нÀ 2") == 0 || //Super Famista 2 + strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 || + strcmp (ROMName, "GANBA LEAGUE") == 0) + { + SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE; + } + + if (strcmp (ROMName, "FURAI NO SIREN") == 0) + SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE; + + //CPU timing hacks + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * + Settings.CyclesPercentage) / 100; + + //no need to ifdef for right now... +//#ifdef HDMA_HACKS + + // A Couple of HDMA related hacks - Lantus + if ((strcmp(ROMName, "SFX SUPERBUTOUDEN2")==0) || + (strcmp(ROMName, "ALIEN vs. PREDATOR")==0) || + (strcmp(ROMName, "STONE PROTECTORS")==0) || + (strcmp(ROMName, "SUPER BATTLETANK 2")==0)) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 130) / 100; + + if(strcmp(ROMName, "HOME IMPROVEMENT")==0) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 200) / 100; + + // End HDMA hacks +//#endif + + + if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100) + // Street Racer + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100; + + // Power Rangers Fight + if (strncmp (ROMId, "A3R", 3) == 0 || + // Clock Tower + strncmp (ROMId, "AJE", 3) == 0) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100; + + + if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100) + // Mortal Kombat 3. Fixes cut off speech sample + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; + + //Darkness Beyond Twilight + //Crimson beyond blood that flows + //buried in the stream of time + //is where your power grows + //I pledge myself to conquer + //all the foes who stand + //before the might gift betsowed + //in my unworthy hand + if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 && + Settings.CyclesPercentage == 100) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100; + + +#ifdef DETECT_NASTY_FX_INTERLEAVE +//XXX: Test without these. Win32 port indicates they aren't needed? +//Apparently are needed! + if (strcmp (ROMName, "WILD TRAX") == 0 || + strcmp (ROMName, "STAR FOX 2") == 0 || + strcmp (ROMName, "YOSSY'S ISLAND") == 0 || + strcmp (ROMName, "YOSHI'S ISLAND") == 0) + CPU.TriedInterleavedMode2 = TRUE; +#endif + + // Start Trek: Deep Sleep 9 + if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; + + + //SA-1 Speedup settings + SA1.WaitAddress = NULL; + SA1.WaitByteAddress1 = NULL; + SA1.WaitByteAddress2 = NULL; + + /* Bass Fishing */ + if (strcmp (ROMId, "ZBPJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1; + SA1.WaitByteAddress1 = FillRAM + 0x304a; + } + /* DAISENRYAKU EXPERTWW2 */ + if (strcmp (ROMId, "AEVJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + /* debjk2 */ + if (strcmp (ROMId, "A2DJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62; + } + /* Dragon Ballz HD */ + if (strcmp (ROMId, "AZIJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x008083 >> MEMMAP_SHIFT] + 0x8083; + SA1.WaitByteAddress1 = FillRAM + 0x3020; + } + /* SFC SDGUNDAMGNEXT */ + if (strcmp (ROMId, "ZX3J") == 0) + { + SA1.WaitAddress = SA1.Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2; + SA1.WaitByteAddress1 = FillRAM + 0x30c4; + } + /* ShougiNoHanamichi */ + if (strcmp (ROMId, "AARJ") == 0) + { + SA1.WaitAddress = SA1.Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a; + SA1.WaitByteAddress1 = SRAM + 0x0c64; + SA1.WaitByteAddress2 = SRAM + 0x0c66; + } + /* KATO HIFUMI9DAN SYOGI */ + if (strcmp (ROMId, "A23J") == 0) + { + SA1.WaitAddress = SA1.Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037; + SA1.WaitByteAddress1 = SRAM + 0x0c06; + SA1.WaitByteAddress2 = SRAM + 0x0c08; + } + /* idaten */ + if (strcmp (ROMId, "AIIJ") == 0) + { + SA1.WaitAddress = SA1.Map [0xc100be >> MEMMAP_SHIFT] + 0x00be; + SA1.WaitByteAddress1 = SRAM + 0x1002; + SA1.WaitByteAddress2 = SRAM + 0x1004; + } + /* igotais */ + if (strcmp (ROMId, "AITJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7; + } + /* J96 DREAM STADIUM */ + if (strcmp (ROMId, "AJ6J") == 0) + { + SA1.WaitAddress = SA1.Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a; + } + /* JumpinDerby */ + if (strcmp (ROMId, "AJUJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926; + } + /* JKAKINOKI SHOUGI */ + if (strcmp (ROMId, "AKAJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070; + } + /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */ + if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0) + { + SA1.WaitAddress = SA1.Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4; + SA1.WaitByteAddress1 = SRAM + 0x72a4; + } + /* KIRBY SUPER DELUXE JAP */ + if (strcmp (ROMId, "AKFJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + /* KIRBY SUPER DELUXE US */ + if (strcmp (ROMId, "AKFE") == 0) + { + SA1.WaitAddress = SA1.Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + /* SUPER MARIO RPG JAP & US */ + if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0) + { + SA1.WaitAddress = SA1.Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + /* marvelous.zip */ + if (strcmp (ROMId, "AVRJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2; + SA1.WaitByteAddress1 = FillRAM + 0x3024; + } + /* AUGUSTA3 MASTERS NEW */ + if (strcmp (ROMId, "AO3J") == 0) + { + SA1.WaitAddress = SA1.Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + /* OSHABERI PARODIUS */ + if (strcmp (ROMId, "AJOJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5; + } + /* PANIC BOMBER WORLD */ + if (strcmp (ROMId, "APBJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x00857a >> MEMMAP_SHIFT] + 0x857a; + } + /* PEBBLE BEACH NEW */ + if (strcmp (ROMId, "AONJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + /* PGA EUROPEAN TOUR */ + if (strcmp (ROMId, "AEPE") == 0) + { + SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + /* PGA TOUR 96 */ + if (strcmp (ROMId, "A3GE") == 0) + { + SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + /* POWER RANGERS 4 */ + if (strcmp (ROMId, "A4RE") == 0) + { + SA1.WaitAddress = SA1.Map [0x009899 >> MEMMAP_SHIFT] + 0x9899; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + /* PACHISURO PALUSUPE */ + if (strcmp (ROMId, "AGFJ") == 0) + { + // Never seems to turn on the SA-1! + } + /* SD F1 GRAND PRIX */ + if (strcmp (ROMId, "AGFJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc; + } + /* SHOUGI MARJONG */ + if (strcmp (ROMId, "ASYJ") == 0) + { + SA1.WaitAddress = SA1.Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc; + SA1.WaitByteAddress1 = SRAM + 0x7ffe; + SA1.WaitByteAddress2 = SRAM + 0x7ffc; + } + /* shogisai2 */ + if (strcmp (ROMId, "AX2J") == 0) + { + SA1.WaitAddress = SA1.Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675; + } + + /* SHINING SCORPION */ + if (strcmp (ROMId, "A4WJ") == 0) + { + SA1.WaitAddress = SA1.Map [0xc048be >> MEMMAP_SHIFT] + 0x48be; + } + /* SHIN SHOUGI CLUB */ + if (strcmp (ROMId, "AHJJ") == 0) + { + SA1.WaitAddress = SA1.Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a; + SA1.WaitByteAddress1 = SRAM + 0x0806; + SA1.WaitByteAddress2 = SRAM + 0x0808; + } + + + //Other + + // Additional game fixes by sanmaiwashi ... + if (strcmp (ROMName, "SFX ŲĶÞÝÀÞÑÓɶÞÀØ 1") == 0) //Gundam Knight Story + { + bytes0x2000 [0xb18] = 0x4c; + bytes0x2000 [0xb19] = 0x4b; + bytes0x2000 [0xb1a] = 0xea; + SNESGameFixes.SRAMInitialValue = 0x6b; + } + + + // HITOMI3 + if (strcmp (ROMName, "HITOMI3") == 0) + { + Memory.SRAMSize = 1; + SRAMMask = Memory.SRAMSize ? + ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; + } + + //sram value fixes + if (strcmp (Memory.ROMName, "SUPER DRIFT OUT") == 0 || + strcmp(Memory.ROMName, "SATAN IS OUR FATHER!") == 0 || + strcmp (ROMName, "goemon 4") == 0) + SNESGameFixes.SRAMInitialValue = 0x00; + +#if 0 + if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0) + { + for (c = 0x200; c < 0x400; c += 16) + { + for (int i = c; i < c + 16; i++) + { + Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000]; + BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE; + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE; + } + } + WriteProtectROM (); + } +#endif + +#define RomPatch(adr,ov,nv) \ + if (ROM [adr] == ov) \ + ROM [adr] = nv + + + // Love Quest + if (strcmp (ROMName, "LOVE QUEST") == 0) + { + RomPatch (0x1385ec, 0xd0, 0xea); + RomPatch (0x1385ed, 0xb2, 0xea); + } + //BNE D0 into nops + + //seems like the next instruction is a BRA + //otherwise, this one's too complex for MKendora + // Nangoku Syonen Papuwa Kun + if (strcmp (ROMName, "NANGOKUSYONEN PAPUWA") == 0) + RomPatch (0x1f0d1, 0xa0, 0x6b); + //turns an LDY into an RTL? + + //this is a cmp on $00:2140 + // Super Batter Up + if (strcmp (ROMName, "Super Batter Up") == 0) + { + RomPatch (0x27ae0, 0xd0, 0xea); + RomPatch (0x27ae1, 0xfa, 0xea); + } + //BNE +} + +// Read variable size MSB int from a file +static long ReadInt (FILE *f, unsigned nbytes) +{ + long v = 0; + while (nbytes--) + { + int c = fgetc(f); + if (c == EOF) + return -1; + v = (v << 8) | (c & 0xFF); + } + return (v); +} + +#define IPS_EOF 0x00454F46l + +void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, + int32 &rom_size) +{ + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char name [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char fname [_MAX_PATH + 1]; + FILE *patch_file = NULL; + long offset = header ? 512 : 0; + + _splitpath (rom_filename, drive, dir, name, ext); + _makepath (fname, drive, dir, name, "ips"); + + if (!(patch_file = fopen (fname, "rb"))) + { + if (!(patch_file = fopen (S9xGetFilename (".ips"), "rb"))) + return; + } + + if (fread ((unsigned char*)fname, 1, 5, patch_file) != 5 || + strncmp (fname, "PATCH", 5) != 0) + { + fclose (patch_file); + return; + } + + int32 ofs; + + for (;;) + { + long len; + long rlen; + int rchar; + + ofs = ReadInt (patch_file, 3); + if (ofs == -1) + goto err_eof; + + if (ofs == IPS_EOF) + break; + + ofs -= offset; + + len = ReadInt (patch_file, 2); + if (len == -1) + goto err_eof; + + /* Apply patch block */ + if (len) + { + if (ofs + len > MAX_ROM_SIZE) + goto err_eof; + + while (len--) + { + rchar = fgetc (patch_file); + if (rchar == EOF) + goto err_eof; + ROM [ofs++] = (uint8) rchar; + } + if (ofs > rom_size) + rom_size = ofs; + } + else + { + rlen = ReadInt (patch_file, 2); + if (rlen == -1) + goto err_eof; + + rchar = fgetc (patch_file); + if (rchar == EOF) + goto err_eof; + + if (ofs + rlen > MAX_ROM_SIZE) + goto err_eof; + + while (rlen--) + ROM [ofs++] = (uint8) rchar; + + if (ofs > rom_size) + rom_size = ofs; + } + } + + // Check if ROM image needs to be truncated + ofs = ReadInt (patch_file, 3); + if (ofs != -1 && ofs - offset < rom_size) + { + // Need to truncate ROM image + rom_size = ofs - offset; + } + fclose (patch_file); + return; + +err_eof: + if (patch_file) + fclose (patch_file); +} + +int is_bsx(unsigned char *p) +{ + unsigned c; + + if ( p[0x19] & 0x4f ) + goto notbsx; + c = p[0x1a]; + if ( (c != 0x33) && (c != 0xff) ) // 0x33 = Manufacturer: Nintendo + goto notbsx; + c = (p[0x17] << 8) | p[0x16]; + if ( (c != 0x0000) && (c != 0xffff) ) + { + if ( (c & 0x040f) != 0 ) + goto notbsx; + if ( (c & 0xff) > 0xc0 ) + goto notbsx; + } + c = p[0x18]; + if ( (c & 0xce) || ((c & 0x30)==0) ) + goto notbsx; + if ( (p[0x15] & 0x03) != 0 ) + goto notbsx; + c = p[0x13]; + if ( (c != 0x00) && (c != 0xff) ) + goto notbsx; + if ( p[0x14] != 0x00 ) + goto notbsx; + if ( bs_name(p) != 0 ) + goto notbsx; + return 0; // It's a Satellaview ROM! +notbsx: + return -1; +} +int bs_name(unsigned char *p) +{ + unsigned c; + int lcount; + int numv; // number of valid name characters seen so far + numv = 0; + for ( lcount = 16; lcount > 0; lcount-- ) + { + if ( check_char( c = *p++ ) != 0 ) + { + c = *p++; + if ( c < 0x20 ) + { + if ( (numv != 0x0b) || (c != 0) ) // Dr. Mario Hack + goto notBsName; + } + + numv++; + lcount--; + continue; + } + else + { + if ( c == 0 ) + { + if ( numv == 0 ) + goto notBsName; + continue; + } + + if ( c < 0x20 ) + goto notBsName; + if ( c >= 0x80 ) + { + if ( (c < 0xa0) || ( c >= 0xf0 ) ) + goto notBsName; + } + numv++; + } + } + if ( numv > 0 ) + return 0; +notBsName: + return -1; +} +int check_char(unsigned c) +{ + if ( ( c & 0x80 ) == 0 ) + return 0; + if ( ( c - 0x20 ) & 0x40 ) + return 1; + else + return 0; +} + +void CMemory::ParseSNESHeader(uint8* RomHeader) +{ + Memory.SRAMSize = RomHeader [0x28]; + strncpy (ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); + ROMSpeed = RomHeader [0x25]; + ROMType = RomHeader [0x26]; + ROMSize = RomHeader [0x27]; + ROMChecksum = RomHeader [0x2e] + (RomHeader [0x2f] << 8); + ROMComplementChecksum = RomHeader [0x2c] + (RomHeader [0x2d] << 8); + ROMRegion= RomHeader[0x29]; + // memmove converted: Different mallocs [Neb] + memcpy (ROMId, &RomHeader [0x2], 4); + if(RomHeader[0x2A]==0x33) + // memmove converted: Different mallocs [Neb] + memcpy (CompanyId, &RomHeader [0], 2); + else sprintf(CompanyId, "%02X", RomHeader[0x2A]); +} + +#undef INLINE +#define INLINE +#include "getset.h" + diff --git a/source/memmap.cpp b/source/memmap.cpp deleted file mode 100644 index c102128..0000000 --- a/source/memmap.cpp +++ /dev/null @@ -1,4448 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include -#ifdef HAVE_STRINGS_H -#include -#endif -#include - -#ifdef __linux -#include -#endif - -#include "snes9x.h" -#include "memmap.h" -#include "cpuexec.h" -#include "ppu.h" -#include "display.h" -#include "cheats.h" -#include "apu.h" -#include "sa1.h" -#include "dsp1.h" -#include "srtc.h" -#include "sdd1.h" -#include "spc7110.h" -#include "seta.h" - -#ifdef DS2_DMA -//#include "ds2_cpu.h" -//#include "ds2_dma.h" -//#include "dma_adj.h" -#endif - -#ifdef __W32_HEAP -#include -#endif - -#ifndef ZSNES_FX -#include "fxemu.h" -extern struct FxInit_s SuperFX; -#else -START_EXTERN_C -extern uint8 *SFXPlotTable; -END_EXTERN_C -#endif - -#ifndef SET_UI_COLOR -#define SET_UI_COLOR(r,g,b) ; -#endif - -//you would think everyone would have these -//since they're so useful. -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -static int retry_count=0; -static uint8 bytes0x2000 [0x2000]; -int is_bsx(unsigned char *); -int bs_name(unsigned char *); -int check_char(unsigned); -void S9xDeinterleaveType2 (bool8 reset=TRUE); -uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32 = 0xFFFFFFFF); - -extern char *rom_filename; - -const uint32 crc32Table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - - - -void S9xDeinterleaveType1(int TotalFileSize, uint8 * base) -{ - if(Settings.DisplayColor==0xffff) - { - Settings.DisplayColor=BUILD_PIXEL(0,31,0); - SET_UI_COLOR(0,255,0); - } - - int i; - int nblocks = TotalFileSize >> 16; - uint8 blocks [256]; - for (i = 0; i < nblocks; i++) - { - blocks [i * 2] = i + nblocks; - blocks [i * 2 + 1] = i; - } - // DS2 DMA notes: base may or may not be 32-byte aligned - uint8 *tmp = (uint8 *) malloc (0x8000); - if (tmp) - { - for (i = 0; i < nblocks * 2; i++) - { - for (int j = i; j < nblocks * 2; j++) - { - if (blocks [j] == i) - { - // memmove converted: Different mallocs [Neb] - memcpy (tmp, &base [blocks [j] * 0x8000], 0x8000); - // memmove converted: Different addresses, or identical for blocks[i] == blocks[j] [Neb] - // DS2 DMA notes: Don't do DMA at all if blocks[i] == blocks[j] - memcpy (&base [blocks [j] * 0x8000], - &base [blocks [i] * 0x8000], 0x8000); - // memmove converted: Different mallocs [Neb] - memcpy (&base [blocks [i] * 0x8000], tmp, 0x8000); - uint8 b = blocks [j]; - blocks [j] = blocks [i]; - blocks [i] = b; - break; - } - } - } - free ((char *) tmp); - } -} - -void S9xDeinterleaveGD24(int TotalFileSize, uint8 * base) -{ - - if(TotalFileSize!=0x300000) - return; - - if(Settings.DisplayColor==0xffff) - { - Settings.DisplayColor=BUILD_PIXEL(0,31,31); - SET_UI_COLOR(0,255,255); - } - - // DS2 DMA notes: base may or may not be 32-byte aligned - uint8 *tmp = (uint8 *) malloc (0x80000); - if (tmp) - { - // memmove converted: Different mallocs [Neb] - memcpy(tmp, &base[0x180000], 0x80000); - // memmove converted: Different addresses [Neb] - memcpy(&base[0x180000], &base[0x200000], 0x80000); - // memmove converted: Different addresses [Neb] - memcpy(&base[0x200000], &base[0x280000], 0x80000); - // memmove converted: Different mallocs [Neb] - memcpy(&base[0x280000], tmp, 0x80000); - free ((char *) tmp); - - S9xDeinterleaveType1(TotalFileSize, base); - } -} - -bool8 CMemory::AllASCII (uint8 *b, int size) -{ - for (int i = 0; i < size; i++) - { - if (b[i] < 32 || b[i] > 126) - return (FALSE); - } - return (TRUE); -} - -int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff) -{ - int score = 0; - int o = skip_header ? 0xff00 + 0x200 : 0xff00; - - o+=romoff; - - if(Memory.ROM [o + 0xd5] & 0x1) - score+=2; - - //Mode23 is SA-1 - if(Memory.ROM [o + 0xd5] == 0x23) - score-=2; - - if(Memory.ROM [o+0xd4] == 0x20) - score +=2; - - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) - { - score += 2; - if(0!=(Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) - score++; - } - - if (Memory.ROM [o + 0xda] == 0x33) - score += 2; - if ((Memory.ROM [o + 0xd5] & 0xf) < 4) - score += 2; - if (!(Memory.ROM [o + 0xfd] & 0x80)) - score -= 6; - if ((Memory.ROM [o + 0xfc]|(Memory.ROM [o + 0xfd]<<8))>0xFFB0) - score -= 2; //reduced after looking at a scan by Cowering - if (CalculatedSize > 1024 * 1024 * 3) - score += 4; - if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) - score -= 1; - - return (score); -} - -int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) -{ - int score = 0; - int o = skip_header ? 0x7f00 + 0x200 : 0x7f00; - - o+=romoff; - - if(!(Memory.ROM [o + 0xd5] & 0x1)) - score+=3; - - //Mode23 is SA-1 - if(Memory.ROM [o + 0xd5] == 0x23) - score+=2; - - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) - { - score += 2; - if(0!=(Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) - score++; - } - - if (Memory.ROM [o + 0xda] == 0x33) - score += 2; - if ((Memory.ROM [o + 0xd5] & 0xf) < 4) - score += 2; - if (CalculatedSize <= 1024 * 1024 * 16) - score += 2; - if (!(Memory.ROM [o + 0xfd] & 0x80)) - score -= 6; - if ((Memory.ROM [o + 0xfc]|(Memory.ROM [o + 0xfd]<<8))>0xFFB0) - score -= 2;//reduced per Cowering suggestion - if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) - score -= 1; - - return (score); -} - -char *CMemory::Safe (const char *s) -{ - static char *safe; - static int safe_len = 0; - - if(s==NULL) - { - if(safe!=NULL) - { - free((char*)safe); - safe = NULL; - } - return NULL; - } - int len = strlen (s); - if (!safe || len + 1 > safe_len) - { - if (safe) - free ((char *) safe); - safe = (char *) malloc (safe_len = len + 1); - } - - for (int i = 0; i < len; i++) - { - if (s [i] >= 32 && s [i] < 127) - safe [i] = s[i]; - else - safe [i] = '?'; - } - safe [len] = 0; - return (safe); -} - -/**********************************************************************************************/ -/* Init() */ -/* This function allocates and zeroes all the memory needed by the emulator */ -/**********************************************************************************************/ -bool8 CMemory::Init () -{ - // DS2 DMA notes: These would do well to be allocated with 32 extra bytes - // so they can be 32-byte aligned. [Neb] - RAM = (uint8 *) malloc (0x20000); - SRAM = (uint8 *) malloc (0x20000); - VRAM = (uint8 *) malloc (0x10000); -#ifdef DS2_DMA - ROM = (uint8 *) AlignedMalloc (MAX_ROM_SIZE + 0x200 + 0x8000, 32, &PtrAdj.ROM); -#else - ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); -#endif - memset (RAM, 0, 0x20000); - memset (SRAM, 0, 0x20000); - memset (VRAM, 0, 0x10000); - // This needs to be initialised with a ROM first anyway, so don't - // bother memsetting. [Neb] - // memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000); - - BSRAM = (uint8 *) malloc (0x80000); - memset (BSRAM, 0, 0x80000); - - FillRAM = NULL; - - IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128); - IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128); - IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128); - - 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); - - if (!RAM || !SRAM || !VRAM || !ROM || !BSRAM || - !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || - !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || - !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT]) - { - Deinit (); - return (FALSE); - } - - // FillRAM uses first 32K of ROM image area, otherwise space just - // wasted. Might be read by the SuperFX code. - - FillRAM = ROM; - - // Add 0x8000 to ROM image pointer to stop SuperFX code accessing - // unallocated memory (can cause crash on some ports). - ROM += 0x8000; // still 32-byte aligned - - C4RAM = ROM + 0x400000 + 8192 * 8; // still 32-byte aligned - ::ROM = ROM; - ::SRAM = SRAM; - ::RegRAM = FillRAM; - -#ifdef ZSNES_FX - SFXPlotTable = ROM + 0x400000; -#else - SuperFX.pvRegisters = &Memory.FillRAM [0x3000]; - SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB, 2=128KB=1024Mb - SuperFX.pvRam = ::SRAM; - SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); - SuperFX.pvRom = (uint8 *) ROM; -#endif - - ZeroMemory (IPPU.TileCache [TILE_2BIT], MAX_2BIT_TILES * 128); - ZeroMemory (IPPU.TileCache [TILE_4BIT], MAX_4BIT_TILES * 128); - ZeroMemory (IPPU.TileCache [TILE_8BIT], MAX_8BIT_TILES * 128); - - ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); - - SDD1Data = NULL; - SDD1Index = NULL; - - return (TRUE); -} - -void CMemory::Deinit () -{ -#ifdef __W32_HEAP - if(_HEAPOK!=_heapchk()) - MessageBox(GUI.hWnd, "CMemory::Deinit", "Heap Corrupt", MB_OK); -#endif - - if (RAM) - { - free ((char *) RAM); - RAM = NULL; - } - if (SRAM) - { - free ((char *) SRAM); - SRAM = NULL; - } - if (VRAM) - { - free ((char *) VRAM); - VRAM = NULL; - } - if (ROM) - { - ROM -= 0x8000; -#ifdef DS2_RAM - AlignedFree ((char *) ROM, PtrAdj.ROM); -#else - free ((char *) ROM); -#endif - ROM = NULL; - } - - if(BSRAM) - { - free((char*) BSRAM); - BSRAM=NULL; - } - - if (IPPU.TileCache [TILE_2BIT]) - { - free ((char *) IPPU.TileCache [TILE_2BIT]); - IPPU.TileCache [TILE_2BIT] = NULL; - } - if (IPPU.TileCache [TILE_4BIT]) - { - free ((char *) IPPU.TileCache [TILE_4BIT]); - IPPU.TileCache [TILE_4BIT] = NULL; - } - if (IPPU.TileCache [TILE_8BIT]) - { - free ((char *) IPPU.TileCache [TILE_8BIT]); - IPPU.TileCache [TILE_8BIT] = NULL; - } - - if (IPPU.TileCached [TILE_2BIT]) - { - free ((char *) IPPU.TileCached [TILE_2BIT]); - IPPU.TileCached [TILE_2BIT] = NULL; - } - if (IPPU.TileCached [TILE_4BIT]) - { - free ((char *) IPPU.TileCached [TILE_4BIT]); - IPPU.TileCached [TILE_4BIT] = NULL; - } - if (IPPU.TileCached [TILE_8BIT]) - { - free ((char *) IPPU.TileCached [TILE_8BIT]); - IPPU.TileCached [TILE_8BIT] = NULL; - } - FreeSDD1Data (); - Safe(NULL); -} - -void CMemory::FreeSDD1Data () -{ - if (SDD1Index) - { - free ((char *) SDD1Index); - SDD1Index = NULL; - } - if (SDD1Data) - { - free ((char *) SDD1Data); - SDD1Data = NULL; - } -} - -/**********************************************************************************************/ -/* LoadROM() */ -/* This function loads a Snes-Backup image */ -/**********************************************************************************************/ - -bool8 CMemory::LoadROM (const char *filename) -{ - int32 TotalFileSize = 0; - bool8 Interleaved = FALSE; - bool8 Tales = FALSE; - - uint8* RomHeader=ROM; - - ExtendedFormat=NOPE; - - - if(CleanUp7110!=NULL) - (*CleanUp7110)(); - - memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); - SNESGameFixes.SRAMInitialValue = 0x60; - - memset (bytes0x2000, 0, 0x2000); - CPU.TriedInterleavedMode2 = FALSE; - - CalculatedSize = 0; - retry_count =0; - -again: - Settings.DisplayColor=0xffff; - SET_UI_COLOR(255,255,255); - - TotalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); - - if (!TotalFileSize) - return FALSE; // it ends here - else if(!Settings.NoPatch) - CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize); - - //fix hacked games here. - if((strncmp("HONKAKUHA IGO GOSEI", (char*)&ROM[0x7FC0],19)==0)&&(ROM[0x7FD5]!=0x31)) - { - ROM[0x7FD5]=0x31; - ROM[0x7FD6]=0x02; - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); - } - - if((strncmp("HONKAKUHA IGO GOSEI", (char*)&ROM[0xFFC0],19)==0)&&(ROM[0xFFD5]!=0x31)) - { - ROM[0xFFD5]=0x31; - ROM[0xFFD6]=0x02; - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); - } - - if((ROM[0x7FD5]==0x42)&&(ROM[0x7FD6]==0x13)&&(strncmp("METAL COMBAT",(char*)&ROM[0x7FC0],12)==0)) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); - } - - int orig_hi_score, orig_lo_score; - int hi_score, lo_score; - - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); - - if (HeaderCount == 0 && !Settings.ForceNoHeader && - ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || - (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) - { -#ifdef DS2_DMA - __dcache_writeback_all(); - { - unsigned int i; - for (i = 0; i < TotalFileSize; i += 512) - { - ds2_DMAcopy_32Byte (2 /* channel: emu internal */, Memory.ROM + i, Memory.ROM + i + 512, 512); - ds2_DMA_wait(2); - ds2_DMA_stop(2); - } - } -#else - // memmove required: Overlapping addresses [Neb] - memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); -#endif - TotalFileSize -= 512; - S9xMessage (S9X_INFO, S9X_HEADER_WARNING, - "Try specifying the -nhd command line option if the game doesn't work\n"); - //modifying ROM, so we need to rescore - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); - } - - CalculatedSize = TotalFileSize & ~0x1FFF; // round down to lower 0x2000 - ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize); - - if(CalculatedSize >0x400000&& - !(ROM[0x7FD5]==0x32&&((ROM[0x7FD6]&0xF0)==0x40)) && //exclude S-DD1 - !(ROM[0xFFD5]==0x3A&&((ROM[0xFFD6]&0xF0)==0xF0))) //exclude SPC7110 - { - //you might be a Jumbo! - ExtendedFormat=YEAH; - } - - //If both vectors are invalid, it's type 1 LoROM - - if(ExtendedFormat==NOPE&&((ROM[0x7FFC]|(ROM[0x7FFD]<<8))<0x8000)&&((ROM[0xFFFC]|(ROM[0xFFFD]<<8)) <0x8000)) - { - if(Settings.DisplayColor==0xffff) - { - Settings.DisplayColor=BUILD_PIXEL(0,31,0); - SET_UI_COLOR(0,255,0); - } - if(!Settings.ForceInterleaved) - S9xDeinterleaveType1(TotalFileSize, ROM); - } - - //CalculatedSize is now set, so rescore - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); - - if(NOPE!=ExtendedFormat) - { - int loromscore, hiromscore, swappedlorom, swappedhirom; - loromscore=ScoreLoROM(FALSE); - hiromscore=ScoreHiROM(FALSE); - swappedlorom=ScoreLoROM(FALSE, 0x400000); - swappedhirom=ScoreHiROM(FALSE, 0x400000); - - //set swapped here. - - if(max(swappedlorom, swappedhirom) >= max(loromscore, hiromscore)) - { - ExtendedFormat = BIGFIRST; - hi_score=swappedhirom; - lo_score=swappedlorom; - RomHeader=ROM+0x400000; - } - else - { - ExtendedFormat = SMALLFIRST; - lo_score=loromscore; - hi_score=hiromscore; - RomHeader=ROM; - } - - - } - - Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; - if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) - { - LoROM = TRUE; - HiROM = FALSE; - - // Ignore map type byte if not 0x2x or 0x3x - if ((RomHeader [0x7fd5] & 0xf0) == 0x20 || (RomHeader [0x7fd5] & 0xf0) == 0x30) - { - switch (RomHeader [0x7fd5] & 0xf) - { - case 1: - Interleaved = TRUE; - break; - case 5: - Interleaved = TRUE; - Tales = TRUE; - break; - } - } - } - else - { - if ((RomHeader [0xffd5] & 0xf0) == 0x20 || (RomHeader [0xffd5] & 0xf0) == 0x30) - { - switch (RomHeader [0xffd5] & 0xf) - { - case 0: - case 3: - Interleaved = TRUE; - break; - } - } - LoROM = FALSE; - HiROM = TRUE; - } - - // More - if (!Settings.ForceHiROM && !Settings.ForceLoROM && - !Settings.ForceInterleaved && !Settings.ForceInterleaved2 && - !Settings.ForceNotInterleaved && !Settings.ForcePAL && - !Settings.ForceSuperFX && !Settings.ForceDSP1 && - !Settings.ForceSA1 && !Settings.ForceC4 && - !Settings.ForceSDD1) - { - - -#ifdef DETECT_NASTY_FX_INTERLEAVE -//MK: Damn. YI trips a BRK currently. Maybe even on a real cart. - -#ifdef LSB_FIRST - if(strncmp((char *) &ROM [0x7fc0], "YOSHI'S ISLAND", 14) == 0&&(*(uint16*)&ROM[0x7FDE])==57611&&ROM[0x10002]==0xA9) -#else - if(strncmp((char *) &ROM [0x7fc0], "YOSHI'S ISLAND", 14) == 0&&(ROM[0x7FDE]+(ROM[0x7FDF]<<8))==57611&&ROM[0x10002]==0xA9) -#endif - { - Interleaved=true; - Settings.ForceInterleaved2=true; - } -#endif - if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0) - { - LoROM = TRUE; - HiROM = FALSE; - Interleaved = FALSE; - } - } - - if (!Settings.ForceNotInterleaved && Interleaved) - { - CPU.TriedInterleavedMode2 = TRUE; - S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, - "ROM image is in interleaved format - converting..."); - - if (Tales) - { - if(Memory.ExtendedFormat==BIGFIRST) - { - S9xDeinterleaveType1(0x400000, ROM); - S9xDeinterleaveType1(CalculatedSize-0x400000, ROM+0x400000); - } - else - { - S9xDeinterleaveType1(CalculatedSize-0x400000, ROM); - S9xDeinterleaveType1(0x400000, ROM+CalculatedSize-0x400000); - - } - - LoROM = FALSE; - HiROM = TRUE; - - - } - else if (Settings.ForceInterleaved2) - { - S9xDeinterleaveType2(FALSE); - } - else if (Settings.ForceInterleaveGD24 && CalculatedSize ==0x300000) - { - bool8 t = LoROM; - - LoROM = HiROM; - HiROM = t; - S9xDeinterleaveGD24(CalculatedSize, ROM); - } - else - { - if(Settings.DisplayColor==0xffff) - { - Settings.DisplayColor=BUILD_PIXEL(0,31,0); - SET_UI_COLOR(0,255,0); - } - bool8 t = LoROM; - - LoROM = HiROM; - HiROM = t; - - S9xDeinterleaveType1(CalculatedSize, ROM); - } - - hi_score = ScoreHiROM (FALSE); - lo_score = ScoreLoROM (FALSE); - - if ((HiROM && - (lo_score >= hi_score || hi_score < 0)) || - (LoROM && - (hi_score > lo_score || lo_score < 0))) - { - if (retry_count == 0) - { - S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, - "ROM lied about its type! Trying again."); - Settings.ForceNotInterleaved = TRUE; - Settings.ForceInterleaved = FALSE; - retry_count++; - goto again; - } - } - } - - if(ExtendedFormat==SMALLFIRST) - Tales=true; - - FreeSDD1Data (); - InitROM (Tales); - S9xLoadCheatFile (S9xGetFilename(".cht")); - S9xInitCheatData (); - S9xApplyCheats (); - - S9xReset (); - - return (TRUE); -} - -uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) -{ - - - FILE* ROMFile; - int32 TotalFileSize = 0; - int len = 0; - - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char fname [_MAX_PATH + 1]; - - unsigned long FileSize = 0; - - _splitpath (filename, drive, dir, name, ext); - _makepath (fname, drive, dir, name, ext); - -#ifdef __WIN32__ - // memmove required: Overlapping addresses [Neb] - memmove (&ext [0], &ext[1], 4); -#endif - - if ((ROMFile = fopen(fname, "rb")) == NULL) - return (0); - - strcpy (ROMFilename, fname); - - HeaderCount = 0; - uint8 *ptr = buffer; - bool8 more = FALSE; - - do - { - FileSize = fread (ptr, 1, maxsize + 0x200 - (ptr - ROM), ROMFile); - fclose (ROMFile); - - int calc_size = FileSize & ~0x1FFF; // round to the lower 0x2000 - - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) - { - // memmove required: Overlapping addresses [Neb] - // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] -#ifdef DS2_DMA - __dcache_writeback_all(); - { - unsigned int i; - for (i = 0; i < calc_size; i += 512) - { - ds2_DMAcopy_32Byte (2 /* channel: emu internal */, ptr + i, ptr + i + 512, 512); - ds2_DMA_wait(2); - ds2_DMA_stop(2); - } - } -#else - memmove (ptr, ptr + 512, calc_size); -#endif - HeaderCount++; - FileSize -= 512; - } - - ptr += FileSize; - TotalFileSize += FileSize; - - - // check for multi file roms - - if ((ptr - ROM) < (maxsize + 0x200) && - (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9')) - { - more = TRUE; - ext [0]++; -#ifdef __WIN32__ - // memmove required: Overlapping addresses [Neb] - memmove (&ext [1], &ext [0], 4); - ext [0] = '.'; -#endif - _makepath (fname, drive, dir, name, ext); - } - else if (ptr - ROM < 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]++; -#ifdef __WIN32__ - // memmove required: Overlapping addresses [Neb] - memmove (&ext [1], &ext [0], 4); - ext [0] = '.'; -#endif - _makepath (fname, drive, dir, name, ext); - } - else - more = FALSE; - - } while (more && (ROMFile = fopen (fname, "rb")) != NULL); - - - - 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 TotalFileSize; - -} - -#if 0 -/**********************************************************************************************/ -/* LoadMulti() */ -/* This function loads a Slotted SNES-Backup image and fills the slot. */ -/**********************************************************************************************/ - -bool8 CMemory::LoadMulti (const char *basename, const char *slot1name, const char *slot2name) -{ - unsigned long FileSize = 0; - - if(*basename=='\0') - return FALSE; - - SufamiTurbo=TRUE; - - int32 offset; - - memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); - SNESGameFixes.SRAMInitialValue = 0x60; - - memset (bytes0x2000, 0, 0x2000); - - CalculatedSize = 0; - - Settings.DisplayColor=0xffff; - SET_UI_COLOR(255,255,255); - - int32 TotalFileSize = FileLoader(ROM, basename, MAX_ROM_SIZE); - - if(0== TotalFileSize) - return FALSE; - else CheckForIPSPatch (basename, HeaderCount != 0, TotalFileSize); - - CalculatedSize=TotalFileSize; - - for(offset=0; offset0x100000||size <0x80000) - return FALSE; - //probably a minicart - return TRUE; - } - return FALSE; -} - -bool8 SameGameSig(uint8* file, int32 size) -{ - //preheader sig - if(strcmp((char*)(file+0xFFA0),"1995/12/16 10:2018ZS5J")) - return FALSE; - if(size!=0x100000) - return FALSE; - if(0x133E1C5B==caCRC32(file, size)) - return TRUE; - return FALSE; -} -bool8 GNextSig(uint8* file, int32 size) -{ - //preheader sig - if(strcmp((char*)(file+0xFFAA),"GNEXT B2ZX3J")) - return FALSE; - if(size!=0x180000) - return FALSE; - if(0x845E420D==caCRC32(file, size)) - return TRUE; - return FALSE; -} -int MultiType(uint8* file, int32 size) -{ - //check for ST signiture - if(SufamiTurboBIOSSig(file, size)) - return 1; - //check for Same Game signiture - if(SameGameSig(file, size)) - return 2; - //check for G-Next signiture - if(GNextSig(file, size)) - return 3; - return 0; -} - -#endif - -//compatibility wrapper -void S9xDeinterleaveMode2 () -{ - S9xDeinterleaveType2(); -} - -void S9xDeinterleaveType2 (bool8 reset) -{ - if(Settings.DisplayColor==0xffff||Settings.DisplayColor==BUILD_PIXEL(0,31,0)) - { - Settings.DisplayColor=BUILD_PIXEL(31,14,6); - SET_UI_COLOR(255,119,25); - - } - S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, - "ROM image is in interleaved format - converting..."); - - int nblocks = Memory.CalculatedSize >> 16; - int step = 64; - - while (nblocks <= step) - step >>= 1; - - nblocks = step; - uint8 blocks [256]; - int i; - - for (i = 0; i < nblocks * 2; i++) - { - blocks [i] = (i & ~0xF) | ((i & 3) << 2) | - ((i & 12) >> 2); - } - -#ifdef DS2_DMA - unsigned int TmpAdj; - uint8 *tmp = (uint8 *) AlignedMalloc (0x10000, 32, &TmpAdj); -#else - uint8 *tmp = (uint8 *) malloc (0x10000); -#endif - - if (tmp) - { -#ifdef DS2_DMA - __dcache_writeback_all(); -#endif - for (i = 0; i < nblocks * 2; i++) - { - for (int j = i; j < nblocks * 2; j++) - { - if (blocks [j] == i) - { -#ifdef DS2_DMA - ds2_DMAcopy_32Byte (2 /* channel: emu internal */, tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); - ds2_DMA_wait(2); - ds2_DMA_stop(2); - - ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [j] * 0x10000], - &Memory.ROM [blocks [i] * 0x10000], 0x10000); - ds2_DMA_wait(2); - ds2_DMA_stop(2); - - ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); - ds2_DMA_wait(2); - ds2_DMA_stop(2); -#else - // memmove converted: Different mallocs [Neb] - memcpy (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); - - // memmove converted: Different addresses, or identical if blocks[i] == blocks[j] [Neb] - memcpy (&Memory.ROM [blocks [j] * 0x10000], - &Memory.ROM [blocks [i] * 0x10000], 0x10000); - // memmove converted: Different mallocs [Neb] - memcpy (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); -#endif - uint8 b = blocks [j]; - blocks [j] = blocks [i]; - blocks [i] = b; - break; - } - } - } - free ((char *) tmp); - tmp=NULL; - } - if(reset) - { - Memory.InitROM (FALSE); - S9xReset (); - } -} - -//CRC32 for char arrays -uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32) -{ - for (register uint32 i = 0; i < size; i++) - { - crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; - } - return ~crc32; -} - -void CMemory::InitROM (bool8 Interleaved) -{ -#ifndef ZSNES_FX - SuperFX.nRomBanks = CalculatedSize >> 15; -#endif - Settings.MultiPlayer5Master = Settings.MultiPlayer5; - Settings.MouseMaster = Settings.Mouse; - Settings.SuperScopeMaster = Settings.SuperScope; - Settings.DSP1Master = Settings.ForceDSP1; - Settings.SuperFX = FALSE; - 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; - s7r.DataRomSize = 0; - CalculatedChecksum=0; - uint8* RomHeader; - - RomHeader=ROM+0x7FB0; - - if(ExtendedFormat==BIGFIRST) - RomHeader+=0x400000; - - if(HiROM) - RomHeader+=0x8000; - - if(!Settings.BS) - { - Settings.BS=(-1!=is_bsx(ROM+0x7FC0)); - - if(Settings.BS) - { - Memory.LoROM=TRUE; - Memory.HiROM=FALSE; - } - - else - { - Settings.BS=(-1!=is_bsx(ROM+0xFFC0)); - if(Settings.BS) - { - Memory.HiROM=TRUE; - Memory.LoROM=FALSE; - } - } - } - - ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS); - ZeroMemory (BlockIsROM, MEMMAP_NUM_BLOCKS); - - ::SRAM = SRAM; - memset (ROMId, 0, 5); - memset (CompanyId, 0, 3); - - ParseSNESHeader(RomHeader); - - // Try to auto-detect the DSP1 chip - if (!Settings.ForceNoDSP1 && - (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0) - Settings.DSP1Master = TRUE; - - if (Memory.HiROM) - { - // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2 - Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5; - - if(((ROMSpeed&0x0F)==0x0A)&&((ROMType&0xF0)==0xF0)) - { - Settings.SPC7110=true; - if((ROMType&0x0F)==0x09) - Settings.SPC7110RTC=true; - } - - if (Settings.BS) - BSHiROMMap (); - else if(Settings.SPC7110) - { - SPC7110HiROMMap(); - } - else if ((ROMSpeed & ~0x10) == 0x25) - { - TalesROMMap (Interleaved); - } - else HiROMMap (); - } - else - { - Settings.SuperFX = Settings.ForceSuperFX; - - if(ROMType==0x25) - { - Settings.OBC1=TRUE; - } - - //BS-X BIOS - if(ROMType==0xE5) - { - Settings.BS=TRUE; - } - - if ((ROMType & 0xf0) == 0x10) - Settings.SuperFX = !Settings.ForceNoSuperFX; - - Settings.SDD1 = Settings.ForceSDD1; - if ((ROMType & 0xf0) == 0x40) - Settings.SDD1 = !Settings.ForceNoSDD1; - - if (Settings.SDD1) - S9xLoadSDD1Data (); - - if(((ROMType &0xF0) == 0xF0)&((ROMSpeed&0x0F)!=5)) - { - SRAMSize=2; - SNESGameFixes.SRAMInitialValue = 0x00; - if((ROMType &0x0F)==6) - { - if(ROM[0x7FD7]==0x09) - { - Settings.SETA=ST_011; - SetSETA=&S9xSetST011; - GetSETA=&S9xGetST011; - } - else - { - Settings.SETA=ST_010; - SetSETA=&S9xSetST010; - GetSETA=&S9xGetST010; - } - } - else - { - Settings.SETA=ST_018; - SRAMSize=2; - } - } - Settings.C4 = Settings.ForceC4; - if ((ROMType & 0xf0) == 0xf0 && - (strncmp (ROMName, "MEGAMAN X", 9) == 0 || - strncmp (ROMName, "ROCKMAN X", 9) == 0)) - { - Settings.C4 = !Settings.ForceNoC4; - } - - if(Settings.SETA&&Settings.SETA!=ST_018) - { - SetaDSPMap(); - } - else if (Settings.SuperFX) - { - //::SRAM = ROM + 1024 * 1024 * 4; - SuperFXROMMap (); - Settings.MultiPlayer5Master = FALSE; - //Settings.MouseMaster = FALSE; - //Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - Settings.SA1 = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - } - else if (Settings.ForceSA1 || - (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && - (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) - { - Settings.SA1 = TRUE; -// Settings.MultiPlayer5Master = FALSE; - //Settings.MouseMaster = FALSE; - //Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - SA1ROMMap (); - } - else if ((ROMSpeed & ~0x10) == 0x25) - TalesROMMap (Interleaved); - else if(ExtendedFormat!=NOPE) - JumboLoROMMap(Interleaved); - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) - { - LoROM24MBSMap (); - Settings.DSP1Master = FALSE; - } - - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) - { - SRAM512KLoROMMap (); - Settings.DSP1Master = FALSE; - } - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0) - { - Settings.MultiPlayer5Master = FALSE; - Settings.MouseMaster = FALSE; - Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - SufamiTurboLoROMMap(); - Memory.SRAMSize = 3; - } - else if ((ROMSpeed & ~0x10) == 0x22 && - strncmp (ROMName, "Super Street Fighter", 20) != 0) - { - AlphaROMMap (); - } - else if (Settings.BS) - BSLoROMMap(); - else LoROMMap (); - } - - if(Settings.BS) - { - ROMRegion=0; - } - - uint32 sum1 = 0; - uint32 sum2 = 0; - if(0==CalculatedChecksum) - { - int power2 = 0; - int size = CalculatedSize; - - while (size >>= 1) - power2++; - - size = 1 << power2; - uint32 remainder = CalculatedSize - size; - - - int i; - - for (i = 0; i < size; i++) - sum1 += ROM [i]; - - for (i = 0; i < (int) remainder; i++) - sum2 += ROM [size + i]; - - int sub = 0; - if (Settings.BS&& ROMType!=0xE5) - { - if (Memory.HiROM) - { - for (i = 0; i < 48; i++) - sub += ROM[0xffb0 + i]; - } - else if (Memory.LoROM) - { - for (i = 0; i < 48; i++) - sub += ROM[0x7fb0 + i]; - } - sum1 -= sub; - } - - - if (remainder) - { - sum1 += sum2 * (size / remainder); - } - - - sum1 &= 0xffff; - Memory.CalculatedChecksum=sum1; - } - //now take a CRC32 - ROMCRC32 = caCRC32(ROM, CalculatedSize); - - if (Settings.ForceNTSC) - Settings.PAL = FALSE; - else if (Settings.ForcePAL) - Settings.PAL = TRUE; - else - { - //Korea refers to South Korea, which uses NTSC - switch(ROMRegion) - { - case 13: - case 1: - case 0: - Settings.PAL=FALSE; - break; - default: Settings.PAL=TRUE; - break; - } - } - if (Settings.PAL) - { - Settings.FrameTime = Settings.FrameTimePAL; - Memory.ROMFramesPerSecond = 50; - } - else - { - Settings.FrameTime = Settings.FrameTimeNTSC; - Memory.ROMFramesPerSecond = 60; - } - - ROMName[ROM_NAME_LEN - 1] = 0; - if (strlen (ROMName)) - { - char *p = ROMName + strlen (ROMName) - 1; - - while (p > ROMName && *(p - 1) == ' ') - p--; - *p = 0; - } - - { - SRAMMask = Memory.SRAMSize ? - ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; - } - if((ROMChecksum + ROMComplementChecksum != 0xffff) || ROMChecksum != CalculatedChecksum || ((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); - } - } - - IAPU.OneCycle = ONE_APU_CYCLE; - Settings.Shutdown = Settings.ShutdownMaster; - - SetDSP=&DSP1SetByte; - GetDSP=&DSP1GetByte; - - ResetSpeedMap(); - ApplyROMFixes (); - 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", - ROMName, - (ROMChecksum + ROMComplementChecksum != 0xffff || - ROMChecksum != CalculatedChecksum) ? "bad checksum" : "checksum ok", - MapType (), - Size (), - KartContents (), - MapMode (), - TVStandard (), - StaticRAMSize (), - ROMId, - CompanyId, - ROMCRC32); - - S9xMessage (S9X_INFO, S9X_ROM_INFO, String); -#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.ForceHeader = Settings.ForceHiROM = Settings.ForceLoROM = - Settings.ForceInterleaved = Settings.ForceNoHeader = Settings.ForceNotInterleaved = - Settings.ForceInterleaved2=false; -} - -bool8 CMemory::LoadSRAM (const char *filename) -{ - int size = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - - memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); - - if (size > 0x20000) - size = 0x20000; - - if (size) - { - FILE *file; - if ((file = fopen (filename, "rb"))) - { - int len = fread ((unsigned char*) ::SRAM, 1, 0x20000, file); - fclose (file); - if (len - size == 512) - { - // S-RAM file has a header - remove it - // memmove required: Overlapping addresses [Neb] - 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); - } - - return (TRUE); - } - S9xHardResetSRTC (); - return (FALSE); - } - if (Settings.SDD1) - S9xSDD1LoadLoggedData (); - - return (TRUE); -} - -bool8 CMemory::SaveSRAM (const char *filename) -{ - if(Settings.SuperFX && Memory.ROMType < 0x15) - return TRUE; - if(Settings.SA1 && Memory.ROMType == 0x34) - return TRUE; - - int size = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (Settings.SRTC) - { - size += SRTC_SRAM_PAD; - S9xSRTCPreSaveState (); - } - - if (Settings.SDD1) - S9xSDD1SaveLoggedData (); - - if (size > 0x20000) - size = 0x20000; - - if (size && *Memory.ROMFilename) - { - - FILE *file= fopen(filename, "w"); - if (file) - { - fwrite((unsigned char *) ::SRAM, size, 1, file); - fclose(file); - if(Settings.SPC7110RTC) - { - S9xSaveSPC7110RTC (&rtc_f9); - } - - return (TRUE); - } - } - return (FALSE); -} - -void CMemory::FixROMSpeed () -{ - int c; - - if(CPU.FastROMSpeed==0) - CPU.FastROMSpeed=SLOW_ONE_CYCLE; - - - for (c = 0x800; c < 0x1000; c++) - { - if (c&0x8 || c&0x400) - MemorySpeed [c] = (uint8) CPU.FastROMSpeed; - } -} - - -void CMemory::ResetSpeedMap() -{ - int i; - memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000); - for(i=0;i<0x400;i+=0x10) - { - MemorySpeed[i+2]=MemorySpeed[0x800+i+2]= ONE_CYCLE; - MemorySpeed[i+3]=MemorySpeed[0x800+i+3]= ONE_CYCLE; - MemorySpeed[i+4]=MemorySpeed[0x800+i+4]= ONE_CYCLE; - MemorySpeed[i+5]=MemorySpeed[0x800+i+5]= ONE_CYCLE; - } - CMemory::FixROMSpeed (); -} - -void CMemory::WriteProtectROM () -{ - // memmove converted: Different mallocs [Neb] - memcpy ((void *) WriteMap, (void *) Map, sizeof (Map)); - for (int c = 0; c < 0x1000; c++) - { - if (BlockIsROM [c]) - WriteMap [c] = (uint8 *) MAP_NONE; - } -} - -void CMemory::MapRAM () -{ - int c; - - if(Memory.LoROM&&!Settings.SDD1) - { - // Banks 70->77, S-RAM - for (c = 0; c < 0x0f; c++) - { - for(int i=0;i<8;i++) - { - Map [(c<<4) + 0xF00+i]=Map [(c<<4) + 0x700+i] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [(c<<4) + 0xF00+i] =BlockIsRAM [(c<<4) + 0x700+i] = TRUE; - BlockIsROM [(c<<4) + 0xF00+i] =BlockIsROM [(c<<4) + 0x700+i] = FALSE; - } - } - } - else if(Memory.LoROM&&Settings.SDD1) - { - // Banks 70->77, S-RAM - for (c = 0; c < 0x0f; c++) - { - for(int i=0;i<8;i++) - { - Map [(c<<4) + 0x700+i] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [(c<<4) + 0x700+i] = TRUE; - BlockIsROM [(c<<4) + 0x700+i] = FALSE; - } - } - } - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); -} - -void CMemory::MapExtraRAM () -{ - int c; - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->73, S-RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x700] = ::SRAM; - Map [c + 0x710] = ::SRAM + 0x8000; - Map [c + 0x720] = ::SRAM + 0x10000; - Map [c + 0x730] = ::SRAM + 0x18000; - - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - BlockIsRAM [c + 0x710] = TRUE; - BlockIsROM [c + 0x710] = FALSE; - BlockIsRAM [c + 0x720] = TRUE; - BlockIsROM [c + 0x720] = FALSE; - BlockIsRAM [c + 0x730] = TRUE; - BlockIsROM [c + 0x730] = FALSE; - } -} - -void CMemory::LoROMMap () -{ - int c; - int i; - int j; - int mask[4]; - for (j=0; j<4; j++) - mask[j]=0x00ff; - - mask[0]=(CalculatedSize/0x8000)-1; - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask[j+1]=mask[j]; - - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; - } - } - } - - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - if(Settings.SETA==ST_018) - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_SETA_RISC; - else Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else if (Settings.C4) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; - } - else if(Settings.OBC1) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_OBC_RAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_OBC_RAM; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; - Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; - } - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i] = Map [i + 0x800] = ROM + (((d)-1)*0x8000); - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - if (Settings.DSP1Master) - { - // Banks 30->3f and b0->bf - for (c = 0x300; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP; - BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; - } - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize]; - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=(c+0x400)>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - - Map [i + 0x400] = Map [i + 0xc00] = ROM + (((d)-1)*0x8000); - } - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - if (Settings.DSP1Master) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xe00] = (uint8 *) MAP_DSP; - BlockIsROM [c + 0xe00] = FALSE; - } - } - - int sum=0, k,l, bankcount; - bankcount=1<<(ROMSize-7);//Mbits - - //safety for corrupt headers - if(bankcount > 128) - bankcount = (CalculatedSize/0x8000)/4; - bankcount*=4;//to banks - bankcount<<=4;//Map banks - bankcount+=0x800;//normalize - for(k=0x800;k<(bankcount);k+=16) - { - uint8* bank=0x8000+Map[k+8]; - for(l=0;l<0x8000;l++) - sum+=bank[l]; - } - CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::SetaDSPMap () -{ - int c; - int i; - int j; - int mask[4]; - for (j=0; j<4; j++) - mask[j]=0x00ff; - - mask[0]=(CalculatedSize/0x8000)-1; - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask[j+1]=mask[j]; - - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; - } - } - } - - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; - Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i] = Map [i + 0x800] = ROM + (((d)-1)*0x8000); - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=(c+0x400)>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - - Map [i + 0x400] = Map [i + 0xc00] = ROM + (((d)-1)*0x8000); - } - - //only upper half is ROM - for (i = c+8; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - memset(SRAM, 0, 0x1000); - for (c=0x600;c<0x680;c+=0x10) - { - for(i=0;i<0x08;i++) - { - //where does the SETA chip access, anyway? - //please confirm this? - Map[c+0x80+i]=(uint8*)MAP_SETA_DSP; - BlockIsROM [c+0x80+i] = FALSE; - BlockIsRAM [c+0x80+i] = TRUE; - } - - for(i=0;i<0x04;i++) - { - //and this! - Map[c+i]=(uint8*)MAP_SETA_DSP; - BlockIsROM [c+i] = FALSE; - } - } - - int sum=0, k,l, bankcount; - bankcount=1<<(ROMSize-7);//Mbits - //safety for corrupt headers - if(bankcount > 128) - bankcount = (CalculatedSize/0x8000)/4; - bankcount*=4;//to banks - bankcount<<=4;//Map banks - bankcount+=0x800;//normalize - for(k=0x800;k<(bankcount);k+=16) - { - uint8* bank=0x8000+Map[k+8]; - for(l=0;l<0x8000;l++) - sum+=bank[l]; - } - CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::BSLoROMMap () -{ - int c; - int i; - - if(Settings.BS) - SRAMSize=5; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) RAM; -// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; -BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; - -// Map [c + 6] = Map [c + 0x806] = (uint8 *)MAP_NONE; -// Map [c + 7] = Map [c + 0x807] = (uint8 *)MAP_NONE; - Map [c + 6] = Map [c + 0x806] = (uint8 *) RAM; -// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; -BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) RAM; -// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; -BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 11) % CalculatedSize] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - for(c=0;c<8;c++) - { - Map[(c<<4)+0x105]=(uint8*)MAP_LOROM_SRAM; - BlockIsROM [(c<<4)+0x105] = FALSE; - BlockIsRAM [(c<<4)+0x105] = TRUE; - } - - - /* // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [((c << 11) + 0x200000) % CalculatedSize - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - */ - for(c=1;c<=4;c++) - { - for(i=0;i<16; i++) - { - Map[0x400+i+(c<<4)]=(uint8*)MAP_LOROM_SRAM; - BlockIsRAM[0x400+i+(c<<4)]=TRUE; - BlockIsROM[0x400+i+(c<<4)]=FALSE; - } - } - - for(i=0;i<0x80;i++) - { - Map[0x700+i]=&BSRAM[0x10000*(i/16)]; - BlockIsRAM[0x700+i]=TRUE; - BlockIsROM[0x700+i]=FALSE; - } - for (i=0; i<8;i++) - { - Map[0x205+(i<<4)]=Map[0x285+(i<<4)]=Map[0x305+(i<<4)]=Map[0x385+(i<<4)]=Map[0x705+(i<<4)]; - BlockIsRAM[0x205+(i<<4)]=BlockIsRAM[0x285+(i<<4)]=BlockIsRAM[0x305+(i<<4)]=BlockIsRAM[0x385+(i<<4)]=TRUE; - BlockIsROM[0x205+(i<<4)]=BlockIsROM[0x285+(i<<4)]=BlockIsROM[0x305+(i<<4)]=BlockIsROM[0x385+(i<<4)]=FALSE; - } - for(c=0;c<8;c++) - { - Map[(c<<4)+0x005]=BSRAM-0x5000; - BlockIsROM [(c<<4)+0x005] = FALSE; - BlockIsRAM [(c<<4)+0x005] = TRUE; - } - MapRAM (); - WriteProtectROM (); - - -} - -void CMemory::HiROMMap () -{ - int i; - int c; - int j; - - int mask[4]; - for (j=0; j<4; j++) - mask[j]=0x00ff; - - mask[0]=(CalculatedSize/0x10000)-1; - - if (Settings.ForceSA1 || - (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && - (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } - - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask[j+1]=mask[j]; - - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; - } - } - } - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i] = Map [i + 0x800] = ROM + (d*0x10000); - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - BlockIsRAM [0xb06 + (c << 4)] = TRUE; - BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - int e=3; - int d=(c)>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i + 0x400] = Map [i + 0xc00] = ROM + (d*0x10000); - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - int bankmax=0x40+ (1<<(ROMSize-6)); - //safety for corrupt headers - if(bankmax > 128) - bankmax = 0x80; - int sum=0; - for(i=0x40;i3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - //makes more sense to map the range here. - //ToP seems to use sram to skip intro??? - if(c>=0x300) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_HIROM_SRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [6 + c] = BlockIsRAM [7 + c] = - BlockIsRAM [0x806 + c]= BlockIsRAM [0x807 + c] = TRUE; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - } - for (i = c + 8; i < c + 16; i++) - { - Map [i] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET0]; - Map [i + 0x800] = &ROM [((c << 12) % 0x400000) + OFFSET2]; - BlockIsROM [i] = TRUE; - BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - { - Map [i + 0x400] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET1]; - Map [i + 0x408] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET1]; - Map [i + 0xc00] = &ROM [((c << 12) %0x400000)+ OFFSET2]; - Map [i + 0xc08] = &ROM [((c << 12) % 0x400000) + OFFSET2]; - BlockIsROM [i + 0x400] = TRUE; - BlockIsROM [i + 0x408] = TRUE; - BlockIsROM [i + 0xc00] = TRUE; - BlockIsROM [i + 0xc08] = TRUE; - } - } - - if((strncmp("TALES",(char*)Map[8]+0xFFC0, 5)==0)) - { - if(((*(Map[8]+0xFFDE))==(*(Map[0x808]+0xFFDE)))) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } - } - - ROMChecksum = *(Map[8]+0xFFDE) + (*(Map[8]+0xFFDF) << 8); - ROMComplementChecksum = *(Map[8]+0xFFDC) + (*(Map[8]+0xFFDD) << 8); - -int sum=0; -for(i=0x40;i<0x80; i++) -{ - uint8 * bank_low=(uint8*)Map[i<<4]; - uint8 * bank_high=(uint8*)Map[(i<<4)+0x800]; - for (c=0;c<0x10000; c++) - { - sum+=bank_low[c]; - sum+=bank_high[c]; - } -} - -CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::AlphaROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = TRUE; - } - } - - // Banks 40->7f and c0->ff - - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize]; - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapRAM (); - WriteProtectROM (); -} - -void DetectSuperFxRamSize() -{ - if(ROM[0x7FDA]==0x33) - { - Memory.SRAMSize=ROM[0x7FBD]; - } - else - { - if(strncmp(Memory.ROMName, "STAR FOX 2", 10)==0) - { - Memory.SRAMSize=6; - } - else Memory.SRAMSize=5; - } -} - -void CMemory::SuperFXROMMap () -{ - int c; - int i; - - DetectSuperFxRamSize(); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [0x006 + c] = Map [0x806 + c] = (uint8 *) ::SRAM - 0x6000; - Map [0x007 + c] = Map [0x807 + c] = (uint8 *) ::SRAM - 0x6000; - BlockIsRAM [0x006 + c] = BlockIsRAM [0x007 + c] = BlockIsRAM [0x806 + c] = BlockIsRAM [0x807 + c] = TRUE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->71, S-RAM - for (c = 0; c < 32; c++) - { - Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16); - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } - - // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K - // block is repeated twice in each 64K block. -#ifdef DS2_DMA - __dcache_writeback_all(); -#endif - for (c = 0; c < 64; c++) - { -#ifdef DS2_DMA - ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - ds2_DMAcopy_32Byte(3 /* channel: emu internal 2 */, &ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - ds2_DMA_wait(2); - ds2_DMA_wait(3); - ds2_DMA_stop(2); - ds2_DMA_stop(3); -#else - // memmove converted: Different addresses [Neb] - memcpy (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - // memmove converted: Different addresses [Neb] - memcpy (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); -#endif - } - - WriteProtectROM (); -} - -void CMemory::SA1ROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = FALSE; - } - } - - // c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); - - // Now copy the map and correct it for the SA1 CPU. - // memmove converted: Different mallocs [Neb] - memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); - // memmove converted: Different mallocs [Neb] - memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map)); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE; - SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE; - } - - // Banks 60->6f - for (c = 0; c < 0x100; c++) - SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; - - BWRAM = SRAM; -} - -void CMemory::LoROM24MBSMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x200; c += 16) - { - Map [c + 0x800] = RAM; - Map [c + 0x801] = RAM; - BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000; - BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapExtraRAM (); - WriteProtectROM (); -} - -void CMemory::SufamiTurboLoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - if (Settings.DSP1Master) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xe00] = (uint8 *) MAP_DSP; - BlockIsROM [c + 0xe00] = FALSE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 60->67, S-RAM - for (c = 0; c < 0x80; c++) - { - Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0x600] = TRUE; - BlockIsROM [c + 0x600] = FALSE; - } - - WriteProtectROM (); -} - -#if 0 - -//untested!! -void CMemory::SameGameMap () -{ - int i; - int c; - int j; - - int mask[4]; - int mask2[4]; - for (j=0; j<4; j++) - mask[j]=mask2[j]=0x00ff; - - mask[0]=(CalculatedSize/0x10000)-1; - mask2[0]=(Slot1Size/0x10000)-1; - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask[j+1]=mask[j]; - - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; - } - } - } - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask2[j+1]=mask2[j]; - - while (x>0x100&&!pastZeros) - { - if(mask2[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask2[j+1]|=x; - x<<=1; - } - } - } - - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - BlockIsRAM [0xb06 + (c << 4)] = TRUE; - BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } - - for c=0; c<0x200; c+=16) - { - for(i=0;i<8;i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - - int f=3; - int g=c>>4; - while(g>mask2[0]) - { - g&=mask2[f]; - f--; - } - - //stuff in HiROM areas - Map[c+0x400+i]=&ROM[d*0x10000]; - Map[c+0xC00+i]=&ROM[d*0x10000]; - //MINI - Map[c+0x600+i]=&ROMOffset1[g*0x10000]; - Map[c+0xE00+i]=&ROMOffset1[g*0x10000]; - - } - for(i=8;i<16;i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - - int f=3; - int g=c>>4; - while(g>mask2[0]) - { - g&=mask2[f]; - f--; - } - - - //all stuff - //BASE - Map[c+i]=&ROM[d*0x10000]; - Map[c+0x800+i]=&ROM[d*0x10000]; - Map[c+0x400+i]=&ROM[d*0x10000]; - Map[c+0xC00+i]=&ROM[d*0x10000]; - //MINI - Map[c+0x200+i]=&ROMOffset1[g*0x10000]; - Map[c+0xA00+i]=&ROMOffset1[g*0x10000]; - Map[c+0x600+i]=&ROMOffset1[g*0x10000]; - Map[c+0xE00+i]=&ROMOffset1[g*0x10000]; - } - - } - - int bankmax=0x40+ (1<<(ROMSize-6)); - //safety for corrupt headers - if(bankmax > 128) - bankmax = 0x80; - int sum=0; - for(i=0x40;i3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - - // Banks 40->4f (was 7f, but SNES docs and GNext overdumping shows nothing here.) - for (c = 0; c < 0x100; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = FALSE; - } - } - - for (c = 0; c < 0x100; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x700] = (uint8 *) &ROMOffset1 [(c << 12) & (Slot1Size-1)]; - } - - // c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); - - // Now copy the map and correct it for the SA1 CPU. - // memmove converted: Different mallocs [Neb] - memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); - // memmove converted: Different mallocs [Neb] - memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map)); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE; - SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE; - } - - // Banks 60->6f - for (c = 0; c < 0x100; c++) - SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; - - BWRAM = SRAM; -} - -void CMemory::SufamiTurboAltROMMap () -{ - int c; - int i; - - if(Slot1Size!=0) - Slot1SRAMSize=(1<<((uint8)ROMOffset1[0x32]))*1024; - else Slot1Size=0x8000; - if(Slot2Size!=0) - Slot2SRAMSize=(1<<((uint8)ROMOffset2[0x32]))*1024; -else Slot2Size=0x8000; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - -// for (i = c + 8; i < c + 16; i++) -// { -// Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; -// BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; -// } - - } - - //Map Bios - - for (c=0; c<0x200; c+=16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [((c>>4)*0x8000)%CalculatedSize] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - } - - - for (c=0x200; c<0x400; c+=16) - { - for (i = c + 8; i < c + 16; i++) - { - if(Slot1Size!=0) - { - Map [i] = Map [i + 0x800] = &ROMOffset1 [(((c>>4)*0x8000)%Slot1Size)] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; - } - - } - - for (c=0x400; c<0x600; c+=16) - { - for (i = c; i < c + 8; i++) - { - if(Slot2Size!=0) - { - Map [i] = Map [i + 0x800] = &ROMOffset2[(((c>>4)*0x8000)%Slot2Size)]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; - - } - for (i = c + 8; i < c + 16; i++) - { - if(Slot2Size!=0) - { - Map [i] = Map [i + 0x800] = &ROMOffset2[(((c>>4)*0x8000)%Slot2Size)] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; - - } - - } - - // Banks 60->67 (7F?), S-RAM - if(Slot1SRAMSize!=0) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xE00] = Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0xE00] = BlockIsRAM [c + 0x600] = TRUE; - BlockIsROM [c + 0xE00] = BlockIsROM [c + 0x600] = FALSE; - } - } - if(Slot2SRAMSize!=0) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xF00] = Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0xF00] = BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0xF00] = BlockIsROM [c + 0x700] = FALSE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - WriteProtectROM (); -} -#endif - - -void CMemory::SRAM512KLoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapExtraRAM (); - WriteProtectROM (); -} - -void CMemory::BSHiROMMap () -{ - int c; - int i; - - SRAMSize=5; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - // XXX: How large is SRAM?? - Map [c + 5] = Map [c + 0x805] = (uint8 *) RAM; -// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; - BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; -// Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; -// Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - Map [c + 6] = Map [c + 0x806] = (uint8 *) RAM; -// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; -BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) RAM; -// Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; -BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM - // XXX: How large is PSRAM? - - //not adjusted, but The Dumper says "4 Mbits" - for (c = 0x600; c < 0x7e0; c += 16) - { - for (i = c; i < c + 8; i++) - { - Map [i] = &ROM [0x400000 + (c << 11)]; - BlockIsRAM [i] = TRUE; - } - for (i = c + 8; i < c + 16; i++) - { - Map [i] = &ROM [0x400000 + (c << 11) - 0x8000]; - BlockIsRAM [i] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - for(i=0;i<0x80;i++) - { - Map[0x700+i]=&BSRAM[0x10000*(i/16)]; - BlockIsRAM[0x700+i]=TRUE; - BlockIsROM[0x700+i]=FALSE; - } - for (i=0; i<8;i++) - { - Map[0x205+(i<<4)]=Map[0x285+(i<<4)]=Map[0x305+(i<<4)]=Map[0x385+(i<<4)]=Map[0x705+(i<<4)]; - BlockIsRAM[0x205+(i<<4)]=BlockIsRAM[0x285+(i<<4)]=BlockIsRAM[0x305+(i<<4)]=BlockIsRAM[0x385+(i<<4)]=TRUE; - BlockIsROM[0x205+(i<<4)]=BlockIsROM[0x285+(i<<4)]=BlockIsROM[0x305+(i<<4)]=BlockIsROM[0x385+(i<<4)]=FALSE; - } - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::JumboLoROMMap (bool8 Interleaved) -{ - int c; - int i; - - uint32 OFFSET0 = 0x400000; - uint32 OFFSET1 = 0x400000; - uint32 OFFSET2 = 0x000000; - - if (Interleaved) - { - OFFSET0 = 0x000000; - OFFSET1 = 0x000000; - OFFSET2 = CalculatedSize-0x400000; //changed to work with interleaved DKJM2. - } - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else if (Settings.C4) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; - Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; - } - - for (i = c + 8; i < c + 16; i++) - { - Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0] - 0x8000; - Map [i + 0x800] = &ROM [((c << 11) % (0x400000)) + OFFSET2] - 0x8000; - BlockIsROM [i + 0x800] = BlockIsROM [i] = TRUE; - } - } - - if (Settings.DSP1Master) - { - // Banks 30->3f and b0->bf - for (c = 0x300; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i + 0x800] = (uint8 *) MAP_DSP; - BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; - } - } - } - - // Banks 40->7f and c0->ff - for (c = 0x400; c < 0x800; c += 16) - { - //updated mappings to correct A15 mirroring - for (i = c; i < c + 8; i++) - { - Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0]; - Map [i + 0x800] = &ROM [((c << 11) % 0x400000) +OFFSET2]; - } - - for (i = c + 8; i < c + 16; i++) - { - Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0] - 0x8000; - Map [i + 0x800] = &ROM [((c << 11) % 0x400000) + OFFSET2 ] - 0x8000; - } - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - //ROM type has to be 64 Mbit header! - int sum=0, k,l; - for(k=0;k<256;k++) - { - uint8* bank=0x8000+Map[8+(k<<4)];//use upper half of the banks, and adjust for LoROM. - for(l=0;l<0x8000;l++) - sum+=bank[l]; - } - CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::SPC7110HiROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - Map [c + 6] /*= Map [c + 0x806]*/ = (uint8 *) MAP_HIROM_SRAM; - Map [c + 7] /*= Map [c + 0x807]*/ = (uint8 *) MAP_HIROM_SRAM; - Map [c + 0x806]=Map [c + 0x807]= (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_NONE; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_NONE; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - // BlockIsRAM [0xb06 + (c << 4)] = TRUE; - // BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c=0;c<0x10;c++) - { - Map [0x500+c]=(uint8 *)MAP_SPC7110_DRAM; - BlockIsROM [0x500+c]=TRUE; - } - - for (c=0;c<0x100;c++) - { - Map [0xD00+c] = (uint8 *) MAP_SPC7110_ROM; - Map [0xE00+c] = (uint8 *) MAP_SPC7110_ROM; - Map [0xF00+c] = (uint8 *) MAP_SPC7110_ROM; - BlockIsROM [0xD00+c] = BlockIsROM [0xE00+c] = BlockIsROM [0xF00+c] = TRUE; - - } - S9xSpc7110Init(); - -int sum=0; -for(i=0;i<(int)CalculatedSize; i++) -{ - sum+=ROM[i]; -} - -if(CalculatedSize==0x300000) - sum<<=1; -CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} -void CMemory::SPC7110Sram(uint8 newstate) -{ - if(newstate&0x80) - { - Memory.Map[6]=(uint8 *)MAP_HIROM_SRAM; - Memory.Map[7]=(uint8 *)MAP_HIROM_SRAM; - Memory.Map[0x306]=(uint8 *)MAP_HIROM_SRAM; - Memory.Map[0x307]=(uint8 *)MAP_HIROM_SRAM; - - - } - else - { - Memory.Map[6]=(uint8 *)MAP_RONLY_SRAM; - Memory.Map[7]=(uint8 *)MAP_RONLY_SRAM; - Memory.Map[0x306]=(uint8 *)MAP_RONLY_SRAM; - Memory.Map[0x307]=(uint8 *)MAP_RONLY_SRAM; - } -} -const char *CMemory::TVStandard () -{ - return (Settings.PAL ? "PAL" : "NTSC"); -} - -const char *CMemory::Speed () -{ - return (ROMSpeed & 0x10 ? "120ns" : "200ns"); -} - -const char *CMemory::MapType () -{ - return (HiROM ? "HiROM" : "LoROM"); -} - -const char *CMemory::StaticRAMSize () -{ - static char tmp [20]; - - if (Memory.SRAMSize > 16) - return ("Corrupt"); - sprintf (tmp, "%dKB", (SRAMMask + 1) / 1024); - return (tmp); -} - -const char *CMemory::Size () -{ - static char tmp [20]; - - if (ROMSize < 7 || ROMSize - 7 > 23) - return ("Corrupt"); - sprintf (tmp, "%dMbits", 1 << (ROMSize - 7)); - return (tmp); -} - -const char *CMemory::KartContents () -{ - static char tmp [30]; - static const char *CoPro [16] = { - "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6", - "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12", - "CoPro#13", "CoPro#14", "CoPro-Custom" - }; - static const char *Contents [3] = { - "ROM", "ROM+RAM", "ROM+RAM+BAT" - }; - if (ROMType == 0&&!Settings.BS) - return ("ROM only"); - - sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]); - - - if(Settings.BS) - sprintf (tmp, "%s+%s", tmp, "BSX"); - else if(Settings.SPC7110&&Settings.SPC7110RTC) - sprintf (tmp, "%s+%s", tmp, "SPC7110+RTC"); - else if(Settings.SPC7110) - sprintf (tmp, "%s+%s", tmp, "SPC7110"); - else if(Settings.SETA!=0) - { - switch(Settings.SETA) - { - case ST_010: - sprintf (tmp, "%s+%s", tmp, "ST-010"); - break; - case ST_011: - sprintf (tmp, "%s+%s", tmp, "ST-011"); - break; - - case ST_018: - sprintf (tmp, "%s+%s", tmp, "ST-018"); - break; - - } - } - else if ((ROMType & 0xf) >= 3) - sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]); - - return (tmp); -} - -const char *CMemory::MapMode () -{ - static char tmp [4]; - sprintf (tmp, "%02x", ROMSpeed & ~0x10); - return (tmp); -} - -const char *CMemory::ROMID () -{ - return (ROMId); -} - -void CMemory::ApplyROMFixes () -{ -#ifdef __W32_HEAP - if(_HEAPOK!=_heapchk()) - MessageBox(GUI.hWnd, "CMemory::ApplyROMFixes", "Heap Corrupt", MB_OK); -#endif - - //don't steal my work! -MK - if(ROMCRC32 == 0x1B4A5616 && strncmp(ROMName, "RUDORA NO HIHOU", 15)==0) - { - strncpy(ROMName, "THIS SCRIPT WAS STOLEN", 22); - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } - - /* - HACKS NSRT can fix that we hadn't detected before. -[14:25:13] <@Nach> case 0x0c572ef0: //So called Hook (US)(2648) -[14:25:13] <@Nach> case 0x6810aa95: //Bazooka Blitzkreig swapped sizes hack -handled -[14:25:17] <@Nach> case 0x61E29C06: //The Tick region hack -[14:25:19] <@Nach> case 0x1EF90F74: //Jikkyou Keiba Simulation Stable Star PAL hack -[14:25:23] <@Nach> case 0x4ab225b5: //So called Krusty's Super Fun House (E) -[14:25:25] <@Nach> case 0x77fd806a: //Donkey Kong Country 2 (E) v1.1 bad dump -handled -[14:25:27] <@Nach> case 0x340f23e5: //Donkey Kong Country 3 (U) copier hack - handled - */ - - if(ROMCRC32==0x6810aa95 || ROMCRC32==0x340f23e5 || ROMCRC32==0x77fd806a || - strncmp (ROMName, "HIGHWAY BATTLE 2", 16)==0 || - (strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 && ROM[0x7FDA]==0)) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } - - //Ambiguous chip function pointer assignments - - //DSP switching: - if(strncmp(ROMName, "DUNGEON MASTER", 14)==0) - { - //Set DSP-2 - SetDSP=&DSP2SetByte; - GetDSP=&DSP2GetByte; - } - -#ifdef DSP_DUMMY_LOOPS - if(strncmp(ROMName, "SD\x0b6\x0de\x0dd\x0c0\x0de\x0d1GX", 10)==0) - { - //Set DSP-3 - SetDSP=&DSP3SetByte; - GetDSP=&DSP3GetByte; - } -#endif - - if(strncmp(ROMName, "TOP GEAR 3000", 13)==0 - ||strncmp(ROMName, "PLANETS CHAMP TG3000", 20)==0) - { - //Set DSP-4 - SetDSP=&DSP4SetByte; - GetDSP=&DSP4GetByte; - } - - //memory map corrections - if(strncmp(ROMName, "XBAND",5)==0) - { - for (int c=0xE00;c<0xE10;c++) - { - Map [c] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c] = TRUE; - BlockIsROM [c] = FALSE; - } - WriteProtectROM (); - } - - //not MAD-1 compliant - if(strcmp (ROMName, "WANDERERS FROM YS") == 0) - { - for(int c=0;c<0xE0;c++) - { - Map[c+0x700]=(uint8*)MAP_LOROM_SRAM; - BlockIsROM[c+0x700]=FALSE; - BlockIsRAM[c+0x700]=TRUE; - } - WriteProtectROM(); - } - - if (strcmp (ROMName, "GOGO ACKMAN3") == 0 || - strcmp (ROMName, "HOME ALONE") == 0) - { - // Banks 00->3f and 80->bf - for (int c = 0; c < 0x400; c += 16) - { - Map [c + 6] = Map [c + 0x806] = SRAM; - Map [c + 7] = Map [c + 0x807] = SRAM; - BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE; - BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE; - BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; - BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; - } - WriteProtectROM (); - } - - if (strcmp (ROMName, "RADICAL DREAMERS") == 0 || - strcmp (ROMName, "TREASURE CONFLIX") == 0) - { - int c; - - for (c = 0; c < 0x80; c++) - { - Map [c + 0x700] = ROM + 0x200000 + 0x1000 * (c & 0xf0); - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } - for (c = 0; c < 0x400; c += 16) - { - Map [c + 5] = Map [c + 0x805] = ROM + 0x300000; - BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; - } - WriteProtectROM (); - } - - if(strncmp(ROMName, "WAR 2410", 8)==0) - { - Map [0x005] = (uint8 *) RAM; - BlockIsRAM [0x005] = TRUE; - BlockIsROM [0x005] = FALSE; - } - - if (strcmp (ROMName, "BATMAN--REVENGE JOKER") == 0) - { - Memory.HiROM = FALSE; - Memory.LoROM = TRUE; - LoROMMap (); - } - - - //NMI hacks - CPU.NMITriggerPoint = 4; - if (strcmp (ROMName, "CACOMA KNIGHT") == 0) - CPU.NMITriggerPoint = 25; - - //Disabling a speed-up - // Games which spool sound samples between the SNES and sound CPU using - // H-DMA as the sample is playing. - if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 || - strcmp (ROMName, "PRIMAL RAGE") == 0 || - strcmp (ROMName, "CLAY FIGHTER") == 0 || - strcmp (ROMName, "ClayFighter 2") == 0 || - strncasecmp (ROMName, "MADDEN", 6) == 0 || - strncmp (ROMName, "NHL", 3) == 0 || - strcmp (ROMName, "WeaponLord") == 0|| - strncmp(ROMName, "WAR 2410", 8)==0) - { - Settings.Shutdown = FALSE; - } - - - //APU timing hacks - - // Stunt Racer FX - if (strcmp (ROMId, "CQ ") == 0 || - // Illusion of Gaia - strncmp (ROMId, "JG", 2) == 0 || - strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0) - { - IAPU.OneCycle = 13; - } - - // RENDERING RANGER R2 - if (strcmp (ROMId, "AVCJ") == 0 || - //Mark Davis - strncmp(ROMName, "THE FISHING MASTER", 18)==0 || //needs >= actual APU timing. (21 is .002 Mhz slower) - // Star Ocean - strncmp (ROMId, "ARF", 3) == 0 || - // Tales of Phantasia - strncmp (ROMId, "ATV", 3) == 0 || - // Act Raiser 1 & 2 - strncasecmp (ROMName, "ActRaiser", 9) == 0 || - // Soulblazer - strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 || - strcmp (ROMName, "SOULBLADER - 1") == 0 || - - // Terranigma - strncmp (ROMId, "AQT", 3) == 0 || - // Robotrek - strncmp (ROMId, "E9 ", 3) == 0 || - strcmp (ROMName, "SLAP STICK 1 JPN") == 0 || - // ZENNIHON PURORESU2 - strncmp (ROMId, "APR", 3) == 0 || - // Bomberman 4 - strncmp (ROMId, "A4B", 3) == 0 || - // UFO KAMEN YAKISOBAN - strncmp (ROMId, "Y7 ", 3) == 0 || - strncmp (ROMId, "Y9 ", 3) == 0 || - // Panic Bomber World - strncmp (ROMId, "APB", 3) == 0 || - ((strncmp (ROMName, "Parlor", 6) == 0 || - strcmp (ROMName, "HEIWA Parlor!Mini8") == 0 || - strncmp (ROMName, "SANKYO Fever! ̨°ÊÞ°!", 21) == 0) && - strcmp (CompanyId, "A0") == 0) || - strcmp (ROMName, "DARK KINGDOM") == 0 || - strcmp (ROMName, "ZAN3 SFC") == 0 || - strcmp (ROMName, "HIOUDEN") == 0 || - strcmp (ROMName, "ÃݼɳÀ") == 0 || //Tenshi no Uta - strcmp (ROMName, "FORTUNE QUEST") == 0 || - strcmp (ROMName, "FISHING TO BASSING") == 0 || - strncmp (ROMName, "TokyoDome '95Battle 7", 21) == 0 || - strcmp (ROMName, "OHMONO BLACKBASS") == 0 || - strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 || - strcmp (ROMName, "MASTERS") ==0 || //Augusta 2 J - strcmp (ROMName, "SFC ¶ÒÝײÀÞ°") == 0 || //Kamen Rider - strncmp (ROMName, "LETs PACHINKO(", 14) == 0) //A set of BS games - { - IAPU.OneCycle = 15; - } - - - //Specific game fixes - - Settings.StarfoxHack = strcmp (ROMName, "STAR FOX") == 0 || - strcmp (ROMName, "STAR WING") == 0; - Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 || - strcmp (ROMName, "DIRT RACER") == 0 || - Settings.StarfoxHack; - - - if((strcmp(ROMName, "LEGEND")==0&&!Settings.PAL)|| - strcmp(ROMName, "King Arthurs World")==0) - { - SNESGameFixes.EchoOnlyOutput=TRUE; - } - - - Settings.DaffyDuck = (strcmp (ROMName, "DAFFY DUCK: MARV MISS") == 0) || - (strcmp (ROMName, "ROBOCOP VS THE TERMIN") == 0) || - (strcmp (ROMName, "ROBOCOP VS TERMINATOR") == 0); //ROBOCOP VS THE TERMIN - Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; - - //OAM hacks because we don't fully understand the - //behavior of the SNES. - - //Totally wacky display... - //seems to need a disproven behavior, so - //we're definitely overlooking some other bug? - if(strncmp(ROMName, "UNIRACERS", 9)==0) - SNESGameFixes.Uniracers=true; - - - //is this even useful now? - if (strcmp (ROMName, "ALIENS vs. PREDATOR") == 0) - SNESGameFixes.alienVSpredetorFix = TRUE; - - if (strcmp (ROMName, "½°Ȩ̂߰нÀ") == 0 || //Super Famista - strcmp (ROMName, "½°Ȩ̂߰нÀ 2") == 0 || //Super Famista 2 - strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 || - strcmp (ROMName, "GANBA LEAGUE") == 0) - { - SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE; - } - - if (strcmp (ROMName, "FURAI NO SIREN") == 0) - SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE; - - //CPU timing hacks - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * - Settings.CyclesPercentage) / 100; - - //no need to ifdef for right now... -//#ifdef HDMA_HACKS - - // A Couple of HDMA related hacks - Lantus - if ((strcmp(ROMName, "SFX SUPERBUTOUDEN2")==0) || - (strcmp(ROMName, "ALIEN vs. PREDATOR")==0) || - (strcmp(ROMName, "STONE PROTECTORS")==0) || - (strcmp(ROMName, "SUPER BATTLETANK 2")==0)) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 130) / 100; - - if(strcmp(ROMName, "HOME IMPROVEMENT")==0) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 200) / 100; - - // End HDMA hacks -//#endif - - - if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100) - // Street Racer - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100; - - // Power Rangers Fight - if (strncmp (ROMId, "A3R", 3) == 0 || - // Clock Tower - strncmp (ROMId, "AJE", 3) == 0) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100; - - - if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100) - // Mortal Kombat 3. Fixes cut off speech sample - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; - - //Darkness Beyond Twilight - //Crimson beyond blood that flows - //buried in the stream of time - //is where your power grows - //I pledge myself to conquer - //all the foes who stand - //before the might gift betsowed - //in my unworthy hand - if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 && - Settings.CyclesPercentage == 100) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100; - - -#ifdef DETECT_NASTY_FX_INTERLEAVE -//XXX: Test without these. Win32 port indicates they aren't needed? -//Apparently are needed! - if (strcmp (ROMName, "WILD TRAX") == 0 || - strcmp (ROMName, "STAR FOX 2") == 0 || - strcmp (ROMName, "YOSSY'S ISLAND") == 0 || - strcmp (ROMName, "YOSHI'S ISLAND") == 0) - CPU.TriedInterleavedMode2 = TRUE; -#endif - - // Start Trek: Deep Sleep 9 - if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; - - - //SA-1 Speedup settings - SA1.WaitAddress = NULL; - SA1.WaitByteAddress1 = NULL; - SA1.WaitByteAddress2 = NULL; - - /* Bass Fishing */ - if (strcmp (ROMId, "ZBPJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1; - SA1.WaitByteAddress1 = FillRAM + 0x304a; - } - /* DAISENRYAKU EXPERTWW2 */ - if (strcmp (ROMId, "AEVJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* debjk2 */ - if (strcmp (ROMId, "A2DJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62; - } - /* Dragon Ballz HD */ - if (strcmp (ROMId, "AZIJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x008083 >> MEMMAP_SHIFT] + 0x8083; - SA1.WaitByteAddress1 = FillRAM + 0x3020; - } - /* SFC SDGUNDAMGNEXT */ - if (strcmp (ROMId, "ZX3J") == 0) - { - SA1.WaitAddress = SA1.Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2; - SA1.WaitByteAddress1 = FillRAM + 0x30c4; - } - /* ShougiNoHanamichi */ - if (strcmp (ROMId, "AARJ") == 0) - { - SA1.WaitAddress = SA1.Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a; - SA1.WaitByteAddress1 = SRAM + 0x0c64; - SA1.WaitByteAddress2 = SRAM + 0x0c66; - } - /* KATO HIFUMI9DAN SYOGI */ - if (strcmp (ROMId, "A23J") == 0) - { - SA1.WaitAddress = SA1.Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037; - SA1.WaitByteAddress1 = SRAM + 0x0c06; - SA1.WaitByteAddress2 = SRAM + 0x0c08; - } - /* idaten */ - if (strcmp (ROMId, "AIIJ") == 0) - { - SA1.WaitAddress = SA1.Map [0xc100be >> MEMMAP_SHIFT] + 0x00be; - SA1.WaitByteAddress1 = SRAM + 0x1002; - SA1.WaitByteAddress2 = SRAM + 0x1004; - } - /* igotais */ - if (strcmp (ROMId, "AITJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7; - } - /* J96 DREAM STADIUM */ - if (strcmp (ROMId, "AJ6J") == 0) - { - SA1.WaitAddress = SA1.Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a; - } - /* JumpinDerby */ - if (strcmp (ROMId, "AJUJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926; - } - /* JKAKINOKI SHOUGI */ - if (strcmp (ROMId, "AKAJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070; - } - /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */ - if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0) - { - SA1.WaitAddress = SA1.Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4; - SA1.WaitByteAddress1 = SRAM + 0x72a4; - } - /* KIRBY SUPER DELUXE JAP */ - if (strcmp (ROMId, "AKFJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - /* KIRBY SUPER DELUXE US */ - if (strcmp (ROMId, "AKFE") == 0) - { - SA1.WaitAddress = SA1.Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - /* SUPER MARIO RPG JAP & US */ - if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0) - { - SA1.WaitAddress = SA1.Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* marvelous.zip */ - if (strcmp (ROMId, "AVRJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2; - SA1.WaitByteAddress1 = FillRAM + 0x3024; - } - /* AUGUSTA3 MASTERS NEW */ - if (strcmp (ROMId, "AO3J") == 0) - { - SA1.WaitAddress = SA1.Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - /* OSHABERI PARODIUS */ - if (strcmp (ROMId, "AJOJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5; - } - /* PANIC BOMBER WORLD */ - if (strcmp (ROMId, "APBJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x00857a >> MEMMAP_SHIFT] + 0x857a; - } - /* PEBBLE BEACH NEW */ - if (strcmp (ROMId, "AONJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - /* PGA EUROPEAN TOUR */ - if (strcmp (ROMId, "AEPE") == 0) - { - SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - /* PGA TOUR 96 */ - if (strcmp (ROMId, "A3GE") == 0) - { - SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - /* POWER RANGERS 4 */ - if (strcmp (ROMId, "A4RE") == 0) - { - SA1.WaitAddress = SA1.Map [0x009899 >> MEMMAP_SHIFT] + 0x9899; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* PACHISURO PALUSUPE */ - if (strcmp (ROMId, "AGFJ") == 0) - { - // Never seems to turn on the SA-1! - } - /* SD F1 GRAND PRIX */ - if (strcmp (ROMId, "AGFJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc; - } - /* SHOUGI MARJONG */ - if (strcmp (ROMId, "ASYJ") == 0) - { - SA1.WaitAddress = SA1.Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc; - SA1.WaitByteAddress1 = SRAM + 0x7ffe; - SA1.WaitByteAddress2 = SRAM + 0x7ffc; - } - /* shogisai2 */ - if (strcmp (ROMId, "AX2J") == 0) - { - SA1.WaitAddress = SA1.Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675; - } - - /* SHINING SCORPION */ - if (strcmp (ROMId, "A4WJ") == 0) - { - SA1.WaitAddress = SA1.Map [0xc048be >> MEMMAP_SHIFT] + 0x48be; - } - /* SHIN SHOUGI CLUB */ - if (strcmp (ROMId, "AHJJ") == 0) - { - SA1.WaitAddress = SA1.Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a; - SA1.WaitByteAddress1 = SRAM + 0x0806; - SA1.WaitByteAddress2 = SRAM + 0x0808; - } - - - //Other - - // Additional game fixes by sanmaiwashi ... - if (strcmp (ROMName, "SFX ŲĶÞÝÀÞÑÓɶÞÀØ 1") == 0) //Gundam Knight Story - { - bytes0x2000 [0xb18] = 0x4c; - bytes0x2000 [0xb19] = 0x4b; - bytes0x2000 [0xb1a] = 0xea; - SNESGameFixes.SRAMInitialValue = 0x6b; - } - - - // HITOMI3 - if (strcmp (ROMName, "HITOMI3") == 0) - { - Memory.SRAMSize = 1; - SRAMMask = Memory.SRAMSize ? - ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; - } - - //sram value fixes - if (strcmp (Memory.ROMName, "SUPER DRIFT OUT") == 0 || - strcmp(Memory.ROMName, "SATAN IS OUR FATHER!") == 0 || - strcmp (ROMName, "goemon 4") == 0) - SNESGameFixes.SRAMInitialValue = 0x00; - -#if 0 - if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0) - { - for (c = 0x200; c < 0x400; c += 16) - { - for (int i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000]; - BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE; - } - } - WriteProtectROM (); - } -#endif - -#define RomPatch(adr,ov,nv) \ - if (ROM [adr] == ov) \ - ROM [adr] = nv - - - // Love Quest - if (strcmp (ROMName, "LOVE QUEST") == 0) - { - RomPatch (0x1385ec, 0xd0, 0xea); - RomPatch (0x1385ed, 0xb2, 0xea); - } - //BNE D0 into nops - - //seems like the next instruction is a BRA - //otherwise, this one's too complex for MKendora - // Nangoku Syonen Papuwa Kun - if (strcmp (ROMName, "NANGOKUSYONEN PAPUWA") == 0) - RomPatch (0x1f0d1, 0xa0, 0x6b); - //turns an LDY into an RTL? - - //this is a cmp on $00:2140 - // Super Batter Up - if (strcmp (ROMName, "Super Batter Up") == 0) - { - RomPatch (0x27ae0, 0xd0, 0xea); - RomPatch (0x27ae1, 0xfa, 0xea); - } - //BNE -} - -// Read variable size MSB int from a file -static long ReadInt (FILE *f, unsigned nbytes) -{ - long v = 0; - while (nbytes--) - { - int c = fgetc(f); - if (c == EOF) - return -1; - v = (v << 8) | (c & 0xFF); - } - return (v); -} - -#define IPS_EOF 0x00454F46l - -void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, - int32 &rom_size) -{ - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char fname [_MAX_PATH + 1]; - FILE *patch_file = NULL; - long offset = header ? 512 : 0; - - _splitpath (rom_filename, drive, dir, name, ext); - _makepath (fname, drive, dir, name, "ips"); - - if (!(patch_file = fopen (fname, "rb"))) - { - if (!(patch_file = fopen (S9xGetFilename (".ips"), "rb"))) - return; - } - - if (fread ((unsigned char*)fname, 1, 5, patch_file) != 5 || - strncmp (fname, "PATCH", 5) != 0) - { - fclose (patch_file); - return; - } - - int32 ofs; - - for (;;) - { - long len; - long rlen; - int rchar; - - ofs = ReadInt (patch_file, 3); - if (ofs == -1) - goto err_eof; - - if (ofs == IPS_EOF) - break; - - ofs -= offset; - - len = ReadInt (patch_file, 2); - if (len == -1) - goto err_eof; - - /* Apply patch block */ - if (len) - { - if (ofs + len > MAX_ROM_SIZE) - goto err_eof; - - while (len--) - { - rchar = fgetc (patch_file); - if (rchar == EOF) - goto err_eof; - ROM [ofs++] = (uint8) rchar; - } - if (ofs > rom_size) - rom_size = ofs; - } - else - { - rlen = ReadInt (patch_file, 2); - if (rlen == -1) - goto err_eof; - - rchar = fgetc (patch_file); - if (rchar == EOF) - goto err_eof; - - if (ofs + rlen > MAX_ROM_SIZE) - goto err_eof; - - while (rlen--) - ROM [ofs++] = (uint8) rchar; - - if (ofs > rom_size) - rom_size = ofs; - } - } - - // Check if ROM image needs to be truncated - ofs = ReadInt (patch_file, 3); - if (ofs != -1 && ofs - offset < rom_size) - { - // Need to truncate ROM image - rom_size = ofs - offset; - } - fclose (patch_file); - return; - -err_eof: - if (patch_file) - fclose (patch_file); -} - -int is_bsx(unsigned char *p) -{ - unsigned c; - - if ( p[0x19] & 0x4f ) - goto notbsx; - c = p[0x1a]; - if ( (c != 0x33) && (c != 0xff) ) // 0x33 = Manufacturer: Nintendo - goto notbsx; - c = (p[0x17] << 8) | p[0x16]; - if ( (c != 0x0000) && (c != 0xffff) ) - { - if ( (c & 0x040f) != 0 ) - goto notbsx; - if ( (c & 0xff) > 0xc0 ) - goto notbsx; - } - c = p[0x18]; - if ( (c & 0xce) || ((c & 0x30)==0) ) - goto notbsx; - if ( (p[0x15] & 0x03) != 0 ) - goto notbsx; - c = p[0x13]; - if ( (c != 0x00) && (c != 0xff) ) - goto notbsx; - if ( p[0x14] != 0x00 ) - goto notbsx; - if ( bs_name(p) != 0 ) - goto notbsx; - return 0; // It's a Satellaview ROM! -notbsx: - return -1; -} -int bs_name(unsigned char *p) -{ - unsigned c; - int lcount; - int numv; // number of valid name characters seen so far - numv = 0; - for ( lcount = 16; lcount > 0; lcount-- ) - { - if ( check_char( c = *p++ ) != 0 ) - { - c = *p++; - if ( c < 0x20 ) - { - if ( (numv != 0x0b) || (c != 0) ) // Dr. Mario Hack - goto notBsName; - } - - numv++; - lcount--; - continue; - } - else - { - if ( c == 0 ) - { - if ( numv == 0 ) - goto notBsName; - continue; - } - - if ( c < 0x20 ) - goto notBsName; - if ( c >= 0x80 ) - { - if ( (c < 0xa0) || ( c >= 0xf0 ) ) - goto notBsName; - } - numv++; - } - } - if ( numv > 0 ) - return 0; -notBsName: - return -1; -} -int check_char(unsigned c) -{ - if ( ( c & 0x80 ) == 0 ) - return 0; - if ( ( c - 0x20 ) & 0x40 ) - return 1; - else - return 0; -} - -void CMemory::ParseSNESHeader(uint8* RomHeader) -{ - Memory.SRAMSize = RomHeader [0x28]; - strncpy (ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); - ROMSpeed = RomHeader [0x25]; - ROMType = RomHeader [0x26]; - ROMSize = RomHeader [0x27]; - ROMChecksum = RomHeader [0x2e] + (RomHeader [0x2f] << 8); - ROMComplementChecksum = RomHeader [0x2c] + (RomHeader [0x2d] << 8); - ROMRegion= RomHeader[0x29]; - // memmove converted: Different mallocs [Neb] - memcpy (ROMId, &RomHeader [0x2], 4); - if(RomHeader[0x2A]==0x33) - // memmove converted: Different mallocs [Neb] - memcpy (CompanyId, &RomHeader [0], 2); - else sprintf(CompanyId, "%02X", RomHeader[0x2A]); -} - -#undef INLINE -#define INLINE -#include "getset.h" - diff --git a/source/obc1.c b/source/obc1.c new file mode 100644 index 0000000..763e7cc --- /dev/null +++ b/source/obc1.c @@ -0,0 +1,204 @@ +/**************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#include "memmap.h" +#include "obc1.h" + +static uint8 *OBC1_RAM = NULL; + +int OBC1_Address; +int OBC1_BasePtr; +int OBC1_Shift; + +extern "C" +{ +uint8 GetOBC1 (uint16 Address) +{ + switch(Address) { + case 0x7ff0: + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)]; + + case 0x7ff1: + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1]; + + case 0x7ff2: + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2]; + + case 0x7ff3: + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3]; + + case 0x7ff4: + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; + } + + return OBC1_RAM[Address & 0x1fff]; +} + +void SetOBC1 (uint8 Byte, uint16 Address) +{ + switch(Address) { + case 0x7ff0: + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)] = Byte; + break; + } + + case 0x7ff1: + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1] = Byte; + break; + } + + case 0x7ff2: + { + OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2] = Byte; + break; + } + + case 0x7ff3: + { + OBC1_RAM[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; + break; + } + + case 0x7ff5: + { + if (Byte & 1) + OBC1_BasePtr = 0x1800; + else + OBC1_BasePtr = 0x1c00; + + OBC1_RAM[0x1ff5] = Byte; + break; + } + + case 0x7ff6: + { + OBC1_Address = Byte & 0x7f; + OBC1_Shift = (Byte & 3) << 1; + break; + } + + default: + OBC1_RAM[Address & 0x1fff] = Byte; + break; + } +} + +uint8 *GetBasePointerOBC1(uint32 Address) +{ + return Memory.FillRAM; +} + +uint8 *GetMemPointerOBC1(uint32 Address) +{ + return (Memory.FillRAM + (Address & 0xffff)); +} + +void ResetOBC1() +{ + OBC1_Address = 0; + OBC1_BasePtr = 0x1c00; + OBC1_Shift = 0; + OBC1_RAM = &Memory.FillRAM[0x6000]; + + memset(OBC1_RAM, 0x00, 0x2000); +} + +} diff --git a/source/obc1.cpp b/source/obc1.cpp deleted file mode 100644 index 763e7cc..0000000 --- a/source/obc1.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#include "memmap.h" -#include "obc1.h" - -static uint8 *OBC1_RAM = NULL; - -int OBC1_Address; -int OBC1_BasePtr; -int OBC1_Shift; - -extern "C" -{ -uint8 GetOBC1 (uint16 Address) -{ - switch(Address) { - case 0x7ff0: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)]; - - case 0x7ff1: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1]; - - case 0x7ff2: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2]; - - case 0x7ff3: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3]; - - case 0x7ff4: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; - } - - return OBC1_RAM[Address & 0x1fff]; -} - -void SetOBC1 (uint8 Byte, uint16 Address) -{ - switch(Address) { - case 0x7ff0: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)] = Byte; - break; - } - - case 0x7ff1: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1] = Byte; - break; - } - - case 0x7ff2: - { - OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2] = Byte; - break; - } - - case 0x7ff3: - { - OBC1_RAM[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; - break; - } - - case 0x7ff5: - { - if (Byte & 1) - OBC1_BasePtr = 0x1800; - else - OBC1_BasePtr = 0x1c00; - - OBC1_RAM[0x1ff5] = Byte; - break; - } - - case 0x7ff6: - { - OBC1_Address = Byte & 0x7f; - OBC1_Shift = (Byte & 3) << 1; - break; - } - - default: - OBC1_RAM[Address & 0x1fff] = Byte; - break; - } -} - -uint8 *GetBasePointerOBC1(uint32 Address) -{ - return Memory.FillRAM; -} - -uint8 *GetMemPointerOBC1(uint32 Address) -{ - return (Memory.FillRAM + (Address & 0xffff)); -} - -void ResetOBC1() -{ - OBC1_Address = 0; - OBC1_BasePtr = 0x1c00; - OBC1_Shift = 0; - OBC1_RAM = &Memory.FillRAM[0x6000]; - - memset(OBC1_RAM, 0x00, 0x2000); -} - -} diff --git a/source/ppu.c b/source/ppu.c new file mode 100644 index 0000000..4717f1d --- /dev/null +++ b/source/ppu.c @@ -0,0 +1,3132 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#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 "sdd1.h" +#include "srtc.h" +#include "spc7110.h" + +#ifndef ZSNES_FX +#include "fxemu.h" +#include "fxinst.h" +extern struct FxInit_s SuperFX; +#else +EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); +EXTERN_C uint8 S9xSuperFXReadReg (uint32); +#endif + +uint32 justifiers=0xFFFF00AA; +uint8 in_bit=0; + +extern uint8 *HDMAMemPointers [8]; + +void S9xLatchCounters (bool force) +{ + if(!force && !(Memory.FillRAM[0x4213] & 0x80)) return; + +#if 0 +# ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +# endif +#endif + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) CPU.V_Counter; + PPU.HBeamPosLatched = (uint16) ((CPU.Cycles * SNES_HCOUNTER_MAX) / Settings.H_Max); + + // 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; +} + +void S9xUpdateJustifiers(); + +void S9xUpdateHTimer () +{ + if (PPU.HTimerEnabled) + { + PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; + if (PPU.HTimerPosition == Settings.H_Max || + PPU.HTimerPosition == Settings.HBlankStart) + { + PPU.HTimerPosition--; + } + + if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) + { + if (PPU.HTimerPosition < CPU.Cycles) + { + // Missed the IRQ on this line already + if (CPU.WhichEvent == HBLANK_END_EVENT || + CPU.WhichEvent == HTIMER_AFTER_EVENT) + { + CPU.WhichEvent = HBLANK_END_EVENT; + CPU.NextEvent = Settings.H_Max; + } + else + { + CPU.WhichEvent = HBLANK_START_EVENT; + CPU.NextEvent = Settings.HBlankStart; + } + } + else + { + if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || + CPU.WhichEvent == HBLANK_START_EVENT) + { + if (PPU.HTimerPosition > Settings.HBlankStart) + { + // HTimer was to trigger before h-blank start, + // now triggers after start of h-blank + CPU.NextEvent = Settings.HBlankStart; + CPU.WhichEvent = HBLANK_START_EVENT; + } + else + { + CPU.NextEvent = PPU.HTimerPosition; + CPU.WhichEvent = HTIMER_BEFORE_EVENT; + } + } + else + { + CPU.WhichEvent = HTIMER_AFTER_EVENT; + CPU.NextEvent = PPU.HTimerPosition; + } + } + } + } +} + +void S9xFixColourBrightness () +{ + IPPU.XB = mul_brightness [PPU.Brightness]; + for (int i = 0; i < 256; i++) + { + IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; + IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; + IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; + IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i], + IPPU.Blue [i]); + } +} + +/******************************************************************************/ +/* 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); + if (Address <= 0x2183) + { + switch (Address) + { + case 0x2100: + // Brightness and screen blank bit + if (Byte != Memory.FillRAM [0x2100]) + { + 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; + } + } + break; + + case 0x2101: + // Sprite (OBJ) tile address + if (Byte != Memory.FillRAM [0x2101]) + { + FLUSH_REDRAW (); + PPU.OBJNameBase = (Byte & 3) << 14; + PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; + PPU.OBJSizeSelect = (Byte >> 5) & 7; + IPPU.OBJChanged = TRUE; + } + break; + + case 0x2102: + // Sprite write address (low) + PPU.OAMAddr = ((Memory.FillRAM[0x2103]&1)<<8) | Byte; + PPU.OAMFlip = 2; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + 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; + } + } else { + if (PPU.FirstSprite != 0) + { + PPU.FirstSprite = 0; + IPPU.OBJChanged = TRUE; + } + } + 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); + if(PPU.BGMode==5||PPU.BGMode==6) + IPPU.Interlace = Memory.FillRAM[0x2133]&1; + } + break; + + case 0x2106: + // Mosaic pixel size and enable + if (Byte != Memory.FillRAM [0x2106]) + { + FLUSH_REDRAW (); + PPU.Mosaic = (Byte >> 4) + 1; + PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1; + PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1; + PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1; + PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; + } + break; + case 0x2107: // [BG0SC] + case 0x2108: // [BG1SC] + case 0x2109: // [BG2SC] + case 0x210A: // [BG3SC] + if (Byte != Memory.FillRAM [Address]) + { + FLUSH_REDRAW (); + PPU.BG[Address - 0x2107].SCSize = Byte & 3; + PPU.BG[Address - 0x2107].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; + + + //This is the Theme Park fix - it appears all these registers + //share a previous byte value for setting them. + + case 0x210D: + //TEST9 if(last_written != 0x210d) PPU.BGnxOFSbyte = 0; + PPU.BG[0].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[0].HOffset = %04x %d)\n", Byte, Address, PPU.BG[0].HOffset, CPU.V_Counter); + break; + + case 0x210E: + PPU.BG[0].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[0].VOffset = %04x %d)\n", Byte, Address, PPU.BG[0].VOffset, CPU.V_Counter); + break; + + case 0x210F: + PPU.BG[1].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[1].HOffset = %04x %d)\n", Byte, Address, PPU.BG[1].HOffset, CPU.V_Counter); + break; + + case 0x2110: + PPU.BG[1].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[1].VOffset = %04x %d)\n", Byte, Address, PPU.BG[1].VOffset, CPU.V_Counter); + break; + + case 0x2111: + PPU.BG[2].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[2].HOffset = %04x %d)\n", Byte, Address, PPU.BG[2].HOffset, CPU.V_Counter); + break; + + case 0x2112: + PPU.BG[2].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[2].VOffset = %04x %d)\n", Byte, Address, PPU.BG[2].VOffset, CPU.V_Counter); + break; + + case 0x2113: + PPU.BG[3].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[3].HOffset = %04x %d)\n", Byte, Address, PPU.BG[3].HOffset, CPU.V_Counter); + break; + + case 0x2114: + PPU.BG[3].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[3].VOffset = %04x %d)\n", Byte, Address, PPU.BG[3].VOffset, CPU.V_Counter); + break; + + //end Theme Park + + 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: + case 3: + PPU.VMA.Increment = 128; + break; + } + if (Byte & 0x0c) + { + static uint16 IncCount [4] = { 0, 32, 64, 128 }; + static uint16 Shift [4] = { 0, 5, 6, 7 }; +// 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.MatrixA >> 8) & 0xff) | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + break; + case 0x211c: + // Mode 7 matrix B (low & high) + PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + break; + case 0x211d: + // Mode 7 matrix C (low & high) + PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8); + break; + case 0x211e: + // Mode 7 matrix D (low & high) + PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); + break; + case 0x211f: + // Mode 7 centre of rotation X (low & high) + PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8); + break; + case 0x2120: + // Mode 7 centre of rotation Y (low & high) + PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); + 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; + } + 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; + } + 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; + } + 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 (); + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; + return; + } + break; + case 0x212e: + // Window mask designation for main screen ? + case 0x212f: + // Window mask designation for sub-screen ? + if (Byte != Memory.FillRAM [Address]) + { + FLUSH_REDRAW (); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2130: + // Fixed colour addition or screen addition + if (Byte != Memory.FillRAM [0x2130]) + { + FLUSH_REDRAW (); + PPU.RecomputeClipWindows = TRUE; + } + 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 + 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]) + { + if (Byte & 0x04) + { + PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; + if(IPPU.DoubleHeightPixels) + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + else + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + } + else PPU.ScreenHeight = SNES_HEIGHT; + + //if((Byte & 1)&&(PPU.BGMode==5||PPU.BGMode==6)) + //IPPU.Interlace=1; + 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.InterlaceSprites=0; + // IPPU.InterlaceSprites = (Byte&2)>>1; + } + + } + break; + case 0x2134: + case 0x2135: + case 0x2136: + // Matrix 16bit x 8bit multiply result (read-only) + /* fall through */ + case 0x2137: + // Software latch for horizontal and vertical timers (read-only) + /* fall through */ + case 0x2138: + // OAM read data (read-only) + /* fall through */ + case 0x2139: + case 0x213a: + // VRAM read data (read-only) + /* fall through */ + case 0x213b: + // CG-RAM read data (read-only) + /* fall through */ + case 0x213c: + case 0x213d: + // Horizontal and vertical (low/high) read counter (read-only) + /* fall through */ + case 0x213e: + // PPU status (time over and range over) + /* fall through */ + 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 SPCTOOL + _SPCInPB (Address & 3, Byte); +#else + // CPU.Flags |= DEBUG_MODE_FLAG; + Memory.FillRAM [Address] = Byte; + IAPU.RAM [(Address & 3) + 0xf4] = Byte; +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; +#endif +#endif // SPCTOOL + break; + case 0x2180: + REGISTER_2180(Byte); + break; + case 0x2181: + PPU.WRAM &= 0x1FF00; + PPU.WRAM |= Byte; + break; + case 0x2182: + PPU.WRAM &= 0x100FF; + PPU.WRAM |= Byte << 8; + break; + case 0x2183: + PPU.WRAM &= 0x0FFFF; + PPU.WRAM |= Byte << 16; + PPU.WRAM &= 0x1FFFF; + 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 < 0x3300) + { + if (!Settings.SuperFX) + { + return; + } + +#ifdef ZSNES_FX + Memory.FillRAM [Address] = Byte; + if (Address < 0x3040) + S9xSuperFXWriteReg (Byte, Address); +#else + switch (Address) + { + case 0x3030: + if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) + { + Memory.FillRAM [Address] = Byte; + // Go flag has been changed + if (Byte & FLG_G) + S9xSuperFXExec (); + else + FxFlushCache (); + } + else + Memory.FillRAM [Address] = Byte; + break; + + case 0x3031: + case 0x3033: + case 0x3037: + case 0x3039: + case 0x303a: + case 0x303f: + Memory.FillRAM [Address] = Byte; + break; + case 0x3034: + case 0x3036: + Memory.FillRAM [Address] = Byte & 0x7f; + break; + case 0x3038: + Memory.FillRAM [Address] = Byte; + fx_dirtySCBR(); + break; + case 0x303b: + break; + case 0x303c: + Memory.FillRAM [Address] = Byte; + fx_updateRamBank(Byte); + break; + case 0x301f: + Memory.FillRAM [Address] = Byte; + Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; + S9xSuperFXExec (); + return; + + default: + Memory.FillRAM[Address] = Byte; + if (Address >= 0x3100) + { + FxCacheWriteAccess (Address); + } + break; + } +#endif + return; + } + } + Memory.FillRAM[Address] = Byte; + +} + +/******************************************************************************/ +/* S9xGetPPU() */ +/* This function retrieves a PPU Register */ +/******************************************************************************/ +uint8 S9xGetPPU (uint16 Address) +{ + uint8 byte = OpenBus; + if(Address<0x2100)//not a real PPU reg + return OpenBus; //treat as unmapped memory returning last byte on the bus + if (Address <= 0x2190) + { + switch (Address) + { + case 0x2100: + case 0x2101: + case 0x2102: + case 0x2103: + return OpenBus; + + case 0x2104: + case 0x2105: + case 0x2106: + case 0x2108: + case 0x2109: + case 0x210a: + case 0x2115: + case 0x2116: + case 0x2118: + case 0x2119: + case 0x211a: + case 0x2124: + case 0x2125: + case 0x2126: + case 0x2128: + case 0x2129: + case 0x212a: + return PPU.OpenBus1; + + case 0x2107: + case 0x2117: + case 0x2121: + case 0x2122: + case 0x2123: + case 0x2127: + case 0x212b: + case 0x212c: + case 0x212d: + case 0x212e: + case 0x212f: + case 0x2130: + case 0x2131: + case 0x2132: + case 0x2133: + return OpenBus; + + case 0x210b: + case 0x210c: + case 0x210d: + case 0x210e: + case 0x210f: + case 0x2110: + case 0x2111: + case 0x2112: + case 0x2113: + return OpenBus; + + case 0x2114: + case 0x211b: + case 0x211c: + case 0x211d: + case 0x211e: + case 0x211f: + case 0x2120: + 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; + } + 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)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + } + } 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; + } + } + } + PPU.OAMFlip ^= 1; + return (PPU.OpenBus1 = byte); + + case 0x2139: + // Read vram low byte +#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 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 + 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 + 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 + 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 + PPU.VBeamFlip = PPU.HBeamFlip = 0; + //neviksti found a 2 and a 3 here. SNEeSe uses a 3. + //XXX: field flags not emulated + return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0)| Model->_5C78) | (~PPU.OpenBus2 & 0x20); + + 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 SPCTOOL + return ((uint8) _SPCOutP [Address & 3]); +#else + // CPU.Flags |= DEBUG_MODE_FLAG; +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; +#endif + if (Settings.APUEnabled) + { +#ifdef CPU_SHUTDOWN +// CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + if (SNESGameFixes.APU_OutPorts_ReturnValueFix && + Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) + { + return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : + (rand() & 0xff)); + } + + return (APU.OutPorts [Address & 3]); + } + + switch (Settings.SoundSkipMethod) + { + case 0: + case 1: + case 3: + CPU.BranchSkip = TRUE; + break; + case 2: + 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]); +#endif // SPCTOOL + + case 0x2180: + // Read WRAM + byte = Memory.RAM [PPU.WRAM++]; + PPU.WRAM &= 0x1FFFF; + break; + case 0x2181: + case 0x2182: + case 0x2183: + default: + return OpenBus; + } + } + else + { + if (Settings.SA1) + return (S9xGetSA1 (Address)); + + if (Address <= 0x2fff || Address >= 0x3300) + { + 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: + 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.PCAtOpcodeStart; +#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.PCAtOpcodeStart; + } + 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; +// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, byte, Address); + + if (Address < 0x4200) + { + CPU.Cycles += ONE_CYCLE; + switch (Address) + { + case 0x4016: + // S9xReset reading of old-style joypads + if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) + { + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + } + break; + case 0x4017: + break; + default: + break; + } + } + else + switch (Address) + { + case 0x4200: + // NMI, V & H IRQ and joypad reading enable flags + if (byte & 0x20) + { + //if(!SNESGameFixes.umiharakawaseFix && PPU.IRQVBeamPos==262) fprintf(stderr, "PPU.IRQVBeamPos = %d, CPU.V_Counter = %d\n", PPU.IRQVBeamPos, CPU.V_Counter); + if (!PPU.VTimerEnabled) + { + PPU.VTimerEnabled = TRUE; + if (PPU.HTimerEnabled) + S9xUpdateHTimer (); + else + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + } + else + { + PPU.VTimerEnabled = FALSE; +// if (SNESGameFixes.umiharakawaseFix) +// byte &= ~0x20; + } + + if (byte & 0x10) + { + if (!PPU.HTimerEnabled) + { + PPU.HTimerEnabled = TRUE; + S9xUpdateHTimer (); + } + } + else + { + // No need to check for HTimer being disabled as the scanline + // event trigger code won't trigger an H-IRQ unless its enabled. + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + } + if (!Settings.DaffyDuck) + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + if ((byte & 0x80) && + !(Memory.FillRAM [0x4200] & 0x80) && + CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && + CPU.V_Counter <= PPU.ScreenHeight + + (SNESGameFixes.alienVSpredetorFix ? 25 : 15) && //jyam 15->25 alien vs predetor +// 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... + (Memory.FillRAM [0x4210] & 0x80) && + !CPU.NMIActive) + { + CPU.Flags |= NMI_FLAG; + CPU.NMIActive = TRUE; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } + break; + case 0x4201: + if((byte&0x80)==0 && (Memory.FillRAM[0x4213]&0x80)==0x80) + S9xLatchCounters(1); + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = byte; + break; + case 0x4202: + // Multiplier (for multply) + break; + case 0x4203: + { + // Multiplicand + uint32 res = Memory.FillRAM[0x4202] * byte; + +#if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS + // assume malloc'd memory is 2-byte aligned + * ((uint16 *) &Memory.FillRAM[0x4216]) = res; +#else + Memory.FillRAM[0x4216] = (uint8) res; + Memory.FillRAM[0x4217] = (uint8) (res >> 8); +#endif + break; + } + case 0x4204: + case 0x4205: + // Low and high muliplier (for divide) + break; + case 0x4206: + { +#if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS + // assume malloc'd memory is 2-byte aligned + uint16 a = *((uint16 *) &Memory.FillRAM[0x4204]); +#else + uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); +#endif + uint16 div = byte ? a / byte : 0xffff; + uint16 rem = byte ? a % byte : a; + +#if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS + // assume malloc'd memory is 2-byte aligned + * ((uint16 *) &Memory.FillRAM[0x4214]) = div; + * ((uint16 *) &Memory.FillRAM[0x4216]) = rem; +#else + Memory.FillRAM[0x4214] = (uint8)div; + Memory.FillRAM[0x4215] = div >> 8; + Memory.FillRAM[0x4216] = (uint8)rem; + Memory.FillRAM[0x4217] = rem >> 8; +#endif + break; + } + case 0x4207: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer (); + break; + + case 0x4208: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer (); + + break; + + case 0x4209: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer (); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420A: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer (); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420B: + 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 (Settings.DisableHDMA) + byte = 0; + Memory.FillRAM[0x420c] = byte; + IPPU.HDMA = byte; + 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; + } + 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) + /* fall through */ + case 0x4213: + // I/O Port (read-only) + /* fall through */ + case 0x4214: + case 0x4215: + // Quotent of divide (read-only) + /* fall through */ + case 0x4216: + case 0x4217: + // Multiply product (read-only) + /* fall through */ + 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: + d = (Address >> 4) & 0x7; + DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; + DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; + DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; + DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; + DMA[d].TransferMode = (byte & 7); + break; + + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + DMA[((Address >> 4) & 0x7)].BAddress = byte; + break; + + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF00; + DMA[d].AAddress |= byte; + break; + + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF; + DMA[d].AAddress |= byte << 8; + break; + + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + DMA[((Address >> 4) & 0x7)].ABank = byte; + HDMAMemPointers[((Address >> 4) & 0x7)]=NULL; + + break; + + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF00; + DMA[d].TransferBytes |= byte; + DMA[d].IndirectAddress &= 0xff00; + DMA[d].IndirectAddress |= byte; + HDMAMemPointers[d]=NULL; + break; + + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF; + DMA[d].TransferBytes |= byte << 8; + DMA[d].IndirectAddress &= 0xff; + DMA[d].IndirectAddress |= byte << 8; + HDMAMemPointers[d]=NULL; + break; + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; + HDMAMemPointers[d]=NULL; + break; + + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + d = (Address >> 4) & 7; + DMA[d].Address &= 0xff00; + DMA[d].Address |= byte; + HDMAMemPointers[d] = NULL; + break; + + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + d = (Address >> 4) & 0x7; + DMA[d].Address &= 0xff; + DMA[d].Address |= byte << 8; + HDMAMemPointers[d] = NULL; + break; + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + d = (Address >> 4) & 0x7; + DMA[d].LineCount = byte & 0x7f; + DMA[d].Repeat = !(byte & 0x80); + break; + + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + Address &= ~4; // Convert 43xF to 43xB + /* fall through */ + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + + // Unknown, but they seem to be RAM-ish +#if 0 + fprintf(stderr, "Write %02x to %04x!\n", byte, Address); +#endif + break; + + //These registers are used by both the S-DD1 and the SPC7110 + case 0x4800: + case 0x4801: + case 0x4802: + case 0x4803: + if(Settings.SPC7110) + S9xSetSPC7110(byte, Address); + //printf ("%02x->%04x\n", byte, Address); + break; + + case 0x4804: + case 0x4805: + case 0x4806: + case 0x4807: + //printf ("%02x->%04x\n", byte, Address); + if(Settings.SPC7110) + S9xSetSPC7110(byte, Address); + else S9xSetSDD1MemoryMap (Address - 0x4804, byte & 7); + break; + + //these are used by the SPC7110 + case 0x4808: + case 0x4809: + case 0x480A: + case 0x480B: + case 0x480C: + case 0x4810: + case 0x4811: + case 0x4812: + case 0x4813: + case 0x4814: + case 0x4815: + case 0x4816: + case 0x4817: + case 0x4818: + case 0x481A: + case 0x4820: + case 0x4821: + case 0x4822: + case 0x4823: + case 0x4824: + case 0x4825: + case 0x4826: + case 0x4827: + case 0x4828: + case 0x4829: + case 0x482A: + case 0x482B: + case 0x482C: + case 0x482D: + case 0x482E: + case 0x482F: + case 0x4830: + case 0x4831: + case 0x4832: + case 0x4833: + case 0x4834: + case 0x4840: + case 0x4841: + case 0x4842: + if(Settings.SPC7110) + { + S9xSetSPC7110(byte, Address); + break; + } + + default: + break; + } + Memory.FillRAM [Address] = byte; +} + +/******************************************************************************/ +/* S9xGetCPU() */ +/* This function retrieves a CPU/DMA Register */ +/******************************************************************************/ +uint8 S9xGetCPU (uint16 Address) +{ + uint8 byte; +// fprintf(stderr, "read from %04x\n", Address); + + if (Address < 0x4200) + { + CPU.Cycles += ONE_CYCLE; + switch (Address) + { + case 0x4016: + { + if (Memory.FillRAM [0x4016] & 1) + { + if ((!Settings.SwapJoypads && + IPPU.Controller == SNES_MOUSE_SWAPPED) || + (Settings.SwapJoypads && + IPPU.Controller == SNES_MOUSE)) + { + if (++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + } + return (0); + } + + int ind = Settings.SwapJoypads ? 1 : 0; + byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15); + PPU.Joypad1ButtonReadPos++; + return (byte & 1); + } + case 0x4017: + { + if (Memory.FillRAM [0x4016] & 1) + { + // MultiPlayer5 adaptor is only allowed to be plugged into port 2 + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5: + return (2); + case SNES_MOUSE_SWAPPED: + if (Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + break; + + case SNES_MOUSE: + if (!Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + break; + } + return (0x00); + } + + int ind = Settings.SwapJoypads ? 0 : 1; + + if (IPPU.Controller == SNES_MULTIPLAYER5) + { + if (Memory.FillRAM [0x4201] & 0x80) + { + byte = ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | + (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); + PPU.Joypad2ButtonReadPos++; + return (byte); + } + else + { + byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | + (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); + PPU.Joypad3ButtonReadPos++; + return (byte); + } + } + else if(IPPU.Controller ==SNES_JUSTIFIER || IPPU.Controller ==SNES_JUSTIFIER_2) + { + uint8 rv; + rv=(1&(justifiers>>in_bit)); + in_bit++; + in_bit%=32; + return rv; + } + return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); + } + 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.PCAtOpcodeStart; +#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. + byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + // Maybe? Register Scan indicated open bus... + byte |= OpenBus&0x3f; + + return (byte); + + case 0x4212: + // V-blank, h-blank and joypads being read flags (read-only) +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#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) + /* fall through */ + case 0x4214: + case 0x4215: + // Quotient of divide result + case 0x4216: + case 0x4217: + // Multiplcation result (for multiply) or remainder of + // divison. + /* fall through */ + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + // Joypads 1-4 button and direction state. + /* fall through */ + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + // DMA direction, address type, fixed flag, + /* fall through */ + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + /* fall through */ + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + /* fall through */ + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + /* fall through */ + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + /* fall through */ + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + /* fall through */ + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + /* fall through */ + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + /* fall through */ + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + return (Memory.FillRAM[Address]); + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + return (DMA[(Address >> 4) & 7].IndirectBank); + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + { + int d = (Address & 0x70) >> 4; + if (IPPU.HDMA & (1 << d)) + { + return (DMA[d].LineCount); + } + return (Memory.FillRAM[Address]); + } + + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + Address &= ~4; // Convert 43xF to 43xB + /* fall through */ + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + + // Unknown, but they seem to be RAM-ish + return (Memory.FillRAM[Address]); + + default: + if(Address>= 0x4800&&Settings.SPC7110) + return S9xGetSPC7110(Address); + + if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) + { + return Memory.FillRAM[Address]; + } + + return OpenBus; + } +// return (Memory.FillRAM[Address]); +} + +static void CommonPPUReset () +{ + PPU.BGMode = 0; + PPU.BG3Priority = 0; + PPU.Brightness = 0; + PPU.VMA.High = 0; + PPU.VMA.Increment = 1; + PPU.VMA.Address = 0; + PPU.VMA.FullGraphicCount = 0; + PPU.VMA.Shift = 0; + + 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.ClipCounts[B] = 0; + PPU.ClipWindowOverlapLogic [B] = CLIP_OR; + PPU.ClipWindow1Enable[B] = FALSE; + PPU.ClipWindow2Enable[B] = FALSE; + PPU.ClipWindow1Inside[B] = TRUE; + PPU.ClipWindow2Inside[B] = TRUE; + } + + PPU.ClipCounts[4] = 0; + PPU.ClipCounts[5] = 0; + PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; + PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; + PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; + PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; + PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; + + PPU.CGFLIP = 0; + int c; + for (c = 0; c < 256; c++) + { + IPPU.Red [c] = (c & 7) << 2; + IPPU.Green [c] = ((c >> 3) & 7) << 2; + IPPU.Blue [c] = ((c >> 6) & 2) << 3; + PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | + (IPPU.Blue [c] << 10); + } + + 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 = 0; + PPU.IRQHBeamPos = 0; + PPU.VBeamPosLatched = 0; + PPU.HBeamPosLatched = 0; + + PPU.HBeamFlip = 0; + PPU.VBeamFlip = 0; + PPU.HVBeamCounterLatched = 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.BG_Forced = 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 = Settings.H_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.Window1Left = 1; + PPU.Window1Right = 0; + PPU.Window2Left = 1; + PPU.Window2Right = 0; + PPU.RecomputeClipWindows = TRUE; + PPU.CGFLIPRead = 0; + PPU.Need16x8Mulitply = FALSE; + PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; + + IPPU.ColorsChanged = TRUE; + IPPU.HDMA = 0; + IPPU.HDMAStarted = FALSE; + IPPU.MaxBrightness = 0; + IPPU.LatchedBlanking = 0; + 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); +#ifdef CORRECT_VRAM_READS + IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? +#else + IPPU.FirstVRAMRead = FALSE; +#endif + IPPU.Interlace = FALSE; + IPPU.InterlaceSprites = FALSE; + IPPU.DoubleWidthPixels = FALSE; + IPPU.HalfWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + 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; + + if (Settings.ControllerOption == 0) + IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; + else + IPPU.Controller = Settings.ControllerOption - 1; + S9xNextController (); + + for (c = 0; c < 2; c++) + memset (&IPPU.Clip [c], 0, sizeof (struct ClipData)); + + if (Settings.MouseMaster) + { + S9xProcessMouse (0); + S9xProcessMouse (1); + } +} + +void S9xResetPPU () +{ + CommonPPUReset (); + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + + IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; + IPPU.Joypads[3] = IPPU.Joypads[4] = 0; + IPPU.SuperScope = 0; + IPPU.Mouse[0] = IPPU.Mouse[1] = 0; + IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; + IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; + + for (int c = 0; c < 0x8000; c += 0x100) + { + if ( !Settings.SuperFX ) + { + memset (&Memory.FillRAM [c], c >> 8, 0x100); + } + else if ( (unsigned)c < 0x3000 || (unsigned)c >= 0x3300 ) + { + /* Don't overwrite SFX pvRegisters at 0x3000-0x32FF, + * they were set in FxReset. + */ + 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); + + Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; +} + +void S9xSoftResetPPU () +{ + CommonPPUReset (); +// PPU.Joypad1ButtonReadPos = 0; +// PPU.Joypad2ButtonReadPos = 0; +// PPU.Joypad3ButtonReadPos = 0; + +// IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; +// IPPU.Joypads[3] = IPPU.Joypads[4] = 0; +// IPPU.SuperScope = 0; +// IPPU.Mouse[0] = IPPU.Mouse[1] = 0; +// IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; +// IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; + + 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); + + Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; +} + +void S9xProcessMouse (int which1) +{ + int x, y; + uint32 buttons; + + if ((IPPU.Controller == SNES_MOUSE || IPPU.Controller == SNES_MOUSE_SWAPPED) && S9xReadMousePosition (which1, x, y, buttons)) + { + int delta_x, delta_y; +#define MOUSE_SIGNATURE 0x1 + IPPU.Mouse [which1] = MOUSE_SIGNATURE | + (PPU.MouseSpeed [which1] << 4) | + ((buttons & 1) << 6) | ((buttons & 2) << 6); + + delta_x = x - IPPU.PrevMouseX[which1]; + delta_y = y - IPPU.PrevMouseY[which1]; + + if (delta_x > 63) + { + delta_x = 63; + IPPU.PrevMouseX[which1] += 63; + } + else + if (delta_x < -63) + { + delta_x = -63; + IPPU.PrevMouseX[which1] -= 63; + } + else + IPPU.PrevMouseX[which1] = x; + + if (delta_y > 63) + { + delta_y = 63; + IPPU.PrevMouseY[which1] += 63; + } + else + if (delta_y < -63) + { + delta_y = -63; + IPPU.PrevMouseY[which1] -= 63; + } + else + IPPU.PrevMouseY[which1] = y; + + if (delta_x < 0) + { + delta_x = -delta_x; + IPPU.Mouse [which1] |= (delta_x | 0x80) << 16; + } + else + IPPU.Mouse [which1] |= delta_x << 16; + + if (delta_y < 0) + { + delta_y = -delta_y; + IPPU.Mouse [which1] |= (delta_y | 0x80) << 24; + } + else + IPPU.Mouse [which1] |= delta_y << 24; + + if (IPPU.Controller == SNES_MOUSE_SWAPPED) + IPPU.Joypads [0] = IPPU.Mouse [which1]; + else + IPPU.Joypads [1] = IPPU.Mouse [which1]; + } +} + +void ProcessSuperScope () +{ + int x, y; + uint32 buttons; + + if (IPPU.Controller == SNES_SUPERSCOPE && + S9xReadSuperScopePosition (x, y, buttons)) + { +#define SUPERSCOPE_SIGNATURE 0x00ff + uint32 scope; + + scope = SUPERSCOPE_SIGNATURE | ((buttons & 1) << (7 + 8)) | + ((buttons & 2) << (5 + 8)) | ((buttons & 4) << (3 + 8)) | + ((buttons & 8) << (1 + 8)); + if(Memory.FillRAM[0x4201]&0x80){ + 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; + + PPU.VBeamPosLatched = (uint16) (y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + IPPU.Joypads [1] = scope; + } +} + +void S9xNextController () +{ + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5: + IPPU.Controller = SNES_JOYPAD; + break; + case SNES_JOYPAD: + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE_SWAPPED; + break; + } + case SNES_MOUSE_SWAPPED: + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE; + break; + } + case SNES_MOUSE: + if (Settings.SuperScopeMaster) + { + IPPU.Controller = SNES_SUPERSCOPE; + break; + } + case SNES_SUPERSCOPE: + if (Settings.JustifierMaster) + { + IPPU.Controller = SNES_JUSTIFIER; + break; + } + case SNES_JUSTIFIER: + if(Settings.JustifierMaster) + { + IPPU.Controller=SNES_JUSTIFIER_2; + break; + } + case SNES_JUSTIFIER_2: + if(Settings.MultiPlayer5Master) + { + IPPU.Controller=SNES_MULTIPLAYER5; + break; + } + default: + IPPU.Controller = SNES_JOYPAD; + break; + } +} + +void S9xUpdateJustifiers() +{ + static bool last_p1; + in_bit=0; +// static int p1count; + justifiers=0xFFFF00AA; + + bool offscreen=JustifierOffscreen(); + + JustifierButtons(justifiers); +// if(p1count==32) +// { + last_p1=!last_p1; +// p1count=0; +// } +// p1count++; + + if(!last_p1) + justifiers|=0x1000; + + int x,y; + uint32 buttons; + + if(Memory.FillRAM[0x4201]&0x80) + { + + S9xReadSuperScopePosition(x,y,buttons); + + x+=40; + if (x > 295) + x = 295; + if (x < 40) + x = 40; + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + if (y < 0) + y = 0; + + if(last_p1) + { + + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + + //process latch as Justifier 2 + if(Settings.SecondJustifier) + { + if(IPPU.Controller==SNES_JUSTIFIER_2) + { + if(!offscreen) + { + + PPU.VBeamPosLatched = (uint16) (y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + } + } + } + else + { + + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + + //emulate player 1. + if(IPPU.Controller==SNES_JUSTIFIER) + { + if(!offscreen) + { + PPU.VBeamPosLatched = (uint16) (y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + } + } + + //needs restructure + if(!offscreen) + { + + if((!last_p1&&IPPU.Controller==SNES_JUSTIFIER)||(last_p1&&IPPU.Controller==SNES_JUSTIFIER_2)) + { + PPU.VBeamPosLatched = (uint16) (y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + else + { + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + + } + } + else + { + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + } + } +} + +void S9xUpdateJoypads () +{ + uint32 i; + + for (i = 0; i < 5; i++) + { + IPPU.Joypads [i] = S9xReadJoypad (i); + } + +// S9xMovieUpdate(); + + for (i = 0; i < 5; i++) + { + if ((IPPU.Joypads [i] & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) == (SNES_LEFT_MASK | SNES_RIGHT_MASK)) + IPPU.Joypads [i] &= ~SNES_RIGHT_MASK; + if ((IPPU.Joypads [i] & (SNES_UP_MASK | SNES_DOWN_MASK)) == (SNES_UP_MASK | SNES_DOWN_MASK)) + IPPU.Joypads [i] &= ~SNES_DOWN_MASK; + } + + // BJ: This is correct behavior AFAICT (used to be Touhaiden hack) + if (IPPU.Controller == SNES_JOYPAD || IPPU.Controller == SNES_MULTIPLAYER5) + { + for (i = 0; i < 5; i++) + { + if (IPPU.Joypads [i]) + IPPU.Joypads [i] |= 0xffff0000; + } + } + + // Read mouse position if enabled + if (Settings.MouseMaster) + { + for (i = 0; i < 2; i++) + S9xProcessMouse (i); + } + + // Read SuperScope if enabled + if (Settings.SuperScopeMaster) + ProcessSuperScope (); + + if (Memory.FillRAM [0x4200] & 1) + { + PPU.Joypad1ButtonReadPos = 16; + if (Memory.FillRAM [0x4201] & 0x80) + { + PPU.Joypad2ButtonReadPos = 16; + PPU.Joypad3ButtonReadPos = 0; + } + else + { + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 16; + } + int ind = Settings.SwapJoypads ? 1 : 0; + + Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads [ind]; + Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads [ind] >> 8); + Memory.FillRAM [0x421a] = (uint8) IPPU.Joypads [ind ^ 1]; + Memory.FillRAM [0x421b] = (uint8) (IPPU.Joypads [ind ^ 1] >> 8); + if (Memory.FillRAM [0x4201] & 0x80) + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [ind]; + Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [ind] >> 8); + Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [2]; + Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [2] >> 8); + } + else + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [3]; + Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [3] >> 8); + Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [4]; + Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [4] >> 8); + } + } + if(Settings.Justifier||Settings.SecondJustifier) + { + Memory.FillRAM [0x421a] = 0x0E; + Memory.FillRAM [0x421b] = 0; + S9xUpdateJustifiers(); + } + +} + +#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) + { + if (!Settings.WinterGold||Settings.StarfoxHack) + FxEmulate (~0); + else + FxEmulate ((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? 700 : 350); + 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 + +// Register reads and writes... + +uint8 REGISTER_4212() +{ + uint8 GetBank = 0; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && + CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) + GetBank = 1; + + GetBank |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) + GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */ + + return (GetBank); +} + +void FLUSH_REDRAW () +{ + if (IPPU.PreviousLine != IPPU.CurrentLine) + S9xUpdateScreen (); +} + +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; + } + 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; + 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; + + 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; + } + } + PPU.OAMFlip &= ~1; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + } + + Memory.FillRAM [0x2104] = byte; +} + +void REGISTER_2118 (uint8 Byte) +{ + 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; + if (!PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + } +// Memory.FillRAM [0x2118] = Byte; +} + +void REGISTER_2118_tile (uint8 Byte) +{ + 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; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2118] = Byte; +} + +void REGISTER_2118_linear (uint8 Byte) +{ + 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; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2118] = Byte; +} + +void REGISTER_2119 (uint8 Byte) +{ + 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; + if (PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + } +// Memory.FillRAM [0x2119] = Byte; +} + +void REGISTER_2119_tile (uint8 Byte) +{ + 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; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2119] = Byte; +} + +void REGISTER_2119_linear (uint8 Byte) +{ + 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; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +// Memory.FillRAM [0x2119] = Byte; +} + +void REGISTER_2122(uint8 Byte) +{ + // CG-RAM (palette) write + + if (PPU.CGFLIP) + { + if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) + { + FLUSH_REDRAW (); + PPU.CGDATA[PPU.CGADD] &= 0x00FF; + PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; + IPPU.ColorsChanged = TRUE; + IPPU.Blue [PPU.CGADD] = IPPU.XB [(Byte >> 2) & 0x1f]; + IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], + IPPU.Green [PPU.CGADD], + IPPU.Blue [PPU.CGADD]); + } + PPU.CGADD++; + } + else + { + if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) + { + FLUSH_REDRAW (); + PPU.CGDATA[PPU.CGADD] &= 0x7F00; + PPU.CGDATA[PPU.CGADD] |= Byte; + IPPU.ColorsChanged = TRUE; + IPPU.Red [PPU.CGADD] = IPPU.XB [Byte & 0x1f]; + IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], + IPPU.Green [PPU.CGADD], + IPPU.Blue [PPU.CGADD]); + } + } + PPU.CGFLIP ^= 1; +// Memory.FillRAM [0x2122] = Byte; +} + +void REGISTER_2180(uint8 Byte) +{ + Memory.RAM[PPU.WRAM++] = Byte; + PPU.WRAM &= 0x1FFFF; + Memory.FillRAM [0x2180] = Byte; +} diff --git a/source/ppu.cpp b/source/ppu.cpp deleted file mode 100644 index 4717f1d..0000000 --- a/source/ppu.cpp +++ /dev/null @@ -1,3132 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#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 "sdd1.h" -#include "srtc.h" -#include "spc7110.h" - -#ifndef ZSNES_FX -#include "fxemu.h" -#include "fxinst.h" -extern struct FxInit_s SuperFX; -#else -EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); -EXTERN_C uint8 S9xSuperFXReadReg (uint32); -#endif - -uint32 justifiers=0xFFFF00AA; -uint8 in_bit=0; - -extern uint8 *HDMAMemPointers [8]; - -void S9xLatchCounters (bool force) -{ - if(!force && !(Memory.FillRAM[0x4213] & 0x80)) return; - -#if 0 -# ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -# endif -#endif - PPU.HVBeamCounterLatched = 1; - PPU.VBeamPosLatched = (uint16) CPU.V_Counter; - PPU.HBeamPosLatched = (uint16) ((CPU.Cycles * SNES_HCOUNTER_MAX) / Settings.H_Max); - - // 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; -} - -void S9xUpdateJustifiers(); - -void S9xUpdateHTimer () -{ - if (PPU.HTimerEnabled) - { - PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; - if (PPU.HTimerPosition == Settings.H_Max || - PPU.HTimerPosition == Settings.HBlankStart) - { - PPU.HTimerPosition--; - } - - if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) - { - if (PPU.HTimerPosition < CPU.Cycles) - { - // Missed the IRQ on this line already - if (CPU.WhichEvent == HBLANK_END_EVENT || - CPU.WhichEvent == HTIMER_AFTER_EVENT) - { - CPU.WhichEvent = HBLANK_END_EVENT; - CPU.NextEvent = Settings.H_Max; - } - else - { - CPU.WhichEvent = HBLANK_START_EVENT; - CPU.NextEvent = Settings.HBlankStart; - } - } - else - { - if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || - CPU.WhichEvent == HBLANK_START_EVENT) - { - if (PPU.HTimerPosition > Settings.HBlankStart) - { - // HTimer was to trigger before h-blank start, - // now triggers after start of h-blank - CPU.NextEvent = Settings.HBlankStart; - CPU.WhichEvent = HBLANK_START_EVENT; - } - else - { - CPU.NextEvent = PPU.HTimerPosition; - CPU.WhichEvent = HTIMER_BEFORE_EVENT; - } - } - else - { - CPU.WhichEvent = HTIMER_AFTER_EVENT; - CPU.NextEvent = PPU.HTimerPosition; - } - } - } - } -} - -void S9xFixColourBrightness () -{ - IPPU.XB = mul_brightness [PPU.Brightness]; - for (int i = 0; i < 256; i++) - { - IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; - IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; - IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; - IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i], - IPPU.Blue [i]); - } -} - -/******************************************************************************/ -/* 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); - if (Address <= 0x2183) - { - switch (Address) - { - case 0x2100: - // Brightness and screen blank bit - if (Byte != Memory.FillRAM [0x2100]) - { - 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; - } - } - break; - - case 0x2101: - // Sprite (OBJ) tile address - if (Byte != Memory.FillRAM [0x2101]) - { - FLUSH_REDRAW (); - PPU.OBJNameBase = (Byte & 3) << 14; - PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; - PPU.OBJSizeSelect = (Byte >> 5) & 7; - IPPU.OBJChanged = TRUE; - } - break; - - case 0x2102: - // Sprite write address (low) - PPU.OAMAddr = ((Memory.FillRAM[0x2103]&1)<<8) | Byte; - PPU.OAMFlip = 2; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - 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; - } - } else { - if (PPU.FirstSprite != 0) - { - PPU.FirstSprite = 0; - IPPU.OBJChanged = TRUE; - } - } - 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); - if(PPU.BGMode==5||PPU.BGMode==6) - IPPU.Interlace = Memory.FillRAM[0x2133]&1; - } - break; - - case 0x2106: - // Mosaic pixel size and enable - if (Byte != Memory.FillRAM [0x2106]) - { - FLUSH_REDRAW (); - PPU.Mosaic = (Byte >> 4) + 1; - PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1; - PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1; - PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1; - PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; - } - break; - case 0x2107: // [BG0SC] - case 0x2108: // [BG1SC] - case 0x2109: // [BG2SC] - case 0x210A: // [BG3SC] - if (Byte != Memory.FillRAM [Address]) - { - FLUSH_REDRAW (); - PPU.BG[Address - 0x2107].SCSize = Byte & 3; - PPU.BG[Address - 0x2107].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; - - - //This is the Theme Park fix - it appears all these registers - //share a previous byte value for setting them. - - case 0x210D: - //TEST9 if(last_written != 0x210d) PPU.BGnxOFSbyte = 0; - PPU.BG[0].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[0].HOffset = %04x %d)\n", Byte, Address, PPU.BG[0].HOffset, CPU.V_Counter); - break; - - case 0x210E: - PPU.BG[0].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[0].VOffset = %04x %d)\n", Byte, Address, PPU.BG[0].VOffset, CPU.V_Counter); - break; - - case 0x210F: - PPU.BG[1].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[1].HOffset = %04x %d)\n", Byte, Address, PPU.BG[1].HOffset, CPU.V_Counter); - break; - - case 0x2110: - PPU.BG[1].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[1].VOffset = %04x %d)\n", Byte, Address, PPU.BG[1].VOffset, CPU.V_Counter); - break; - - case 0x2111: - PPU.BG[2].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[2].HOffset = %04x %d)\n", Byte, Address, PPU.BG[2].HOffset, CPU.V_Counter); - break; - - case 0x2112: - PPU.BG[2].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[2].VOffset = %04x %d)\n", Byte, Address, PPU.BG[2].VOffset, CPU.V_Counter); - break; - - case 0x2113: - PPU.BG[3].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[3].HOffset = %04x %d)\n", Byte, Address, PPU.BG[3].HOffset, CPU.V_Counter); - break; - - case 0x2114: - PPU.BG[3].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[3].VOffset = %04x %d)\n", Byte, Address, PPU.BG[3].VOffset, CPU.V_Counter); - break; - - //end Theme Park - - 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: - case 3: - PPU.VMA.Increment = 128; - break; - } - if (Byte & 0x0c) - { - static uint16 IncCount [4] = { 0, 32, 64, 128 }; - static uint16 Shift [4] = { 0, 5, 6, 7 }; -// 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.MatrixA >> 8) & 0xff) | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - break; - case 0x211c: - // Mode 7 matrix B (low & high) - PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - break; - case 0x211d: - // Mode 7 matrix C (low & high) - PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8); - break; - case 0x211e: - // Mode 7 matrix D (low & high) - PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); - break; - case 0x211f: - // Mode 7 centre of rotation X (low & high) - PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8); - break; - case 0x2120: - // Mode 7 centre of rotation Y (low & high) - PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); - 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; - } - 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; - } - 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; - } - 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 (); - PPU.RecomputeClipWindows = TRUE; - Memory.FillRAM [Address] = Byte; - return; - } - break; - case 0x212e: - // Window mask designation for main screen ? - case 0x212f: - // Window mask designation for sub-screen ? - if (Byte != Memory.FillRAM [Address]) - { - FLUSH_REDRAW (); - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2130: - // Fixed colour addition or screen addition - if (Byte != Memory.FillRAM [0x2130]) - { - FLUSH_REDRAW (); - PPU.RecomputeClipWindows = TRUE; - } - 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 - 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]) - { - if (Byte & 0x04) - { - PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; - if(IPPU.DoubleHeightPixels) - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - else - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - } - else PPU.ScreenHeight = SNES_HEIGHT; - - //if((Byte & 1)&&(PPU.BGMode==5||PPU.BGMode==6)) - //IPPU.Interlace=1; - 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.InterlaceSprites=0; - // IPPU.InterlaceSprites = (Byte&2)>>1; - } - - } - break; - case 0x2134: - case 0x2135: - case 0x2136: - // Matrix 16bit x 8bit multiply result (read-only) - /* fall through */ - case 0x2137: - // Software latch for horizontal and vertical timers (read-only) - /* fall through */ - case 0x2138: - // OAM read data (read-only) - /* fall through */ - case 0x2139: - case 0x213a: - // VRAM read data (read-only) - /* fall through */ - case 0x213b: - // CG-RAM read data (read-only) - /* fall through */ - case 0x213c: - case 0x213d: - // Horizontal and vertical (low/high) read counter (read-only) - /* fall through */ - case 0x213e: - // PPU status (time over and range over) - /* fall through */ - 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 SPCTOOL - _SPCInPB (Address & 3, Byte); -#else - // CPU.Flags |= DEBUG_MODE_FLAG; - Memory.FillRAM [Address] = Byte; - IAPU.RAM [(Address & 3) + 0xf4] = Byte; -#ifdef SPC700_SHUTDOWN - IAPU.APUExecuting = Settings.APUEnabled; - IAPU.WaitCounter++; -#endif -#endif // SPCTOOL - break; - case 0x2180: - REGISTER_2180(Byte); - break; - case 0x2181: - PPU.WRAM &= 0x1FF00; - PPU.WRAM |= Byte; - break; - case 0x2182: - PPU.WRAM &= 0x100FF; - PPU.WRAM |= Byte << 8; - break; - case 0x2183: - PPU.WRAM &= 0x0FFFF; - PPU.WRAM |= Byte << 16; - PPU.WRAM &= 0x1FFFF; - 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 < 0x3300) - { - if (!Settings.SuperFX) - { - return; - } - -#ifdef ZSNES_FX - Memory.FillRAM [Address] = Byte; - if (Address < 0x3040) - S9xSuperFXWriteReg (Byte, Address); -#else - switch (Address) - { - case 0x3030: - if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) - { - Memory.FillRAM [Address] = Byte; - // Go flag has been changed - if (Byte & FLG_G) - S9xSuperFXExec (); - else - FxFlushCache (); - } - else - Memory.FillRAM [Address] = Byte; - break; - - case 0x3031: - case 0x3033: - case 0x3037: - case 0x3039: - case 0x303a: - case 0x303f: - Memory.FillRAM [Address] = Byte; - break; - case 0x3034: - case 0x3036: - Memory.FillRAM [Address] = Byte & 0x7f; - break; - case 0x3038: - Memory.FillRAM [Address] = Byte; - fx_dirtySCBR(); - break; - case 0x303b: - break; - case 0x303c: - Memory.FillRAM [Address] = Byte; - fx_updateRamBank(Byte); - break; - case 0x301f: - Memory.FillRAM [Address] = Byte; - Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; - S9xSuperFXExec (); - return; - - default: - Memory.FillRAM[Address] = Byte; - if (Address >= 0x3100) - { - FxCacheWriteAccess (Address); - } - break; - } -#endif - return; - } - } - Memory.FillRAM[Address] = Byte; - -} - -/******************************************************************************/ -/* S9xGetPPU() */ -/* This function retrieves a PPU Register */ -/******************************************************************************/ -uint8 S9xGetPPU (uint16 Address) -{ - uint8 byte = OpenBus; - if(Address<0x2100)//not a real PPU reg - return OpenBus; //treat as unmapped memory returning last byte on the bus - if (Address <= 0x2190) - { - switch (Address) - { - case 0x2100: - case 0x2101: - case 0x2102: - case 0x2103: - return OpenBus; - - case 0x2104: - case 0x2105: - case 0x2106: - case 0x2108: - case 0x2109: - case 0x210a: - case 0x2115: - case 0x2116: - case 0x2118: - case 0x2119: - case 0x211a: - case 0x2124: - case 0x2125: - case 0x2126: - case 0x2128: - case 0x2129: - case 0x212a: - return PPU.OpenBus1; - - case 0x2107: - case 0x2117: - case 0x2121: - case 0x2122: - case 0x2123: - case 0x2127: - case 0x212b: - case 0x212c: - case 0x212d: - case 0x212e: - case 0x212f: - case 0x2130: - case 0x2131: - case 0x2132: - case 0x2133: - return OpenBus; - - case 0x210b: - case 0x210c: - case 0x210d: - case 0x210e: - case 0x210f: - case 0x2110: - case 0x2111: - case 0x2112: - case 0x2113: - return OpenBus; - - case 0x2114: - case 0x211b: - case 0x211c: - case 0x211d: - case 0x211e: - case 0x211f: - case 0x2120: - 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; - } - 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)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - } - } 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; - } - } - } - PPU.OAMFlip ^= 1; - return (PPU.OpenBus1 = byte); - - case 0x2139: - // Read vram low byte -#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 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 - 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 - 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 - 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 - PPU.VBeamFlip = PPU.HBeamFlip = 0; - //neviksti found a 2 and a 3 here. SNEeSe uses a 3. - //XXX: field flags not emulated - return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0)| Model->_5C78) | (~PPU.OpenBus2 & 0x20); - - 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 SPCTOOL - return ((uint8) _SPCOutP [Address & 3]); -#else - // CPU.Flags |= DEBUG_MODE_FLAG; -#ifdef SPC700_SHUTDOWN - IAPU.APUExecuting = Settings.APUEnabled; - IAPU.WaitCounter++; -#endif - if (Settings.APUEnabled) - { -#ifdef CPU_SHUTDOWN -// CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - if (SNESGameFixes.APU_OutPorts_ReturnValueFix && - Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) - { - return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : - (rand() & 0xff)); - } - - return (APU.OutPorts [Address & 3]); - } - - switch (Settings.SoundSkipMethod) - { - case 0: - case 1: - case 3: - CPU.BranchSkip = TRUE; - break; - case 2: - 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]); -#endif // SPCTOOL - - case 0x2180: - // Read WRAM - byte = Memory.RAM [PPU.WRAM++]; - PPU.WRAM &= 0x1FFFF; - break; - case 0x2181: - case 0x2182: - case 0x2183: - default: - return OpenBus; - } - } - else - { - if (Settings.SA1) - return (S9xGetSA1 (Address)); - - if (Address <= 0x2fff || Address >= 0x3300) - { - 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: - 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.PCAtOpcodeStart; -#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.PCAtOpcodeStart; - } - 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; -// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, byte, Address); - - if (Address < 0x4200) - { - CPU.Cycles += ONE_CYCLE; - switch (Address) - { - case 0x4016: - // S9xReset reading of old-style joypads - if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) - { - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - } - break; - case 0x4017: - break; - default: - break; - } - } - else - switch (Address) - { - case 0x4200: - // NMI, V & H IRQ and joypad reading enable flags - if (byte & 0x20) - { - //if(!SNESGameFixes.umiharakawaseFix && PPU.IRQVBeamPos==262) fprintf(stderr, "PPU.IRQVBeamPos = %d, CPU.V_Counter = %d\n", PPU.IRQVBeamPos, CPU.V_Counter); - if (!PPU.VTimerEnabled) - { - PPU.VTimerEnabled = TRUE; - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - else - { - PPU.VTimerEnabled = FALSE; -// if (SNESGameFixes.umiharakawaseFix) -// byte &= ~0x20; - } - - if (byte & 0x10) - { - if (!PPU.HTimerEnabled) - { - PPU.HTimerEnabled = TRUE; - S9xUpdateHTimer (); - } - } - else - { - // No need to check for HTimer being disabled as the scanline - // event trigger code won't trigger an H-IRQ unless its enabled. - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - } - if (!Settings.DaffyDuck) - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - if ((byte & 0x80) && - !(Memory.FillRAM [0x4200] & 0x80) && - CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter <= PPU.ScreenHeight + - (SNESGameFixes.alienVSpredetorFix ? 25 : 15) && //jyam 15->25 alien vs predetor -// 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... - (Memory.FillRAM [0x4210] & 0x80) && - !CPU.NMIActive) - { - CPU.Flags |= NMI_FLAG; - CPU.NMIActive = TRUE; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } - break; - case 0x4201: - if((byte&0x80)==0 && (Memory.FillRAM[0x4213]&0x80)==0x80) - S9xLatchCounters(1); - Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = byte; - break; - case 0x4202: - // Multiplier (for multply) - break; - case 0x4203: - { - // Multiplicand - uint32 res = Memory.FillRAM[0x4202] * byte; - -#if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS - // assume malloc'd memory is 2-byte aligned - * ((uint16 *) &Memory.FillRAM[0x4216]) = res; -#else - Memory.FillRAM[0x4216] = (uint8) res; - Memory.FillRAM[0x4217] = (uint8) (res >> 8); -#endif - break; - } - case 0x4204: - case 0x4205: - // Low and high muliplier (for divide) - break; - case 0x4206: - { -#if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS - // assume malloc'd memory is 2-byte aligned - uint16 a = *((uint16 *) &Memory.FillRAM[0x4204]); -#else - uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); -#endif - uint16 div = byte ? a / byte : 0xffff; - uint16 rem = byte ? a % byte : a; - -#if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS - // assume malloc'd memory is 2-byte aligned - * ((uint16 *) &Memory.FillRAM[0x4214]) = div; - * ((uint16 *) &Memory.FillRAM[0x4216]) = rem; -#else - Memory.FillRAM[0x4214] = (uint8)div; - Memory.FillRAM[0x4215] = div >> 8; - Memory.FillRAM[0x4216] = (uint8)rem; - Memory.FillRAM[0x4217] = rem >> 8; -#endif - break; - } - case 0x4207: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer (); - break; - - case 0x4208: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer (); - - break; - - case 0x4209: - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420A: - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420B: - 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 (Settings.DisableHDMA) - byte = 0; - Memory.FillRAM[0x420c] = byte; - IPPU.HDMA = byte; - 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; - } - 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) - /* fall through */ - case 0x4213: - // I/O Port (read-only) - /* fall through */ - case 0x4214: - case 0x4215: - // Quotent of divide (read-only) - /* fall through */ - case 0x4216: - case 0x4217: - // Multiply product (read-only) - /* fall through */ - 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: - d = (Address >> 4) & 0x7; - DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; - DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; - DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; - DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; - DMA[d].TransferMode = (byte & 7); - break; - - case 0x4301: - case 0x4311: - case 0x4321: - case 0x4331: - case 0x4341: - case 0x4351: - case 0x4361: - case 0x4371: - DMA[((Address >> 4) & 0x7)].BAddress = byte; - break; - - case 0x4302: - case 0x4312: - case 0x4322: - case 0x4332: - case 0x4342: - case 0x4352: - case 0x4362: - case 0x4372: - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF00; - DMA[d].AAddress |= byte; - break; - - case 0x4303: - case 0x4313: - case 0x4323: - case 0x4333: - case 0x4343: - case 0x4353: - case 0x4363: - case 0x4373: - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF; - DMA[d].AAddress |= byte << 8; - break; - - case 0x4304: - case 0x4314: - case 0x4324: - case 0x4334: - case 0x4344: - case 0x4354: - case 0x4364: - case 0x4374: - DMA[((Address >> 4) & 0x7)].ABank = byte; - HDMAMemPointers[((Address >> 4) & 0x7)]=NULL; - - break; - - case 0x4305: - case 0x4315: - case 0x4325: - case 0x4335: - case 0x4345: - case 0x4355: - case 0x4365: - case 0x4375: - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF00; - DMA[d].TransferBytes |= byte; - DMA[d].IndirectAddress &= 0xff00; - DMA[d].IndirectAddress |= byte; - HDMAMemPointers[d]=NULL; - break; - - case 0x4306: - case 0x4316: - case 0x4326: - case 0x4336: - case 0x4346: - case 0x4356: - case 0x4366: - case 0x4376: - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF; - DMA[d].TransferBytes |= byte << 8; - DMA[d].IndirectAddress &= 0xff; - DMA[d].IndirectAddress |= byte << 8; - HDMAMemPointers[d]=NULL; - break; - - case 0x4307: - case 0x4317: - case 0x4327: - case 0x4337: - case 0x4347: - case 0x4357: - case 0x4367: - case 0x4377: - DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; - HDMAMemPointers[d]=NULL; - break; - - case 0x4308: - case 0x4318: - case 0x4328: - case 0x4338: - case 0x4348: - case 0x4358: - case 0x4368: - case 0x4378: - d = (Address >> 4) & 7; - DMA[d].Address &= 0xff00; - DMA[d].Address |= byte; - HDMAMemPointers[d] = NULL; - break; - - case 0x4309: - case 0x4319: - case 0x4329: - case 0x4339: - case 0x4349: - case 0x4359: - case 0x4369: - case 0x4379: - d = (Address >> 4) & 0x7; - DMA[d].Address &= 0xff; - DMA[d].Address |= byte << 8; - HDMAMemPointers[d] = NULL; - break; - - case 0x430A: - case 0x431A: - case 0x432A: - case 0x433A: - case 0x434A: - case 0x435A: - case 0x436A: - case 0x437A: - d = (Address >> 4) & 0x7; - DMA[d].LineCount = byte & 0x7f; - DMA[d].Repeat = !(byte & 0x80); - break; - - case 0x430F: - case 0x431F: - case 0x432F: - case 0x433F: - case 0x434F: - case 0x435F: - case 0x436F: - case 0x437F: - Address &= ~4; // Convert 43xF to 43xB - /* fall through */ - case 0x430B: - case 0x431B: - case 0x432B: - case 0x433B: - case 0x434B: - case 0x435B: - case 0x436B: - case 0x437B: - - // Unknown, but they seem to be RAM-ish -#if 0 - fprintf(stderr, "Write %02x to %04x!\n", byte, Address); -#endif - break; - - //These registers are used by both the S-DD1 and the SPC7110 - case 0x4800: - case 0x4801: - case 0x4802: - case 0x4803: - if(Settings.SPC7110) - S9xSetSPC7110(byte, Address); - //printf ("%02x->%04x\n", byte, Address); - break; - - case 0x4804: - case 0x4805: - case 0x4806: - case 0x4807: - //printf ("%02x->%04x\n", byte, Address); - if(Settings.SPC7110) - S9xSetSPC7110(byte, Address); - else S9xSetSDD1MemoryMap (Address - 0x4804, byte & 7); - break; - - //these are used by the SPC7110 - case 0x4808: - case 0x4809: - case 0x480A: - case 0x480B: - case 0x480C: - case 0x4810: - case 0x4811: - case 0x4812: - case 0x4813: - case 0x4814: - case 0x4815: - case 0x4816: - case 0x4817: - case 0x4818: - case 0x481A: - case 0x4820: - case 0x4821: - case 0x4822: - case 0x4823: - case 0x4824: - case 0x4825: - case 0x4826: - case 0x4827: - case 0x4828: - case 0x4829: - case 0x482A: - case 0x482B: - case 0x482C: - case 0x482D: - case 0x482E: - case 0x482F: - case 0x4830: - case 0x4831: - case 0x4832: - case 0x4833: - case 0x4834: - case 0x4840: - case 0x4841: - case 0x4842: - if(Settings.SPC7110) - { - S9xSetSPC7110(byte, Address); - break; - } - - default: - break; - } - Memory.FillRAM [Address] = byte; -} - -/******************************************************************************/ -/* S9xGetCPU() */ -/* This function retrieves a CPU/DMA Register */ -/******************************************************************************/ -uint8 S9xGetCPU (uint16 Address) -{ - uint8 byte; -// fprintf(stderr, "read from %04x\n", Address); - - if (Address < 0x4200) - { - CPU.Cycles += ONE_CYCLE; - switch (Address) - { - case 0x4016: - { - if (Memory.FillRAM [0x4016] & 1) - { - if ((!Settings.SwapJoypads && - IPPU.Controller == SNES_MOUSE_SWAPPED) || - (Settings.SwapJoypads && - IPPU.Controller == SNES_MOUSE)) - { - if (++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - } - return (0); - } - - int ind = Settings.SwapJoypads ? 1 : 0; - byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15); - PPU.Joypad1ButtonReadPos++; - return (byte & 1); - } - case 0x4017: - { - if (Memory.FillRAM [0x4016] & 1) - { - // MultiPlayer5 adaptor is only allowed to be plugged into port 2 - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5: - return (2); - case SNES_MOUSE_SWAPPED: - if (Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - break; - - case SNES_MOUSE: - if (!Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - break; - } - return (0x00); - } - - int ind = Settings.SwapJoypads ? 0 : 1; - - if (IPPU.Controller == SNES_MULTIPLAYER5) - { - if (Memory.FillRAM [0x4201] & 0x80) - { - byte = ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); - PPU.Joypad2ButtonReadPos++; - return (byte); - } - else - { - byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); - PPU.Joypad3ButtonReadPos++; - return (byte); - } - } - else if(IPPU.Controller ==SNES_JUSTIFIER || IPPU.Controller ==SNES_JUSTIFIER_2) - { - uint8 rv; - rv=(1&(justifiers>>in_bit)); - in_bit++; - in_bit%=32; - return rv; - } - return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); - } - 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.PCAtOpcodeStart; -#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. - byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - // Maybe? Register Scan indicated open bus... - byte |= OpenBus&0x3f; - - return (byte); - - case 0x4212: - // V-blank, h-blank and joypads being read flags (read-only) -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#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) - /* fall through */ - case 0x4214: - case 0x4215: - // Quotient of divide result - case 0x4216: - case 0x4217: - // Multiplcation result (for multiply) or remainder of - // divison. - /* fall through */ - case 0x4218: - case 0x4219: - case 0x421a: - case 0x421b: - case 0x421c: - case 0x421d: - case 0x421e: - case 0x421f: - // Joypads 1-4 button and direction state. - /* fall through */ - case 0x4300: - case 0x4310: - case 0x4320: - case 0x4330: - case 0x4340: - case 0x4350: - case 0x4360: - case 0x4370: - // DMA direction, address type, fixed flag, - /* fall through */ - case 0x4301: - case 0x4311: - case 0x4321: - case 0x4331: - case 0x4341: - case 0x4351: - case 0x4361: - case 0x4371: - /* fall through */ - case 0x4302: - case 0x4312: - case 0x4322: - case 0x4332: - case 0x4342: - case 0x4352: - case 0x4362: - case 0x4372: - /* fall through */ - case 0x4303: - case 0x4313: - case 0x4323: - case 0x4333: - case 0x4343: - case 0x4353: - case 0x4363: - case 0x4373: - /* fall through */ - case 0x4304: - case 0x4314: - case 0x4324: - case 0x4334: - case 0x4344: - case 0x4354: - case 0x4364: - case 0x4374: - /* fall through */ - case 0x4305: - case 0x4315: - case 0x4325: - case 0x4335: - case 0x4345: - case 0x4355: - case 0x4365: - case 0x4375: - /* fall through */ - case 0x4306: - case 0x4316: - case 0x4326: - case 0x4336: - case 0x4346: - case 0x4356: - case 0x4366: - case 0x4376: - /* fall through */ - case 0x4308: - case 0x4318: - case 0x4328: - case 0x4338: - case 0x4348: - case 0x4358: - case 0x4368: - case 0x4378: - /* fall through */ - case 0x4309: - case 0x4319: - case 0x4329: - case 0x4339: - case 0x4349: - case 0x4359: - case 0x4369: - case 0x4379: - return (Memory.FillRAM[Address]); - - case 0x4307: - case 0x4317: - case 0x4327: - case 0x4337: - case 0x4347: - case 0x4357: - case 0x4367: - case 0x4377: - return (DMA[(Address >> 4) & 7].IndirectBank); - - case 0x430A: - case 0x431A: - case 0x432A: - case 0x433A: - case 0x434A: - case 0x435A: - case 0x436A: - case 0x437A: - { - int d = (Address & 0x70) >> 4; - if (IPPU.HDMA & (1 << d)) - { - return (DMA[d].LineCount); - } - return (Memory.FillRAM[Address]); - } - - case 0x430F: - case 0x431F: - case 0x432F: - case 0x433F: - case 0x434F: - case 0x435F: - case 0x436F: - case 0x437F: - Address &= ~4; // Convert 43xF to 43xB - /* fall through */ - case 0x430B: - case 0x431B: - case 0x432B: - case 0x433B: - case 0x434B: - case 0x435B: - case 0x436B: - case 0x437B: - - // Unknown, but they seem to be RAM-ish - return (Memory.FillRAM[Address]); - - default: - if(Address>= 0x4800&&Settings.SPC7110) - return S9xGetSPC7110(Address); - - if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) - { - return Memory.FillRAM[Address]; - } - - return OpenBus; - } -// return (Memory.FillRAM[Address]); -} - -static void CommonPPUReset () -{ - PPU.BGMode = 0; - PPU.BG3Priority = 0; - PPU.Brightness = 0; - PPU.VMA.High = 0; - PPU.VMA.Increment = 1; - PPU.VMA.Address = 0; - PPU.VMA.FullGraphicCount = 0; - PPU.VMA.Shift = 0; - - 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.ClipCounts[B] = 0; - PPU.ClipWindowOverlapLogic [B] = CLIP_OR; - PPU.ClipWindow1Enable[B] = FALSE; - PPU.ClipWindow2Enable[B] = FALSE; - PPU.ClipWindow1Inside[B] = TRUE; - PPU.ClipWindow2Inside[B] = TRUE; - } - - PPU.ClipCounts[4] = 0; - PPU.ClipCounts[5] = 0; - PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; - PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; - PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; - PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; - PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; - - PPU.CGFLIP = 0; - int c; - for (c = 0; c < 256; c++) - { - IPPU.Red [c] = (c & 7) << 2; - IPPU.Green [c] = ((c >> 3) & 7) << 2; - IPPU.Blue [c] = ((c >> 6) & 2) << 3; - PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | - (IPPU.Blue [c] << 10); - } - - 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 = 0; - PPU.IRQHBeamPos = 0; - PPU.VBeamPosLatched = 0; - PPU.HBeamPosLatched = 0; - - PPU.HBeamFlip = 0; - PPU.VBeamFlip = 0; - PPU.HVBeamCounterLatched = 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.BG_Forced = 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 = Settings.H_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.Window1Left = 1; - PPU.Window1Right = 0; - PPU.Window2Left = 1; - PPU.Window2Right = 0; - PPU.RecomputeClipWindows = TRUE; - PPU.CGFLIPRead = 0; - PPU.Need16x8Mulitply = FALSE; - PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; - - IPPU.ColorsChanged = TRUE; - IPPU.HDMA = 0; - IPPU.HDMAStarted = FALSE; - IPPU.MaxBrightness = 0; - IPPU.LatchedBlanking = 0; - 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); -#ifdef CORRECT_VRAM_READS - IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? -#else - IPPU.FirstVRAMRead = FALSE; -#endif - IPPU.Interlace = FALSE; - IPPU.InterlaceSprites = FALSE; - IPPU.DoubleWidthPixels = FALSE; - IPPU.HalfWidthPixels = FALSE; - IPPU.DoubleHeightPixels = FALSE; - 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; - - if (Settings.ControllerOption == 0) - IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; - else - IPPU.Controller = Settings.ControllerOption - 1; - S9xNextController (); - - for (c = 0; c < 2; c++) - memset (&IPPU.Clip [c], 0, sizeof (struct ClipData)); - - if (Settings.MouseMaster) - { - S9xProcessMouse (0); - S9xProcessMouse (1); - } -} - -void S9xResetPPU () -{ - CommonPPUReset (); - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - - IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; - IPPU.Joypads[3] = IPPU.Joypads[4] = 0; - IPPU.SuperScope = 0; - IPPU.Mouse[0] = IPPU.Mouse[1] = 0; - IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; - IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; - - for (int c = 0; c < 0x8000; c += 0x100) - { - if ( !Settings.SuperFX ) - { - memset (&Memory.FillRAM [c], c >> 8, 0x100); - } - else if ( (unsigned)c < 0x3000 || (unsigned)c >= 0x3300 ) - { - /* Don't overwrite SFX pvRegisters at 0x3000-0x32FF, - * they were set in FxReset. - */ - 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); - - Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; -} - -void S9xSoftResetPPU () -{ - CommonPPUReset (); -// PPU.Joypad1ButtonReadPos = 0; -// PPU.Joypad2ButtonReadPos = 0; -// PPU.Joypad3ButtonReadPos = 0; - -// IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; -// IPPU.Joypads[3] = IPPU.Joypads[4] = 0; -// IPPU.SuperScope = 0; -// IPPU.Mouse[0] = IPPU.Mouse[1] = 0; -// IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; -// IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; - - 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); - - Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; -} - -void S9xProcessMouse (int which1) -{ - int x, y; - uint32 buttons; - - if ((IPPU.Controller == SNES_MOUSE || IPPU.Controller == SNES_MOUSE_SWAPPED) && S9xReadMousePosition (which1, x, y, buttons)) - { - int delta_x, delta_y; -#define MOUSE_SIGNATURE 0x1 - IPPU.Mouse [which1] = MOUSE_SIGNATURE | - (PPU.MouseSpeed [which1] << 4) | - ((buttons & 1) << 6) | ((buttons & 2) << 6); - - delta_x = x - IPPU.PrevMouseX[which1]; - delta_y = y - IPPU.PrevMouseY[which1]; - - if (delta_x > 63) - { - delta_x = 63; - IPPU.PrevMouseX[which1] += 63; - } - else - if (delta_x < -63) - { - delta_x = -63; - IPPU.PrevMouseX[which1] -= 63; - } - else - IPPU.PrevMouseX[which1] = x; - - if (delta_y > 63) - { - delta_y = 63; - IPPU.PrevMouseY[which1] += 63; - } - else - if (delta_y < -63) - { - delta_y = -63; - IPPU.PrevMouseY[which1] -= 63; - } - else - IPPU.PrevMouseY[which1] = y; - - if (delta_x < 0) - { - delta_x = -delta_x; - IPPU.Mouse [which1] |= (delta_x | 0x80) << 16; - } - else - IPPU.Mouse [which1] |= delta_x << 16; - - if (delta_y < 0) - { - delta_y = -delta_y; - IPPU.Mouse [which1] |= (delta_y | 0x80) << 24; - } - else - IPPU.Mouse [which1] |= delta_y << 24; - - if (IPPU.Controller == SNES_MOUSE_SWAPPED) - IPPU.Joypads [0] = IPPU.Mouse [which1]; - else - IPPU.Joypads [1] = IPPU.Mouse [which1]; - } -} - -void ProcessSuperScope () -{ - int x, y; - uint32 buttons; - - if (IPPU.Controller == SNES_SUPERSCOPE && - S9xReadSuperScopePosition (x, y, buttons)) - { -#define SUPERSCOPE_SIGNATURE 0x00ff - uint32 scope; - - scope = SUPERSCOPE_SIGNATURE | ((buttons & 1) << (7 + 8)) | - ((buttons & 2) << (5 + 8)) | ((buttons & 4) << (3 + 8)) | - ((buttons & 8) << (1 + 8)); - if(Memory.FillRAM[0x4201]&0x80){ - 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; - - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - IPPU.Joypads [1] = scope; - } -} - -void S9xNextController () -{ - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5: - IPPU.Controller = SNES_JOYPAD; - break; - case SNES_JOYPAD: - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE_SWAPPED; - break; - } - case SNES_MOUSE_SWAPPED: - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE; - break; - } - case SNES_MOUSE: - if (Settings.SuperScopeMaster) - { - IPPU.Controller = SNES_SUPERSCOPE; - break; - } - case SNES_SUPERSCOPE: - if (Settings.JustifierMaster) - { - IPPU.Controller = SNES_JUSTIFIER; - break; - } - case SNES_JUSTIFIER: - if(Settings.JustifierMaster) - { - IPPU.Controller=SNES_JUSTIFIER_2; - break; - } - case SNES_JUSTIFIER_2: - if(Settings.MultiPlayer5Master) - { - IPPU.Controller=SNES_MULTIPLAYER5; - break; - } - default: - IPPU.Controller = SNES_JOYPAD; - break; - } -} - -void S9xUpdateJustifiers() -{ - static bool last_p1; - in_bit=0; -// static int p1count; - justifiers=0xFFFF00AA; - - bool offscreen=JustifierOffscreen(); - - JustifierButtons(justifiers); -// if(p1count==32) -// { - last_p1=!last_p1; -// p1count=0; -// } -// p1count++; - - if(!last_p1) - justifiers|=0x1000; - - int x,y; - uint32 buttons; - - if(Memory.FillRAM[0x4201]&0x80) - { - - S9xReadSuperScopePosition(x,y,buttons); - - x+=40; - if (x > 295) - x = 295; - if (x < 40) - x = 40; - if (y > PPU.ScreenHeight - 1) - y = PPU.ScreenHeight - 1; - if (y < 0) - y = 0; - - if(last_p1) - { - - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - - //process latch as Justifier 2 - if(Settings.SecondJustifier) - { - if(IPPU.Controller==SNES_JUSTIFIER_2) - { - if(!offscreen) - { - - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - } - } - } - else - { - - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - - //emulate player 1. - if(IPPU.Controller==SNES_JUSTIFIER) - { - if(!offscreen) - { - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - } - } - - //needs restructure - if(!offscreen) - { - - if((!last_p1&&IPPU.Controller==SNES_JUSTIFIER)||(last_p1&&IPPU.Controller==SNES_JUSTIFIER_2)) - { - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - else - { - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - - } - } - else - { - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - } - } -} - -void S9xUpdateJoypads () -{ - uint32 i; - - for (i = 0; i < 5; i++) - { - IPPU.Joypads [i] = S9xReadJoypad (i); - } - -// S9xMovieUpdate(); - - for (i = 0; i < 5; i++) - { - if ((IPPU.Joypads [i] & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) == (SNES_LEFT_MASK | SNES_RIGHT_MASK)) - IPPU.Joypads [i] &= ~SNES_RIGHT_MASK; - if ((IPPU.Joypads [i] & (SNES_UP_MASK | SNES_DOWN_MASK)) == (SNES_UP_MASK | SNES_DOWN_MASK)) - IPPU.Joypads [i] &= ~SNES_DOWN_MASK; - } - - // BJ: This is correct behavior AFAICT (used to be Touhaiden hack) - if (IPPU.Controller == SNES_JOYPAD || IPPU.Controller == SNES_MULTIPLAYER5) - { - for (i = 0; i < 5; i++) - { - if (IPPU.Joypads [i]) - IPPU.Joypads [i] |= 0xffff0000; - } - } - - // Read mouse position if enabled - if (Settings.MouseMaster) - { - for (i = 0; i < 2; i++) - S9xProcessMouse (i); - } - - // Read SuperScope if enabled - if (Settings.SuperScopeMaster) - ProcessSuperScope (); - - if (Memory.FillRAM [0x4200] & 1) - { - PPU.Joypad1ButtonReadPos = 16; - if (Memory.FillRAM [0x4201] & 0x80) - { - PPU.Joypad2ButtonReadPos = 16; - PPU.Joypad3ButtonReadPos = 0; - } - else - { - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 16; - } - int ind = Settings.SwapJoypads ? 1 : 0; - - Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads [ind]; - Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads [ind] >> 8); - Memory.FillRAM [0x421a] = (uint8) IPPU.Joypads [ind ^ 1]; - Memory.FillRAM [0x421b] = (uint8) (IPPU.Joypads [ind ^ 1] >> 8); - if (Memory.FillRAM [0x4201] & 0x80) - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [ind]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [ind] >> 8); - Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [2]; - Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [2] >> 8); - } - else - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [3]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [3] >> 8); - Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [4]; - Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [4] >> 8); - } - } - if(Settings.Justifier||Settings.SecondJustifier) - { - Memory.FillRAM [0x421a] = 0x0E; - Memory.FillRAM [0x421b] = 0; - S9xUpdateJustifiers(); - } - -} - -#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) - { - if (!Settings.WinterGold||Settings.StarfoxHack) - FxEmulate (~0); - else - FxEmulate ((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? 700 : 350); - 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 - -// Register reads and writes... - -uint8 REGISTER_4212() -{ - uint8 GetBank = 0; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) - GetBank = 1; - - GetBank |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) - GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */ - - return (GetBank); -} - -void FLUSH_REDRAW () -{ - if (IPPU.PreviousLine != IPPU.CurrentLine) - S9xUpdateScreen (); -} - -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; - } - 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; - 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; - - 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; - } - } - PPU.OAMFlip &= ~1; - ++PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - } - - Memory.FillRAM [0x2104] = byte; -} - -void REGISTER_2118 (uint8 Byte) -{ - 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; - if (!PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - } -// Memory.FillRAM [0x2118] = Byte; -} - -void REGISTER_2118_tile (uint8 Byte) -{ - 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; - if (!PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2118] = Byte; -} - -void REGISTER_2118_linear (uint8 Byte) -{ - 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; - if (!PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2118] = Byte; -} - -void REGISTER_2119 (uint8 Byte) -{ - 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; - if (PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - } -// Memory.FillRAM [0x2119] = Byte; -} - -void REGISTER_2119_tile (uint8 Byte) -{ - 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; - if (PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2119] = Byte; -} - -void REGISTER_2119_linear (uint8 Byte) -{ - 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; - if (PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2119] = Byte; -} - -void REGISTER_2122(uint8 Byte) -{ - // CG-RAM (palette) write - - if (PPU.CGFLIP) - { - if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) - { - FLUSH_REDRAW (); - PPU.CGDATA[PPU.CGADD] &= 0x00FF; - PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; - IPPU.ColorsChanged = TRUE; - IPPU.Blue [PPU.CGADD] = IPPU.XB [(Byte >> 2) & 0x1f]; - IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; - IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], - IPPU.Green [PPU.CGADD], - IPPU.Blue [PPU.CGADD]); - } - PPU.CGADD++; - } - else - { - if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) - { - FLUSH_REDRAW (); - PPU.CGDATA[PPU.CGADD] &= 0x7F00; - PPU.CGDATA[PPU.CGADD] |= Byte; - IPPU.ColorsChanged = TRUE; - IPPU.Red [PPU.CGADD] = IPPU.XB [Byte & 0x1f]; - IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; - IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], - IPPU.Green [PPU.CGADD], - IPPU.Blue [PPU.CGADD]); - } - } - PPU.CGFLIP ^= 1; -// Memory.FillRAM [0x2122] = Byte; -} - -void REGISTER_2180(uint8 Byte) -{ - Memory.RAM[PPU.WRAM++] = Byte; - PPU.WRAM &= 0x1FFFF; - Memory.FillRAM [0x2180] = Byte; -} diff --git a/source/sa1.c b/source/sa1.c new file mode 100644 index 0000000..36a9ff6 --- /dev/null +++ b/source/sa1.c @@ -0,0 +1,936 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "snes9x.h" +#include "ppu.h" +#include "cpuexec.h" + +#include "sa1.h" + +static void S9xSA1CharConv2 (); +static void S9xSA1DMA (); +static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift); + +void S9xSA1Init () +{ + 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; +} + +void S9xSA1Reset () +{ + SA1.Registers.PB = 0; + SA1.Registers.PC = Memory.FillRAM [0x2203] | + (Memory.FillRAM [0x2204] << 8); + SA1.Registers.D.W = 0; + SA1.Registers.DB = 0; + SA1.Registers.SH = 1; + SA1.Registers.SL = 0xFF; + SA1.Registers.XH = 0; + SA1.Registers.YH = 0; + SA1.Registers.P.W = 0; + + SA1.ShiftedPB = 0; + SA1.ShiftedDB = 0; + SA1SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + SA1ClearFlags (Decimal); + + SA1.WaitingForInterrupt = FALSE; + SA1.PC = NULL; + SA1.PCBase = NULL; + S9xSA1SetPCBase (SA1.Registers.PC); + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + + 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) SA1.Registers.PB << 16; + SA1.ShiftedDB = (uint32) SA1.Registers.DB << 16; + + S9xSA1SetPCBase (SA1.ShiftedPB + SA1.Registers.PC); + 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 >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (*(GetAddress + (address & 0xffff))); + + switch ((intptr_t) 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: + return OpenBus; + } +} + +uint16 S9xSA1GetWord (uint32 address) +{ + OpenBus = S9xSA1GetByte (address); + return (OpenBus | (S9xSA1GetByte (address + 1) << 8)); +} + +void S9xSA1SetByte (uint8 byte, uint32 address) +{ + uint8 *Setaddress = SA1.WriteMap [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; + + if (Setaddress >= (uint8 *) CMemory::MAP_LAST) + { + *(Setaddress + (address & 0xffff)) = byte; + return; + } + + switch ((intptr_t) 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) +{ + S9xSA1SetByte ((uint8) Word, address); + S9xSA1SetByte ((uint8) (Word >> 8), address + 1); +} + +void S9xSA1SetPCBase (uint32 address) +{ + uint8 *GetAddress = SA1.Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + SA1.PCBase = GetAddress; + SA1.PC = GetAddress + (address & 0xffff); + return; + } + + switch ((intptr_t) GetAddress) + { + case CMemory::MAP_PPU: + SA1.PCBase = Memory.FillRAM - 0x2000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case CMemory::MAP_CPU: + SA1.PCBase = Memory.FillRAM - 0x4000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case CMemory::MAP_DSP: + SA1.PCBase = Memory.FillRAM - 0x6000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case CMemory::MAP_SA1RAM: + case CMemory::MAP_LOROM_SRAM: + SA1.PCBase = Memory.SRAM; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case CMemory::MAP_BWRAM: + SA1.PCBase = SA1.BWRAM - 0x6000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + case CMemory::MAP_HIROM_SRAM: + SA1.PCBase = Memory.SRAM - 0x6000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case CMemory::MAP_DEBUG: + + default: + case CMemory::MAP_NONE: + SA1.PCBase = Memory.RAM; + SA1.PC = Memory.RAM + (address & 0xffff); + return; + } +} + +void S9xSA1ExecuteDuringSleep () +{ +#if 0 + if (SA1.Executing) + { + while (CPU.Cycles < CPU.NextEvent) + { + S9xSA1MainLoop (); + CPU.Cycles += TWO_CYCLES * 2; + } + } +#endif +} + +void S9xSetSA1MemMap (uint32 which1, uint8 map) +{ + int c; + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; + + if (which1 >= 2) + start2 += 0x400; + + for (c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 12)]; + int i; + + for (i = c; i < c + 16; i++) + Memory.Map [start + i] = SA1.Map [start + i] = block; + } + + for (c = 0; c < 0x200; c += 16) + { + uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 11) - 0x8000]; + int i; + + for (i = c + 8; i < c + 16; i++) + Memory.Map [start2 + i] = SA1.Map [start2 + i] = block; + } +} + +uint8 S9xGetSA1 (uint32 address) +{ +// printf ("R: %04x\n", address); + switch (address) + { + case 0x2300: + return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | + (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); + case 0x2301: + return ((Memory.FillRAM [0x2200] & 0xf) | + (Memory.FillRAM [0x2301] & 0xf0)); + case 0x2306: + return ((uint8) SA1.sum); + case 0x2307: + return ((uint8) (SA1.sum >> 8)); + case 0x2308: + return ((uint8) (SA1.sum >> 16)); + case 0x2309: + return ((uint8) (SA1.sum >> 24)); + case 0x230a: + return ((uint8) (SA1.sum >> 32)); + case 0x230c: + return (Memory.FillRAM [0x230c]); + case 0x230d: + { + uint8 byte = Memory.FillRAM [0x230d]; + + if (Memory.FillRAM [0x2258] & 0x80) + { + S9xSA1ReadVariableLengthData (TRUE, FALSE); + } + return (byte); + } + default: + printf ("R: %04x\n", address); + break; + } + return (Memory.FillRAM [address]); +} + +void S9xSetSA1 (uint8 byte, uint32 address) +{ +//printf ("W: %02x -> %04x\n", byte, address); + switch (address) + { + case 0x2200: + SA1.Waiting = (byte & 0x60) != 0; +// SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + + if (!(byte & 0x20) && (Memory.FillRAM [0x2200] & 0x20)) + { + S9xSA1Reset (); + } + if (byte & 0x80) + { + Memory.FillRAM [0x2301] |= 0x80; + if (Memory.FillRAM [0x220a] & 0x80) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + } + } + if (byte & 0x10) + { + Memory.FillRAM [0x2301] |= 0x10; + 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_PENDING_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && + (Memory.FillRAM [0x2301] & byte & 0x40)) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= TIMER_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && + (Memory.FillRAM [0x2301] & byte & 0x20)) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x10) && + (Memory.FillRAM [0x2301] & byte & 0x10)) + { +#if 0 + 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_PENDING_FLAG; + break; + case 0x220c: +// printf ("SNES NMI vector: %04x\n", byte | (Memory.FillRAM [0x220d] << 8)); + break; + case 0x220d: +// printf ("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM [0x220c]); + break; + + case 0x220e: +// printf ("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM [0x220f] << 8)); + break; + case 0x220f: +// printf ("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM [0x220e]); + break; + + case 0x2210: +#if 0 + printf ("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); + printf ("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); + printf ("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); +#endif + break; + case 0x2211: + printf ("Timer reset\n"); + break; + case 0x2212: + printf ("H-Timer %04x\n", byte | (Memory.FillRAM [0x2213] << 8)); + break; + case 0x2213: + printf ("H-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2212]); + break; + case 0x2214: + printf ("V-Timer %04x\n", byte | (Memory.FillRAM [0x2215] << 8)); + break; + case 0x2215: + printf ("V-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2214]); + break; + case 0x2220: + case 0x2221: + case 0x2222: + case 0x2223: + S9xSetSA1MemMap (address - 0x2220, byte); +// printf ("MMC: %02x\n", byte); + break; + case 0x2224: +// printf ("BWRAM image SNES %02x -> 0x6000\n", byte); + Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; + break; + case 0x2225: +// printf ("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM [address]); + if (byte != Memory.FillRAM [address]) + S9xSA1SetBWRAMMemMap (byte); + break; + case 0x2226: +// printf ("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + case 0x2227: +// printf ("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + + case 0x2228: +// printf ("BW-RAM write protect area %02x\n", byte); + break; + case 0x2229: +// printf ("I-RAM SNES write protect area %02x\n", byte); + break; + case 0x222a: +// printf ("I-RAM SA1 write protect area %02x\n", byte); + break; + case 0x2230: +#if 0 + printf ("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); + printf ("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); + printf ("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); + printf ("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); + printf ("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); + printf ("DMA source %s\n", DMAsource [byte & 3]); +#endif + break; + case 0x2231: + if (byte & 0x80) + SA1.in_char_dma = FALSE; +#if 0 + printf ("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); + printf ("DMA colour mode %d\n", byte & 3); + printf ("virtual VRAM width %d\n", (byte >> 2) & 7); +#endif + break; + case 0x2232: + case 0x2233: + case 0x2234: + Memory.FillRAM [address] = byte; +#if 0 + printf ("DMA source start %06x\n", + Memory.FillRAM [0x2232] | (Memory.FillRAM [0x2233] << 8) | + (Memory.FillRAM [0x2234] << 16)); +#endif + break; + case 0x2235: + Memory.FillRAM [address] = byte; + break; + case 0x2236: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xa4) == 0x80) + { + // Normal DMA to I-RAM + S9xSA1DMA (); + } + else + if ((Memory.FillRAM [0x2230] & 0xb0) == 0xb0) + { + Memory.FillRAM [0x2300] |= 0x20; + if (Memory.FillRAM [0x2201] & 0x20) + S9xSetIRQ (SA1_DMA_IRQ_SOURCE); + SA1.in_char_dma = TRUE; + } + break; + case 0x2237: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xa4) == 0x84) + { + // Normal DMA to BW-RAM + S9xSA1DMA (); + } +#if 0 + printf ("DMA dest address %06x\n", + Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8) | + (Memory.FillRAM [0x2237] << 16)); +#endif + break; + case 0x2238: + case 0x2239: + Memory.FillRAM [address] = byte; +#if 0 + printf ("DMA length %04x\n", + Memory.FillRAM [0x2238] | (Memory.FillRAM [0x2239] << 8)); +#endif + break; + case 0x223f: + SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; + //printf ("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); + break; + + case 0x2240: case 0x2241: case 0x2242: case 0x2243: + case 0x2244: case 0x2245: case 0x2246: case 0x2247: + case 0x2248: case 0x2249: case 0x224a: case 0x224b: + case 0x224c: case 0x224d: case 0x224e: +#if 0 + if (!(SA1.Flags & TRACE_FLAG)) + { + TraceSA1 (); + Trace (); + } +#endif + Memory.FillRAM [address] = byte; + break; + + case 0x224f: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) + { + // Char conversion 2 DMA enabled + // memmove converted: Same malloc but constant non-overlapping addresses [Neb] + memcpy (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, + &Memory.FillRAM [0x2240], 16); + SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; + if ((SA1.in_char_dma & 3) == 0) + { + S9xSA1CharConv2 (); + } + } + break; + case 0x2250: + if (byte & 2) + SA1.sum = 0; + SA1.arithmetic_op = byte & 3; + break; + + case 0x2251: + SA1.op1 = (SA1.op1 & 0xff00) | byte; + break; + case 0x2252: + SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); + break; + case 0x2253: + SA1.op2 = (SA1.op2 & 0xff00) | byte; + break; + case 0x2254: + SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); + switch (SA1.arithmetic_op) + { + case 0: // multiply + SA1.sum = SA1.op1 * SA1.op2; + break; + case 1: // divide + if (SA1.op2 == 0) + SA1.sum = SA1.op1 << 16; + else + { + SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | + ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); + } + break; + case 2: + default: // cumulative sum + SA1.sum += SA1.op1 * SA1.op2; + if (SA1.sum & ((int64) 0xffffff << 32)) + SA1.overflow = TRUE; + break; + } + break; + case 0x2258: // Variable bit-field length/auto inc/start. + Memory.FillRAM [0x2258] = byte; + S9xSA1ReadVariableLengthData (TRUE, FALSE); + return; + case 0x2259: + case 0x225a: + case 0x225b: // Variable bit-field start address + Memory.FillRAM [address] = byte; + // XXX: ??? + SA1.variable_bit_pos = 0; + S9xSA1ReadVariableLengthData (FALSE, TRUE); + return; + default: +// printf ("W: %02x->%04x\n", byte, address); + break; + } + if (address >= 0x2200 && address <= 0x22ff) + Memory.FillRAM [address] = byte; +} + +static void S9xSA1CharConv2 () +{ + uint32 dest = Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8); + uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; + int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : + (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; + int bytes_per_char = 8 * depth; + uint8 *p = &Memory.FillRAM [0x3000] + dest + offset * bytes_per_char; + uint8 *q = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; + + switch (depth) + { + case 2: + break; + case 4: + break; + case 8: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + p += 2; + } + break; + } +} + +static void S9xSA1DMA () +{ + uint32 src = Memory.FillRAM [0x2232] | + (Memory.FillRAM [0x2233] << 8) | + (Memory.FillRAM [0x2234] << 16); + uint32 dst = Memory.FillRAM [0x2235] | + (Memory.FillRAM [0x2236] << 8) | + (Memory.FillRAM [0x2237] << 16); + uint32 len = Memory.FillRAM [0x2238] | + (Memory.FillRAM [0x2239] << 8); + + uint8 *s; + uint8 *d; + + switch (Memory.FillRAM [0x2230] & 3) + { + case 0: // ROM + s = SA1.Map [(src >> MEMMAP_SHIFT) & MEMMAP_MASK]; + 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 required: Can overlap arbitrarily [Neb] + memmove (d, s, len); + Memory.FillRAM [0x2301] |= 0x20; + + if (Memory.FillRAM [0x220a] & 0x20) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; +// SA1.Executing = !SA1.Waiting; + } +} + +void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) +{ + uint32 addr = Memory.FillRAM [0x2259] | + (Memory.FillRAM [0x225a] << 8) | + (Memory.FillRAM [0x225b] << 16); + uint8 shift = Memory.FillRAM [0x2258] & 15; + + if (no_shift) + shift = 0; + else + if (shift == 0) + shift = 16; + + uint8 s = shift + SA1.variable_bit_pos; + + if (s >= 16) + { + addr += (s >> 4) << 1; + s &= 15; + } + uint32 data = S9xSA1GetWord (addr) | + (S9xSA1GetWord (addr + 2) << 16); + + data >>= s; + Memory.FillRAM [0x230c] = (uint8) data; + Memory.FillRAM [0x230d] = (uint8) (data >> 8); + if (inc) + { + SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; + Memory.FillRAM [0x2259] = (uint8) addr; + Memory.FillRAM [0x225a] = (uint8) (addr >> 8); + Memory.FillRAM [0x225b] = (uint8) (addr >> 16); + } +} + diff --git a/source/sa1.cpp b/source/sa1.cpp deleted file mode 100644 index 36a9ff6..0000000 --- a/source/sa1.cpp +++ /dev/null @@ -1,936 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "snes9x.h" -#include "ppu.h" -#include "cpuexec.h" - -#include "sa1.h" - -static void S9xSA1CharConv2 (); -static void S9xSA1DMA (); -static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift); - -void S9xSA1Init () -{ - 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; -} - -void S9xSA1Reset () -{ - SA1.Registers.PB = 0; - SA1.Registers.PC = Memory.FillRAM [0x2203] | - (Memory.FillRAM [0x2204] << 8); - SA1.Registers.D.W = 0; - SA1.Registers.DB = 0; - SA1.Registers.SH = 1; - SA1.Registers.SL = 0xFF; - SA1.Registers.XH = 0; - SA1.Registers.YH = 0; - SA1.Registers.P.W = 0; - - SA1.ShiftedPB = 0; - SA1.ShiftedDB = 0; - SA1SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); - SA1ClearFlags (Decimal); - - SA1.WaitingForInterrupt = FALSE; - SA1.PC = NULL; - SA1.PCBase = NULL; - S9xSA1SetPCBase (SA1.Registers.PC); - SA1.S9xOpcodes = S9xSA1OpcodesM1X1; - - 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) SA1.Registers.PB << 16; - SA1.ShiftedDB = (uint32) SA1.Registers.DB << 16; - - S9xSA1SetPCBase (SA1.ShiftedPB + SA1.Registers.PC); - 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 >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (*(GetAddress + (address & 0xffff))); - - switch ((intptr_t) 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: - return OpenBus; - } -} - -uint16 S9xSA1GetWord (uint32 address) -{ - OpenBus = S9xSA1GetByte (address); - return (OpenBus | (S9xSA1GetByte (address + 1) << 8)); -} - -void S9xSA1SetByte (uint8 byte, uint32 address) -{ - uint8 *Setaddress = SA1.WriteMap [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - - if (Setaddress >= (uint8 *) CMemory::MAP_LAST) - { - *(Setaddress + (address & 0xffff)) = byte; - return; - } - - switch ((intptr_t) 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) -{ - S9xSA1SetByte ((uint8) Word, address); - S9xSA1SetByte ((uint8) (Word >> 8), address + 1); -} - -void S9xSA1SetPCBase (uint32 address) -{ - uint8 *GetAddress = SA1.Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - SA1.PCBase = GetAddress; - SA1.PC = GetAddress + (address & 0xffff); - return; - } - - switch ((intptr_t) GetAddress) - { - case CMemory::MAP_PPU: - SA1.PCBase = Memory.FillRAM - 0x2000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_CPU: - SA1.PCBase = Memory.FillRAM - 0x4000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_DSP: - SA1.PCBase = Memory.FillRAM - 0x6000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: - SA1.PCBase = Memory.SRAM; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_BWRAM: - SA1.PCBase = SA1.BWRAM - 0x6000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - case CMemory::MAP_HIROM_SRAM: - SA1.PCBase = Memory.SRAM - 0x6000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_DEBUG: - - default: - case CMemory::MAP_NONE: - SA1.PCBase = Memory.RAM; - SA1.PC = Memory.RAM + (address & 0xffff); - return; - } -} - -void S9xSA1ExecuteDuringSleep () -{ -#if 0 - if (SA1.Executing) - { - while (CPU.Cycles < CPU.NextEvent) - { - S9xSA1MainLoop (); - CPU.Cycles += TWO_CYCLES * 2; - } - } -#endif -} - -void S9xSetSA1MemMap (uint32 which1, uint8 map) -{ - int c; - int start = which1 * 0x100 + 0xc00; - int start2 = which1 * 0x200; - - if (which1 >= 2) - start2 += 0x400; - - for (c = 0; c < 0x100; c += 16) - { - uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 12)]; - int i; - - for (i = c; i < c + 16; i++) - Memory.Map [start + i] = SA1.Map [start + i] = block; - } - - for (c = 0; c < 0x200; c += 16) - { - uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 11) - 0x8000]; - int i; - - for (i = c + 8; i < c + 16; i++) - Memory.Map [start2 + i] = SA1.Map [start2 + i] = block; - } -} - -uint8 S9xGetSA1 (uint32 address) -{ -// printf ("R: %04x\n", address); - switch (address) - { - case 0x2300: - return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | - (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); - case 0x2301: - return ((Memory.FillRAM [0x2200] & 0xf) | - (Memory.FillRAM [0x2301] & 0xf0)); - case 0x2306: - return ((uint8) SA1.sum); - case 0x2307: - return ((uint8) (SA1.sum >> 8)); - case 0x2308: - return ((uint8) (SA1.sum >> 16)); - case 0x2309: - return ((uint8) (SA1.sum >> 24)); - case 0x230a: - return ((uint8) (SA1.sum >> 32)); - case 0x230c: - return (Memory.FillRAM [0x230c]); - case 0x230d: - { - uint8 byte = Memory.FillRAM [0x230d]; - - if (Memory.FillRAM [0x2258] & 0x80) - { - S9xSA1ReadVariableLengthData (TRUE, FALSE); - } - return (byte); - } - default: - printf ("R: %04x\n", address); - break; - } - return (Memory.FillRAM [address]); -} - -void S9xSetSA1 (uint8 byte, uint32 address) -{ -//printf ("W: %02x -> %04x\n", byte, address); - switch (address) - { - case 0x2200: - SA1.Waiting = (byte & 0x60) != 0; -// SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - - if (!(byte & 0x20) && (Memory.FillRAM [0x2200] & 0x20)) - { - S9xSA1Reset (); - } - if (byte & 0x80) - { - Memory.FillRAM [0x2301] |= 0x80; - if (Memory.FillRAM [0x220a] & 0x80) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - } - } - if (byte & 0x10) - { - Memory.FillRAM [0x2301] |= 0x10; - 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_PENDING_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; -// SA1.Executing = !SA1.Waiting; - } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && - (Memory.FillRAM [0x2301] & byte & 0x40)) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= TIMER_IRQ_SOURCE; -// SA1.Executing = !SA1.Waiting; - } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && - (Memory.FillRAM [0x2301] & byte & 0x20)) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; -// SA1.Executing = !SA1.Waiting; - } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x10) && - (Memory.FillRAM [0x2301] & byte & 0x10)) - { -#if 0 - 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_PENDING_FLAG; - break; - case 0x220c: -// printf ("SNES NMI vector: %04x\n", byte | (Memory.FillRAM [0x220d] << 8)); - break; - case 0x220d: -// printf ("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM [0x220c]); - break; - - case 0x220e: -// printf ("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM [0x220f] << 8)); - break; - case 0x220f: -// printf ("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM [0x220e]); - break; - - case 0x2210: -#if 0 - printf ("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); - printf ("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); - printf ("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); -#endif - break; - case 0x2211: - printf ("Timer reset\n"); - break; - case 0x2212: - printf ("H-Timer %04x\n", byte | (Memory.FillRAM [0x2213] << 8)); - break; - case 0x2213: - printf ("H-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2212]); - break; - case 0x2214: - printf ("V-Timer %04x\n", byte | (Memory.FillRAM [0x2215] << 8)); - break; - case 0x2215: - printf ("V-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2214]); - break; - case 0x2220: - case 0x2221: - case 0x2222: - case 0x2223: - S9xSetSA1MemMap (address - 0x2220, byte); -// printf ("MMC: %02x\n", byte); - break; - case 0x2224: -// printf ("BWRAM image SNES %02x -> 0x6000\n", byte); - Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; - break; - case 0x2225: -// printf ("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM [address]); - if (byte != Memory.FillRAM [address]) - S9xSA1SetBWRAMMemMap (byte); - break; - case 0x2226: -// printf ("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - case 0x2227: -// printf ("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2228: -// printf ("BW-RAM write protect area %02x\n", byte); - break; - case 0x2229: -// printf ("I-RAM SNES write protect area %02x\n", byte); - break; - case 0x222a: -// printf ("I-RAM SA1 write protect area %02x\n", byte); - break; - case 0x2230: -#if 0 - printf ("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); - printf ("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); - printf ("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); - printf ("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); - printf ("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); - printf ("DMA source %s\n", DMAsource [byte & 3]); -#endif - break; - case 0x2231: - if (byte & 0x80) - SA1.in_char_dma = FALSE; -#if 0 - printf ("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); - printf ("DMA colour mode %d\n", byte & 3); - printf ("virtual VRAM width %d\n", (byte >> 2) & 7); -#endif - break; - case 0x2232: - case 0x2233: - case 0x2234: - Memory.FillRAM [address] = byte; -#if 0 - printf ("DMA source start %06x\n", - Memory.FillRAM [0x2232] | (Memory.FillRAM [0x2233] << 8) | - (Memory.FillRAM [0x2234] << 16)); -#endif - break; - case 0x2235: - Memory.FillRAM [address] = byte; - break; - case 0x2236: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xa4) == 0x80) - { - // Normal DMA to I-RAM - S9xSA1DMA (); - } - else - if ((Memory.FillRAM [0x2230] & 0xb0) == 0xb0) - { - Memory.FillRAM [0x2300] |= 0x20; - if (Memory.FillRAM [0x2201] & 0x20) - S9xSetIRQ (SA1_DMA_IRQ_SOURCE); - SA1.in_char_dma = TRUE; - } - break; - case 0x2237: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xa4) == 0x84) - { - // Normal DMA to BW-RAM - S9xSA1DMA (); - } -#if 0 - printf ("DMA dest address %06x\n", - Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8) | - (Memory.FillRAM [0x2237] << 16)); -#endif - break; - case 0x2238: - case 0x2239: - Memory.FillRAM [address] = byte; -#if 0 - printf ("DMA length %04x\n", - Memory.FillRAM [0x2238] | (Memory.FillRAM [0x2239] << 8)); -#endif - break; - case 0x223f: - SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; - //printf ("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); - break; - - case 0x2240: case 0x2241: case 0x2242: case 0x2243: - case 0x2244: case 0x2245: case 0x2246: case 0x2247: - case 0x2248: case 0x2249: case 0x224a: case 0x224b: - case 0x224c: case 0x224d: case 0x224e: -#if 0 - if (!(SA1.Flags & TRACE_FLAG)) - { - TraceSA1 (); - Trace (); - } -#endif - Memory.FillRAM [address] = byte; - break; - - case 0x224f: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) - { - // Char conversion 2 DMA enabled - // memmove converted: Same malloc but constant non-overlapping addresses [Neb] - memcpy (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, - &Memory.FillRAM [0x2240], 16); - SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; - if ((SA1.in_char_dma & 3) == 0) - { - S9xSA1CharConv2 (); - } - } - break; - case 0x2250: - if (byte & 2) - SA1.sum = 0; - SA1.arithmetic_op = byte & 3; - break; - - case 0x2251: - SA1.op1 = (SA1.op1 & 0xff00) | byte; - break; - case 0x2252: - SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); - break; - case 0x2253: - SA1.op2 = (SA1.op2 & 0xff00) | byte; - break; - case 0x2254: - SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); - switch (SA1.arithmetic_op) - { - case 0: // multiply - SA1.sum = SA1.op1 * SA1.op2; - break; - case 1: // divide - if (SA1.op2 == 0) - SA1.sum = SA1.op1 << 16; - else - { - SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | - ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); - } - break; - case 2: - default: // cumulative sum - SA1.sum += SA1.op1 * SA1.op2; - if (SA1.sum & ((int64) 0xffffff << 32)) - SA1.overflow = TRUE; - break; - } - break; - case 0x2258: // Variable bit-field length/auto inc/start. - Memory.FillRAM [0x2258] = byte; - S9xSA1ReadVariableLengthData (TRUE, FALSE); - return; - case 0x2259: - case 0x225a: - case 0x225b: // Variable bit-field start address - Memory.FillRAM [address] = byte; - // XXX: ??? - SA1.variable_bit_pos = 0; - S9xSA1ReadVariableLengthData (FALSE, TRUE); - return; - default: -// printf ("W: %02x->%04x\n", byte, address); - break; - } - if (address >= 0x2200 && address <= 0x22ff) - Memory.FillRAM [address] = byte; -} - -static void S9xSA1CharConv2 () -{ - uint32 dest = Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8); - uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; - int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : - (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; - int bytes_per_char = 8 * depth; - uint8 *p = &Memory.FillRAM [0x3000] + dest + offset * bytes_per_char; - uint8 *q = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; - - switch (depth) - { - case 2: - break; - case 4: - break; - case 8: - for (int l = 0; l < 8; l++, q += 8) - { - for (int b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - p += 2; - } - break; - } -} - -static void S9xSA1DMA () -{ - uint32 src = Memory.FillRAM [0x2232] | - (Memory.FillRAM [0x2233] << 8) | - (Memory.FillRAM [0x2234] << 16); - uint32 dst = Memory.FillRAM [0x2235] | - (Memory.FillRAM [0x2236] << 8) | - (Memory.FillRAM [0x2237] << 16); - uint32 len = Memory.FillRAM [0x2238] | - (Memory.FillRAM [0x2239] << 8); - - uint8 *s; - uint8 *d; - - switch (Memory.FillRAM [0x2230] & 3) - { - case 0: // ROM - s = SA1.Map [(src >> MEMMAP_SHIFT) & MEMMAP_MASK]; - 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 required: Can overlap arbitrarily [Neb] - memmove (d, s, len); - Memory.FillRAM [0x2301] |= 0x20; - - if (Memory.FillRAM [0x220a] & 0x20) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; -// SA1.Executing = !SA1.Waiting; - } -} - -void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) -{ - uint32 addr = Memory.FillRAM [0x2259] | - (Memory.FillRAM [0x225a] << 8) | - (Memory.FillRAM [0x225b] << 16); - uint8 shift = Memory.FillRAM [0x2258] & 15; - - if (no_shift) - shift = 0; - else - if (shift == 0) - shift = 16; - - uint8 s = shift + SA1.variable_bit_pos; - - if (s >= 16) - { - addr += (s >> 4) << 1; - s &= 15; - } - uint32 data = S9xSA1GetWord (addr) | - (S9xSA1GetWord (addr + 2) << 16); - - data >>= s; - Memory.FillRAM [0x230c] = (uint8) data; - Memory.FillRAM [0x230d] = (uint8) (data >> 8); - if (inc) - { - SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; - Memory.FillRAM [0x2259] = (uint8) addr; - Memory.FillRAM [0x225a] = (uint8) (addr >> 8); - Memory.FillRAM [0x225b] = (uint8) (addr >> 16); - } -} - diff --git a/source/sa1cpu.c b/source/sa1cpu.c new file mode 100644 index 0000000..299aab3 --- /dev/null +++ b/source/sa1cpu.c @@ -0,0 +1,245 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" + +#include "sa1.h" +#define CPU SA1 +#define ICPU SA1 +#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 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 SetZN16 SA1SetZN16 +#define SetZN8 SA1SetZN8 +#define ADC8 SA1ADC8 +#define ADC16 SA1ADC16 +#define AND16 SA1AND16 +#define AND8 SA1AND8 +#define A_ASL16 SA1A_ASL16 +#define A_ASL8 SA1A_ASL8 +#define ASL16 SA1ASL16 +#define ASL8 SA1ASL8 +#define BIT16 SA1BIT16 +#define BIT8 SA1BIT8 +#define CMP16 SA1CMP16 +#define CMP8 SA1CMP8 +#define CMX16 SA1CMX16 +#define CMX8 SA1CMX8 +#define CMY16 SA1CMY16 +#define CMY8 SA1CMY8 +#define A_DEC16 SA1A_DEC16 +#define A_DEC8 SA1A_DEC8 +#define DEC16 SA1DEC16 +#define DEC8 SA1DEC8 +#define EOR16 SA1EOR16 +#define EOR8 SA1EOR8 +#define A_INC16 SA1A_INC16 +#define A_INC8 SA1A_INC8 +#define INC16 SA1INC16 +#define INC8 SA1INC8 +#define LDA16 SA1LDA16 +#define LDA8 SA1LDA8 +#define LDX16 SA1LDX16 +#define LDX8 SA1LDX8 +#define LDY16 SA1LDY16 +#define LDY8 SA1LDY8 +#define A_LSR16 SA1A_LSR16 +#define A_LSR8 SA1A_LSR8 +#define LSR16 SA1LSR16 +#define LSR8 SA1LSR8 +#define ORA16 SA1ORA16 +#define ORA8 SA1ORA8 +#define A_ROL16 SA1A_ROL16 +#define A_ROL8 SA1A_ROL8 +#define ROL16 SA1ROL16 +#define ROL8 SA1ROL8 +#define A_ROR16 SA1A_ROR16 +#define A_ROR8 SA1A_ROR8 +#define ROR16 SA1ROR16 +#define ROR8 SA1ROR8 +#define SBC16 SA1SBC16 +#define SBC8 SA1SBC8 +#define STA16 SA1STA16 +#define STA8 SA1STA8 +#define STX16 SA1STX16 +#define STX8 SA1STX8 +#define STY16 SA1STY16 +#define STY8 SA1STY8 +#define STZ16 SA1STZ16 +#define STZ8 SA1STZ8 +#define TSB16 SA1TSB16 +#define TSB8 SA1TSB8 +#define TRB16 SA1TRB16 +#define TRB8 SA1TRB8 + +//#undef CPU_SHUTDOWN +#undef VAR_CYCLES +#define SA1_OPCODES + +#include "cpuops.cpp" + +void S9xSA1MainLoop () +{ + int i; + +#if 0 + if (SA1.Flags & NMI_FLAG) + { + SA1.Flags &= ~NMI_FLAG; + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1.PC++; + } + S9xSA1Opcode_NMI (); + } +#endif + if (SA1.Flags & IRQ_PENDING_FLAG) + { + if (SA1.IRQActive) + { + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1.PC++; + } + if (!SA1CheckFlag (IRQ)) + S9xSA1Opcode_IRQ (); + } + else + SA1.Flags &= ~IRQ_PENDING_FLAG; + } + + for (i = 0; i < 3 && SA1.Executing; i++) + { +#ifdef CPU_SHUTDOWN + SA1.PCAtOpcodeStart = SA1.PC; +#endif + (*SA1.S9xOpcodes [*SA1.PC++].S9xOpcode) (); + } +} + diff --git a/source/sa1cpu.cpp b/source/sa1cpu.cpp deleted file mode 100644 index 299aab3..0000000 --- a/source/sa1cpu.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" - -#include "sa1.h" -#define CPU SA1 -#define ICPU SA1 -#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 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 SetZN16 SA1SetZN16 -#define SetZN8 SA1SetZN8 -#define ADC8 SA1ADC8 -#define ADC16 SA1ADC16 -#define AND16 SA1AND16 -#define AND8 SA1AND8 -#define A_ASL16 SA1A_ASL16 -#define A_ASL8 SA1A_ASL8 -#define ASL16 SA1ASL16 -#define ASL8 SA1ASL8 -#define BIT16 SA1BIT16 -#define BIT8 SA1BIT8 -#define CMP16 SA1CMP16 -#define CMP8 SA1CMP8 -#define CMX16 SA1CMX16 -#define CMX8 SA1CMX8 -#define CMY16 SA1CMY16 -#define CMY8 SA1CMY8 -#define A_DEC16 SA1A_DEC16 -#define A_DEC8 SA1A_DEC8 -#define DEC16 SA1DEC16 -#define DEC8 SA1DEC8 -#define EOR16 SA1EOR16 -#define EOR8 SA1EOR8 -#define A_INC16 SA1A_INC16 -#define A_INC8 SA1A_INC8 -#define INC16 SA1INC16 -#define INC8 SA1INC8 -#define LDA16 SA1LDA16 -#define LDA8 SA1LDA8 -#define LDX16 SA1LDX16 -#define LDX8 SA1LDX8 -#define LDY16 SA1LDY16 -#define LDY8 SA1LDY8 -#define A_LSR16 SA1A_LSR16 -#define A_LSR8 SA1A_LSR8 -#define LSR16 SA1LSR16 -#define LSR8 SA1LSR8 -#define ORA16 SA1ORA16 -#define ORA8 SA1ORA8 -#define A_ROL16 SA1A_ROL16 -#define A_ROL8 SA1A_ROL8 -#define ROL16 SA1ROL16 -#define ROL8 SA1ROL8 -#define A_ROR16 SA1A_ROR16 -#define A_ROR8 SA1A_ROR8 -#define ROR16 SA1ROR16 -#define ROR8 SA1ROR8 -#define SBC16 SA1SBC16 -#define SBC8 SA1SBC8 -#define STA16 SA1STA16 -#define STA8 SA1STA8 -#define STX16 SA1STX16 -#define STX8 SA1STX8 -#define STY16 SA1STY16 -#define STY8 SA1STY8 -#define STZ16 SA1STZ16 -#define STZ8 SA1STZ8 -#define TSB16 SA1TSB16 -#define TSB8 SA1TSB8 -#define TRB16 SA1TRB16 -#define TRB8 SA1TRB8 - -//#undef CPU_SHUTDOWN -#undef VAR_CYCLES -#define SA1_OPCODES - -#include "cpuops.cpp" - -void S9xSA1MainLoop () -{ - int i; - -#if 0 - if (SA1.Flags & NMI_FLAG) - { - SA1.Flags &= ~NMI_FLAG; - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1.PC++; - } - S9xSA1Opcode_NMI (); - } -#endif - if (SA1.Flags & IRQ_PENDING_FLAG) - { - if (SA1.IRQActive) - { - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1.PC++; - } - if (!SA1CheckFlag (IRQ)) - S9xSA1Opcode_IRQ (); - } - else - SA1.Flags &= ~IRQ_PENDING_FLAG; - } - - for (i = 0; i < 3 && SA1.Executing; i++) - { -#ifdef CPU_SHUTDOWN - SA1.PCAtOpcodeStart = SA1.PC; -#endif - (*SA1.S9xOpcodes [*SA1.PC++].S9xOpcode) (); - } -} - diff --git a/source/screenshot.c b/source/screenshot.c new file mode 100644 index 0000000..f33b240 --- /dev/null +++ b/source/screenshot.c @@ -0,0 +1,235 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + + +#ifdef HAVE_CONFIG_H + #include +#endif +#include + +#ifndef __WIN32__ +#include +#else +#include +#endif +#include +#include + +#ifdef HAVE_LIBPNG +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "display.h" +#include "gfx.h" +#include "ppu.h" +#include "screenshot.h" + +bool8 S9xDoScreenshot(int width, int height){ +#ifdef HAVE_LIBPNG + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + png_color pngpal[256]; + int imgwidth; + int imgheight; + const char *fname=S9xGetFilenameInc(".png"); + + Settings.TakeScreenshot=FALSE; + + if((fp=fopen(fname, "wb"))==NULL){ + perror("Screenshot failed"); + return FALSE; + } + + png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if(!png_ptr){ + fclose(fp); + unlink(fname); + return FALSE; + } + info_ptr=png_create_info_struct(png_ptr); + if(!info_ptr){ + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose(fp); + unlink(fname); + return FALSE; + } + + if(setjmp(png_jmpbuf(png_ptr))){ + perror("Screenshot: setjmp"); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + unlink(fname); + return FALSE; + } + + imgwidth=width; + imgheight=height; + if(Settings.StretchScreenshots==1){ + if(width<=256 && height>SNES_HEIGHT_EXTENDED) imgwidth=width<<1; + if(width>256 && height<=SNES_HEIGHT_EXTENDED) imgheight=height<<1; + } else if(Settings.StretchScreenshots==2){ + if(width<=256) imgwidth=width<<1; + if(height<=SNES_HEIGHT_EXTENDED) imgheight=height<<1; + } + + png_init_io(png_ptr, fp); + if(!Settings.SixteenBit){ + // BJ: credit sanmaiwashi for the idea to do palettized pngs, and to + // S9xSetPalette in x11.cpp for how to calculate the RGB values + int b=IPPU.MaxBrightness*140; + for(int i=0; i<256; i++){ + pngpal[i].red = (PPU.CGDATA[i] & 0x1f)*b>>8; + pngpal[i].green = ((PPU.CGDATA[i] >> 5) & 0x1f)*b>>8; + pngpal[i].blue = ((PPU.CGDATA[i] >> 10) & 0x1f)*b>>8; + } + png_set_PLTE(png_ptr, info_ptr, pngpal, 256); + } + png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, + (Settings.SixteenBit?PNG_COLOR_TYPE_RGB:PNG_COLOR_TYPE_PALETTE), + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + if(Settings.SixteenBit){ + /* 5 bits per color */ + 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)]; + uint8 *screen=GFX.Screen; + for(int y=0; y -#endif -#include - -#ifndef __WIN32__ -#include -#else -#include -#endif -#include -#include - -#ifdef HAVE_LIBPNG -#include -#endif - -#include "snes9x.h" -#include "memmap.h" -#include "display.h" -#include "gfx.h" -#include "ppu.h" -#include "screenshot.h" - -bool8 S9xDoScreenshot(int width, int height){ -#ifdef HAVE_LIBPNG - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - png_color_8 sig_bit; - png_color pngpal[256]; - int imgwidth; - int imgheight; - const char *fname=S9xGetFilenameInc(".png"); - - Settings.TakeScreenshot=FALSE; - - if((fp=fopen(fname, "wb"))==NULL){ - perror("Screenshot failed"); - return FALSE; - } - - png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if(!png_ptr){ - fclose(fp); - unlink(fname); - return FALSE; - } - info_ptr=png_create_info_struct(png_ptr); - if(!info_ptr){ - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - fclose(fp); - unlink(fname); - return FALSE; - } - - if(setjmp(png_jmpbuf(png_ptr))){ - perror("Screenshot: setjmp"); - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); - unlink(fname); - return FALSE; - } - - imgwidth=width; - imgheight=height; - if(Settings.StretchScreenshots==1){ - if(width<=256 && height>SNES_HEIGHT_EXTENDED) imgwidth=width<<1; - if(width>256 && height<=SNES_HEIGHT_EXTENDED) imgheight=height<<1; - } else if(Settings.StretchScreenshots==2){ - if(width<=256) imgwidth=width<<1; - if(height<=SNES_HEIGHT_EXTENDED) imgheight=height<<1; - } - - png_init_io(png_ptr, fp); - if(!Settings.SixteenBit){ - // BJ: credit sanmaiwashi for the idea to do palettized pngs, and to - // S9xSetPalette in x11.cpp for how to calculate the RGB values - int b=IPPU.MaxBrightness*140; - for(int i=0; i<256; i++){ - pngpal[i].red = (PPU.CGDATA[i] & 0x1f)*b>>8; - pngpal[i].green = ((PPU.CGDATA[i] >> 5) & 0x1f)*b>>8; - pngpal[i].blue = ((PPU.CGDATA[i] >> 10) & 0x1f)*b>>8; - } - png_set_PLTE(png_ptr, info_ptr, pngpal, 256); - } - png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, - (Settings.SixteenBit?PNG_COLOR_TYPE_RGB:PNG_COLOR_TYPE_PALETTE), - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - if(Settings.SixteenBit){ - /* 5 bits per color */ - 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)]; - uint8 *screen=GFX.Screen; - for(int y=0; y +#endif + +void S9xSetSDD1MemoryMap (uint32 bank, uint32 value) +{ + 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"), "wb"); + + if (fs) + { + fwrite (Memory.SDD1LoggedData, 8, + Memory.SDD1LoggedDataCount, fs); + fclose (fs); +#if defined(__linux) + chown (S9xGetFilename (".dat"), getuid (), getgid ()); +#endif + } + Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount; + } +} + +void S9xSDD1LoadLoggedData () +{ + FILE *fs = fopen (S9xGetFilename (".dat"), "rb"); + + Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0; + + if (fs) + { + int c = fread (Memory.SDD1LoggedData, 8, + MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs); + + if (c != EOF) + Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c; + fclose (fs); + } +} + diff --git a/source/sdd1.cpp b/source/sdd1.cpp deleted file mode 100644 index 7dc6f4a..0000000 --- a/source/sdd1.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#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; - - 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"), "wb"); - - if (fs) - { - fwrite (Memory.SDD1LoggedData, 8, - Memory.SDD1LoggedDataCount, fs); - fclose (fs); -#if defined(__linux) - chown (S9xGetFilename (".dat"), getuid (), getgid ()); -#endif - } - Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount; - } -} - -void S9xSDD1LoadLoggedData () -{ - FILE *fs = fopen (S9xGetFilename (".dat"), "rb"); - - Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0; - - if (fs) - { - int c = fread (Memory.SDD1LoggedData, 8, - MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs); - - if (c != EOF) - Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c; - fclose (fs); - } -} - diff --git a/source/sdd1emu.c b/source/sdd1emu.c new file mode 100644 index 0000000..bc32b43 --- /dev/null +++ b/source/sdd1emu.c @@ -0,0 +1,414 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +/* S-DD1 decompressor + * + * Based on code and documentation by Andreas Naive, who deserves a great deal + * of thanks and credit for figuring this out. + * + * Andreas says: + * The author is greatly indebted with The Dumper, without whose help and + * patience providing him with real S-DD1 data the research had never been + * possible. He also wish to note that in the very beggining of his research, + * Neviksti had done some steps in the right direction. By last, the author is + * indirectly indebted to all the people that worked and contributed in the + * S-DD1 issue in the past. + */ + +#include +#include "port.h" +#include "sdd1emu.h" + +static int valid_bits; +static uint16 in_stream; +static uint8 *in_buf; +static uint8 bit_ctr[8]; +static uint8 context_states[32]; +static int context_MPS[32]; +static int bitplane_type; +static int high_context_bits; +static int low_context_bits; +static int prev_bits[8]; + +static struct { + uint8 code_size; + uint8 MPS_next; + uint8 LPS_next; +} evolution_table[] = { + /* 0 */ { 0,25,25}, + /* 1 */ { 0, 2, 1}, + /* 2 */ { 0, 3, 1}, + /* 3 */ { 0, 4, 2}, + /* 4 */ { 0, 5, 3}, + /* 5 */ { 1, 6, 4}, + /* 6 */ { 1, 7, 5}, + /* 7 */ { 1, 8, 6}, + /* 8 */ { 1, 9, 7}, + /* 9 */ { 2,10, 8}, + /* 10 */ { 2,11, 9}, + /* 11 */ { 2,12,10}, + /* 12 */ { 2,13,11}, + /* 13 */ { 3,14,12}, + /* 14 */ { 3,15,13}, + /* 15 */ { 3,16,14}, + /* 16 */ { 3,17,15}, + /* 17 */ { 4,18,16}, + /* 18 */ { 4,19,17}, + /* 19 */ { 5,20,18}, + /* 20 */ { 5,21,19}, + /* 21 */ { 6,22,20}, + /* 22 */ { 6,23,21}, + /* 23 */ { 7,24,22}, + /* 24 */ { 7,24,23}, + /* 25 */ { 0,26, 1}, + /* 26 */ { 1,27, 2}, + /* 27 */ { 2,28, 4}, + /* 28 */ { 3,29, 8}, + /* 29 */ { 4,30,12}, + /* 30 */ { 5,31,16}, + /* 31 */ { 6,32,18}, + /* 32 */ { 7,24,22} +}; + +static uint8 run_table[128] = { + 128, 64, 96, 32, 112, 48, 80, 16, 120, 56, 88, 24, 104, 40, 72, + 8, 124, 60, 92, 28, 108, 44, 76, 12, 116, 52, 84, 20, 100, 36, + 68, 4, 126, 62, 94, 30, 110, 46, 78, 14, 118, 54, 86, 22, 102, + 38, 70, 6, 122, 58, 90, 26, 106, 42, 74, 10, 114, 50, 82, 18, + 98, 34, 66, 2, 127, 63, 95, 31, 111, 47, 79, 15, 119, 55, 87, + 23, 103, 39, 71, 7, 123, 59, 91, 27, 107, 43, 75, 11, 115, 51, + 83, 19, 99, 35, 67, 3, 125, 61, 93, 29, 109, 45, 77, 13, 117, + 53, 85, 21, 101, 37, 69, 5, 121, 57, 89, 25, 105, 41, 73, 9, + 113, 49, 81, 17, 97, 33, 65, 1 +}; + +static inline uint8 GetCodeword(int bits){ + uint8 tmp; + + if(!valid_bits){ + in_stream|=*(in_buf++); + valid_bits=8; + } + in_stream<<=1; + valid_bits--; + in_stream^=0x8000; + if(in_stream&0x8000) return 0x80+(1<>8) | (0x7f>>bits); + in_stream<<=bits; + valid_bits-=bits; + if(valid_bits<0){ + in_stream |= (*(in_buf++))<<(-valid_bits); + valid_bits+=8; + } + return run_table[tmp]; +} + +static inline uint8 GolombGetBit(int code_size){ + if(!bit_ctr[code_size]) bit_ctr[code_size]=GetCodeword(code_size); + bit_ctr[code_size]--; + if(bit_ctr[code_size]==0x80){ + bit_ctr[code_size]=0; + return 2; /* secret code for 'last zero'. ones are always last. */ + } + return (bit_ctr[code_size]==0)?1:0; +} + +static inline uint8 ProbGetBit(uint8 context){ + uint8 state=context_states[context]; + uint8 bit=GolombGetBit(evolution_table[state].code_size); + + if(bit&1){ + context_states[context]=evolution_table[state].LPS_next; + if(state<2){ + context_MPS[context]^=1; + return context_MPS[context]; /* just inverted, so just return it */ + } else{ + return context_MPS[context]^1; /* we know bit is 1, so use a constant */ + } + } else if(bit){ + context_states[context]=evolution_table[state].MPS_next; + /* zero here, zero there, no difference so drop through. */ + } + return context_MPS[context]; /* we know bit is 0, so don't bother xoring */ +} + +static inline uint8 GetBit(uint8 cur_bitplane){ + uint8 bit; + + bit=ProbGetBit(((cur_bitplane&1)<<4) + | ((prev_bits[cur_bitplane]&high_context_bits)>>5) + | (prev_bits[cur_bitplane]&low_context_bits)); + + prev_bits[cur_bitplane] <<= 1; + prev_bits[cur_bitplane] |= bit; + return bit; +} + +void SDD1_decompress(uint8 *out, uint8 *in, int len){ + uint8 bit, i, plane; + uint8 byte1, byte2; + + if(len==0) len=0x10000; + + bitplane_type=in[0]>>6; + + switch(in[0]&0x30){ + case 0x00: + high_context_bits=0x01c0; + low_context_bits =0x0001; + break; + case 0x10: + high_context_bits=0x0180; + low_context_bits =0x0001; + break; + case 0x20: + high_context_bits=0x00c0; + low_context_bits =0x0001; + break; + case 0x30: + high_context_bits=0x0180; + low_context_bits =0x0003; + break; + } + + in_stream=(in[0]<<11) | (in[1]<<3); + valid_bits=5; + in_buf=in+2; + memset(bit_ctr, 0, sizeof(bit_ctr)); + memset(context_states, 0, sizeof(context_states)); + memset(context_MPS, 0, sizeof(context_MPS)); + memset(prev_bits, 0, sizeof(prev_bits)); + + switch(bitplane_type){ + case 0: + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(0)) byte1 |= bit; + if(GetBit(1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + } + break; + case 1: + i=plane=0; + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(plane)) byte1 |= bit; + if(GetBit(plane+1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + if(!(i+=32)) plane = (plane+2)&7; + } + break; + case 2: + i=plane=0; + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(plane)) byte1 |= bit; + if(GetBit(plane+1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + if(!(i+=32)) plane ^= 2; + } + break; + case 3: + do { + for(byte1=plane=0, bit=1; bit; bit<<=1, plane++){ + if(GetBit(plane)) byte1 |= bit; + } + *(out++)=byte1; + } while(--len); + break; + } +} + +static uint8 cur_plane; +static uint8 num_bits; +static uint8 next_byte; + +void SDD1_init(uint8 *in){ + bitplane_type=in[0]>>6; + + switch(in[0]&0x30){ + case 0x00: + high_context_bits=0x01c0; + low_context_bits =0x0001; + break; + case 0x10: + high_context_bits=0x0180; + low_context_bits =0x0001; + break; + case 0x20: + high_context_bits=0x00c0; + low_context_bits =0x0001; + break; + case 0x30: + high_context_bits=0x0180; + low_context_bits =0x0003; + break; + } + + in_stream=(in[0]<<11) | (in[1]<<3); + valid_bits=5; + in_buf=in+2; + memset(bit_ctr, 0, sizeof(bit_ctr)); + memset(context_states, 0, sizeof(context_states)); + memset(context_MPS, 0, sizeof(context_MPS)); + memset(prev_bits, 0, sizeof(prev_bits)); + + cur_plane=0; + num_bits=0; +} + +uint8 SDD1_get_byte(void){ + uint8 bit; + uint8 byte=0; + + switch(bitplane_type){ + case 0: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(0)) byte |= bit; + if(GetBit(1)) next_byte |= bit; + } + return byte; + } else { + return next_byte; + } + + case 1: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(cur_plane)) byte |= bit; + if(GetBit(cur_plane+1)) next_byte |= bit; + } + return byte; + } else { + if(!num_bits) cur_plane = (cur_plane+2)&7; + return next_byte; + } + + case 2: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(cur_plane)) byte |= bit; + if(GetBit(cur_plane+1)) next_byte |= bit; + } + return byte; + } else { + if(!num_bits) cur_plane ^= 2; + return next_byte; + } + + case 3: + for(cur_plane=0, bit=1; bit; bit<<=1, cur_plane++){ + if(GetBit(cur_plane)) byte |= bit; + } + return byte; + + default: + /* should never happen */ + return 0; + } +} + diff --git a/source/sdd1emu.cpp b/source/sdd1emu.cpp deleted file mode 100644 index bc32b43..0000000 --- a/source/sdd1emu.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -/* S-DD1 decompressor - * - * Based on code and documentation by Andreas Naive, who deserves a great deal - * of thanks and credit for figuring this out. - * - * Andreas says: - * The author is greatly indebted with The Dumper, without whose help and - * patience providing him with real S-DD1 data the research had never been - * possible. He also wish to note that in the very beggining of his research, - * Neviksti had done some steps in the right direction. By last, the author is - * indirectly indebted to all the people that worked and contributed in the - * S-DD1 issue in the past. - */ - -#include -#include "port.h" -#include "sdd1emu.h" - -static int valid_bits; -static uint16 in_stream; -static uint8 *in_buf; -static uint8 bit_ctr[8]; -static uint8 context_states[32]; -static int context_MPS[32]; -static int bitplane_type; -static int high_context_bits; -static int low_context_bits; -static int prev_bits[8]; - -static struct { - uint8 code_size; - uint8 MPS_next; - uint8 LPS_next; -} evolution_table[] = { - /* 0 */ { 0,25,25}, - /* 1 */ { 0, 2, 1}, - /* 2 */ { 0, 3, 1}, - /* 3 */ { 0, 4, 2}, - /* 4 */ { 0, 5, 3}, - /* 5 */ { 1, 6, 4}, - /* 6 */ { 1, 7, 5}, - /* 7 */ { 1, 8, 6}, - /* 8 */ { 1, 9, 7}, - /* 9 */ { 2,10, 8}, - /* 10 */ { 2,11, 9}, - /* 11 */ { 2,12,10}, - /* 12 */ { 2,13,11}, - /* 13 */ { 3,14,12}, - /* 14 */ { 3,15,13}, - /* 15 */ { 3,16,14}, - /* 16 */ { 3,17,15}, - /* 17 */ { 4,18,16}, - /* 18 */ { 4,19,17}, - /* 19 */ { 5,20,18}, - /* 20 */ { 5,21,19}, - /* 21 */ { 6,22,20}, - /* 22 */ { 6,23,21}, - /* 23 */ { 7,24,22}, - /* 24 */ { 7,24,23}, - /* 25 */ { 0,26, 1}, - /* 26 */ { 1,27, 2}, - /* 27 */ { 2,28, 4}, - /* 28 */ { 3,29, 8}, - /* 29 */ { 4,30,12}, - /* 30 */ { 5,31,16}, - /* 31 */ { 6,32,18}, - /* 32 */ { 7,24,22} -}; - -static uint8 run_table[128] = { - 128, 64, 96, 32, 112, 48, 80, 16, 120, 56, 88, 24, 104, 40, 72, - 8, 124, 60, 92, 28, 108, 44, 76, 12, 116, 52, 84, 20, 100, 36, - 68, 4, 126, 62, 94, 30, 110, 46, 78, 14, 118, 54, 86, 22, 102, - 38, 70, 6, 122, 58, 90, 26, 106, 42, 74, 10, 114, 50, 82, 18, - 98, 34, 66, 2, 127, 63, 95, 31, 111, 47, 79, 15, 119, 55, 87, - 23, 103, 39, 71, 7, 123, 59, 91, 27, 107, 43, 75, 11, 115, 51, - 83, 19, 99, 35, 67, 3, 125, 61, 93, 29, 109, 45, 77, 13, 117, - 53, 85, 21, 101, 37, 69, 5, 121, 57, 89, 25, 105, 41, 73, 9, - 113, 49, 81, 17, 97, 33, 65, 1 -}; - -static inline uint8 GetCodeword(int bits){ - uint8 tmp; - - if(!valid_bits){ - in_stream|=*(in_buf++); - valid_bits=8; - } - in_stream<<=1; - valid_bits--; - in_stream^=0x8000; - if(in_stream&0x8000) return 0x80+(1<>8) | (0x7f>>bits); - in_stream<<=bits; - valid_bits-=bits; - if(valid_bits<0){ - in_stream |= (*(in_buf++))<<(-valid_bits); - valid_bits+=8; - } - return run_table[tmp]; -} - -static inline uint8 GolombGetBit(int code_size){ - if(!bit_ctr[code_size]) bit_ctr[code_size]=GetCodeword(code_size); - bit_ctr[code_size]--; - if(bit_ctr[code_size]==0x80){ - bit_ctr[code_size]=0; - return 2; /* secret code for 'last zero'. ones are always last. */ - } - return (bit_ctr[code_size]==0)?1:0; -} - -static inline uint8 ProbGetBit(uint8 context){ - uint8 state=context_states[context]; - uint8 bit=GolombGetBit(evolution_table[state].code_size); - - if(bit&1){ - context_states[context]=evolution_table[state].LPS_next; - if(state<2){ - context_MPS[context]^=1; - return context_MPS[context]; /* just inverted, so just return it */ - } else{ - return context_MPS[context]^1; /* we know bit is 1, so use a constant */ - } - } else if(bit){ - context_states[context]=evolution_table[state].MPS_next; - /* zero here, zero there, no difference so drop through. */ - } - return context_MPS[context]; /* we know bit is 0, so don't bother xoring */ -} - -static inline uint8 GetBit(uint8 cur_bitplane){ - uint8 bit; - - bit=ProbGetBit(((cur_bitplane&1)<<4) - | ((prev_bits[cur_bitplane]&high_context_bits)>>5) - | (prev_bits[cur_bitplane]&low_context_bits)); - - prev_bits[cur_bitplane] <<= 1; - prev_bits[cur_bitplane] |= bit; - return bit; -} - -void SDD1_decompress(uint8 *out, uint8 *in, int len){ - uint8 bit, i, plane; - uint8 byte1, byte2; - - if(len==0) len=0x10000; - - bitplane_type=in[0]>>6; - - switch(in[0]&0x30){ - case 0x00: - high_context_bits=0x01c0; - low_context_bits =0x0001; - break; - case 0x10: - high_context_bits=0x0180; - low_context_bits =0x0001; - break; - case 0x20: - high_context_bits=0x00c0; - low_context_bits =0x0001; - break; - case 0x30: - high_context_bits=0x0180; - low_context_bits =0x0003; - break; - } - - in_stream=(in[0]<<11) | (in[1]<<3); - valid_bits=5; - in_buf=in+2; - memset(bit_ctr, 0, sizeof(bit_ctr)); - memset(context_states, 0, sizeof(context_states)); - memset(context_MPS, 0, sizeof(context_MPS)); - memset(prev_bits, 0, sizeof(prev_bits)); - - switch(bitplane_type){ - case 0: - while(1) { - for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ - if(GetBit(0)) byte1 |= bit; - if(GetBit(1)) byte2 |= bit; - } - *(out++)=byte1; - if(!--len) return; - *(out++)=byte2; - if(!--len) return; - } - break; - case 1: - i=plane=0; - while(1) { - for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ - if(GetBit(plane)) byte1 |= bit; - if(GetBit(plane+1)) byte2 |= bit; - } - *(out++)=byte1; - if(!--len) return; - *(out++)=byte2; - if(!--len) return; - if(!(i+=32)) plane = (plane+2)&7; - } - break; - case 2: - i=plane=0; - while(1) { - for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ - if(GetBit(plane)) byte1 |= bit; - if(GetBit(plane+1)) byte2 |= bit; - } - *(out++)=byte1; - if(!--len) return; - *(out++)=byte2; - if(!--len) return; - if(!(i+=32)) plane ^= 2; - } - break; - case 3: - do { - for(byte1=plane=0, bit=1; bit; bit<<=1, plane++){ - if(GetBit(plane)) byte1 |= bit; - } - *(out++)=byte1; - } while(--len); - break; - } -} - -static uint8 cur_plane; -static uint8 num_bits; -static uint8 next_byte; - -void SDD1_init(uint8 *in){ - bitplane_type=in[0]>>6; - - switch(in[0]&0x30){ - case 0x00: - high_context_bits=0x01c0; - low_context_bits =0x0001; - break; - case 0x10: - high_context_bits=0x0180; - low_context_bits =0x0001; - break; - case 0x20: - high_context_bits=0x00c0; - low_context_bits =0x0001; - break; - case 0x30: - high_context_bits=0x0180; - low_context_bits =0x0003; - break; - } - - in_stream=(in[0]<<11) | (in[1]<<3); - valid_bits=5; - in_buf=in+2; - memset(bit_ctr, 0, sizeof(bit_ctr)); - memset(context_states, 0, sizeof(context_states)); - memset(context_MPS, 0, sizeof(context_MPS)); - memset(prev_bits, 0, sizeof(prev_bits)); - - cur_plane=0; - num_bits=0; -} - -uint8 SDD1_get_byte(void){ - uint8 bit; - uint8 byte=0; - - switch(bitplane_type){ - case 0: - num_bits+=16; - if(num_bits&16){ - next_byte=0; - for(bit=0x80; bit; bit>>=1){ - if(GetBit(0)) byte |= bit; - if(GetBit(1)) next_byte |= bit; - } - return byte; - } else { - return next_byte; - } - - case 1: - num_bits+=16; - if(num_bits&16){ - next_byte=0; - for(bit=0x80; bit; bit>>=1){ - if(GetBit(cur_plane)) byte |= bit; - if(GetBit(cur_plane+1)) next_byte |= bit; - } - return byte; - } else { - if(!num_bits) cur_plane = (cur_plane+2)&7; - return next_byte; - } - - case 2: - num_bits+=16; - if(num_bits&16){ - next_byte=0; - for(bit=0x80; bit; bit>>=1){ - if(GetBit(cur_plane)) byte |= bit; - if(GetBit(cur_plane+1)) next_byte |= bit; - } - return byte; - } else { - if(!num_bits) cur_plane ^= 2; - return next_byte; - } - - case 3: - for(cur_plane=0, bit=1; bit; bit<<=1, cur_plane++){ - if(GetBit(cur_plane)) byte |= bit; - } - return byte; - - default: - /* should never happen */ - return 0; - } -} - diff --git a/source/seta.c b/source/seta.c new file mode 100644 index 0000000..4e7d208 --- /dev/null +++ b/source/seta.c @@ -0,0 +1,105 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include "seta.h" + +void (*SetSETA)(uint32, uint8)=&S9xSetST010; +uint8 (*GetSETA)(uint32)=&S9xGetST010; + +extern "C"{ +uint8 S9xGetSetaDSP(uint32 Address) +{ + return GetSETA(Address); +} + +void S9xSetSetaDSP(uint8 Byte, uint32 Address) +{ + SetSETA(Address, Byte); +} +} + diff --git a/source/seta.cpp b/source/seta.cpp deleted file mode 100644 index 4e7d208..0000000 --- a/source/seta.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include "seta.h" - -void (*SetSETA)(uint32, uint8)=&S9xSetST010; -uint8 (*GetSETA)(uint32)=&S9xGetST010; - -extern "C"{ -uint8 S9xGetSetaDSP(uint32 Address) -{ - return GetSETA(Address); -} - -void S9xSetSetaDSP(uint8 Byte, uint32 Address) -{ - SetSETA(Address, Byte); -} -} - diff --git a/source/seta010.c b/source/seta010.c new file mode 100644 index 0000000..13eab8a --- /dev/null +++ b/source/seta010.c @@ -0,0 +1,750 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include "seta.h" +#include "memmap.h" + +// Mode 7 scaling constants for all raster lines +const int16 ST010_M7Scale[176] = { + 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, + 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, + 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, + 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, + 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, + 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, + 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, + 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, + 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, + 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, + 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, + 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, + 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, + 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, + 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, + 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, + 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, + 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, + 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, + 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, + 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, + 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b +}; + +// H-DMA hack +bool seta_hack; + +//temporary Op04 requirement +#include + +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif + +ST010_Regs ST010; + +uint8 S9xGetST010(uint32 Address) +{ + if(!(Address&0x80000)) + return 0x80; + + if((Address&0xFFF)==0x20) + return ST010.op_reg; + if ((Address&0xFFF)==0x21) + return ST010.execute; + return Memory.SRAM[Address&Memory.SRAMMask]; +} + +const int16 ST010_SinTable[256] = { + 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, + 0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504, + 0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3, + 0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5, + 0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d, + 0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b, + 0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324, + 0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2, + -0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504, + -0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3, + -0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5, + -0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d, + -0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b, + -0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3, + -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}; + +const unsigned char ST010_ArcTan[32][32] = { + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + { 0x80, 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}}; + +short ST010_Sin(short Theta) +{ + return ST010_SinTable[(Theta >> 8) & 0xff]; +} + +short ST010_Cos(short Theta) +{ + return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]; +} + +void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) +{ + if ((x0 < 0) && (y0 < 0)) + { + x1 = -x0; + y1 = -y0; + Quadrant = -0x8000; + } + else if (x0 < 0) + { + x1 = y0; + y1 = -x0; + Quadrant = -0x4000; + } + else if (y0 < 0) + { + x1 = -y0; + y1 = x0; + Quadrant = 0x4000; + } + else + { + x1 = x0; + y1 = y0; + Quadrant = 0x0000; + } + + while ((x1 > 0x1f) || (y1 > 0x1f)) + { + if (x1 > 1) x1 >>= 1; + if (y1 > 1) y1 >>= 1; + } + + 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) +{ + X1 = X0 * Multiplier << 1; + Y1 = Y0 * Multiplier << 1; +} + +void ST010_Multiply(short Multiplicand, short Multiplier, int &Product) +{ + Product = Multiplicand * Multiplier << 1; +} + +void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1) +{ + X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); + Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); +} + +void SETA_Distance(short Y0, short X0, short &Distance) +{ + if (X0 < 0) X0 = -X0; + if (Y0 < 0) Y0 = -Y0; + Distance = ((X0 * 0x7af0) + 0x4000) >> 15; +} + +void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) +{ + bool Sorted; + uint16 Temp; + + if (Positions > 1) + do { + Sorted = true; + for (int i = 0; i < Positions - 1; i++) + if (Places[i] < Places[i + 1]) + { + Temp = Places[i + 1]; + Places[i + 1] = Places[i]; + Places[i] = Temp; + + Temp = Drivers[i + 1]; + Drivers[i + 1] = Drivers[i]; + Drivers[i] = Temp; + + Sorted = false; + } + Positions--; + } while (!Sorted); +} + +#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] + +void S9xSetST010(uint32 Address, uint8 Byte) +{ + if(!(Address&0x80000)) + { + 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; + + if(ST010.execute&0x80) + { + 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: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_SortDrivers(*(short*)&SRAM[0x0024], (uint16*) (SRAM + 0x0040), (uint16*) (SRAM + 0x0080)); +#else + uint16 Places[32]; + uint16 Positions = ST010_WORD(0x0024); + int Pos, Offset; + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + Places[Pos] = ST010_WORD(0x0040 + Offset); + Offset += 2; + } + + ST010_SortDrivers(Positions, Places, (uint16*) (SRAM + 0x0080)); + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); + SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); + Offset += 2; + } +#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: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_Scale(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]); +#else + int x1, y1; + + ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); + + Memory.SRAM[0x0010]=(uint8)(x1); + Memory.SRAM[0x0011]=(uint8)(x1 >> 8); + Memory.SRAM[0x0012]=(uint8)(x1 >> 16); + Memory.SRAM[0x0013]=(uint8)(x1 >> 24); + Memory.SRAM[0x0014]=(uint8)(y1); + Memory.SRAM[0x0015]=(uint8)(y1 >> 8); + Memory.SRAM[0x0016]=(uint8)(y1 >> 16); + Memory.SRAM[0x0017]=(uint8)(y1 >> 24); +#endif + break; + } + + // 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; + + 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 + 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: + { + 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); + + // 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); + + if (data) data = ~data; + + Memory.SRAM[0x03b0 + offset]=(uint8)(data); + Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8); + + offset += 2; + } + + // Shift Angle for use with Lookup table + Memory.SRAM[0x00] = Memory.SRAM[0x01]; + Memory.SRAM[0x01] = 0x00; + + 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: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_Rotate(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]); +#else + short x1, y1; + + ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); + + Memory.SRAM[0x0010]=(uint8)(x1); + Memory.SRAM[0x0011]=(uint8)(x1 >> 8); + Memory.SRAM[0x0012]=(uint8)(y1); + Memory.SRAM[0x0013]=(uint8)(y1 >> 8); +#endif + break; + } + + // 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; + + 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 + break; + } + + // calculate AI orientation based on specific guidelines + case 0x05: + { + int 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 = SRAM[0xC4]|(SRAM[0xC5]<<8)|(SRAM[0xC6]<<16)|(SRAM[0xC7]<<24); + int32 xpos = SRAM[0xC8]|(SRAM[0xC9]<<8)|(SRAM[0xCA]<<16)|(SRAM[0xCB]<<24); + uint16 rot = SRAM[0xCC]|(SRAM[0xCD]<<8); + + // physics + 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); + + // new target coordinates + 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); + + // quirk: clear and move in9 + SRAM[0xD2]=0xFF; + SRAM[0xD3]=0xFF; + SRAM[0xDA]=0; + SRAM[0xDB]=0; + + // grab the target angle + ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1); + + // check for wrapping + //if((o1<0x6000 && rot>0xA000) || + // (rot<0x6000 && o1>0xA000)) + //if(o10x8000) + { + o1+=0x8000; + rot+=0x8000; + wrap=true; + } + //o1=0x0000; + //rot=0xFF00; + + uint16 old_speed; + + old_speed = speed; + + // special case + if(abs(o1-rot)==0x8000) + { + speed = 0x100; + } + // slow down for sharp curves + else if(abs(o1-rot)>=0x1000) + { + uint32 slow = abs(o1-rot); + slow >>= 4; // scaling + speed -= slow; + } + // otherwise accelerate + else + { + speed += accel; + if(speed > speed_max) + { + // clip speed + speed = speed_max; + } + } + + // prevent negative/positive overflow + if(abs(old_speed-speed)>0x8000) { + if(old_speedrot && (o1-rot)>0x80) || + (o1=0x80) ) + { + if(o1rot) rot+=0x280; + } + + // turn off wrapping + 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; + + // 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)) ) + { + // announce our new destination and flag it + xpos_max = xpos_new&0x7FFF; + ypos_max = ypos_new; + flags |= 0x08; + } + + // update position + xpos -= (ST010_Cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; + ypos -= (ST010_Sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; + + // quirk: mask upper byte + xpos &= 0x1FFFFFFF; + ypos &= 0x1FFFFFFF; + + SRAM[0x00C0]=(uint8)(ypos_max); + SRAM[0x00C1]=(uint8)(ypos_max >> 8); + SRAM[0x00C2]=(uint8)(xpos_max); + SRAM[0x00C3]=(uint8)(xpos_max >> 8); + SRAM[0x00C4]=(uint8)(ypos); + SRAM[0x00C5]=(uint8)(ypos >> 8); + SRAM[0x00C6]=(uint8)(ypos >> 16); + SRAM[0x00C7]=(uint8)(ypos >> 24); + SRAM[0x00C8]=(uint8)(xpos); + SRAM[0x00C9]=(uint8)(xpos >> 8); + SRAM[0x00CA]=(uint8)(xpos >> 16); + SRAM[0x00CB]=(uint8)(xpos >> 24); + SRAM[0x00CC]=(uint8)(rot); + SRAM[0x00CD]=(uint8)(rot >> 8); + SRAM[0x00D4]=(uint8)(speed); + SRAM[0x00D5]=(uint8)(speed >> 8); + SRAM[0x00DC]=(uint8)(flags); + SRAM[0x00DD]=(uint8)(flags >> 8); + + break; + } + + default: + printf("Unknown Op\n"); + break; + } + + // lower signal: op processed + ST010.op_reg=0; + ST010.execute=0; + } +} + diff --git a/source/seta010.cpp b/source/seta010.cpp deleted file mode 100644 index 13eab8a..0000000 --- a/source/seta010.cpp +++ /dev/null @@ -1,750 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include "seta.h" -#include "memmap.h" - -// Mode 7 scaling constants for all raster lines -const int16 ST010_M7Scale[176] = { - 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, - 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, - 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, - 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, - 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, - 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, - 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, - 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, - 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, - 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, - 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, - 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, - 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, - 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, - 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, - 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, - 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, - 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, - 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, - 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, - 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, - 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b -}; - -// H-DMA hack -bool seta_hack; - -//temporary Op04 requirement -#include - -#ifndef PI -#define PI 3.1415926535897932384626433832795 -#endif - -ST010_Regs ST010; - -uint8 S9xGetST010(uint32 Address) -{ - if(!(Address&0x80000)) - return 0x80; - - if((Address&0xFFF)==0x20) - return ST010.op_reg; - if ((Address&0xFFF)==0x21) - return ST010.execute; - return Memory.SRAM[Address&Memory.SRAMMask]; -} - -const int16 ST010_SinTable[256] = { - 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, - 0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, - 0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, - 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, - 0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6, - 0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504, - 0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3, - 0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5, - 0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d, - 0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b, - 0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23, - 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3, - 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, - 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df, - 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b, - 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324, - 0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2, - -0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, - -0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a, - -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, - -0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6, - -0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504, - -0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3, - -0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5, - -0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d, - -0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b, - -0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23, - -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3, - -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}; - -const unsigned char ST010_ArcTan[32][32] = { - { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, - { 0x80, 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}, - { 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}}; - -short ST010_Sin(short Theta) -{ - return ST010_SinTable[(Theta >> 8) & 0xff]; -} - -short ST010_Cos(short Theta) -{ - return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]; -} - -void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) -{ - if ((x0 < 0) && (y0 < 0)) - { - x1 = -x0; - y1 = -y0; - Quadrant = -0x8000; - } - else if (x0 < 0) - { - x1 = y0; - y1 = -x0; - Quadrant = -0x4000; - } - else if (y0 < 0) - { - x1 = -y0; - y1 = x0; - Quadrant = 0x4000; - } - else - { - x1 = x0; - y1 = y0; - Quadrant = 0x0000; - } - - while ((x1 > 0x1f) || (y1 > 0x1f)) - { - if (x1 > 1) x1 >>= 1; - if (y1 > 1) y1 >>= 1; - } - - 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) -{ - X1 = X0 * Multiplier << 1; - Y1 = Y0 * Multiplier << 1; -} - -void ST010_Multiply(short Multiplicand, short Multiplier, int &Product) -{ - Product = Multiplicand * Multiplier << 1; -} - -void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1) -{ - X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); - Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); -} - -void SETA_Distance(short Y0, short X0, short &Distance) -{ - if (X0 < 0) X0 = -X0; - if (Y0 < 0) Y0 = -Y0; - Distance = ((X0 * 0x7af0) + 0x4000) >> 15; -} - -void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) -{ - bool Sorted; - uint16 Temp; - - if (Positions > 1) - do { - Sorted = true; - for (int i = 0; i < Positions - 1; i++) - if (Places[i] < Places[i + 1]) - { - Temp = Places[i + 1]; - Places[i + 1] = Places[i]; - Places[i] = Temp; - - Temp = Drivers[i + 1]; - Drivers[i + 1] = Drivers[i]; - Drivers[i] = Temp; - - Sorted = false; - } - Positions--; - } while (!Sorted); -} - -#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] - -void S9xSetST010(uint32 Address, uint8 Byte) -{ - if(!(Address&0x80000)) - { - 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; - - if(ST010.execute&0x80) - { - 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: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_SortDrivers(*(short*)&SRAM[0x0024], (uint16*) (SRAM + 0x0040), (uint16*) (SRAM + 0x0080)); -#else - uint16 Places[32]; - uint16 Positions = ST010_WORD(0x0024); - int Pos, Offset; - - Offset = 0; - - for (Pos = 0; Pos < Positions; Pos++) - { - Places[Pos] = ST010_WORD(0x0040 + Offset); - Offset += 2; - } - - ST010_SortDrivers(Positions, Places, (uint16*) (SRAM + 0x0080)); - - Offset = 0; - - for (Pos = 0; Pos < Positions; Pos++) - { - SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); - SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); - Offset += 2; - } -#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: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_Scale(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]); -#else - int x1, y1; - - ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); - - Memory.SRAM[0x0010]=(uint8)(x1); - Memory.SRAM[0x0011]=(uint8)(x1 >> 8); - Memory.SRAM[0x0012]=(uint8)(x1 >> 16); - Memory.SRAM[0x0013]=(uint8)(x1 >> 24); - Memory.SRAM[0x0014]=(uint8)(y1); - Memory.SRAM[0x0015]=(uint8)(y1 >> 8); - Memory.SRAM[0x0016]=(uint8)(y1 >> 16); - Memory.SRAM[0x0017]=(uint8)(y1 >> 24); -#endif - break; - } - - // 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; - - 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 - 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: - { - 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); - - // 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); - - if (data) data = ~data; - - Memory.SRAM[0x03b0 + offset]=(uint8)(data); - Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8); - - offset += 2; - } - - // Shift Angle for use with Lookup table - Memory.SRAM[0x00] = Memory.SRAM[0x01]; - Memory.SRAM[0x01] = 0x00; - - 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: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_Rotate(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]); -#else - short x1, y1; - - ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); - - Memory.SRAM[0x0010]=(uint8)(x1); - Memory.SRAM[0x0011]=(uint8)(x1 >> 8); - Memory.SRAM[0x0012]=(uint8)(y1); - Memory.SRAM[0x0013]=(uint8)(y1 >> 8); -#endif - break; - } - - // 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; - - 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 - break; - } - - // calculate AI orientation based on specific guidelines - case 0x05: - { - int 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 = SRAM[0xC4]|(SRAM[0xC5]<<8)|(SRAM[0xC6]<<16)|(SRAM[0xC7]<<24); - int32 xpos = SRAM[0xC8]|(SRAM[0xC9]<<8)|(SRAM[0xCA]<<16)|(SRAM[0xCB]<<24); - uint16 rot = SRAM[0xCC]|(SRAM[0xCD]<<8); - - // physics - 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); - - // new target coordinates - 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); - - // quirk: clear and move in9 - SRAM[0xD2]=0xFF; - SRAM[0xD3]=0xFF; - SRAM[0xDA]=0; - SRAM[0xDB]=0; - - // grab the target angle - ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1); - - // check for wrapping - //if((o1<0x6000 && rot>0xA000) || - // (rot<0x6000 && o1>0xA000)) - //if(o10x8000) - { - o1+=0x8000; - rot+=0x8000; - wrap=true; - } - //o1=0x0000; - //rot=0xFF00; - - uint16 old_speed; - - old_speed = speed; - - // special case - if(abs(o1-rot)==0x8000) - { - speed = 0x100; - } - // slow down for sharp curves - else if(abs(o1-rot)>=0x1000) - { - uint32 slow = abs(o1-rot); - slow >>= 4; // scaling - speed -= slow; - } - // otherwise accelerate - else - { - speed += accel; - if(speed > speed_max) - { - // clip speed - speed = speed_max; - } - } - - // prevent negative/positive overflow - if(abs(old_speed-speed)>0x8000) { - if(old_speedrot && (o1-rot)>0x80) || - (o1=0x80) ) - { - if(o1rot) rot+=0x280; - } - - // turn off wrapping - 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; - - // 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)) ) - { - // announce our new destination and flag it - xpos_max = xpos_new&0x7FFF; - ypos_max = ypos_new; - flags |= 0x08; - } - - // update position - xpos -= (ST010_Cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; - ypos -= (ST010_Sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; - - // quirk: mask upper byte - xpos &= 0x1FFFFFFF; - ypos &= 0x1FFFFFFF; - - SRAM[0x00C0]=(uint8)(ypos_max); - SRAM[0x00C1]=(uint8)(ypos_max >> 8); - SRAM[0x00C2]=(uint8)(xpos_max); - SRAM[0x00C3]=(uint8)(xpos_max >> 8); - SRAM[0x00C4]=(uint8)(ypos); - SRAM[0x00C5]=(uint8)(ypos >> 8); - SRAM[0x00C6]=(uint8)(ypos >> 16); - SRAM[0x00C7]=(uint8)(ypos >> 24); - SRAM[0x00C8]=(uint8)(xpos); - SRAM[0x00C9]=(uint8)(xpos >> 8); - SRAM[0x00CA]=(uint8)(xpos >> 16); - SRAM[0x00CB]=(uint8)(xpos >> 24); - SRAM[0x00CC]=(uint8)(rot); - SRAM[0x00CD]=(uint8)(rot >> 8); - SRAM[0x00D4]=(uint8)(speed); - SRAM[0x00D5]=(uint8)(speed >> 8); - SRAM[0x00DC]=(uint8)(flags); - SRAM[0x00DD]=(uint8)(flags >> 8); - - break; - } - - default: - printf("Unknown Op\n"); - break; - } - - // lower signal: op processed - ST010.op_reg=0; - ST010.execute=0; - } -} - diff --git a/source/seta011.c b/source/seta011.c new file mode 100644 index 0000000..b8fd213 --- /dev/null +++ b/source/seta011.c @@ -0,0 +1,232 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#include "seta.h" +#include "memmap.h" + +ST011_Regs ST011; + +// shougi playboard +uint8 board[9][9]; + +// debug +static int line = 0; + +uint8 S9xGetST011(uint32 Address) +{ + uint8 t; + uint16 address = (uint16) Address & 0xFFFF; + + // line counter + line++; + + // status check + if (address == 0x01) + { + t = 0xFF; + } + // read directly from s-ram + else + { + t = Memory.SRAM[address]; + } + + // debug +// if(address<0x150) +// printf( "ST011 R: %06X %02X\n", Address, t); + + return t; +} + +void S9xSetST011(uint32 Address, uint8 Byte) +{ + uint16 address = (uint16) Address & 0xFFFF; + static bool reset = false; + + // debug + line++; + + if(!reset) + { + // bootup values + ST011.waiting4command = true; + reset = true; + } + + // debug +// if(address<0x150) +// printf( "ST011 W: %06X %02X\n", Address, Byte ); + + Memory.SRAM[address]=Byte; + + // op commands/data goes through this address + 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) + { + 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.in_index++; + } + } + + if (ST011.in_count==ST011.in_index) + { + // Actually execute the command + ST011.waiting4command = true; + ST011.out_index = 0; + switch (ST011.command) + { + // 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; + + // unknown + case 0x02: break; + + // unknown + case 0x04: + { + // outputs + Memory.SRAM[0x12C] = 0x00; + //Memory.SRAM[0x12D] = 0x00; + Memory.SRAM[0x12E] = 0x00; + } + break; + + // unknown + case 0x05: + { + // outputs + Memory.SRAM[0x12C] = 0x00; + //Memory.SRAM[0x12D] = 0x00; + Memory.SRAM[0x12E] = 0x00; + } + break; + + // unknown + case 0x06: break; + case 0x07: break; + + // unknown + case 0x0E: + { + // outputs + Memory.SRAM[0x12C] = 0x00; + Memory.SRAM[0x12D] = 0x00; + } + break; + } + } +} + diff --git a/source/seta011.cpp b/source/seta011.cpp deleted file mode 100644 index b8fd213..0000000 --- a/source/seta011.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#include "seta.h" -#include "memmap.h" - -ST011_Regs ST011; - -// shougi playboard -uint8 board[9][9]; - -// debug -static int line = 0; - -uint8 S9xGetST011(uint32 Address) -{ - uint8 t; - uint16 address = (uint16) Address & 0xFFFF; - - // line counter - line++; - - // status check - if (address == 0x01) - { - t = 0xFF; - } - // read directly from s-ram - else - { - t = Memory.SRAM[address]; - } - - // debug -// if(address<0x150) -// printf( "ST011 R: %06X %02X\n", Address, t); - - return t; -} - -void S9xSetST011(uint32 Address, uint8 Byte) -{ - uint16 address = (uint16) Address & 0xFFFF; - static bool reset = false; - - // debug - line++; - - if(!reset) - { - // bootup values - ST011.waiting4command = true; - reset = true; - } - - // debug -// if(address<0x150) -// printf( "ST011 W: %06X %02X\n", Address, Byte ); - - Memory.SRAM[address]=Byte; - - // op commands/data goes through this address - 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) - { - 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.in_index++; - } - } - - if (ST011.in_count==ST011.in_index) - { - // Actually execute the command - ST011.waiting4command = true; - ST011.out_index = 0; - switch (ST011.command) - { - // 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; - - // unknown - case 0x02: break; - - // unknown - case 0x04: - { - // outputs - Memory.SRAM[0x12C] = 0x00; - //Memory.SRAM[0x12D] = 0x00; - Memory.SRAM[0x12E] = 0x00; - } - break; - - // unknown - case 0x05: - { - // outputs - Memory.SRAM[0x12C] = 0x00; - //Memory.SRAM[0x12D] = 0x00; - Memory.SRAM[0x12E] = 0x00; - } - break; - - // unknown - case 0x06: break; - case 0x07: break; - - // unknown - case 0x0E: - { - // outputs - Memory.SRAM[0x12C] = 0x00; - Memory.SRAM[0x12D] = 0x00; - } - break; - } - } -} - diff --git a/source/seta018.c b/source/seta018.c new file mode 100644 index 0000000..cafca06 --- /dev/null +++ b/source/seta018.c @@ -0,0 +1,254 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include "seta.h" +#include "memmap.h" + +ST018_Regs ST018; + +static int line; // line counter + +extern "C"{ +uint8 S9xGetST018(uint32 Address) +{ + uint8 t = 0; // Initialise to some value for the compiler + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + // these roles may be flipped + // op output + if (address == 0x3804) + { + if (ST018.out_count) + { + t = (uint8) ST018.output [ST018.out_index]; + ST018.out_index++; + if (ST018.out_count==ST018.out_index) + ST018.out_count=0; + } + else + t = 0x81; + } + // status register + else if (address == 0x3800) + t = ST018.status; + + printf( "ST018 R: %06X %02X\n", Address, t); + + return t; +} + +void S9xSetST018(uint8 Byte, uint32 Address) +{ + uint16 address = (uint16) Address&0xFFFF; + static bool reset = false; + + printf( "ST018 W: %06X %02X\n", Address, Byte ); + + line++; + + if (!reset) + { + // bootup values + ST018.waiting4command = true; + ST018.part_command = 0; + reset = true; + } + + Memory.SRAM[address]=Byte; + + // default status for now + ST018.status = 0x00; + + // op data goes through this address + if (address==0x3804) + { + // check for new commands: 3 bytes length + if(ST018.waiting4command && ST018.part_command==2) + { + ST018.waiting4command = false; + 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) + { + case 0x0100: ST018.in_count = 0; break; + case 0xFF00: ST018.in_count = 0; break; + default: ST018.waiting4command = true; break; + } + } + else if(ST018.waiting4command) + { + // 3-byte commands + ST018.part_command++; + ST018.command <<= 8; + ST018.command |= Byte; + } + } + // extra parameters + else if (address==0x3802) + { + ST018.parameters[ST018.in_index] = Byte; + ST018.in_index++; + } + + if (ST018.in_count==ST018.in_index) + { + // Actually execute the command + ST018.waiting4command = true; + 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; + + // 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; + + // 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; + + // 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/seta018.cpp b/source/seta018.cpp deleted file mode 100644 index cafca06..0000000 --- a/source/seta018.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include "seta.h" -#include "memmap.h" - -ST018_Regs ST018; - -static int line; // line counter - -extern "C"{ -uint8 S9xGetST018(uint32 Address) -{ - uint8 t = 0; // Initialise to some value for the compiler - uint16 address = (uint16) Address & 0xFFFF; - - line++; - - // these roles may be flipped - // op output - if (address == 0x3804) - { - if (ST018.out_count) - { - t = (uint8) ST018.output [ST018.out_index]; - ST018.out_index++; - if (ST018.out_count==ST018.out_index) - ST018.out_count=0; - } - else - t = 0x81; - } - // status register - else if (address == 0x3800) - t = ST018.status; - - printf( "ST018 R: %06X %02X\n", Address, t); - - return t; -} - -void S9xSetST018(uint8 Byte, uint32 Address) -{ - uint16 address = (uint16) Address&0xFFFF; - static bool reset = false; - - printf( "ST018 W: %06X %02X\n", Address, Byte ); - - line++; - - if (!reset) - { - // bootup values - ST018.waiting4command = true; - ST018.part_command = 0; - reset = true; - } - - Memory.SRAM[address]=Byte; - - // default status for now - ST018.status = 0x00; - - // op data goes through this address - if (address==0x3804) - { - // check for new commands: 3 bytes length - if(ST018.waiting4command && ST018.part_command==2) - { - ST018.waiting4command = false; - 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) - { - case 0x0100: ST018.in_count = 0; break; - case 0xFF00: ST018.in_count = 0; break; - default: ST018.waiting4command = true; break; - } - } - else if(ST018.waiting4command) - { - // 3-byte commands - ST018.part_command++; - ST018.command <<= 8; - ST018.command |= Byte; - } - } - // extra parameters - else if (address==0x3802) - { - ST018.parameters[ST018.in_index] = Byte; - ST018.in_index++; - } - - if (ST018.in_count==ST018.in_index) - { - // Actually execute the command - ST018.waiting4command = true; - 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; - - // 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; - - // 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; - - // 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/snaporig.c b/source/snaporig.c new file mode 100644 index 0000000..69ff33e --- /dev/null +++ b/source/snaporig.c @@ -0,0 +1,469 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include + +#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) +#include +#include +#include +#endif + +#include "snapshot.h" +#include "snaporig.h" +#include "memmap.h" +#include "snes9x.h" +#include "65c816.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "apu.h" +#include "soundux.h" + +struct SOrigPPU OrigPPU; +struct SOrigDMA OrigDMA [8]; +struct SOrigRegisters OrigRegisters; +struct SOrigCPUState OrigCPU; +struct SOrigAPU OrigAPU; +SOrigSoundData OrigSoundData; +struct SOrigAPURegisters OrigAPURegisters; +char ROMFilename [1025]; + +static int ReadOrigSnapshot (STREAM); + +bool8 S9xLoadOrigSnapshot (const char *filename) +{ + FILE* fp; + + fp = fopen(filename, "r"); + if(NULL == fp) + return (FALSE); + + int result; + if ((result = ReadOrigSnapshot (fp)) != SUCCESS) + { + fclose(fp); + return (FALSE); + } + + fclose(fp); + return (TRUE); +} + +static int ReadBlock (const char *key, void *block, int max_len, STREAM snap) +{ + char buffer [20]; + int len = 0; + int rem = 0; + + if (READ_STREAM (buffer, 11, snap) != 11 || + strncmp (buffer, key, 4) != 0 || + (len = atoi (&buffer [4])) == 0) + return (WRONG_FORMAT); + + if (len > max_len) + { + rem = len - max_len; + len = max_len; + } + if (READ_STREAM (block, len, snap) != len) + return (WRONG_FORMAT); + + if (rem) + { + char *junk = new char [rem]; + READ_STREAM (junk, rem, snap); + delete[] junk; + } + + return (SUCCESS); +} + +static int ReadOrigSnapshot (STREAM snap) +{ + char buffer [_MAX_PATH]; + char rom_filename [_MAX_PATH]; + int result; + int i; + int j; + + int version; + int len = strlen (ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (READ_STREAM (buffer, len, snap) != len) + return (WRONG_FORMAT); + if (strncmp (buffer, ORIG_SNAPSHOT_MAGIC, strlen (ORIG_SNAPSHOT_MAGIC)) != 0) + return (WRONG_FORMAT); + if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION) + return (WRONG_VERSION); + + if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS) + return (result); + + if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS) + return (result); + + 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."); + } + + S9xReset (); + S9xSetSoundMute (TRUE); + if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS) + return (result); + OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; + Memory.FixROMSpeed (); + if (version == 3) + { + OrigCPU.Cycles = OrigCPU.Cycles_old; + OrigCPU.NextEvent = OrigCPU.NextEvent_old; + OrigCPU.V_Counter = OrigCPU.V_Counter_old; + OrigCPU.MemSpeed = OrigCPU.MemSpeed_old; + OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old; + OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; + } + CPU.Flags = OrigCPU.Flags; + CPU.BranchSkip = OrigCPU.BranchSkip; + CPU.NMIActive = OrigCPU.NMIActive; + CPU.IRQActive = OrigCPU.IRQActive; + CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt; + CPU.WhichEvent = OrigCPU.WhichEvent; + CPU.Cycles = OrigCPU.Cycles; + CPU.NextEvent = OrigCPU.NextEvent; + CPU.V_Counter = OrigCPU.V_Counter; + CPU.MemSpeed = OrigCPU.MemSpeed; + CPU.MemSpeedx2 = OrigCPU.MemSpeedx2; + CPU.FastROMSpeed = OrigCPU.FastROMSpeed; + + if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS) + return (result); + + ICPU.Registers = *(struct SRegisters *) &OrigRegisters; + + if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS) + return (result); + + if (version == 2) + { + OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13; + OrigPPU.OBJNameBase <<= 1; + OrigPPU.OBJNameSelect <<= 13; + } + PPU.BGMode = OrigPPU.BGMode; + PPU.BG3Priority = OrigPPU.BG3Priority; + PPU.Brightness = OrigPPU.Brightness; + + PPU.VMA.High = OrigPPU.VMA.High; + PPU.VMA.Increment = OrigPPU.VMA.Increment; + PPU.VMA.Address = OrigPPU.VMA.Address; + PPU.VMA.Mask1 = OrigPPU.VMA.Mask1; + PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount; + PPU.VMA.Shift = OrigPPU.VMA.Shift; + + for (i = 0; i < 4; i++) + { + PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase; + PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset; + PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset; + PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize; + PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase; + PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize; + } + + PPU.CGFLIP = OrigPPU.CGFLIP; + for (i = 0; i < 256; i++) + PPU.CGDATA [i] = OrigPPU.CGDATA [i]; + PPU.FirstSprite = OrigPPU.FirstSprite; + for (i = 0; i < 128; i++) + { + PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos; + PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos; + PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name; + PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip; + PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip; + PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority; + PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette; + PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size; + } + PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation; + PPU.OAMAddr = OrigPPU.OAMAddr; + + PPU.OAMFlip = OrigPPU.OAMFlip; + PPU.OAMTileAddress = OrigPPU.OAMTileAddress; + PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos; + PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos; + PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched; + PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched; + + PPU.HBeamFlip = OrigPPU.HBeamFlip; + PPU.VBeamFlip = OrigPPU.VBeamFlip; + PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched; + + PPU.MatrixA = OrigPPU.MatrixA; + PPU.MatrixB = OrigPPU.MatrixB; + PPU.MatrixC = OrigPPU.MatrixC; + PPU.MatrixD = OrigPPU.MatrixD; + PPU.CentreX = OrigPPU.CentreX; + PPU.CentreY = OrigPPU.CentreY; + PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos; + PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos; + PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos; + + PPU.CGADD = OrigPPU.CGADD; + PPU.FixedColourRed = OrigPPU.FixedColourRed; + PPU.FixedColourGreen = OrigPPU.FixedColourGreen; + PPU.FixedColourBlue = OrigPPU.FixedColourBlue; + PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr; + PPU.ScreenHeight = OrigPPU.ScreenHeight; + PPU.WRAM = OrigPPU.WRAM; + PPU.ForcedBlanking = OrigPPU.ForcedBlanking; + PPU.OBJNameSelect = OrigPPU.OBJNameSelect; + PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect; + PPU.OBJNameBase = OrigPPU.OBJNameBase; + PPU.OAMReadFlip = OrigPPU.OAMReadFlip; + // memmove converted: Different data segments [Neb] + memcpy (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData)); + PPU.VTimerEnabled = OrigPPU.VTimerEnabled; + PPU.HTimerEnabled = OrigPPU.HTimerEnabled; + PPU.HTimerPosition = OrigPPU.HTimerPosition; + PPU.Mosaic = OrigPPU.Mosaic; + // memmove converted: Different data segments [Neb] + memcpy (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic)); + PPU.Mode7HFlip = OrigPPU.Mode7HFlip; + PPU.Mode7VFlip = OrigPPU.Mode7VFlip; + PPU.Mode7Repeat = OrigPPU.Mode7Repeat; + PPU.Window1Left = OrigPPU.Window1Left; + PPU.Window1Right = OrigPPU.Window1Right; + PPU.Window2Left = OrigPPU.Window2Left; + PPU.Window2Right = OrigPPU.Window2Right; + for (i = 0; i < 6; i++) + { + PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i]; + PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i]; + PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i]; + PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i]; + PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i]; + } + PPU.CGFLIPRead = OrigPPU.CGFLIPRead; + PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply; + + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + S9xFixColourBrightness (); + IPPU.RenderThisFrame = FALSE; + + if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS) + return (result); + + for (i = 0; i < 8; i++) + { + DMA[i].TransferDirection = OrigDMA[i].TransferDirection; + DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed; + DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement; + DMA[i].TransferMode = OrigDMA[i].TransferMode; + DMA[i].ABank = OrigDMA[i].ABank; + DMA[i].AAddress = OrigDMA[i].AAddress; + DMA[i].Address = OrigDMA[i].Address; + DMA[i].BAddress = OrigDMA[i].BAddress; + DMA[i].TransferBytes = OrigDMA[i].TransferBytes; + DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing; + DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress; + DMA[i].IndirectBank = OrigDMA[i].IndirectBank; + DMA[i].Repeat = OrigDMA[i].Repeat; + DMA[i].LineCount = OrigDMA[i].LineCount; + DMA[i].FirstLine = OrigDMA[i].FirstLine; + } + + if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("SRA:", ::SRAM, 0x10000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS) + return (result); + if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS) + { + APU = *(struct SAPU *) &OrigAPU; + + if ((result = ReadBlock ("ARE:", &OrigAPURegisters, + sizeof (OrigAPURegisters), snap)) != SUCCESS) + return (result); + IAPU.Registers = *(struct SAPURegisters *) &OrigAPURegisters; + if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("SOU:", &OrigSoundData, + sizeof (SOrigSoundData), snap)) != SUCCESS) + return (result); + + + SoundData.master_volume [0] = OrigSoundData.master_volume_left; + SoundData.master_volume [1] = OrigSoundData.master_volume_right; + SoundData.echo_volume [0] = OrigSoundData.echo_volume_left; + SoundData.echo_volume [1] = OrigSoundData.echo_volume_right; + + SoundData.echo_enable = OrigSoundData.echo_enable; + SoundData.echo_feedback = OrigSoundData.echo_feedback; + SoundData.echo_ptr = OrigSoundData.echo_ptr; + SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size; + SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled; + SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable; + SoundData.pitch_mod = OrigSoundData.pitch_mod; + + for (i = 0; i < 3; i++) + SoundData.dummy [i] = OrigSoundData.dummy [i]; + for (i = 0; i < NUM_CHANNELS; i++) + { + SoundData.channels [i].state = OrigSoundData.channels [i].state; + SoundData.channels [i].type = OrigSoundData.channels [i].type; + SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left; + SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right; + SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency; + SoundData.channels [i].count = OrigSoundData.channels [i].count; + SoundData.channels [i].loop = OrigSoundData.channels [i].loop; + SoundData.channels [i].envx = OrigSoundData.channels [i].envx; + SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level; + SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level; + SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target; + SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error; + SoundData.channels [i].erate = OrigSoundData.channels [i].erate; + SoundData.channels [i].direction = OrigSoundData.channels [i].direction; + SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate; + SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate; + SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate; + SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate; + SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level; + SoundData.channels [i].sample = OrigSoundData.channels [i].sample; + for (j = 0; j < 16; j++) + SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j]; + + for (j = 0; j < 2; j++) + SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j]; + + SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number; + SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block; + SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode; + SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer; + SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer; + SoundData.channels [i].mode = OrigSoundData.channels [i].mode; + } + + S9xSetSoundMute (FALSE); + IAPU.PC = IAPU.RAM + IAPU.Registers.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); + } + S9xFixSoundAfterSnapshotLoad (); + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); + S9xUnpackStatus (); + S9xFixCycles (); + S9xReschedule (); + + return (SUCCESS); +} + diff --git a/source/snaporig.cpp b/source/snaporig.cpp deleted file mode 100644 index 69ff33e..0000000 --- a/source/snaporig.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#ifdef HAVE_STRINGS_H -#include -#endif -#include -#include - -#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) -#include -#include -#include -#endif - -#include "snapshot.h" -#include "snaporig.h" -#include "memmap.h" -#include "snes9x.h" -#include "65c816.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "apu.h" -#include "soundux.h" - -struct SOrigPPU OrigPPU; -struct SOrigDMA OrigDMA [8]; -struct SOrigRegisters OrigRegisters; -struct SOrigCPUState OrigCPU; -struct SOrigAPU OrigAPU; -SOrigSoundData OrigSoundData; -struct SOrigAPURegisters OrigAPURegisters; -char ROMFilename [1025]; - -static int ReadOrigSnapshot (STREAM); - -bool8 S9xLoadOrigSnapshot (const char *filename) -{ - FILE* fp; - - fp = fopen(filename, "r"); - if(NULL == fp) - return (FALSE); - - int result; - if ((result = ReadOrigSnapshot (fp)) != SUCCESS) - { - fclose(fp); - return (FALSE); - } - - fclose(fp); - return (TRUE); -} - -static int ReadBlock (const char *key, void *block, int max_len, STREAM snap) -{ - char buffer [20]; - int len = 0; - int rem = 0; - - if (READ_STREAM (buffer, 11, snap) != 11 || - strncmp (buffer, key, 4) != 0 || - (len = atoi (&buffer [4])) == 0) - return (WRONG_FORMAT); - - if (len > max_len) - { - rem = len - max_len; - len = max_len; - } - if (READ_STREAM (block, len, snap) != len) - return (WRONG_FORMAT); - - if (rem) - { - char *junk = new char [rem]; - READ_STREAM (junk, rem, snap); - delete[] junk; - } - - return (SUCCESS); -} - -static int ReadOrigSnapshot (STREAM snap) -{ - char buffer [_MAX_PATH]; - char rom_filename [_MAX_PATH]; - int result; - int i; - int j; - - int version; - int len = strlen (ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1; - if (READ_STREAM (buffer, len, snap) != len) - return (WRONG_FORMAT); - if (strncmp (buffer, ORIG_SNAPSHOT_MAGIC, strlen (ORIG_SNAPSHOT_MAGIC)) != 0) - return (WRONG_FORMAT); - if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION) - return (WRONG_VERSION); - - if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS) - return (result); - - if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS) - return (result); - - 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."); - } - - S9xReset (); - S9xSetSoundMute (TRUE); - if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS) - return (result); - OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; - Memory.FixROMSpeed (); - if (version == 3) - { - OrigCPU.Cycles = OrigCPU.Cycles_old; - OrigCPU.NextEvent = OrigCPU.NextEvent_old; - OrigCPU.V_Counter = OrigCPU.V_Counter_old; - OrigCPU.MemSpeed = OrigCPU.MemSpeed_old; - OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old; - OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; - } - CPU.Flags = OrigCPU.Flags; - CPU.BranchSkip = OrigCPU.BranchSkip; - CPU.NMIActive = OrigCPU.NMIActive; - CPU.IRQActive = OrigCPU.IRQActive; - CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt; - CPU.WhichEvent = OrigCPU.WhichEvent; - CPU.Cycles = OrigCPU.Cycles; - CPU.NextEvent = OrigCPU.NextEvent; - CPU.V_Counter = OrigCPU.V_Counter; - CPU.MemSpeed = OrigCPU.MemSpeed; - CPU.MemSpeedx2 = OrigCPU.MemSpeedx2; - CPU.FastROMSpeed = OrigCPU.FastROMSpeed; - - if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS) - return (result); - - ICPU.Registers = *(struct SRegisters *) &OrigRegisters; - - if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS) - return (result); - - if (version == 2) - { - OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13; - OrigPPU.OBJNameBase <<= 1; - OrigPPU.OBJNameSelect <<= 13; - } - PPU.BGMode = OrigPPU.BGMode; - PPU.BG3Priority = OrigPPU.BG3Priority; - PPU.Brightness = OrigPPU.Brightness; - - PPU.VMA.High = OrigPPU.VMA.High; - PPU.VMA.Increment = OrigPPU.VMA.Increment; - PPU.VMA.Address = OrigPPU.VMA.Address; - PPU.VMA.Mask1 = OrigPPU.VMA.Mask1; - PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount; - PPU.VMA.Shift = OrigPPU.VMA.Shift; - - for (i = 0; i < 4; i++) - { - PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase; - PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset; - PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset; - PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize; - PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase; - PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize; - } - - PPU.CGFLIP = OrigPPU.CGFLIP; - for (i = 0; i < 256; i++) - PPU.CGDATA [i] = OrigPPU.CGDATA [i]; - PPU.FirstSprite = OrigPPU.FirstSprite; - for (i = 0; i < 128; i++) - { - PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos; - PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos; - PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name; - PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip; - PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip; - PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority; - PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette; - PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size; - } - PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation; - PPU.OAMAddr = OrigPPU.OAMAddr; - - PPU.OAMFlip = OrigPPU.OAMFlip; - PPU.OAMTileAddress = OrigPPU.OAMTileAddress; - PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos; - PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos; - PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched; - PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched; - - PPU.HBeamFlip = OrigPPU.HBeamFlip; - PPU.VBeamFlip = OrigPPU.VBeamFlip; - PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched; - - PPU.MatrixA = OrigPPU.MatrixA; - PPU.MatrixB = OrigPPU.MatrixB; - PPU.MatrixC = OrigPPU.MatrixC; - PPU.MatrixD = OrigPPU.MatrixD; - PPU.CentreX = OrigPPU.CentreX; - PPU.CentreY = OrigPPU.CentreY; - PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos; - PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos; - PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos; - - PPU.CGADD = OrigPPU.CGADD; - PPU.FixedColourRed = OrigPPU.FixedColourRed; - PPU.FixedColourGreen = OrigPPU.FixedColourGreen; - PPU.FixedColourBlue = OrigPPU.FixedColourBlue; - PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr; - PPU.ScreenHeight = OrigPPU.ScreenHeight; - PPU.WRAM = OrigPPU.WRAM; - PPU.ForcedBlanking = OrigPPU.ForcedBlanking; - PPU.OBJNameSelect = OrigPPU.OBJNameSelect; - PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect; - PPU.OBJNameBase = OrigPPU.OBJNameBase; - PPU.OAMReadFlip = OrigPPU.OAMReadFlip; - // memmove converted: Different data segments [Neb] - memcpy (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData)); - PPU.VTimerEnabled = OrigPPU.VTimerEnabled; - PPU.HTimerEnabled = OrigPPU.HTimerEnabled; - PPU.HTimerPosition = OrigPPU.HTimerPosition; - PPU.Mosaic = OrigPPU.Mosaic; - // memmove converted: Different data segments [Neb] - memcpy (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic)); - PPU.Mode7HFlip = OrigPPU.Mode7HFlip; - PPU.Mode7VFlip = OrigPPU.Mode7VFlip; - PPU.Mode7Repeat = OrigPPU.Mode7Repeat; - PPU.Window1Left = OrigPPU.Window1Left; - PPU.Window1Right = OrigPPU.Window1Right; - PPU.Window2Left = OrigPPU.Window2Left; - PPU.Window2Right = OrigPPU.Window2Right; - for (i = 0; i < 6; i++) - { - PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i]; - PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i]; - PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i]; - PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i]; - PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i]; - } - PPU.CGFLIPRead = OrigPPU.CGFLIPRead; - PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply; - - IPPU.ColorsChanged = TRUE; - IPPU.OBJChanged = TRUE; - S9xFixColourBrightness (); - IPPU.RenderThisFrame = FALSE; - - if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS) - return (result); - - for (i = 0; i < 8; i++) - { - DMA[i].TransferDirection = OrigDMA[i].TransferDirection; - DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed; - DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement; - DMA[i].TransferMode = OrigDMA[i].TransferMode; - DMA[i].ABank = OrigDMA[i].ABank; - DMA[i].AAddress = OrigDMA[i].AAddress; - DMA[i].Address = OrigDMA[i].Address; - DMA[i].BAddress = OrigDMA[i].BAddress; - DMA[i].TransferBytes = OrigDMA[i].TransferBytes; - DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing; - DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress; - DMA[i].IndirectBank = OrigDMA[i].IndirectBank; - DMA[i].Repeat = OrigDMA[i].Repeat; - DMA[i].LineCount = OrigDMA[i].LineCount; - DMA[i].FirstLine = OrigDMA[i].FirstLine; - } - - if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("SRA:", ::SRAM, 0x10000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS) - return (result); - if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS) - { - APU = *(struct SAPU *) &OrigAPU; - - if ((result = ReadBlock ("ARE:", &OrigAPURegisters, - sizeof (OrigAPURegisters), snap)) != SUCCESS) - return (result); - IAPU.Registers = *(struct SAPURegisters *) &OrigAPURegisters; - if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("SOU:", &OrigSoundData, - sizeof (SOrigSoundData), snap)) != SUCCESS) - return (result); - - - SoundData.master_volume [0] = OrigSoundData.master_volume_left; - SoundData.master_volume [1] = OrigSoundData.master_volume_right; - SoundData.echo_volume [0] = OrigSoundData.echo_volume_left; - SoundData.echo_volume [1] = OrigSoundData.echo_volume_right; - - SoundData.echo_enable = OrigSoundData.echo_enable; - SoundData.echo_feedback = OrigSoundData.echo_feedback; - SoundData.echo_ptr = OrigSoundData.echo_ptr; - SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size; - SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled; - SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable; - SoundData.pitch_mod = OrigSoundData.pitch_mod; - - for (i = 0; i < 3; i++) - SoundData.dummy [i] = OrigSoundData.dummy [i]; - for (i = 0; i < NUM_CHANNELS; i++) - { - SoundData.channels [i].state = OrigSoundData.channels [i].state; - SoundData.channels [i].type = OrigSoundData.channels [i].type; - SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left; - SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right; - SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency; - SoundData.channels [i].count = OrigSoundData.channels [i].count; - SoundData.channels [i].loop = OrigSoundData.channels [i].loop; - SoundData.channels [i].envx = OrigSoundData.channels [i].envx; - SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level; - SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level; - SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target; - SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error; - SoundData.channels [i].erate = OrigSoundData.channels [i].erate; - SoundData.channels [i].direction = OrigSoundData.channels [i].direction; - SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate; - SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate; - SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate; - SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate; - SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level; - SoundData.channels [i].sample = OrigSoundData.channels [i].sample; - for (j = 0; j < 16; j++) - SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j]; - - for (j = 0; j < 2; j++) - SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j]; - - SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number; - SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block; - SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode; - SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer; - SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer; - SoundData.channels [i].mode = OrigSoundData.channels [i].mode; - } - - S9xSetSoundMute (FALSE); - IAPU.PC = IAPU.RAM + IAPU.Registers.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); - } - S9xFixSoundAfterSnapshotLoad (); - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); - S9xUnpackStatus (); - S9xFixCycles (); - S9xReschedule (); - - return (SUCCESS); -} - diff --git a/source/snapshot.c b/source/snapshot.c new file mode 100644 index 0000000..ac4abe4 --- /dev/null +++ b/source/snapshot.c @@ -0,0 +1,1789 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include + +#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) +#include +#include +#include +#endif + +#include "snapshot.h" +#include "snaporig.h" +#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 "srtc.h" +#include "sdd1.h" +#include "spc7110.h" + +extern uint8 *SRAM; + +#ifdef ZSNES_FX +START_EXTERN_C +void S9xSuperFXPreSaveState (); +void S9xSuperFXPostSaveState (); +void S9xSuperFXPostLoadState (); +END_EXTERN_C +#endif + +bool8 S9xUnfreezeZSNES (const char *filename); + +typedef struct { + int offset; + int size; + int type; +} FreezeData; + +enum { + INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V +}; + +#define Offset(field,structure) \ +((int) (((char *) (&(((structure)NULL)->field))) - ((char *) NULL))) + +#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) + +struct SnapshotMovieInfo +{ + uint32 MovieInputDataSize; +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SnapshotMovieInfo *) + +static FreezeData SnapMovie [] = { + {OFFSET (MovieInputDataSize), 4, INT_V}, +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SCPUState *) + +static FreezeData SnapCPU [] = { + {OFFSET (Flags), 4, INT_V}, + {OFFSET (BranchSkip), 1, INT_V}, + {OFFSET (NMIActive), 1, INT_V}, + {OFFSET (IRQActive), 1, INT_V}, + {OFFSET (WaitingForInterrupt), 1, INT_V}, + {OFFSET (WhichEvent), 1, INT_V}, + {OFFSET (Cycles), 4, INT_V}, + {OFFSET (NextEvent), 4, INT_V}, + {OFFSET (V_Counter), 4, INT_V}, + {OFFSET (MemSpeed), 4, INT_V}, + {OFFSET (MemSpeedx2), 4, INT_V}, + {OFFSET (FastROMSpeed), 4, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SRegisters *) + +static FreezeData SnapRegisters [] = { + {OFFSET (PB), 1, INT_V}, + {OFFSET (DB), 1, INT_V}, + {OFFSET (P.W), 2, INT_V}, + {OFFSET (A.W), 2, INT_V}, + {OFFSET (D.W), 2, INT_V}, + {OFFSET (S.W), 2, INT_V}, + {OFFSET (X.W), 2, INT_V}, + {OFFSET (Y.W), 2, INT_V}, + {OFFSET (PC), 2, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SPPU *) + +static FreezeData SnapPPU [] = { + {OFFSET (BGMode), 1, INT_V}, + {OFFSET (BG3Priority), 1, INT_V}, + {OFFSET (Brightness), 1, INT_V}, + {OFFSET (VMA.High), 1, INT_V}, + {OFFSET (VMA.Increment), 1, INT_V}, + {OFFSET (VMA.Address), 2, INT_V}, + {OFFSET (VMA.Mask1), 2, INT_V}, + {OFFSET (VMA.FullGraphicCount), 2, INT_V}, + {OFFSET (VMA.Shift), 2, INT_V}, + {OFFSET (BG[0].SCBase), 2, INT_V}, + {OFFSET (BG[0].VOffset), 2, INT_V}, + {OFFSET (BG[0].HOffset), 2, INT_V}, + {OFFSET (BG[0].BGSize), 1, INT_V}, + {OFFSET (BG[0].NameBase), 2, INT_V}, + {OFFSET (BG[0].SCSize), 2, INT_V}, + + {OFFSET (BG[1].SCBase), 2, INT_V}, + {OFFSET (BG[1].VOffset), 2, INT_V}, + {OFFSET (BG[1].HOffset), 2, INT_V}, + {OFFSET (BG[1].BGSize), 1, INT_V}, + {OFFSET (BG[1].NameBase), 2, INT_V}, + {OFFSET (BG[1].SCSize), 2, INT_V}, + + {OFFSET (BG[2].SCBase), 2, INT_V}, + {OFFSET (BG[2].VOffset), 2, INT_V}, + {OFFSET (BG[2].HOffset), 2, INT_V}, + {OFFSET (BG[2].BGSize), 1, INT_V}, + {OFFSET (BG[2].NameBase), 2, INT_V}, + {OFFSET (BG[2].SCSize), 2, INT_V}, + + {OFFSET (BG[3].SCBase), 2, INT_V}, + {OFFSET (BG[3].VOffset), 2, INT_V}, + {OFFSET (BG[3].HOffset), 2, INT_V}, + {OFFSET (BG[3].BGSize), 1, INT_V}, + {OFFSET (BG[3].NameBase), 2, INT_V}, + {OFFSET (BG[3].SCSize), 2, INT_V}, + + {OFFSET (CGFLIP), 1, INT_V}, + {OFFSET (CGDATA), 256, uint16_ARRAY_V}, + {OFFSET (FirstSprite), 1, INT_V}, +#define O(N) \ + {OFFSET (OBJ[N].HPos), 2, INT_V}, \ + {OFFSET (OBJ[N].VPos), 2, INT_V}, \ + {OFFSET (OBJ[N].Name), 2, INT_V}, \ + {OFFSET (OBJ[N].VFlip), 1, INT_V}, \ + {OFFSET (OBJ[N].HFlip), 1, INT_V}, \ + {OFFSET (OBJ[N].Priority), 1, INT_V}, \ + {OFFSET (OBJ[N].Palette), 1, INT_V}, \ + {OFFSET (OBJ[N].Size), 1, INT_V} + + 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 + {OFFSET (OAMPriorityRotation), 1, INT_V}, + {OFFSET (OAMAddr), 2, INT_V}, + {OFFSET (OAMFlip), 1, INT_V}, + {OFFSET (OAMTileAddress), 2, INT_V}, + {OFFSET (IRQVBeamPos), 2, INT_V}, + {OFFSET (IRQHBeamPos), 2, INT_V}, + {OFFSET (VBeamPosLatched), 2, INT_V}, + {OFFSET (HBeamPosLatched), 2, INT_V}, + {OFFSET (HBeamFlip), 1, INT_V}, + {OFFSET (VBeamFlip), 1, INT_V}, + {OFFSET (HVBeamCounterLatched), 1, INT_V}, + {OFFSET (MatrixA), 2, INT_V}, + {OFFSET (MatrixB), 2, INT_V}, + {OFFSET (MatrixC), 2, INT_V}, + {OFFSET (MatrixD), 2, INT_V}, + {OFFSET (CentreX), 2, INT_V}, + {OFFSET (CentreY), 2, INT_V}, + {OFFSET (Joypad1ButtonReadPos), 1, INT_V}, + {OFFSET (Joypad2ButtonReadPos), 1, INT_V}, + {OFFSET (Joypad3ButtonReadPos), 1, INT_V}, + {OFFSET (CGADD), 1, INT_V}, + {OFFSET (FixedColourRed), 1, INT_V}, + {OFFSET (FixedColourGreen), 1, INT_V}, + {OFFSET (FixedColourBlue), 1, INT_V}, + {OFFSET (SavedOAMAddr), 2, INT_V}, + {OFFSET (ScreenHeight), 2, INT_V}, + {OFFSET (WRAM), 4, INT_V}, + {OFFSET (ForcedBlanking), 1, INT_V}, + {OFFSET (OBJNameSelect), 2, INT_V}, + {OFFSET (OBJSizeSelect), 1, INT_V}, + {OFFSET (OBJNameBase), 2, INT_V}, + {OFFSET (OAMReadFlip), 1, INT_V}, + {OFFSET (VTimerEnabled), 1, INT_V}, + {OFFSET (HTimerEnabled), 1, INT_V}, + {OFFSET (HTimerPosition), 2, INT_V}, + {OFFSET (Mosaic), 1, INT_V}, + {OFFSET (Mode7HFlip), 1, INT_V}, + {OFFSET (Mode7VFlip), 1, INT_V}, + {OFFSET (Mode7Repeat), 1, INT_V}, + {OFFSET (Window1Left), 1, INT_V}, + {OFFSET (Window1Right), 1, INT_V}, + {OFFSET (Window2Left), 1, INT_V}, + {OFFSET (Window2Right), 1, INT_V}, +#define O(N) \ + {OFFSET (ClipWindowOverlapLogic[N]), 1, INT_V}, \ + {OFFSET (ClipWindow1Enable[N]), 1, INT_V}, \ + {OFFSET (ClipWindow2Enable[N]), 1, INT_V}, \ + {OFFSET (ClipWindow1Inside[N]), 1, INT_V}, \ + {OFFSET (ClipWindow2Inside[N]), 1, INT_V} + + O(0), O(1), O(2), O(3), O(4), O(5), + +#undef O + + {OFFSET (CGFLIPRead), 1, INT_V}, + {OFFSET (Need16x8Mulitply), 1, INT_V}, + {OFFSET (BGMosaic), 4, uint8_ARRAY_V}, + {OFFSET (OAMData), 512 + 32, uint8_ARRAY_V}, + {OFFSET (Need16x8Mulitply), 1, INT_V}, + {OFFSET (MouseSpeed), 2, uint8_ARRAY_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SDMA *) + +static FreezeData SnapDMA [] = { +#define O(N) \ + {OFFSET (TransferDirection) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (AAddressFixed) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (AAddressDecrement) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (TransferMode) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (ABank) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (AAddress) + N * sizeof (struct SDMA), 2, INT_V}, \ + {OFFSET (Address) + N * sizeof (struct SDMA), 2, INT_V}, \ + {OFFSET (BAddress) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (TransferBytes) + N * sizeof (struct SDMA), 2, INT_V}, \ + {OFFSET (HDMAIndirectAddressing) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (IndirectAddress) + N * sizeof (struct SDMA), 2, INT_V}, \ + {OFFSET (IndirectBank) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (Repeat) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (LineCount) + N * sizeof (struct SDMA), 1, INT_V}, \ + {OFFSET (FirstLine) + N * sizeof (struct SDMA), 1, INT_V} + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) +#undef O +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SAPU *) + +static FreezeData SnapAPU [] = { + {OFFSET (Cycles), 4, INT_V}, + {OFFSET (ShowROM), 1, INT_V}, + {OFFSET (Flags), 1, INT_V}, + {OFFSET (KeyedChannels), 1, INT_V}, + {OFFSET (OutPorts), 4, uint8_ARRAY_V}, + {OFFSET (DSP), 0x80, uint8_ARRAY_V}, + {OFFSET (ExtraRAM), 64, uint8_ARRAY_V}, + {OFFSET (Timer), 3, uint16_ARRAY_V}, + {OFFSET (TimerTarget), 3, uint16_ARRAY_V}, + {OFFSET (TimerEnabled), 3, uint8_ARRAY_V}, + {OFFSET (TimerValueWritten), 3, uint8_ARRAY_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SAPURegisters *) + +static FreezeData SnapAPURegisters [] = { + {OFFSET (P), 1, INT_V}, + {OFFSET (YA.W), 2, INT_V}, + {OFFSET (X), 1, INT_V}, + {OFFSET (S), 1, INT_V}, + {OFFSET (PC), 2, INT_V}, +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,SSoundData *) + +static FreezeData SnapSoundData [] = { + {OFFSET (master_volume [0]), 2, INT_V}, + {OFFSET (master_volume [1]), 2, INT_V}, + {OFFSET (echo_volume [0]), 2, INT_V}, + {OFFSET (echo_volume [1]), 2, INT_V}, + {OFFSET (echo_enable), 4, INT_V}, + {OFFSET (echo_feedback), 4, INT_V}, + {OFFSET (echo_ptr), 4, INT_V}, + {OFFSET (echo_buffer_size), 4, INT_V}, + {OFFSET (echo_write_enabled), 4, INT_V}, + {OFFSET (echo_channel_enable), 4, INT_V}, + {OFFSET (pitch_mod), 4, INT_V}, + {OFFSET (dummy), 3, uint32_ARRAY_V}, +#define O(N) \ + {OFFSET (channels [N].state), 4, INT_V}, \ + {OFFSET (channels [N].type), 4, INT_V}, \ + {OFFSET (channels [N].volume_left), 2, INT_V}, \ + {OFFSET (channels [N].volume_right), 2, INT_V}, \ + {OFFSET (channels [N].hertz), 4, INT_V}, \ + {OFFSET (channels [N].count), 4, INT_V}, \ + {OFFSET (channels [N].loop), 1, INT_V}, \ + {OFFSET (channels [N].envx), 4, INT_V}, \ + {OFFSET (channels [N].left_vol_level), 2, INT_V}, \ + {OFFSET (channels [N].right_vol_level), 2, INT_V}, \ + {OFFSET (channels [N].envx_target), 2, INT_V}, \ + {OFFSET (channels [N].env_error), 4, INT_V}, \ + {OFFSET (channels [N].erate), 4, INT_V}, \ + {OFFSET (channels [N].direction), 4, INT_V}, \ + {OFFSET (channels [N].attack_rate), 4, INT_V}, \ + {OFFSET (channels [N].decay_rate), 4, INT_V}, \ + {OFFSET (channels [N].sustain_rate), 4, INT_V}, \ + {OFFSET (channels [N].release_rate), 4, INT_V}, \ + {OFFSET (channels [N].sustain_level), 4, INT_V}, \ + {OFFSET (channels [N].sample), 2, INT_V}, \ + {OFFSET (channels [N].decoded), 16, uint16_ARRAY_V}, \ + {OFFSET (channels [N].previous16), 2, uint16_ARRAY_V}, \ + {OFFSET (channels [N].sample_number), 2, INT_V}, \ + {OFFSET (channels [N].last_block), 1, INT_V}, \ + {OFFSET (channels [N].needs_decode), 1, INT_V}, \ + {OFFSET (channels [N].block_pointer), 4, INT_V}, \ + {OFFSET (channels [N].sample_pointer), 4, INT_V}, \ + {OFFSET (channels [N].mode), 4, INT_V} + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) +#undef O +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SSA1Registers *) + +static FreezeData SnapSA1Registers [] = { + {OFFSET (PB), 1, INT_V}, + {OFFSET (DB), 1, INT_V}, + {OFFSET (P.W), 2, INT_V}, + {OFFSET (A.W), 2, INT_V}, + {OFFSET (D.W), 2, INT_V}, + {OFFSET (S.W), 2, INT_V}, + {OFFSET (X.W), 2, INT_V}, + {OFFSET (Y.W), 2, INT_V}, + {OFFSET (PC), 2, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SSA1 *) + +static FreezeData SnapSA1 [] = { + {OFFSET (Flags), 4, INT_V}, + {OFFSET (NMIActive), 1, INT_V}, + {OFFSET (IRQActive), 1, INT_V}, + {OFFSET (WaitingForInterrupt), 1, INT_V}, + {OFFSET (op1), 2, INT_V}, + {OFFSET (op2), 2, INT_V}, + {OFFSET (arithmetic_op), 4, INT_V}, + {OFFSET (sum), 8, INT_V}, + {OFFSET (overflow), 1, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SPC7110EmuVars *) + +static FreezeData SnapSPC7110 [] = { + {OFFSET (reg4800), 1, INT_V}, + {OFFSET (reg4801), 1, INT_V}, + {OFFSET (reg4802), 1, INT_V}, + {OFFSET (reg4803), 1, INT_V}, + {OFFSET (reg4804), 1, INT_V}, + {OFFSET (reg4805), 1, INT_V}, + {OFFSET (reg4806), 1, INT_V}, + {OFFSET (reg4807), 1, INT_V}, + {OFFSET (reg4808), 1, INT_V}, + {OFFSET (reg4809), 1, INT_V}, + {OFFSET (reg480A), 1, INT_V}, + {OFFSET (reg480B), 1, INT_V}, + {OFFSET (reg480C), 1, INT_V}, + {OFFSET (reg4811), 1, INT_V}, + {OFFSET (reg4812), 1, INT_V}, + {OFFSET (reg4813), 1, INT_V}, + {OFFSET (reg4814), 1, INT_V}, + {OFFSET (reg4815), 1, INT_V}, + {OFFSET (reg4816), 1, INT_V}, + {OFFSET (reg4817), 1, INT_V}, + {OFFSET (reg4818), 1, INT_V}, + {OFFSET (reg4820), 1, INT_V}, + {OFFSET (reg4821), 1, INT_V}, + {OFFSET (reg4822), 1, INT_V}, + {OFFSET (reg4823), 1, INT_V}, + {OFFSET (reg4824), 1, INT_V}, + {OFFSET (reg4825), 1, INT_V}, + {OFFSET (reg4826), 1, INT_V}, + {OFFSET (reg4827), 1, INT_V}, + {OFFSET (reg4828), 1, INT_V}, + {OFFSET (reg4829), 1, INT_V}, + {OFFSET (reg482A), 1, INT_V}, + {OFFSET (reg482B), 1, INT_V}, + {OFFSET (reg482C), 1, INT_V}, + {OFFSET (reg482D), 1, INT_V}, + {OFFSET (reg482E), 1, INT_V}, + {OFFSET (reg482F), 1, INT_V}, + {OFFSET (reg4830), 1, INT_V}, + {OFFSET (reg4831), 1, INT_V}, + {OFFSET (reg4832), 1, INT_V}, + {OFFSET (reg4833), 1, INT_V}, + {OFFSET (reg4834), 1, INT_V}, + {OFFSET (reg4840), 1, INT_V}, + {OFFSET (reg4841), 1, INT_V}, + {OFFSET (reg4842), 1, INT_V}, + {OFFSET (AlignBy), 1, INT_V}, + {OFFSET (written), 1, INT_V}, + {OFFSET (offset_add), 1, INT_V}, + {OFFSET (DataRomOffset), 4, INT_V}, + {OFFSET (DataRomSize), 4, INT_V}, + {OFFSET (bank50Internal), 4, INT_V}, + {OFFSET (bank50), 0x10000, uint8_ARRAY_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f,struct SPC7110RTC *) + +static FreezeData SnapS7RTC [] = { + {OFFSET (reg), 16, uint8_ARRAY_V}, + {OFFSET (index), 2, INT_V}, + {OFFSET (control), 1, INT_V}, + {OFFSET (init), 1, INT_V}, + {OFFSET (last_used),4,INT_V} +}; + +//static char ROMFilename [_MAX_PATH]; +//static char SnapshotFilename [_MAX_PATH]; + +void FreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, + int num_fields); +void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size); + +int UnfreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, + int num_fields); +int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size); + +int UnfreezeStructCopy (STREAM stream, const char *name, uint8** block, FreezeData *fields, int num_fields); + +void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uint8* block); + +int UnfreezeBlockCopy (STREAM stream, const char *name, uint8** block, int size); + +bool8 Snapshot (const char *filename) +{ + return (S9xFreezeGame (filename)); +} + +bool8 S9xFreezeGame (const char *filename) +{ + FILE* fp; + fp = fopen(filename, "w"); + if(NULL == fp) + return (FALSE); + + fseek(fp, 4, SEEK_SET); //Valid data offset 4 bytes + S9xFreezeToStream (fp); + fclose(fp); +#if 0 //Not support moive now + if(S9xMovieActive()) + { + sprintf(String, "Movie snapshot %s", S9xBasename (filename)); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + } + else + { + sprintf(String, "Saved %s", S9xBasename (filename)); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + } +#endif + return (TRUE); +} + +bool8 S9xLoadSnapshot (const char *filename) +{ + return (S9xUnfreezeGame (filename)); +} + +bool8 S9xUnfreezeGame (const char *filename) +{ + if (S9xLoadOrigSnapshot (filename)) + return (TRUE); + + if (S9xUnfreezeZSNES (filename)) + return (TRUE); + + FILE* fp; + fp = fopen(filename, "r"); + if(NULL == fp) + return (FALSE); + + fseek(fp, 4, SEEK_SET); //Valid data offset 4 bytes + + int result; + if ((result = S9xUnfreezeFromStream (fp)) != SUCCESS) + { +#if 0 + switch (result) + { + case WRONG_FORMAT: + S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, + "File not in Snes9x freeze format"); + break; + case WRONG_VERSION: + S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, + "Incompatable Snes9x freeze file format 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; + default: + case FILE_NOT_FOUND: + sprintf (String, "ROM image \"%s\" for freeze file not found", + ROMFilename); + S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); + break; + } +#endif + fclose(fp); + return (FALSE); + } +#if 0 //Not support movie now + if(!S9xMovieActive()) + { + sprintf(String, "Loaded %s", S9xBasename (filename)); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + } +#endif + fclose(fp); + return (TRUE); +} + +void S9xFreezeToStream (STREAM stream) +{ + char buffer [1024]; + int i; + + S9xSetSoundMute (TRUE); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPreSaveState (); +#endif + + 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); + WRITE_STREAM (buffer, strlen (buffer), stream); + sprintf (buffer, "NAM:%06d:%s%c", strlen (Memory.ROMFilename) + 1, + Memory.ROMFilename, 0); + WRITE_STREAM (buffer, strlen (buffer) + 1, stream); + FreezeStruct (stream, "CPU", &CPU, SnapCPU, COUNT (SnapCPU)); + FreezeStruct (stream, "REG", &ICPU.Registers, SnapRegisters, COUNT (SnapRegisters)); + FreezeStruct (stream, "PPU", &PPU, SnapPPU, COUNT (SnapPPU)); + FreezeStruct (stream, "DMA", DMA, SnapDMA, COUNT (SnapDMA)); + + // RAM and VRAM + FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); + FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); + FreezeBlock (stream, "SRA", ::SRAM, 0x20000); + FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); + if (Settings.APUEnabled) + { + // APU + FreezeStruct (stream, "APU", &APU, SnapAPU, COUNT (SnapAPU)); + FreezeStruct (stream, "ARE", &IAPU.Registers, SnapAPURegisters, + COUNT (SnapAPURegisters)); + FreezeBlock (stream, "ARA", IAPU.RAM, 0x10000); + FreezeStruct (stream, "SOU", &SoundData, SnapSoundData, + COUNT (SnapSoundData)); + } + if (Settings.SA1) + { + SA1.Registers.PC = SA1.PC - SA1.PCBase; + S9xSA1PackStatus (); + FreezeStruct (stream, "SA1", &SA1, SnapSA1, COUNT (SnapSA1)); + FreezeStruct (stream, "SAR", &SA1.Registers, SnapSA1Registers, + COUNT (SnapSA1Registers)); + } + + if (Settings.SPC7110) + { + FreezeStruct (stream, "SP7", &s7r, SnapSPC7110, COUNT (SnapSPC7110)); + } + if(Settings.SPC7110RTC) + { + FreezeStruct (stream, "RTC", &rtc_f9, SnapS7RTC, COUNT (SnapS7RTC)); + } + + S9xSetSoundMute (FALSE); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostSaveState (); +#endif +} + +int S9xUnfreezeFromStream (STREAM stream) +{ + char buffer [_MAX_PATH + 1]; + char rom_filename [_MAX_PATH + 1]; + int result; + + int version; + unsigned int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (READ_STREAM (buffer, len, stream) != len) + return (WRONG_FORMAT); + if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) + return (WRONG_FORMAT); + if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) + return (WRONG_VERSION); + + if ((result = UnfreezeBlock (stream, "NAM", (uint8 *) rom_filename, _MAX_PATH)) != SUCCESS) + return (result); + + 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."); + } + +// ## 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; + + do + { + if ((result = UnfreezeStructCopy (stream, "CPU", &local_cpu, SnapCPU, COUNT (SnapCPU))) != SUCCESS) + break; + if ((result = UnfreezeStructCopy (stream, "REG", &local_registers, SnapRegisters, COUNT (SnapRegisters))) != SUCCESS) + break; + if ((result = UnfreezeStructCopy (stream, "PPU", &local_ppu, SnapPPU, COUNT (SnapPPU))) != SUCCESS) + break; + if ((result = UnfreezeStructCopy (stream, "DMA", &local_dma, SnapDMA, COUNT (SnapDMA))) != SUCCESS) + break; + if ((result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000)) != SUCCESS) + break; + if ((result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000)) != SUCCESS) + break; + if ((result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000)) != SUCCESS) + break; + if ((result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000)) != SUCCESS) + break; + if (UnfreezeStructCopy (stream, "APU", &local_apu, SnapAPU, COUNT (SnapAPU)) == SUCCESS) + { + if ((result = UnfreezeStructCopy (stream, "ARE", &local_apu_registers, SnapAPURegisters, COUNT (SnapAPURegisters))) != SUCCESS) + break; + if ((result = UnfreezeBlockCopy (stream, "ARA", &local_apu_ram, 0x10000)) != SUCCESS) + break; + if ((result = UnfreezeStructCopy (stream, "SOU", &local_apu_sounddata, SnapSoundData, COUNT (SnapSoundData))) != SUCCESS) + break; + } + if ((result = UnfreezeStructCopy (stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1))) == SUCCESS) + { + if ((result = UnfreezeStructCopy (stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT (SnapSA1Registers))) != SUCCESS) + break; + } + + if ((result = UnfreezeStructCopy (stream, "SP7", &local_spc, SnapSPC7110, COUNT(SnapSPC7110))) != SUCCESS) + { + if(Settings.SPC7110) + break; + } + if ((result = UnfreezeStructCopy (stream, "RTC", &local_spc_rtc, SnapS7RTC, COUNT (SnapS7RTC))) != SUCCESS) + { + if(Settings.SPC7110RTC) + break; + } + + result=SUCCESS; + + } while(false); +// ## end load ## + + if (result == SUCCESS) + { + uint32 old_flags = CPU.Flags; + uint32 sa1_old_flags = SA1.Flags; + S9xReset (); + S9xSetSoundMute (TRUE); + + UnfreezeStructFromCopy (&CPU, SnapCPU, COUNT (SnapCPU), local_cpu); + UnfreezeStructFromCopy (&ICPU.Registers, SnapRegisters, COUNT (SnapRegisters), local_registers); + UnfreezeStructFromCopy (&PPU, SnapPPU, COUNT (SnapPPU), local_ppu); + UnfreezeStructFromCopy (DMA, SnapDMA, COUNT (SnapDMA), local_dma); + memcpy (Memory.VRAM, local_vram, 0x10000); + memcpy (Memory.RAM, local_ram, 0x20000); + memcpy (::SRAM, local_sram, 0x20000); + memcpy (Memory.FillRAM, local_fillram, 0x8000); + if(local_apu) + { + UnfreezeStructFromCopy (&APU, SnapAPU, COUNT (SnapAPU), local_apu); + UnfreezeStructFromCopy (&IAPU.Registers, SnapAPURegisters, COUNT (SnapAPURegisters), local_apu_registers); + memcpy (IAPU.RAM, local_apu_ram, 0x10000); + UnfreezeStructFromCopy (&SoundData, SnapSoundData, COUNT (SnapSoundData), local_apu_sounddata); + } + if(local_sa1) + { + UnfreezeStructFromCopy (&SA1, SnapSA1, COUNT (SnapSA1), local_sa1); + UnfreezeStructFromCopy (&SA1.Registers, SnapSA1Registers, COUNT (SnapSA1Registers), local_sa1_registers); + } + if(local_spc) + { + UnfreezeStructFromCopy (&s7r, SnapSPC7110, COUNT (SnapSPC7110), local_spc); + } + if(local_spc_rtc) + { + UnfreezeStructFromCopy (&rtc_f9, SnapS7RTC, COUNT (SnapS7RTC), local_spc_rtc); + } + + Memory.FixROMSpeed (); + CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | + SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); + + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + CPU.InDMA = FALSE; + S9xFixColourBrightness (); + IPPU.RenderThisFrame = FALSE; + + if (local_apu) + { + S9xSetSoundMute (FALSE); + IAPU.PC = IAPU.RAM + IAPU.Registers.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 (local_sa1) + { + S9xFixSA1AfterSnapshotLoad (); + SA1.Flags |= sa1_old_flags & (TRACE_FLAG); + } + + if (local_spc_rtc) + { + S9xUpdateRTC(); + } + + S9xFixSoundAfterSnapshotLoad (); + + uint8 hdma_byte = Memory.FillRAM[0x420c]; + S9xSetCPU(hdma_byte, 0x420c); + + 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; + } + + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); + 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 (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; + + return (result); +} + +int FreezeSize (int size, int type) +{ + switch (type) + { + case uint16_ARRAY_V: + return (size * 2); + case uint32_ARRAY_V: + return (size * 4); + default: + return (size); + } +} + +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; + + for (i = 0; i < num_fields; i++) + { + if (fields [i].offset + FreezeSize (fields [i].size, + fields [i].type) > len) + len = fields [i].offset + FreezeSize (fields [i].size, + fields [i].type); + } + + uint8 *block = new uint8 [len]; + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + + // Build the block ready to be streamed out + for (i = 0; i < num_fields; i++) + { + switch (fields [i].type) + { + case INT_V: + switch (fields [i].size) + { + case 1: + *ptr++ = *((uint8 *) base + fields [i].offset); + break; + case 2: + word = *((uint16 *) ((uint8 *) base + fields [i].offset)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + break; + case 4: + dword = *((uint32 *) ((uint8 *) base + fields [i].offset)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + break; + case 8: + qword = *((int64 *) ((uint8 *) base + fields [i].offset)); + *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: + // memmove converted: Different mallocs [Neb] + memcpy (ptr, (uint8 *) base + fields [i].offset, fields [i].size); + ptr += fields [i].size; + break; + case uint16_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + word = *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + } + break; + case uint32_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + dword = *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + } + break; + } + } + + FreezeBlock (stream, name, block, len); + delete[] block; +} + +void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer [512]; + sprintf (buffer, "%s:%06d:", name, size); + WRITE_STREAM (buffer, strlen (buffer), stream); + WRITE_STREAM ((char*)block, size, stream); + +} + +int UnfreezeStruct (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; + + for (i = 0; i < num_fields; i++) + { + if (fields [i].offset + FreezeSize (fields [i].size, + fields [i].type) > len) + len = fields [i].offset + FreezeSize (fields [i].size, + fields [i].type); + } + + uint8 *block = new uint8 [len]; + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + int result; + + if ((result = UnfreezeBlock (stream, name, block, len)) != SUCCESS) + { + delete block; + return (result); + } + + // Unpack the block of data into a C structure + for (i = 0; i < num_fields; i++) + { + switch (fields [i].type) + { + case INT_V: + switch (fields [i].size) + { + case 1: + *((uint8 *) base + fields [i].offset) = *ptr++; + break; + case 2: + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; + break; + case 4: + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; + break; + case 8: + 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 *) ((uint8 *) base + fields [i].offset)) = qword; + break; + } + break; + case uint8_ARRAY_V: + // memmove converted: Different mallocs [Neb] + memcpy ((uint8 *) base + fields [i].offset, ptr, fields [i].size); + ptr += fields [i].size; + break; + case uint16_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; + } + break; + case uint32_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; + } + break; + } + } + + delete [] block; + return (result); +} + +int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer [20]; + int len = 0; + int rem = 0; + int rew_len; + if (READ_STREAM (buffer, 11, stream) != 11 || + strncmp (buffer, name, 3) != 0 || buffer [3] != ':' || + (len = atoi (&buffer [4])) == 0) + { + REVERT_STREAM(stream, FIND_STREAM(stream)-11, 0); + return (WRONG_FORMAT); + } + + if (len > size) + { + rem = len - size; + len = size; + } + if ((rew_len=READ_STREAM ((char*)block, len, stream)) != len) + { + REVERT_STREAM(stream, FIND_STREAM(stream)-11-rew_len, 0); + return (WRONG_FORMAT); + } + if (rem) + { + char *junk = new char [rem]; + READ_STREAM (junk, rem, stream); + delete [] junk; + } + + return (SUCCESS); +} + +int UnfreezeStructCopy (STREAM stream, const char *name, uint8** block, FreezeData *fields, int num_fields) +{ + // Work out the size of the required block + int len = 0; + int i; + + for (i = 0; i < num_fields; i++) + { + if (fields [i].offset + FreezeSize (fields [i].size, + fields [i].type) > len) + len = fields [i].offset + FreezeSize (fields [i].size, + fields [i].type); + } + + return (UnfreezeBlockCopy (stream, name, block, len)); +} + +void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uint8* block) +{ + int i; + int j; + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + + // Unpack the block of data into a C structure + for (i = 0; i < num_fields; i++) + { + switch (fields [i].type) + { + case INT_V: + switch (fields [i].size) + { + case 1: + *((uint8 *) base + fields [i].offset) = *ptr++; + break; + case 2: + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; + break; + case 4: + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; + break; + case 8: + 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 *) ((uint8 *) base + fields [i].offset)) = qword; + break; + } + break; + case uint8_ARRAY_V: + // memmove required: Source could point within dest [Neb] + memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); + ptr += fields [i].size; + break; + case uint16_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; + } + break; + case uint32_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; + } + break; + } + } +} + +int UnfreezeBlockCopy (STREAM stream, const 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); +} + +extern uint8 spc_dump_dsp[0x100]; + +bool8 S9xSPCDump (const char *filename) +{ + return (FALSE); +#if 0 + 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; + + S9xSetSoundMute (TRUE); + + if (!(fs = fopen (filename, "wb"))) + return (FALSE); + + // 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 + + 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); +#endif +} + +bool8 S9xUnfreezeZSNES (const char *filename) +{ + FILE *fs; + uint8 t [4000]; + + if (!(fs = fopen (filename, "rb"))) + return (FALSE); + + if (fread ((char*)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 + + ICPU.Registers.A.W = READ_WORD (&t [41]); + ICPU.Registers.DB = t [43]; + ICPU.Registers.PB = t [44]; + ICPU.Registers.S.W = READ_WORD (&t [45]); + ICPU.Registers.D.W = READ_WORD (&t [47]); + ICPU.Registers.X.W = READ_WORD (&t [49]); + ICPU.Registers.Y.W = READ_WORD (&t [51]); + ICPU.Registers.P.W = READ_WORD (&t [53]); + ICPU.Registers.PC = READ_WORD (&t [55]); + + fread ((char*)t, 1, 8, fs); + fread ((char*)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]); + // 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 ((char*)Memory.RAM, 1, 128 * 1024, fs); + fread ((char*)Memory.VRAM, 1, 64 * 1024, fs); + + if (Settings.APUEnabled) + { + // SNES SPC700 RAM (64K) + fread ((char*)IAPU.RAM, 1, 64 * 1024, fs); + + // Junk 16 bytes + fread ((char*)t, 1, 16, fs); + + // SNES SPC700 state and internal ZSNES SPC700 emulation state + fread ((char*)t, 1, 304, fs); + + IAPU.Registers.PC = READ_DWORD (&t [0]); + IAPU.Registers.YA.B.A = t [4]; + IAPU.Registers.X = t [8]; + IAPU.Registers.YA.B.Y = t [12]; + IAPU.Registers.P = t [16]; + IAPU.Registers.S = t [24]; + + APU.Cycles = READ_DWORD (&t [32]); + 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 converted: Different mallocs [Neb] + memcpy (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 + IAPU.Registers.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 (::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); + + SA1.Registers.A.W = READ_DWORD (&t [592]); + SA1.Registers.X.W = READ_DWORD (&t [596]); + SA1.Registers.Y.W = READ_DWORD (&t [600]); + SA1.Registers.D.W = READ_DWORD (&t [604]); + SA1.Registers.DB = t [608]; + SA1.Registers.PB = t [612]; + SA1.Registers.S.W = READ_DWORD (&t [616]); + SA1.Registers.PC = READ_DWORD (&t [636]); + SA1.Registers.P.W = t [620] | (t [624] << 8); + + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: This code path is not used [Neb] + memcpy (&Memory.FillRAM [0x3000], t + 692, 2 * 1024); + + fread (::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.InDMA = FALSE; + S9xFixColourBrightness (); + IPPU.RenderThisFrame = FALSE; + + S9xFixSoundAfterSnapshotLoad (); + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); + S9xUnpackStatus (); + S9xFixCycles (); + S9xReschedule (); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostLoadState (); +#endif + return (TRUE); + } + fclose (fs); + return (FALSE); +} + diff --git a/source/snapshot.cpp b/source/snapshot.cpp deleted file mode 100644 index ac4abe4..0000000 --- a/source/snapshot.cpp +++ /dev/null @@ -1,1789 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#ifdef HAVE_STRINGS_H -#include -#endif -#include -#include - -#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) -#include -#include -#include -#endif - -#include "snapshot.h" -#include "snaporig.h" -#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 "srtc.h" -#include "sdd1.h" -#include "spc7110.h" - -extern uint8 *SRAM; - -#ifdef ZSNES_FX -START_EXTERN_C -void S9xSuperFXPreSaveState (); -void S9xSuperFXPostSaveState (); -void S9xSuperFXPostLoadState (); -END_EXTERN_C -#endif - -bool8 S9xUnfreezeZSNES (const char *filename); - -typedef struct { - int offset; - int size; - int type; -} FreezeData; - -enum { - INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V -}; - -#define Offset(field,structure) \ -((int) (((char *) (&(((structure)NULL)->field))) - ((char *) NULL))) - -#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) - -struct SnapshotMovieInfo -{ - uint32 MovieInputDataSize; -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SnapshotMovieInfo *) - -static FreezeData SnapMovie [] = { - {OFFSET (MovieInputDataSize), 4, INT_V}, -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SCPUState *) - -static FreezeData SnapCPU [] = { - {OFFSET (Flags), 4, INT_V}, - {OFFSET (BranchSkip), 1, INT_V}, - {OFFSET (NMIActive), 1, INT_V}, - {OFFSET (IRQActive), 1, INT_V}, - {OFFSET (WaitingForInterrupt), 1, INT_V}, - {OFFSET (WhichEvent), 1, INT_V}, - {OFFSET (Cycles), 4, INT_V}, - {OFFSET (NextEvent), 4, INT_V}, - {OFFSET (V_Counter), 4, INT_V}, - {OFFSET (MemSpeed), 4, INT_V}, - {OFFSET (MemSpeedx2), 4, INT_V}, - {OFFSET (FastROMSpeed), 4, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SRegisters *) - -static FreezeData SnapRegisters [] = { - {OFFSET (PB), 1, INT_V}, - {OFFSET (DB), 1, INT_V}, - {OFFSET (P.W), 2, INT_V}, - {OFFSET (A.W), 2, INT_V}, - {OFFSET (D.W), 2, INT_V}, - {OFFSET (S.W), 2, INT_V}, - {OFFSET (X.W), 2, INT_V}, - {OFFSET (Y.W), 2, INT_V}, - {OFFSET (PC), 2, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPPU *) - -static FreezeData SnapPPU [] = { - {OFFSET (BGMode), 1, INT_V}, - {OFFSET (BG3Priority), 1, INT_V}, - {OFFSET (Brightness), 1, INT_V}, - {OFFSET (VMA.High), 1, INT_V}, - {OFFSET (VMA.Increment), 1, INT_V}, - {OFFSET (VMA.Address), 2, INT_V}, - {OFFSET (VMA.Mask1), 2, INT_V}, - {OFFSET (VMA.FullGraphicCount), 2, INT_V}, - {OFFSET (VMA.Shift), 2, INT_V}, - {OFFSET (BG[0].SCBase), 2, INT_V}, - {OFFSET (BG[0].VOffset), 2, INT_V}, - {OFFSET (BG[0].HOffset), 2, INT_V}, - {OFFSET (BG[0].BGSize), 1, INT_V}, - {OFFSET (BG[0].NameBase), 2, INT_V}, - {OFFSET (BG[0].SCSize), 2, INT_V}, - - {OFFSET (BG[1].SCBase), 2, INT_V}, - {OFFSET (BG[1].VOffset), 2, INT_V}, - {OFFSET (BG[1].HOffset), 2, INT_V}, - {OFFSET (BG[1].BGSize), 1, INT_V}, - {OFFSET (BG[1].NameBase), 2, INT_V}, - {OFFSET (BG[1].SCSize), 2, INT_V}, - - {OFFSET (BG[2].SCBase), 2, INT_V}, - {OFFSET (BG[2].VOffset), 2, INT_V}, - {OFFSET (BG[2].HOffset), 2, INT_V}, - {OFFSET (BG[2].BGSize), 1, INT_V}, - {OFFSET (BG[2].NameBase), 2, INT_V}, - {OFFSET (BG[2].SCSize), 2, INT_V}, - - {OFFSET (BG[3].SCBase), 2, INT_V}, - {OFFSET (BG[3].VOffset), 2, INT_V}, - {OFFSET (BG[3].HOffset), 2, INT_V}, - {OFFSET (BG[3].BGSize), 1, INT_V}, - {OFFSET (BG[3].NameBase), 2, INT_V}, - {OFFSET (BG[3].SCSize), 2, INT_V}, - - {OFFSET (CGFLIP), 1, INT_V}, - {OFFSET (CGDATA), 256, uint16_ARRAY_V}, - {OFFSET (FirstSprite), 1, INT_V}, -#define O(N) \ - {OFFSET (OBJ[N].HPos), 2, INT_V}, \ - {OFFSET (OBJ[N].VPos), 2, INT_V}, \ - {OFFSET (OBJ[N].Name), 2, INT_V}, \ - {OFFSET (OBJ[N].VFlip), 1, INT_V}, \ - {OFFSET (OBJ[N].HFlip), 1, INT_V}, \ - {OFFSET (OBJ[N].Priority), 1, INT_V}, \ - {OFFSET (OBJ[N].Palette), 1, INT_V}, \ - {OFFSET (OBJ[N].Size), 1, INT_V} - - 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 - {OFFSET (OAMPriorityRotation), 1, INT_V}, - {OFFSET (OAMAddr), 2, INT_V}, - {OFFSET (OAMFlip), 1, INT_V}, - {OFFSET (OAMTileAddress), 2, INT_V}, - {OFFSET (IRQVBeamPos), 2, INT_V}, - {OFFSET (IRQHBeamPos), 2, INT_V}, - {OFFSET (VBeamPosLatched), 2, INT_V}, - {OFFSET (HBeamPosLatched), 2, INT_V}, - {OFFSET (HBeamFlip), 1, INT_V}, - {OFFSET (VBeamFlip), 1, INT_V}, - {OFFSET (HVBeamCounterLatched), 1, INT_V}, - {OFFSET (MatrixA), 2, INT_V}, - {OFFSET (MatrixB), 2, INT_V}, - {OFFSET (MatrixC), 2, INT_V}, - {OFFSET (MatrixD), 2, INT_V}, - {OFFSET (CentreX), 2, INT_V}, - {OFFSET (CentreY), 2, INT_V}, - {OFFSET (Joypad1ButtonReadPos), 1, INT_V}, - {OFFSET (Joypad2ButtonReadPos), 1, INT_V}, - {OFFSET (Joypad3ButtonReadPos), 1, INT_V}, - {OFFSET (CGADD), 1, INT_V}, - {OFFSET (FixedColourRed), 1, INT_V}, - {OFFSET (FixedColourGreen), 1, INT_V}, - {OFFSET (FixedColourBlue), 1, INT_V}, - {OFFSET (SavedOAMAddr), 2, INT_V}, - {OFFSET (ScreenHeight), 2, INT_V}, - {OFFSET (WRAM), 4, INT_V}, - {OFFSET (ForcedBlanking), 1, INT_V}, - {OFFSET (OBJNameSelect), 2, INT_V}, - {OFFSET (OBJSizeSelect), 1, INT_V}, - {OFFSET (OBJNameBase), 2, INT_V}, - {OFFSET (OAMReadFlip), 1, INT_V}, - {OFFSET (VTimerEnabled), 1, INT_V}, - {OFFSET (HTimerEnabled), 1, INT_V}, - {OFFSET (HTimerPosition), 2, INT_V}, - {OFFSET (Mosaic), 1, INT_V}, - {OFFSET (Mode7HFlip), 1, INT_V}, - {OFFSET (Mode7VFlip), 1, INT_V}, - {OFFSET (Mode7Repeat), 1, INT_V}, - {OFFSET (Window1Left), 1, INT_V}, - {OFFSET (Window1Right), 1, INT_V}, - {OFFSET (Window2Left), 1, INT_V}, - {OFFSET (Window2Right), 1, INT_V}, -#define O(N) \ - {OFFSET (ClipWindowOverlapLogic[N]), 1, INT_V}, \ - {OFFSET (ClipWindow1Enable[N]), 1, INT_V}, \ - {OFFSET (ClipWindow2Enable[N]), 1, INT_V}, \ - {OFFSET (ClipWindow1Inside[N]), 1, INT_V}, \ - {OFFSET (ClipWindow2Inside[N]), 1, INT_V} - - O(0), O(1), O(2), O(3), O(4), O(5), - -#undef O - - {OFFSET (CGFLIPRead), 1, INT_V}, - {OFFSET (Need16x8Mulitply), 1, INT_V}, - {OFFSET (BGMosaic), 4, uint8_ARRAY_V}, - {OFFSET (OAMData), 512 + 32, uint8_ARRAY_V}, - {OFFSET (Need16x8Mulitply), 1, INT_V}, - {OFFSET (MouseSpeed), 2, uint8_ARRAY_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SDMA *) - -static FreezeData SnapDMA [] = { -#define O(N) \ - {OFFSET (TransferDirection) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (AAddressFixed) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (AAddressDecrement) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (TransferMode) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (ABank) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (AAddress) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (Address) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (BAddress) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (TransferBytes) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (HDMAIndirectAddressing) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (IndirectAddress) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (IndirectBank) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (Repeat) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (LineCount) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (FirstLine) + N * sizeof (struct SDMA), 1, INT_V} - - O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) -#undef O -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SAPU *) - -static FreezeData SnapAPU [] = { - {OFFSET (Cycles), 4, INT_V}, - {OFFSET (ShowROM), 1, INT_V}, - {OFFSET (Flags), 1, INT_V}, - {OFFSET (KeyedChannels), 1, INT_V}, - {OFFSET (OutPorts), 4, uint8_ARRAY_V}, - {OFFSET (DSP), 0x80, uint8_ARRAY_V}, - {OFFSET (ExtraRAM), 64, uint8_ARRAY_V}, - {OFFSET (Timer), 3, uint16_ARRAY_V}, - {OFFSET (TimerTarget), 3, uint16_ARRAY_V}, - {OFFSET (TimerEnabled), 3, uint8_ARRAY_V}, - {OFFSET (TimerValueWritten), 3, uint8_ARRAY_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SAPURegisters *) - -static FreezeData SnapAPURegisters [] = { - {OFFSET (P), 1, INT_V}, - {OFFSET (YA.W), 2, INT_V}, - {OFFSET (X), 1, INT_V}, - {OFFSET (S), 1, INT_V}, - {OFFSET (PC), 2, INT_V}, -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,SSoundData *) - -static FreezeData SnapSoundData [] = { - {OFFSET (master_volume [0]), 2, INT_V}, - {OFFSET (master_volume [1]), 2, INT_V}, - {OFFSET (echo_volume [0]), 2, INT_V}, - {OFFSET (echo_volume [1]), 2, INT_V}, - {OFFSET (echo_enable), 4, INT_V}, - {OFFSET (echo_feedback), 4, INT_V}, - {OFFSET (echo_ptr), 4, INT_V}, - {OFFSET (echo_buffer_size), 4, INT_V}, - {OFFSET (echo_write_enabled), 4, INT_V}, - {OFFSET (echo_channel_enable), 4, INT_V}, - {OFFSET (pitch_mod), 4, INT_V}, - {OFFSET (dummy), 3, uint32_ARRAY_V}, -#define O(N) \ - {OFFSET (channels [N].state), 4, INT_V}, \ - {OFFSET (channels [N].type), 4, INT_V}, \ - {OFFSET (channels [N].volume_left), 2, INT_V}, \ - {OFFSET (channels [N].volume_right), 2, INT_V}, \ - {OFFSET (channels [N].hertz), 4, INT_V}, \ - {OFFSET (channels [N].count), 4, INT_V}, \ - {OFFSET (channels [N].loop), 1, INT_V}, \ - {OFFSET (channels [N].envx), 4, INT_V}, \ - {OFFSET (channels [N].left_vol_level), 2, INT_V}, \ - {OFFSET (channels [N].right_vol_level), 2, INT_V}, \ - {OFFSET (channels [N].envx_target), 2, INT_V}, \ - {OFFSET (channels [N].env_error), 4, INT_V}, \ - {OFFSET (channels [N].erate), 4, INT_V}, \ - {OFFSET (channels [N].direction), 4, INT_V}, \ - {OFFSET (channels [N].attack_rate), 4, INT_V}, \ - {OFFSET (channels [N].decay_rate), 4, INT_V}, \ - {OFFSET (channels [N].sustain_rate), 4, INT_V}, \ - {OFFSET (channels [N].release_rate), 4, INT_V}, \ - {OFFSET (channels [N].sustain_level), 4, INT_V}, \ - {OFFSET (channels [N].sample), 2, INT_V}, \ - {OFFSET (channels [N].decoded), 16, uint16_ARRAY_V}, \ - {OFFSET (channels [N].previous16), 2, uint16_ARRAY_V}, \ - {OFFSET (channels [N].sample_number), 2, INT_V}, \ - {OFFSET (channels [N].last_block), 1, INT_V}, \ - {OFFSET (channels [N].needs_decode), 1, INT_V}, \ - {OFFSET (channels [N].block_pointer), 4, INT_V}, \ - {OFFSET (channels [N].sample_pointer), 4, INT_V}, \ - {OFFSET (channels [N].mode), 4, INT_V} - - O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) -#undef O -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SSA1Registers *) - -static FreezeData SnapSA1Registers [] = { - {OFFSET (PB), 1, INT_V}, - {OFFSET (DB), 1, INT_V}, - {OFFSET (P.W), 2, INT_V}, - {OFFSET (A.W), 2, INT_V}, - {OFFSET (D.W), 2, INT_V}, - {OFFSET (S.W), 2, INT_V}, - {OFFSET (X.W), 2, INT_V}, - {OFFSET (Y.W), 2, INT_V}, - {OFFSET (PC), 2, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SSA1 *) - -static FreezeData SnapSA1 [] = { - {OFFSET (Flags), 4, INT_V}, - {OFFSET (NMIActive), 1, INT_V}, - {OFFSET (IRQActive), 1, INT_V}, - {OFFSET (WaitingForInterrupt), 1, INT_V}, - {OFFSET (op1), 2, INT_V}, - {OFFSET (op2), 2, INT_V}, - {OFFSET (arithmetic_op), 4, INT_V}, - {OFFSET (sum), 8, INT_V}, - {OFFSET (overflow), 1, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPC7110EmuVars *) - -static FreezeData SnapSPC7110 [] = { - {OFFSET (reg4800), 1, INT_V}, - {OFFSET (reg4801), 1, INT_V}, - {OFFSET (reg4802), 1, INT_V}, - {OFFSET (reg4803), 1, INT_V}, - {OFFSET (reg4804), 1, INT_V}, - {OFFSET (reg4805), 1, INT_V}, - {OFFSET (reg4806), 1, INT_V}, - {OFFSET (reg4807), 1, INT_V}, - {OFFSET (reg4808), 1, INT_V}, - {OFFSET (reg4809), 1, INT_V}, - {OFFSET (reg480A), 1, INT_V}, - {OFFSET (reg480B), 1, INT_V}, - {OFFSET (reg480C), 1, INT_V}, - {OFFSET (reg4811), 1, INT_V}, - {OFFSET (reg4812), 1, INT_V}, - {OFFSET (reg4813), 1, INT_V}, - {OFFSET (reg4814), 1, INT_V}, - {OFFSET (reg4815), 1, INT_V}, - {OFFSET (reg4816), 1, INT_V}, - {OFFSET (reg4817), 1, INT_V}, - {OFFSET (reg4818), 1, INT_V}, - {OFFSET (reg4820), 1, INT_V}, - {OFFSET (reg4821), 1, INT_V}, - {OFFSET (reg4822), 1, INT_V}, - {OFFSET (reg4823), 1, INT_V}, - {OFFSET (reg4824), 1, INT_V}, - {OFFSET (reg4825), 1, INT_V}, - {OFFSET (reg4826), 1, INT_V}, - {OFFSET (reg4827), 1, INT_V}, - {OFFSET (reg4828), 1, INT_V}, - {OFFSET (reg4829), 1, INT_V}, - {OFFSET (reg482A), 1, INT_V}, - {OFFSET (reg482B), 1, INT_V}, - {OFFSET (reg482C), 1, INT_V}, - {OFFSET (reg482D), 1, INT_V}, - {OFFSET (reg482E), 1, INT_V}, - {OFFSET (reg482F), 1, INT_V}, - {OFFSET (reg4830), 1, INT_V}, - {OFFSET (reg4831), 1, INT_V}, - {OFFSET (reg4832), 1, INT_V}, - {OFFSET (reg4833), 1, INT_V}, - {OFFSET (reg4834), 1, INT_V}, - {OFFSET (reg4840), 1, INT_V}, - {OFFSET (reg4841), 1, INT_V}, - {OFFSET (reg4842), 1, INT_V}, - {OFFSET (AlignBy), 1, INT_V}, - {OFFSET (written), 1, INT_V}, - {OFFSET (offset_add), 1, INT_V}, - {OFFSET (DataRomOffset), 4, INT_V}, - {OFFSET (DataRomSize), 4, INT_V}, - {OFFSET (bank50Internal), 4, INT_V}, - {OFFSET (bank50), 0x10000, uint8_ARRAY_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPC7110RTC *) - -static FreezeData SnapS7RTC [] = { - {OFFSET (reg), 16, uint8_ARRAY_V}, - {OFFSET (index), 2, INT_V}, - {OFFSET (control), 1, INT_V}, - {OFFSET (init), 1, INT_V}, - {OFFSET (last_used),4,INT_V} -}; - -//static char ROMFilename [_MAX_PATH]; -//static char SnapshotFilename [_MAX_PATH]; - -void FreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, - int num_fields); -void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size); - -int UnfreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, - int num_fields); -int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size); - -int UnfreezeStructCopy (STREAM stream, const char *name, uint8** block, FreezeData *fields, int num_fields); - -void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uint8* block); - -int UnfreezeBlockCopy (STREAM stream, const char *name, uint8** block, int size); - -bool8 Snapshot (const char *filename) -{ - return (S9xFreezeGame (filename)); -} - -bool8 S9xFreezeGame (const char *filename) -{ - FILE* fp; - fp = fopen(filename, "w"); - if(NULL == fp) - return (FALSE); - - fseek(fp, 4, SEEK_SET); //Valid data offset 4 bytes - S9xFreezeToStream (fp); - fclose(fp); -#if 0 //Not support moive now - if(S9xMovieActive()) - { - sprintf(String, "Movie snapshot %s", S9xBasename (filename)); - S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); - } - else - { - sprintf(String, "Saved %s", S9xBasename (filename)); - S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); - } -#endif - return (TRUE); -} - -bool8 S9xLoadSnapshot (const char *filename) -{ - return (S9xUnfreezeGame (filename)); -} - -bool8 S9xUnfreezeGame (const char *filename) -{ - if (S9xLoadOrigSnapshot (filename)) - return (TRUE); - - if (S9xUnfreezeZSNES (filename)) - return (TRUE); - - FILE* fp; - fp = fopen(filename, "r"); - if(NULL == fp) - return (FALSE); - - fseek(fp, 4, SEEK_SET); //Valid data offset 4 bytes - - int result; - if ((result = S9xUnfreezeFromStream (fp)) != SUCCESS) - { -#if 0 - switch (result) - { - case WRONG_FORMAT: - S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, - "File not in Snes9x freeze format"); - break; - case WRONG_VERSION: - S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, - "Incompatable Snes9x freeze file format 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; - default: - case FILE_NOT_FOUND: - sprintf (String, "ROM image \"%s\" for freeze file not found", - ROMFilename); - S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); - break; - } -#endif - fclose(fp); - return (FALSE); - } -#if 0 //Not support movie now - if(!S9xMovieActive()) - { - sprintf(String, "Loaded %s", S9xBasename (filename)); - S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); - } -#endif - fclose(fp); - return (TRUE); -} - -void S9xFreezeToStream (STREAM stream) -{ - char buffer [1024]; - int i; - - S9xSetSoundMute (TRUE); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPreSaveState (); -#endif - - 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); - WRITE_STREAM (buffer, strlen (buffer), stream); - sprintf (buffer, "NAM:%06d:%s%c", strlen (Memory.ROMFilename) + 1, - Memory.ROMFilename, 0); - WRITE_STREAM (buffer, strlen (buffer) + 1, stream); - FreezeStruct (stream, "CPU", &CPU, SnapCPU, COUNT (SnapCPU)); - FreezeStruct (stream, "REG", &ICPU.Registers, SnapRegisters, COUNT (SnapRegisters)); - FreezeStruct (stream, "PPU", &PPU, SnapPPU, COUNT (SnapPPU)); - FreezeStruct (stream, "DMA", DMA, SnapDMA, COUNT (SnapDMA)); - - // RAM and VRAM - FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); - FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); - FreezeBlock (stream, "SRA", ::SRAM, 0x20000); - FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); - if (Settings.APUEnabled) - { - // APU - FreezeStruct (stream, "APU", &APU, SnapAPU, COUNT (SnapAPU)); - FreezeStruct (stream, "ARE", &IAPU.Registers, SnapAPURegisters, - COUNT (SnapAPURegisters)); - FreezeBlock (stream, "ARA", IAPU.RAM, 0x10000); - FreezeStruct (stream, "SOU", &SoundData, SnapSoundData, - COUNT (SnapSoundData)); - } - if (Settings.SA1) - { - SA1.Registers.PC = SA1.PC - SA1.PCBase; - S9xSA1PackStatus (); - FreezeStruct (stream, "SA1", &SA1, SnapSA1, COUNT (SnapSA1)); - FreezeStruct (stream, "SAR", &SA1.Registers, SnapSA1Registers, - COUNT (SnapSA1Registers)); - } - - if (Settings.SPC7110) - { - FreezeStruct (stream, "SP7", &s7r, SnapSPC7110, COUNT (SnapSPC7110)); - } - if(Settings.SPC7110RTC) - { - FreezeStruct (stream, "RTC", &rtc_f9, SnapS7RTC, COUNT (SnapS7RTC)); - } - - S9xSetSoundMute (FALSE); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostSaveState (); -#endif -} - -int S9xUnfreezeFromStream (STREAM stream) -{ - char buffer [_MAX_PATH + 1]; - char rom_filename [_MAX_PATH + 1]; - int result; - - int version; - unsigned int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; - if (READ_STREAM (buffer, len, stream) != len) - return (WRONG_FORMAT); - if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) - return (WRONG_FORMAT); - if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) - return (WRONG_VERSION); - - if ((result = UnfreezeBlock (stream, "NAM", (uint8 *) rom_filename, _MAX_PATH)) != SUCCESS) - return (result); - - 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."); - } - -// ## 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; - - do - { - if ((result = UnfreezeStructCopy (stream, "CPU", &local_cpu, SnapCPU, COUNT (SnapCPU))) != SUCCESS) - break; - if ((result = UnfreezeStructCopy (stream, "REG", &local_registers, SnapRegisters, COUNT (SnapRegisters))) != SUCCESS) - break; - if ((result = UnfreezeStructCopy (stream, "PPU", &local_ppu, SnapPPU, COUNT (SnapPPU))) != SUCCESS) - break; - if ((result = UnfreezeStructCopy (stream, "DMA", &local_dma, SnapDMA, COUNT (SnapDMA))) != SUCCESS) - break; - if ((result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000)) != SUCCESS) - break; - if ((result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000)) != SUCCESS) - break; - if ((result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000)) != SUCCESS) - break; - if ((result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000)) != SUCCESS) - break; - if (UnfreezeStructCopy (stream, "APU", &local_apu, SnapAPU, COUNT (SnapAPU)) == SUCCESS) - { - if ((result = UnfreezeStructCopy (stream, "ARE", &local_apu_registers, SnapAPURegisters, COUNT (SnapAPURegisters))) != SUCCESS) - break; - if ((result = UnfreezeBlockCopy (stream, "ARA", &local_apu_ram, 0x10000)) != SUCCESS) - break; - if ((result = UnfreezeStructCopy (stream, "SOU", &local_apu_sounddata, SnapSoundData, COUNT (SnapSoundData))) != SUCCESS) - break; - } - if ((result = UnfreezeStructCopy (stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1))) == SUCCESS) - { - if ((result = UnfreezeStructCopy (stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT (SnapSA1Registers))) != SUCCESS) - break; - } - - if ((result = UnfreezeStructCopy (stream, "SP7", &local_spc, SnapSPC7110, COUNT(SnapSPC7110))) != SUCCESS) - { - if(Settings.SPC7110) - break; - } - if ((result = UnfreezeStructCopy (stream, "RTC", &local_spc_rtc, SnapS7RTC, COUNT (SnapS7RTC))) != SUCCESS) - { - if(Settings.SPC7110RTC) - break; - } - - result=SUCCESS; - - } while(false); -// ## end load ## - - if (result == SUCCESS) - { - uint32 old_flags = CPU.Flags; - uint32 sa1_old_flags = SA1.Flags; - S9xReset (); - S9xSetSoundMute (TRUE); - - UnfreezeStructFromCopy (&CPU, SnapCPU, COUNT (SnapCPU), local_cpu); - UnfreezeStructFromCopy (&ICPU.Registers, SnapRegisters, COUNT (SnapRegisters), local_registers); - UnfreezeStructFromCopy (&PPU, SnapPPU, COUNT (SnapPPU), local_ppu); - UnfreezeStructFromCopy (DMA, SnapDMA, COUNT (SnapDMA), local_dma); - memcpy (Memory.VRAM, local_vram, 0x10000); - memcpy (Memory.RAM, local_ram, 0x20000); - memcpy (::SRAM, local_sram, 0x20000); - memcpy (Memory.FillRAM, local_fillram, 0x8000); - if(local_apu) - { - UnfreezeStructFromCopy (&APU, SnapAPU, COUNT (SnapAPU), local_apu); - UnfreezeStructFromCopy (&IAPU.Registers, SnapAPURegisters, COUNT (SnapAPURegisters), local_apu_registers); - memcpy (IAPU.RAM, local_apu_ram, 0x10000); - UnfreezeStructFromCopy (&SoundData, SnapSoundData, COUNT (SnapSoundData), local_apu_sounddata); - } - if(local_sa1) - { - UnfreezeStructFromCopy (&SA1, SnapSA1, COUNT (SnapSA1), local_sa1); - UnfreezeStructFromCopy (&SA1.Registers, SnapSA1Registers, COUNT (SnapSA1Registers), local_sa1_registers); - } - if(local_spc) - { - UnfreezeStructFromCopy (&s7r, SnapSPC7110, COUNT (SnapSPC7110), local_spc); - } - if(local_spc_rtc) - { - UnfreezeStructFromCopy (&rtc_f9, SnapS7RTC, COUNT (SnapS7RTC), local_spc_rtc); - } - - Memory.FixROMSpeed (); - CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | - SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); - - IPPU.ColorsChanged = TRUE; - IPPU.OBJChanged = TRUE; - CPU.InDMA = FALSE; - S9xFixColourBrightness (); - IPPU.RenderThisFrame = FALSE; - - if (local_apu) - { - S9xSetSoundMute (FALSE); - IAPU.PC = IAPU.RAM + IAPU.Registers.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 (local_sa1) - { - S9xFixSA1AfterSnapshotLoad (); - SA1.Flags |= sa1_old_flags & (TRACE_FLAG); - } - - if (local_spc_rtc) - { - S9xUpdateRTC(); - } - - S9xFixSoundAfterSnapshotLoad (); - - uint8 hdma_byte = Memory.FillRAM[0x420c]; - S9xSetCPU(hdma_byte, 0x420c); - - 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; - } - - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); - 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 (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; - - return (result); -} - -int FreezeSize (int size, int type) -{ - switch (type) - { - case uint16_ARRAY_V: - return (size * 2); - case uint32_ARRAY_V: - return (size * 4); - default: - return (size); - } -} - -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; - - for (i = 0; i < num_fields; i++) - { - if (fields [i].offset + FreezeSize (fields [i].size, - fields [i].type) > len) - len = fields [i].offset + FreezeSize (fields [i].size, - fields [i].type); - } - - uint8 *block = new uint8 [len]; - uint8 *ptr = block; - uint16 word; - uint32 dword; - int64 qword; - - // Build the block ready to be streamed out - for (i = 0; i < num_fields; i++) - { - switch (fields [i].type) - { - case INT_V: - switch (fields [i].size) - { - case 1: - *ptr++ = *((uint8 *) base + fields [i].offset); - break; - case 2: - word = *((uint16 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (word >> 8); - *ptr++ = (uint8) word; - break; - case 4: - dword = *((uint32 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - break; - case 8: - qword = *((int64 *) ((uint8 *) base + fields [i].offset)); - *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: - // memmove converted: Different mallocs [Neb] - memcpy (ptr, (uint8 *) base + fields [i].offset, fields [i].size); - ptr += fields [i].size; - break; - case uint16_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - word = *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)); - *ptr++ = (uint8) (word >> 8); - *ptr++ = (uint8) word; - } - break; - case uint32_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - dword = *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - } - break; - } - } - - FreezeBlock (stream, name, block, len); - delete[] block; -} - -void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size) -{ - char buffer [512]; - sprintf (buffer, "%s:%06d:", name, size); - WRITE_STREAM (buffer, strlen (buffer), stream); - WRITE_STREAM ((char*)block, size, stream); - -} - -int UnfreezeStruct (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; - - for (i = 0; i < num_fields; i++) - { - if (fields [i].offset + FreezeSize (fields [i].size, - fields [i].type) > len) - len = fields [i].offset + FreezeSize (fields [i].size, - fields [i].type); - } - - uint8 *block = new uint8 [len]; - uint8 *ptr = block; - uint16 word; - uint32 dword; - int64 qword; - int result; - - if ((result = UnfreezeBlock (stream, name, block, len)) != SUCCESS) - { - delete block; - return (result); - } - - // Unpack the block of data into a C structure - for (i = 0; i < num_fields; i++) - { - switch (fields [i].type) - { - case INT_V: - switch (fields [i].size) - { - case 1: - *((uint8 *) base + fields [i].offset) = *ptr++; - break; - case 2: - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; - break; - case 4: - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; - break; - case 8: - 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 *) ((uint8 *) base + fields [i].offset)) = qword; - break; - } - break; - case uint8_ARRAY_V: - // memmove converted: Different mallocs [Neb] - memcpy ((uint8 *) base + fields [i].offset, ptr, fields [i].size); - ptr += fields [i].size; - break; - case uint16_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; - } - break; - case uint32_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; - } - break; - } - } - - delete [] block; - return (result); -} - -int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size) -{ - char buffer [20]; - int len = 0; - int rem = 0; - int rew_len; - if (READ_STREAM (buffer, 11, stream) != 11 || - strncmp (buffer, name, 3) != 0 || buffer [3] != ':' || - (len = atoi (&buffer [4])) == 0) - { - REVERT_STREAM(stream, FIND_STREAM(stream)-11, 0); - return (WRONG_FORMAT); - } - - if (len > size) - { - rem = len - size; - len = size; - } - if ((rew_len=READ_STREAM ((char*)block, len, stream)) != len) - { - REVERT_STREAM(stream, FIND_STREAM(stream)-11-rew_len, 0); - return (WRONG_FORMAT); - } - if (rem) - { - char *junk = new char [rem]; - READ_STREAM (junk, rem, stream); - delete [] junk; - } - - return (SUCCESS); -} - -int UnfreezeStructCopy (STREAM stream, const char *name, uint8** block, FreezeData *fields, int num_fields) -{ - // Work out the size of the required block - int len = 0; - int i; - - for (i = 0; i < num_fields; i++) - { - if (fields [i].offset + FreezeSize (fields [i].size, - fields [i].type) > len) - len = fields [i].offset + FreezeSize (fields [i].size, - fields [i].type); - } - - return (UnfreezeBlockCopy (stream, name, block, len)); -} - -void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uint8* block) -{ - int i; - int j; - uint8 *ptr = block; - uint16 word; - uint32 dword; - int64 qword; - - // Unpack the block of data into a C structure - for (i = 0; i < num_fields; i++) - { - switch (fields [i].type) - { - case INT_V: - switch (fields [i].size) - { - case 1: - *((uint8 *) base + fields [i].offset) = *ptr++; - break; - case 2: - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; - break; - case 4: - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; - break; - case 8: - 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 *) ((uint8 *) base + fields [i].offset)) = qword; - break; - } - break; - case uint8_ARRAY_V: - // memmove required: Source could point within dest [Neb] - memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); - ptr += fields [i].size; - break; - case uint16_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; - } - break; - case uint32_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; - } - break; - } - } -} - -int UnfreezeBlockCopy (STREAM stream, const 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); -} - -extern uint8 spc_dump_dsp[0x100]; - -bool8 S9xSPCDump (const char *filename) -{ - return (FALSE); -#if 0 - 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; - - S9xSetSoundMute (TRUE); - - if (!(fs = fopen (filename, "wb"))) - return (FALSE); - - // 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 - - 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); -#endif -} - -bool8 S9xUnfreezeZSNES (const char *filename) -{ - FILE *fs; - uint8 t [4000]; - - if (!(fs = fopen (filename, "rb"))) - return (FALSE); - - if (fread ((char*)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 - - ICPU.Registers.A.W = READ_WORD (&t [41]); - ICPU.Registers.DB = t [43]; - ICPU.Registers.PB = t [44]; - ICPU.Registers.S.W = READ_WORD (&t [45]); - ICPU.Registers.D.W = READ_WORD (&t [47]); - ICPU.Registers.X.W = READ_WORD (&t [49]); - ICPU.Registers.Y.W = READ_WORD (&t [51]); - ICPU.Registers.P.W = READ_WORD (&t [53]); - ICPU.Registers.PC = READ_WORD (&t [55]); - - fread ((char*)t, 1, 8, fs); - fread ((char*)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]); - // 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 ((char*)Memory.RAM, 1, 128 * 1024, fs); - fread ((char*)Memory.VRAM, 1, 64 * 1024, fs); - - if (Settings.APUEnabled) - { - // SNES SPC700 RAM (64K) - fread ((char*)IAPU.RAM, 1, 64 * 1024, fs); - - // Junk 16 bytes - fread ((char*)t, 1, 16, fs); - - // SNES SPC700 state and internal ZSNES SPC700 emulation state - fread ((char*)t, 1, 304, fs); - - IAPU.Registers.PC = READ_DWORD (&t [0]); - IAPU.Registers.YA.B.A = t [4]; - IAPU.Registers.X = t [8]; - IAPU.Registers.YA.B.Y = t [12]; - IAPU.Registers.P = t [16]; - IAPU.Registers.S = t [24]; - - APU.Cycles = READ_DWORD (&t [32]); - 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 converted: Different mallocs [Neb] - memcpy (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 + IAPU.Registers.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 (::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); - - SA1.Registers.A.W = READ_DWORD (&t [592]); - SA1.Registers.X.W = READ_DWORD (&t [596]); - SA1.Registers.Y.W = READ_DWORD (&t [600]); - SA1.Registers.D.W = READ_DWORD (&t [604]); - SA1.Registers.DB = t [608]; - SA1.Registers.PB = t [612]; - SA1.Registers.S.W = READ_DWORD (&t [616]); - SA1.Registers.PC = READ_DWORD (&t [636]); - SA1.Registers.P.W = t [620] | (t [624] << 8); - - // memmove converted: Different mallocs [Neb] - // DS2 DMA notes: This code path is not used [Neb] - memcpy (&Memory.FillRAM [0x3000], t + 692, 2 * 1024); - - fread (::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.InDMA = FALSE; - S9xFixColourBrightness (); - IPPU.RenderThisFrame = FALSE; - - S9xFixSoundAfterSnapshotLoad (); - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - S9xSetPCBase (ICPU.ShiftedPB + ICPU.Registers.PC); - S9xUnpackStatus (); - S9xFixCycles (); - S9xReschedule (); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostLoadState (); -#endif - return (TRUE); - } - fclose (fs); - return (FALSE); -} - diff --git a/source/soundux.c b/source/soundux.c new file mode 100644 index 0000000..10e0130 --- /dev/null +++ b/source/soundux.c @@ -0,0 +1,1714 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#ifdef __DJGPP__ +#include +#undef TRUE +#endif + +#include +#include +#include +#include +#include + +#define CLIP16(v) \ + if ((v) < -32768) \ + (v) = -32768; \ + else \ + if ((v) > 32767) \ +(v) = 32767 + +#define CLIP16_latch(v,l) \ + if ((v) < -32768) \ +{ (v) = -32768; (l)++; }\ + else \ + if ((v) > 32767) \ +{ (v) = 32767; (l)++; } + +#define CLIP24(v) \ + if ((v) < -8388608) \ + (v) = -8388608; \ + else \ + if ((v) > 8388607) \ +(v) = 8388607 + +#define CLIP8(v) \ + if ((v) < -128) \ + (v) = -128; \ + else \ + if ((v) > 127) \ +(v) = 127 + +#include "snes9x.h" +#include "soundux.h" +#include "apu.h" +#include "memmap.h" +#include "cpuexec.h" + +extern int32 Echo [24000]; +extern int32 DummyEchoBuffer [SOUND_BUFFER_SIZE]; +extern int32 MixBuffer [SOUND_BUFFER_SIZE]; +extern int32 EchoBuffer [SOUND_BUFFER_SIZE]; +extern int32 FilterTaps [8]; +static uint8 FilterTapDefinitionBitfield; +// In the above, bit I is set if FilterTaps[I] is non-zero. +extern unsigned long Z; +extern int32 Loop [16]; + +extern long FilterValues[4][2]; +extern int32 NoiseFreq [32]; + +static int32 noise_gen; + +#undef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FIXED_POINT 0x10000UL +#define FIXED_POINT_REMAINDER 0xffffUL +#define FIXED_POINT_SHIFT 16 + +#define VOL_DIV8 0x8000 +#define VOL_DIV16 0x0080 +#define ENVX_SHIFT 24 + +extern "C" void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); +extern "C" void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); + +// F is channel's current frequency and M is the 16-bit modulation waveform +// from the previous channel multiplied by the current envelope volume level. +#define PITCH_MOD(F,M) ((F) * ((((unsigned long) (M)) + 0x800000) >> 16) >> 7) +//#define PITCH_MOD(F,M) ((F) * ((((M) & 0x7fffff) >> 14) + 1) >> 8) + +#define LAST_SAMPLE 0xffffff +#define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) + +void S9xSetEightBitConsoleSound (bool8 Enabled) +{ + if (Settings.EightBitConsoleSound != Enabled) + { + Settings.EightBitConsoleSound = Enabled; + int i; + for (i = 0; i < 8; i++) + { + SoundData.channels[i].needs_decode = TRUE; + } + } +} + +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; + 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 ch) +{ + APU.DSP [APU_ENDX] |= 1 << ch; +} +#ifdef __DJGPP +END_OF_FUNCTION (S9xAPUSetEndX) +#endif + +void S9xSetEnvRate (Channel *ch, unsigned long rate, int direction, int target) +{ + ch->envx_target = target; + + if (rate == ~0UL) + { + ch->direction = 0; + rate = 0; + } + else + ch->direction = direction; + + static int64 steps [] = + { + // 0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 + 0, + (int64) FIXED_POINT * 1000 * 64, + (int64) FIXED_POINT * 1000 * 619, + (int64) FIXED_POINT * 1000 * 619, + (int64) FIXED_POINT * 1000 * 128, + (int64) FIXED_POINT * 1000 * 1, + (int64) FIXED_POINT * 1000 * 64, + (int64) FIXED_POINT * 1000 * 55, + (int64) FIXED_POINT * 1000 * 64, + (int64) FIXED_POINT * 1000 * 619 + }; + + if (rate == 0 || so.playback_rate == 0) + ch->erate = 0; + else + { + ch->erate = (unsigned long) + (steps [ch->state] / (rate * so.playback_rate)); + } +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xSetEnvRate); +#endif + +void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, + int target) +{ + S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target); +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xSetEnvelopeRate); +#endif + +void S9xSetSoundVolume (int channel, short volume_left, short volume_right) +{ + Channel *ch = &SoundData.channels[channel]; + ch->volume_left = volume_left; + ch->volume_right = volume_right; + ch-> left_vol_level = (ch->envx * volume_left) / 128; + ch->right_vol_level = (ch->envx * volume_right) / 128; +} + +void S9xSetMasterVolume (short volume_left, short volume_right) +{ + if (Settings.DisableMasterVolume || SNESGameFixes.EchoOnlyOutput) + { + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; + } + else + { + SoundData.master_volume [0] = volume_left; + SoundData.master_volume [1] = volume_right; + } +} + +void S9xSetEchoVolume (short volume_left, short volume_right) +{ + SoundData.echo_volume [0] = volume_left; + SoundData.echo_volume [1] = volume_right; +} + +void S9xSetEchoEnable (uint8 byte) +{ + SoundData.echo_channel_enable = byte; + if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho) + byte = 0; + if (byte && !SoundData.echo_enable) + { + memset (Echo, 0, sizeof (Echo)); + memset (Loop, 0, sizeof (Loop)); + } + + 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) +{ + CLIP8(feedback); + SoundData.echo_feedback = feedback; +} + +void S9xSetEchoDelay (int delay) +{ + SoundData.echo_buffer_size = (512 * delay * so.playback_rate) / 32000; + SoundData.echo_buffer_size <<= 1; + if (SoundData.echo_buffer_size) + SoundData.echo_ptr %= SoundData.echo_buffer_size; + else + SoundData.echo_ptr = 0; + S9xSetEchoEnable (APU.DSP [APU_EON]); +} + +void S9xSetEchoWriteEnable (uint8 byte) +{ + SoundData.echo_write_enabled = byte; + S9xSetEchoDelay (APU.DSP [APU_EDL] & 15); +} + +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, 8, -1, 0); + } +} + +void S9xFixSoundAfterSnapshotLoad () +{ + SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20); + SoundData.echo_channel_enable = APU.DSP [APU_EON]; + 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]); + for (int i = 0; i < 8; i++) + { + SoundData.channels[i].needs_decode = TRUE; + S9xSetSoundFrequency (i, SoundData.channels[i].hertz); + SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT; + SoundData.channels [i].next_sample = 0; + SoundData.channels [i].interpolate = 0; + SoundData.channels [i].previous [0] = (int32) SoundData.channels [i].previous16 [0]; + SoundData.channels [i].previous [1] = (int32) SoundData.channels [i].previous16 [1]; + } + IAPU.Scanline = 0; +} + +void S9xSetFilterCoefficient (int tap, int value) +{ + FilterTaps [tap & 7] = value; + if (value == 0 || (tap == 0 && value == 127)) + FilterTapDefinitionBitfield &= ~(1 << (tap & 7)); + else + FilterTapDefinitionBitfield |= 1 << (tap & 7); +} + +void S9xSetSoundADSR (int channel, int attack_rate, int decay_rate, + int sustain_rate, int sustain_level, int release_rate) +{ + Channel *ch = &SoundData.channels[channel]; + ch->attack_rate = attack_rate; + ch->decay_rate = decay_rate; + ch->sustain_rate = sustain_rate; + ch->release_rate = release_rate; + ch->sustain_level = sustain_level + 1; + + switch (SoundData.channels[channel].state) + { + case SOUND_ATTACK: + S9xSetEnvRate (ch, attack_rate, 1, 127); + break; + + case SOUND_DECAY: + S9xSetEnvRate (ch, decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3); + break; + case SOUND_SUSTAIN: + S9xSetEnvRate (ch, sustain_rate, -1, 0); + break; + } +} + +void S9xSetEnvelopeHeight (int channel, int level) +{ + Channel *ch = &SoundData.channels[channel]; + + ch->envx = level; + ch->envxx = level << ENVX_SHIFT; + + ch->left_vol_level = (level * ch->volume_left) / 128; + ch->right_vol_level = (level * ch->volume_right) / 128; + + if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) + { + S9xAPUSetEndOfSample (channel, ch); + } +} + +int S9xGetEnvelopeHeight (int channel) +{ + if ((Settings.SoundEnvelopeHeightReading || + SNESGameFixes.SoundEnvelopeHeightReading2) && + SoundData.channels[channel].state != SOUND_SILENT && + SoundData.channels[channel].state != SOUND_GAIN) + { + return (SoundData.channels[channel].envx); + } + + //siren fix from XPP + if (SNESGameFixes.SoundEnvelopeHeightReading2 && + SoundData.channels[channel].state != SOUND_SILENT) + { + return (SoundData.channels[channel].envx); + } + + return (0); +} + +#if 1 +void S9xSetSoundSample (int, uint16) +{ +} +#else +void S9xSetSoundSample (int channel, uint16 sample_number) +{ + register Channel *ch = &SoundData.channels[channel]; + + if (ch->state != SOUND_SILENT && + sample_number != ch->sample_number) + { + int keep = ch->state; + ch->state = SOUND_SILENT; + ch->sample_number = sample_number; + ch->loop = FALSE; + ch->needs_decode = TRUE; + ch->last_block = FALSE; + ch->previous [0] = ch->previous[1] = 0; + uint8 *dir = S9xGetSampleAddress (sample_number); + ch->block_pointer = READ_WORD (dir); + ch->sample_pointer = 0; + ch->state = keep; + } +} +#endif + +void S9xSetSoundFrequency (int channel, int hertz) +{ + if (so.playback_rate) + { + if (SoundData.channels[channel].type == SOUND_NOISE) + hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f]; + SoundData.channels[channel].frequency = (int) + (((int64) hertz * FIXED_POINT) / so.playback_rate); + if (Settings.FixFrequency) + { + SoundData.channels[channel].frequency = + (unsigned long) (SoundData.channels[channel].frequency * 49 / 50); + } + } +} + +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); +} + +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; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + +#if (defined (USE_X86_ASM) && (defined (__i386__) || defined (__i486__) ||\ + defined (__i586__) || defined (__WIN32__) || defined (__DJGPP))) + int16 *raw = ch->block = ch->decoded; + + 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; + unsigned int i; + + compressed++; + signed short *raw = ch->block = ch->decoded; + + 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; +} + +void AltDecodeBlock2 (Channel *ch) +{ + int32 out; + unsigned char filter; + unsigned char shift; + signed char sample1, sample2; + unsigned char 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; + if ((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; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + 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; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + 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; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + 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; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + 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; +} + +void DecodeBlock (Channel *ch) +{ + int32 out; + unsigned char filter; + unsigned char shift; + signed char sample1, sample2; + unsigned char i; + 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; + } + + if (Settings.EightBitConsoleSound) + { + signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; + + filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + + int16 interim[16]; + uint8 interim_byte = 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 = filter&0x0c; + + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; + + int16 amplitude = 0; + + for (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; + if (invalid_header) { sample1>>=3; sample2>>=3; } + + for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ + out=(((nybblesmp) ? sample2 : sample1) << shift); + out >>= 1; + + switch(filter) + { + case 0x00: + // Method0 - [Smp] + break; + + case 0x04: + // Method1 - [Delta]+[Smp-1](15/16) + out+=(prev0>>1)+((-prev0)>>5); + break; + + case 0x08: + // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) + out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); + break; + + default: + // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) + out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); + break; + + } + CLIP16(out); + int16 result = (signed short)(out<<1); + if (abs(result) > amplitude) + amplitude = abs(result); + interim[interim_byte++] = out; + prev1=(signed short)prev0; + prev0=(signed short)(out<<1); + } + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + + int32 total_deviation_from_previous = 0; + for (i = 1; i < 16; i++) + total_deviation_from_previous += abs(interim[i] - interim[i - 1]); + if (total_deviation_from_previous >= (int32) amplitude * 4) + { + /* Looks like noise. Generate noise. */ + for (i = 0; i < 16; i++) + { + int feedback = (noise_gen << 13) ^ (noise_gen << 14); + noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); + ch->decoded[i] = (noise_gen << 17) >> 17; + } + } + else if (interim[0] < interim[1] && interim[1] < interim[2] + && interim[2] < interim[3] + && interim[4] > interim[5] && interim[5] > interim[6] + && interim[6] > interim[7] && interim[7] > interim[8] + && interim[8] > interim[9] && interim[9] > interim[10] + && interim[10] > interim[11] + && interim[12] < interim[13] && interim[13] < interim[14] + && interim[14] < interim[15]) + { + /* Looks like a sine or triangle wave. Make it a + * triangle wave with an amplitude equivalent to that + * of the highest amplitude sample of the block. */ + ch->decoded[0] = ch->decoded[8] = 0; + ch->decoded[1] = ch->decoded[7] = amplitude / 4; + ch->decoded[2] = ch->decoded[6] = amplitude / 2; + ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4; + ch->decoded[4] = amplitude; + ch->decoded[9] = ch->decoded[15] = -(amplitude / 4); + ch->decoded[10] = ch->decoded[14] = -(amplitude / 2); + ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4); + ch->decoded[12] = -amplitude; + } + else if (interim[0] > interim[1] && interim[1] > interim[2] + && interim[2] > interim[3] + && interim[4] < interim[5] && interim[5] < interim[6] + && interim[6] < interim[7] && interim[7] < interim[8] + && interim[8] < interim[9] && interim[9] < interim[10] + && interim[10] < interim[11] + && interim[12] > interim[13] && interim[13] > interim[14] + && interim[14] > interim[15]) + { + /* Inverted triangle wave. */ + ch->decoded[0] = ch->decoded[8] = 0; + ch->decoded[1] = ch->decoded[7] = -(amplitude / 4); + ch->decoded[2] = ch->decoded[6] = -(amplitude / 2); + ch->decoded[3] = ch->decoded[5] = -(amplitude * 3 / 4); + ch->decoded[4] = -amplitude; + ch->decoded[9] = ch->decoded[15] = amplitude / 4; + ch->decoded[10] = ch->decoded[14] = amplitude / 2; + ch->decoded[11] = ch->decoded[13] = amplitude * 3 / 4; + ch->decoded[12] = amplitude; + } + else if (interim[0] < interim[1] && interim[1] < interim[2] + && interim[2] < interim[3] && interim[3] < interim[4] + && interim[4] < interim[5] && interim[5] < interim[6] + && interim[6] < interim[7] + && interim[8] > interim[9] && interim[9] > interim[10] + && interim[10] > interim[11] && interim[11] > interim[12] + && interim[12] > interim[13] && interim[13] > interim[14] + && interim[14] > interim[15]) + { + /* Looks like a V wave. Make it a half-triangle wave + * with an amplitude equivalent to that + * of the highest amplitude sample of the block. */ + ch->decoded[0] = 0; + ch->decoded[1] = ch->decoded[15] = amplitude / 8; + ch->decoded[2] = ch->decoded[14] = amplitude / 4; + ch->decoded[3] = ch->decoded[13] = amplitude * 3 / 8; + ch->decoded[4] = ch->decoded[12] = amplitude / 2; + ch->decoded[5] = ch->decoded[11] = amplitude * 5 / 8; + ch->decoded[6] = ch->decoded[10] = amplitude * 3 / 4; + ch->decoded[7] = ch->decoded[9] = amplitude * 7 / 8; + ch->decoded[8] = amplitude; + } + else if (interim[0] > interim[1] && interim[1] > interim[2] + && interim[2] > interim[3] && interim[3] > interim[4] + && interim[4] > interim[5] && interim[5] > interim[6] + && interim[6] > interim[7] + && interim[8] < interim[9] && interim[9] < interim[10] + && interim[10] < interim[11] && interim[11] < interim[12] + && interim[12] < interim[13] && interim[13] < interim[14] + && interim[14] < interim[15]) + { + /* Inverted V wave. */ + ch->decoded[0] = 0; + ch->decoded[1] = ch->decoded[15] = -(amplitude / 8); + ch->decoded[2] = ch->decoded[14] = -(amplitude / 4); + ch->decoded[3] = ch->decoded[13] = -(amplitude * 3 / 8); + ch->decoded[4] = ch->decoded[12] = -(amplitude / 2); + ch->decoded[5] = ch->decoded[11] = -(amplitude * 5 / 8); + ch->decoded[6] = ch->decoded[10] = -(amplitude * 3 / 4); + ch->decoded[7] = ch->decoded[9] = -(amplitude * 7 / 8); + ch->decoded[8] = -amplitude; + } + else + { + // Make it a square wave with an amplitude equivalent to that + // of the highest amplitude sample of the block. + // But actually put half of the amplitude, because + // square waves are just loud. + for (i = 0; i < 8; i++) + ch->decoded[i] = amplitude / 2; + for (i = 8; i < 16; i++) + ch->decoded[i] = -(amplitude / 2); + } + } + else + { + signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; + + filter = *compressed; + if ((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 = filter&0x0c; + + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; + + for (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; + if (invalid_header) { sample1>>=3; sample2>>=3; } + + for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ + out=(((nybblesmp) ? sample2 : sample1) << shift); + out >>= 1; + + switch(filter) + { + case 0x00: + // Method0 - [Smp] + break; + + case 0x04: + // Method1 - [Delta]+[Smp-1](15/16) + out+=(prev0>>1)+((-prev0)>>5); + break; + + case 0x08: + // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) + out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); + break; + + default: + // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) + out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); + break; + + } + CLIP16(out); + *raw++ = (signed short)(out<<1); + prev1=(signed short)prev0; + prev0=(signed short)(out<<1); + } + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + } + ch->block_pointer += 9; +} + +static inline void MixStereo (int sample_count) +{ + static int32 wave[SOUND_BUFFER_SIZE]; + + int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; + + for (uint32 J = 0; J < NUM_CHANNELS; J++) + { + Channel *ch = &SoundData.channels[J]; + + if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J))) + continue; + + int32 VL, VR; + unsigned long freq0 = ch->frequency; + + // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux + freq0 = freq0 * 985/1000; + + bool8 mod = pitch_mod & (1 << J); + + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; + if (ch->sample_pointer == 0) + ch->sample_pointer = 1; + if (ch->sample_pointer > SOUND_DECODE_LENGTH) + ch->sample_pointer = SOUND_DECODE_LENGTH - 1; + + ch->next_sample=ch->block[ch->sample_pointer]; + ch->interpolate = 0; + + if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod) + ch->interpolate = ((ch->next_sample - ch->sample) * + (long) freq0) / (long) FIXED_POINT; + } + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + + for (uint32 I = 0; I < (uint32) sample_count; I += 2) + { + unsigned long freq = freq0; + + if (mod) + freq = PITCH_MOD(freq, wave [I / 2]); + + ch->env_error += ch->erate; + if (ch->env_error >= FIXED_POINT) + { + uint32 step = ch->env_error >> FIXED_POINT_SHIFT; + + switch (ch->state) + { + case SOUND_ATTACK: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_DECAY; + if (ch->sustain_level != 8) + { + S9xSetEnvRate (ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) + >> 3); + break; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); + } + break; + + case SOUND_DECAY: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= ch->envx_target) + { + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); + } + break; + + case SOUND_SUSTAIN: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_RELEASE: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_INCREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0); + } + break; + + case SOUND_INCREASE_BENT_LINE: + if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) + { + while (ch->env_error >= FIXED_POINT) + { + ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + } + else + { + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + } + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0); + } + break; + + case SOUND_DECREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx -= step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_DECREASE_EXPONENTIAL: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_GAIN: + S9xSetEnvRate (ch, 0, -1, 0); + break; + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + + ch->count += freq; + if (ch->count >= FIXED_POINT) + { + VL = ch->count >> FIXED_POINT_SHIFT; + ch->sample_pointer += VL; + ch->count &= FIXED_POINT_REMAINDER; + + ch->sample = ch->next_sample; + if (ch->sample_pointer >= SOUND_DECODE_LENGTH) + { + if (JUST_PLAYED_LAST_SAMPLE(ch)) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + do + { + ch->sample_pointer -= SOUND_DECODE_LENGTH; + if (ch->last_block) + { + if (!ch->loop) + { + ch->sample_pointer = LAST_SAMPLE; + ch->next_sample = ch->sample; + break; + } + else + { + S9xAPUSetEndX (J); + ch->last_block = FALSE; + uint8 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = READ_WORD(dir + 2); + } + } + DecodeBlock (ch); + } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); + if (!JUST_PLAYED_LAST_SAMPLE (ch)) + ch->next_sample = ch->block [ch->sample_pointer]; + } + else + ch->next_sample = ch->block [ch->sample_pointer]; + + if (ch->type == SOUND_SAMPLE) + { + if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod) + { + ch->interpolate = ((ch->next_sample - ch->sample) * + (long) freq) / (long) FIXED_POINT; + ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) * + (long) (ch->count)) / (long) FIXED_POINT)); + } + else + ch->interpolate = 0; + } + else + { + // Snes9x 1.53's SPC_DSP.cpp, by blargg + int feedback = (noise_gen << 13) ^ (noise_gen << 14); + noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); + ch->sample = (noise_gen << 17) >> 17; + ch->interpolate = 0; + } + + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + else + { + if (ch->interpolate) + { + int32 s = (int32) ch->sample + ch->interpolate; + + CLIP16(s); + ch->sample = (int16) s; + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + } + + if (pitch_mod & (1 << (J + 1))) + wave [I / 2] = ch->sample * ch->envx; + + MixBuffer [I ] += VL; + MixBuffer [I + 1] += VR; + ch->echo_buf_ptr [I ] += VL; + ch->echo_buf_ptr [I + 1] += VR; + } +stereo_exit: ; + } +} + +#ifdef __DJGPP +END_OF_FUNCTION(MixStereo); +#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 J; + int I; + + if (!so.mute_sound) + { + if (SoundData.echo_enable) + memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer [0])); + memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); + MixStereo (sample_count); + } + + /* Mix and convert waveforms */ + int byte_count = sample_count << 1; + + // 16-bit sound + if (so.mute_sound) + { + memset (buffer, 0, byte_count); + } + else + { + if (SoundData.echo_enable && SoundData.echo_buffer_size) + { + // 16-bit stereo sound with echo enabled ... + if (FilterTapDefinitionBitfield == 0) + { + // ... but no filter defined. + for (J = 0; J < sample_count; J++) + { + int E = Echo [SoundData.echo_ptr]; + + Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + + EchoBuffer [J]; + + if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer [J] * + SoundData.master_volume [J & 1] + + E * SoundData.echo_volume [J & 1]) / VOL_DIV16; + + CLIP16(I); + ((signed short *) buffer)[J] = I; + } + } + else + { + // ... with filter defined. + for (J = 0; J < sample_count; J++) + { + int E = Echo [SoundData.echo_ptr]; + + Loop [(Z - 0) & 15] = E; + E = E * FilterTaps [0]; + if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1]; + if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2]; + if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3]; + if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4]; + if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5]; + if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6]; + if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7]; + E /= 128; + Z++; + + Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + + EchoBuffer [J]; + + if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer [J] * + SoundData.master_volume [J & 1] + + E * SoundData.echo_volume [J & 1]) / VOL_DIV16; + + CLIP16(I); + ((signed short *) 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]) / VOL_DIV16; + + CLIP16(I); + ((signed short *) buffer)[J] = I; + } + } + } +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xMixSamples); +#endif + +void S9xResetSound (bool8 full) +{ + for (int i = 0; i < 8; 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].count = 0; + SoundData.channels[i].loop = FALSE; + SoundData.channels[i].envx_target = 0; + SoundData.channels[i].env_error = 0; + SoundData.channels[i].erate = 0; + SoundData.channels[i].envx = 0; + SoundData.channels[i].envxx = 0; + SoundData.channels[i].left_vol_level = 0; + SoundData.channels[i].right_vol_level = 0; + SoundData.channels[i].direction = 0; + SoundData.channels[i].attack_rate = 0; + SoundData.channels[i].decay_rate = 0; + SoundData.channels[i].sustain_rate = 0; + SoundData.channels[i].release_rate = 0; + SoundData.channels[i].sustain_level = 0; + SoundData.echo_ptr = 0; + SoundData.echo_feedback = 0; + SoundData.echo_buffer_size = 1; + } + FilterTaps [0] = 127; + FilterTaps [1] = 0; + FilterTaps [2] = 0; + FilterTaps [3] = 0; + FilterTaps [4] = 0; + FilterTaps [5] = 0; + FilterTaps [6] = 0; + FilterTaps [7] = 0; + FilterTapDefinitionBitfield = 0; + so.mute_sound = TRUE; + noise_gen = 1; + so.sound_switch = 255; + so.samples_mixed_so_far = 0; + so.play_position = 0; + so.err_counter = 0; + + if (full) + { + SoundData.echo_enable = 0; + SoundData.echo_write_enabled = 0; + SoundData.echo_channel_enable = 0; + SoundData.pitch_mod = 0; + SoundData.dummy[0] = 0; + SoundData.dummy[1] = 0; + SoundData.dummy[2] = 0; + SoundData.master_volume[0] = 0; + SoundData.master_volume[1] = 0; + SoundData.echo_volume[0] = 0; + SoundData.echo_volume[1] = 0; + SoundData.noise_hertz = 0; + } + + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; + if (so.playback_rate) + so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME / (1.0 / so.playback_rate)); + else + so.err_rate = 0; +} + +void S9xSetPlaybackRate (uint32 playback_rate) +{ + so.playback_rate = playback_rate; + so.err_rate = (uint32) (SNES_SCANLINE_TIME * FIXED_POINT / (1.0 / (double) so.playback_rate)); + S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); + for (int i = 0; i < 8; i++) + S9xSetSoundFrequency (i, SoundData.channels [i].hertz); +} + +bool8 S9xInitSound (int mode, bool8 stereo, int buffer_size) +{ + so.sound_fd = -1; + so.sound_switch = 255; + + so.playback_rate = 0; + so.buffer_size = 0; + so.encoded = FALSE; + + S9xResetSound (TRUE); + + if (!(mode & 7)) + return (1); + + S9xSetSoundMute (TRUE); + if (!S9xOpenSoundDevice (mode, stereo, buffer_size)) + { + S9xMessage (S9X_ERROR, S9X_SOUND_DEVICE_OPEN_FAILED, + "Sound device open failed"); + 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->envx = 0; + ch->envxx = 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->env_error = 0; + ch->next_sample = 0; + ch->interpolate = 0; + switch (ch->mode) + { + case MODE_ADSR: + if (ch->attack_rate == 0) + { + if (ch->decay_rate == 0 || ch->sustain_level == 8) + { + ch->state = SOUND_SUSTAIN; + ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); + } + else + { + ch->state = SOUND_DECAY; + ch->envx = MAX_ENVELOPE_HEIGHT; + S9xSetEnvRate (ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3); + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + } + else + { + ch->state = SOUND_ATTACK; + ch->envx = 0; + ch->left_vol_level = 0; + ch->right_vol_level = 0; + S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT); + } + ch->envxx = ch->envx << ENVX_SHIFT; + break; + + 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/soundux.cpp b/source/soundux.cpp deleted file mode 100644 index 10e0130..0000000 --- a/source/soundux.cpp +++ /dev/null @@ -1,1714 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#ifdef __DJGPP__ -#include -#undef TRUE -#endif - -#include -#include -#include -#include -#include - -#define CLIP16(v) \ - if ((v) < -32768) \ - (v) = -32768; \ - else \ - if ((v) > 32767) \ -(v) = 32767 - -#define CLIP16_latch(v,l) \ - if ((v) < -32768) \ -{ (v) = -32768; (l)++; }\ - else \ - if ((v) > 32767) \ -{ (v) = 32767; (l)++; } - -#define CLIP24(v) \ - if ((v) < -8388608) \ - (v) = -8388608; \ - else \ - if ((v) > 8388607) \ -(v) = 8388607 - -#define CLIP8(v) \ - if ((v) < -128) \ - (v) = -128; \ - else \ - if ((v) > 127) \ -(v) = 127 - -#include "snes9x.h" -#include "soundux.h" -#include "apu.h" -#include "memmap.h" -#include "cpuexec.h" - -extern int32 Echo [24000]; -extern int32 DummyEchoBuffer [SOUND_BUFFER_SIZE]; -extern int32 MixBuffer [SOUND_BUFFER_SIZE]; -extern int32 EchoBuffer [SOUND_BUFFER_SIZE]; -extern int32 FilterTaps [8]; -static uint8 FilterTapDefinitionBitfield; -// In the above, bit I is set if FilterTaps[I] is non-zero. -extern unsigned long Z; -extern int32 Loop [16]; - -extern long FilterValues[4][2]; -extern int32 NoiseFreq [32]; - -static int32 noise_gen; - -#undef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) - -#define FIXED_POINT 0x10000UL -#define FIXED_POINT_REMAINDER 0xffffUL -#define FIXED_POINT_SHIFT 16 - -#define VOL_DIV8 0x8000 -#define VOL_DIV16 0x0080 -#define ENVX_SHIFT 24 - -extern "C" void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); -extern "C" void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); - -// F is channel's current frequency and M is the 16-bit modulation waveform -// from the previous channel multiplied by the current envelope volume level. -#define PITCH_MOD(F,M) ((F) * ((((unsigned long) (M)) + 0x800000) >> 16) >> 7) -//#define PITCH_MOD(F,M) ((F) * ((((M) & 0x7fffff) >> 14) + 1) >> 8) - -#define LAST_SAMPLE 0xffffff -#define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) - -void S9xSetEightBitConsoleSound (bool8 Enabled) -{ - if (Settings.EightBitConsoleSound != Enabled) - { - Settings.EightBitConsoleSound = Enabled; - int i; - for (i = 0; i < 8; i++) - { - SoundData.channels[i].needs_decode = TRUE; - } - } -} - -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; - 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 ch) -{ - APU.DSP [APU_ENDX] |= 1 << ch; -} -#ifdef __DJGPP -END_OF_FUNCTION (S9xAPUSetEndX) -#endif - -void S9xSetEnvRate (Channel *ch, unsigned long rate, int direction, int target) -{ - ch->envx_target = target; - - if (rate == ~0UL) - { - ch->direction = 0; - rate = 0; - } - else - ch->direction = direction; - - static int64 steps [] = - { - // 0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 - 0, - (int64) FIXED_POINT * 1000 * 64, - (int64) FIXED_POINT * 1000 * 619, - (int64) FIXED_POINT * 1000 * 619, - (int64) FIXED_POINT * 1000 * 128, - (int64) FIXED_POINT * 1000 * 1, - (int64) FIXED_POINT * 1000 * 64, - (int64) FIXED_POINT * 1000 * 55, - (int64) FIXED_POINT * 1000 * 64, - (int64) FIXED_POINT * 1000 * 619 - }; - - if (rate == 0 || so.playback_rate == 0) - ch->erate = 0; - else - { - ch->erate = (unsigned long) - (steps [ch->state] / (rate * so.playback_rate)); - } -} - -#ifdef __DJGPP -END_OF_FUNCTION(S9xSetEnvRate); -#endif - -void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, - int target) -{ - S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target); -} - -#ifdef __DJGPP -END_OF_FUNCTION(S9xSetEnvelopeRate); -#endif - -void S9xSetSoundVolume (int channel, short volume_left, short volume_right) -{ - Channel *ch = &SoundData.channels[channel]; - ch->volume_left = volume_left; - ch->volume_right = volume_right; - ch-> left_vol_level = (ch->envx * volume_left) / 128; - ch->right_vol_level = (ch->envx * volume_right) / 128; -} - -void S9xSetMasterVolume (short volume_left, short volume_right) -{ - if (Settings.DisableMasterVolume || SNESGameFixes.EchoOnlyOutput) - { - SoundData.master_volume [0] = SoundData.master_volume [1] = 127; - } - else - { - SoundData.master_volume [0] = volume_left; - SoundData.master_volume [1] = volume_right; - } -} - -void S9xSetEchoVolume (short volume_left, short volume_right) -{ - SoundData.echo_volume [0] = volume_left; - SoundData.echo_volume [1] = volume_right; -} - -void S9xSetEchoEnable (uint8 byte) -{ - SoundData.echo_channel_enable = byte; - if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho) - byte = 0; - if (byte && !SoundData.echo_enable) - { - memset (Echo, 0, sizeof (Echo)); - memset (Loop, 0, sizeof (Loop)); - } - - 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) -{ - CLIP8(feedback); - SoundData.echo_feedback = feedback; -} - -void S9xSetEchoDelay (int delay) -{ - SoundData.echo_buffer_size = (512 * delay * so.playback_rate) / 32000; - SoundData.echo_buffer_size <<= 1; - if (SoundData.echo_buffer_size) - SoundData.echo_ptr %= SoundData.echo_buffer_size; - else - SoundData.echo_ptr = 0; - S9xSetEchoEnable (APU.DSP [APU_EON]); -} - -void S9xSetEchoWriteEnable (uint8 byte) -{ - SoundData.echo_write_enabled = byte; - S9xSetEchoDelay (APU.DSP [APU_EDL] & 15); -} - -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, 8, -1, 0); - } -} - -void S9xFixSoundAfterSnapshotLoad () -{ - SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20); - SoundData.echo_channel_enable = APU.DSP [APU_EON]; - 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]); - for (int i = 0; i < 8; i++) - { - SoundData.channels[i].needs_decode = TRUE; - S9xSetSoundFrequency (i, SoundData.channels[i].hertz); - SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT; - SoundData.channels [i].next_sample = 0; - SoundData.channels [i].interpolate = 0; - SoundData.channels [i].previous [0] = (int32) SoundData.channels [i].previous16 [0]; - SoundData.channels [i].previous [1] = (int32) SoundData.channels [i].previous16 [1]; - } - IAPU.Scanline = 0; -} - -void S9xSetFilterCoefficient (int tap, int value) -{ - FilterTaps [tap & 7] = value; - if (value == 0 || (tap == 0 && value == 127)) - FilterTapDefinitionBitfield &= ~(1 << (tap & 7)); - else - FilterTapDefinitionBitfield |= 1 << (tap & 7); -} - -void S9xSetSoundADSR (int channel, int attack_rate, int decay_rate, - int sustain_rate, int sustain_level, int release_rate) -{ - Channel *ch = &SoundData.channels[channel]; - ch->attack_rate = attack_rate; - ch->decay_rate = decay_rate; - ch->sustain_rate = sustain_rate; - ch->release_rate = release_rate; - ch->sustain_level = sustain_level + 1; - - switch (SoundData.channels[channel].state) - { - case SOUND_ATTACK: - S9xSetEnvRate (ch, attack_rate, 1, 127); - break; - - case SOUND_DECAY: - S9xSetEnvRate (ch, decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3); - break; - case SOUND_SUSTAIN: - S9xSetEnvRate (ch, sustain_rate, -1, 0); - break; - } -} - -void S9xSetEnvelopeHeight (int channel, int level) -{ - Channel *ch = &SoundData.channels[channel]; - - ch->envx = level; - ch->envxx = level << ENVX_SHIFT; - - ch->left_vol_level = (level * ch->volume_left) / 128; - ch->right_vol_level = (level * ch->volume_right) / 128; - - if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) - { - S9xAPUSetEndOfSample (channel, ch); - } -} - -int S9xGetEnvelopeHeight (int channel) -{ - if ((Settings.SoundEnvelopeHeightReading || - SNESGameFixes.SoundEnvelopeHeightReading2) && - SoundData.channels[channel].state != SOUND_SILENT && - SoundData.channels[channel].state != SOUND_GAIN) - { - return (SoundData.channels[channel].envx); - } - - //siren fix from XPP - if (SNESGameFixes.SoundEnvelopeHeightReading2 && - SoundData.channels[channel].state != SOUND_SILENT) - { - return (SoundData.channels[channel].envx); - } - - return (0); -} - -#if 1 -void S9xSetSoundSample (int, uint16) -{ -} -#else -void S9xSetSoundSample (int channel, uint16 sample_number) -{ - register Channel *ch = &SoundData.channels[channel]; - - if (ch->state != SOUND_SILENT && - sample_number != ch->sample_number) - { - int keep = ch->state; - ch->state = SOUND_SILENT; - ch->sample_number = sample_number; - ch->loop = FALSE; - ch->needs_decode = TRUE; - ch->last_block = FALSE; - ch->previous [0] = ch->previous[1] = 0; - uint8 *dir = S9xGetSampleAddress (sample_number); - ch->block_pointer = READ_WORD (dir); - ch->sample_pointer = 0; - ch->state = keep; - } -} -#endif - -void S9xSetSoundFrequency (int channel, int hertz) -{ - if (so.playback_rate) - { - if (SoundData.channels[channel].type == SOUND_NOISE) - hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f]; - SoundData.channels[channel].frequency = (int) - (((int64) hertz * FIXED_POINT) / so.playback_rate); - if (Settings.FixFrequency) - { - SoundData.channels[channel].frequency = - (unsigned long) (SoundData.channels[channel].frequency * 49 / 50); - } - } -} - -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); -} - -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; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; - -#if (defined (USE_X86_ASM) && (defined (__i386__) || defined (__i486__) ||\ - defined (__i586__) || defined (__WIN32__) || defined (__DJGPP))) - int16 *raw = ch->block = ch->decoded; - - 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; - unsigned int i; - - compressed++; - signed short *raw = ch->block = ch->decoded; - - 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; -} - -void AltDecodeBlock2 (Channel *ch) -{ - int32 out; - unsigned char filter; - unsigned char shift; - signed char sample1, sample2; - unsigned char 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; - if ((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; - //Sample 2 = Bottom Nibble, Sign Extended. - sample2 >>= 4; - //Sample 1 = Top Nibble, shifted down and Sign Extended. - 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; - //Sample 2 = Bottom Nibble, Sign Extended. - sample2 >>= 4; - //Sample 1 = Top Nibble, shifted down and Sign Extended. - 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; - //Sample 2 = Bottom Nibble, Sign Extended. - sample2 >>= 4; - //Sample 1 = Top Nibble, shifted down and Sign Extended. - 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; - //Sample 2 = Bottom Nibble, Sign Extended. - sample2 >>= 4; - //Sample 1 = Top Nibble, shifted down and Sign Extended. - 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; -} - -void DecodeBlock (Channel *ch) -{ - int32 out; - unsigned char filter; - unsigned char shift; - signed char sample1, sample2; - unsigned char i; - 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; - } - - if (Settings.EightBitConsoleSound) - { - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - filter = *compressed; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; - - int16 interim[16]; - uint8 interim_byte = 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 = filter&0x0c; - - int32 prev0 = ch->previous [0]; - int32 prev1 = ch->previous [1]; - - int16 amplitude = 0; - - for (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; - if (invalid_header) { sample1>>=3; sample2>>=3; } - - for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ - out=(((nybblesmp) ? sample2 : sample1) << shift); - out >>= 1; - - switch(filter) - { - case 0x00: - // Method0 - [Smp] - break; - - case 0x04: - // Method1 - [Delta]+[Smp-1](15/16) - out+=(prev0>>1)+((-prev0)>>5); - break; - - case 0x08: - // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) - out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); - break; - - default: - // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) - out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); - break; - - } - CLIP16(out); - int16 result = (signed short)(out<<1); - if (abs(result) > amplitude) - amplitude = abs(result); - interim[interim_byte++] = out; - prev1=(signed short)prev0; - prev0=(signed short)(out<<1); - } - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - - int32 total_deviation_from_previous = 0; - for (i = 1; i < 16; i++) - total_deviation_from_previous += abs(interim[i] - interim[i - 1]); - if (total_deviation_from_previous >= (int32) amplitude * 4) - { - /* Looks like noise. Generate noise. */ - for (i = 0; i < 16; i++) - { - int feedback = (noise_gen << 13) ^ (noise_gen << 14); - noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); - ch->decoded[i] = (noise_gen << 17) >> 17; - } - } - else if (interim[0] < interim[1] && interim[1] < interim[2] - && interim[2] < interim[3] - && interim[4] > interim[5] && interim[5] > interim[6] - && interim[6] > interim[7] && interim[7] > interim[8] - && interim[8] > interim[9] && interim[9] > interim[10] - && interim[10] > interim[11] - && interim[12] < interim[13] && interim[13] < interim[14] - && interim[14] < interim[15]) - { - /* Looks like a sine or triangle wave. Make it a - * triangle wave with an amplitude equivalent to that - * of the highest amplitude sample of the block. */ - ch->decoded[0] = ch->decoded[8] = 0; - ch->decoded[1] = ch->decoded[7] = amplitude / 4; - ch->decoded[2] = ch->decoded[6] = amplitude / 2; - ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4; - ch->decoded[4] = amplitude; - ch->decoded[9] = ch->decoded[15] = -(amplitude / 4); - ch->decoded[10] = ch->decoded[14] = -(amplitude / 2); - ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4); - ch->decoded[12] = -amplitude; - } - else if (interim[0] > interim[1] && interim[1] > interim[2] - && interim[2] > interim[3] - && interim[4] < interim[5] && interim[5] < interim[6] - && interim[6] < interim[7] && interim[7] < interim[8] - && interim[8] < interim[9] && interim[9] < interim[10] - && interim[10] < interim[11] - && interim[12] > interim[13] && interim[13] > interim[14] - && interim[14] > interim[15]) - { - /* Inverted triangle wave. */ - ch->decoded[0] = ch->decoded[8] = 0; - ch->decoded[1] = ch->decoded[7] = -(amplitude / 4); - ch->decoded[2] = ch->decoded[6] = -(amplitude / 2); - ch->decoded[3] = ch->decoded[5] = -(amplitude * 3 / 4); - ch->decoded[4] = -amplitude; - ch->decoded[9] = ch->decoded[15] = amplitude / 4; - ch->decoded[10] = ch->decoded[14] = amplitude / 2; - ch->decoded[11] = ch->decoded[13] = amplitude * 3 / 4; - ch->decoded[12] = amplitude; - } - else if (interim[0] < interim[1] && interim[1] < interim[2] - && interim[2] < interim[3] && interim[3] < interim[4] - && interim[4] < interim[5] && interim[5] < interim[6] - && interim[6] < interim[7] - && interim[8] > interim[9] && interim[9] > interim[10] - && interim[10] > interim[11] && interim[11] > interim[12] - && interim[12] > interim[13] && interim[13] > interim[14] - && interim[14] > interim[15]) - { - /* Looks like a V wave. Make it a half-triangle wave - * with an amplitude equivalent to that - * of the highest amplitude sample of the block. */ - ch->decoded[0] = 0; - ch->decoded[1] = ch->decoded[15] = amplitude / 8; - ch->decoded[2] = ch->decoded[14] = amplitude / 4; - ch->decoded[3] = ch->decoded[13] = amplitude * 3 / 8; - ch->decoded[4] = ch->decoded[12] = amplitude / 2; - ch->decoded[5] = ch->decoded[11] = amplitude * 5 / 8; - ch->decoded[6] = ch->decoded[10] = amplitude * 3 / 4; - ch->decoded[7] = ch->decoded[9] = amplitude * 7 / 8; - ch->decoded[8] = amplitude; - } - else if (interim[0] > interim[1] && interim[1] > interim[2] - && interim[2] > interim[3] && interim[3] > interim[4] - && interim[4] > interim[5] && interim[5] > interim[6] - && interim[6] > interim[7] - && interim[8] < interim[9] && interim[9] < interim[10] - && interim[10] < interim[11] && interim[11] < interim[12] - && interim[12] < interim[13] && interim[13] < interim[14] - && interim[14] < interim[15]) - { - /* Inverted V wave. */ - ch->decoded[0] = 0; - ch->decoded[1] = ch->decoded[15] = -(amplitude / 8); - ch->decoded[2] = ch->decoded[14] = -(amplitude / 4); - ch->decoded[3] = ch->decoded[13] = -(amplitude * 3 / 8); - ch->decoded[4] = ch->decoded[12] = -(amplitude / 2); - ch->decoded[5] = ch->decoded[11] = -(amplitude * 5 / 8); - ch->decoded[6] = ch->decoded[10] = -(amplitude * 3 / 4); - ch->decoded[7] = ch->decoded[9] = -(amplitude * 7 / 8); - ch->decoded[8] = -amplitude; - } - else - { - // Make it a square wave with an amplitude equivalent to that - // of the highest amplitude sample of the block. - // But actually put half of the amplitude, because - // square waves are just loud. - for (i = 0; i < 8; i++) - ch->decoded[i] = amplitude / 2; - for (i = 8; i < 16; i++) - ch->decoded[i] = -(amplitude / 2); - } - } - else - { - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - filter = *compressed; - if ((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 = filter&0x0c; - - int32 prev0 = ch->previous [0]; - int32 prev1 = ch->previous [1]; - - for (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; - if (invalid_header) { sample1>>=3; sample2>>=3; } - - for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ - out=(((nybblesmp) ? sample2 : sample1) << shift); - out >>= 1; - - switch(filter) - { - case 0x00: - // Method0 - [Smp] - break; - - case 0x04: - // Method1 - [Delta]+[Smp-1](15/16) - out+=(prev0>>1)+((-prev0)>>5); - break; - - case 0x08: - // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) - out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); - break; - - default: - // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) - out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); - break; - - } - CLIP16(out); - *raw++ = (signed short)(out<<1); - prev1=(signed short)prev0; - prev0=(signed short)(out<<1); - } - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - } - ch->block_pointer += 9; -} - -static inline void MixStereo (int sample_count) -{ - static int32 wave[SOUND_BUFFER_SIZE]; - - int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; - - for (uint32 J = 0; J < NUM_CHANNELS; J++) - { - Channel *ch = &SoundData.channels[J]; - - if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J))) - continue; - - int32 VL, VR; - unsigned long freq0 = ch->frequency; - - // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux - freq0 = freq0 * 985/1000; - - bool8 mod = pitch_mod & (1 << J); - - if (ch->needs_decode) - { - DecodeBlock(ch); - ch->needs_decode = FALSE; - ch->sample = ch->block[0]; - ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; - if (ch->sample_pointer == 0) - ch->sample_pointer = 1; - if (ch->sample_pointer > SOUND_DECODE_LENGTH) - ch->sample_pointer = SOUND_DECODE_LENGTH - 1; - - ch->next_sample=ch->block[ch->sample_pointer]; - ch->interpolate = 0; - - if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod) - ch->interpolate = ((ch->next_sample - ch->sample) * - (long) freq0) / (long) FIXED_POINT; - } - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - - for (uint32 I = 0; I < (uint32) sample_count; I += 2) - { - unsigned long freq = freq0; - - if (mod) - freq = PITCH_MOD(freq, wave [I / 2]); - - ch->env_error += ch->erate; - if (ch->env_error >= FIXED_POINT) - { - uint32 step = ch->env_error >> FIXED_POINT_SHIFT; - - switch (ch->state) - { - case SOUND_ATTACK: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_DECAY; - if (ch->sustain_level != 8) - { - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) - >> 3); - break; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - break; - - case SOUND_DECAY: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= ch->envx_target) - { - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - break; - - case SOUND_SUSTAIN: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_RELEASE: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_INCREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0); - } - break; - - case SOUND_INCREASE_BENT_LINE: - if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) - { - while (ch->env_error >= FIXED_POINT) - { - ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - } - else - { - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - } - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0); - } - break; - - case SOUND_DECREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx -= step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_DECREASE_EXPONENTIAL: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_GAIN: - S9xSetEnvRate (ch, 0, -1, 0); - break; - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - - ch->count += freq; - if (ch->count >= FIXED_POINT) - { - VL = ch->count >> FIXED_POINT_SHIFT; - ch->sample_pointer += VL; - ch->count &= FIXED_POINT_REMAINDER; - - ch->sample = ch->next_sample; - if (ch->sample_pointer >= SOUND_DECODE_LENGTH) - { - if (JUST_PLAYED_LAST_SAMPLE(ch)) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - do - { - ch->sample_pointer -= SOUND_DECODE_LENGTH; - if (ch->last_block) - { - if (!ch->loop) - { - ch->sample_pointer = LAST_SAMPLE; - ch->next_sample = ch->sample; - break; - } - else - { - S9xAPUSetEndX (J); - ch->last_block = FALSE; - uint8 *dir = S9xGetSampleAddress (ch->sample_number); - ch->block_pointer = READ_WORD(dir + 2); - } - } - DecodeBlock (ch); - } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); - if (!JUST_PLAYED_LAST_SAMPLE (ch)) - ch->next_sample = ch->block [ch->sample_pointer]; - } - else - ch->next_sample = ch->block [ch->sample_pointer]; - - if (ch->type == SOUND_SAMPLE) - { - if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod) - { - ch->interpolate = ((ch->next_sample - ch->sample) * - (long) freq) / (long) FIXED_POINT; - ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) * - (long) (ch->count)) / (long) FIXED_POINT)); - } - else - ch->interpolate = 0; - } - else - { - // Snes9x 1.53's SPC_DSP.cpp, by blargg - int feedback = (noise_gen << 13) ^ (noise_gen << 14); - noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); - ch->sample = (noise_gen << 17) >> 17; - ch->interpolate = 0; - } - - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - else - { - if (ch->interpolate) - { - int32 s = (int32) ch->sample + ch->interpolate; - - CLIP16(s); - ch->sample = (int16) s; - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - } - - if (pitch_mod & (1 << (J + 1))) - wave [I / 2] = ch->sample * ch->envx; - - MixBuffer [I ] += VL; - MixBuffer [I + 1] += VR; - ch->echo_buf_ptr [I ] += VL; - ch->echo_buf_ptr [I + 1] += VR; - } -stereo_exit: ; - } -} - -#ifdef __DJGPP -END_OF_FUNCTION(MixStereo); -#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 J; - int I; - - if (!so.mute_sound) - { - if (SoundData.echo_enable) - memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer [0])); - memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); - MixStereo (sample_count); - } - - /* Mix and convert waveforms */ - int byte_count = sample_count << 1; - - // 16-bit sound - if (so.mute_sound) - { - memset (buffer, 0, byte_count); - } - else - { - if (SoundData.echo_enable && SoundData.echo_buffer_size) - { - // 16-bit stereo sound with echo enabled ... - if (FilterTapDefinitionBitfield == 0) - { - // ... but no filter defined. - for (J = 0; J < sample_count; J++) - { - int E = Echo [SoundData.echo_ptr]; - - Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + - EchoBuffer [J]; - - if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - I = (MixBuffer [J] * - SoundData.master_volume [J & 1] + - E * SoundData.echo_volume [J & 1]) / VOL_DIV16; - - CLIP16(I); - ((signed short *) buffer)[J] = I; - } - } - else - { - // ... with filter defined. - for (J = 0; J < sample_count; J++) - { - int E = Echo [SoundData.echo_ptr]; - - Loop [(Z - 0) & 15] = E; - E = E * FilterTaps [0]; - if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1]; - if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2]; - if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3]; - if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4]; - if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5]; - if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6]; - if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7]; - E /= 128; - Z++; - - Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + - EchoBuffer [J]; - - if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - I = (MixBuffer [J] * - SoundData.master_volume [J & 1] + - E * SoundData.echo_volume [J & 1]) / VOL_DIV16; - - CLIP16(I); - ((signed short *) 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]) / VOL_DIV16; - - CLIP16(I); - ((signed short *) buffer)[J] = I; - } - } - } -} - -#ifdef __DJGPP -END_OF_FUNCTION(S9xMixSamples); -#endif - -void S9xResetSound (bool8 full) -{ - for (int i = 0; i < 8; 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].count = 0; - SoundData.channels[i].loop = FALSE; - SoundData.channels[i].envx_target = 0; - SoundData.channels[i].env_error = 0; - SoundData.channels[i].erate = 0; - SoundData.channels[i].envx = 0; - SoundData.channels[i].envxx = 0; - SoundData.channels[i].left_vol_level = 0; - SoundData.channels[i].right_vol_level = 0; - SoundData.channels[i].direction = 0; - SoundData.channels[i].attack_rate = 0; - SoundData.channels[i].decay_rate = 0; - SoundData.channels[i].sustain_rate = 0; - SoundData.channels[i].release_rate = 0; - SoundData.channels[i].sustain_level = 0; - SoundData.echo_ptr = 0; - SoundData.echo_feedback = 0; - SoundData.echo_buffer_size = 1; - } - FilterTaps [0] = 127; - FilterTaps [1] = 0; - FilterTaps [2] = 0; - FilterTaps [3] = 0; - FilterTaps [4] = 0; - FilterTaps [5] = 0; - FilterTaps [6] = 0; - FilterTaps [7] = 0; - FilterTapDefinitionBitfield = 0; - so.mute_sound = TRUE; - noise_gen = 1; - so.sound_switch = 255; - so.samples_mixed_so_far = 0; - so.play_position = 0; - so.err_counter = 0; - - if (full) - { - SoundData.echo_enable = 0; - SoundData.echo_write_enabled = 0; - SoundData.echo_channel_enable = 0; - SoundData.pitch_mod = 0; - SoundData.dummy[0] = 0; - SoundData.dummy[1] = 0; - SoundData.dummy[2] = 0; - SoundData.master_volume[0] = 0; - SoundData.master_volume[1] = 0; - SoundData.echo_volume[0] = 0; - SoundData.echo_volume[1] = 0; - SoundData.noise_hertz = 0; - } - - SoundData.master_volume [0] = SoundData.master_volume [1] = 127; - if (so.playback_rate) - so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME / (1.0 / so.playback_rate)); - else - so.err_rate = 0; -} - -void S9xSetPlaybackRate (uint32 playback_rate) -{ - so.playback_rate = playback_rate; - so.err_rate = (uint32) (SNES_SCANLINE_TIME * FIXED_POINT / (1.0 / (double) so.playback_rate)); - S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); - for (int i = 0; i < 8; i++) - S9xSetSoundFrequency (i, SoundData.channels [i].hertz); -} - -bool8 S9xInitSound (int mode, bool8 stereo, int buffer_size) -{ - so.sound_fd = -1; - so.sound_switch = 255; - - so.playback_rate = 0; - so.buffer_size = 0; - so.encoded = FALSE; - - S9xResetSound (TRUE); - - if (!(mode & 7)) - return (1); - - S9xSetSoundMute (TRUE); - if (!S9xOpenSoundDevice (mode, stereo, buffer_size)) - { - S9xMessage (S9X_ERROR, S9X_SOUND_DEVICE_OPEN_FAILED, - "Sound device open failed"); - 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->envx = 0; - ch->envxx = 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->env_error = 0; - ch->next_sample = 0; - ch->interpolate = 0; - switch (ch->mode) - { - case MODE_ADSR: - if (ch->attack_rate == 0) - { - if (ch->decay_rate == 0 || ch->sustain_level == 8) - { - ch->state = SOUND_SUSTAIN; - ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - else - { - ch->state = SOUND_DECAY; - ch->envx = MAX_ENVELOPE_HEIGHT; - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3); - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - } - else - { - ch->state = SOUND_ATTACK; - ch->envx = 0; - ch->left_vol_level = 0; - ch->right_vol_level = 0; - S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT); - } - ch->envxx = ch->envx << ENVX_SHIFT; - break; - - 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/spc700.c b/source/spc700.c new file mode 100644 index 0000000..3bfeeac --- /dev/null +++ b/source/spc700.c @@ -0,0 +1,2548 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#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 + +#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) \ + APU.Cycles = CPU.Cycles = CPU.NextEvent; \ + 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 STOP (char *s) +{ + char buffer[100]; + + buffer[0] = '\0'; + + sprintf (String, "Sound CPU in unknown state executing %s at %04X\n%s\n", s, IAPU.PC - IAPU.RAM, buffer); + S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String); + APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; + IAPU.APUExecuting = FALSE; + + S9xExit (); +} + +#define TCALL(n)\ +{\ + PushW (IAPU.PC - IAPU.RAM + 1); \ + IAPU.PC = IAPU.RAM + (APU.ExtraRAM [((15 - n) << 1)] + \ + (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \ +} + +// XXX: HalfCarry - BJ fixed? +#define SBC(a,b)\ +int16 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); + +// XXX: HalfCarry - BJ fixed? +// XXX: HalfCarry used Int16 before; trying to fix it with Work16 [Neb] +#define ADC(a,b)\ +uint16 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 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)\ + uint16 Work16 = ((b) << 1) | APUCheckCarry (); \ + IAPU._Carry = Work16 >= 0x100; \ + (b) = (uint8) Work16; \ + APUSetZN8 (b); +#define ROR(b)\ + uint16 Work16 = (b) | ((uint16) APUCheckCarry () << 8); \ + IAPU._Carry = (uint8) Work16 & 1; \ + Work16 >>= 1; \ + (b) = (uint8) Work16; \ + APUSetZN8 (b); + +#define Push(b)\ + *(IAPU.RAM + 0x100 + IAPU.Registers.S) = b;\ + IAPU.Registers.S--; + +#define Pop(b)\ + IAPU.Registers.S++;\ + (b) = *(IAPU.RAM + 0x100 + IAPU.Registers.S); + +#ifdef FAST_LSB_WORD_ACCESS +#define PushW(w)\ + *(uint16 *) (IAPU.RAM + 0xff + IAPU.Registers.S) = w;\ + IAPU.Registers.S -= 2; +#define PopW(w)\ + IAPU.Registers.S += 2;\ + w = *(uint16 *) (IAPU.RAM + 0xff + IAPU.Registers.S); +#else +#define PushW(w)\ + *(IAPU.RAM + 0xff + IAPU.Registers.S) = w;\ + *(IAPU.RAM + 0x100 + IAPU.Registers.S) = (w >> 8);\ + IAPU.Registers.S -= 2; +#define PopW(w)\ + IAPU.Registers.S += 2; \ + (w) = *(IAPU.RAM + 0xff + IAPU.Registers.S) + (*(IAPU.RAM + 0x100 + IAPU.Registers.S) << 8); +#endif + +#define Relative()\ + int8 Int8 = OP1;\ + int16 Int16 = (intptr_t) (IAPU.PC + 2 - IAPU.RAM) + Int8; + +#define Relative2()\ + int8 Int8 = OP2;\ + int16 Int16 = (intptr_t) (IAPU.PC + 3 - IAPU.RAM) + Int8; + +#ifdef FAST_LSB_WORD_ACCESS +#define IndexedXIndirect()\ + IAPU.Address = *(uint16 *) (IAPU.DirectPage + ((OP1 + IAPU.Registers.X) & 0xff)); + +#define Absolute()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1); + +#define AbsoluteX()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.Registers.X; + +#define AbsoluteY()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.Registers.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) + IAPU.Registers.YA.B.Y; +#else +#define IndexedXIndirect()\ + IAPU.Address = *(IAPU.DirectPage + ((OP1 + IAPU.Registers.X) & 0xff)) + \ + (*(IAPU.DirectPage + ((OP1 + IAPU.Registers.X + 1) & 0xff)) << 8); +#define Absolute()\ + IAPU.Address = OP1 + (OP2 << 8); + +#define AbsoluteX()\ + IAPU.Address = OP1 + (OP2 << 8) + IAPU.Registers.X; + +#define AbsoluteY()\ + IAPU.Address = OP1 + (OP2 << 8) + IAPU.Registers.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) + \ + IAPU.Registers.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 +{ + uint8 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) \ +uint8 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) \ +uint8 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 + IAPU.Registers.YA.B.A |= S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu05 () +{ +// OR A,abs + Absolute (); + IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu06 () +{ +// OR A,(X) + IAPU.Registers.YA.B.A |= S9xAPUGetByteZ (IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu07 () +{ +// OR A,(dp+X) + IndexedXIndirect (); + IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu08 () +{ +// OR A,#00 + IAPU.Registers.YA.B.A |= OP1; + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu09 () +{ +// OR dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + Work8 |= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu14 () +{ +// OR A,dp+X + IAPU.Registers.YA.B.A |= S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu15 () +{ +// OR A,abs+X + AbsoluteX (); + IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu16 () +{ +// OR A,abs+Y + AbsoluteY (); + IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu17 () +{ +// OR A,(dp)+Y + IndirectIndexedY (); + IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu18 () +{ +// OR dp,#00 + uint8 Work8 = OP1; + Work8 |= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu19 () +{ +// OR (X),(Y) + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X) | S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, IAPU.Registers.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 + uint8 Work8 = S9xAPUGetByteZ (OP1); + ASL (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu0C () +{ +// ASL abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ASL (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu1B () +{ +// ASL dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + ASL (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); + IAPU.PC += 2; +} + +void Apu1C () +{ +// ASL A + ASL (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu0D () +{ +// PUSH PSW + S9xAPUPackStatus (); + Push (IAPU.Registers.P); + IAPU.PC++; +} + +void Apu2D () +{ +// PUSH A + Push (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu4D () +{ +// PUSH X + Push (IAPU.Registers.X); + IAPU.PC++; +} + +void Apu6D () +{ +// PUSH Y + Push (IAPU.Registers.YA.B.Y); + IAPU.PC++; +} + +void Apu8E () +{ +// POP PSW + Pop (IAPU.Registers.P); + S9xAPUUnpackStatus (); + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + IAPU.PC++; +} + +void ApuAE () +{ +// POP A + Pop (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuCE () +{ +// POP X + Pop (IAPU.Registers.X); + IAPU.PC++; +} + +void ApuEE () +{ +// POP Y + Pop (IAPU.Registers.YA.B.Y); + IAPU.PC++; +} + +void Apu0E () +{ +// TSET1 abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + S9xAPUSetByte (Work8 | IAPU.Registers.YA.B.A, IAPU.Address); + Work8 &= IAPU.Registers.YA.B.A; + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu4E () +{ +// TCLR1 abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + S9xAPUSetByte (Work8 & ~IAPU.Registers.YA.B.A, IAPU.Address); + Work8 &= IAPU.Registers.YA.B.A; + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu0F () +{ +// BRK + +#if 0 + STOP ("BRK"); +#else + PushW (IAPU.PC + 1 - IAPU.RAM); + S9xAPUPackStatus (); + Push (IAPU.Registers.P); + APUSetBreak (); + APUClearInterrupt (); +// XXX:Where is the BRK vector ??? + IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8); +#endif +} + +void ApuEF () +{ +// SLEEP + // XXX: sleep + // STOP ("SLEEP"); + IAPU.APUExecuting = FALSE; + IAPU.PC++; +} + +void ApuFF () +{ +// STOP + // STOP ("STOP"); + IAPU.APUExecuting = FALSE; + IAPU.PC++; +} + +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 + uint16 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 + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + int32 Int32 = (long) IAPU.Registers.YA.W - (long) Work16; + IAPU._Carry = Int32 >= 0; + APUSetZN16 ((uint16) Int32); + IAPU.PC += 2; +} + +void Apu3A () +{ +// INCW dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Work16++; + S9xAPUSetByteZ ((uint8) Work16, OP1); + S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); + APUSetZN16 (Work16); + IAPU.PC += 2; +} + +// XXX: HalfCarry - BJ Fixed? Or is it between bits 7 and 8 for ADDW/SUBW? +void Apu7A () +{ +// ADDW YA,dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + uint32 Work32 = (uint32) IAPU.Registers.YA.W + Work16; + IAPU._Carry = Work32 >= 0x10000; + if (~(IAPU.Registers.YA.W ^ Work16) & (Work16 ^ (uint16) Work32) & 0x8000) + APUSetOverflow (); + else + APUClearOverflow (); + APUClearHalfCarry (); + if((IAPU.Registers.YA.W ^ Work16 ^ (uint16) Work32) & 0x10) + APUSetHalfCarry (); + IAPU.Registers.YA.W = (uint16) Work32; + APUSetZN16 (IAPU.Registers.YA.W); + IAPU.PC += 2; +} + +// XXX: BJ: i think the old HalfCarry behavior was wrong... +// XXX: Or is it between bits 7 and 8 for ADDW/SUBW? +// XXX: Used Work32 instead of Int32 before. Fixed? [Neb] +void Apu9A () +{ +// SUBW YA,dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + int32 Int32 = (long) IAPU.Registers.YA.W - (long) Work16; + APUClearHalfCarry (); + IAPU._Carry = Int32 >= 0; + if (((IAPU.Registers.YA.W ^ Work16) & 0x8000) && + ((IAPU.Registers.YA.W ^ (uint16) Int32) & 0x8000)) + APUSetOverflow (); + else + APUClearOverflow (); + if (((IAPU.Registers.YA.W ^ Work16) & 0x0080) && + ((IAPU.Registers.YA.W ^ (uint16) Int32) & 0x0080)) + APUSetHalfCarry (); + APUSetHalfCarry (); + if((IAPU.Registers.YA.W ^ Work16 ^ (uint16) Int32) & 0x10) + APUClearHalfCarry (); + IAPU.Registers.YA.W = (uint16) Int32; + APUSetZN16 (IAPU.Registers.YA.W); + IAPU.PC += 2; +} + +void ApuBA () +{ +// MOVW YA,dp + IAPU.Registers.YA.B.A = S9xAPUGetByteZ (OP1); + IAPU.Registers.YA.B.Y = S9xAPUGetByteZ (OP1 + 1); + APUSetZN16 (IAPU.Registers.YA.W); + IAPU.PC += 2; +} + +void ApuDA () +{ +// MOVW dp,YA + S9xAPUSetByteZ (IAPU.Registers.YA.B.A, OP1); + S9xAPUSetByteZ (IAPU.Registers.YA.B.Y, OP1 + 1); + IAPU.PC += 2; +} + +void Apu64 () +{ +// CMP A,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu65 () +{ +// CMP A,abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu66 () +{ +// CMP A,(X) + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC++; +} + +void Apu67 () +{ +// CMP A,(dp+X) + IndexedXIndirect (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu68 () +{ +// CMP A,#00 + uint8 Work8 = OP1; + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu69 () +{ +// CMP dp(dest), dp(src) + uint8 W1 = S9xAPUGetByteZ (OP1); + uint8 Work8 = S9xAPUGetByteZ (OP2); + CMP (Work8, W1); + IAPU.PC += 3; +} + +void Apu74 () +{ +// CMP A, dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu75 () +{ +// CMP A,abs+X + AbsoluteX (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu76 () +{ +// CMP A, abs+Y + AbsoluteY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu77 () +{ +// CMP A,(dp)+Y + IndirectIndexedY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu78 () +{ +// CMP dp,#00 + uint8 Work8 = OP1; + uint8 W1 = S9xAPUGetByteZ (OP2); + CMP (W1, Work8); + IAPU.PC += 3; +} + +void Apu79 () +{ +// CMP (X),(Y) + uint8 W1 = S9xAPUGetByteZ (IAPU.Registers.X); + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); + CMP (W1, Work8); + IAPU.PC++; +} + +void Apu1E () +{ +// CMP X,abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.X, Work8); + IAPU.PC += 3; +} + +void Apu3E () +{ +// CMP X,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + CMP (IAPU.Registers.X, Work8); + IAPU.PC += 2; +} + +void ApuC8 () +{ +// CMP X,#00 + CMP (IAPU.Registers.X, OP1); + IAPU.PC += 2; +} + +void Apu5E () +{ +// CMP Y,abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.Registers.YA.B.Y, Work8); + IAPU.PC += 3; +} + +void Apu7E () +{ +// CMP Y,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + CMP (IAPU.Registers.YA.B.Y, Work8); + IAPU.PC += 2; +} + +void ApuAD () +{ +// CMP Y,#00 + uint8 Work8 = OP1; + CMP (IAPU.Registers.YA.B.Y, Work8); + IAPU.PC += 2; +} + +void Apu1F () +{ +// JMP (abs+X) + Absolute (); + IAPU.PC = IAPU.RAM + S9xAPUGetByte (IAPU.Address + IAPU.Registers.X) + + (S9xAPUGetByte (IAPU.Address + IAPU.Registers.X + 1) << 8); +// XXX: HERE: + // APU.Flags |= TRACE_FLAG; +} + +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 + IAPU.Registers.YA.B.A &= S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu25 () +{ +// AND A,abs + Absolute (); + IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu26 () +{ +// AND A,(X) + IAPU.Registers.YA.B.A &= S9xAPUGetByteZ (IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu27 () +{ +// AND A,(dp+X) + IndexedXIndirect (); + IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu28 () +{ +// AND A,#00 + IAPU.Registers.YA.B.A &= OP1; + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu29 () +{ +// AND dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + Work8 &= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu34 () +{ +// AND A,dp+X + IAPU.Registers.YA.B.A &= S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu35 () +{ +// AND A,abs+X + AbsoluteX (); + IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu36 () +{ +// AND A,abs+Y + AbsoluteY (); + IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu37 () +{ +// AND A,(dp)+Y + IndirectIndexedY (); + IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu38 () +{ +// AND dp,#00 + uint8 Work8 = OP1; + Work8 &= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu39 () +{ +// AND (X),(Y) + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X) & S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, IAPU.Registers.X); + IAPU.PC++; +} + +void Apu2B () +{ +// ROL dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ROL (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu2C () +{ +// ROL abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ROL (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu3B () +{ +// ROL dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + ROL (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); + IAPU.PC += 2; +} + +void Apu3C () +{ +// ROL A + ROL (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu2E () +{ +// CBNE dp,rel + uint8 Work8 = OP1; + Relative2 (); + + if (S9xAPUGetByteZ (Work8) != IAPU.Registers.YA.B.A) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 3; +} + +void ApuDE () +{ +// CBNE dp+X,rel + uint8 Work8 = OP1 + IAPU.Registers.X; + Relative2 (); + + if (S9xAPUGetByteZ (Work8) != IAPU.Registers.YA.B.A) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 3; +} + +void Apu3D () +{ +// INC X + IAPU.Registers.X++; + APUSetZN8 (IAPU.Registers.X); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuFC () +{ +// INC Y + IAPU.Registers.YA.B.Y++; + APUSetZN8 (IAPU.Registers.YA.B.Y); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu1D () +{ +// DEC X + IAPU.Registers.X--; + APUSetZN8 (IAPU.Registers.X); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuDC () +{ +// DEC Y + IAPU.Registers.YA.B.Y--; + APUSetZN8 (IAPU.Registers.YA.B.Y); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuAB () +{ +// INC dp + uint8 Work8 = S9xAPUGetByteZ (OP1) + 1; + S9xAPUSetByteZ (Work8, OP1); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void ApuAC () +{ +// INC abs + Absolute (); + uint8 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 + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X) + 1; + S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void ApuBC () +{ +// INC A + IAPU.Registers.YA.B.A++; + APUSetZN8 (IAPU.Registers.YA.B.A); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu8B () +{ +// DEC dp + uint8 Work8 = S9xAPUGetByteZ (OP1) - 1; + S9xAPUSetByteZ (Work8, OP1); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void Apu8C () +{ +// DEC abs + Absolute (); + uint8 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 + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X) - 1; + S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void Apu9C () +{ +// DEC A + IAPU.Registers.YA.B.A--; + APUSetZN8 (IAPU.Registers.YA.B.A); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu44 () +{ +// EOR A,dp + IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu45 () +{ +// EOR A,abs + Absolute (); + IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu46 () +{ +// EOR A,(X) + IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ (IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu47 () +{ +// EOR A,(dp+X) + IndexedXIndirect (); + IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu48 () +{ +// EOR A,#00 + IAPU.Registers.YA.B.A ^= OP1; + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu49 () +{ +// EOR dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + Work8 ^= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu54 () +{ +// EOR A,dp+X + IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu55 () +{ +// EOR A,abs+X + AbsoluteX (); + IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu56 () +{ +// EOR A,abs+Y + AbsoluteY (); + IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void Apu57 () +{ +// EOR A,(dp)+Y + IndirectIndexedY (); + IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void Apu58 () +{ +// EOR dp,#00 + uint8 Work8 = OP1; + Work8 ^= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu59 () +{ +// EOR (X),(Y) + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X) ^ S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, IAPU.Registers.X); + IAPU.PC++; +} + +void Apu4B () +{ +// LSR dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + LSR (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu4C () +{ +// LSR abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + LSR (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu5B () +{ +// LSR dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + LSR (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); + IAPU.PC += 2; +} + +void Apu5C () +{ +// LSR A + LSR (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu7D () +{ +// MOV A,X + IAPU.Registers.YA.B.A = IAPU.Registers.X; + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuDD () +{ +// MOV A,Y + IAPU.Registers.YA.B.A = IAPU.Registers.YA.B.Y; + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu5D () +{ +// MOV X,A + IAPU.Registers.X = IAPU.Registers.YA.B.A; + APUSetZN8 (IAPU.Registers.X); + IAPU.PC++; +} + +void ApuFD () +{ +// MOV Y,A + IAPU.Registers.YA.B.Y = IAPU.Registers.YA.B.A; + APUSetZN8 (IAPU.Registers.YA.B.Y); + IAPU.PC++; +} + +void Apu9D () +{ +//MOV X,SP + IAPU.Registers.X = IAPU.Registers.S; + APUSetZN8 (IAPU.Registers.X); + IAPU.PC++; +} + +void ApuBD () +{ +// MOV SP,X + IAPU.Registers.S = IAPU.Registers.X; + IAPU.PC++; +} + +void Apu6B () +{ +// ROR dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ROR (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu6C () +{ +// ROR abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ROR (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu7B () +{ +// ROR dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + ROR (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); + IAPU.PC += 2; +} + +void Apu7C () +{ +// ROR A + ROR (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu6E () +{ +// DBNZ dp,rel + uint8 Work8 = OP1; + Relative2 (); + uint8 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 (); + IAPU.Registers.YA.B.Y--; + if (IAPU.Registers.YA.B.Y != 0) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + APU.Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu6F () +{ +// RET + PopW (IAPU.Registers.PC); + IAPU.PC = IAPU.RAM + IAPU.Registers.PC; +} + +void Apu7F () +{ +// RETI + // STOP ("RETI"); + Pop (IAPU.Registers.P); + S9xAPUUnpackStatus (); + PopW (IAPU.Registers.PC); + IAPU.PC = IAPU.RAM + IAPU.Registers.PC; +} + +void Apu84 () +{ +// ADC A,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu85 () +{ +// ADC A, abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu86 () +{ +// ADC A,(X) + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC++; +} + +void Apu87 () +{ +// ADC A,(dp+X) + IndexedXIndirect (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu88 () +{ +// ADC A,#00 + uint8 Work8 = OP1; + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu89 () +{ +// ADC dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + uint8 W1 = S9xAPUGetByteZ (OP2); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void Apu94 () +{ +// ADC A,dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu95 () +{ +// ADC A, abs+X + AbsoluteX (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu96 () +{ +// ADC A, abs+Y + AbsoluteY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu97 () +{ +// ADC A, (dp)+Y + IndirectIndexedY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ADC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu98 () +{ +// ADC dp,#00 + uint8 Work8 = OP1; + uint8 W1 = S9xAPUGetByteZ (OP2); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void Apu99 () +{ +// ADC (X),(Y) + uint8 W1 = S9xAPUGetByteZ (IAPU.Registers.X); + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, IAPU.Registers.X); + IAPU.PC++; +} + +void Apu8D () +{ +// MOV Y,#00 + IAPU.Registers.YA.B.Y = OP1; + APUSetZN8 (IAPU.Registers.YA.B.Y); + IAPU.PC += 2; +} + +void Apu8F () +{ +// MOV dp,#00 + uint8 Work8 = OP1; + S9xAPUSetByteZ (Work8, OP2); + IAPU.PC += 3; +} + +void Apu9E () +{ +// DIV YA,X + if (IAPU.Registers.X == 0) + { + APUSetOverflow (); + IAPU.Registers.YA.B.Y = 0xff; + IAPU.Registers.YA.B.A = 0xff; + } + else + { + APUClearOverflow (); + uint8 Work8 = IAPU.Registers.YA.W / IAPU.Registers.X; + IAPU.Registers.YA.B.Y = IAPU.Registers.YA.W % IAPU.Registers.X; + IAPU.Registers.YA.B.A = Work8; + } +// XXX How should Overflow, Half Carry, Zero and Negative flags be set?? + // APUSetZN16 (IAPU.Registers.YA.W); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void Apu9F () +{ +// XCN A + IAPU.Registers.YA.B.A = (IAPU.Registers.YA.B.A >> 4) | (IAPU.Registers.YA.B.A << 4); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuA4 () +{ +// SBC A, dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA5 () +{ +// SBC A, abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuA6 () +{ +// SBC A, (X) + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC++; +} + +void ApuA7 () +{ +// SBC A,(dp+X) + IndexedXIndirect (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA8 () +{ +// SBC A,#00 + uint8 Work8 = OP1; + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA9 () +{ +// SBC dp(dest), dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + uint8 W1 = S9xAPUGetByteZ (OP2); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void ApuB4 () +{ +// SBC A, dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuB5 () +{ +// SBC A,abs+X + AbsoluteX (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuB6 () +{ +// SBC A,abs+Y + AbsoluteY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuB7 () +{ +// SBC A,(dp)+Y + IndirectIndexedY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + SBC (IAPU.Registers.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuB8 () +{ +// SBC dp,#00 + uint8 Work8 = OP1; + uint8 W1 = S9xAPUGetByteZ (OP2); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void ApuB9 () +{ +// SBC (X),(Y) + uint8 W1 = S9xAPUGetByteZ (IAPU.Registers.X); + uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, IAPU.Registers.X); + IAPU.PC++; +} + +void ApuAF () +{ +// MOV (X)+, A + S9xAPUSetByteZ (IAPU.Registers.YA.B.A, IAPU.Registers.X++); + IAPU.PC++; +} + +void ApuBE () +{ +// DAS + if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry()) + { + IAPU.Registers.YA.B.A -= 6; + } + if (IAPU.Registers.YA.B.A > 0x9f || !IAPU._Carry) + { + IAPU.Registers.YA.B.A -= 0x60; + APUClearCarry (); + } + else { APUSetCarry (); } + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuBF () +{ +// MOV A,(X)+ + IAPU.Registers.YA.B.A = S9xAPUGetByteZ (IAPU.Registers.X++); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuC0 () +{ +// DI + APUClearInterrupt (); + IAPU.PC++; +} + +void ApuA0 () +{ +// EI + APUSetInterrupt (); + IAPU.PC++; +} + +void ApuC4 () +{ +// MOV dp,A + S9xAPUSetByteZ (IAPU.Registers.YA.B.A, OP1); + IAPU.PC += 2; +} + +void ApuC5 () +{ +// MOV abs,A + Absolute (); + S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuC6 () +{ +// MOV (X), A + S9xAPUSetByteZ (IAPU.Registers.YA.B.A, IAPU.Registers.X); + IAPU.PC++; +} + +void ApuC7 () +{ +// MOV (dp+X),A + IndexedXIndirect (); + S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); + IAPU.PC += 2; +} + +void ApuC9 () +{ +// MOV abs,X + Absolute (); + S9xAPUSetByte (IAPU.Registers.X, IAPU.Address); + IAPU.PC += 3; +} + +void ApuCB () +{ +// MOV dp,Y + S9xAPUSetByteZ (IAPU.Registers.YA.B.Y, OP1); + IAPU.PC += 2; +} + +void ApuCC () +{ +// MOV abs,Y + Absolute (); + S9xAPUSetByte (IAPU.Registers.YA.B.Y, IAPU.Address); + IAPU.PC += 3; +} + +void ApuCD () +{ +// MOV X,#00 + IAPU.Registers.X = OP1; + APUSetZN8 (IAPU.Registers.X); + IAPU.PC += 2; +} + +void ApuCF () +{ +// MUL YA + IAPU.Registers.YA.W = (uint16) IAPU.Registers.YA.B.A * IAPU.Registers.YA.B.Y; + APUSetZN16 (IAPU.Registers.YA.W); + IAPU.PC++; +} + +void ApuD4 () +{ +// MOV dp+X, A + S9xAPUSetByteZ (IAPU.Registers.YA.B.A, OP1 + IAPU.Registers.X); + IAPU.PC += 2; +} + +void ApuD5 () +{ +// MOV abs+X,A + AbsoluteX (); + S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuD6 () +{ +// MOV abs+Y,A + AbsoluteY (); + S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuD7 () +{ +// MOV (dp)+Y,A + IndirectIndexedY (); + S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); + IAPU.PC += 2; +} + +void ApuD8 () +{ +// MOV dp,X + S9xAPUSetByteZ (IAPU.Registers.X, OP1); + IAPU.PC += 2; +} + +void ApuD9 () +{ +// MOV dp+Y,X + S9xAPUSetByteZ (IAPU.Registers.X, OP1 + IAPU.Registers.YA.B.Y); + IAPU.PC += 2; +} + +void ApuDB () +{ +// MOV dp+X,Y + S9xAPUSetByteZ (IAPU.Registers.YA.B.Y, OP1 + IAPU.Registers.X); + IAPU.PC += 2; +} + +void ApuDF () +{ +// DAA + if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry()) + { + if(IAPU.Registers.YA.B.A > 0xf0) APUSetCarry (); + IAPU.Registers.YA.B.A += 6; + //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc... + } + //else { APUClearHalfCarry (); } ditto as above + if (IAPU.Registers.YA.B.A > 0x9f || IAPU._Carry) + { + IAPU.Registers.YA.B.A += 0x60; + APUSetCarry (); + } + else { APUClearCarry (); } + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuE4 () +{ +// MOV A, dp + IAPU.Registers.YA.B.A = S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void ApuE5 () +{ +// MOV A,abs + Absolute (); + IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void ApuE6 () +{ +// MOV A,(X) + IAPU.Registers.YA.B.A = S9xAPUGetByteZ (IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC++; +} + +void ApuE7 () +{ +// MOV A,(dp+X) + IndexedXIndirect (); + IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void ApuE8 () +{ +// MOV A,#00 + IAPU.Registers.YA.B.A = OP1; + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void ApuE9 () +{ +// MOV X, abs + Absolute (); + IAPU.Registers.X = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.X); + IAPU.PC += 3; +} + +void ApuEB () +{ +// MOV Y,dp + IAPU.Registers.YA.B.Y = S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.Registers.YA.B.Y); + IAPU.PC += 2; +} + +void ApuEC () +{ +// MOV Y,abs + Absolute (); + IAPU.Registers.YA.B.Y = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.Y); + IAPU.PC += 3; +} + +void ApuF4 () +{ +// MOV A, dp+X + IAPU.Registers.YA.B.A = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void ApuF5 () +{ +// MOV A, abs+X + AbsoluteX (); + IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void ApuF6 () +{ +// MOV A, abs+Y + AbsoluteY (); + IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 3; +} + +void ApuF7 () +{ +// MOV A, (dp)+Y + IndirectIndexedY (); + IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.Registers.YA.B.A); + IAPU.PC += 2; +} + +void ApuF8 () +{ +// MOV X,dp + IAPU.Registers.X = S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.Registers.X); + IAPU.PC += 2; +} + +void ApuF9 () +{ +// MOV X,dp+Y + IAPU.Registers.X = S9xAPUGetByteZ (OP1 + IAPU.Registers.YA.B.Y); + APUSetZN8 (IAPU.Registers.X); + IAPU.PC += 2; +} + +void ApuFA () +{ +// MOV dp(dest),dp(src) + S9xAPUSetByteZ (S9xAPUGetByteZ (OP1), OP2); + IAPU.PC += 3; +} + +void ApuFB () +{ +// MOV Y,dp+X + IAPU.Registers.YA.B.Y = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); + APUSetZN8 (IAPU.Registers.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/spc700.cpp b/source/spc700.cpp deleted file mode 100644 index 3bfeeac..0000000 --- a/source/spc700.cpp +++ /dev/null @@ -1,2548 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#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 - -#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) \ - APU.Cycles = CPU.Cycles = CPU.NextEvent; \ - 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 STOP (char *s) -{ - char buffer[100]; - - buffer[0] = '\0'; - - sprintf (String, "Sound CPU in unknown state executing %s at %04X\n%s\n", s, IAPU.PC - IAPU.RAM, buffer); - S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String); - APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; - IAPU.APUExecuting = FALSE; - - S9xExit (); -} - -#define TCALL(n)\ -{\ - PushW (IAPU.PC - IAPU.RAM + 1); \ - IAPU.PC = IAPU.RAM + (APU.ExtraRAM [((15 - n) << 1)] + \ - (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \ -} - -// XXX: HalfCarry - BJ fixed? -#define SBC(a,b)\ -int16 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); - -// XXX: HalfCarry - BJ fixed? -// XXX: HalfCarry used Int16 before; trying to fix it with Work16 [Neb] -#define ADC(a,b)\ -uint16 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 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)\ - uint16 Work16 = ((b) << 1) | APUCheckCarry (); \ - IAPU._Carry = Work16 >= 0x100; \ - (b) = (uint8) Work16; \ - APUSetZN8 (b); -#define ROR(b)\ - uint16 Work16 = (b) | ((uint16) APUCheckCarry () << 8); \ - IAPU._Carry = (uint8) Work16 & 1; \ - Work16 >>= 1; \ - (b) = (uint8) Work16; \ - APUSetZN8 (b); - -#define Push(b)\ - *(IAPU.RAM + 0x100 + IAPU.Registers.S) = b;\ - IAPU.Registers.S--; - -#define Pop(b)\ - IAPU.Registers.S++;\ - (b) = *(IAPU.RAM + 0x100 + IAPU.Registers.S); - -#ifdef FAST_LSB_WORD_ACCESS -#define PushW(w)\ - *(uint16 *) (IAPU.RAM + 0xff + IAPU.Registers.S) = w;\ - IAPU.Registers.S -= 2; -#define PopW(w)\ - IAPU.Registers.S += 2;\ - w = *(uint16 *) (IAPU.RAM + 0xff + IAPU.Registers.S); -#else -#define PushW(w)\ - *(IAPU.RAM + 0xff + IAPU.Registers.S) = w;\ - *(IAPU.RAM + 0x100 + IAPU.Registers.S) = (w >> 8);\ - IAPU.Registers.S -= 2; -#define PopW(w)\ - IAPU.Registers.S += 2; \ - (w) = *(IAPU.RAM + 0xff + IAPU.Registers.S) + (*(IAPU.RAM + 0x100 + IAPU.Registers.S) << 8); -#endif - -#define Relative()\ - int8 Int8 = OP1;\ - int16 Int16 = (intptr_t) (IAPU.PC + 2 - IAPU.RAM) + Int8; - -#define Relative2()\ - int8 Int8 = OP2;\ - int16 Int16 = (intptr_t) (IAPU.PC + 3 - IAPU.RAM) + Int8; - -#ifdef FAST_LSB_WORD_ACCESS -#define IndexedXIndirect()\ - IAPU.Address = *(uint16 *) (IAPU.DirectPage + ((OP1 + IAPU.Registers.X) & 0xff)); - -#define Absolute()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1); - -#define AbsoluteX()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.Registers.X; - -#define AbsoluteY()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.Registers.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) + IAPU.Registers.YA.B.Y; -#else -#define IndexedXIndirect()\ - IAPU.Address = *(IAPU.DirectPage + ((OP1 + IAPU.Registers.X) & 0xff)) + \ - (*(IAPU.DirectPage + ((OP1 + IAPU.Registers.X + 1) & 0xff)) << 8); -#define Absolute()\ - IAPU.Address = OP1 + (OP2 << 8); - -#define AbsoluteX()\ - IAPU.Address = OP1 + (OP2 << 8) + IAPU.Registers.X; - -#define AbsoluteY()\ - IAPU.Address = OP1 + (OP2 << 8) + IAPU.Registers.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) + \ - IAPU.Registers.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 -{ - uint8 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) \ -uint8 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) \ -uint8 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 - IAPU.Registers.YA.B.A |= S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu05 () -{ -// OR A,abs - Absolute (); - IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu06 () -{ -// OR A,(X) - IAPU.Registers.YA.B.A |= S9xAPUGetByteZ (IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu07 () -{ -// OR A,(dp+X) - IndexedXIndirect (); - IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu08 () -{ -// OR A,#00 - IAPU.Registers.YA.B.A |= OP1; - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu09 () -{ -// OR dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - Work8 |= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu14 () -{ -// OR A,dp+X - IAPU.Registers.YA.B.A |= S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu15 () -{ -// OR A,abs+X - AbsoluteX (); - IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu16 () -{ -// OR A,abs+Y - AbsoluteY (); - IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu17 () -{ -// OR A,(dp)+Y - IndirectIndexedY (); - IAPU.Registers.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu18 () -{ -// OR dp,#00 - uint8 Work8 = OP1; - Work8 |= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu19 () -{ -// OR (X),(Y) - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X) | S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); - APUSetZN8 (Work8); - S9xAPUSetByteZ (Work8, IAPU.Registers.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 - uint8 Work8 = S9xAPUGetByteZ (OP1); - ASL (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu0C () -{ -// ASL abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ASL (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu1B () -{ -// ASL dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - ASL (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); - IAPU.PC += 2; -} - -void Apu1C () -{ -// ASL A - ASL (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu0D () -{ -// PUSH PSW - S9xAPUPackStatus (); - Push (IAPU.Registers.P); - IAPU.PC++; -} - -void Apu2D () -{ -// PUSH A - Push (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu4D () -{ -// PUSH X - Push (IAPU.Registers.X); - IAPU.PC++; -} - -void Apu6D () -{ -// PUSH Y - Push (IAPU.Registers.YA.B.Y); - IAPU.PC++; -} - -void Apu8E () -{ -// POP PSW - Pop (IAPU.Registers.P); - S9xAPUUnpackStatus (); - if (APUCheckDirectPage ()) - IAPU.DirectPage = IAPU.RAM + 0x100; - else - IAPU.DirectPage = IAPU.RAM; - IAPU.PC++; -} - -void ApuAE () -{ -// POP A - Pop (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuCE () -{ -// POP X - Pop (IAPU.Registers.X); - IAPU.PC++; -} - -void ApuEE () -{ -// POP Y - Pop (IAPU.Registers.YA.B.Y); - IAPU.PC++; -} - -void Apu0E () -{ -// TSET1 abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - S9xAPUSetByte (Work8 | IAPU.Registers.YA.B.A, IAPU.Address); - Work8 &= IAPU.Registers.YA.B.A; - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu4E () -{ -// TCLR1 abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - S9xAPUSetByte (Work8 & ~IAPU.Registers.YA.B.A, IAPU.Address); - Work8 &= IAPU.Registers.YA.B.A; - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu0F () -{ -// BRK - -#if 0 - STOP ("BRK"); -#else - PushW (IAPU.PC + 1 - IAPU.RAM); - S9xAPUPackStatus (); - Push (IAPU.Registers.P); - APUSetBreak (); - APUClearInterrupt (); -// XXX:Where is the BRK vector ??? - IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8); -#endif -} - -void ApuEF () -{ -// SLEEP - // XXX: sleep - // STOP ("SLEEP"); - IAPU.APUExecuting = FALSE; - IAPU.PC++; -} - -void ApuFF () -{ -// STOP - // STOP ("STOP"); - IAPU.APUExecuting = FALSE; - IAPU.PC++; -} - -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 - uint16 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 - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - int32 Int32 = (long) IAPU.Registers.YA.W - (long) Work16; - IAPU._Carry = Int32 >= 0; - APUSetZN16 ((uint16) Int32); - IAPU.PC += 2; -} - -void Apu3A () -{ -// INCW dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - Work16++; - S9xAPUSetByteZ ((uint8) Work16, OP1); - S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); - APUSetZN16 (Work16); - IAPU.PC += 2; -} - -// XXX: HalfCarry - BJ Fixed? Or is it between bits 7 and 8 for ADDW/SUBW? -void Apu7A () -{ -// ADDW YA,dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - uint32 Work32 = (uint32) IAPU.Registers.YA.W + Work16; - IAPU._Carry = Work32 >= 0x10000; - if (~(IAPU.Registers.YA.W ^ Work16) & (Work16 ^ (uint16) Work32) & 0x8000) - APUSetOverflow (); - else - APUClearOverflow (); - APUClearHalfCarry (); - if((IAPU.Registers.YA.W ^ Work16 ^ (uint16) Work32) & 0x10) - APUSetHalfCarry (); - IAPU.Registers.YA.W = (uint16) Work32; - APUSetZN16 (IAPU.Registers.YA.W); - IAPU.PC += 2; -} - -// XXX: BJ: i think the old HalfCarry behavior was wrong... -// XXX: Or is it between bits 7 and 8 for ADDW/SUBW? -// XXX: Used Work32 instead of Int32 before. Fixed? [Neb] -void Apu9A () -{ -// SUBW YA,dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - int32 Int32 = (long) IAPU.Registers.YA.W - (long) Work16; - APUClearHalfCarry (); - IAPU._Carry = Int32 >= 0; - if (((IAPU.Registers.YA.W ^ Work16) & 0x8000) && - ((IAPU.Registers.YA.W ^ (uint16) Int32) & 0x8000)) - APUSetOverflow (); - else - APUClearOverflow (); - if (((IAPU.Registers.YA.W ^ Work16) & 0x0080) && - ((IAPU.Registers.YA.W ^ (uint16) Int32) & 0x0080)) - APUSetHalfCarry (); - APUSetHalfCarry (); - if((IAPU.Registers.YA.W ^ Work16 ^ (uint16) Int32) & 0x10) - APUClearHalfCarry (); - IAPU.Registers.YA.W = (uint16) Int32; - APUSetZN16 (IAPU.Registers.YA.W); - IAPU.PC += 2; -} - -void ApuBA () -{ -// MOVW YA,dp - IAPU.Registers.YA.B.A = S9xAPUGetByteZ (OP1); - IAPU.Registers.YA.B.Y = S9xAPUGetByteZ (OP1 + 1); - APUSetZN16 (IAPU.Registers.YA.W); - IAPU.PC += 2; -} - -void ApuDA () -{ -// MOVW dp,YA - S9xAPUSetByteZ (IAPU.Registers.YA.B.A, OP1); - S9xAPUSetByteZ (IAPU.Registers.YA.B.Y, OP1 + 1); - IAPU.PC += 2; -} - -void Apu64 () -{ -// CMP A,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu65 () -{ -// CMP A,abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu66 () -{ -// CMP A,(X) - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC++; -} - -void Apu67 () -{ -// CMP A,(dp+X) - IndexedXIndirect (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu68 () -{ -// CMP A,#00 - uint8 Work8 = OP1; - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu69 () -{ -// CMP dp(dest), dp(src) - uint8 W1 = S9xAPUGetByteZ (OP1); - uint8 Work8 = S9xAPUGetByteZ (OP2); - CMP (Work8, W1); - IAPU.PC += 3; -} - -void Apu74 () -{ -// CMP A, dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu75 () -{ -// CMP A,abs+X - AbsoluteX (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu76 () -{ -// CMP A, abs+Y - AbsoluteY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu77 () -{ -// CMP A,(dp)+Y - IndirectIndexedY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu78 () -{ -// CMP dp,#00 - uint8 Work8 = OP1; - uint8 W1 = S9xAPUGetByteZ (OP2); - CMP (W1, Work8); - IAPU.PC += 3; -} - -void Apu79 () -{ -// CMP (X),(Y) - uint8 W1 = S9xAPUGetByteZ (IAPU.Registers.X); - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); - CMP (W1, Work8); - IAPU.PC++; -} - -void Apu1E () -{ -// CMP X,abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.X, Work8); - IAPU.PC += 3; -} - -void Apu3E () -{ -// CMP X,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - CMP (IAPU.Registers.X, Work8); - IAPU.PC += 2; -} - -void ApuC8 () -{ -// CMP X,#00 - CMP (IAPU.Registers.X, OP1); - IAPU.PC += 2; -} - -void Apu5E () -{ -// CMP Y,abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.Registers.YA.B.Y, Work8); - IAPU.PC += 3; -} - -void Apu7E () -{ -// CMP Y,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - CMP (IAPU.Registers.YA.B.Y, Work8); - IAPU.PC += 2; -} - -void ApuAD () -{ -// CMP Y,#00 - uint8 Work8 = OP1; - CMP (IAPU.Registers.YA.B.Y, Work8); - IAPU.PC += 2; -} - -void Apu1F () -{ -// JMP (abs+X) - Absolute (); - IAPU.PC = IAPU.RAM + S9xAPUGetByte (IAPU.Address + IAPU.Registers.X) + - (S9xAPUGetByte (IAPU.Address + IAPU.Registers.X + 1) << 8); -// XXX: HERE: - // APU.Flags |= TRACE_FLAG; -} - -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 - IAPU.Registers.YA.B.A &= S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu25 () -{ -// AND A,abs - Absolute (); - IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu26 () -{ -// AND A,(X) - IAPU.Registers.YA.B.A &= S9xAPUGetByteZ (IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu27 () -{ -// AND A,(dp+X) - IndexedXIndirect (); - IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu28 () -{ -// AND A,#00 - IAPU.Registers.YA.B.A &= OP1; - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu29 () -{ -// AND dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - Work8 &= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu34 () -{ -// AND A,dp+X - IAPU.Registers.YA.B.A &= S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu35 () -{ -// AND A,abs+X - AbsoluteX (); - IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu36 () -{ -// AND A,abs+Y - AbsoluteY (); - IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu37 () -{ -// AND A,(dp)+Y - IndirectIndexedY (); - IAPU.Registers.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu38 () -{ -// AND dp,#00 - uint8 Work8 = OP1; - Work8 &= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu39 () -{ -// AND (X),(Y) - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X) & S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); - APUSetZN8 (Work8); - S9xAPUSetByteZ (Work8, IAPU.Registers.X); - IAPU.PC++; -} - -void Apu2B () -{ -// ROL dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ROL (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu2C () -{ -// ROL abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ROL (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu3B () -{ -// ROL dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - ROL (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); - IAPU.PC += 2; -} - -void Apu3C () -{ -// ROL A - ROL (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu2E () -{ -// CBNE dp,rel - uint8 Work8 = OP1; - Relative2 (); - - if (S9xAPUGetByteZ (Work8) != IAPU.Registers.YA.B.A) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - APU.Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 3; -} - -void ApuDE () -{ -// CBNE dp+X,rel - uint8 Work8 = OP1 + IAPU.Registers.X; - Relative2 (); - - if (S9xAPUGetByteZ (Work8) != IAPU.Registers.YA.B.A) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - APU.Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 3; -} - -void Apu3D () -{ -// INC X - IAPU.Registers.X++; - APUSetZN8 (IAPU.Registers.X); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void ApuFC () -{ -// INC Y - IAPU.Registers.YA.B.Y++; - APUSetZN8 (IAPU.Registers.YA.B.Y); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void Apu1D () -{ -// DEC X - IAPU.Registers.X--; - APUSetZN8 (IAPU.Registers.X); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void ApuDC () -{ -// DEC Y - IAPU.Registers.YA.B.Y--; - APUSetZN8 (IAPU.Registers.YA.B.Y); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void ApuAB () -{ -// INC dp - uint8 Work8 = S9xAPUGetByteZ (OP1) + 1; - S9xAPUSetByteZ (Work8, OP1); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void ApuAC () -{ -// INC abs - Absolute (); - uint8 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 - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X) + 1; - S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void ApuBC () -{ -// INC A - IAPU.Registers.YA.B.A++; - APUSetZN8 (IAPU.Registers.YA.B.A); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void Apu8B () -{ -// DEC dp - uint8 Work8 = S9xAPUGetByteZ (OP1) - 1; - S9xAPUSetByteZ (Work8, OP1); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void Apu8C () -{ -// DEC abs - Absolute (); - uint8 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 - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X) - 1; - S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void Apu9C () -{ -// DEC A - IAPU.Registers.YA.B.A--; - APUSetZN8 (IAPU.Registers.YA.B.A); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void Apu44 () -{ -// EOR A,dp - IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu45 () -{ -// EOR A,abs - Absolute (); - IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu46 () -{ -// EOR A,(X) - IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ (IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu47 () -{ -// EOR A,(dp+X) - IndexedXIndirect (); - IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu48 () -{ -// EOR A,#00 - IAPU.Registers.YA.B.A ^= OP1; - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu49 () -{ -// EOR dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - Work8 ^= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu54 () -{ -// EOR A,dp+X - IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu55 () -{ -// EOR A,abs+X - AbsoluteX (); - IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu56 () -{ -// EOR A,abs+Y - AbsoluteY (); - IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void Apu57 () -{ -// EOR A,(dp)+Y - IndirectIndexedY (); - IAPU.Registers.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void Apu58 () -{ -// EOR dp,#00 - uint8 Work8 = OP1; - Work8 ^= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu59 () -{ -// EOR (X),(Y) - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X) ^ S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); - APUSetZN8 (Work8); - S9xAPUSetByteZ (Work8, IAPU.Registers.X); - IAPU.PC++; -} - -void Apu4B () -{ -// LSR dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - LSR (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu4C () -{ -// LSR abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - LSR (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu5B () -{ -// LSR dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - LSR (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); - IAPU.PC += 2; -} - -void Apu5C () -{ -// LSR A - LSR (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu7D () -{ -// MOV A,X - IAPU.Registers.YA.B.A = IAPU.Registers.X; - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuDD () -{ -// MOV A,Y - IAPU.Registers.YA.B.A = IAPU.Registers.YA.B.Y; - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu5D () -{ -// MOV X,A - IAPU.Registers.X = IAPU.Registers.YA.B.A; - APUSetZN8 (IAPU.Registers.X); - IAPU.PC++; -} - -void ApuFD () -{ -// MOV Y,A - IAPU.Registers.YA.B.Y = IAPU.Registers.YA.B.A; - APUSetZN8 (IAPU.Registers.YA.B.Y); - IAPU.PC++; -} - -void Apu9D () -{ -//MOV X,SP - IAPU.Registers.X = IAPU.Registers.S; - APUSetZN8 (IAPU.Registers.X); - IAPU.PC++; -} - -void ApuBD () -{ -// MOV SP,X - IAPU.Registers.S = IAPU.Registers.X; - IAPU.PC++; -} - -void Apu6B () -{ -// ROR dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ROR (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu6C () -{ -// ROR abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ROR (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu7B () -{ -// ROR dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - ROR (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.Registers.X); - IAPU.PC += 2; -} - -void Apu7C () -{ -// ROR A - ROR (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu6E () -{ -// DBNZ dp,rel - uint8 Work8 = OP1; - Relative2 (); - uint8 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 (); - IAPU.Registers.YA.B.Y--; - if (IAPU.Registers.YA.B.Y != 0) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - APU.Cycles += IAPU.TwoCycles; - } - else - IAPU.PC += 2; -} - -void Apu6F () -{ -// RET - PopW (IAPU.Registers.PC); - IAPU.PC = IAPU.RAM + IAPU.Registers.PC; -} - -void Apu7F () -{ -// RETI - // STOP ("RETI"); - Pop (IAPU.Registers.P); - S9xAPUUnpackStatus (); - PopW (IAPU.Registers.PC); - IAPU.PC = IAPU.RAM + IAPU.Registers.PC; -} - -void Apu84 () -{ -// ADC A,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu85 () -{ -// ADC A, abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu86 () -{ -// ADC A,(X) - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC++; -} - -void Apu87 () -{ -// ADC A,(dp+X) - IndexedXIndirect (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu88 () -{ -// ADC A,#00 - uint8 Work8 = OP1; - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu89 () -{ -// ADC dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - uint8 W1 = S9xAPUGetByteZ (OP2); - ADC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void Apu94 () -{ -// ADC A,dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu95 () -{ -// ADC A, abs+X - AbsoluteX (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu96 () -{ -// ADC A, abs+Y - AbsoluteY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu97 () -{ -// ADC A, (dp)+Y - IndirectIndexedY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ADC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu98 () -{ -// ADC dp,#00 - uint8 Work8 = OP1; - uint8 W1 = S9xAPUGetByteZ (OP2); - ADC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void Apu99 () -{ -// ADC (X),(Y) - uint8 W1 = S9xAPUGetByteZ (IAPU.Registers.X); - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); - ADC (W1, Work8); - S9xAPUSetByteZ (W1, IAPU.Registers.X); - IAPU.PC++; -} - -void Apu8D () -{ -// MOV Y,#00 - IAPU.Registers.YA.B.Y = OP1; - APUSetZN8 (IAPU.Registers.YA.B.Y); - IAPU.PC += 2; -} - -void Apu8F () -{ -// MOV dp,#00 - uint8 Work8 = OP1; - S9xAPUSetByteZ (Work8, OP2); - IAPU.PC += 3; -} - -void Apu9E () -{ -// DIV YA,X - if (IAPU.Registers.X == 0) - { - APUSetOverflow (); - IAPU.Registers.YA.B.Y = 0xff; - IAPU.Registers.YA.B.A = 0xff; - } - else - { - APUClearOverflow (); - uint8 Work8 = IAPU.Registers.YA.W / IAPU.Registers.X; - IAPU.Registers.YA.B.Y = IAPU.Registers.YA.W % IAPU.Registers.X; - IAPU.Registers.YA.B.A = Work8; - } -// XXX How should Overflow, Half Carry, Zero and Negative flags be set?? - // APUSetZN16 (IAPU.Registers.YA.W); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void Apu9F () -{ -// XCN A - IAPU.Registers.YA.B.A = (IAPU.Registers.YA.B.A >> 4) | (IAPU.Registers.YA.B.A << 4); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuA4 () -{ -// SBC A, dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuA5 () -{ -// SBC A, abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void ApuA6 () -{ -// SBC A, (X) - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.X); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC++; -} - -void ApuA7 () -{ -// SBC A,(dp+X) - IndexedXIndirect (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuA8 () -{ -// SBC A,#00 - uint8 Work8 = OP1; - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuA9 () -{ -// SBC dp(dest), dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - uint8 W1 = S9xAPUGetByteZ (OP2); - SBC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void ApuB4 () -{ -// SBC A, dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuB5 () -{ -// SBC A,abs+X - AbsoluteX (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void ApuB6 () -{ -// SBC A,abs+Y - AbsoluteY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 3; -} - -void ApuB7 () -{ -// SBC A,(dp)+Y - IndirectIndexedY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - SBC (IAPU.Registers.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuB8 () -{ -// SBC dp,#00 - uint8 Work8 = OP1; - uint8 W1 = S9xAPUGetByteZ (OP2); - SBC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void ApuB9 () -{ -// SBC (X),(Y) - uint8 W1 = S9xAPUGetByteZ (IAPU.Registers.X); - uint8 Work8 = S9xAPUGetByteZ (IAPU.Registers.YA.B.Y); - SBC (W1, Work8); - S9xAPUSetByteZ (W1, IAPU.Registers.X); - IAPU.PC++; -} - -void ApuAF () -{ -// MOV (X)+, A - S9xAPUSetByteZ (IAPU.Registers.YA.B.A, IAPU.Registers.X++); - IAPU.PC++; -} - -void ApuBE () -{ -// DAS - if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry()) - { - IAPU.Registers.YA.B.A -= 6; - } - if (IAPU.Registers.YA.B.A > 0x9f || !IAPU._Carry) - { - IAPU.Registers.YA.B.A -= 0x60; - APUClearCarry (); - } - else { APUSetCarry (); } - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuBF () -{ -// MOV A,(X)+ - IAPU.Registers.YA.B.A = S9xAPUGetByteZ (IAPU.Registers.X++); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuC0 () -{ -// DI - APUClearInterrupt (); - IAPU.PC++; -} - -void ApuA0 () -{ -// EI - APUSetInterrupt (); - IAPU.PC++; -} - -void ApuC4 () -{ -// MOV dp,A - S9xAPUSetByteZ (IAPU.Registers.YA.B.A, OP1); - IAPU.PC += 2; -} - -void ApuC5 () -{ -// MOV abs,A - Absolute (); - S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); - IAPU.PC += 3; -} - -void ApuC6 () -{ -// MOV (X), A - S9xAPUSetByteZ (IAPU.Registers.YA.B.A, IAPU.Registers.X); - IAPU.PC++; -} - -void ApuC7 () -{ -// MOV (dp+X),A - IndexedXIndirect (); - S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); - IAPU.PC += 2; -} - -void ApuC9 () -{ -// MOV abs,X - Absolute (); - S9xAPUSetByte (IAPU.Registers.X, IAPU.Address); - IAPU.PC += 3; -} - -void ApuCB () -{ -// MOV dp,Y - S9xAPUSetByteZ (IAPU.Registers.YA.B.Y, OP1); - IAPU.PC += 2; -} - -void ApuCC () -{ -// MOV abs,Y - Absolute (); - S9xAPUSetByte (IAPU.Registers.YA.B.Y, IAPU.Address); - IAPU.PC += 3; -} - -void ApuCD () -{ -// MOV X,#00 - IAPU.Registers.X = OP1; - APUSetZN8 (IAPU.Registers.X); - IAPU.PC += 2; -} - -void ApuCF () -{ -// MUL YA - IAPU.Registers.YA.W = (uint16) IAPU.Registers.YA.B.A * IAPU.Registers.YA.B.Y; - APUSetZN16 (IAPU.Registers.YA.W); - IAPU.PC++; -} - -void ApuD4 () -{ -// MOV dp+X, A - S9xAPUSetByteZ (IAPU.Registers.YA.B.A, OP1 + IAPU.Registers.X); - IAPU.PC += 2; -} - -void ApuD5 () -{ -// MOV abs+X,A - AbsoluteX (); - S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); - IAPU.PC += 3; -} - -void ApuD6 () -{ -// MOV abs+Y,A - AbsoluteY (); - S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); - IAPU.PC += 3; -} - -void ApuD7 () -{ -// MOV (dp)+Y,A - IndirectIndexedY (); - S9xAPUSetByte (IAPU.Registers.YA.B.A, IAPU.Address); - IAPU.PC += 2; -} - -void ApuD8 () -{ -// MOV dp,X - S9xAPUSetByteZ (IAPU.Registers.X, OP1); - IAPU.PC += 2; -} - -void ApuD9 () -{ -// MOV dp+Y,X - S9xAPUSetByteZ (IAPU.Registers.X, OP1 + IAPU.Registers.YA.B.Y); - IAPU.PC += 2; -} - -void ApuDB () -{ -// MOV dp+X,Y - S9xAPUSetByteZ (IAPU.Registers.YA.B.Y, OP1 + IAPU.Registers.X); - IAPU.PC += 2; -} - -void ApuDF () -{ -// DAA - if ((IAPU.Registers.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry()) - { - if(IAPU.Registers.YA.B.A > 0xf0) APUSetCarry (); - IAPU.Registers.YA.B.A += 6; - //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc... - } - //else { APUClearHalfCarry (); } ditto as above - if (IAPU.Registers.YA.B.A > 0x9f || IAPU._Carry) - { - IAPU.Registers.YA.B.A += 0x60; - APUSetCarry (); - } - else { APUClearCarry (); } - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuE4 () -{ -// MOV A, dp - IAPU.Registers.YA.B.A = S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void ApuE5 () -{ -// MOV A,abs - Absolute (); - IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void ApuE6 () -{ -// MOV A,(X) - IAPU.Registers.YA.B.A = S9xAPUGetByteZ (IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC++; -} - -void ApuE7 () -{ -// MOV A,(dp+X) - IndexedXIndirect (); - IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void ApuE8 () -{ -// MOV A,#00 - IAPU.Registers.YA.B.A = OP1; - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void ApuE9 () -{ -// MOV X, abs - Absolute (); - IAPU.Registers.X = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.X); - IAPU.PC += 3; -} - -void ApuEB () -{ -// MOV Y,dp - IAPU.Registers.YA.B.Y = S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.Registers.YA.B.Y); - IAPU.PC += 2; -} - -void ApuEC () -{ -// MOV Y,abs - Absolute (); - IAPU.Registers.YA.B.Y = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.Y); - IAPU.PC += 3; -} - -void ApuF4 () -{ -// MOV A, dp+X - IAPU.Registers.YA.B.A = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void ApuF5 () -{ -// MOV A, abs+X - AbsoluteX (); - IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void ApuF6 () -{ -// MOV A, abs+Y - AbsoluteY (); - IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 3; -} - -void ApuF7 () -{ -// MOV A, (dp)+Y - IndirectIndexedY (); - IAPU.Registers.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.Registers.YA.B.A); - IAPU.PC += 2; -} - -void ApuF8 () -{ -// MOV X,dp - IAPU.Registers.X = S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.Registers.X); - IAPU.PC += 2; -} - -void ApuF9 () -{ -// MOV X,dp+Y - IAPU.Registers.X = S9xAPUGetByteZ (OP1 + IAPU.Registers.YA.B.Y); - APUSetZN8 (IAPU.Registers.X); - IAPU.PC += 2; -} - -void ApuFA () -{ -// MOV dp(dest),dp(src) - S9xAPUSetByteZ (S9xAPUGetByteZ (OP1), OP2); - IAPU.PC += 3; -} - -void ApuFB () -{ -// MOV Y,dp+X - IAPU.Registers.YA.B.Y = S9xAPUGetByteZ (OP1 + IAPU.Registers.X); - APUSetZN8 (IAPU.Registers.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/spc7110.c b/source/spc7110.c new file mode 100644 index 0000000..3ae0cfd --- /dev/null +++ b/source/spc7110.c @@ -0,0 +1,2285 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ + +#include "spc7110.h" +#include "memmap.h" +#include +#include + +//Windows includes +#ifdef __WIN32__ +#ifndef _XBOX // chdir and getcwd not supported on Xbox hardware +#include +#define chdir _chdir +#define getcwd _getcwd +#endif +#define FREEZEFOLDER GUI.FreezeFileDir +//zinx suggested this, for *nix compatibility +#define PATH_MAX MAX_PATH +#else // Unix +#include "display.h" +#include +#include +#define FREEZEFOLDER S9xGetSnapshotDirectory () +#endif + +extern "C" const char *S9xGetFilename (const char *); +extern "C" char *osd_GetPackDir(); +//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 + +//not much headroom, but FEOEZ has 41 tables, I think, and SPL4 has 38. +#define MAX_TABLES 48 + +//default to using 5 megs of RAM for method 3 caching. +uint16 cacheMegs=5; + +//using function pointers to initialize cache management +void (*CleanUp7110)(void)=NULL; +void (*LoadUp7110)(char*)=&SPC7110Load; +void (*Copy7110)(void)=NULL; + +//size and offset of the pack data +//offset and size of reads from pack +typedef struct SPC7110DecompressionLocationStruct +{ + 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; + + (*LoadUp7110)(osd_GetPackDir()); + + s7r.bank50Internal=0; + memset(s7r.bank50,0x00,DECOMP_BUFFER_SIZE); +} + + +//full cache decompression routine (memcpy) Method 1 +void MovePackData() +{ + //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(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 + 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; + } + + //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(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) + { + FILE* fp=fopen("sp7err.out","a"); +// 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; + 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]; + if (strlen (FREEZEFOLDER)) + { + //splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy (name, FREEZEFOLDER); + 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); + 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(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) + { + FILE* fp=fopen("sp7err.out","a"); +// 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) +{ + 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; + } + 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=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; + + } + } + } + + 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=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; + } + } + } + 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; + return tmp; + } + else return 0; +//RTC done flag + case 0x4842: + if(!Settings.SPC7110RTC) + return Address>>8; + s7r.reg4842^=0x80; + return s7r.reg4842^0x80; + default: + return 0x00; + } +} +} +void S9xSetSPC7110 (uint8 data, uint16 Address) +{ + 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(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: + Memory.SPC7110Sram(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 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 &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; + + int f_len; + //do + while(1) + { + i=0; + f_len= fread(buffer, 1, 12,fp); + if(f_len < 12) break; + + 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)(); + + 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 + } + + if(flog) + { + uint8 buffer[8]; + int table=0; + uint16 offset=0; + uint16 length=0; + fseek(flog, 35,0); + + int f_len; + //do + while(1) + { + int i=0; + Data7110 *log=NULL; + f_len= fread(buffer, 1, 8, flog); + if(f_len < 8) break; + + 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); + } + + + 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 + } + //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); + } + } +} +bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9) +{ + FILE* fp; + + if((fp=fopen(S9xGetFilename(".rtc"), "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"), "rb"))==NULL) + return (FALSE); + for (int i=0; i<16;i++) + { + fread(&(rtc_f9->reg[i]),1,1,fp); + } + 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); + + 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); +} + diff --git a/source/spc7110.cpp b/source/spc7110.cpp deleted file mode 100644 index 3ae0cfd..0000000 --- a/source/spc7110.cpp +++ /dev/null @@ -1,2285 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ - -#include "spc7110.h" -#include "memmap.h" -#include -#include - -//Windows includes -#ifdef __WIN32__ -#ifndef _XBOX // chdir and getcwd not supported on Xbox hardware -#include -#define chdir _chdir -#define getcwd _getcwd -#endif -#define FREEZEFOLDER GUI.FreezeFileDir -//zinx suggested this, for *nix compatibility -#define PATH_MAX MAX_PATH -#else // Unix -#include "display.h" -#include -#include -#define FREEZEFOLDER S9xGetSnapshotDirectory () -#endif - -extern "C" const char *S9xGetFilename (const char *); -extern "C" char *osd_GetPackDir(); -//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 - -//not much headroom, but FEOEZ has 41 tables, I think, and SPL4 has 38. -#define MAX_TABLES 48 - -//default to using 5 megs of RAM for method 3 caching. -uint16 cacheMegs=5; - -//using function pointers to initialize cache management -void (*CleanUp7110)(void)=NULL; -void (*LoadUp7110)(char*)=&SPC7110Load; -void (*Copy7110)(void)=NULL; - -//size and offset of the pack data -//offset and size of reads from pack -typedef struct SPC7110DecompressionLocationStruct -{ - 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; - - (*LoadUp7110)(osd_GetPackDir()); - - s7r.bank50Internal=0; - memset(s7r.bank50,0x00,DECOMP_BUFFER_SIZE); -} - - -//full cache decompression routine (memcpy) Method 1 -void MovePackData() -{ - //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(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 - 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; - } - - //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(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) - { - FILE* fp=fopen("sp7err.out","a"); -// 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; - 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]; - if (strlen (FREEZEFOLDER)) - { - //splitpath (Memory.ROMFilename, drive, dir, fname, ext); - strcpy (name, FREEZEFOLDER); - 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); - 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(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) - { - FILE* fp=fopen("sp7err.out","a"); -// 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) -{ - 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; - } - 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=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; - - } - } - } - - 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=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; - } - } - } - 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; - return tmp; - } - else return 0; -//RTC done flag - case 0x4842: - if(!Settings.SPC7110RTC) - return Address>>8; - s7r.reg4842^=0x80; - return s7r.reg4842^0x80; - default: - return 0x00; - } -} -} -void S9xSetSPC7110 (uint8 data, uint16 Address) -{ - 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(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: - Memory.SPC7110Sram(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 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 &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; - - int f_len; - //do - while(1) - { - i=0; - f_len= fread(buffer, 1, 12,fp); - if(f_len < 12) break; - - 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)(); - - 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 - } - - if(flog) - { - uint8 buffer[8]; - int table=0; - uint16 offset=0; - uint16 length=0; - fseek(flog, 35,0); - - int f_len; - //do - while(1) - { - int i=0; - Data7110 *log=NULL; - f_len= fread(buffer, 1, 8, flog); - if(f_len < 8) break; - - 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); - } - - - 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 - } - //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); - } - } -} -bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9) -{ - FILE* fp; - - if((fp=fopen(S9xGetFilename(".rtc"), "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"), "rb"))==NULL) - return (FALSE); - for (int i=0; i<16;i++) - { - fread(&(rtc_f9->reg[i]),1,1,fp); - } - 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); - - 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); -} - diff --git a/source/srtc.c b/source/srtc.c new file mode 100644 index 0000000..0e6f30e --- /dev/null +++ b/source/srtc.c @@ -0,0 +1,581 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include +#include "snes9x.h" +#include "srtc.h" +#include "memmap.h" + +/*** 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) + +***/ + +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 () +{ + rtc.index = -1; + rtc.mode = MODE_READ; +} + +void S9xHardResetSRTC () +{ + 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); +} + +/**********************************************************************************************/ +/* S9xSRTCComputeDayOfWeek() */ +/* Return 0-6 for Sunday-Saturday */ +/**********************************************************************************************/ +unsigned int S9xSRTCComputeDayOfWeek () +{ + 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; +} + + +/**********************************************************************************************/ +/* S9xSRTCDaysInMonth() */ +/* Return the number of days in a specific month for a certain year */ +/**********************************************************************************************/ +int S9xSRTCDaysInMmonth( 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 + + +/**********************************************************************************************/ +/* S9xUpdateSrtcTime() */ +/* Advance the S-RTC time if counting is enabled */ +/**********************************************************************************************/ +void S9xUpdateSrtcTime () +{ + 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; + } + } +} + + +/**********************************************************************************************/ +/* S9xSetSRTC() */ +/* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ +/**********************************************************************************************/ +void S9xSetSRTC (uint8 data, 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? + } + } +} + +/**********************************************************************************************/ +/* S9xGetSRTC() */ +/* This function retrieves data from the S-RTC */ +/**********************************************************************************************/ +uint8 S9xGetSRTC (uint16 Address) +{ + if ( rtc.mode == MODE_READ ) + { + if ( rtc.index < 0 ) + { + S9xUpdateSrtcTime (); // Only update it if the game reads it + rtc.index++; + return ( 0x0f ); // Send start marker. + } + else if (rtc.index > MAX_RTC_INDEX) + { + rtc.index = -1; // Setup for next set of reads + return ( 0x0f ); // Data done marker. + } + else + { + // Feed out the data + return rtc.data[rtc.index++]; + } + } + else + { + return 0x0; + } +} + +void S9xSRTCPreSaveState () +{ + if (Settings.SRTC) + { + S9xUpdateSrtcTime (); + + int s = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (s > 0x20000) + s = 0x20000; + + SRAM [s + 0] = rtc.needs_init; + SRAM [s + 1] = rtc.count_enable; + // memmove converted: Different mallocs [Neb] + memcpy (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); + SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; + SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; + +#ifdef LSB_FIRST + // memmove converted: Different mallocs [Neb] + memcpy (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); +#else + SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); + SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); + SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); + SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); + SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); + SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); + SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); + SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); +#endif + } +} + +void S9xSRTCPostLoadState () +{ + if (Settings.SRTC) + { + int s = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (s > 0x20000) + s = 0x20000; + + rtc.needs_init = SRAM [s + 0]; + rtc.count_enable = SRAM [s + 1]; + // memmove converted: Different mallocs [Neb] + memcpy (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); + rtc.index = SRAM [s + 3 + MAX_RTC_INDEX]; + rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX]; + +#ifdef LSB_FIRST + // memmove converted: Different mallocs [Neb] + memcpy (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); +#else + rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0); + rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8); + rtc.system_timestamp |= (SRAM [s + 7 + MAX_RTC_INDEX] << 16); + rtc.system_timestamp |= (SRAM [s + 8 + MAX_RTC_INDEX] << 24); + rtc.system_timestamp |= (SRAM [s + 9 + MAX_RTC_INDEX] << 32); + rtc.system_timestamp |= (SRAM [s + 10 + MAX_RTC_INDEX] << 40); + rtc.system_timestamp |= (SRAM [s + 11 + MAX_RTC_INDEX] << 48); + rtc.system_timestamp |= (SRAM [s + 12 + MAX_RTC_INDEX] << 56); +#endif + S9xUpdateSrtcTime (); + } +} + diff --git a/source/srtc.cpp b/source/srtc.cpp deleted file mode 100644 index 0e6f30e..0000000 --- a/source/srtc.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include -#include "snes9x.h" -#include "srtc.h" -#include "memmap.h" - -/*** 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) - -***/ - -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 () -{ - rtc.index = -1; - rtc.mode = MODE_READ; -} - -void S9xHardResetSRTC () -{ - 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); -} - -/**********************************************************************************************/ -/* S9xSRTCComputeDayOfWeek() */ -/* Return 0-6 for Sunday-Saturday */ -/**********************************************************************************************/ -unsigned int S9xSRTCComputeDayOfWeek () -{ - 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; -} - - -/**********************************************************************************************/ -/* S9xSRTCDaysInMonth() */ -/* Return the number of days in a specific month for a certain year */ -/**********************************************************************************************/ -int S9xSRTCDaysInMmonth( 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 - - -/**********************************************************************************************/ -/* S9xUpdateSrtcTime() */ -/* Advance the S-RTC time if counting is enabled */ -/**********************************************************************************************/ -void S9xUpdateSrtcTime () -{ - 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; - } - } -} - - -/**********************************************************************************************/ -/* S9xSetSRTC() */ -/* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ -/**********************************************************************************************/ -void S9xSetSRTC (uint8 data, 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? - } - } -} - -/**********************************************************************************************/ -/* S9xGetSRTC() */ -/* This function retrieves data from the S-RTC */ -/**********************************************************************************************/ -uint8 S9xGetSRTC (uint16 Address) -{ - if ( rtc.mode == MODE_READ ) - { - if ( rtc.index < 0 ) - { - S9xUpdateSrtcTime (); // Only update it if the game reads it - rtc.index++; - return ( 0x0f ); // Send start marker. - } - else if (rtc.index > MAX_RTC_INDEX) - { - rtc.index = -1; // Setup for next set of reads - return ( 0x0f ); // Data done marker. - } - else - { - // Feed out the data - return rtc.data[rtc.index++]; - } - } - else - { - return 0x0; - } -} - -void S9xSRTCPreSaveState () -{ - if (Settings.SRTC) - { - S9xUpdateSrtcTime (); - - int s = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (s > 0x20000) - s = 0x20000; - - SRAM [s + 0] = rtc.needs_init; - SRAM [s + 1] = rtc.count_enable; - // memmove converted: Different mallocs [Neb] - memcpy (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); - SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; - SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; - -#ifdef LSB_FIRST - // memmove converted: Different mallocs [Neb] - memcpy (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); -#else - SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); - SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); - SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); - SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); - SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); - SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); - SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); - SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); -#endif - } -} - -void S9xSRTCPostLoadState () -{ - if (Settings.SRTC) - { - int s = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (s > 0x20000) - s = 0x20000; - - rtc.needs_init = SRAM [s + 0]; - rtc.count_enable = SRAM [s + 1]; - // memmove converted: Different mallocs [Neb] - memcpy (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); - rtc.index = SRAM [s + 3 + MAX_RTC_INDEX]; - rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX]; - -#ifdef LSB_FIRST - // memmove converted: Different mallocs [Neb] - memcpy (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); -#else - rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0); - rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8); - rtc.system_timestamp |= (SRAM [s + 7 + MAX_RTC_INDEX] << 16); - rtc.system_timestamp |= (SRAM [s + 8 + MAX_RTC_INDEX] << 24); - rtc.system_timestamp |= (SRAM [s + 9 + MAX_RTC_INDEX] << 32); - rtc.system_timestamp |= (SRAM [s + 10 + MAX_RTC_INDEX] << 40); - rtc.system_timestamp |= (SRAM [s + 11 + MAX_RTC_INDEX] << 48); - rtc.system_timestamp |= (SRAM [s + 12 + MAX_RTC_INDEX] << 56); -#endif - S9xUpdateSrtcTime (); - } -} - diff --git a/source/tile.c b/source/tile.c new file mode 100644 index 0000000..3dcab74 --- /dev/null +++ b/source/tile.c @@ -0,0 +1,1065 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + 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, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + 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 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. +*******************************************************************************/ +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "display.h" +#include "gfx.h" +#include "tile.h" + +extern uint32 HeadMask [4]; +extern uint32 TailMask [5]; + +static uint8 ConvertTile (uint8 *pCache, uint32 TileAddr) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + switch (BG.BitShift) + { + case 8: + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + if ((pix = *(tp + 16))) + { + p1 |= odd_high[1][pix >> 4]; + p2 |= odd_low[1][pix & 0xf]; + } + if ((pix = *(tp + 17))) + { + p1 |= even_high[1][pix >> 4]; + p2 |= even_low[1][pix & 0xf]; + } + if ((pix = *(tp + 32))) + { + p1 |= odd_high[2][pix >> 4]; + p2 |= odd_low[2][pix & 0xf]; + } + if ((pix = *(tp + 33))) + { + p1 |= even_high[2][pix >> 4]; + p2 |= even_low[2][pix & 0xf]; + } + if ((pix = *(tp + 48))) + { + p1 |= odd_high[3][pix >> 4]; + p2 |= odd_low[3][pix & 0xf]; + } + if ((pix = *(tp + 49))) + { + p1 |= even_high[3][pix >> 4]; + p2 |= even_low[3][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + + case 4: + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + if ((pix = *(tp + 16))) + { + p1 |= odd_high[1][pix >> 4]; + p2 |= odd_low[1][pix & 0xf]; + } + if ((pix = *(tp + 17))) + { + p1 |= even_high[1][pix >> 4]; + p2 |= even_low[1][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + + case 2: + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + } + return (non_zero ? TRUE : BLANK_TILE); +} +#define PLOT_PIXEL(screen, pixel) (pixel) + + +static void WRITE_4PIXELS16 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + Screen [N] = ScreenColors [Pixel]; + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + Screen [N] = ScreenColors [Pixel]; + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_HALFWIDTH (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N += 2) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + Screen [N >> 1] = ScreenColors [Pixel]; + Depth [N >> 1] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_HALFWIDTH (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N += 2) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2 - N])) + { + Screen [N >> 1] = ScreenColors [Pixel]; + Depth [N >> 1] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16x2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + Screen [N * 2] = Screen [N * 2 + 1] = ScreenColors [Pixel]; + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPEDx2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + Screen [N * 2] = Screen [N * 2 + 1] = ScreenColors [Pixel]; + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16x2x2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPEDx2x2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; + } + } +} + +void DrawTile16 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) +} + +void DrawClippedTile16 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) +} + +void DrawTile16HalfWidth (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2) +} + +void DrawClippedTile16HalfWidth (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2) +} + +void DrawTile16x2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) +} + +void DrawClippedTile16x2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) +} + +void DrawTile16x2x2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) +} + +void DrawClippedTile16x2x2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) +} + +void DrawLargePixel16 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + uint16 pixel; + + RENDER_TILE_LARGE (ScreenColors [pixel], PLOT_PIXEL) +} + +void DrawLargePixel16HalfWidth (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + uint16 pixel; + + RENDER_TILE_LARGE_HALFWIDTH (ScreenColors [pixel], PLOT_PIXEL) +} + +static void WRITE_4PIXELS16_ADD (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_ADD (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_ADD1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N])); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_ADD1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N])); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_SUB (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_SUB (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_SUB1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_SUB1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint8 N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } +} + + +void DrawTile16Add (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + switch (Tile & (V_FLIP | H_FLIP)) + { + case 0: + bp = pCache + StartLine; + for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + { + for (uint8 N = 0; N < 8; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = bp[N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } + } + break; + case H_FLIP: + bp = pCache + StartLine; + for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + { + for (uint8 N = 0; N < 8; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } + } + break; + case H_FLIP | V_FLIP: + bp = pCache + 56 - StartLine; + for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + { + for (uint8 N = 0; N < 8; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } + } + break; + case V_FLIP: + bp = pCache + 56 - StartLine; + for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + { + for (uint8 N = 0; N < 8; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = bp[N])) + { + switch (SubDepth [N]) + { + case 0: + Screen [N] = ScreenColors [Pixel]; + break; + case 1: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); + break; + default: + Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); + break; + } + Depth [N] = GFX.Z2; + } + } + } + break; + default: + break; + } +} + +void DrawClippedTile16Add (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) +} + +void DrawTile16Add1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) +} + +void DrawClippedTile16Add1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) +} + +void DrawTile16Sub (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) +} + +void DrawClippedTile16Sub (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) +} + +void DrawTile16Sub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) +} + +void DrawClippedTile16Sub1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) +} + +static void WRITE_4PIXELS16_ADDF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + if (SubDepth [N] == 1) + Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], GFX.FixedColour)); + else + Screen [N] = ScreenColors [Pixel]; + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + if (SubDepth [N] == 1) + Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], GFX.FixedColour)); + else + Screen [N] = ScreenColors [Pixel]; + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_SUBF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) + { + if (SubDepth [N] == 1) + Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], GFX.FixedColour); + else + Screen [N] = ScreenColors [Pixel]; + Depth [N] = GFX.Z2; + } + } +} + +static void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) +{ + uint8 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + + for (uint N = 0; N < 4; N++) + { + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) + { + if (SubDepth [N] == 1) + Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], GFX.FixedColour); + else + Screen [N] = ScreenColors [Pixel]; + Depth [N] = GFX.Z2; + } + } +} + +void DrawTile16FixedAdd1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) +} + +void DrawClippedTile16FixedAdd1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, + WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) +} + +void DrawTile16FixedSub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) +} + +void DrawClippedTile16FixedSub1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, + WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) +} + +void DrawLargePixel16Add (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint16 pixel; + +#define LARGE_ADD_PIXEL(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_ADD (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_ADD_PIXEL) +} + +void DrawLargePixel16Add1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint16 pixel; + +#define LARGE_ADD_PIXEL1_2(s, p) \ +((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) \ + : p)) + + RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_ADD_PIXEL1_2) +} + +void DrawLargePixel16Sub (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint16 pixel; + +#define LARGE_SUB_PIXEL(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_SUB (p, *(s + GFX.Delta)) : \ + COLOR_SUB (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_SUB_PIXEL) +} + +void DrawLargePixel16Sub1_2 (uint32 Tile, int32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint16 pixel; + +#define LARGE_SUB_PIXEL1_2(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ + COLOR_SUB (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_SUB_PIXEL1_2) +} + diff --git a/source/tile.cpp b/source/tile.cpp deleted file mode 100644 index 3dcab74..0000000 --- a/source/tile.cpp +++ /dev/null @@ -1,1065 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - 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, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - 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 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. -*******************************************************************************/ -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "display.h" -#include "gfx.h" -#include "tile.h" - -extern uint32 HeadMask [4]; -extern uint32 TailMask [5]; - -static uint8 ConvertTile (uint8 *pCache, uint32 TileAddr) -{ - register uint8 *tp = &Memory.VRAM[TileAddr]; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; - - switch (BG.BitShift) - { - case 8: - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - if ((pix = *(tp + 16))) - { - p1 |= odd_high[1][pix >> 4]; - p2 |= odd_low[1][pix & 0xf]; - } - if ((pix = *(tp + 17))) - { - p1 |= even_high[1][pix >> 4]; - p2 |= even_low[1][pix & 0xf]; - } - if ((pix = *(tp + 32))) - { - p1 |= odd_high[2][pix >> 4]; - p2 |= odd_low[2][pix & 0xf]; - } - if ((pix = *(tp + 33))) - { - p1 |= even_high[2][pix >> 4]; - p2 |= even_low[2][pix & 0xf]; - } - if ((pix = *(tp + 48))) - { - p1 |= odd_high[3][pix >> 4]; - p2 |= odd_low[3][pix & 0xf]; - } - if ((pix = *(tp + 49))) - { - p1 |= even_high[3][pix >> 4]; - p2 |= even_low[3][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - - case 4: - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - if ((pix = *(tp + 16))) - { - p1 |= odd_high[1][pix >> 4]; - p2 |= odd_low[1][pix & 0xf]; - } - if ((pix = *(tp + 17))) - { - p1 |= even_high[1][pix >> 4]; - p2 |= even_low[1][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - - case 2: - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - } - return (non_zero ? TRUE : BLANK_TILE); -} -#define PLOT_PIXEL(screen, pixel) (pixel) - - -static void WRITE_4PIXELS16 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_HALFWIDTH (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N += 2) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - Screen [N >> 1] = ScreenColors [Pixel]; - Depth [N >> 1] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_HALFWIDTH (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N += 2) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2 - N])) - { - Screen [N >> 1] = ScreenColors [Pixel]; - Depth [N >> 1] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16x2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - Screen [N * 2] = Screen [N * 2 + 1] = ScreenColors [Pixel]; - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPEDx2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - Screen [N * 2] = Screen [N * 2 + 1] = ScreenColors [Pixel]; - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16x2x2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPEDx2x2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; - } - } -} - -void DrawTile16 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) -} - -void DrawClippedTile16 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) -} - -void DrawTile16HalfWidth (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2) -} - -void DrawClippedTile16HalfWidth (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2) -} - -void DrawTile16x2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) -} - -void DrawClippedTile16x2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) -} - -void DrawTile16x2x2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) -} - -void DrawClippedTile16x2x2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) -} - -void DrawLargePixel16 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - uint16 pixel; - - RENDER_TILE_LARGE (ScreenColors [pixel], PLOT_PIXEL) -} - -void DrawLargePixel16HalfWidth (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - uint16 pixel; - - RENDER_TILE_LARGE_HALFWIDTH (ScreenColors [pixel], PLOT_PIXEL) -} - -static void WRITE_4PIXELS16_ADD (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_ADD (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_ADD1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N])); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_ADD1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N])); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_SUB (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_SUB (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_SUB1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_SUB1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint8 N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } -} - - -void DrawTile16Add (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - switch (Tile & (V_FLIP | H_FLIP)) - { - case 0: - bp = pCache + StartLine; - for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } - } - break; - case H_FLIP: - bp = pCache + StartLine; - for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } - } - break; - case H_FLIP | V_FLIP: - bp = pCache + 56 - StartLine; - for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } - } - break; - case V_FLIP: - bp = pCache + 56 - StartLine; - for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[N])) - { - switch (SubDepth [N]) - { - case 0: - Screen [N] = ScreenColors [Pixel]; - break; - case 1: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour); - break; - default: - Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]); - break; - } - Depth [N] = GFX.Z2; - } - } - } - break; - default: - break; - } -} - -void DrawClippedTile16Add (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) -} - -void DrawTile16Add1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) -} - -void DrawClippedTile16Add1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) -} - -void DrawTile16Sub (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) -} - -void DrawClippedTile16Sub (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) -} - -void DrawTile16Sub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) -} - -void DrawClippedTile16Sub1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) -} - -static void WRITE_4PIXELS16_ADDF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - if (SubDepth [N] == 1) - Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], GFX.FixedColour)); - else - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - if (SubDepth [N] == 1) - Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], GFX.FixedColour)); - else - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_SUBF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) - { - if (SubDepth [N] == 1) - Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], GFX.FixedColour); - else - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } -} - -static void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (int32 Offset, uint8 *Pixels, uint16 *ScreenColors) -{ - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - - for (uint N = 0; N < 4; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) - { - if (SubDepth [N] == 1) - Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], GFX.FixedColour); - else - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } -} - -void DrawTile16FixedAdd1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) -} - -void DrawClippedTile16FixedAdd1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, - WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) -} - -void DrawTile16FixedSub1_2 (uint32 Tile, int32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) -} - -void DrawClippedTile16FixedSub1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, - WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) -} - -void DrawLargePixel16Add (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint16 pixel; - -#define LARGE_ADD_PIXEL(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_ADD_PIXEL) -} - -void DrawLargePixel16Add1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint16 pixel; - -#define LARGE_ADD_PIXEL1_2(s, p) \ -((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p)) - - RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_ADD_PIXEL1_2) -} - -void DrawLargePixel16Sub (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint16 pixel; - -#define LARGE_SUB_PIXEL(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_SUB (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_SUB_PIXEL) -} - -void DrawLargePixel16Sub1_2 (uint32 Tile, int32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint16 pixel; - -#define LARGE_SUB_PIXEL1_2(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (ScreenColors [pixel], LARGE_SUB_PIXEL1_2) -} - -- cgit v1.2.3