diff --git a/source/snes9x/c4.cpp b/source/snes9x/c4.cpp index ce40682..d586e79 100644 --- a/source/snes9x/c4.cpp +++ b/source/snes9x/c4.cpp @@ -328,14 +328,3 @@ uint8 * S9xGetMemPointerC4 (uint16 Address) return (NULL); return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); } - -#ifdef ZSNES_C4 -START_EXTERN_C - -void C4LoaDMem (char *C4RAM) -{ - memmove(C4RAM + (READ_WORD(C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(C4RAM + 0x1f40)), READ_WORD(C4RAM + 0x1f43)); -} - -END_EXTERN_C -#endif diff --git a/source/snes9x/c4.h b/source/snes9x/c4.h index 649d8bb..9b4c607 100644 --- a/source/snes9x/c4.h +++ b/source/snes9x/c4.h @@ -178,10 +178,6 @@ #ifndef _C4_H_ #define _C4_H_ -#ifdef ZSNES_C4 -START_EXTERN_C -#endif - extern int16 C4WFXVal; extern int16 C4WFYVal; extern int16 C4WFZVal; @@ -195,10 +191,6 @@ extern int16 C41FAngleRes; extern int16 C41FDist; extern int16 C41FDistVal; -#ifdef ZSNES_C4 -extern uint8 *C4Ram; -#endif - void C4TransfWireFrame (void); void C4TransfWireFrame2 (void); void C4CalcWireFrame (void); @@ -208,11 +200,6 @@ void C4Op1F (void); void S9xInitC4 (void); void S9xSetC4 (uint8, uint16); uint8 S9xGetC4 (uint16); - -#ifdef ZSNES_C4 -END_EXTERN_C -#endif - uint8 * S9xGetBasePointerC4 (uint16); uint8 * S9xGetMemPointerC4 (uint16); diff --git a/source/snes9x/cheats2.cpp b/source/snes9x/cheats2.cpp index d174c5c..fc076b5 100644 --- a/source/snes9x/cheats2.cpp +++ b/source/snes9x/cheats2.cpp @@ -186,12 +186,9 @@ static void S9xSetByteFree (uint8, uint32); static uint8 S9xGetByteFree (uint32 address) { uint32 Cycles = CPU.Cycles; - uint32 WaitAddress = CPU.WaitAddress; uint8 byte; byte = S9xGetByte(address); - - CPU.WaitAddress = WaitAddress; CPU.Cycles = Cycles; return (byte); @@ -200,11 +197,8 @@ static uint8 S9xGetByteFree (uint32 address) static void S9xSetByteFree (uint8 byte, uint32 address) { uint32 Cycles = CPU.Cycles; - uint32 WaitAddress = CPU.WaitAddress; S9xSetByte(byte, address); - - CPU.WaitAddress = WaitAddress; CPU.Cycles = Cycles; } diff --git a/source/snes9x/controls.cpp b/source/snes9x/controls.cpp index b94a402..267d07f 100644 --- a/source/snes9x/controls.cpp +++ b/source/snes9x/controls.cpp @@ -429,7 +429,6 @@ static const int ptrspeeds[4] = { 1, 1, 4, 8 }; S(ToggleBG2), \ S(ToggleBG3), \ S(ToggleEmuTurbo), \ - S(ToggleHDMA), \ S(ToggleSprites), \ S(ToggleTransparency) \ @@ -2458,11 +2457,6 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2) DisplayStateChange("Sprites", !(Settings.BG_Forced & 16)); break; - case ToggleHDMA: - Settings.DisableHDMA = !Settings.DisableHDMA; - DisplayStateChange("HDMA emulation", !Settings.DisableHDMA); - break; - case ToggleTransparency: Settings.Transparency = !Settings.Transparency; DisplayStateChange("Transparency effects", Settings.Transparency); diff --git a/source/snes9x/cpu.cpp b/source/snes9x/cpu.cpp index f2efb4c..547a446 100644 --- a/source/snes9x/cpu.cpp +++ b/source/snes9x/cpu.cpp @@ -208,12 +208,16 @@ static void S9xResetCPU (void) static void S9xSoftResetCPU (void) { CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. - CPU.PrevCycles = -1; + CPU.PrevCycles = CPU.Cycles; CPU.V_Counter = 0; CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); CPU.PCBase = NULL; - CPU.IRQActive = FALSE; - CPU.IRQPending = 0; + CPU.NMILine = FALSE; + CPU.IRQLine = FALSE; + CPU.IRQTransition = FALSE; + CPU.IRQLastState = FALSE; + CPU.IRQExternal = FALSE; + CPU.IRQPending = Timings.IRQPendCount; CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; CPU.FastROMSpeed = SLOW_ONE_CYCLE; @@ -226,9 +230,6 @@ static void S9xSoftResetCPU (void) CPU.WhichEvent = HC_RENDER_EVENT; CPU.NextEvent = Timings.RenderPos; CPU.WaitingForInterrupt = FALSE; - CPU.WaitAddress = 0xffffffff; - CPU.WaitCounter = 0; - CPU.PBPCAtOpcodeStart = 0xffffffff; CPU.AutoSaveTimer = 0; CPU.SRAMModified = FALSE; @@ -261,7 +262,6 @@ static void S9xSoftResetCPU (void) ICPU.S9xOpcodes = S9xOpcodesE1; ICPU.S9xOpLengths = S9xOpLengthsM1X1; - ICPU.CPUExecuting = TRUE; S9xUnpackStatus(); } diff --git a/source/snes9x/cpuexec.cpp b/source/snes9x/cpuexec.cpp index 0d372e4..5b1656e 100644 --- a/source/snes9x/cpuexec.cpp +++ b/source/snes9x/cpuexec.cpp @@ -1,598 +1,552 @@ -/*********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - (c) Copyright 2009 - 2010 BearOso, - OV2 - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com), - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code used in 1.39-1.51 - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - SPC7110 and RTC C++ emulator code used in 1.52+ - (c) Copyright 2009 byuu, - neviksti - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001 - 2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound emulator code used in 1.5-1.51 - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - Sound emulator code used in 1.52+ - (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - NTSC filter - (c) Copyright 2006 - 2007 Shay Green - - GTK+ GUI code - (c) Copyright 2004 - 2010 BearOso - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - (c) Copyright 2009 - 2010 OV2 - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2010 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com/ - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. - ***********************************************************************************/ - - -#include "snes9x.h" -#include "memmap.h" -#include "cpuops.h" -#include "dma.h" -#include "apu/apu.h" -#include "fxemu.h" -#include "snapshot.h" -#ifdef DEBUGGER -#include "debug.h" -#include "missing.h" -#endif - - -void S9xMainLoop (void) -{ - for (;;) - { - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (Timings.NMITriggerPos <= CPU.Cycles) - { - CPU.Flags &= ~NMI_FLAG; - Timings.NMITriggerPos = 0xffff; - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - Registers.PCw++; - } - - S9xOpcode_NMI(); - } - } - - #ifdef DEBUGGER - if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) - { - for (int Break = 0; Break != 6; Break++) - { - if (S9xBreakpoint[Break].Enabled && - S9xBreakpoint[Break].Bank == Registers.PB && - S9xBreakpoint[Break].Address == Registers.PCw) - { - if (S9xBreakpoint[Break].Enabled == 2) - S9xBreakpoint[Break].Enabled = TRUE; - else - CPU.Flags |= DEBUG_MODE_FLAG; - } - } - } - #endif - - if (CPU.Flags & IRQ_FLAG) - { - if (CPU.IRQPending) - // FIXME: In case of IRQ during WRAM refresh - CPU.IRQPending--; - else - { - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - Registers.PCw++; - } - - if (CPU.IRQActive && !Settings.DisableIRQ) - { - if (!CheckFlag(IRQ)) - // in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared. - S9xOpcode_IRQ(); - } - else - CPU.Flags &= ~IRQ_FLAG; - } - } - - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - - #ifdef DEBUGGER - if (CPU.Flags & DEBUG_MODE_FLAG) - break; - - if (CPU.Flags & TRACE_FLAG) - S9xTrace(); - - if (CPU.Flags & SINGLE_STEP_FLAG) - { - CPU.Flags &= ~SINGLE_STEP_FLAG; - CPU.Flags |= DEBUG_MODE_FLAG; - } - #endif - } - - #ifdef CPU_SHUTDOWN - CPU.PBPCAtOpcodeStart = Registers.PBPC; - #endif - - register uint8 Op; - register struct SOpcodes *Opcodes; - - CPU.PrevCycles = CPU.Cycles; - - if (CPU.PCBase) - { - Op = CPU.PCBase[Registers.PCw]; - CPU.Cycles += CPU.MemSpeed; - Opcodes = ICPU.S9xOpcodes; - } - else - { - Op = S9xGetByte(Registers.PBPC); - OpenBus = Op; - Opcodes = S9xOpcodesSlow; - } - - if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) - { - uint8 *oldPCBase = CPU.PCBase; - - CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); - if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) - Opcodes = S9xOpcodesSlow; - } - - Registers.PCw++; - (*Opcodes[Op].S9xOpcode)(); - - if (SA1.Executing) - S9xSA1MainLoop(); - - #if (S9X_ACCURACY_LEVEL <= 2) - while (CPU.Cycles >= CPU.NextEvent) - S9xDoHEventProcessing(); - #endif - } - - S9xPackStatus(); - - if (CPU.Flags & SCAN_KEYS_FLAG) - { - #ifdef DEBUGGER - if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) - #endif - S9xSyncSpeed(); - CPU.Flags &= ~SCAN_KEYS_FLAG; - } -} - -void S9xSetIRQ (uint32 source) -{ - CPU.IRQActive |= source; - CPU.IRQPending = Timings.IRQPendCount; - CPU.Flags |= IRQ_FLAG; - - if (CPU.WaitingForInterrupt) - { - // Force IRQ to trigger immediately after WAI - - // Final Fantasy Mystic Quest crashes without this. - CPU.WaitingForInterrupt = FALSE; - Registers.PCw++; - } - -#ifdef DEBUGGER - S9xTraceMessage("--- /IRQ low"); -#endif -} - -void S9xClearIRQ (uint32 source) -{ - CPU.IRQActive &= ~source; - if (!CPU.IRQActive) - CPU.Flags &= ~IRQ_FLAG; - -#ifdef DEBUGGER - S9xTraceMessage("--- /IRQ high"); -#endif -} - -void S9xDoHEventProcessing (void) -{ -#ifdef DEBUGGER - static char eventname[13][32] = - { - "", - "HC_HBLANK_START_EVENT", - "HC_IRQ_1_3_EVENT ", - "HC_HDMA_START_EVENT ", - "HC_IRQ_3_5_EVENT ", - "HC_HCOUNTER_MAX_EVENT", - "HC_IRQ_5_7_EVENT ", - "HC_HDMA_INIT_EVENT ", - "HC_IRQ_7_9_EVENT ", - "HC_RENDER_EVENT ", - "HC_IRQ_9_A_EVENT ", - "HC_WRAM_REFRESH_EVENT", - "HC_IRQ_A_1_EVENT " - }; -#endif - -#ifdef DEBUGGER - if (Settings.TraceHCEvent) - S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d", - eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); -#endif - -#ifdef CPU_SHUTDOWN - CPU.WaitCounter++; -#endif - - switch (CPU.WhichEvent) - { - case HC_HBLANK_START_EVENT: - S9xCheckMissingHTimerPosition(Timings.HBlankStart); - S9xReschedule(); - break; - - case HC_HDMA_START_EVENT: - S9xCheckMissingHTimerPosition(Timings.HDMAStart); - S9xReschedule(); - - if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) - { - #ifdef DEBUGGER - S9xTraceFormattedMessage("*** HDMA Transfer HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); - #endif - PPU.HDMA = S9xDoHDMA(PPU.HDMA); - } - - break; - - case HC_HCOUNTER_MAX_EVENT: - #ifndef ZSNES_FX - if (Settings.SuperFX) - { - if (!SuperFX.oneLineDone) - S9xSuperFXExec(); - SuperFX.oneLineDone = FALSE; - } - #else - S9xSuperFXExec(); - #endif - - S9xAPUEndScanline(); - CPU.Cycles -= Timings.H_Max; - S9xAPUSetReferenceTime(CPU.Cycles); - - if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max)) - Timings.NMITriggerPos -= Timings.H_Max; - - CPU.V_Counter++; - if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1 - { - CPU.V_Counter = 0; - Timings.InterlaceField ^= 1; - - // From byuu: - // [NTSC] - // interlace mode has 525 scanlines: 263 on the even frame, and 262 on the odd. - // non-interlace mode has 524 scanlines: 262 scanlines on both even and odd frames. - // [PAL] - // interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd. - // non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames. - if (IPPU.Interlace && !Timings.InterlaceField) - Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL) - else - Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL) - - Memory.FillRAM[0x213F] ^= 0x80; - PPU.RangeTimeOver = 0; - - // FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles. - Memory.FillRAM[0x4210] = Model->_5A22; - CPU.Flags &= ~NMI_FLAG; - Timings.NMITriggerPos = 0xffff; - - ICPU.Frame++; - PPU.HVBeamCounterLatched = 0; - CPU.Flags |= SCAN_KEYS_FLAG; - } - - // From byuu: - // In non-interlace mode, there are 341 dots per scanline, and 262 scanlines per frame. - // On odd frames, scanline 240 is one dot short. - // In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines, - // and odd frames have 262 scanlines. - // Interlace mode scanline 240 on odd frames is not missing a dot. - if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240 - Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360 - else - Timings.H_Max = Timings.H_Max_Master; // HC=1364 - - if (Model->_5A22 == 2) - { - if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240 - { - if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534 - Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538 - else - Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE; // HC=534 - } - } - else - Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; - - S9xCheckMissingHTimerPosition(0); - - if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240). - { - S9xEndScreenRefresh(); - PPU.HDMA = 0; - // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. - #ifdef DEBUGGER - missing.dma_this_frame = 0; - #endif - 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; - } - - // FIXME: writing to $4210 will wait 6 cycles. - Memory.FillRAM[0x4210] = 0x80 | Model->_5A22; - if (Memory.FillRAM[0x4200] & 0x80) - { - // FIXME: triggered at HC=6, checked just before the final CPU cycle, - // then, when to call S9xOpcode_NMI()? - CPU.Flags |= NMI_FLAG; - Timings.NMITriggerPos = 6 + 6; - } - - } - - if (CPU.V_Counter == PPU.ScreenHeight + 3) // FIXME: not true - { - if (Memory.FillRAM[0x4200] & 1) - S9xDoAutoJoypad(); - } - - if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1 - S9xStartScreenRefresh(); - - CPU.NextEvent = -1; - S9xReschedule(); - - break; - - case HC_HDMA_INIT_EVENT: - S9xCheckMissingHTimerPosition(Timings.HDMAInit); - S9xReschedule(); - - if (CPU.V_Counter == 0) - { - #ifdef DEBUGGER - S9xTraceFormattedMessage("*** HDMA Init HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); - #endif - S9xStartHDMA(); - } - - break; - - case HC_RENDER_EVENT: - if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight) - RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); - - S9xCheckMissingHTimerPosition(Timings.RenderPos); - S9xReschedule(); - - break; - - case HC_WRAM_REFRESH_EVENT: - #ifdef DEBUGGER - S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); - #endif - - S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); - CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; - - S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); - S9xReschedule(); - - break; - - case HC_IRQ_1_3_EVENT: - case HC_IRQ_3_5_EVENT: - case HC_IRQ_5_7_EVENT: - case HC_IRQ_7_9_EVENT: - case HC_IRQ_9_A_EVENT: - case HC_IRQ_A_1_EVENT: - if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_IRQ_SOURCE); - else - if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_IRQ_SOURCE); - - S9xReschedule(); - break; - } - -#ifdef DEBUGGER - if (Settings.TraceHCEvent) - S9xTraceFormattedMessage("--- HC event rescheduled (%s) expected HC:%04d current HC:%04d", - eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); -#endif -} - +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "cpuops.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "snapshot.h" +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + +static inline void S9xReschedule (void); + + +void S9xMainLoop (void) +{ + for (;;) + { + if (CPU.NMILine) + { + if (Timings.NMITriggerPos <= CPU.Cycles) + { + CPU.NMILine = FALSE; + Timings.NMITriggerPos = 0xffff; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + S9xOpcode_NMI(); + } + } + + if (CPU.IRQTransition || CPU.IRQExternal) + { + if (CPU.IRQPending) + CPU.IRQPending--; + else + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + CPU.IRQTransition = FALSE; + CPU.IRQPending = Timings.IRQPendCount; + + if (!CheckFlag(IRQ)) + S9xOpcode_IRQ(); + } + } + + #ifdef DEBUGGER + if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) + { + for (int Break = 0; Break != 6; Break++) + { + if (S9xBreakpoint[Break].Enabled && + S9xBreakpoint[Break].Bank == Registers.PB && + S9xBreakpoint[Break].Address == Registers.PCw) + { + if (S9xBreakpoint[Break].Enabled == 2) + S9xBreakpoint[Break].Enabled = TRUE; + else + CPU.Flags |= DEBUG_MODE_FLAG; + } + } + } + + if (CPU.Flags & DEBUG_MODE_FLAG) + break; + + if (CPU.Flags & TRACE_FLAG) + S9xTrace(); + + if (CPU.Flags & SINGLE_STEP_FLAG) + { + CPU.Flags &= ~SINGLE_STEP_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + #endif + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + + register uint8 Op; + register struct SOpcodes *Opcodes; + + if (CPU.PCBase) + { + Op = CPU.PCBase[Registers.PCw]; + CPU.PrevCycles = CPU.Cycles; + CPU.Cycles += CPU.MemSpeed; + S9xCheckInterrupts(); + Opcodes = ICPU.S9xOpcodes; + } + else + { + Op = S9xGetByte(Registers.PBPC); + OpenBus = Op; + Opcodes = S9xOpcodesSlow; + } + + if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + { + uint8 *oldPCBase = CPU.PCBase; + + CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); + if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) + Opcodes = S9xOpcodesSlow; + } + + Registers.PCw++; + (*Opcodes[Op].S9xOpcode)(); + + if (Settings.SA1) + S9xSA1MainLoop(); + } + + S9xPackStatus(); + + if (CPU.Flags & SCAN_KEYS_FLAG) + { + #ifdef DEBUGGER + if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) + #endif + S9xSyncSpeed(); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + +static inline void S9xReschedule (void) +{ + switch (CPU.WhichEvent) + { + case HC_HBLANK_START_EVENT: + CPU.WhichEvent = HC_HDMA_START_EVENT; + CPU.NextEvent = Timings.HDMAStart; + break; + + case HC_HDMA_START_EVENT: + CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; + CPU.NextEvent = Timings.H_Max; + break; + + case HC_HCOUNTER_MAX_EVENT: + CPU.WhichEvent = HC_HDMA_INIT_EVENT; + CPU.NextEvent = Timings.HDMAInit; + break; + + case HC_HDMA_INIT_EVENT: + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + break; + + case HC_RENDER_EVENT: + CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; + CPU.NextEvent = Timings.WRAMRefreshPos; + break; + + case HC_WRAM_REFRESH_EVENT: + CPU.WhichEvent = HC_HBLANK_START_EVENT; + CPU.NextEvent = Timings.HBlankStart; + break; + } +} + +void S9xDoHEventProcessing (void) +{ +#ifdef DEBUGGER + static char eventname[7][32] = + { + "", + "HC_HBLANK_START_EVENT", + "HC_HDMA_START_EVENT ", + "HC_HCOUNTER_MAX_EVENT", + "HC_HDMA_INIT_EVENT ", + "HC_RENDER_EVENT ", + "HC_WRAM_REFRESH_EVENT" + }; +#endif + +#ifdef DEBUGGER + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d", + eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); +#endif + + switch (CPU.WhichEvent) + { + case HC_HBLANK_START_EVENT: + S9xReschedule(); + break; + + case HC_HDMA_START_EVENT: + S9xReschedule(); + + if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + { + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** HDMA Transfer HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + #endif + PPU.HDMA = S9xDoHDMA(PPU.HDMA); + } + + break; + + case HC_HCOUNTER_MAX_EVENT: + if (Settings.SuperFX) + { + if (!SuperFX.oneLineDone) + S9xSuperFXExec(); + SuperFX.oneLineDone = FALSE; + } + + S9xAPUEndScanline(); + CPU.Cycles -= Timings.H_Max; + CPU.PrevCycles -= Timings.H_Max; + S9xAPUSetReferenceTime(CPU.Cycles); + + if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max)) + Timings.NMITriggerPos -= Timings.H_Max; + + CPU.V_Counter++; + if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1 + { + CPU.V_Counter = 0; + Timings.InterlaceField ^= 1; + + // From byuu: + // [NTSC] + // interlace mode has 525 scanlines: 263 on the even frame, and 262 on the odd. + // non-interlace mode has 524 scanlines: 262 scanlines on both even and odd frames. + // [PAL] + // interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd. + // non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames. + if (IPPU.Interlace && !Timings.InterlaceField) + Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL) + else + Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL) + + Memory.FillRAM[0x213F] ^= 0x80; + PPU.RangeTimeOver = 0; + + // FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles. + Memory.FillRAM[0x4210] = Model->_5A22; + CPU.NMILine = FALSE; + Timings.NMITriggerPos = 0xffff; + + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + } + + // From byuu: + // In non-interlace mode, there are 341 dots per scanline, and 262 scanlines per frame. + // On odd frames, scanline 240 is one dot short. + // In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines, + // and odd frames have 262 scanlines. + // Interlace mode scanline 240 on odd frames is not missing a dot. + if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240 + Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360 + else + Timings.H_Max = Timings.H_Max_Master; // HC=1364 + + if (Model->_5A22 == 2) + { + if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240 + { + if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534 + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538 + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE; // HC=534 + } + } + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240). + { + S9xEndScreenRefresh(); + PPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + #ifdef DEBUGGER + missing.dma_this_frame = 0; + #endif + 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; + } + + // FIXME: writing to $4210 will wait 6 cycles. + Memory.FillRAM[0x4210] = 0x80 | Model->_5A22; + if (Memory.FillRAM[0x4200] & 0x80) + { + // FIXME: triggered at HC=6, checked just before the final CPU cycle, + // then, when to call S9xOpcode_NMI()? + CPU.NMILine = TRUE; + Timings.NMITriggerPos = 6 + 6; + } + + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) // FIXME: not true + { + if (Memory.FillRAM[0x4200] & 1) + S9xDoAutoJoypad(); + } + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1 + S9xStartScreenRefresh(); + + S9xReschedule(); + + break; + + case HC_HDMA_INIT_EVENT: + S9xReschedule(); + + if (CPU.V_Counter == 0) + { + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** HDMA Init HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + #endif + S9xStartHDMA(); + } + + break; + + case HC_RENDER_EVENT: + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight) + RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); + + S9xReschedule(); + + break; + + case HC_WRAM_REFRESH_EVENT: + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); + #endif + + CPU.PrevCycles = CPU.Cycles; + CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; + S9xCheckInterrupts(); + + S9xReschedule(); + + break; + } + +#ifdef DEBUGGER + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event rescheduled (%s) expected HC:%04d current HC:%04d", + eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); +#endif +} diff --git a/source/snes9x/cpuexec.h b/source/snes9x/cpuexec.h index b11cff6..ccfadd5 100644 --- a/source/snes9x/cpuexec.h +++ b/source/snes9x/cpuexec.h @@ -179,6 +179,9 @@ #define _CPUEXEC_H_ #include "ppu.h" +#ifdef DEBUGGER +#include "debug.h" +#endif struct SOpcodes { @@ -193,7 +196,6 @@ struct SICPU uint8 _Zero; uint8 _Negative; uint8 _Overflow; - bool8 CPUExecuting; uint32 ShiftedPB; uint32 ShiftedDB; uint32 Frame; @@ -217,8 +219,6 @@ void S9xMainLoop (void); void S9xReset (void); void S9xSoftReset (void); void S9xDoHEventProcessing (void); -void S9xClearIRQ (uint32); -void S9xSetIRQ (uint32); static inline void S9xUnpackStatus (void) { @@ -270,84 +270,43 @@ static inline void S9xFixCycles (void) } } -static inline void S9xReschedule (void) +static inline void S9xCheckInterrupts (void) { - uint8 next = 0; - int32 hpos = 0; + bool8 thisIRQ = PPU.HTimerEnabled || PPU.VTimerEnabled; - switch (CPU.WhichEvent) + if (CPU.IRQLine && thisIRQ) + CPU.IRQTransition = TRUE; + + if (PPU.HTimerEnabled) { - case HC_HBLANK_START_EVENT: - case HC_IRQ_1_3_EVENT: - next = HC_HDMA_START_EVENT; - hpos = Timings.HDMAStart; - break; + int32 htimepos = PPU.HTimerPosition; + if (CPU.Cycles >= Timings.H_Max) + htimepos += Timings.H_Max; - case HC_HDMA_START_EVENT: - case HC_IRQ_3_5_EVENT: - next = HC_HCOUNTER_MAX_EVENT; - hpos = Timings.H_Max; - break; - - case HC_HCOUNTER_MAX_EVENT: - case HC_IRQ_5_7_EVENT: - next = HC_HDMA_INIT_EVENT; - hpos = Timings.HDMAInit; - break; - - case HC_HDMA_INIT_EVENT: - case HC_IRQ_7_9_EVENT: - next = HC_RENDER_EVENT; - hpos = Timings.RenderPos; - break; - - case HC_RENDER_EVENT: - case HC_IRQ_9_A_EVENT: - next = HC_WRAM_REFRESH_EVENT; - hpos = Timings.WRAMRefreshPos; - break; - - case HC_WRAM_REFRESH_EVENT: - case HC_IRQ_A_1_EVENT: - next = HC_HBLANK_START_EVENT; - hpos = Timings.HBlankStart; - break; + if (CPU.PrevCycles >= htimepos || CPU.Cycles < htimepos) + thisIRQ = FALSE; } - if (((int32) PPU.HTimerPosition > CPU.NextEvent) && ((int32) PPU.HTimerPosition < hpos)) + if (PPU.VTimerEnabled) { - hpos = (int32) PPU.HTimerPosition; + int32 vcounter = CPU.V_Counter; + if (CPU.Cycles >= Timings.H_Max) + vcounter++; - switch (next) - { - case HC_HDMA_START_EVENT: - next = HC_IRQ_1_3_EVENT; - break; - - case HC_HCOUNTER_MAX_EVENT: - next = HC_IRQ_3_5_EVENT; - break; - - case HC_HDMA_INIT_EVENT: - next = HC_IRQ_5_7_EVENT; - break; - - case HC_RENDER_EVENT: - next = HC_IRQ_7_9_EVENT; - break; - - case HC_WRAM_REFRESH_EVENT: - next = HC_IRQ_9_A_EVENT; - break; - - case HC_HBLANK_START_EVENT: - next = HC_IRQ_A_1_EVENT; - break; - } + if (vcounter != PPU.VTimerPosition) + thisIRQ = FALSE; } - CPU.NextEvent = hpos; - CPU.WhichEvent = next; + if (!CPU.IRQLastState && thisIRQ) + { +#ifdef DEBUGGER + S9xTraceFormattedMessage("--- /IRQ High->Low prev HC:%04d curr HC:%04d HTimer:%d Pos:%04d VTimer:%d Pos:%03d", + CPU.PrevCycles, CPU.Cycles, PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition); +#endif + CPU.IRQLine = TRUE; + } + + CPU.IRQLastState = thisIRQ; } #endif diff --git a/source/snes9x/cpumacro.h b/source/snes9x/cpumacro.h index 9b1fc4c..73c4340 100644 --- a/source/snes9x/cpumacro.h +++ b/source/snes9x/cpumacro.h @@ -280,7 +280,6 @@ static void Op##OP (void) \ S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \ else \ Registers.PCw = newPC.W; \ - CPUShutdown(); \ } \ } @@ -515,9 +514,6 @@ static inline void CPY (uint8 val) static inline void DEC16 (uint32 OpAddress, s9xwrap_t w) { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif uint16 Work16 = S9xGetWord(OpAddress, w) - 1; AddCycles(ONE_CYCLE); S9xSetWord(Work16, OpAddress, w, WRITE_10); @@ -527,9 +523,6 @@ static inline void DEC16 (uint32 OpAddress, s9xwrap_t w) static inline void DEC8 (uint32 OpAddress) { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif uint8 Work8 = S9xGetByte(OpAddress) - 1; AddCycles(ONE_CYCLE); S9xSetByte(Work8, OpAddress); @@ -551,9 +544,6 @@ static inline void EOR (uint8 val) static inline void INC16 (uint32 OpAddress, s9xwrap_t w) { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif uint16 Work16 = S9xGetWord(OpAddress, w) + 1; AddCycles(ONE_CYCLE); S9xSetWord(Work16, OpAddress, w, WRITE_10); @@ -563,9 +553,6 @@ static inline void INC16 (uint32 OpAddress, s9xwrap_t w) static inline void INC8 (uint32 OpAddress) { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif uint8 Work8 = S9xGetByte(OpAddress) + 1; AddCycles(ONE_CYCLE); S9xSetByte(Work8, OpAddress); diff --git a/source/snes9x/cpuops.cpp b/source/snes9x/cpuops.cpp index e67a869..d68cd37 100644 --- a/source/snes9x/cpuops.cpp +++ b/source/snes9x/cpuops.cpp @@ -1,4027 +1,3885 @@ -/*********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - (c) Copyright 2009 - 2010 BearOso, - OV2 - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com), - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code used in 1.39-1.51 - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - SPC7110 and RTC C++ emulator code used in 1.52+ - (c) Copyright 2009 byuu, - neviksti - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001 - 2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound emulator code used in 1.5-1.51 - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - Sound emulator code used in 1.52+ - (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - NTSC filter - (c) Copyright 2006 - 2007 Shay Green - - GTK+ GUI code - (c) Copyright 2004 - 2010 BearOso - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - (c) Copyright 2009 - 2010 OV2 - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2010 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com/ - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. - ***********************************************************************************/ - - -#include "snes9x.h" -#include "memmap.h" -#include "apu/apu.h" - -// for "Magic WDM" features -#ifdef DEBUGGER -#include "snapshot.h" -#include "display.h" -#include "debug.h" -#include "missing.h" -#endif - -#ifdef SA1_OPCODES -#define AddCycles(n) { } -#else -#if (S9X_ACCURACY_LEVEL >= 3) -#define AddCycles(n) { CPU.Cycles += (n); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } -#else -#define AddCycles(n) { CPU.Cycles += (n); } -#endif -#endif - -#include "cpuaddr.h" -#include "cpuops.h" -#include "cpumacro.h" - - -/* ADC ********************************************************************* */ - -static void Op69M1 (void) -{ - ADC(Immediate8(READ)); -} - -static void Op69M0 (void) -{ - ADC(Immediate16(READ)); -} - -static void Op69Slow (void) -{ - if (CheckMemory()) - ADC(Immediate8Slow(READ)); - else - ADC(Immediate16Slow(READ)); -} - -rOP8 (65M1, Direct, WRAP_BANK, ADC) -rOP16(65M0, Direct, WRAP_BANK, ADC) -rOPM (65Slow, DirectSlow, WRAP_BANK, ADC) - -rOP8 (75E1, DirectIndexedXE1, WRAP_BANK, ADC) -rOP8 (75E0M1, DirectIndexedXE0, WRAP_BANK, ADC) -rOP16(75E0M0, DirectIndexedXE0, WRAP_BANK, ADC) -rOPM (75Slow, DirectIndexedXSlow, WRAP_BANK, ADC) - -rOP8 (72E1, DirectIndirectE1, WRAP_NONE, ADC) -rOP8 (72E0M1, DirectIndirectE0, WRAP_NONE, ADC) -rOP16(72E0M0, DirectIndirectE0, WRAP_NONE, ADC) -rOPM (72Slow, DirectIndirectSlow, WRAP_NONE, ADC) - -rOP8 (61E1, DirectIndexedIndirectE1, WRAP_NONE, ADC) -rOP8 (61E0M1, DirectIndexedIndirectE0, WRAP_NONE, ADC) -rOP16(61E0M0, DirectIndexedIndirectE0, WRAP_NONE, ADC) -rOPM (61Slow, DirectIndexedIndirectSlow, WRAP_NONE, ADC) - -rOP8 (71E1, DirectIndirectIndexedE1, WRAP_NONE, ADC) -rOP8 (71E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) -rOP16(71E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) -rOP8 (71E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) -rOP16(71E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) -rOPM (71Slow, DirectIndirectIndexedSlow, WRAP_NONE, ADC) - -rOP8 (67M1, DirectIndirectLong, WRAP_NONE, ADC) -rOP16(67M0, DirectIndirectLong, WRAP_NONE, ADC) -rOPM (67Slow, DirectIndirectLongSlow, WRAP_NONE, ADC) - -rOP8 (77M1, DirectIndirectIndexedLong, WRAP_NONE, ADC) -rOP16(77M0, DirectIndirectIndexedLong, WRAP_NONE, ADC) -rOPM (77Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ADC) - -rOP8 (6DM1, Absolute, WRAP_NONE, ADC) -rOP16(6DM0, Absolute, WRAP_NONE, ADC) -rOPM (6DSlow, AbsoluteSlow, WRAP_NONE, ADC) - -rOP8 (7DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) -rOP16(7DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) -rOP8 (7DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) -rOP16(7DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) -rOPM (7DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ADC) - -rOP8 (79M1X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) -rOP16(79M0X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) -rOP8 (79M1X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) -rOP16(79M0X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) -rOPM (79Slow, AbsoluteIndexedYSlow, WRAP_NONE, ADC) - -rOP8 (6FM1, AbsoluteLong, WRAP_NONE, ADC) -rOP16(6FM0, AbsoluteLong, WRAP_NONE, ADC) -rOPM (6FSlow, AbsoluteLongSlow, WRAP_NONE, ADC) - -rOP8 (7FM1, AbsoluteLongIndexedX, WRAP_NONE, ADC) -rOP16(7FM0, AbsoluteLongIndexedX, WRAP_NONE, ADC) -rOPM (7FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ADC) - -rOP8 (63M1, StackRelative, WRAP_NONE, ADC) -rOP16(63M0, StackRelative, WRAP_NONE, ADC) -rOPM (63Slow, StackRelativeSlow, WRAP_NONE, ADC) - -rOP8 (73M1, StackRelativeIndirectIndexed, WRAP_NONE, ADC) -rOP16(73M0, StackRelativeIndirectIndexed, WRAP_NONE, ADC) -rOPM (73Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC) - -/* AND ********************************************************************* */ - -static void Op29M1 (void) -{ - Registers.AL &= Immediate8(READ); - SetZN(Registers.AL); -} - -static void Op29M0 (void) -{ - Registers.A.W &= Immediate16(READ); - SetZN(Registers.A.W); -} - -static void Op29Slow (void) -{ - if (CheckMemory()) - { - Registers.AL &= Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W &= Immediate16Slow(READ); - SetZN(Registers.A.W); - } -} - -rOP8 (25M1, Direct, WRAP_BANK, AND) -rOP16(25M0, Direct, WRAP_BANK, AND) -rOPM (25Slow, DirectSlow, WRAP_BANK, AND) - -rOP8 (35E1, DirectIndexedXE1, WRAP_BANK, AND) -rOP8 (35E0M1, DirectIndexedXE0, WRAP_BANK, AND) -rOP16(35E0M0, DirectIndexedXE0, WRAP_BANK, AND) -rOPM (35Slow, DirectIndexedXSlow, WRAP_BANK, AND) - -rOP8 (32E1, DirectIndirectE1, WRAP_NONE, AND) -rOP8 (32E0M1, DirectIndirectE0, WRAP_NONE, AND) -rOP16(32E0M0, DirectIndirectE0, WRAP_NONE, AND) -rOPM (32Slow, DirectIndirectSlow, WRAP_NONE, AND) - -rOP8 (21E1, DirectIndexedIndirectE1, WRAP_NONE, AND) -rOP8 (21E0M1, DirectIndexedIndirectE0, WRAP_NONE, AND) -rOP16(21E0M0, DirectIndexedIndirectE0, WRAP_NONE, AND) -rOPM (21Slow, DirectIndexedIndirectSlow, WRAP_NONE, AND) - -rOP8 (31E1, DirectIndirectIndexedE1, WRAP_NONE, AND) -rOP8 (31E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) -rOP16(31E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) -rOP8 (31E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) -rOP16(31E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) -rOPM (31Slow, DirectIndirectIndexedSlow, WRAP_NONE, AND) - -rOP8 (27M1, DirectIndirectLong, WRAP_NONE, AND) -rOP16(27M0, DirectIndirectLong, WRAP_NONE, AND) -rOPM (27Slow, DirectIndirectLongSlow, WRAP_NONE, AND) - -rOP8 (37M1, DirectIndirectIndexedLong, WRAP_NONE, AND) -rOP16(37M0, DirectIndirectIndexedLong, WRAP_NONE, AND) -rOPM (37Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, AND) - -rOP8 (2DM1, Absolute, WRAP_NONE, AND) -rOP16(2DM0, Absolute, WRAP_NONE, AND) -rOPM (2DSlow, AbsoluteSlow, WRAP_NONE, AND) - -rOP8 (3DM1X1, AbsoluteIndexedXX1, WRAP_NONE, AND) -rOP16(3DM0X1, AbsoluteIndexedXX1, WRAP_NONE, AND) -rOP8 (3DM1X0, AbsoluteIndexedXX0, WRAP_NONE, AND) -rOP16(3DM0X0, AbsoluteIndexedXX0, WRAP_NONE, AND) -rOPM (3DSlow, AbsoluteIndexedXSlow, WRAP_NONE, AND) - -rOP8 (39M1X1, AbsoluteIndexedYX1, WRAP_NONE, AND) -rOP16(39M0X1, AbsoluteIndexedYX1, WRAP_NONE, AND) -rOP8 (39M1X0, AbsoluteIndexedYX0, WRAP_NONE, AND) -rOP16(39M0X0, AbsoluteIndexedYX0, WRAP_NONE, AND) -rOPM (39Slow, AbsoluteIndexedYSlow, WRAP_NONE, AND) - -rOP8 (2FM1, AbsoluteLong, WRAP_NONE, AND) -rOP16(2FM0, AbsoluteLong, WRAP_NONE, AND) -rOPM (2FSlow, AbsoluteLongSlow, WRAP_NONE, AND) - -rOP8 (3FM1, AbsoluteLongIndexedX, WRAP_NONE, AND) -rOP16(3FM0, AbsoluteLongIndexedX, WRAP_NONE, AND) -rOPM (3FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, AND) - -rOP8 (23M1, StackRelative, WRAP_NONE, AND) -rOP16(23M0, StackRelative, WRAP_NONE, AND) -rOPM (23Slow, StackRelativeSlow, WRAP_NONE, AND) - -rOP8 (33M1, StackRelativeIndirectIndexed, WRAP_NONE, AND) -rOP16(33M0, StackRelativeIndirectIndexed, WRAP_NONE, AND) -rOPM (33Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, AND) - -/* ASL ********************************************************************* */ - -static void Op0AM1 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = (Registers.AL & 0x80) != 0; - Registers.AL <<= 1; - SetZN(Registers.AL); -} - -static void Op0AM0 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = (Registers.AH & 0x80) != 0; - Registers.A.W <<= 1; - SetZN(Registers.A.W); -} - -static void Op0ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - ICPU._Carry = (Registers.AL & 0x80) != 0; - Registers.AL <<= 1; - SetZN(Registers.AL); - } - else - { - ICPU._Carry = (Registers.AH & 0x80) != 0; - Registers.A.W <<= 1; - SetZN(Registers.A.W); - } -} - -mOP8 (06M1, Direct, WRAP_BANK, ASL) -mOP16(06M0, Direct, WRAP_BANK, ASL) -mOPM (06Slow, DirectSlow, WRAP_BANK, ASL) - -mOP8 (16E1, DirectIndexedXE1, WRAP_BANK, ASL) -mOP8 (16E0M1, DirectIndexedXE0, WRAP_BANK, ASL) -mOP16(16E0M0, DirectIndexedXE0, WRAP_BANK, ASL) -mOPM (16Slow, DirectIndexedXSlow, WRAP_BANK, ASL) - -mOP8 (0EM1, Absolute, WRAP_NONE, ASL) -mOP16(0EM0, Absolute, WRAP_NONE, ASL) -mOPM (0ESlow, AbsoluteSlow, WRAP_NONE, ASL) - -mOP8 (1EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) -mOP16(1EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) -mOP8 (1EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) -mOP16(1EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) -mOPM (1ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ASL) - -/* BIT ********************************************************************* */ - -static void Op89M1 (void) -{ - ICPU._Zero = Registers.AL & Immediate8(READ); -} - -static void Op89M0 (void) -{ - ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0; -} - -static void Op89Slow (void) -{ - if (CheckMemory()) - ICPU._Zero = Registers.AL & Immediate8Slow(READ); - else - ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0; -} - -rOP8 (24M1, Direct, WRAP_BANK, BIT) -rOP16(24M0, Direct, WRAP_BANK, BIT) -rOPM (24Slow, DirectSlow, WRAP_BANK, BIT) - -rOP8 (34E1, DirectIndexedXE1, WRAP_BANK, BIT) -rOP8 (34E0M1, DirectIndexedXE0, WRAP_BANK, BIT) -rOP16(34E0M0, DirectIndexedXE0, WRAP_BANK, BIT) -rOPM (34Slow, DirectIndexedXSlow, WRAP_BANK, BIT) - -rOP8 (2CM1, Absolute, WRAP_NONE, BIT) -rOP16(2CM0, Absolute, WRAP_NONE, BIT) -rOPM (2CSlow, AbsoluteSlow, WRAP_NONE, BIT) - -rOP8 (3CM1X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) -rOP16(3CM0X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) -rOP8 (3CM1X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) -rOP16(3CM0X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) -rOPM (3CSlow, AbsoluteIndexedXSlow, WRAP_NONE, BIT) - -/* CMP ********************************************************************* */ - -static void OpC9M1 (void) -{ - int16 Int16 = (int16) Registers.AL - (int16) Immediate8(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); -} - -static void OpC9M0 (void) -{ - int32 Int32 = (int32) Registers.A.W - (int32) Immediate16(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); -} - -static void OpC9Slow (void) -{ - if (CheckMemory()) - { - int16 Int16 = (int16) Registers.AL - (int16) Immediate8Slow(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); - } - else - { - int32 Int32 = (int32) Registers.A.W - (int32) Immediate16Slow(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); - } -} - -rOP8 (C5M1, Direct, WRAP_BANK, CMP) -rOP16(C5M0, Direct, WRAP_BANK, CMP) -rOPM (C5Slow, DirectSlow, WRAP_BANK, CMP) - -rOP8 (D5E1, DirectIndexedXE1, WRAP_BANK, CMP) -rOP8 (D5E0M1, DirectIndexedXE0, WRAP_BANK, CMP) -rOP16(D5E0M0, DirectIndexedXE0, WRAP_BANK, CMP) -rOPM (D5Slow, DirectIndexedXSlow, WRAP_BANK, CMP) - -rOP8 (D2E1, DirectIndirectE1, WRAP_NONE, CMP) -rOP8 (D2E0M1, DirectIndirectE0, WRAP_NONE, CMP) -rOP16(D2E0M0, DirectIndirectE0, WRAP_NONE, CMP) -rOPM (D2Slow, DirectIndirectSlow, WRAP_NONE, CMP) - -rOP8 (C1E1, DirectIndexedIndirectE1, WRAP_NONE, CMP) -rOP8 (C1E0M1, DirectIndexedIndirectE0, WRAP_NONE, CMP) -rOP16(C1E0M0, DirectIndexedIndirectE0, WRAP_NONE, CMP) -rOPM (C1Slow, DirectIndexedIndirectSlow, WRAP_NONE, CMP) - -rOP8 (D1E1, DirectIndirectIndexedE1, WRAP_NONE, CMP) -rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) -rOP16(D1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) -rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) -rOP16(D1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) -rOPM (D1Slow, DirectIndirectIndexedSlow, WRAP_NONE, CMP) - -rOP8 (C7M1, DirectIndirectLong, WRAP_NONE, CMP) -rOP16(C7M0, DirectIndirectLong, WRAP_NONE, CMP) -rOPM (C7Slow, DirectIndirectLongSlow, WRAP_NONE, CMP) - -rOP8 (D7M1, DirectIndirectIndexedLong, WRAP_NONE, CMP) -rOP16(D7M0, DirectIndirectIndexedLong, WRAP_NONE, CMP) -rOPM (D7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, CMP) - -rOP8 (CDM1, Absolute, WRAP_NONE, CMP) -rOP16(CDM0, Absolute, WRAP_NONE, CMP) -rOPM (CDSlow, AbsoluteSlow, WRAP_NONE, CMP) - -rOP8 (DDM1X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) -rOP16(DDM0X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) -rOP8 (DDM1X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) -rOP16(DDM0X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) -rOPM (DDSlow, AbsoluteIndexedXSlow, WRAP_NONE, CMP) - -rOP8 (D9M1X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) -rOP16(D9M0X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) -rOP8 (D9M1X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) -rOP16(D9M0X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) -rOPM (D9Slow, AbsoluteIndexedYSlow, WRAP_NONE, CMP) - -rOP8 (CFM1, AbsoluteLong, WRAP_NONE, CMP) -rOP16(CFM0, AbsoluteLong, WRAP_NONE, CMP) -rOPM (CFSlow, AbsoluteLongSlow, WRAP_NONE, CMP) - -rOP8 (DFM1, AbsoluteLongIndexedX, WRAP_NONE, CMP) -rOP16(DFM0, AbsoluteLongIndexedX, WRAP_NONE, CMP) -rOPM (DFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, CMP) - -rOP8 (C3M1, StackRelative, WRAP_NONE, CMP) -rOP16(C3M0, StackRelative, WRAP_NONE, CMP) -rOPM (C3Slow, StackRelativeSlow, WRAP_NONE, CMP) - -rOP8 (D3M1, StackRelativeIndirectIndexed, WRAP_NONE, CMP) -rOP16(D3M0, StackRelativeIndirectIndexed, WRAP_NONE, CMP) -rOPM (D3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP) - -/* CPX ********************************************************************* */ - -static void OpE0X1 (void) -{ - int16 Int16 = (int16) Registers.XL - (int16) Immediate8(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); -} - -static void OpE0X0 (void) -{ - int32 Int32 = (int32) Registers.X.W - (int32) Immediate16(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); -} - -static void OpE0Slow (void) -{ - if (CheckIndex()) - { - int16 Int16 = (int16) Registers.XL - (int16) Immediate8Slow(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); - } - else - { - int32 Int32 = (int32) Registers.X.W - (int32) Immediate16Slow(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); - } -} - -rOP8 (E4X1, Direct, WRAP_BANK, CPX) -rOP16(E4X0, Direct, WRAP_BANK, CPX) -rOPX (E4Slow, DirectSlow, WRAP_BANK, CPX) - -rOP8 (ECX1, Absolute, WRAP_NONE, CPX) -rOP16(ECX0, Absolute, WRAP_NONE, CPX) -rOPX (ECSlow, AbsoluteSlow, WRAP_NONE, CPX) - -/* CPY ********************************************************************* */ - -static void OpC0X1 (void) -{ - int16 Int16 = (int16) Registers.YL - (int16) Immediate8(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); -} - -static void OpC0X0 (void) -{ - int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); -} - -static void OpC0Slow (void) -{ - if (CheckIndex()) - { - int16 Int16 = (int16) Registers.YL - (int16) Immediate8Slow(READ); - ICPU._Carry = Int16 >= 0; - SetZN((uint8) Int16); - } - else - { - int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16Slow(READ); - ICPU._Carry = Int32 >= 0; - SetZN((uint16) Int32); - } -} - -rOP8 (C4X1, Direct, WRAP_BANK, CPY) -rOP16(C4X0, Direct, WRAP_BANK, CPY) -rOPX (C4Slow, DirectSlow, WRAP_BANK, CPY) - -rOP8 (CCX1, Absolute, WRAP_NONE, CPY) -rOP16(CCX0, Absolute, WRAP_NONE, CPY) -rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY) - -/* DEC ********************************************************************* */ - -static void Op3AM1 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.AL--; - SetZN(Registers.AL); -} - -static void Op3AM0 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.A.W--; - SetZN(Registers.A.W); -} - -static void Op3ASlow (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - - if (CheckMemory()) - { - Registers.AL--; - SetZN(Registers.AL); - } - else - { - Registers.A.W--; - SetZN(Registers.A.W); - } -} - -mOP8 (C6M1, Direct, WRAP_BANK, DEC) -mOP16(C6M0, Direct, WRAP_BANK, DEC) -mOPM (C6Slow, DirectSlow, WRAP_BANK, DEC) - -mOP8 (D6E1, DirectIndexedXE1, WRAP_BANK, DEC) -mOP8 (D6E0M1, DirectIndexedXE0, WRAP_BANK, DEC) -mOP16(D6E0M0, DirectIndexedXE0, WRAP_BANK, DEC) -mOPM (D6Slow, DirectIndexedXSlow, WRAP_BANK, DEC) - -mOP8 (CEM1, Absolute, WRAP_NONE, DEC) -mOP16(CEM0, Absolute, WRAP_NONE, DEC) -mOPM (CESlow, AbsoluteSlow, WRAP_NONE, DEC) - -mOP8 (DEM1X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) -mOP16(DEM0X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) -mOP8 (DEM1X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) -mOP16(DEM0X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) -mOPM (DESlow, AbsoluteIndexedXSlow, WRAP_NONE, DEC) - -/* EOR ********************************************************************* */ - -static void Op49M1 (void) -{ - Registers.AL ^= Immediate8(READ); - SetZN(Registers.AL); -} - -static void Op49M0 (void) -{ - Registers.A.W ^= Immediate16(READ); - SetZN(Registers.A.W); -} - -static void Op49Slow (void) -{ - if (CheckMemory()) - { - Registers.AL ^= Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W ^= Immediate16Slow(READ); - SetZN(Registers.A.W); - } -} - -rOP8 (45M1, Direct, WRAP_BANK, EOR) -rOP16(45M0, Direct, WRAP_BANK, EOR) -rOPM (45Slow, DirectSlow, WRAP_BANK, EOR) - -rOP8 (55E1, DirectIndexedXE1, WRAP_BANK, EOR) -rOP8 (55E0M1, DirectIndexedXE0, WRAP_BANK, EOR) -rOP16(55E0M0, DirectIndexedXE0, WRAP_BANK, EOR) -rOPM (55Slow, DirectIndexedXSlow, WRAP_BANK, EOR) - -rOP8 (52E1, DirectIndirectE1, WRAP_NONE, EOR) -rOP8 (52E0M1, DirectIndirectE0, WRAP_NONE, EOR) -rOP16(52E0M0, DirectIndirectE0, WRAP_NONE, EOR) -rOPM (52Slow, DirectIndirectSlow, WRAP_NONE, EOR) - -rOP8 (41E1, DirectIndexedIndirectE1, WRAP_NONE, EOR) -rOP8 (41E0M1, DirectIndexedIndirectE0, WRAP_NONE, EOR) -rOP16(41E0M0, DirectIndexedIndirectE0, WRAP_NONE, EOR) -rOPM (41Slow, DirectIndexedIndirectSlow, WRAP_NONE, EOR) - -rOP8 (51E1, DirectIndirectIndexedE1, WRAP_NONE, EOR) -rOP8 (51E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) -rOP16(51E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) -rOP8 (51E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) -rOP16(51E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) -rOPM (51Slow, DirectIndirectIndexedSlow, WRAP_NONE, EOR) - -rOP8 (47M1, DirectIndirectLong, WRAP_NONE, EOR) -rOP16(47M0, DirectIndirectLong, WRAP_NONE, EOR) -rOPM (47Slow, DirectIndirectLongSlow, WRAP_NONE, EOR) - -rOP8 (57M1, DirectIndirectIndexedLong, WRAP_NONE, EOR) -rOP16(57M0, DirectIndirectIndexedLong, WRAP_NONE, EOR) -rOPM (57Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, EOR) - -rOP8 (4DM1, Absolute, WRAP_NONE, EOR) -rOP16(4DM0, Absolute, WRAP_NONE, EOR) -rOPM (4DSlow, AbsoluteSlow, WRAP_NONE, EOR) - -rOP8 (5DM1X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) -rOP16(5DM0X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) -rOP8 (5DM1X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) -rOP16(5DM0X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) -rOPM (5DSlow, AbsoluteIndexedXSlow, WRAP_NONE, EOR) - -rOP8 (59M1X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) -rOP16(59M0X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) -rOP8 (59M1X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) -rOP16(59M0X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) -rOPM (59Slow, AbsoluteIndexedYSlow, WRAP_NONE, EOR) - -rOP8 (4FM1, AbsoluteLong, WRAP_NONE, EOR) -rOP16(4FM0, AbsoluteLong, WRAP_NONE, EOR) -rOPM (4FSlow, AbsoluteLongSlow, WRAP_NONE, EOR) - -rOP8 (5FM1, AbsoluteLongIndexedX, WRAP_NONE, EOR) -rOP16(5FM0, AbsoluteLongIndexedX, WRAP_NONE, EOR) -rOPM (5FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, EOR) - -rOP8 (43M1, StackRelative, WRAP_NONE, EOR) -rOP16(43M0, StackRelative, WRAP_NONE, EOR) -rOPM (43Slow, StackRelativeSlow, WRAP_NONE, EOR) - -rOP8 (53M1, StackRelativeIndirectIndexed, WRAP_NONE, EOR) -rOP16(53M0, StackRelativeIndirectIndexed, WRAP_NONE, EOR) -rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR) - -/* INC ********************************************************************* */ - -static void Op1AM1 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.AL++; - SetZN(Registers.AL); -} - -static void Op1AM0 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.A.W++; - SetZN(Registers.A.W); -} - -static void Op1ASlow (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - - if (CheckMemory()) - { - Registers.AL++; - SetZN(Registers.AL); - } - else - { - Registers.A.W++; - SetZN(Registers.A.W); - } -} - -mOP8 (E6M1, Direct, WRAP_BANK, INC) -mOP16(E6M0, Direct, WRAP_BANK, INC) -mOPM (E6Slow, DirectSlow, WRAP_BANK, INC) - -mOP8 (F6E1, DirectIndexedXE1, WRAP_BANK, INC) -mOP8 (F6E0M1, DirectIndexedXE0, WRAP_BANK, INC) -mOP16(F6E0M0, DirectIndexedXE0, WRAP_BANK, INC) -mOPM (F6Slow, DirectIndexedXSlow, WRAP_BANK, INC) - -mOP8 (EEM1, Absolute, WRAP_NONE, INC) -mOP16(EEM0, Absolute, WRAP_NONE, INC) -mOPM (EESlow, AbsoluteSlow, WRAP_NONE, INC) - -mOP8 (FEM1X1, AbsoluteIndexedXX1, WRAP_NONE, INC) -mOP16(FEM0X1, AbsoluteIndexedXX1, WRAP_NONE, INC) -mOP8 (FEM1X0, AbsoluteIndexedXX0, WRAP_NONE, INC) -mOP16(FEM0X0, AbsoluteIndexedXX0, WRAP_NONE, INC) -mOPM (FESlow, AbsoluteIndexedXSlow, WRAP_NONE, INC) - -/* LDA ********************************************************************* */ - -static void OpA9M1 (void) -{ - Registers.AL = Immediate8(READ); - SetZN(Registers.AL); -} - -static void OpA9M0 (void) -{ - Registers.A.W = Immediate16(READ); - SetZN(Registers.A.W); -} - -static void OpA9Slow (void) -{ - if (CheckMemory()) - { - Registers.AL = Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W = Immediate16Slow(READ); - SetZN(Registers.A.W); - } -} - -rOP8 (A5M1, Direct, WRAP_BANK, LDA) -rOP16(A5M0, Direct, WRAP_BANK, LDA) -rOPM (A5Slow, DirectSlow, WRAP_BANK, LDA) - -rOP8 (B5E1, DirectIndexedXE1, WRAP_BANK, LDA) -rOP8 (B5E0M1, DirectIndexedXE0, WRAP_BANK, LDA) -rOP16(B5E0M0, DirectIndexedXE0, WRAP_BANK, LDA) -rOPM (B5Slow, DirectIndexedXSlow, WRAP_BANK, LDA) - -rOP8 (B2E1, DirectIndirectE1, WRAP_NONE, LDA) -rOP8 (B2E0M1, DirectIndirectE0, WRAP_NONE, LDA) -rOP16(B2E0M0, DirectIndirectE0, WRAP_NONE, LDA) -rOPM (B2Slow, DirectIndirectSlow, WRAP_NONE, LDA) - -rOP8 (A1E1, DirectIndexedIndirectE1, WRAP_NONE, LDA) -rOP8 (A1E0M1, DirectIndexedIndirectE0, WRAP_NONE, LDA) -rOP16(A1E0M0, DirectIndexedIndirectE0, WRAP_NONE, LDA) -rOPM (A1Slow, DirectIndexedIndirectSlow, WRAP_NONE, LDA) - -rOP8 (B1E1, DirectIndirectIndexedE1, WRAP_NONE, LDA) -rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) -rOP16(B1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) -rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) -rOP16(B1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) -rOPM (B1Slow, DirectIndirectIndexedSlow, WRAP_NONE, LDA) - -rOP8 (A7M1, DirectIndirectLong, WRAP_NONE, LDA) -rOP16(A7M0, DirectIndirectLong, WRAP_NONE, LDA) -rOPM (A7Slow, DirectIndirectLongSlow, WRAP_NONE, LDA) - -rOP8 (B7M1, DirectIndirectIndexedLong, WRAP_NONE, LDA) -rOP16(B7M0, DirectIndirectIndexedLong, WRAP_NONE, LDA) -rOPM (B7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, LDA) - -rOP8 (ADM1, Absolute, WRAP_NONE, LDA) -rOP16(ADM0, Absolute, WRAP_NONE, LDA) -rOPM (ADSlow, AbsoluteSlow, WRAP_NONE, LDA) - -rOP8 (BDM1X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) -rOP16(BDM0X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) -rOP8 (BDM1X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) -rOP16(BDM0X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) -rOPM (BDSlow, AbsoluteIndexedXSlow, WRAP_NONE, LDA) - -rOP8 (B9M1X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) -rOP16(B9M0X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) -rOP8 (B9M1X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) -rOP16(B9M0X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) -rOPM (B9Slow, AbsoluteIndexedYSlow, WRAP_NONE, LDA) - -rOP8 (AFM1, AbsoluteLong, WRAP_NONE, LDA) -rOP16(AFM0, AbsoluteLong, WRAP_NONE, LDA) -rOPM (AFSlow, AbsoluteLongSlow, WRAP_NONE, LDA) - -rOP8 (BFM1, AbsoluteLongIndexedX, WRAP_NONE, LDA) -rOP16(BFM0, AbsoluteLongIndexedX, WRAP_NONE, LDA) -rOPM (BFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, LDA) - -rOP8 (A3M1, StackRelative, WRAP_NONE, LDA) -rOP16(A3M0, StackRelative, WRAP_NONE, LDA) -rOPM (A3Slow, StackRelativeSlow, WRAP_NONE, LDA) - -rOP8 (B3M1, StackRelativeIndirectIndexed, WRAP_NONE, LDA) -rOP16(B3M0, StackRelativeIndirectIndexed, WRAP_NONE, LDA) -rOPM (B3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA) - -/* LDX ********************************************************************* */ - -static void OpA2X1 (void) -{ - Registers.XL = Immediate8(READ); - SetZN(Registers.XL); -} - -static void OpA2X0 (void) -{ - Registers.X.W = Immediate16(READ); - SetZN(Registers.X.W); -} - -static void OpA2Slow (void) -{ - if (CheckIndex()) - { - Registers.XL = Immediate8Slow(READ); - SetZN(Registers.XL); - } - else - { - Registers.X.W = Immediate16Slow(READ); - SetZN(Registers.X.W); - } -} - -rOP8 (A6X1, Direct, WRAP_BANK, LDX) -rOP16(A6X0, Direct, WRAP_BANK, LDX) -rOPX (A6Slow, DirectSlow, WRAP_BANK, LDX) - -rOP8 (B6E1, DirectIndexedYE1, WRAP_BANK, LDX) -rOP8 (B6E0X1, DirectIndexedYE0, WRAP_BANK, LDX) -rOP16(B6E0X0, DirectIndexedYE0, WRAP_BANK, LDX) -rOPX (B6Slow, DirectIndexedYSlow, WRAP_BANK, LDX) - -rOP8 (AEX1, Absolute, WRAP_BANK, LDX) -rOP16(AEX0, Absolute, WRAP_BANK, LDX) -rOPX (AESlow, AbsoluteSlow, WRAP_BANK, LDX) - -rOP8 (BEX1, AbsoluteIndexedYX1, WRAP_BANK, LDX) -rOP16(BEX0, AbsoluteIndexedYX0, WRAP_BANK, LDX) -rOPX (BESlow, AbsoluteIndexedYSlow, WRAP_BANK, LDX) - -/* LDY ********************************************************************* */ - -static void OpA0X1 (void) -{ - Registers.YL = Immediate8(READ); - SetZN(Registers.YL); -} - -static void OpA0X0 (void) -{ - Registers.Y.W = Immediate16(READ); - SetZN(Registers.Y.W); -} - -static void OpA0Slow (void) -{ - if (CheckIndex()) - { - Registers.YL = Immediate8Slow(READ); - SetZN(Registers.YL); - } - else - { - Registers.Y.W = Immediate16Slow(READ); - SetZN(Registers.Y.W); - } -} - -rOP8 (A4X1, Direct, WRAP_BANK, LDY) -rOP16(A4X0, Direct, WRAP_BANK, LDY) -rOPX (A4Slow, DirectSlow, WRAP_BANK, LDY) - -rOP8 (B4E1, DirectIndexedXE1, WRAP_BANK, LDY) -rOP8 (B4E0X1, DirectIndexedXE0, WRAP_BANK, LDY) -rOP16(B4E0X0, DirectIndexedXE0, WRAP_BANK, LDY) -rOPX (B4Slow, DirectIndexedXSlow, WRAP_BANK, LDY) - -rOP8 (ACX1, Absolute, WRAP_BANK, LDY) -rOP16(ACX0, Absolute, WRAP_BANK, LDY) -rOPX (ACSlow, AbsoluteSlow, WRAP_BANK, LDY) - -rOP8 (BCX1, AbsoluteIndexedXX1, WRAP_BANK, LDY) -rOP16(BCX0, AbsoluteIndexedXX0, WRAP_BANK, LDY) -rOPX (BCSlow, AbsoluteIndexedXSlow, WRAP_BANK, LDY) - -/* LSR ********************************************************************* */ - -static void Op4AM1 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = Registers.AL & 1; - Registers.AL >>= 1; - SetZN(Registers.AL); -} - -static void Op4AM0 (void) -{ - AddCycles(ONE_CYCLE); - ICPU._Carry = Registers.A.W & 1; - Registers.A.W >>= 1; - SetZN(Registers.A.W); -} - -static void Op4ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - ICPU._Carry = Registers.AL & 1; - Registers.AL >>= 1; - SetZN(Registers.AL); - } - else - { - ICPU._Carry = Registers.A.W & 1; - Registers.A.W >>= 1; - SetZN(Registers.A.W); - } -} - -mOP8 (46M1, Direct, WRAP_BANK, LSR) -mOP16(46M0, Direct, WRAP_BANK, LSR) -mOPM (46Slow, DirectSlow, WRAP_BANK, LSR) - -mOP8 (56E1, DirectIndexedXE1, WRAP_BANK, LSR) -mOP8 (56E0M1, DirectIndexedXE0, WRAP_BANK, LSR) -mOP16(56E0M0, DirectIndexedXE0, WRAP_BANK, LSR) -mOPM (56Slow, DirectIndexedXSlow, WRAP_BANK, LSR) - -mOP8 (4EM1, Absolute, WRAP_NONE, LSR) -mOP16(4EM0, Absolute, WRAP_NONE, LSR) -mOPM (4ESlow, AbsoluteSlow, WRAP_NONE, LSR) - -mOP8 (5EM1X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) -mOP16(5EM0X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) -mOP8 (5EM1X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) -mOP16(5EM0X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) -mOPM (5ESlow, AbsoluteIndexedXSlow, WRAP_NONE, LSR) - -/* ORA ********************************************************************* */ - -static void Op09M1 (void) -{ - Registers.AL |= Immediate8(READ); - SetZN(Registers.AL); -} - -static void Op09M0 (void) -{ - Registers.A.W |= Immediate16(READ); - SetZN(Registers.A.W); -} - -static void Op09Slow (void) -{ - if (CheckMemory()) - { - Registers.AL |= Immediate8Slow(READ); - SetZN(Registers.AL); - } - else - { - Registers.A.W |= Immediate16Slow(READ); - SetZN(Registers.A.W); - } -} - -rOP8 (05M1, Direct, WRAP_BANK, ORA) -rOP16(05M0, Direct, WRAP_BANK, ORA) -rOPM (05Slow, DirectSlow, WRAP_BANK, ORA) - -rOP8 (15E1, DirectIndexedXE1, WRAP_BANK, ORA) -rOP8 (15E0M1, DirectIndexedXE0, WRAP_BANK, ORA) -rOP16(15E0M0, DirectIndexedXE0, WRAP_BANK, ORA) -rOPM (15Slow, DirectIndexedXSlow, WRAP_BANK, ORA) - -rOP8 (12E1, DirectIndirectE1, WRAP_NONE, ORA) -rOP8 (12E0M1, DirectIndirectE0, WRAP_NONE, ORA) -rOP16(12E0M0, DirectIndirectE0, WRAP_NONE, ORA) -rOPM (12Slow, DirectIndirectSlow, WRAP_NONE, ORA) - -rOP8 (01E1, DirectIndexedIndirectE1, WRAP_NONE, ORA) -rOP8 (01E0M1, DirectIndexedIndirectE0, WRAP_NONE, ORA) -rOP16(01E0M0, DirectIndexedIndirectE0, WRAP_NONE, ORA) -rOPM (01Slow, DirectIndexedIndirectSlow, WRAP_NONE, ORA) - -rOP8 (11E1, DirectIndirectIndexedE1, WRAP_NONE, ORA) -rOP8 (11E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) -rOP16(11E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) -rOP8 (11E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) -rOP16(11E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) -rOPM (11Slow, DirectIndirectIndexedSlow, WRAP_NONE, ORA) - -rOP8 (07M1, DirectIndirectLong, WRAP_NONE, ORA) -rOP16(07M0, DirectIndirectLong, WRAP_NONE, ORA) -rOPM (07Slow, DirectIndirectLongSlow, WRAP_NONE, ORA) - -rOP8 (17M1, DirectIndirectIndexedLong, WRAP_NONE, ORA) -rOP16(17M0, DirectIndirectIndexedLong, WRAP_NONE, ORA) -rOPM (17Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ORA) - -rOP8 (0DM1, Absolute, WRAP_NONE, ORA) -rOP16(0DM0, Absolute, WRAP_NONE, ORA) -rOPM (0DSlow, AbsoluteSlow, WRAP_NONE, ORA) - -rOP8 (1DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) -rOP16(1DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) -rOP8 (1DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) -rOP16(1DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) -rOPM (1DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ORA) - -rOP8 (19M1X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) -rOP16(19M0X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) -rOP8 (19M1X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) -rOP16(19M0X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) -rOPM (19Slow, AbsoluteIndexedYSlow, WRAP_NONE, ORA) - -rOP8 (0FM1, AbsoluteLong, WRAP_NONE, ORA) -rOP16(0FM0, AbsoluteLong, WRAP_NONE, ORA) -rOPM (0FSlow, AbsoluteLongSlow, WRAP_NONE, ORA) - -rOP8 (1FM1, AbsoluteLongIndexedX, WRAP_NONE, ORA) -rOP16(1FM0, AbsoluteLongIndexedX, WRAP_NONE, ORA) -rOPM (1FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ORA) - -rOP8 (03M1, StackRelative, WRAP_NONE, ORA) -rOP16(03M0, StackRelative, WRAP_NONE, ORA) -rOPM (03Slow, StackRelativeSlow, WRAP_NONE, ORA) - -rOP8 (13M1, StackRelativeIndirectIndexed, WRAP_NONE, ORA) -rOP16(13M0, StackRelativeIndirectIndexed, WRAP_NONE, ORA) -rOPM (13Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA) - -/* ROL ********************************************************************* */ - -static void Op2AM1 (void) -{ - AddCycles(ONE_CYCLE); - uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x100; - Registers.AL = (uint8) w; - SetZN(Registers.AL); -} - -static void Op2AM0 (void) -{ - AddCycles(ONE_CYCLE); - uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x10000; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); -} - -static void Op2ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x100; - Registers.AL = (uint8) w; - SetZN(Registers.AL); - } - else - { - uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); - ICPU._Carry = w >= 0x10000; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); - } -} - -mOP8 (26M1, Direct, WRAP_BANK, ROL) -mOP16(26M0, Direct, WRAP_BANK, ROL) -mOPM (26Slow, DirectSlow, WRAP_BANK, ROL) - -mOP8 (36E1, DirectIndexedXE1, WRAP_BANK, ROL) -mOP8 (36E0M1, DirectIndexedXE0, WRAP_BANK, ROL) -mOP16(36E0M0, DirectIndexedXE0, WRAP_BANK, ROL) -mOPM (36Slow, DirectIndexedXSlow, WRAP_BANK, ROL) - -mOP8 (2EM1, Absolute, WRAP_NONE, ROL) -mOP16(2EM0, Absolute, WRAP_NONE, ROL) -mOPM (2ESlow, AbsoluteSlow, WRAP_NONE, ROL) - -mOP8 (3EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) -mOP16(3EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) -mOP8 (3EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) -mOP16(3EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) -mOPM (3ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROL) - -/* ROR ********************************************************************* */ - -static void Op6AM1 (void) -{ - AddCycles(ONE_CYCLE); - uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); - ICPU._Carry = w & 1; - w >>= 1; - Registers.AL = (uint8) w; - SetZN(Registers.AL); -} - -static void Op6AM0 (void) -{ - AddCycles(ONE_CYCLE); - uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); - ICPU._Carry = w & 1; - w >>= 1; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); -} - -static void Op6ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); - ICPU._Carry = w & 1; - w >>= 1; - Registers.AL = (uint8) w; - SetZN(Registers.AL); - } - else - { - uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); - ICPU._Carry = w & 1; - w >>= 1; - Registers.A.W = (uint16) w; - SetZN(Registers.A.W); - } -} - -mOP8 (66M1, Direct, WRAP_BANK, ROR) -mOP16(66M0, Direct, WRAP_BANK, ROR) -mOPM (66Slow, DirectSlow, WRAP_BANK, ROR) - -mOP8 (76E1, DirectIndexedXE1, WRAP_BANK, ROR) -mOP8 (76E0M1, DirectIndexedXE0, WRAP_BANK, ROR) -mOP16(76E0M0, DirectIndexedXE0, WRAP_BANK, ROR) -mOPM (76Slow, DirectIndexedXSlow, WRAP_BANK, ROR) - -mOP8 (6EM1, Absolute, WRAP_NONE, ROR) -mOP16(6EM0, Absolute, WRAP_NONE, ROR) -mOPM (6ESlow, AbsoluteSlow, WRAP_NONE, ROR) - -mOP8 (7EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) -mOP16(7EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) -mOP8 (7EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) -mOP16(7EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) -mOPM (7ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROR) - -/* SBC ********************************************************************* */ - -static void OpE9M1 (void) -{ - SBC(Immediate8(READ)); -} - -static void OpE9M0 (void) -{ - SBC(Immediate16(READ)); -} - -static void OpE9Slow (void) -{ - if (CheckMemory()) - SBC(Immediate8Slow(READ)); - else - SBC(Immediate16Slow(READ)); -} - -rOP8 (E5M1, Direct, WRAP_BANK, SBC) -rOP16(E5M0, Direct, WRAP_BANK, SBC) -rOPM (E5Slow, DirectSlow, WRAP_BANK, SBC) - -rOP8 (F5E1, DirectIndexedXE1, WRAP_BANK, SBC) -rOP8 (F5E0M1, DirectIndexedXE0, WRAP_BANK, SBC) -rOP16(F5E0M0, DirectIndexedXE0, WRAP_BANK, SBC) -rOPM (F5Slow, DirectIndexedXSlow, WRAP_BANK, SBC) - -rOP8 (F2E1, DirectIndirectE1, WRAP_NONE, SBC) -rOP8 (F2E0M1, DirectIndirectE0, WRAP_NONE, SBC) -rOP16(F2E0M0, DirectIndirectE0, WRAP_NONE, SBC) -rOPM (F2Slow, DirectIndirectSlow, WRAP_NONE, SBC) - -rOP8 (E1E1, DirectIndexedIndirectE1, WRAP_NONE, SBC) -rOP8 (E1E0M1, DirectIndexedIndirectE0, WRAP_NONE, SBC) -rOP16(E1E0M0, DirectIndexedIndirectE0, WRAP_NONE, SBC) -rOPM (E1Slow, DirectIndexedIndirectSlow, WRAP_NONE, SBC) - -rOP8 (F1E1, DirectIndirectIndexedE1, WRAP_NONE, SBC) -rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) -rOP16(F1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) -rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) -rOP16(F1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) -rOPM (F1Slow, DirectIndirectIndexedSlow, WRAP_NONE, SBC) - -rOP8 (E7M1, DirectIndirectLong, WRAP_NONE, SBC) -rOP16(E7M0, DirectIndirectLong, WRAP_NONE, SBC) -rOPM (E7Slow, DirectIndirectLongSlow, WRAP_NONE, SBC) - -rOP8 (F7M1, DirectIndirectIndexedLong, WRAP_NONE, SBC) -rOP16(F7M0, DirectIndirectIndexedLong, WRAP_NONE, SBC) -rOPM (F7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, SBC) - -rOP8 (EDM1, Absolute, WRAP_NONE, SBC) -rOP16(EDM0, Absolute, WRAP_NONE, SBC) -rOPM (EDSlow, AbsoluteSlow, WRAP_NONE, SBC) - -rOP8 (FDM1X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) -rOP16(FDM0X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) -rOP8 (FDM1X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) -rOP16(FDM0X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) -rOPM (FDSlow, AbsoluteIndexedXSlow, WRAP_NONE, SBC) - -rOP8 (F9M1X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) -rOP16(F9M0X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) -rOP8 (F9M1X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) -rOP16(F9M0X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) -rOPM (F9Slow, AbsoluteIndexedYSlow, WRAP_NONE, SBC) - -rOP8 (EFM1, AbsoluteLong, WRAP_NONE, SBC) -rOP16(EFM0, AbsoluteLong, WRAP_NONE, SBC) -rOPM (EFSlow, AbsoluteLongSlow, WRAP_NONE, SBC) - -rOP8 (FFM1, AbsoluteLongIndexedX, WRAP_NONE, SBC) -rOP16(FFM0, AbsoluteLongIndexedX, WRAP_NONE, SBC) -rOPM (FFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, SBC) - -rOP8 (E3M1, StackRelative, WRAP_NONE, SBC) -rOP16(E3M0, StackRelative, WRAP_NONE, SBC) -rOPM (E3Slow, StackRelativeSlow, WRAP_NONE, SBC) - -rOP8 (F3M1, StackRelativeIndirectIndexed, WRAP_NONE, SBC) -rOP16(F3M0, StackRelativeIndirectIndexed, WRAP_NONE, SBC) -rOPM (F3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC) - -/* STA ********************************************************************* */ - -wOP8 (85M1, Direct, WRAP_BANK, STA) -wOP16(85M0, Direct, WRAP_BANK, STA) -wOPM (85Slow, DirectSlow, WRAP_BANK, STA) - -wOP8 (95E1, DirectIndexedXE1, WRAP_BANK, STA) -wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) -wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) -wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) - -wOP8 (92E1, DirectIndirectE1, WRAP_NONE, STA) -wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) -wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) -wOPM (92Slow, DirectIndirectSlow, WRAP_NONE, STA) - -wOP8 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) -wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) -wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) -wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) - -wOP8 (91E1, DirectIndirectIndexedE1, WRAP_NONE, STA) -wOP8 (91E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) -wOP16(91E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) -wOP8 (91E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) -wOP16(91E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) -wOPM (91Slow, DirectIndirectIndexedSlow, WRAP_NONE, STA) - -wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) -wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) -wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) - -wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) -wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) -wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) - -wOP8 (8DM1, Absolute, WRAP_NONE, STA) -wOP16(8DM0, Absolute, WRAP_NONE, STA) -wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) - -wOP8 (9DM1X1, AbsoluteIndexedXX1, WRAP_NONE, STA) -wOP16(9DM0X1, AbsoluteIndexedXX1, WRAP_NONE, STA) -wOP8 (9DM1X0, AbsoluteIndexedXX0, WRAP_NONE, STA) -wOP16(9DM0X0, AbsoluteIndexedXX0, WRAP_NONE, STA) -wOPM (9DSlow, AbsoluteIndexedXSlow, WRAP_NONE, STA) - -wOP8 (99M1X1, AbsoluteIndexedYX1, WRAP_NONE, STA) -wOP16(99M0X1, AbsoluteIndexedYX1, WRAP_NONE, STA) -wOP8 (99M1X0, AbsoluteIndexedYX0, WRAP_NONE, STA) -wOP16(99M0X0, AbsoluteIndexedYX0, WRAP_NONE, STA) -wOPM (99Slow, AbsoluteIndexedYSlow, WRAP_NONE, STA) - -wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) -wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) -wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) - -wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) -wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) -wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) - -wOP8 (83M1, StackRelative, WRAP_NONE, STA) -wOP16(83M0, StackRelative, WRAP_NONE, STA) -wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) - -wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) -wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) -wOPM (93Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, STA) - -/* STX ********************************************************************* */ - -wOP8 (86X1, Direct, WRAP_BANK, STX) -wOP16(86X0, Direct, WRAP_BANK, STX) -wOPX (86Slow, DirectSlow, WRAP_BANK, STX) - -wOP8 (96E1, DirectIndexedYE1, WRAP_BANK, STX) -wOP8 (96E0X1, DirectIndexedYE0, WRAP_BANK, STX) -wOP16(96E0X0, DirectIndexedYE0, WRAP_BANK, STX) -wOPX (96Slow, DirectIndexedYSlow, WRAP_BANK, STX) - -wOP8 (8EX1, Absolute, WRAP_BANK, STX) -wOP16(8EX0, Absolute, WRAP_BANK, STX) -wOPX (8ESlow, AbsoluteSlow, WRAP_BANK, STX) - -/* STY ********************************************************************* */ - -wOP8 (84X1, Direct, WRAP_BANK, STY) -wOP16(84X0, Direct, WRAP_BANK, STY) -wOPX (84Slow, DirectSlow, WRAP_BANK, STY) - -wOP8 (94E1, DirectIndexedXE1, WRAP_BANK, STY) -wOP8 (94E0X1, DirectIndexedXE0, WRAP_BANK, STY) -wOP16(94E0X0, DirectIndexedXE0, WRAP_BANK, STY) -wOPX (94Slow, DirectIndexedXSlow, WRAP_BANK, STY) - -wOP8 (8CX1, Absolute, WRAP_BANK, STY) -wOP16(8CX0, Absolute, WRAP_BANK, STY) -wOPX (8CSlow, AbsoluteSlow, WRAP_BANK, STY) - -/* STZ ********************************************************************* */ - -wOP8 (64M1, Direct, WRAP_BANK, STZ) -wOP16(64M0, Direct, WRAP_BANK, STZ) -wOPM (64Slow, DirectSlow, WRAP_BANK, STZ) - -wOP8 (74E1, DirectIndexedXE1, WRAP_BANK, STZ) -wOP8 (74E0M1, DirectIndexedXE0, WRAP_BANK, STZ) -wOP16(74E0M0, DirectIndexedXE0, WRAP_BANK, STZ) -wOPM (74Slow, DirectIndexedXSlow, WRAP_BANK, STZ) - -wOP8 (9CM1, Absolute, WRAP_NONE, STZ) -wOP16(9CM0, Absolute, WRAP_NONE, STZ) -wOPM (9CSlow, AbsoluteSlow, WRAP_NONE, STZ) - -wOP8 (9EM1X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) -wOP16(9EM0X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) -wOP8 (9EM1X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) -wOP16(9EM0X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) -wOPM (9ESlow, AbsoluteIndexedXSlow, WRAP_NONE, STZ) - -/* TRB ********************************************************************* */ - -mOP8 (14M1, Direct, WRAP_BANK, TRB) -mOP16(14M0, Direct, WRAP_BANK, TRB) -mOPM (14Slow, DirectSlow, WRAP_BANK, TRB) - -mOP8 (1CM1, Absolute, WRAP_BANK, TRB) -mOP16(1CM0, Absolute, WRAP_BANK, TRB) -mOPM (1CSlow, AbsoluteSlow, WRAP_BANK, TRB) - -/* TSB ********************************************************************* */ - -mOP8 (04M1, Direct, WRAP_BANK, TSB) -mOP16(04M0, Direct, WRAP_BANK, TSB) -mOPM (04Slow, DirectSlow, WRAP_BANK, TSB) - -mOP8 (0CM1, Absolute, WRAP_BANK, TSB) -mOP16(0CM0, Absolute, WRAP_BANK, TSB) -mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) - -/* Branch Instructions ***************************************************** */ - -#ifdef CPU_SHUTDOWN - -#ifndef SA1_OPCODES - -inline void CPUShutdown (void) -{ - if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) - { - // Don't skip cycles with a pending NMI or IRQ - could cause delayed interrupt. - if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_FLAG | NMI_FLAG))) - { - CPU.WaitAddress = 0xffffffff; - if (Settings.SA1) - S9xSA1ExecuteDuringSleep(); - CPU.Cycles = CPU.NextEvent; - ICPU.CPUExecuting = FALSE; - S9xAPUExecute(); - ICPU.CPUExecuting = TRUE; - } - else - if (CPU.WaitCounter >= 2) - CPU.WaitCounter = 1; - else - CPU.WaitCounter--; - } -} - -#else - -inline void CPUShutdown (void) -{ - if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) - { - if (CPU.WaitCounter >= 1) - SA1.Executing = FALSE; - else - CPU.WaitCounter++; - } -} - -#endif - -#else - -#define CPUShutdown() - -#endif - -// BCC -bOP(90E0, Relative, !CheckCarry(), 0, 0) -bOP(90E1, Relative, !CheckCarry(), 0, 1) -bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) - -// BCS -bOP(B0E0, Relative, CheckCarry(), 0, 0) -bOP(B0E1, Relative, CheckCarry(), 0, 1) -bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) - -// BEQ -bOP(F0E0, Relative, CheckZero(), 2, 0) -bOP(F0E1, Relative, CheckZero(), 2, 1) -bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) - -// BMI -bOP(30E0, Relative, CheckNegative(), 1, 0) -bOP(30E1, Relative, CheckNegative(), 1, 1) -bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) - -// BNE -bOP(D0E0, Relative, !CheckZero(), 1, 0) -bOP(D0E1, Relative, !CheckZero(), 1, 1) -bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) - -// BPL -bOP(10E0, Relative, !CheckNegative(), 1, 0) -bOP(10E1, Relative, !CheckNegative(), 1, 1) -bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation()) - -// BRA -bOP(80E0, Relative, 1, X, 0) -bOP(80E1, Relative, 1, X, 1) -bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) - -// BVC -bOP(50E0, Relative, !CheckOverflow(), 0, 0) -bOP(50E1, Relative, !CheckOverflow(), 0, 1) -bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation()) - -// BVS -bOP(70E0, Relative, CheckOverflow(), 0, 0) -bOP(70E1, Relative, CheckOverflow(), 0, 1) -bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) - -// BRL -static void Op82 (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); -} - -static void Op82Slow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); -} - -/* Flag Instructions ******************************************************* */ - -// CLC -static void Op18 (void) -{ - ClearCarry(); - AddCycles(ONE_CYCLE); -} - -// SEC -static void Op38 (void) -{ - SetCarry(); - AddCycles(ONE_CYCLE); -} - -// CLD -static void OpD8 (void) -{ - ClearDecimal(); - AddCycles(ONE_CYCLE); -} - -// SED -static void OpF8 (void) -{ - SetDecimal(); - AddCycles(ONE_CYCLE); -#ifdef DEBUGGER - missing.decimal_mode = 1; -#endif -} - -// CLI -static void Op58 (void) -{ - ClearIRQ(); - AddCycles(ONE_CYCLE); - //CHECK_FOR_IRQ(); -} - -// SEI -static void Op78 (void) -{ - SetIRQ(); - AddCycles(ONE_CYCLE); -} - -// CLV -static void OpB8 (void) -{ - ClearOverflow(); - AddCycles(ONE_CYCLE); -} - -/* DEX/DEY ***************************************************************** */ - -static void OpCAX1 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.XL--; - SetZN(Registers.XL); -} - -static void OpCAX0 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.X.W--; - SetZN(Registers.X.W); -} - -static void OpCASlow (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - - if (CheckIndex()) - { - Registers.XL--; - SetZN(Registers.XL); - } - else - { - Registers.X.W--; - SetZN(Registers.X.W); - } -} - -static void Op88X1 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.YL--; - SetZN(Registers.YL); -} - -static void Op88X0 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.Y.W--; - SetZN(Registers.Y.W); -} - -static void Op88Slow (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - - if (CheckIndex()) - { - Registers.YL--; - SetZN(Registers.YL); - } - else - { - Registers.Y.W--; - SetZN(Registers.Y.W); - } -} - -/* INX/INY ***************************************************************** */ - -static void OpE8X1 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.XL++; - SetZN(Registers.XL); -} - -static void OpE8X0 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.X.W++; - SetZN(Registers.X.W); -} - -static void OpE8Slow (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - - if (CheckIndex()) - { - Registers.XL++; - SetZN(Registers.XL); - } - else - { - Registers.X.W++; - SetZN(Registers.X.W); - } -} - -static void OpC8X1 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.YL++; - SetZN(Registers.YL); -} - -static void OpC8X0 (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - Registers.Y.W++; - SetZN(Registers.Y.W); -} - -static void OpC8Slow (void) -{ - AddCycles(ONE_CYCLE); -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - - if (CheckIndex()) - { - Registers.YL--; - SetZN(Registers.YL); - } - else - { - Registers.Y.W--; - SetZN(Registers.Y.W); - } -} - -/* NOP ********************************************************************* */ - -static void OpEA (void) -{ - AddCycles(ONE_CYCLE); -} - -/* PUSH Instructions ******************************************************* */ - -#define PushW(w) \ - S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \ - Registers.S.W -= 2; - -#define PushWE(w) \ - Registers.SL--; \ - S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \ - Registers.SL--; - -#define PushB(b) \ - S9xSetByte(b, Registers.S.W--); - -#define PushBE(b) \ - S9xSetByte(b, Registers.S.W); \ - Registers.SL--; - -// PEA -static void OpF4E0 (void) -{ - uint16 val = (uint16) Absolute(NONE); - PushW(val); - OpenBus = val & 0xff; -} - -static void OpF4E1 (void) -{ - // Note: PEA is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 val = (uint16) Absolute(NONE); - PushW(val); - OpenBus = val & 0xff; - Registers.SH = 1; -} - -static void OpF4Slow (void) -{ - uint16 val = (uint16) AbsoluteSlow(NONE); - PushW(val); - OpenBus = val & 0xff; - if (CheckEmulation()) - Registers.SH = 1; -} - -// PEI -static void OpD4E0 (void) -{ - uint16 val = (uint16) DirectIndirectE0(NONE); - PushW(val); - OpenBus = val & 0xff; -} - -static void OpD4E1 (void) -{ - // Note: PEI is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 val = (uint16) DirectIndirectE1(NONE); - PushW(val); - OpenBus = val & 0xff; - Registers.SH = 1; -} - -static void OpD4Slow (void) -{ - uint16 val = (uint16) DirectIndirectSlow(NONE); - PushW(val); - OpenBus = val & 0xff; - if (CheckEmulation()) - Registers.SH = 1; -} - -// PER -static void Op62E0 (void) -{ - uint16 val = (uint16) RelativeLong(NONE); - PushW(val); - OpenBus = val & 0xff; -} - -static void Op62E1 (void) -{ - // Note: PER is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 val = (uint16) RelativeLong(NONE); - PushW(val); - OpenBus = val & 0xff; - Registers.SH = 1; -} - -static void Op62Slow (void) -{ - uint16 val = (uint16) RelativeLongSlow(NONE); - PushW(val); - OpenBus = val & 0xff; - if (CheckEmulation()) - Registers.SH = 1; -} - -// PHA -static void Op48E1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.AL); - OpenBus = Registers.AL; -} - -static void Op48E0M1 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.AL); - OpenBus = Registers.AL; -} - -static void Op48E0M0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.A.W); - OpenBus = Registers.AL; -} - -static void Op48Slow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.AL); - } - else - if (CheckMemory()) - { - PushB(Registers.AL); - } - else - { - PushW(Registers.A.W); - } - - OpenBus = Registers.AL; -} - -// PHB -static void Op8BE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.DB); - OpenBus = Registers.DB; -} - -static void Op8BE0 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.DB); - OpenBus = Registers.DB; -} - -static void Op8BSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.DB); - } - else - { - PushB(Registers.DB); - } - - OpenBus = Registers.DB; -} - -// PHD -static void Op0BE0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.D.W); - OpenBus = Registers.DL; -} - -static void Op0BE1 (void) -{ - // Note: PHD is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - AddCycles(ONE_CYCLE); - PushW(Registers.D.W); - OpenBus = Registers.DL; - Registers.SH = 1; -} - -static void Op0BSlow (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.D.W); - OpenBus = Registers.DL; - if (CheckEmulation()) - Registers.SH = 1; -} - -// PHK -static void Op4BE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.PB); - OpenBus = Registers.PB; -} - -static void Op4BE0 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.PB); - OpenBus = Registers.PB; -} - -static void Op4BSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.PB); - } - else - { - PushB(Registers.PB); - } - - OpenBus = Registers.PB; -} - -// PHP -static void Op08E0 (void) -{ - S9xPackStatus(); - AddCycles(ONE_CYCLE); - PushB(Registers.PL); - OpenBus = Registers.PL; -} - -static void Op08E1 (void) -{ - S9xPackStatus(); - AddCycles(ONE_CYCLE); - PushBE(Registers.PL); - OpenBus = Registers.PL; -} - -static void Op08Slow (void) -{ - S9xPackStatus(); - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.PL); - } - else - { - PushB(Registers.PL); - } - - OpenBus = Registers.PL; -} - -// PHX -static void OpDAE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.XL); - OpenBus = Registers.XL; -} - -static void OpDAE0X1 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.XL); - OpenBus = Registers.XL; -} - -static void OpDAE0X0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.X.W); - OpenBus = Registers.XL; -} - -static void OpDASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.XL); - } - else - if (CheckIndex()) - { - PushB(Registers.XL); - } - else - { - PushW(Registers.X.W); - } - - OpenBus = Registers.XL; -} - -// PHY -static void Op5AE1 (void) -{ - AddCycles(ONE_CYCLE); - PushBE(Registers.YL); - OpenBus = Registers.YL; -} - -static void Op5AE0X1 (void) -{ - AddCycles(ONE_CYCLE); - PushB(Registers.YL); - OpenBus = Registers.YL; -} - -static void Op5AE0X0 (void) -{ - AddCycles(ONE_CYCLE); - PushW(Registers.Y.W); - OpenBus = Registers.YL; -} - -static void Op5ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushBE(Registers.YL); - } - else - if (CheckIndex()) - { - PushB(Registers.YL); - } - else - { - PushW(Registers.Y.W); - } - - OpenBus = Registers.YL; -} - -/* PULL Instructions ******************************************************* */ - -#define PullW(w) \ - w = S9xGetWord(Registers.S.W + 1, WRAP_BANK); \ - Registers.S.W += 2; - -#define PullWE(w) \ - Registers.SL++; \ - w = S9xGetWord(Registers.S.W, WRAP_PAGE); \ - Registers.SL++; - -#define PullB(b) \ - b = S9xGetByte(++Registers.S.W); - -#define PullBE(b) \ - Registers.SL++; \ - b = S9xGetByte(Registers.S.W); - -// PLA -static void Op68E1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; -} - -static void Op68E0M1 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; -} - -static void Op68E0M0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.A.W); - SetZN(Registers.A.W); - OpenBus = Registers.AH; -} - -static void Op68Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; - } - else - if (CheckMemory()) - { - PullB(Registers.AL); - SetZN(Registers.AL); - OpenBus = Registers.AL; - } - else - { - PullW(Registers.A.W); - SetZN(Registers.A.W); - OpenBus = Registers.AH; - } -} - -// PLB -static void OpABE1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.DB); - SetZN(Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = Registers.DB; -} - -static void OpABE0 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.DB); - SetZN(Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = Registers.DB; -} - -static void OpABSlow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.DB); - } - else - { - PullB(Registers.DB); - } - - SetZN(Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = Registers.DB; -} - -// PLD -static void Op2BE0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.D.W); - SetZN(Registers.D.W); - OpenBus = Registers.DH; -} - -static void Op2BE1 (void) -{ - // Note: PLD is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - AddCycles(TWO_CYCLES); - PullW(Registers.D.W); - SetZN(Registers.D.W); - OpenBus = Registers.DH; - Registers.SH = 1; -} - -static void Op2BSlow (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.D.W); - SetZN(Registers.D.W); - OpenBus = Registers.DH; - if (CheckEmulation()) - Registers.SH = 1; -} - -// PLP -static void Op28E1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.PL); - OpenBus = Registers.PL; - SetFlags(MemoryFlag | IndexFlag); - S9xUnpackStatus(); - S9xFixCycles(); - //CHECK_FOR_IRQ(); -} - -static void Op28E0 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.PL); - OpenBus = Registers.PL; - S9xUnpackStatus(); - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); -} - -static void Op28Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.PL); - OpenBus = Registers.PL; - SetFlags(MemoryFlag | IndexFlag); - } - else - { - PullB(Registers.PL); - OpenBus = Registers.PL; - } - - S9xUnpackStatus(); - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); -} - -// PLX -static void OpFAE1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; -} - -static void OpFAE0X1 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; -} - -static void OpFAE0X0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.X.W); - SetZN(Registers.X.W); - OpenBus = Registers.XH; -} - -static void OpFASlow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; - } - else - if (CheckIndex()) - { - PullB(Registers.XL); - SetZN(Registers.XL); - OpenBus = Registers.XL; - } - else - { - PullW(Registers.X.W); - SetZN(Registers.X.W); - OpenBus = Registers.XH; - } -} - -// PLY -static void Op7AE1 (void) -{ - AddCycles(TWO_CYCLES); - PullBE(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; -} - -static void Op7AE0X1 (void) -{ - AddCycles(TWO_CYCLES); - PullB(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; -} - -static void Op7AE0X0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.Y.W); - SetZN(Registers.Y.W); - OpenBus = Registers.YH; -} - -static void Op7ASlow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullBE(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; - } - else - if (CheckIndex()) - { - PullB(Registers.YL); - SetZN(Registers.YL); - OpenBus = Registers.YL; - } - else - { - PullW(Registers.Y.W); - SetZN(Registers.Y.W); - OpenBus = Registers.YH; - } -} - -/* Transfer Instructions *************************************************** */ - -// TAX -static void OpAAX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.XL = Registers.AL; - SetZN(Registers.XL); -} - -static void OpAAX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.X.W = Registers.A.W; - SetZN(Registers.X.W); -} - -static void OpAASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.XL = Registers.AL; - SetZN(Registers.XL); - } - else - { - Registers.X.W = Registers.A.W; - SetZN(Registers.X.W); - } -} - -// TAY -static void OpA8X1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.YL = Registers.AL; - SetZN(Registers.YL); -} - -static void OpA8X0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.Y.W = Registers.A.W; - SetZN(Registers.Y.W); -} - -static void OpA8Slow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.YL = Registers.AL; - SetZN(Registers.YL); - } - else - { - Registers.Y.W = Registers.A.W; - SetZN(Registers.Y.W); - } -} - -// TCD -static void Op5B (void) -{ - AddCycles(ONE_CYCLE); - Registers.D.W = Registers.A.W; - SetZN(Registers.D.W); -} - -// TCS -static void Op1B (void) -{ - AddCycles(ONE_CYCLE); - Registers.S.W = Registers.A.W; - if (CheckEmulation()) - Registers.SH = 1; -} - -// TDC -static void Op7B (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.D.W; - SetZN(Registers.A.W); -} - -// TSC -static void Op3B (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.S.W; - SetZN(Registers.A.W); -} - -// TSX -static void OpBAX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.XL = Registers.SL; - SetZN(Registers.XL); -} - -static void OpBAX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.X.W = Registers.S.W; - SetZN(Registers.X.W); -} - -static void OpBASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.XL = Registers.SL; - SetZN(Registers.XL); - } - else - { - Registers.X.W = Registers.S.W; - SetZN(Registers.X.W); - } -} - -// TXA -static void Op8AM1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.AL = Registers.XL; - SetZN(Registers.AL); -} - -static void Op8AM0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.X.W; - SetZN(Registers.A.W); -} - -static void Op8ASlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - Registers.AL = Registers.XL; - SetZN(Registers.AL); - } - else - { - Registers.A.W = Registers.X.W; - SetZN(Registers.A.W); - } -} - -// TXS -static void Op9A (void) -{ - AddCycles(ONE_CYCLE); - Registers.S.W = Registers.X.W; - if (CheckEmulation()) - Registers.SH = 1; -} - -// TXY -static void Op9BX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.YL = Registers.XL; - SetZN(Registers.YL); -} - -static void Op9BX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.Y.W = Registers.X.W; - SetZN(Registers.Y.W); -} - -static void Op9BSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.YL = Registers.XL; - SetZN(Registers.YL); - } - else - { - Registers.Y.W = Registers.X.W; - SetZN(Registers.Y.W); - } -} - -// TYA -static void Op98M1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.AL = Registers.YL; - SetZN(Registers.AL); -} - -static void Op98M0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.A.W = Registers.Y.W; - SetZN(Registers.A.W); -} - -static void Op98Slow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckMemory()) - { - Registers.AL = Registers.YL; - SetZN(Registers.AL); - } - else - { - Registers.A.W = Registers.Y.W; - SetZN(Registers.A.W); - } -} - -// TYX -static void OpBBX1 (void) -{ - AddCycles(ONE_CYCLE); - Registers.XL = Registers.YL; - SetZN(Registers.XL); -} - -static void OpBBX0 (void) -{ - AddCycles(ONE_CYCLE); - Registers.X.W = Registers.Y.W; - SetZN(Registers.X.W); -} - -static void OpBBSlow (void) -{ - AddCycles(ONE_CYCLE); - - if (CheckIndex()) - { - Registers.XL = Registers.YL; - SetZN(Registers.XL); - } - else - { - Registers.X.W = Registers.Y.W; - SetZN(Registers.X.W); - } -} - -/* XCE ********************************************************************* */ - -static void OpFB (void) -{ - AddCycles(ONE_CYCLE); - - uint8 A1 = ICPU._Carry; - uint8 A2 = Registers.PH; - - ICPU._Carry = A2 & 1; - Registers.PH = A1; - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - Registers.SH = 1; - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); -} - -/* BRK ********************************************************************* */ - -static void Op00 (void) -{ -#ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - S9xTraceMessage("*** BRK"); -#endif - - AddCycles(CPU.MemSpeed); - - uint16 addr; - - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw + 1); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - addr = S9xGetWord(0xFFE6); - } - else - { - PushWE(Registers.PCw + 1); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - addr = S9xGetWord(0xFFFE); - } - - S9xSetPCBase(addr); - OpenBus = addr >> 8; -} - -/* IRQ ********************************************************************* */ - -void S9xOpcode_IRQ (void) -{ -#ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - #ifdef SA1_OPCODES - S9xTraceMessage("*** SA1 IRQ"); - #else - S9xTraceMessage("*** IRQ"); - #endif -#endif - - // IRQ and NMI do an opcode fetch as their first "IO" cycle. - AddCycles(CPU.MemSpeed + ONE_CYCLE); - - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2208]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) - { - OpenBus = Memory.FillRAM[0x220f]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFEE); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } - else - { - PushWE(Registers.PCw); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2208]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) - { - OpenBus = Memory.FillRAM[0x220f]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFFE); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } -} - -/* NMI ********************************************************************* */ - -void S9xOpcode_NMI (void) -{ -#ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - #ifdef SA1_OPCODES - S9xTraceMessage("*** SA1 NMI"); - #else - S9xTraceMessage("*** NMI"); - #endif -#endif - - // IRQ and NMI do an opcode fetch as their first "IO" cycle. - AddCycles(CPU.MemSpeed + ONE_CYCLE); - - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2206]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10)) - { - OpenBus = Memory.FillRAM[0x220d]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFEA); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } - else - { - PushWE(Registers.PCw); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2206]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) - { - OpenBus = Memory.FillRAM[0x220d]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFFA); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } -} - -/* COP ********************************************************************* */ - -static void Op02 (void) -{ -#ifdef DEBUGGER - if (CPU.Flags & TRACE_FLAG) - S9xTraceMessage("*** COP"); -#endif - - AddCycles(CPU.MemSpeed); - - uint16 addr; - - if (!CheckEmulation()) - { - PushB(Registers.PB); - PushW(Registers.PCw + 1); - S9xPackStatus(); - PushB(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - addr = S9xGetWord(0xFFE4); - } - else - { - PushWE(Registers.PCw + 1); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - addr = S9xGetWord(0xFFF4); - } - - S9xSetPCBase(addr); - OpenBus = addr >> 8; -} - -/* JML ********************************************************************* */ - -static void OpDC (void) -{ - S9xSetPCBase(AbsoluteIndirectLong(JUMP)); -} - -static void OpDCSlow (void) -{ - S9xSetPCBase(AbsoluteIndirectLongSlow(JUMP)); -} - -static void Op5C (void) -{ - S9xSetPCBase(AbsoluteLong(JUMP)); -} - -static void Op5CSlow (void) -{ - S9xSetPCBase(AbsoluteLongSlow(JUMP)); -} - -/* JMP ********************************************************************* */ - -static void Op4C (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP))); -#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) - CPUShutdown(); -#endif -} - -static void Op4CSlow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP))); -#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) - CPUShutdown(); -#endif -} - -static void Op6C (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirect(JUMP))); -} - -static void Op6CSlow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirectSlow(JUMP))); -} - -static void Op7C (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirect(JUMP))); -} - -static void Op7CSlow (void) -{ - S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirectSlow(JUMP))); -} - -/* JSL/RTL ***************************************************************** */ - -static void Op22E1 (void) -{ - // Note: JSL is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint32 addr = AbsoluteLong(JSR); - PushB(Registers.PB); - PushW(Registers.PCw - 1); - Registers.SH = 1; - S9xSetPCBase(addr); -} - -static void Op22E0 (void) -{ - uint32 addr = AbsoluteLong(JSR); - PushB(Registers.PB); - PushW(Registers.PCw - 1); - S9xSetPCBase(addr); -} - -static void Op22Slow (void) -{ - uint32 addr = AbsoluteLongSlow(JSR); - PushB(Registers.PB); - PushW(Registers.PCw - 1); - if (CheckEmulation()) - Registers.SH = 1; - S9xSetPCBase(addr); -} - -static void Op6BE1 (void) -{ - // Note: RTL is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - PullB(Registers.PB); - Registers.SH = 1; - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); -} - -static void Op6BE0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - PullB(Registers.PB); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); -} - -static void Op6BSlow (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - PullB(Registers.PB); - if (CheckEmulation()) - Registers.SH = 1; - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); -} - -/* JSR/RTS ***************************************************************** */ - -static void Op20E1 (void) -{ - uint16 addr = Absolute(JSR); - AddCycles(ONE_CYCLE); - PushWE(Registers.PCw - 1); - S9xSetPCBase(ICPU.ShiftedPB + addr); -} - -static void Op20E0 (void) -{ - uint16 addr = Absolute(JSR); - AddCycles(ONE_CYCLE); - PushW(Registers.PCw - 1); - S9xSetPCBase(ICPU.ShiftedPB + addr); -} - -static void Op20Slow (void) -{ - uint16 addr = AbsoluteSlow(JSR); - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - PushWE(Registers.PCw - 1); - } - else - { - PushW(Registers.PCw - 1); - } - - S9xSetPCBase(ICPU.ShiftedPB + addr); -} - -static void OpFCE1 (void) -{ - // Note: JSR (a,X) is a new instruction, - // and so doesn't respect the emu-mode stack bounds. - uint16 addr = AbsoluteIndexedIndirect(JSR); - PushW(Registers.PCw - 1); - Registers.SH = 1; - S9xSetPCBase(ICPU.ShiftedPB + addr); -} - -static void OpFCE0 (void) -{ - uint16 addr = AbsoluteIndexedIndirect(JSR); - PushW(Registers.PCw - 1); - S9xSetPCBase(ICPU.ShiftedPB + addr); -} - -static void OpFCSlow (void) -{ - uint16 addr = AbsoluteIndexedIndirectSlow(JSR); - PushW(Registers.PCw - 1); - if (CheckEmulation()) - Registers.SH = 1; - S9xSetPCBase(ICPU.ShiftedPB + addr); -} - -static void Op60E1 (void) -{ - AddCycles(TWO_CYCLES); - PullWE(Registers.PCw); - AddCycles(ONE_CYCLE); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); -} - -static void Op60E0 (void) -{ - AddCycles(TWO_CYCLES); - PullW(Registers.PCw); - AddCycles(ONE_CYCLE); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); -} - -static void Op60Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (CheckEmulation()) - { - PullWE(Registers.PCw); - } - else - { - PullW(Registers.PCw); - } - - AddCycles(ONE_CYCLE); - Registers.PCw++; - S9xSetPCBase(Registers.PBPC); -} - -/* MVN/MVP ***************************************************************** */ - -static void Op54X1 (void) -{ - uint32 SrcBank; - - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); - - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - - Registers.XL++; - Registers.YL++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); -} - -static void Op54X0 (void) -{ - uint32 SrcBank; - - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); - - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - - Registers.X.W++; - Registers.Y.W++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); -} - -static void Op54Slow (void) -{ - uint32 SrcBank; - - OpenBus = Registers.DB = Immediate8Slow(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8Slow(NONE); - - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - - if (CheckIndex()) - { - Registers.XL++; - Registers.YL++; - } - else - { - Registers.X.W++; - Registers.Y.W++; - } - - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); -} - -static void Op44X1 (void) -{ - uint32 SrcBank; - - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); - - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - - Registers.XL--; - Registers.YL--; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); -} - -static void Op44X0 (void) -{ - uint32 SrcBank; - - Registers.DB = Immediate8(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); - - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - - Registers.X.W--; - Registers.Y.W--; - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); -} - -static void Op44Slow (void) -{ - uint32 SrcBank; - - OpenBus = Registers.DB = Immediate8Slow(NONE); - ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8Slow(NONE); - - S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); - - if (CheckIndex()) - { - Registers.XL--; - Registers.YL--; - } - else - { - Registers.X.W--; - Registers.Y.W--; - } - - Registers.A.W--; - if (Registers.A.W != 0xffff) - Registers.PCw -= 3; - - AddCycles(TWO_CYCLES); -} - -/* REP/SEP ***************************************************************** */ - -static void OpC2 (void) -{ - uint8 Work8 = ~Immediate8(READ); - Registers.PL &= Work8; - ICPU._Carry &= Work8; - ICPU._Overflow &= (Work8 >> 6); - ICPU._Negative &= Work8; - ICPU._Zero |= ~Work8 & Zero; - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); -} - -static void OpC2Slow (void) -{ - uint8 Work8 = ~Immediate8Slow(READ); - Registers.PL &= Work8; - ICPU._Carry &= Work8; - ICPU._Overflow &= (Work8 >> 6); - ICPU._Negative &= Work8; - ICPU._Zero |= ~Work8 & Zero; - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); -} - -static void OpE2 (void) -{ - uint8 Work8 = Immediate8(READ); - Registers.PL |= Work8; - ICPU._Carry |= Work8 & 1; - ICPU._Overflow |= (Work8 >> 6) & 1; - ICPU._Negative |= Work8; - if (Work8 & Zero) - ICPU._Zero = 0; - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); -} - -static void OpE2Slow (void) -{ - uint8 Work8 = Immediate8Slow(READ); - Registers.PL |= Work8; - ICPU._Carry |= Work8 & 1; - ICPU._Overflow |= (Work8 >> 6) & 1; - ICPU._Negative |= Work8; - if (Work8 & Zero) - ICPU._Zero = 0; - - AddCycles(ONE_CYCLE); - - if (CheckEmulation()) - { - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); -} - -/* XBA ********************************************************************* */ - -static void OpEB (void) -{ - uint8 Work8 = Registers.AL; - Registers.AL = Registers.AH; - Registers.AH = Work8; - SetZN(Registers.AL); - AddCycles(TWO_CYCLES); -} - -/* RTI ********************************************************************* */ - -static void Op40Slow (void) -{ - AddCycles(TWO_CYCLES); - - if (!CheckEmulation()) - { - PullB(Registers.PL); - S9xUnpackStatus(); - PullW(Registers.PCw); - PullB(Registers.PB); - OpenBus = Registers.PB; - ICPU.ShiftedPB = Registers.PB << 16; - } - else - { - PullBE(Registers.PL); - S9xUnpackStatus(); - PullWE(Registers.PCw); - OpenBus = Registers.PCh; - SetFlags(MemoryFlag | IndexFlag); - #ifdef DEBUGGER - missing.emulate6502 = 1; - #endif - } - - S9xSetPCBase(Registers.PBPC); - - if (CheckIndex()) - { - Registers.XH = 0; - Registers.YH = 0; - } - - S9xFixCycles(); - //CHECK_FOR_IRQ(); -} - -/* STP/WAI ***************************************************************** */ - -// WAI -static void OpCB (void) -{ - // Ok, let's just C-ify the ASM versions separately. -#ifdef SA1_OPCODES - SA1.WaitingForInterrupt = TRUE; - Registers.PCw--; -#if 0 - // XXX: FIXME - if (Settings.Shutdown) - { - SA1.Cycles = SA1.NextEvent; - SA1.Executing = FALSE; - //S9xAPUExecute(); // FIXME - SA1.Executing = TRUE; - } -#endif -#else // SA1_OPCODES -#if 0 - if (CPU.IRQActive) - AddCycles(TWO_CYCLES); - else -#endif - { - CPU.WaitingForInterrupt = TRUE; - Registers.PCw--; - #ifdef CPU_SHUTDOWN - if (Settings.Shutdown) - { - CPU.Cycles = CPU.NextEvent; - ICPU.CPUExecuting = FALSE; - S9xAPUExecute(); - ICPU.CPUExecuting = TRUE; - } - else - AddCycles(TWO_CYCLES); - #else - AddCycles(TWO_CYCLES); -#endif - } -#endif // SA1_OPCODES -} - -// STP -static void OpDB (void) -{ - Registers.PCw--; - CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG; -} - -/* WDM (Reserved S9xOpcode) ************************************************ */ - -#ifdef DEBUGGER -extern FILE *trace, *trace2; -#endif - -static void Op42 (void) -{ -#ifdef DEBUGGER - uint8 byte = (uint8) S9xGetWord(Registers.PBPC); -#else - S9xGetWord(Registers.PBPC); -#endif - Registers.PCw++; - -#ifdef DEBUGGER - // Hey, let's use this to trigger debug modes. - switch (byte) - { - case 0xdb: // "STP" = Enter debug mode - CPU.Flags |= DEBUG_MODE_FLAG; - break; - - #ifndef SA1_OPCODES - case 0xe2: // "SEP" = Trace on - if (!(CPU.Flags & TRACE_FLAG)) - { - char buf[25]; - CPU.Flags |= TRACE_FLAG; - snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw); - S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); - if (trace != NULL) - fclose(trace); - trace = fopen("WDMtrace.log", "ab"); - } - - break; - - case 0xc2: // "REP" = Trace off - if (CPU.Flags & TRACE_FLAG) - { - char buf[26]; - CPU.Flags &= ~TRACE_FLAG; - snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw); - S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); - if (trace != NULL) - fclose(trace); - trace = NULL; - } - - break; - #endif - - case 0x42: // "WDM" = Snapshot - char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1]; - - _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff); - sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename); - S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def); - S9xFreezeGame(filename); - - break; - - default: - break; - } -#endif -} - -/* CPU-S9xOpcodes Definitions ************************************************/ - -struct SOpcodes S9xOpcodesM1X1[256] = -{ - { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, - { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, - { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, - { Op0FM1 }, { Op10E0 }, { Op11E0M1X1 }, { Op12E0M1 }, { Op13M1 }, - { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, - { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, - { Op1EM1X1 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, - { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, - { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, - { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X1 }, - { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, - { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, - { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, - { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, - { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, - { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, - { Op50E0 }, { Op51E0M1X1 }, { Op52E0M1 }, { Op53M1 }, { Op54X1 }, - { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, - { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, - { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, - { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, - { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, - { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X1 }, { Op72E0M1 }, - { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, - { Op78 }, { Op79M1X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, - { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, - { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, - { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, - { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E0 }, - { Op91E0M1X1 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X1 }, { Op95E0M1 }, - { Op96E0X1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, - { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, - { OpA0X1 }, { OpA1E0M1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, - { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, - { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, - { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X1 }, { OpB2E0M1 }, { OpB3M1 }, - { OpB4E0X1 }, { OpB5E0M1 }, { OpB6E0X1 }, { OpB7M1 }, { OpB8 }, - { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, - { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E0M1 }, { OpC2 }, - { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, - { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, - { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X1 }, - { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, - { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE0X1 }, { OpDB }, - { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, - { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, - { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, - { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, - { OpF0E0 }, { OpF1E0M1X1 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, - { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, - { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM1X1 }, { OpFEM1X1 }, - { OpFFM1 } -}; - -struct SOpcodes S9xOpcodesE1[256] = -{ - { Op00 }, { Op01E1 }, { Op02 }, { Op03M1 }, { Op04M1 }, - { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E1 }, { Op09M1 }, - { Op0AM1 }, { Op0BE1 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, - { Op0FM1 }, { Op10E1 }, { Op11E1 }, { Op12E1 }, { Op13M1 }, - { Op14M1 }, { Op15E1 }, { Op16E1 }, { Op17M1 }, { Op18 }, - { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, - { Op1EM1X1 }, { Op1FM1 }, { Op20E1 }, { Op21E1 }, { Op22E1 }, - { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, - { Op28E1 }, { Op29M1 }, { Op2AM1 }, { Op2BE1 }, { Op2CM1 }, - { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E1 }, { Op31E1 }, - { Op32E1 }, { Op33M1 }, { Op34E1 }, { Op35E1 }, { Op36E1 }, - { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, - { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, - { Op41E1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, - { Op46M1 }, { Op47M1 }, { Op48E1 }, { Op49M1 }, { Op4AM1 }, - { Op4BE1 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, - { Op50E1 }, { Op51E1 }, { Op52E1 }, { Op53M1 }, { Op54X1 }, - { Op55E1 }, { Op56E1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, - { Op5AE1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, - { Op5FM1 }, { Op60E1 }, { Op61E1 }, { Op62E1 }, { Op63M1 }, - { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E1 }, - { Op69M1 }, { Op6AM1 }, { Op6BE1 }, { Op6C }, { Op6DM1 }, - { Op6EM1 }, { Op6FM1 }, { Op70E1 }, { Op71E1 }, { Op72E1 }, - { Op73M1 }, { Op74E1 }, { Op75E1 }, { Op76E1 }, { Op77M1 }, - { Op78 }, { Op79M1X1 }, { Op7AE1 }, { Op7B }, { Op7C }, - { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E1 }, { Op81E1 }, - { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, - { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE1 }, - { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E1 }, - { Op91E1 }, { Op92E1 }, { Op93M1 }, { Op94E1 }, { Op95E1 }, - { Op96E1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, - { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, - { OpA0X1 }, { OpA1E1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, - { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, - { OpAAX1 }, { OpABE1 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, - { OpAFM1 }, { OpB0E1 }, { OpB1E1 }, { OpB2E1 }, { OpB3M1 }, - { OpB4E1 }, { OpB5E1 }, { OpB6E1 }, { OpB7M1 }, { OpB8 }, - { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, - { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E1 }, { OpC2 }, - { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, - { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, - { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E1 }, { OpD1E1 }, - { OpD2E1 }, { OpD3M1 }, { OpD4E1 }, { OpD5E1 }, { OpD6E1 }, - { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE1 }, { OpDB }, - { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, - { OpE1E1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, - { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, - { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, - { OpF0E1 }, { OpF1E1 }, { OpF2E1 }, { OpF3M1 }, { OpF4E1 }, - { OpF5E1 }, { OpF6E1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, - { OpFAE1 }, { OpFB }, { OpFCE1 }, { OpFDM1X1 }, { OpFEM1X1 }, - { OpFFM1 } -}; - -struct SOpcodes S9xOpcodesM1X0[256] = -{ - { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, - { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, - { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, - { Op0FM1 }, { Op10E0 }, { Op11E0M1X0 }, { Op12E0M1 }, { Op13M1 }, - { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, - { Op19M1X0 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X0 }, - { Op1EM1X0 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, - { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, - { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, - { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X0 }, - { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, - { Op37M1 }, { Op38 }, { Op39M1X0 }, { Op3AM1 }, { Op3B }, - { Op3CM1X0 }, { Op3DM1X0 }, { Op3EM1X0 }, { Op3FM1 }, { Op40Slow }, - { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X0 }, { Op45M1 }, - { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, - { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, - { Op50E0 }, { Op51E0M1X0 }, { Op52E0M1 }, { Op53M1 }, { Op54X0 }, - { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X0 }, - { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM1X0 }, { Op5EM1X0 }, - { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, - { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, - { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, - { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X0 }, { Op72E0M1 }, - { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, - { Op78 }, { Op79M1X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, - { Op7DM1X0 }, { Op7EM1X0 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, - { Op82 }, { Op83M1 }, { Op84X0 }, { Op85M1 }, { Op86X0 }, - { Op87M1 }, { Op88X0 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, - { Op8CX0 }, { Op8DM1 }, { Op8EX0 }, { Op8FM1 }, { Op90E0 }, - { Op91E0M1X0 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X0 }, { Op95E0M1 }, - { Op96E0X0 }, { Op97M1 }, { Op98M1 }, { Op99M1X0 }, { Op9A }, - { Op9BX0 }, { Op9CM1 }, { Op9DM1X0 }, { Op9EM1X0 }, { Op9FM1 }, - { OpA0X0 }, { OpA1E0M1 }, { OpA2X0 }, { OpA3M1 }, { OpA4X0 }, - { OpA5M1 }, { OpA6X0 }, { OpA7M1 }, { OpA8X0 }, { OpA9M1 }, - { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM1 }, { OpAEX0 }, - { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X0 }, { OpB2E0M1 }, { OpB3M1 }, - { OpB4E0X0 }, { OpB5E0M1 }, { OpB6E0X0 }, { OpB7M1 }, { OpB8 }, - { OpB9M1X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM1X0 }, - { OpBEX0 }, { OpBFM1 }, { OpC0X0 }, { OpC1E0M1 }, { OpC2 }, - { OpC3M1 }, { OpC4X0 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, - { OpC8X0 }, { OpC9M1 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, - { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X0 }, - { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, - { OpD7M1 }, { OpD8 }, { OpD9M1X0 }, { OpDAE0X0 }, { OpDB }, - { OpDC }, { OpDDM1X0 }, { OpDEM1X0 }, { OpDFM1 }, { OpE0X0 }, - { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X0 }, { OpE5M1 }, - { OpE6M1 }, { OpE7M1 }, { OpE8X0 }, { OpE9M1 }, { OpEA }, - { OpEB }, { OpECX0 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, - { OpF0E0 }, { OpF1E0M1X0 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, - { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X0 }, - { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM1X0 }, { OpFEM1X0 }, - { OpFFM1 } -}; - -struct SOpcodes S9xOpcodesM0X0[256] = -{ - { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, - { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, - { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, - { Op0FM0 }, { Op10E0 }, { Op11E0M0X0 }, { Op12E0M0 }, { Op13M0 }, - { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, - { Op19M0X0 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X0 }, - { Op1EM0X0 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, - { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, - { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, - { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X0 }, - { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, - { Op37M0 }, { Op38 }, { Op39M0X0 }, { Op3AM0 }, { Op3B }, - { Op3CM0X0 }, { Op3DM0X0 }, { Op3EM0X0 }, { Op3FM0 }, { Op40Slow }, - { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X0 }, { Op45M0 }, - { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, - { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, - { Op50E0 }, { Op51E0M0X0 }, { Op52E0M0 }, { Op53M0 }, { Op54X0 }, - { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X0 }, - { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM0X0 }, { Op5EM0X0 }, - { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, - { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, - { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, - { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X0 }, { Op72E0M0 }, - { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, - { Op78 }, { Op79M0X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, - { Op7DM0X0 }, { Op7EM0X0 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, - { Op82 }, { Op83M0 }, { Op84X0 }, { Op85M0 }, { Op86X0 }, - { Op87M0 }, { Op88X0 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, - { Op8CX0 }, { Op8DM0 }, { Op8EX0 }, { Op8FM0 }, { Op90E0 }, - { Op91E0M0X0 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X0 }, { Op95E0M0 }, - { Op96E0X0 }, { Op97M0 }, { Op98M0 }, { Op99M0X0 }, { Op9A }, - { Op9BX0 }, { Op9CM0 }, { Op9DM0X0 }, { Op9EM0X0 }, { Op9FM0 }, - { OpA0X0 }, { OpA1E0M0 }, { OpA2X0 }, { OpA3M0 }, { OpA4X0 }, - { OpA5M0 }, { OpA6X0 }, { OpA7M0 }, { OpA8X0 }, { OpA9M0 }, - { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM0 }, { OpAEX0 }, - { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X0 }, { OpB2E0M0 }, { OpB3M0 }, - { OpB4E0X0 }, { OpB5E0M0 }, { OpB6E0X0 }, { OpB7M0 }, { OpB8 }, - { OpB9M0X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM0X0 }, - { OpBEX0 }, { OpBFM0 }, { OpC0X0 }, { OpC1E0M0 }, { OpC2 }, - { OpC3M0 }, { OpC4X0 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, - { OpC8X0 }, { OpC9M0 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, - { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X0 }, - { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, - { OpD7M0 }, { OpD8 }, { OpD9M0X0 }, { OpDAE0X0 }, { OpDB }, - { OpDC }, { OpDDM0X0 }, { OpDEM0X0 }, { OpDFM0 }, { OpE0X0 }, - { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X0 }, { OpE5M0 }, - { OpE6M0 }, { OpE7M0 }, { OpE8X0 }, { OpE9M0 }, { OpEA }, - { OpEB }, { OpECX0 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, - { OpF0E0 }, { OpF1E0M0X0 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, - { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X0 }, - { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM0X0 }, { OpFEM0X0 }, - { OpFFM0 } -}; - -struct SOpcodes S9xOpcodesM0X1[256] = -{ - { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, - { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, - { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, - { Op0FM0 }, { Op10E0 }, { Op11E0M0X1 }, { Op12E0M0 }, { Op13M0 }, - { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, - { Op19M0X1 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X1 }, - { Op1EM0X1 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, - { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, - { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, - { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X1 }, - { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, - { Op37M0 }, { Op38 }, { Op39M0X1 }, { Op3AM0 }, { Op3B }, - { Op3CM0X1 }, { Op3DM0X1 }, { Op3EM0X1 }, { Op3FM0 }, { Op40Slow }, - { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X1 }, { Op45M0 }, - { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, - { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, - { Op50E0 }, { Op51E0M0X1 }, { Op52E0M0 }, { Op53M0 }, { Op54X1 }, - { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X1 }, - { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM0X1 }, { Op5EM0X1 }, - { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, - { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, - { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, - { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X1 }, { Op72E0M0 }, - { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, - { Op78 }, { Op79M0X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, - { Op7DM0X1 }, { Op7EM0X1 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, - { Op82 }, { Op83M0 }, { Op84X1 }, { Op85M0 }, { Op86X1 }, - { Op87M0 }, { Op88X1 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, - { Op8CX1 }, { Op8DM0 }, { Op8EX1 }, { Op8FM0 }, { Op90E0 }, - { Op91E0M0X1 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X1 }, { Op95E0M0 }, - { Op96E0X1 }, { Op97M0 }, { Op98M0 }, { Op99M0X1 }, { Op9A }, - { Op9BX1 }, { Op9CM0 }, { Op9DM0X1 }, { Op9EM0X1 }, { Op9FM0 }, - { OpA0X1 }, { OpA1E0M0 }, { OpA2X1 }, { OpA3M0 }, { OpA4X1 }, - { OpA5M0 }, { OpA6X1 }, { OpA7M0 }, { OpA8X1 }, { OpA9M0 }, - { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM0 }, { OpAEX1 }, - { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X1 }, { OpB2E0M0 }, { OpB3M0 }, - { OpB4E0X1 }, { OpB5E0M0 }, { OpB6E0X1 }, { OpB7M0 }, { OpB8 }, - { OpB9M0X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM0X1 }, - { OpBEX1 }, { OpBFM0 }, { OpC0X1 }, { OpC1E0M0 }, { OpC2 }, - { OpC3M0 }, { OpC4X1 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, - { OpC8X1 }, { OpC9M0 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, - { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X1 }, - { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, - { OpD7M0 }, { OpD8 }, { OpD9M0X1 }, { OpDAE0X1 }, { OpDB }, - { OpDC }, { OpDDM0X1 }, { OpDEM0X1 }, { OpDFM0 }, { OpE0X1 }, - { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X1 }, { OpE5M0 }, - { OpE6M0 }, { OpE7M0 }, { OpE8X1 }, { OpE9M0 }, { OpEA }, - { OpEB }, { OpECX1 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, - { OpF0E0 }, { OpF1E0M0X1 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, - { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X1 }, - { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM0X1 }, { OpFEM0X1 }, - { OpFFM0 } -}; - -struct SOpcodes S9xOpcodesSlow[256] = -{ - { Op00 }, { Op01Slow }, { Op02 }, { Op03Slow }, { Op04Slow }, - { Op05Slow }, { Op06Slow }, { Op07Slow }, { Op08Slow }, { Op09Slow }, - { Op0ASlow }, { Op0BSlow }, { Op0CSlow }, { Op0DSlow }, { Op0ESlow }, - { Op0FSlow }, { Op10Slow }, { Op11Slow }, { Op12Slow }, { Op13Slow }, - { Op14Slow }, { Op15Slow }, { Op16Slow }, { Op17Slow }, { Op18 }, - { Op19Slow }, { Op1ASlow }, { Op1B }, { Op1CSlow }, { Op1DSlow }, - { Op1ESlow }, { Op1FSlow }, { Op20Slow }, { Op21Slow }, { Op22Slow }, - { Op23Slow }, { Op24Slow }, { Op25Slow }, { Op26Slow }, { Op27Slow }, - { Op28Slow }, { Op29Slow }, { Op2ASlow }, { Op2BSlow }, { Op2CSlow }, - { Op2DSlow }, { Op2ESlow }, { Op2FSlow }, { Op30Slow }, { Op31Slow }, - { Op32Slow }, { Op33Slow }, { Op34Slow }, { Op35Slow }, { Op36Slow }, - { Op37Slow }, { Op38 }, { Op39Slow }, { Op3ASlow }, { Op3B }, - { Op3CSlow }, { Op3DSlow }, { Op3ESlow }, { Op3FSlow }, { Op40Slow }, - { Op41Slow }, { Op42 }, { Op43Slow }, { Op44Slow }, { Op45Slow }, - { Op46Slow }, { Op47Slow }, { Op48Slow }, { Op49Slow }, { Op4ASlow }, - { Op4BSlow }, { Op4CSlow }, { Op4DSlow }, { Op4ESlow }, { Op4FSlow }, - { Op50Slow }, { Op51Slow }, { Op52Slow }, { Op53Slow }, { Op54Slow }, - { Op55Slow }, { Op56Slow }, { Op57Slow }, { Op58 }, { Op59Slow }, - { Op5ASlow }, { Op5B }, { Op5CSlow }, { Op5DSlow }, { Op5ESlow }, - { Op5FSlow }, { Op60Slow }, { Op61Slow }, { Op62Slow }, { Op63Slow }, - { Op64Slow }, { Op65Slow }, { Op66Slow }, { Op67Slow }, { Op68Slow }, - { Op69Slow }, { Op6ASlow }, { Op6BSlow }, { Op6CSlow }, { Op6DSlow }, - { Op6ESlow }, { Op6FSlow }, { Op70Slow }, { Op71Slow }, { Op72Slow }, - { Op73Slow }, { Op74Slow }, { Op75Slow }, { Op76Slow }, { Op77Slow }, - { Op78 }, { Op79Slow }, { Op7ASlow }, { Op7B }, { Op7CSlow }, - { Op7DSlow }, { Op7ESlow }, { Op7FSlow }, { Op80Slow }, { Op81Slow }, - { Op82Slow }, { Op83Slow }, { Op84Slow }, { Op85Slow }, { Op86Slow }, - { Op87Slow }, { Op88Slow }, { Op89Slow }, { Op8ASlow }, { Op8BSlow }, - { Op8CSlow }, { Op8DSlow }, { Op8ESlow }, { Op8FSlow }, { Op90Slow }, - { Op91Slow }, { Op92Slow }, { Op93Slow }, { Op94Slow }, { Op95Slow }, - { Op96Slow }, { Op97Slow }, { Op98Slow }, { Op99Slow }, { Op9A }, - { Op9BSlow }, { Op9CSlow }, { Op9DSlow }, { Op9ESlow }, { Op9FSlow }, - { OpA0Slow }, { OpA1Slow }, { OpA2Slow }, { OpA3Slow }, { OpA4Slow }, - { OpA5Slow }, { OpA6Slow }, { OpA7Slow }, { OpA8Slow }, { OpA9Slow }, - { OpAASlow }, { OpABSlow }, { OpACSlow }, { OpADSlow }, { OpAESlow }, - { OpAFSlow }, { OpB0Slow }, { OpB1Slow }, { OpB2Slow }, { OpB3Slow }, - { OpB4Slow }, { OpB5Slow }, { OpB6Slow }, { OpB7Slow }, { OpB8 }, - { OpB9Slow }, { OpBASlow }, { OpBBSlow }, { OpBCSlow }, { OpBDSlow }, - { OpBESlow }, { OpBFSlow }, { OpC0Slow }, { OpC1Slow }, { OpC2Slow }, - { OpC3Slow }, { OpC4Slow }, { OpC5Slow }, { OpC6Slow }, { OpC7Slow }, - { OpC8Slow }, { OpC9Slow }, { OpCASlow }, { OpCB }, { OpCCSlow }, - { OpCDSlow }, { OpCESlow }, { OpCFSlow }, { OpD0Slow }, { OpD1Slow }, - { OpD2Slow }, { OpD3Slow }, { OpD4Slow }, { OpD5Slow }, { OpD6Slow }, - { OpD7Slow }, { OpD8 }, { OpD9Slow }, { OpDASlow }, { OpDB }, - { OpDCSlow }, { OpDDSlow }, { OpDESlow }, { OpDFSlow }, { OpE0Slow }, - { OpE1Slow }, { OpE2Slow }, { OpE3Slow }, { OpE4Slow }, { OpE5Slow }, - { OpE6Slow }, { OpE7Slow }, { OpE8Slow }, { OpE9Slow }, { OpEA }, - { OpEB }, { OpECSlow }, { OpEDSlow }, { OpEESlow }, { OpEFSlow }, - { OpF0Slow }, { OpF1Slow }, { OpF2Slow }, { OpF3Slow }, { OpF4Slow }, - { OpF5Slow }, { OpF6Slow }, { OpF7Slow }, { OpF8 }, { OpF9Slow }, - { OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow }, - { OpFFSlow } -}; - +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" + +// for "Magic WDM" features +#ifdef DEBUGGER +#include "snapshot.h" +#include "display.h" +#include "debug.h" +#include "missing.h" +#endif + +#ifdef SA1_OPCODES +#define AddCycles(n) { SA1.Cycles += (n); } +#else +#define AddCycles(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } +#endif + +#include "cpuaddr.h" +#include "cpuops.h" +#include "cpumacro.h" + + +/* ADC ********************************************************************* */ + +static void Op69M1 (void) +{ + ADC(Immediate8(READ)); +} + +static void Op69M0 (void) +{ + ADC(Immediate16(READ)); +} + +static void Op69Slow (void) +{ + if (CheckMemory()) + ADC(Immediate8Slow(READ)); + else + ADC(Immediate16Slow(READ)); +} + +rOP8 (65M1, Direct, WRAP_BANK, ADC) +rOP16(65M0, Direct, WRAP_BANK, ADC) +rOPM (65Slow, DirectSlow, WRAP_BANK, ADC) + +rOP8 (75E1, DirectIndexedXE1, WRAP_BANK, ADC) +rOP8 (75E0M1, DirectIndexedXE0, WRAP_BANK, ADC) +rOP16(75E0M0, DirectIndexedXE0, WRAP_BANK, ADC) +rOPM (75Slow, DirectIndexedXSlow, WRAP_BANK, ADC) + +rOP8 (72E1, DirectIndirectE1, WRAP_NONE, ADC) +rOP8 (72E0M1, DirectIndirectE0, WRAP_NONE, ADC) +rOP16(72E0M0, DirectIndirectE0, WRAP_NONE, ADC) +rOPM (72Slow, DirectIndirectSlow, WRAP_NONE, ADC) + +rOP8 (61E1, DirectIndexedIndirectE1, WRAP_NONE, ADC) +rOP8 (61E0M1, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOP16(61E0M0, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOPM (61Slow, DirectIndexedIndirectSlow, WRAP_NONE, ADC) + +rOP8 (71E1, DirectIndirectIndexedE1, WRAP_NONE, ADC) +rOP8 (71E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP16(71E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP8 (71E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOP16(71E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOPM (71Slow, DirectIndirectIndexedSlow, WRAP_NONE, ADC) + +rOP8 (67M1, DirectIndirectLong, WRAP_NONE, ADC) +rOP16(67M0, DirectIndirectLong, WRAP_NONE, ADC) +rOPM (67Slow, DirectIndirectLongSlow, WRAP_NONE, ADC) + +rOP8 (77M1, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOP16(77M0, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOPM (77Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ADC) + +rOP8 (6DM1, Absolute, WRAP_NONE, ADC) +rOP16(6DM0, Absolute, WRAP_NONE, ADC) +rOPM (6DSlow, AbsoluteSlow, WRAP_NONE, ADC) + +rOP8 (7DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP16(7DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP8 (7DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOP16(7DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOPM (7DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ADC) + +rOP8 (79M1X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP16(79M0X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP8 (79M1X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOP16(79M0X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOPM (79Slow, AbsoluteIndexedYSlow, WRAP_NONE, ADC) + +rOP8 (6FM1, AbsoluteLong, WRAP_NONE, ADC) +rOP16(6FM0, AbsoluteLong, WRAP_NONE, ADC) +rOPM (6FSlow, AbsoluteLongSlow, WRAP_NONE, ADC) + +rOP8 (7FM1, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOP16(7FM0, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOPM (7FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ADC) + +rOP8 (63M1, StackRelative, WRAP_NONE, ADC) +rOP16(63M0, StackRelative, WRAP_NONE, ADC) +rOPM (63Slow, StackRelativeSlow, WRAP_NONE, ADC) + +rOP8 (73M1, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOP16(73M0, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOPM (73Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC) + +/* AND ********************************************************************* */ + +static void Op29M1 (void) +{ + Registers.AL &= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op29M0 (void) +{ + Registers.A.W &= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op29Slow (void) +{ + if (CheckMemory()) + { + Registers.AL &= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W &= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (25M1, Direct, WRAP_BANK, AND) +rOP16(25M0, Direct, WRAP_BANK, AND) +rOPM (25Slow, DirectSlow, WRAP_BANK, AND) + +rOP8 (35E1, DirectIndexedXE1, WRAP_BANK, AND) +rOP8 (35E0M1, DirectIndexedXE0, WRAP_BANK, AND) +rOP16(35E0M0, DirectIndexedXE0, WRAP_BANK, AND) +rOPM (35Slow, DirectIndexedXSlow, WRAP_BANK, AND) + +rOP8 (32E1, DirectIndirectE1, WRAP_NONE, AND) +rOP8 (32E0M1, DirectIndirectE0, WRAP_NONE, AND) +rOP16(32E0M0, DirectIndirectE0, WRAP_NONE, AND) +rOPM (32Slow, DirectIndirectSlow, WRAP_NONE, AND) + +rOP8 (21E1, DirectIndexedIndirectE1, WRAP_NONE, AND) +rOP8 (21E0M1, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOP16(21E0M0, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOPM (21Slow, DirectIndexedIndirectSlow, WRAP_NONE, AND) + +rOP8 (31E1, DirectIndirectIndexedE1, WRAP_NONE, AND) +rOP8 (31E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP16(31E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP8 (31E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOP16(31E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOPM (31Slow, DirectIndirectIndexedSlow, WRAP_NONE, AND) + +rOP8 (27M1, DirectIndirectLong, WRAP_NONE, AND) +rOP16(27M0, DirectIndirectLong, WRAP_NONE, AND) +rOPM (27Slow, DirectIndirectLongSlow, WRAP_NONE, AND) + +rOP8 (37M1, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOP16(37M0, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOPM (37Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, AND) + +rOP8 (2DM1, Absolute, WRAP_NONE, AND) +rOP16(2DM0, Absolute, WRAP_NONE, AND) +rOPM (2DSlow, AbsoluteSlow, WRAP_NONE, AND) + +rOP8 (3DM1X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP16(3DM0X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP8 (3DM1X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOP16(3DM0X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOPM (3DSlow, AbsoluteIndexedXSlow, WRAP_NONE, AND) + +rOP8 (39M1X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP16(39M0X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP8 (39M1X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOP16(39M0X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOPM (39Slow, AbsoluteIndexedYSlow, WRAP_NONE, AND) + +rOP8 (2FM1, AbsoluteLong, WRAP_NONE, AND) +rOP16(2FM0, AbsoluteLong, WRAP_NONE, AND) +rOPM (2FSlow, AbsoluteLongSlow, WRAP_NONE, AND) + +rOP8 (3FM1, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOP16(3FM0, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOPM (3FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, AND) + +rOP8 (23M1, StackRelative, WRAP_NONE, AND) +rOP16(23M0, StackRelative, WRAP_NONE, AND) +rOPM (23Slow, StackRelativeSlow, WRAP_NONE, AND) + +rOP8 (33M1, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOP16(33M0, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOPM (33Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, AND) + +/* ASL ********************************************************************* */ + +static void Op0AM1 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN(Registers.AL); +} + +static void Op0AM0 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN(Registers.A.W); +} + +static void Op0ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN(Registers.AL); + } + else + { + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN(Registers.A.W); + } +} + +mOP8 (06M1, Direct, WRAP_BANK, ASL) +mOP16(06M0, Direct, WRAP_BANK, ASL) +mOPM (06Slow, DirectSlow, WRAP_BANK, ASL) + +mOP8 (16E1, DirectIndexedXE1, WRAP_BANK, ASL) +mOP8 (16E0M1, DirectIndexedXE0, WRAP_BANK, ASL) +mOP16(16E0M0, DirectIndexedXE0, WRAP_BANK, ASL) +mOPM (16Slow, DirectIndexedXSlow, WRAP_BANK, ASL) + +mOP8 (0EM1, Absolute, WRAP_NONE, ASL) +mOP16(0EM0, Absolute, WRAP_NONE, ASL) +mOPM (0ESlow, AbsoluteSlow, WRAP_NONE, ASL) + +mOP8 (1EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP16(1EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP8 (1EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOP16(1EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOPM (1ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ASL) + +/* BIT ********************************************************************* */ + +static void Op89M1 (void) +{ + ICPU._Zero = Registers.AL & Immediate8(READ); +} + +static void Op89M0 (void) +{ + ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0; +} + +static void Op89Slow (void) +{ + if (CheckMemory()) + ICPU._Zero = Registers.AL & Immediate8Slow(READ); + else + ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0; +} + +rOP8 (24M1, Direct, WRAP_BANK, BIT) +rOP16(24M0, Direct, WRAP_BANK, BIT) +rOPM (24Slow, DirectSlow, WRAP_BANK, BIT) + +rOP8 (34E1, DirectIndexedXE1, WRAP_BANK, BIT) +rOP8 (34E0M1, DirectIndexedXE0, WRAP_BANK, BIT) +rOP16(34E0M0, DirectIndexedXE0, WRAP_BANK, BIT) +rOPM (34Slow, DirectIndexedXSlow, WRAP_BANK, BIT) + +rOP8 (2CM1, Absolute, WRAP_NONE, BIT) +rOP16(2CM0, Absolute, WRAP_NONE, BIT) +rOPM (2CSlow, AbsoluteSlow, WRAP_NONE, BIT) + +rOP8 (3CM1X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP16(3CM0X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP8 (3CM1X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOP16(3CM0X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOPM (3CSlow, AbsoluteIndexedXSlow, WRAP_NONE, BIT) + +/* CMP ********************************************************************* */ + +static void OpC9M1 (void) +{ + int16 Int16 = (int16) Registers.AL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpC9M0 (void) +{ + int32 Int32 = (int32) Registers.A.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpC9Slow (void) +{ + if (CheckMemory()) + { + int16 Int16 = (int16) Registers.AL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.A.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (C5M1, Direct, WRAP_BANK, CMP) +rOP16(C5M0, Direct, WRAP_BANK, CMP) +rOPM (C5Slow, DirectSlow, WRAP_BANK, CMP) + +rOP8 (D5E1, DirectIndexedXE1, WRAP_BANK, CMP) +rOP8 (D5E0M1, DirectIndexedXE0, WRAP_BANK, CMP) +rOP16(D5E0M0, DirectIndexedXE0, WRAP_BANK, CMP) +rOPM (D5Slow, DirectIndexedXSlow, WRAP_BANK, CMP) + +rOP8 (D2E1, DirectIndirectE1, WRAP_NONE, CMP) +rOP8 (D2E0M1, DirectIndirectE0, WRAP_NONE, CMP) +rOP16(D2E0M0, DirectIndirectE0, WRAP_NONE, CMP) +rOPM (D2Slow, DirectIndirectSlow, WRAP_NONE, CMP) + +rOP8 (C1E1, DirectIndexedIndirectE1, WRAP_NONE, CMP) +rOP8 (C1E0M1, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOP16(C1E0M0, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOPM (C1Slow, DirectIndexedIndirectSlow, WRAP_NONE, CMP) + +rOP8 (D1E1, DirectIndirectIndexedE1, WRAP_NONE, CMP) +rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP16(D1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOP16(D1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOPM (D1Slow, DirectIndirectIndexedSlow, WRAP_NONE, CMP) + +rOP8 (C7M1, DirectIndirectLong, WRAP_NONE, CMP) +rOP16(C7M0, DirectIndirectLong, WRAP_NONE, CMP) +rOPM (C7Slow, DirectIndirectLongSlow, WRAP_NONE, CMP) + +rOP8 (D7M1, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOP16(D7M0, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOPM (D7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, CMP) + +rOP8 (CDM1, Absolute, WRAP_NONE, CMP) +rOP16(CDM0, Absolute, WRAP_NONE, CMP) +rOPM (CDSlow, AbsoluteSlow, WRAP_NONE, CMP) + +rOP8 (DDM1X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP16(DDM0X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP8 (DDM1X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOP16(DDM0X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOPM (DDSlow, AbsoluteIndexedXSlow, WRAP_NONE, CMP) + +rOP8 (D9M1X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP16(D9M0X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP8 (D9M1X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOP16(D9M0X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOPM (D9Slow, AbsoluteIndexedYSlow, WRAP_NONE, CMP) + +rOP8 (CFM1, AbsoluteLong, WRAP_NONE, CMP) +rOP16(CFM0, AbsoluteLong, WRAP_NONE, CMP) +rOPM (CFSlow, AbsoluteLongSlow, WRAP_NONE, CMP) + +rOP8 (DFM1, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOP16(DFM0, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOPM (DFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, CMP) + +rOP8 (C3M1, StackRelative, WRAP_NONE, CMP) +rOP16(C3M0, StackRelative, WRAP_NONE, CMP) +rOPM (C3Slow, StackRelativeSlow, WRAP_NONE, CMP) + +rOP8 (D3M1, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOP16(D3M0, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOPM (D3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP) + +/* CPX ********************************************************************* */ + +static void OpE0X1 (void) +{ + int16 Int16 = (int16) Registers.XL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpE0X0 (void) +{ + int32 Int32 = (int32) Registers.X.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpE0Slow (void) +{ + if (CheckIndex()) + { + int16 Int16 = (int16) Registers.XL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.X.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (E4X1, Direct, WRAP_BANK, CPX) +rOP16(E4X0, Direct, WRAP_BANK, CPX) +rOPX (E4Slow, DirectSlow, WRAP_BANK, CPX) + +rOP8 (ECX1, Absolute, WRAP_NONE, CPX) +rOP16(ECX0, Absolute, WRAP_NONE, CPX) +rOPX (ECSlow, AbsoluteSlow, WRAP_NONE, CPX) + +/* CPY ********************************************************************* */ + +static void OpC0X1 (void) +{ + int16 Int16 = (int16) Registers.YL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpC0X0 (void) +{ + int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpC0Slow (void) +{ + if (CheckIndex()) + { + int16 Int16 = (int16) Registers.YL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (C4X1, Direct, WRAP_BANK, CPY) +rOP16(C4X0, Direct, WRAP_BANK, CPY) +rOPX (C4Slow, DirectSlow, WRAP_BANK, CPY) + +rOP8 (CCX1, Absolute, WRAP_NONE, CPY) +rOP16(CCX0, Absolute, WRAP_NONE, CPY) +rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY) + +/* DEC ********************************************************************* */ + +static void Op3AM1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL--; + SetZN(Registers.AL); +} + +static void Op3AM0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W--; + SetZN(Registers.A.W); +} + +static void Op3ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL--; + SetZN(Registers.AL); + } + else + { + Registers.A.W--; + SetZN(Registers.A.W); + } +} + +mOP8 (C6M1, Direct, WRAP_BANK, DEC) +mOP16(C6M0, Direct, WRAP_BANK, DEC) +mOPM (C6Slow, DirectSlow, WRAP_BANK, DEC) + +mOP8 (D6E1, DirectIndexedXE1, WRAP_BANK, DEC) +mOP8 (D6E0M1, DirectIndexedXE0, WRAP_BANK, DEC) +mOP16(D6E0M0, DirectIndexedXE0, WRAP_BANK, DEC) +mOPM (D6Slow, DirectIndexedXSlow, WRAP_BANK, DEC) + +mOP8 (CEM1, Absolute, WRAP_NONE, DEC) +mOP16(CEM0, Absolute, WRAP_NONE, DEC) +mOPM (CESlow, AbsoluteSlow, WRAP_NONE, DEC) + +mOP8 (DEM1X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP16(DEM0X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP8 (DEM1X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOP16(DEM0X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOPM (DESlow, AbsoluteIndexedXSlow, WRAP_NONE, DEC) + +/* EOR ********************************************************************* */ + +static void Op49M1 (void) +{ + Registers.AL ^= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op49M0 (void) +{ + Registers.A.W ^= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op49Slow (void) +{ + if (CheckMemory()) + { + Registers.AL ^= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W ^= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (45M1, Direct, WRAP_BANK, EOR) +rOP16(45M0, Direct, WRAP_BANK, EOR) +rOPM (45Slow, DirectSlow, WRAP_BANK, EOR) + +rOP8 (55E1, DirectIndexedXE1, WRAP_BANK, EOR) +rOP8 (55E0M1, DirectIndexedXE0, WRAP_BANK, EOR) +rOP16(55E0M0, DirectIndexedXE0, WRAP_BANK, EOR) +rOPM (55Slow, DirectIndexedXSlow, WRAP_BANK, EOR) + +rOP8 (52E1, DirectIndirectE1, WRAP_NONE, EOR) +rOP8 (52E0M1, DirectIndirectE0, WRAP_NONE, EOR) +rOP16(52E0M0, DirectIndirectE0, WRAP_NONE, EOR) +rOPM (52Slow, DirectIndirectSlow, WRAP_NONE, EOR) + +rOP8 (41E1, DirectIndexedIndirectE1, WRAP_NONE, EOR) +rOP8 (41E0M1, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOP16(41E0M0, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOPM (41Slow, DirectIndexedIndirectSlow, WRAP_NONE, EOR) + +rOP8 (51E1, DirectIndirectIndexedE1, WRAP_NONE, EOR) +rOP8 (51E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP16(51E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP8 (51E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOP16(51E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOPM (51Slow, DirectIndirectIndexedSlow, WRAP_NONE, EOR) + +rOP8 (47M1, DirectIndirectLong, WRAP_NONE, EOR) +rOP16(47M0, DirectIndirectLong, WRAP_NONE, EOR) +rOPM (47Slow, DirectIndirectLongSlow, WRAP_NONE, EOR) + +rOP8 (57M1, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOP16(57M0, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOPM (57Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, EOR) + +rOP8 (4DM1, Absolute, WRAP_NONE, EOR) +rOP16(4DM0, Absolute, WRAP_NONE, EOR) +rOPM (4DSlow, AbsoluteSlow, WRAP_NONE, EOR) + +rOP8 (5DM1X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP16(5DM0X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP8 (5DM1X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOP16(5DM0X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOPM (5DSlow, AbsoluteIndexedXSlow, WRAP_NONE, EOR) + +rOP8 (59M1X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP16(59M0X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP8 (59M1X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOP16(59M0X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOPM (59Slow, AbsoluteIndexedYSlow, WRAP_NONE, EOR) + +rOP8 (4FM1, AbsoluteLong, WRAP_NONE, EOR) +rOP16(4FM0, AbsoluteLong, WRAP_NONE, EOR) +rOPM (4FSlow, AbsoluteLongSlow, WRAP_NONE, EOR) + +rOP8 (5FM1, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOP16(5FM0, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOPM (5FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, EOR) + +rOP8 (43M1, StackRelative, WRAP_NONE, EOR) +rOP16(43M0, StackRelative, WRAP_NONE, EOR) +rOPM (43Slow, StackRelativeSlow, WRAP_NONE, EOR) + +rOP8 (53M1, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOP16(53M0, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR) + +/* INC ********************************************************************* */ + +static void Op1AM1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL++; + SetZN(Registers.AL); +} + +static void Op1AM0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W++; + SetZN(Registers.A.W); +} + +static void Op1ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL++; + SetZN(Registers.AL); + } + else + { + Registers.A.W++; + SetZN(Registers.A.W); + } +} + +mOP8 (E6M1, Direct, WRAP_BANK, INC) +mOP16(E6M0, Direct, WRAP_BANK, INC) +mOPM (E6Slow, DirectSlow, WRAP_BANK, INC) + +mOP8 (F6E1, DirectIndexedXE1, WRAP_BANK, INC) +mOP8 (F6E0M1, DirectIndexedXE0, WRAP_BANK, INC) +mOP16(F6E0M0, DirectIndexedXE0, WRAP_BANK, INC) +mOPM (F6Slow, DirectIndexedXSlow, WRAP_BANK, INC) + +mOP8 (EEM1, Absolute, WRAP_NONE, INC) +mOP16(EEM0, Absolute, WRAP_NONE, INC) +mOPM (EESlow, AbsoluteSlow, WRAP_NONE, INC) + +mOP8 (FEM1X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP16(FEM0X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP8 (FEM1X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOP16(FEM0X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOPM (FESlow, AbsoluteIndexedXSlow, WRAP_NONE, INC) + +/* LDA ********************************************************************* */ + +static void OpA9M1 (void) +{ + Registers.AL = Immediate8(READ); + SetZN(Registers.AL); +} + +static void OpA9M0 (void) +{ + Registers.A.W = Immediate16(READ); + SetZN(Registers.A.W); +} + +static void OpA9Slow (void) +{ + if (CheckMemory()) + { + Registers.AL = Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W = Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (A5M1, Direct, WRAP_BANK, LDA) +rOP16(A5M0, Direct, WRAP_BANK, LDA) +rOPM (A5Slow, DirectSlow, WRAP_BANK, LDA) + +rOP8 (B5E1, DirectIndexedXE1, WRAP_BANK, LDA) +rOP8 (B5E0M1, DirectIndexedXE0, WRAP_BANK, LDA) +rOP16(B5E0M0, DirectIndexedXE0, WRAP_BANK, LDA) +rOPM (B5Slow, DirectIndexedXSlow, WRAP_BANK, LDA) + +rOP8 (B2E1, DirectIndirectE1, WRAP_NONE, LDA) +rOP8 (B2E0M1, DirectIndirectE0, WRAP_NONE, LDA) +rOP16(B2E0M0, DirectIndirectE0, WRAP_NONE, LDA) +rOPM (B2Slow, DirectIndirectSlow, WRAP_NONE, LDA) + +rOP8 (A1E1, DirectIndexedIndirectE1, WRAP_NONE, LDA) +rOP8 (A1E0M1, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOP16(A1E0M0, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOPM (A1Slow, DirectIndexedIndirectSlow, WRAP_NONE, LDA) + +rOP8 (B1E1, DirectIndirectIndexedE1, WRAP_NONE, LDA) +rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP16(B1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOP16(B1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOPM (B1Slow, DirectIndirectIndexedSlow, WRAP_NONE, LDA) + +rOP8 (A7M1, DirectIndirectLong, WRAP_NONE, LDA) +rOP16(A7M0, DirectIndirectLong, WRAP_NONE, LDA) +rOPM (A7Slow, DirectIndirectLongSlow, WRAP_NONE, LDA) + +rOP8 (B7M1, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOP16(B7M0, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOPM (B7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, LDA) + +rOP8 (ADM1, Absolute, WRAP_NONE, LDA) +rOP16(ADM0, Absolute, WRAP_NONE, LDA) +rOPM (ADSlow, AbsoluteSlow, WRAP_NONE, LDA) + +rOP8 (BDM1X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP16(BDM0X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP8 (BDM1X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOP16(BDM0X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOPM (BDSlow, AbsoluteIndexedXSlow, WRAP_NONE, LDA) + +rOP8 (B9M1X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP16(B9M0X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP8 (B9M1X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOP16(B9M0X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOPM (B9Slow, AbsoluteIndexedYSlow, WRAP_NONE, LDA) + +rOP8 (AFM1, AbsoluteLong, WRAP_NONE, LDA) +rOP16(AFM0, AbsoluteLong, WRAP_NONE, LDA) +rOPM (AFSlow, AbsoluteLongSlow, WRAP_NONE, LDA) + +rOP8 (BFM1, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOP16(BFM0, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOPM (BFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, LDA) + +rOP8 (A3M1, StackRelative, WRAP_NONE, LDA) +rOP16(A3M0, StackRelative, WRAP_NONE, LDA) +rOPM (A3Slow, StackRelativeSlow, WRAP_NONE, LDA) + +rOP8 (B3M1, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOP16(B3M0, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOPM (B3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA) + +/* LDX ********************************************************************* */ + +static void OpA2X1 (void) +{ + Registers.XL = Immediate8(READ); + SetZN(Registers.XL); +} + +static void OpA2X0 (void) +{ + Registers.X.W = Immediate16(READ); + SetZN(Registers.X.W); +} + +static void OpA2Slow (void) +{ + if (CheckIndex()) + { + Registers.XL = Immediate8Slow(READ); + SetZN(Registers.XL); + } + else + { + Registers.X.W = Immediate16Slow(READ); + SetZN(Registers.X.W); + } +} + +rOP8 (A6X1, Direct, WRAP_BANK, LDX) +rOP16(A6X0, Direct, WRAP_BANK, LDX) +rOPX (A6Slow, DirectSlow, WRAP_BANK, LDX) + +rOP8 (B6E1, DirectIndexedYE1, WRAP_BANK, LDX) +rOP8 (B6E0X1, DirectIndexedYE0, WRAP_BANK, LDX) +rOP16(B6E0X0, DirectIndexedYE0, WRAP_BANK, LDX) +rOPX (B6Slow, DirectIndexedYSlow, WRAP_BANK, LDX) + +rOP8 (AEX1, Absolute, WRAP_BANK, LDX) +rOP16(AEX0, Absolute, WRAP_BANK, LDX) +rOPX (AESlow, AbsoluteSlow, WRAP_BANK, LDX) + +rOP8 (BEX1, AbsoluteIndexedYX1, WRAP_BANK, LDX) +rOP16(BEX0, AbsoluteIndexedYX0, WRAP_BANK, LDX) +rOPX (BESlow, AbsoluteIndexedYSlow, WRAP_BANK, LDX) + +/* LDY ********************************************************************* */ + +static void OpA0X1 (void) +{ + Registers.YL = Immediate8(READ); + SetZN(Registers.YL); +} + +static void OpA0X0 (void) +{ + Registers.Y.W = Immediate16(READ); + SetZN(Registers.Y.W); +} + +static void OpA0Slow (void) +{ + if (CheckIndex()) + { + Registers.YL = Immediate8Slow(READ); + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Immediate16Slow(READ); + SetZN(Registers.Y.W); + } +} + +rOP8 (A4X1, Direct, WRAP_BANK, LDY) +rOP16(A4X0, Direct, WRAP_BANK, LDY) +rOPX (A4Slow, DirectSlow, WRAP_BANK, LDY) + +rOP8 (B4E1, DirectIndexedXE1, WRAP_BANK, LDY) +rOP8 (B4E0X1, DirectIndexedXE0, WRAP_BANK, LDY) +rOP16(B4E0X0, DirectIndexedXE0, WRAP_BANK, LDY) +rOPX (B4Slow, DirectIndexedXSlow, WRAP_BANK, LDY) + +rOP8 (ACX1, Absolute, WRAP_BANK, LDY) +rOP16(ACX0, Absolute, WRAP_BANK, LDY) +rOPX (ACSlow, AbsoluteSlow, WRAP_BANK, LDY) + +rOP8 (BCX1, AbsoluteIndexedXX1, WRAP_BANK, LDY) +rOP16(BCX0, AbsoluteIndexedXX0, WRAP_BANK, LDY) +rOPX (BCSlow, AbsoluteIndexedXSlow, WRAP_BANK, LDY) + +/* LSR ********************************************************************* */ + +static void Op4AM1 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN(Registers.AL); +} + +static void Op4AM0 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN(Registers.A.W); +} + +static void Op4ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN(Registers.AL); + } + else + { + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN(Registers.A.W); + } +} + +mOP8 (46M1, Direct, WRAP_BANK, LSR) +mOP16(46M0, Direct, WRAP_BANK, LSR) +mOPM (46Slow, DirectSlow, WRAP_BANK, LSR) + +mOP8 (56E1, DirectIndexedXE1, WRAP_BANK, LSR) +mOP8 (56E0M1, DirectIndexedXE0, WRAP_BANK, LSR) +mOP16(56E0M0, DirectIndexedXE0, WRAP_BANK, LSR) +mOPM (56Slow, DirectIndexedXSlow, WRAP_BANK, LSR) + +mOP8 (4EM1, Absolute, WRAP_NONE, LSR) +mOP16(4EM0, Absolute, WRAP_NONE, LSR) +mOPM (4ESlow, AbsoluteSlow, WRAP_NONE, LSR) + +mOP8 (5EM1X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP16(5EM0X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP8 (5EM1X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOP16(5EM0X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOPM (5ESlow, AbsoluteIndexedXSlow, WRAP_NONE, LSR) + +/* ORA ********************************************************************* */ + +static void Op09M1 (void) +{ + Registers.AL |= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op09M0 (void) +{ + Registers.A.W |= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op09Slow (void) +{ + if (CheckMemory()) + { + Registers.AL |= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W |= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (05M1, Direct, WRAP_BANK, ORA) +rOP16(05M0, Direct, WRAP_BANK, ORA) +rOPM (05Slow, DirectSlow, WRAP_BANK, ORA) + +rOP8 (15E1, DirectIndexedXE1, WRAP_BANK, ORA) +rOP8 (15E0M1, DirectIndexedXE0, WRAP_BANK, ORA) +rOP16(15E0M0, DirectIndexedXE0, WRAP_BANK, ORA) +rOPM (15Slow, DirectIndexedXSlow, WRAP_BANK, ORA) + +rOP8 (12E1, DirectIndirectE1, WRAP_NONE, ORA) +rOP8 (12E0M1, DirectIndirectE0, WRAP_NONE, ORA) +rOP16(12E0M0, DirectIndirectE0, WRAP_NONE, ORA) +rOPM (12Slow, DirectIndirectSlow, WRAP_NONE, ORA) + +rOP8 (01E1, DirectIndexedIndirectE1, WRAP_NONE, ORA) +rOP8 (01E0M1, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOP16(01E0M0, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOPM (01Slow, DirectIndexedIndirectSlow, WRAP_NONE, ORA) + +rOP8 (11E1, DirectIndirectIndexedE1, WRAP_NONE, ORA) +rOP8 (11E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP16(11E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP8 (11E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOP16(11E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOPM (11Slow, DirectIndirectIndexedSlow, WRAP_NONE, ORA) + +rOP8 (07M1, DirectIndirectLong, WRAP_NONE, ORA) +rOP16(07M0, DirectIndirectLong, WRAP_NONE, ORA) +rOPM (07Slow, DirectIndirectLongSlow, WRAP_NONE, ORA) + +rOP8 (17M1, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOP16(17M0, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOPM (17Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ORA) + +rOP8 (0DM1, Absolute, WRAP_NONE, ORA) +rOP16(0DM0, Absolute, WRAP_NONE, ORA) +rOPM (0DSlow, AbsoluteSlow, WRAP_NONE, ORA) + +rOP8 (1DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP16(1DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP8 (1DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOP16(1DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOPM (1DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ORA) + +rOP8 (19M1X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP16(19M0X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP8 (19M1X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOP16(19M0X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOPM (19Slow, AbsoluteIndexedYSlow, WRAP_NONE, ORA) + +rOP8 (0FM1, AbsoluteLong, WRAP_NONE, ORA) +rOP16(0FM0, AbsoluteLong, WRAP_NONE, ORA) +rOPM (0FSlow, AbsoluteLongSlow, WRAP_NONE, ORA) + +rOP8 (1FM1, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOP16(1FM0, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOPM (1FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ORA) + +rOP8 (03M1, StackRelative, WRAP_NONE, ORA) +rOP16(03M0, StackRelative, WRAP_NONE, ORA) +rOPM (03Slow, StackRelativeSlow, WRAP_NONE, ORA) + +rOP8 (13M1, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOP16(13M0, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOPM (13Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA) + +/* ROL ********************************************************************* */ + +static void Op2AM1 (void) +{ + AddCycles(ONE_CYCLE); + uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x100; + Registers.AL = (uint8) w; + SetZN(Registers.AL); +} + +static void Op2AM0 (void) +{ + AddCycles(ONE_CYCLE); + uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x10000; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); +} + +static void Op2ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x100; + Registers.AL = (uint8) w; + SetZN(Registers.AL); + } + else + { + uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x10000; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); + } +} + +mOP8 (26M1, Direct, WRAP_BANK, ROL) +mOP16(26M0, Direct, WRAP_BANK, ROL) +mOPM (26Slow, DirectSlow, WRAP_BANK, ROL) + +mOP8 (36E1, DirectIndexedXE1, WRAP_BANK, ROL) +mOP8 (36E0M1, DirectIndexedXE0, WRAP_BANK, ROL) +mOP16(36E0M0, DirectIndexedXE0, WRAP_BANK, ROL) +mOPM (36Slow, DirectIndexedXSlow, WRAP_BANK, ROL) + +mOP8 (2EM1, Absolute, WRAP_NONE, ROL) +mOP16(2EM0, Absolute, WRAP_NONE, ROL) +mOPM (2ESlow, AbsoluteSlow, WRAP_NONE, ROL) + +mOP8 (3EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP16(3EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP8 (3EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOP16(3EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOPM (3ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROL) + +/* ROR ********************************************************************* */ + +static void Op6AM1 (void) +{ + AddCycles(ONE_CYCLE); + uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = w & 1; + w >>= 1; + Registers.AL = (uint8) w; + SetZN(Registers.AL); +} + +static void Op6AM0 (void) +{ + AddCycles(ONE_CYCLE); + uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = w & 1; + w >>= 1; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); +} + +static void Op6ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = w & 1; + w >>= 1; + Registers.AL = (uint8) w; + SetZN(Registers.AL); + } + else + { + uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = w & 1; + w >>= 1; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); + } +} + +mOP8 (66M1, Direct, WRAP_BANK, ROR) +mOP16(66M0, Direct, WRAP_BANK, ROR) +mOPM (66Slow, DirectSlow, WRAP_BANK, ROR) + +mOP8 (76E1, DirectIndexedXE1, WRAP_BANK, ROR) +mOP8 (76E0M1, DirectIndexedXE0, WRAP_BANK, ROR) +mOP16(76E0M0, DirectIndexedXE0, WRAP_BANK, ROR) +mOPM (76Slow, DirectIndexedXSlow, WRAP_BANK, ROR) + +mOP8 (6EM1, Absolute, WRAP_NONE, ROR) +mOP16(6EM0, Absolute, WRAP_NONE, ROR) +mOPM (6ESlow, AbsoluteSlow, WRAP_NONE, ROR) + +mOP8 (7EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP16(7EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP8 (7EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOP16(7EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOPM (7ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROR) + +/* SBC ********************************************************************* */ + +static void OpE9M1 (void) +{ + SBC(Immediate8(READ)); +} + +static void OpE9M0 (void) +{ + SBC(Immediate16(READ)); +} + +static void OpE9Slow (void) +{ + if (CheckMemory()) + SBC(Immediate8Slow(READ)); + else + SBC(Immediate16Slow(READ)); +} + +rOP8 (E5M1, Direct, WRAP_BANK, SBC) +rOP16(E5M0, Direct, WRAP_BANK, SBC) +rOPM (E5Slow, DirectSlow, WRAP_BANK, SBC) + +rOP8 (F5E1, DirectIndexedXE1, WRAP_BANK, SBC) +rOP8 (F5E0M1, DirectIndexedXE0, WRAP_BANK, SBC) +rOP16(F5E0M0, DirectIndexedXE0, WRAP_BANK, SBC) +rOPM (F5Slow, DirectIndexedXSlow, WRAP_BANK, SBC) + +rOP8 (F2E1, DirectIndirectE1, WRAP_NONE, SBC) +rOP8 (F2E0M1, DirectIndirectE0, WRAP_NONE, SBC) +rOP16(F2E0M0, DirectIndirectE0, WRAP_NONE, SBC) +rOPM (F2Slow, DirectIndirectSlow, WRAP_NONE, SBC) + +rOP8 (E1E1, DirectIndexedIndirectE1, WRAP_NONE, SBC) +rOP8 (E1E0M1, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOP16(E1E0M0, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOPM (E1Slow, DirectIndexedIndirectSlow, WRAP_NONE, SBC) + +rOP8 (F1E1, DirectIndirectIndexedE1, WRAP_NONE, SBC) +rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP16(F1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOP16(F1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOPM (F1Slow, DirectIndirectIndexedSlow, WRAP_NONE, SBC) + +rOP8 (E7M1, DirectIndirectLong, WRAP_NONE, SBC) +rOP16(E7M0, DirectIndirectLong, WRAP_NONE, SBC) +rOPM (E7Slow, DirectIndirectLongSlow, WRAP_NONE, SBC) + +rOP8 (F7M1, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOP16(F7M0, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOPM (F7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, SBC) + +rOP8 (EDM1, Absolute, WRAP_NONE, SBC) +rOP16(EDM0, Absolute, WRAP_NONE, SBC) +rOPM (EDSlow, AbsoluteSlow, WRAP_NONE, SBC) + +rOP8 (FDM1X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP16(FDM0X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP8 (FDM1X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOP16(FDM0X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOPM (FDSlow, AbsoluteIndexedXSlow, WRAP_NONE, SBC) + +rOP8 (F9M1X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP16(F9M0X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP8 (F9M1X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOP16(F9M0X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOPM (F9Slow, AbsoluteIndexedYSlow, WRAP_NONE, SBC) + +rOP8 (EFM1, AbsoluteLong, WRAP_NONE, SBC) +rOP16(EFM0, AbsoluteLong, WRAP_NONE, SBC) +rOPM (EFSlow, AbsoluteLongSlow, WRAP_NONE, SBC) + +rOP8 (FFM1, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOP16(FFM0, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOPM (FFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, SBC) + +rOP8 (E3M1, StackRelative, WRAP_NONE, SBC) +rOP16(E3M0, StackRelative, WRAP_NONE, SBC) +rOPM (E3Slow, StackRelativeSlow, WRAP_NONE, SBC) + +rOP8 (F3M1, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOP16(F3M0, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOPM (F3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC) + +/* STA ********************************************************************* */ + +wOP8 (85M1, Direct, WRAP_BANK, STA) +wOP16(85M0, Direct, WRAP_BANK, STA) +wOPM (85Slow, DirectSlow, WRAP_BANK, STA) + +wOP8 (95E1, DirectIndexedXE1, WRAP_BANK, STA) +wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) +wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) +wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) + +wOP8 (92E1, DirectIndirectE1, WRAP_NONE, STA) +wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) +wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) +wOPM (92Slow, DirectIndirectSlow, WRAP_NONE, STA) + +wOP8 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) +wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) + +wOP8 (91E1, DirectIndirectIndexedE1, WRAP_NONE, STA) +wOP8 (91E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP16(91E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP8 (91E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOP16(91E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOPM (91Slow, DirectIndirectIndexedSlow, WRAP_NONE, STA) + +wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) +wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) +wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) + +wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) + +wOP8 (8DM1, Absolute, WRAP_NONE, STA) +wOP16(8DM0, Absolute, WRAP_NONE, STA) +wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) + +wOP8 (9DM1X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP16(9DM0X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP8 (9DM1X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOP16(9DM0X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOPM (9DSlow, AbsoluteIndexedXSlow, WRAP_NONE, STA) + +wOP8 (99M1X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP16(99M0X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP8 (99M1X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOP16(99M0X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOPM (99Slow, AbsoluteIndexedYSlow, WRAP_NONE, STA) + +wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) +wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) +wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) + +wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) + +wOP8 (83M1, StackRelative, WRAP_NONE, STA) +wOP16(83M0, StackRelative, WRAP_NONE, STA) +wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) + +wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOPM (93Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, STA) + +/* STX ********************************************************************* */ + +wOP8 (86X1, Direct, WRAP_BANK, STX) +wOP16(86X0, Direct, WRAP_BANK, STX) +wOPX (86Slow, DirectSlow, WRAP_BANK, STX) + +wOP8 (96E1, DirectIndexedYE1, WRAP_BANK, STX) +wOP8 (96E0X1, DirectIndexedYE0, WRAP_BANK, STX) +wOP16(96E0X0, DirectIndexedYE0, WRAP_BANK, STX) +wOPX (96Slow, DirectIndexedYSlow, WRAP_BANK, STX) + +wOP8 (8EX1, Absolute, WRAP_BANK, STX) +wOP16(8EX0, Absolute, WRAP_BANK, STX) +wOPX (8ESlow, AbsoluteSlow, WRAP_BANK, STX) + +/* STY ********************************************************************* */ + +wOP8 (84X1, Direct, WRAP_BANK, STY) +wOP16(84X0, Direct, WRAP_BANK, STY) +wOPX (84Slow, DirectSlow, WRAP_BANK, STY) + +wOP8 (94E1, DirectIndexedXE1, WRAP_BANK, STY) +wOP8 (94E0X1, DirectIndexedXE0, WRAP_BANK, STY) +wOP16(94E0X0, DirectIndexedXE0, WRAP_BANK, STY) +wOPX (94Slow, DirectIndexedXSlow, WRAP_BANK, STY) + +wOP8 (8CX1, Absolute, WRAP_BANK, STY) +wOP16(8CX0, Absolute, WRAP_BANK, STY) +wOPX (8CSlow, AbsoluteSlow, WRAP_BANK, STY) + +/* STZ ********************************************************************* */ + +wOP8 (64M1, Direct, WRAP_BANK, STZ) +wOP16(64M0, Direct, WRAP_BANK, STZ) +wOPM (64Slow, DirectSlow, WRAP_BANK, STZ) + +wOP8 (74E1, DirectIndexedXE1, WRAP_BANK, STZ) +wOP8 (74E0M1, DirectIndexedXE0, WRAP_BANK, STZ) +wOP16(74E0M0, DirectIndexedXE0, WRAP_BANK, STZ) +wOPM (74Slow, DirectIndexedXSlow, WRAP_BANK, STZ) + +wOP8 (9CM1, Absolute, WRAP_NONE, STZ) +wOP16(9CM0, Absolute, WRAP_NONE, STZ) +wOPM (9CSlow, AbsoluteSlow, WRAP_NONE, STZ) + +wOP8 (9EM1X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP16(9EM0X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP8 (9EM1X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOP16(9EM0X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOPM (9ESlow, AbsoluteIndexedXSlow, WRAP_NONE, STZ) + +/* TRB ********************************************************************* */ + +mOP8 (14M1, Direct, WRAP_BANK, TRB) +mOP16(14M0, Direct, WRAP_BANK, TRB) +mOPM (14Slow, DirectSlow, WRAP_BANK, TRB) + +mOP8 (1CM1, Absolute, WRAP_BANK, TRB) +mOP16(1CM0, Absolute, WRAP_BANK, TRB) +mOPM (1CSlow, AbsoluteSlow, WRAP_BANK, TRB) + +/* TSB ********************************************************************* */ + +mOP8 (04M1, Direct, WRAP_BANK, TSB) +mOP16(04M0, Direct, WRAP_BANK, TSB) +mOPM (04Slow, DirectSlow, WRAP_BANK, TSB) + +mOP8 (0CM1, Absolute, WRAP_BANK, TSB) +mOP16(0CM0, Absolute, WRAP_BANK, TSB) +mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) + +/* Branch Instructions ***************************************************** */ + +// BCC +bOP(90E0, Relative, !CheckCarry(), 0, 0) +bOP(90E1, Relative, !CheckCarry(), 0, 1) +bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) + +// BCS +bOP(B0E0, Relative, CheckCarry(), 0, 0) +bOP(B0E1, Relative, CheckCarry(), 0, 1) +bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) + +// BEQ +bOP(F0E0, Relative, CheckZero(), 2, 0) +bOP(F0E1, Relative, CheckZero(), 2, 1) +bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) + +// BMI +bOP(30E0, Relative, CheckNegative(), 1, 0) +bOP(30E1, Relative, CheckNegative(), 1, 1) +bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) + +// BNE +bOP(D0E0, Relative, !CheckZero(), 1, 0) +bOP(D0E1, Relative, !CheckZero(), 1, 1) +bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) + +// BPL +bOP(10E0, Relative, !CheckNegative(), 1, 0) +bOP(10E1, Relative, !CheckNegative(), 1, 1) +bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation()) + +// BRA +bOP(80E0, Relative, 1, X, 0) +bOP(80E1, Relative, 1, X, 1) +bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) + +// BVC +bOP(50E0, Relative, !CheckOverflow(), 0, 0) +bOP(50E1, Relative, !CheckOverflow(), 0, 1) +bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation()) + +// BVS +bOP(70E0, Relative, CheckOverflow(), 0, 0) +bOP(70E1, Relative, CheckOverflow(), 0, 1) +bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) + +// BRL +static void Op82 (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); +} + +static void Op82Slow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); +} + +/* Flag Instructions ******************************************************* */ + +// CLC +static void Op18 (void) +{ + ClearCarry(); + AddCycles(ONE_CYCLE); +} + +// SEC +static void Op38 (void) +{ + SetCarry(); + AddCycles(ONE_CYCLE); +} + +// CLD +static void OpD8 (void) +{ + ClearDecimal(); + AddCycles(ONE_CYCLE); +} + +// SED +static void OpF8 (void) +{ + SetDecimal(); + AddCycles(ONE_CYCLE); +#ifdef DEBUGGER + missing.decimal_mode = 1; +#endif +} + +// CLI +static void Op58 (void) +{ + ClearIRQ(); + AddCycles(ONE_CYCLE); + CHECK_FOR_IRQ(); +} + +// SEI +static void Op78 (void) +{ + SetIRQ(); + AddCycles(ONE_CYCLE); +} + +// CLV +static void OpB8 (void) +{ + ClearOverflow(); + AddCycles(ONE_CYCLE); +} + +/* DEX/DEY ***************************************************************** */ + +static void OpCAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL--; + SetZN(Registers.XL); +} + +static void OpCAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W--; + SetZN(Registers.X.W); +} + +static void OpCASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL--; + SetZN(Registers.XL); + } + else + { + Registers.X.W--; + SetZN(Registers.X.W); + } +} + +static void Op88X1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL--; + SetZN(Registers.YL); +} + +static void Op88X0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W--; + SetZN(Registers.Y.W); +} + +static void Op88Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL--; + SetZN(Registers.YL); + } + else + { + Registers.Y.W--; + SetZN(Registers.Y.W); + } +} + +/* INX/INY ***************************************************************** */ + +static void OpE8X1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL++; + SetZN(Registers.XL); +} + +static void OpE8X0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W++; + SetZN(Registers.X.W); +} + +static void OpE8Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL++; + SetZN(Registers.XL); + } + else + { + Registers.X.W++; + SetZN(Registers.X.W); + } +} + +static void OpC8X1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL++; + SetZN(Registers.YL); +} + +static void OpC8X0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W++; + SetZN(Registers.Y.W); +} + +static void OpC8Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL--; + SetZN(Registers.YL); + } + else + { + Registers.Y.W--; + SetZN(Registers.Y.W); + } +} + +/* NOP ********************************************************************* */ + +static void OpEA (void) +{ + AddCycles(ONE_CYCLE); +} + +/* PUSH Instructions ******************************************************* */ + +#define PushW(w) \ + S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \ + Registers.S.W -= 2; + +#define PushWE(w) \ + Registers.SL--; \ + S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \ + Registers.SL--; + +#define PushB(b) \ + S9xSetByte(b, Registers.S.W--); + +#define PushBE(b) \ + S9xSetByte(b, Registers.S.W); \ + Registers.SL--; + +// PEA +static void OpF4E0 (void) +{ + uint16 val = (uint16) Absolute(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void OpF4E1 (void) +{ + // Note: PEA is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) Absolute(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void OpF4Slow (void) +{ + uint16 val = (uint16) AbsoluteSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PEI +static void OpD4E0 (void) +{ + uint16 val = (uint16) DirectIndirectE0(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void OpD4E1 (void) +{ + // Note: PEI is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) DirectIndirectE1(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void OpD4Slow (void) +{ + uint16 val = (uint16) DirectIndirectSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PER +static void Op62E0 (void) +{ + uint16 val = (uint16) RelativeLong(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void Op62E1 (void) +{ + // Note: PER is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) RelativeLong(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void Op62Slow (void) +{ + uint16 val = (uint16) RelativeLongSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PHA +static void Op48E1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op48E0M1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op48E0M0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.A.W); + OpenBus = Registers.AL; +} + +static void Op48Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.AL); + } + else + if (CheckMemory()) + { + PushB(Registers.AL); + } + else + { + PushW(Registers.A.W); + } + + OpenBus = Registers.AL; +} + +// PHB +static void Op8BE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.DB); + OpenBus = Registers.DB; +} + +static void Op8BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.DB); + OpenBus = Registers.DB; +} + +static void Op8BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.DB); + } + else + { + PushB(Registers.DB); + } + + OpenBus = Registers.DB; +} + +// PHD +static void Op0BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; +} + +static void Op0BE1 (void) +{ + // Note: PHD is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; + Registers.SH = 1; +} + +static void Op0BSlow (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PHK +static void Op4BE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.PB); + OpenBus = Registers.PB; +} + +static void Op4BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.PB); + OpenBus = Registers.PB; +} + +static void Op4BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.PB); + } + else + { + PushB(Registers.PB); + } + + OpenBus = Registers.PB; +} + +// PHP +static void Op08E0 (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + PushB(Registers.PL); + OpenBus = Registers.PL; +} + +static void Op08E1 (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + PushBE(Registers.PL); + OpenBus = Registers.PL; +} + +static void Op08Slow (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.PL); + } + else + { + PushB(Registers.PL); + } + + OpenBus = Registers.PL; +} + +// PHX +static void OpDAE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpDAE0X1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpDAE0X0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.X.W); + OpenBus = Registers.XL; +} + +static void OpDASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.XL); + } + else + if (CheckIndex()) + { + PushB(Registers.XL); + } + else + { + PushW(Registers.X.W); + } + + OpenBus = Registers.XL; +} + +// PHY +static void Op5AE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op5AE0X1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op5AE0X0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.Y.W); + OpenBus = Registers.YL; +} + +static void Op5ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.YL); + } + else + if (CheckIndex()) + { + PushB(Registers.YL); + } + else + { + PushW(Registers.Y.W); + } + + OpenBus = Registers.YL; +} + +/* PULL Instructions ******************************************************* */ + +#define PullW(w) \ + w = S9xGetWord(Registers.S.W + 1, WRAP_BANK); \ + Registers.S.W += 2; + +#define PullWE(w) \ + Registers.SL++; \ + w = S9xGetWord(Registers.S.W, WRAP_PAGE); \ + Registers.SL++; + +#define PullB(b) \ + b = S9xGetByte(++Registers.S.W); + +#define PullBE(b) \ + Registers.SL++; \ + b = S9xGetByte(Registers.S.W); + +// PLA +static void Op68E1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op68E0M1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op68E0M0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.A.W); + SetZN(Registers.A.W); + OpenBus = Registers.AH; +} + +static void Op68Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; + } + else + if (CheckMemory()) + { + PullB(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; + } + else + { + PullW(Registers.A.W); + SetZN(Registers.A.W); + OpenBus = Registers.AH; + } +} + +// PLB +static void OpABE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.DB); + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +static void OpABE0 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.DB); + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +static void OpABSlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.DB); + } + else + { + PullB(Registers.DB); + } + + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +// PLD +static void Op2BE0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; +} + +static void Op2BE1 (void) +{ + // Note: PLD is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; + Registers.SH = 1; +} + +static void Op2BSlow (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PLP +static void Op28E1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.PL); + OpenBus = Registers.PL; + SetFlags(MemoryFlag | IndexFlag); + S9xUnpackStatus(); + S9xFixCycles(); + CHECK_FOR_IRQ(); +} + +static void Op28E0 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.PL); + OpenBus = Registers.PL; + S9xUnpackStatus(); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + CHECK_FOR_IRQ(); +} + +static void Op28Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.PL); + OpenBus = Registers.PL; + SetFlags(MemoryFlag | IndexFlag); + } + else + { + PullB(Registers.PL); + OpenBus = Registers.PL; + } + + S9xUnpackStatus(); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + CHECK_FOR_IRQ(); +} + +// PLX +static void OpFAE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpFAE0X1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpFAE0X0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.X.W); + SetZN(Registers.X.W); + OpenBus = Registers.XH; +} + +static void OpFASlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; + } + else + if (CheckIndex()) + { + PullB(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; + } + else + { + PullW(Registers.X.W); + SetZN(Registers.X.W); + OpenBus = Registers.XH; + } +} + +// PLY +static void Op7AE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op7AE0X1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op7AE0X0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.Y.W); + SetZN(Registers.Y.W); + OpenBus = Registers.YH; +} + +static void Op7ASlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; + } + else + if (CheckIndex()) + { + PullB(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; + } + else + { + PullW(Registers.Y.W); + SetZN(Registers.Y.W); + OpenBus = Registers.YH; + } +} + +/* Transfer Instructions *************************************************** */ + +// TAX +static void OpAAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.AL; + SetZN(Registers.XL); +} + +static void OpAAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.A.W; + SetZN(Registers.X.W); +} + +static void OpAASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.AL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.A.W; + SetZN(Registers.X.W); + } +} + +// TAY +static void OpA8X1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL = Registers.AL; + SetZN(Registers.YL); +} + +static void OpA8X0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.A.W; + SetZN(Registers.Y.W); +} + +static void OpA8Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL = Registers.AL; + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Registers.A.W; + SetZN(Registers.Y.W); + } +} + +// TCD +static void Op5B (void) +{ + AddCycles(ONE_CYCLE); + Registers.D.W = Registers.A.W; + SetZN(Registers.D.W); +} + +// TCS +static void Op1B (void) +{ + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.A.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +// TDC +static void Op7B (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.D.W; + SetZN(Registers.A.W); +} + +// TSC +static void Op3B (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.S.W; + SetZN(Registers.A.W); +} + +// TSX +static void OpBAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.SL; + SetZN(Registers.XL); +} + +static void OpBAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.S.W; + SetZN(Registers.X.W); +} + +static void OpBASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.SL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.S.W; + SetZN(Registers.X.W); + } +} + +// TXA +static void Op8AM1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL = Registers.XL; + SetZN(Registers.AL); +} + +static void Op8AM0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.X.W; + SetZN(Registers.A.W); +} + +static void Op8ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL = Registers.XL; + SetZN(Registers.AL); + } + else + { + Registers.A.W = Registers.X.W; + SetZN(Registers.A.W); + } +} + +// TXS +static void Op9A (void) +{ + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.X.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +// TXY +static void Op9BX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL = Registers.XL; + SetZN(Registers.YL); +} + +static void Op9BX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.X.W; + SetZN(Registers.Y.W); +} + +static void Op9BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL = Registers.XL; + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Registers.X.W; + SetZN(Registers.Y.W); + } +} + +// TYA +static void Op98M1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL = Registers.YL; + SetZN(Registers.AL); +} + +static void Op98M0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.Y.W; + SetZN(Registers.A.W); +} + +static void Op98Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL = Registers.YL; + SetZN(Registers.AL); + } + else + { + Registers.A.W = Registers.Y.W; + SetZN(Registers.A.W); + } +} + +// TYX +static void OpBBX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.YL; + SetZN(Registers.XL); +} + +static void OpBBX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.Y.W; + SetZN(Registers.X.W); +} + +static void OpBBSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.YL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.Y.W; + SetZN(Registers.X.W); + } +} + +/* XCE ********************************************************************* */ + +static void OpFB (void) +{ + AddCycles(ONE_CYCLE); + + uint8 A1 = ICPU._Carry; + uint8 A2 = Registers.PH; + + ICPU._Carry = A2 & 1; + Registers.PH = A1; + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + Registers.SH = 1; + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +/* BRK ********************************************************************* */ + +static void Op00 (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** BRK"); +#endif + + AddCycles(CPU.MemSpeed); + + uint16 addr; + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw + 1); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFE6); + } + else + { + PushWE(Registers.PCw + 1); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFFE); + } + + S9xSetPCBase(addr); + OpenBus = addr >> 8; +} + +/* IRQ ********************************************************************* */ + +void S9xOpcode_IRQ (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + #ifdef SA1_OPCODES + S9xTraceMessage("*** SA1 IRQ"); + #else + S9xTraceMessage("*** IRQ"); + #endif +#endif + + // IRQ and NMI do an opcode fetch as their first "IO" cycle. + AddCycles(CPU.MemSpeed + ONE_CYCLE); + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2208]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) + { + OpenBus = Memory.FillRAM[0x220f]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFEE); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } + else + { + PushWE(Registers.PCw); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2208]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) + { + OpenBus = Memory.FillRAM[0x220f]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFFE); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } +} + +/* NMI ********************************************************************* */ + +void S9xOpcode_NMI (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + #ifdef SA1_OPCODES + S9xTraceMessage("*** SA1 NMI"); + #else + S9xTraceMessage("*** NMI"); + #endif +#endif + + // IRQ and NMI do an opcode fetch as their first "IO" cycle. + AddCycles(CPU.MemSpeed + ONE_CYCLE); + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2206]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10)) + { + OpenBus = Memory.FillRAM[0x220d]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFEA); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } + else + { + PushWE(Registers.PCw); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2206]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10)) + { + OpenBus = Memory.FillRAM[0x220d]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFFA); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } +} + +/* COP ********************************************************************* */ + +static void Op02 (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** COP"); +#endif + + AddCycles(CPU.MemSpeed); + + uint16 addr; + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw + 1); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFE4); + } + else + { + PushWE(Registers.PCw + 1); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFF4); + } + + S9xSetPCBase(addr); + OpenBus = addr >> 8; +} + +/* JML ********************************************************************* */ + +static void OpDC (void) +{ + S9xSetPCBase(AbsoluteIndirectLong(JUMP)); +} + +static void OpDCSlow (void) +{ + S9xSetPCBase(AbsoluteIndirectLongSlow(JUMP)); +} + +static void Op5C (void) +{ + S9xSetPCBase(AbsoluteLong(JUMP)); +} + +static void Op5CSlow (void) +{ + S9xSetPCBase(AbsoluteLongSlow(JUMP)); +} + +/* JMP ********************************************************************* */ + +static void Op4C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP))); +} + +static void Op4CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP))); +} + +static void Op6C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirect(JUMP))); +} + +static void Op6CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirectSlow(JUMP))); +} + +static void Op7C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirect(JUMP))); +} + +static void Op7CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirectSlow(JUMP))); +} + +/* JSL/RTL ***************************************************************** */ + +static void Op22E1 (void) +{ + // Note: JSL is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint32 addr = AbsoluteLong(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase(addr); +} + +static void Op22E0 (void) +{ + uint32 addr = AbsoluteLong(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + S9xSetPCBase(addr); +} + +static void Op22Slow (void) +{ + uint32 addr = AbsoluteLongSlow(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + if (CheckEmulation()) + Registers.SH = 1; + S9xSetPCBase(addr); +} + +static void Op6BE1 (void) +{ + // Note: RTL is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op6BE0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op6BSlow (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + if (CheckEmulation()) + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +/* JSR/RTS ***************************************************************** */ + +static void Op20E1 (void) +{ + uint16 addr = Absolute(JSR); + AddCycles(ONE_CYCLE); + PushWE(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op20E0 (void) +{ + uint16 addr = Absolute(JSR); + AddCycles(ONE_CYCLE); + PushW(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op20Slow (void) +{ + uint16 addr = AbsoluteSlow(JSR); + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushWE(Registers.PCw - 1); + } + else + { + PushW(Registers.PCw - 1); + } + + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCE1 (void) +{ + // Note: JSR (a,X) is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 addr = AbsoluteIndexedIndirect(JSR); + PushW(Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCE0 (void) +{ + uint16 addr = AbsoluteIndexedIndirect(JSR); + PushW(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCSlow (void) +{ + uint16 addr = AbsoluteIndexedIndirectSlow(JSR); + PushW(Registers.PCw - 1); + if (CheckEmulation()) + Registers.SH = 1; + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op60E1 (void) +{ + AddCycles(TWO_CYCLES); + PullWE(Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op60E0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op60Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullWE(Registers.PCw); + } + else + { + PullW(Registers.PCw); + } + + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +/* MVN/MVP ***************************************************************** */ + +static void Op54X1 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL++; + Registers.YL++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op54X0 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.X.W++; + Registers.Y.W++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op54Slow (void) +{ + uint32 SrcBank; + + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + if (CheckIndex()) + { + Registers.XL++; + Registers.YL++; + } + else + { + Registers.X.W++; + Registers.Y.W++; + } + + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44X1 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL--; + Registers.YL--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44X0 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.X.W--; + Registers.Y.W--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44Slow (void) +{ + uint32 SrcBank; + + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + if (CheckIndex()) + { + Registers.XL--; + Registers.YL--; + } + else + { + Registers.X.W--; + Registers.Y.W--; + } + + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +/* REP/SEP ***************************************************************** */ + +static void OpC2 (void) +{ + uint8 Work8 = ~Immediate8(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + CHECK_FOR_IRQ(); +} + +static void OpC2Slow (void) +{ + uint8 Work8 = ~Immediate8Slow(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + CHECK_FOR_IRQ(); +} + +static void OpE2 (void) +{ + uint8 Work8 = Immediate8(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +static void OpE2Slow (void) +{ + uint8 Work8 = Immediate8Slow(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +/* XBA ********************************************************************* */ + +static void OpEB (void) +{ + uint8 Work8 = Registers.AL; + Registers.AL = Registers.AH; + Registers.AH = Work8; + SetZN(Registers.AL); + AddCycles(TWO_CYCLES); +} + +/* RTI ********************************************************************* */ + +static void Op40Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (!CheckEmulation()) + { + PullB(Registers.PL); + S9xUnpackStatus(); + PullW(Registers.PCw); + PullB(Registers.PB); + OpenBus = Registers.PB; + ICPU.ShiftedPB = Registers.PB << 16; + } + else + { + PullBE(Registers.PL); + S9xUnpackStatus(); + PullWE(Registers.PCw); + OpenBus = Registers.PCh; + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + S9xSetPCBase(Registers.PBPC); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + CHECK_FOR_IRQ(); +} + +/* STP/WAI ***************************************************************** */ + +// WAI +static void OpCB (void) +{ +#ifdef SA1_OPCODES + SA1.WaitingForInterrupt = TRUE; + Registers.PCw--; + AddCycles(TWO_CYCLES); +#else + CPU.WaitingForInterrupt = TRUE; + Registers.PCw--; + AddCycles(TWO_CYCLES); +#endif +} + +// STP +static void OpDB (void) +{ + Registers.PCw--; + CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG; +} + +/* WDM (Reserved S9xOpcode) ************************************************ */ + +#ifdef DEBUGGER +extern FILE *trace, *trace2; +#endif + +static void Op42 (void) +{ +#ifdef DEBUGGER + uint8 byte = (uint8) S9xGetWord(Registers.PBPC); +#else + S9xGetWord(Registers.PBPC); +#endif + Registers.PCw++; + +#ifdef DEBUGGER + // Hey, let's use this to trigger debug modes. + switch (byte) + { + case 0xdb: // "STP" = Enter debug mode + CPU.Flags |= DEBUG_MODE_FLAG; + break; + + #ifndef SA1_OPCODES + case 0xe2: // "SEP" = Trace on + if (!(CPU.Flags & TRACE_FLAG)) + { + char buf[25]; + CPU.Flags |= TRACE_FLAG; + snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if (trace != NULL) + fclose(trace); + ENSURE_TRACE_OPEN(trace,"WDMtrace.log","ab") + } + + break; + + case 0xc2: // "REP" = Trace off + if (CPU.Flags & TRACE_FLAG) + { + char buf[26]; + CPU.Flags &= ~TRACE_FLAG; + snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if (trace != NULL) + fclose(trace); + trace = NULL; + } + + break; + #endif + + case 0x42: // "WDM" = Snapshot + char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff); + sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def); + S9xFreezeGame(filename); + + break; + + default: + break; + } +#endif +} + +/* CPU-S9xOpcodes Definitions ************************************************/ + +struct SOpcodes S9xOpcodesM1X1[256] = +{ + { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, + { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E0 }, { Op11E0M1X1 }, { Op12E0M1 }, { Op13M1 }, + { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, + { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, + { Op1EM1X1 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X1 }, + { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, + { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, + { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, + { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E0 }, { Op51E0M1X1 }, { Op52E0M1 }, { Op53M1 }, { Op54X1 }, + { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, + { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, + { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X1 }, { Op72E0M1 }, + { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, + { Op78 }, { Op79M1X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, + { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, + { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, + { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, + { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E0 }, + { Op91E0M1X1 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X1 }, { Op95E0M1 }, + { Op96E0X1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, + { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, + { OpA0X1 }, { OpA1E0M1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, + { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, + { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, + { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X1 }, { OpB2E0M1 }, { OpB3M1 }, + { OpB4E0X1 }, { OpB5E0M1 }, { OpB6E0X1 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, + { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E0M1 }, { OpC2 }, + { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X1 }, + { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE0X1 }, { OpDB }, + { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, + { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E0 }, { OpF1E0M1X1 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, + { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, + { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM1X1 }, { OpFEM1X1 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesE1[256] = +{ + { Op00 }, { Op01E1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E1 }, { Op09M1 }, + { Op0AM1 }, { Op0BE1 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E1 }, { Op11E1 }, { Op12E1 }, { Op13M1 }, + { Op14M1 }, { Op15E1 }, { Op16E1 }, { Op17M1 }, { Op18 }, + { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, + { Op1EM1X1 }, { Op1FM1 }, { Op20E1 }, { Op21E1 }, { Op22E1 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E1 }, { Op29M1 }, { Op2AM1 }, { Op2BE1 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E1 }, { Op31E1 }, + { Op32E1 }, { Op33M1 }, { Op34E1 }, { Op35E1 }, { Op36E1 }, + { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, + { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, + { Op41E1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE1 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E1 }, { Op51E1 }, { Op52E1 }, { Op53M1 }, { Op54X1 }, + { Op55E1 }, { Op56E1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, + { Op5AE1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, + { Op5FM1 }, { Op60E1 }, { Op61E1 }, { Op62E1 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE1 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E1 }, { Op71E1 }, { Op72E1 }, + { Op73M1 }, { Op74E1 }, { Op75E1 }, { Op76E1 }, { Op77M1 }, + { Op78 }, { Op79M1X1 }, { Op7AE1 }, { Op7B }, { Op7C }, + { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E1 }, { Op81E1 }, + { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, + { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE1 }, + { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E1 }, + { Op91E1 }, { Op92E1 }, { Op93M1 }, { Op94E1 }, { Op95E1 }, + { Op96E1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, + { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, + { OpA0X1 }, { OpA1E1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, + { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, + { OpAAX1 }, { OpABE1 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, + { OpAFM1 }, { OpB0E1 }, { OpB1E1 }, { OpB2E1 }, { OpB3M1 }, + { OpB4E1 }, { OpB5E1 }, { OpB6E1 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, + { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E1 }, { OpC2 }, + { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E1 }, { OpD1E1 }, + { OpD2E1 }, { OpD3M1 }, { OpD4E1 }, { OpD5E1 }, { OpD6E1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE1 }, { OpDB }, + { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, + { OpE1E1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E1 }, { OpF1E1 }, { OpF2E1 }, { OpF3M1 }, { OpF4E1 }, + { OpF5E1 }, { OpF6E1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, + { OpFAE1 }, { OpFB }, { OpFCE1 }, { OpFDM1X1 }, { OpFEM1X1 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesM1X0[256] = +{ + { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, + { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E0 }, { Op11E0M1X0 }, { Op12E0M1 }, { Op13M1 }, + { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, + { Op19M1X0 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X0 }, + { Op1EM1X0 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X0 }, + { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, + { Op37M1 }, { Op38 }, { Op39M1X0 }, { Op3AM1 }, { Op3B }, + { Op3CM1X0 }, { Op3DM1X0 }, { Op3EM1X0 }, { Op3FM1 }, { Op40Slow }, + { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X0 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E0 }, { Op51E0M1X0 }, { Op52E0M1 }, { Op53M1 }, { Op54X0 }, + { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X0 }, + { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM1X0 }, { Op5EM1X0 }, + { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X0 }, { Op72E0M1 }, + { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, + { Op78 }, { Op79M1X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, + { Op7DM1X0 }, { Op7EM1X0 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, + { Op82 }, { Op83M1 }, { Op84X0 }, { Op85M1 }, { Op86X0 }, + { Op87M1 }, { Op88X0 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, + { Op8CX0 }, { Op8DM1 }, { Op8EX0 }, { Op8FM1 }, { Op90E0 }, + { Op91E0M1X0 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X0 }, { Op95E0M1 }, + { Op96E0X0 }, { Op97M1 }, { Op98M1 }, { Op99M1X0 }, { Op9A }, + { Op9BX0 }, { Op9CM1 }, { Op9DM1X0 }, { Op9EM1X0 }, { Op9FM1 }, + { OpA0X0 }, { OpA1E0M1 }, { OpA2X0 }, { OpA3M1 }, { OpA4X0 }, + { OpA5M1 }, { OpA6X0 }, { OpA7M1 }, { OpA8X0 }, { OpA9M1 }, + { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM1 }, { OpAEX0 }, + { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X0 }, { OpB2E0M1 }, { OpB3M1 }, + { OpB4E0X0 }, { OpB5E0M1 }, { OpB6E0X0 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM1X0 }, + { OpBEX0 }, { OpBFM1 }, { OpC0X0 }, { OpC1E0M1 }, { OpC2 }, + { OpC3M1 }, { OpC4X0 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X0 }, { OpC9M1 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X0 }, + { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X0 }, { OpDAE0X0 }, { OpDB }, + { OpDC }, { OpDDM1X0 }, { OpDEM1X0 }, { OpDFM1 }, { OpE0X0 }, + { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X0 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X0 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX0 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E0 }, { OpF1E0M1X0 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, + { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X0 }, + { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM1X0 }, { OpFEM1X0 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesM0X0[256] = +{ + { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, + { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, + { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, + { Op0FM0 }, { Op10E0 }, { Op11E0M0X0 }, { Op12E0M0 }, { Op13M0 }, + { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, + { Op19M0X0 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X0 }, + { Op1EM0X0 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, + { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, + { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, + { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X0 }, + { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, + { Op37M0 }, { Op38 }, { Op39M0X0 }, { Op3AM0 }, { Op3B }, + { Op3CM0X0 }, { Op3DM0X0 }, { Op3EM0X0 }, { Op3FM0 }, { Op40Slow }, + { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X0 }, { Op45M0 }, + { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, + { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, + { Op50E0 }, { Op51E0M0X0 }, { Op52E0M0 }, { Op53M0 }, { Op54X0 }, + { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X0 }, + { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM0X0 }, { Op5EM0X0 }, + { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, + { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, + { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, + { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X0 }, { Op72E0M0 }, + { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, + { Op78 }, { Op79M0X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, + { Op7DM0X0 }, { Op7EM0X0 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, + { Op82 }, { Op83M0 }, { Op84X0 }, { Op85M0 }, { Op86X0 }, + { Op87M0 }, { Op88X0 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, + { Op8CX0 }, { Op8DM0 }, { Op8EX0 }, { Op8FM0 }, { Op90E0 }, + { Op91E0M0X0 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X0 }, { Op95E0M0 }, + { Op96E0X0 }, { Op97M0 }, { Op98M0 }, { Op99M0X0 }, { Op9A }, + { Op9BX0 }, { Op9CM0 }, { Op9DM0X0 }, { Op9EM0X0 }, { Op9FM0 }, + { OpA0X0 }, { OpA1E0M0 }, { OpA2X0 }, { OpA3M0 }, { OpA4X0 }, + { OpA5M0 }, { OpA6X0 }, { OpA7M0 }, { OpA8X0 }, { OpA9M0 }, + { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM0 }, { OpAEX0 }, + { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X0 }, { OpB2E0M0 }, { OpB3M0 }, + { OpB4E0X0 }, { OpB5E0M0 }, { OpB6E0X0 }, { OpB7M0 }, { OpB8 }, + { OpB9M0X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM0X0 }, + { OpBEX0 }, { OpBFM0 }, { OpC0X0 }, { OpC1E0M0 }, { OpC2 }, + { OpC3M0 }, { OpC4X0 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, + { OpC8X0 }, { OpC9M0 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, + { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X0 }, + { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, + { OpD7M0 }, { OpD8 }, { OpD9M0X0 }, { OpDAE0X0 }, { OpDB }, + { OpDC }, { OpDDM0X0 }, { OpDEM0X0 }, { OpDFM0 }, { OpE0X0 }, + { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X0 }, { OpE5M0 }, + { OpE6M0 }, { OpE7M0 }, { OpE8X0 }, { OpE9M0 }, { OpEA }, + { OpEB }, { OpECX0 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, + { OpF0E0 }, { OpF1E0M0X0 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, + { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X0 }, + { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM0X0 }, { OpFEM0X0 }, + { OpFFM0 } +}; + +struct SOpcodes S9xOpcodesM0X1[256] = +{ + { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, + { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, + { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, + { Op0FM0 }, { Op10E0 }, { Op11E0M0X1 }, { Op12E0M0 }, { Op13M0 }, + { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, + { Op19M0X1 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X1 }, + { Op1EM0X1 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, + { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, + { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, + { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X1 }, + { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, + { Op37M0 }, { Op38 }, { Op39M0X1 }, { Op3AM0 }, { Op3B }, + { Op3CM0X1 }, { Op3DM0X1 }, { Op3EM0X1 }, { Op3FM0 }, { Op40Slow }, + { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X1 }, { Op45M0 }, + { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, + { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, + { Op50E0 }, { Op51E0M0X1 }, { Op52E0M0 }, { Op53M0 }, { Op54X1 }, + { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X1 }, + { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM0X1 }, { Op5EM0X1 }, + { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, + { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, + { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, + { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X1 }, { Op72E0M0 }, + { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, + { Op78 }, { Op79M0X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, + { Op7DM0X1 }, { Op7EM0X1 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, + { Op82 }, { Op83M0 }, { Op84X1 }, { Op85M0 }, { Op86X1 }, + { Op87M0 }, { Op88X1 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, + { Op8CX1 }, { Op8DM0 }, { Op8EX1 }, { Op8FM0 }, { Op90E0 }, + { Op91E0M0X1 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X1 }, { Op95E0M0 }, + { Op96E0X1 }, { Op97M0 }, { Op98M0 }, { Op99M0X1 }, { Op9A }, + { Op9BX1 }, { Op9CM0 }, { Op9DM0X1 }, { Op9EM0X1 }, { Op9FM0 }, + { OpA0X1 }, { OpA1E0M0 }, { OpA2X1 }, { OpA3M0 }, { OpA4X1 }, + { OpA5M0 }, { OpA6X1 }, { OpA7M0 }, { OpA8X1 }, { OpA9M0 }, + { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM0 }, { OpAEX1 }, + { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X1 }, { OpB2E0M0 }, { OpB3M0 }, + { OpB4E0X1 }, { OpB5E0M0 }, { OpB6E0X1 }, { OpB7M0 }, { OpB8 }, + { OpB9M0X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM0X1 }, + { OpBEX1 }, { OpBFM0 }, { OpC0X1 }, { OpC1E0M0 }, { OpC2 }, + { OpC3M0 }, { OpC4X1 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, + { OpC8X1 }, { OpC9M0 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X1 }, + { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, + { OpD7M0 }, { OpD8 }, { OpD9M0X1 }, { OpDAE0X1 }, { OpDB }, + { OpDC }, { OpDDM0X1 }, { OpDEM0X1 }, { OpDFM0 }, { OpE0X1 }, + { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X1 }, { OpE5M0 }, + { OpE6M0 }, { OpE7M0 }, { OpE8X1 }, { OpE9M0 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, + { OpF0E0 }, { OpF1E0M0X1 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, + { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X1 }, + { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM0X1 }, { OpFEM0X1 }, + { OpFFM0 } +}; + +struct SOpcodes S9xOpcodesSlow[256] = +{ + { Op00 }, { Op01Slow }, { Op02 }, { Op03Slow }, { Op04Slow }, + { Op05Slow }, { Op06Slow }, { Op07Slow }, { Op08Slow }, { Op09Slow }, + { Op0ASlow }, { Op0BSlow }, { Op0CSlow }, { Op0DSlow }, { Op0ESlow }, + { Op0FSlow }, { Op10Slow }, { Op11Slow }, { Op12Slow }, { Op13Slow }, + { Op14Slow }, { Op15Slow }, { Op16Slow }, { Op17Slow }, { Op18 }, + { Op19Slow }, { Op1ASlow }, { Op1B }, { Op1CSlow }, { Op1DSlow }, + { Op1ESlow }, { Op1FSlow }, { Op20Slow }, { Op21Slow }, { Op22Slow }, + { Op23Slow }, { Op24Slow }, { Op25Slow }, { Op26Slow }, { Op27Slow }, + { Op28Slow }, { Op29Slow }, { Op2ASlow }, { Op2BSlow }, { Op2CSlow }, + { Op2DSlow }, { Op2ESlow }, { Op2FSlow }, { Op30Slow }, { Op31Slow }, + { Op32Slow }, { Op33Slow }, { Op34Slow }, { Op35Slow }, { Op36Slow }, + { Op37Slow }, { Op38 }, { Op39Slow }, { Op3ASlow }, { Op3B }, + { Op3CSlow }, { Op3DSlow }, { Op3ESlow }, { Op3FSlow }, { Op40Slow }, + { Op41Slow }, { Op42 }, { Op43Slow }, { Op44Slow }, { Op45Slow }, + { Op46Slow }, { Op47Slow }, { Op48Slow }, { Op49Slow }, { Op4ASlow }, + { Op4BSlow }, { Op4CSlow }, { Op4DSlow }, { Op4ESlow }, { Op4FSlow }, + { Op50Slow }, { Op51Slow }, { Op52Slow }, { Op53Slow }, { Op54Slow }, + { Op55Slow }, { Op56Slow }, { Op57Slow }, { Op58 }, { Op59Slow }, + { Op5ASlow }, { Op5B }, { Op5CSlow }, { Op5DSlow }, { Op5ESlow }, + { Op5FSlow }, { Op60Slow }, { Op61Slow }, { Op62Slow }, { Op63Slow }, + { Op64Slow }, { Op65Slow }, { Op66Slow }, { Op67Slow }, { Op68Slow }, + { Op69Slow }, { Op6ASlow }, { Op6BSlow }, { Op6CSlow }, { Op6DSlow }, + { Op6ESlow }, { Op6FSlow }, { Op70Slow }, { Op71Slow }, { Op72Slow }, + { Op73Slow }, { Op74Slow }, { Op75Slow }, { Op76Slow }, { Op77Slow }, + { Op78 }, { Op79Slow }, { Op7ASlow }, { Op7B }, { Op7CSlow }, + { Op7DSlow }, { Op7ESlow }, { Op7FSlow }, { Op80Slow }, { Op81Slow }, + { Op82Slow }, { Op83Slow }, { Op84Slow }, { Op85Slow }, { Op86Slow }, + { Op87Slow }, { Op88Slow }, { Op89Slow }, { Op8ASlow }, { Op8BSlow }, + { Op8CSlow }, { Op8DSlow }, { Op8ESlow }, { Op8FSlow }, { Op90Slow }, + { Op91Slow }, { Op92Slow }, { Op93Slow }, { Op94Slow }, { Op95Slow }, + { Op96Slow }, { Op97Slow }, { Op98Slow }, { Op99Slow }, { Op9A }, + { Op9BSlow }, { Op9CSlow }, { Op9DSlow }, { Op9ESlow }, { Op9FSlow }, + { OpA0Slow }, { OpA1Slow }, { OpA2Slow }, { OpA3Slow }, { OpA4Slow }, + { OpA5Slow }, { OpA6Slow }, { OpA7Slow }, { OpA8Slow }, { OpA9Slow }, + { OpAASlow }, { OpABSlow }, { OpACSlow }, { OpADSlow }, { OpAESlow }, + { OpAFSlow }, { OpB0Slow }, { OpB1Slow }, { OpB2Slow }, { OpB3Slow }, + { OpB4Slow }, { OpB5Slow }, { OpB6Slow }, { OpB7Slow }, { OpB8 }, + { OpB9Slow }, { OpBASlow }, { OpBBSlow }, { OpBCSlow }, { OpBDSlow }, + { OpBESlow }, { OpBFSlow }, { OpC0Slow }, { OpC1Slow }, { OpC2Slow }, + { OpC3Slow }, { OpC4Slow }, { OpC5Slow }, { OpC6Slow }, { OpC7Slow }, + { OpC8Slow }, { OpC9Slow }, { OpCASlow }, { OpCB }, { OpCCSlow }, + { OpCDSlow }, { OpCESlow }, { OpCFSlow }, { OpD0Slow }, { OpD1Slow }, + { OpD2Slow }, { OpD3Slow }, { OpD4Slow }, { OpD5Slow }, { OpD6Slow }, + { OpD7Slow }, { OpD8 }, { OpD9Slow }, { OpDASlow }, { OpDB }, + { OpDCSlow }, { OpDDSlow }, { OpDESlow }, { OpDFSlow }, { OpE0Slow }, + { OpE1Slow }, { OpE2Slow }, { OpE3Slow }, { OpE4Slow }, { OpE5Slow }, + { OpE6Slow }, { OpE7Slow }, { OpE8Slow }, { OpE9Slow }, { OpEA }, + { OpEB }, { OpECSlow }, { OpEDSlow }, { OpEESlow }, { OpEFSlow }, + { OpF0Slow }, { OpF1Slow }, { OpF2Slow }, { OpF3Slow }, { OpF4Slow }, + { OpF5Slow }, { OpF6Slow }, { OpF7Slow }, { OpF8 }, { OpF9Slow }, + { OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow }, + { OpFFSlow } +}; diff --git a/source/snes9x/cpuops.h b/source/snes9x/cpuops.h index acb3406..d9bfcc1 100644 --- a/source/snes9x/cpuops.h +++ b/source/snes9x/cpuops.h @@ -181,8 +181,9 @@ void S9xOpcode_NMI (void); void S9xOpcode_IRQ (void); -#define CHECK_FOR_IRQ() \ -if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \ - S9xOpcode_IRQ() - +#ifndef SA1_OPCODES +#define CHECK_FOR_IRQ() {} // if (CPU.IRQLine) S9xOpcode_IRQ(); } +#else +#define CHECK_FOR_IRQ() {} +#endif #endif diff --git a/source/snes9x/dma.cpp b/source/snes9x/dma.cpp index bd2c6f2..bf17109 100644 --- a/source/snes9x/dma.cpp +++ b/source/snes9x/dma.cpp @@ -185,7 +185,7 @@ #include "missing.h" #endif -#define ADD_CYCLES(n) CPU.Cycles += (n) +#define ADD_CYCLES(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); } extern uint8 *HDMAMemPointers[8]; extern int HDMA_ModeByteCounts[8]; @@ -741,9 +741,6 @@ bool8 S9xDoDMA (uint8 Channel) break; case 0x18: // VMDATAL - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif if (!PPU.VMA.FullGraphicCount) { do @@ -766,9 +763,6 @@ bool8 S9xDoDMA (uint8 Channel) break; case 0x19: // VMDATAH - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif if (!PPU.VMA.FullGraphicCount) { do @@ -837,9 +831,6 @@ bool8 S9xDoDMA (uint8 Channel) if (d->BAddress == 0x18) { // VMDATAL - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif if (!PPU.VMA.FullGraphicCount) { switch (b) @@ -1282,7 +1273,7 @@ bool8 S9xDoDMA (uint8 Channel) } } - if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff)) + if (CPU.NMILine && (Timings.NMITriggerPos != 0xffff)) { Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; if (Timings.NMITriggerPos >= Timings.H_Max) @@ -1373,10 +1364,7 @@ static inline bool8 HDMAReadLineCount (int d) void S9xStartHDMA (void) { - if (Settings.DisableHDMA) - PPU.HDMA = 0; - else - PPU.HDMA = Memory.FillRAM[0x420c]; + PPU.HDMA = Memory.FillRAM[0x420c]; #ifdef DEBUGGER missing.hdma_this_frame = PPU.HDMA; diff --git a/source/snes9x/fxemu.cpp b/source/snes9x/fxemu.cpp index b3237ae..ce1af63 100644 --- a/source/snes9x/fxemu.cpp +++ b/source/snes9x/fxemu.cpp @@ -202,6 +202,7 @@ void S9xResetSuperFX (void) SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max)))); SuperFX.oneLineDone = FALSE; SuperFX.vFlags = 0; + CPU.IRQExternal = FALSE; FxReset(&SuperFX); } @@ -299,13 +300,10 @@ uint8 S9xGetSuperFX (uint16 address) uint8 byte; byte = Memory.FillRAM[address]; -#ifdef CPU_SHUTDOWN - if (address == 0x3030) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; -#endif + if (address == 0x3031) { - S9xClearIRQ(GSU_IRQ_SOURCE); + CPU.IRQExternal = FALSE; Memory.FillRAM[0x3031] = byte & 0x7f; } @@ -320,7 +318,7 @@ void S9xSuperFXExec (void) uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8); if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) - S9xSetIRQ(GSU_IRQ_SOURCE); + CPU.IRQExternal = TRUE; } } diff --git a/source/snes9x/fxemu.h b/source/snes9x/fxemu.h index 45df36e..b2ce64e 100644 --- a/source/snes9x/fxemu.h +++ b/source/snes9x/fxemu.h @@ -178,7 +178,8 @@ #ifndef _FXEMU_H_ #define _FXEMU_H_ -#ifndef ZSNES_FX +#define FX_BREAKPOINT (-1) +#define FX_ERROR_ILLEGAL_ADDRESS (-2) // The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator struct FxInfo_s @@ -196,41 +197,12 @@ struct FxInfo_s extern struct FxInfo_s SuperFX; void S9xInitSuperFX (void); +void S9xResetSuperFX (void); +void S9xSuperFXExec (void); void S9xSetSuperFX (uint8, uint16); uint8 S9xGetSuperFX (uint16); void fx_flushCache (void); void fx_computeScreenPointers (void); uint32 fx_run (uint32); -#define FX_BREAKPOINT (-1) -#define FX_ERROR_ILLEGAL_ADDRESS (-2) - -#else - -#define S9xSetSuperFX S9xSuperFXWriteReg -#define S9xGetSuperFX S9xSuperFXReadReg - -START_EXTERN_C -extern uint8 *SFXPlotTable; - -void S9xSuperFXWriteReg (uint8, uint32); -uint8 S9xSuperFXReadReg (uint32); -void S9xSuperFXPreSaveState (void); -void S9xSuperFXPostSaveState (void); -void S9xSuperFXPostLoadState (void); -END_EXTERN_C - -#endif - -#ifdef ZSNES_FX -START_EXTERN_C -#endif - -void S9xResetSuperFX (void); -void S9xSuperFXExec (void); - -#ifdef ZSNES_FX -END_EXTERN_C -#endif - #endif diff --git a/source/snes9x/fxinst.h b/source/snes9x/fxinst.h index 8f44ae9..dd3736e 100644 --- a/source/snes9x/fxinst.h +++ b/source/snes9x/fxinst.h @@ -178,8 +178,6 @@ #ifndef _FXINST_H_ #define _FXINST_H_ -#ifndef ZSNES_FX - /* * FxChip(GSU) register space specification * (Register address space 3000-32ff) @@ -542,5 +540,3 @@ extern void (*fx_OpcodeTable[]) (void); #define BRANCH_DELAY_RELATIVE #endif - -#endif diff --git a/source/snes9x/getset.h b/source/snes9x/getset.h index bf5557b..b7dda2b 100644 --- a/source/snes9x/getset.h +++ b/source/snes9x/getset.h @@ -187,12 +187,12 @@ #include "seta.h" #include "bsx.h" -#if (S9X_ACCURACY_LEVEL >= 2) - #define addCyclesInMemoryAccess \ if (!CPU.InDMAorHDMA) \ { \ + CPU.PrevCycles = CPU.Cycles; \ CPU.Cycles += speed; \ + S9xCheckInterrupts(); \ while (CPU.Cycles >= CPU.NextEvent) \ S9xDoHEventProcessing(); \ } @@ -200,23 +200,13 @@ #define addCyclesInMemoryAccess_x2 \ if (!CPU.InDMAorHDMA) \ { \ + CPU.PrevCycles = CPU.Cycles; \ CPU.Cycles += speed << 1; \ + S9xCheckInterrupts(); \ while (CPU.Cycles >= CPU.NextEvent) \ S9xDoHEventProcessing(); \ } -#else - -#define addCyclesInMemoryAccess \ - if (!CPU.InDMAorHDMA) \ - CPU.Cycles += speed; - -#define addCyclesInMemoryAccess_x2 \ - if (!CPU.InDMAorHDMA) \ - CPU.Cycles += speed << 1; - -#endif - extern uint8 OpenBus; static inline int32 memory_speed (uint32 address) @@ -247,10 +237,6 @@ inline uint8 S9xGetByte (uint32 Address) if (GetAddress >= (uint8 *) CMemory::MAP_LAST) { - #ifdef CPU_SHUTDOWN - if (Memory.BlockIsRAM[block]) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif byte = *(GetAddress + (Address & 0xffff)); addCyclesInMemoryAccess; return (byte); @@ -379,10 +365,6 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) if (GetAddress >= (uint8 *) CMemory::MAP_LAST) { - #ifdef CPU_SHUTDOWN - if (Memory.BlockIsRAM[block]) - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif word = READ_WORD(GetAddress + (Address & 0xffff)); addCyclesInMemoryAccess_x2; return (word); @@ -510,33 +492,14 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) inline void S9xSetByte (uint8 Byte, uint32 Address) { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - int block = (Address & 0xffffff) >> MEMMAP_SHIFT; uint8 *SetAddress = Memory.WriteMap[block]; int32 speed = memory_speed(Address); if (SetAddress >= (uint8 *) CMemory::MAP_LAST) { - #ifdef CPU_SHUTDOWN - SetAddress += (Address & 0xffff); - *SetAddress = Byte; - addCyclesInMemoryAccess; - - if (Settings.SA1) - { - if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) - { - SA1.Executing = SA1.S9xOpcodes != NULL; - SA1.WaitCounter = 0; - } - } - #else *(SetAddress + (Address & 0xffff)) = Byte; addCyclesInMemoryAccess; - #endif return; } @@ -593,7 +556,6 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) case CMemory::MAP_SA1RAM: *(Memory.SRAM + (Address & 0xffff)) = Byte; - SA1.Executing = !SA1.Waiting; addCyclesInMemoryAccess; return; @@ -670,33 +632,14 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON return; } -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = 0xffffffff; -#endif - int block = (Address & 0xffffff) >> MEMMAP_SHIFT; uint8 *SetAddress = Memory.WriteMap[block]; int32 speed = memory_speed(Address); if (SetAddress >= (uint8 *) CMemory::MAP_LAST) { - #ifdef CPU_SHUTDOWN - SetAddress += (Address & 0xffff); - WRITE_WORD(SetAddress, Word); - addCyclesInMemoryAccess_x2; - - if (Settings.SA1) - { - if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) - { - SA1.Executing = SA1.S9xOpcodes != NULL; - SA1.WaitCounter = 0; - } - } - #else WRITE_WORD(SetAddress + (Address & 0xffff), Word); addCyclesInMemoryAccess_x2; - #endif return; } @@ -806,7 +749,6 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON case CMemory::MAP_SA1RAM: WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); - SA1.Executing = !SA1.Waiting; addCyclesInMemoryAccess_x2; return; diff --git a/source/snes9x/globals.cpp b/source/snes9x/globals.cpp index 2fc439a..60d7959 100644 --- a/source/snes9x/globals.cpp +++ b/source/snes9x/globals.cpp @@ -209,6 +209,8 @@ struct SDSP3 DSP3; struct SDSP4 DSP4; struct SSA1 SA1; struct SSA1Registers SA1Registers; +struct FxRegs_s GSU; +struct FxInfo_s SuperFX; struct SST010 ST010; struct SST011 ST011; struct SST018 ST018; @@ -228,10 +230,6 @@ struct Missing missing; #endif struct SCheatData Cheat; struct Watch watches[16]; -#ifndef ZSNES_FX -struct FxRegs_s GSU; -struct FxInfo_s SuperFX; -#endif CMemory Memory; char String[513]; @@ -244,15 +242,6 @@ SnesModel M1SNES = { 1, 3, 2 }; SnesModel M2SNES = { 2, 4, 3 }; SnesModel *Model = &M1SNES; -#if defined(ZSNES_FX) || defined(ZSNES_C4) -uint8 *ROM = NULL; -uint8 *SRAM = NULL; -uint8 *RegRAM = NULL; -#endif -#ifdef ZSNES_FX -uint8 *SFXPlotTable = NULL; -#endif - #ifdef GFX_MULTI_FORMAT uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565; uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565; diff --git a/source/snes9x/memmap.cpp b/source/snes9x/memmap.cpp index 2a72f8c..5f2506e 100644 --- a/source/snes9x/memmap.cpp +++ b/source/snes9x/memmap.cpp @@ -1144,21 +1144,11 @@ bool8 CMemory::Init (void) BIOSROM = ROM + 0x300000; // BS BSRAM = ROM + 0x400000; // BS -#if defined(ZSNES_FX) || defined(ZSNES_C4) - ::ROM = ROM; - ::SRAM = SRAM; - ::RegRAM = FillRAM; -#endif - -#ifdef ZSNES_FX - SFXPlotTable = ROM + 0x400000; -#else SuperFX.pvRegisters = FillRAM + 0x3000; SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB=512Mb, 2=128KB=1024Mb SuperFX.pvRam = SRAM; SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); SuperFX.pvRom = (uint8 *) ROM; -#endif PostRomInitFunc = NULL; @@ -2280,10 +2270,8 @@ void CMemory::InitROM (void) Settings.SETA = 0; Settings.SRTC = FALSE; Settings.BS = FALSE; -#ifndef ZSNES_FX + SuperFX.nRomBanks = CalculatedSize >> 15; -#endif - SA1.Executing = FALSE; //// Parse ROM header and read ROM informatoin @@ -2409,9 +2397,7 @@ void CMemory::InitROM (void) case 0x1520: case 0x1A20: Settings.SuperFX = TRUE; - #ifndef ZSNES_FX S9xInitSuperFX(); - #endif if (ROM[0x7FDA] == 0x33) SRAMSize = ROM[0x7FBD]; else @@ -3510,7 +3496,6 @@ bool8 CMemory::match_id (const char *str) void CMemory::ApplyROMFixes (void) { - Settings.Shutdown = Settings.ShutdownMaster; Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster; //// Warnings @@ -3587,6 +3572,7 @@ void CMemory::ApplyROMFixes (void) Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; + Timings.IRQTriggerCycles = 10; if (!Settings.DisableGameSpecificHacks) { @@ -3601,14 +3587,6 @@ void CMemory::ApplyROMFixes (void) if (!Settings.DisableGameSpecificHacks) { - // Opcode-based emulators cannot escape from "reading $4211/BPL" infinite loop... - // The true IRQ can be triggered inside an opcode. - if (match_na("TRAVERSE")) // Traverse - Starlight & Prairie - { - Timings.IRQPendCount = 1; - printf("IRQ count hack: %d\n", Timings.IRQPendCount); - } - // An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0. // If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further. // If Snes9x jumps into the IRQ handler before escaping from the loop, @@ -3618,12 +3596,6 @@ void CMemory::ApplyROMFixes (void) Timings.IRQPendCount = 2; printf("IRQ count hack: %d\n", Timings.IRQPendCount); } - - if (match_na("BATTLE BLAZE")) - { - Timings.IRQPendCount = 1; - printf("IRQ count hack: %d\n", Timings.IRQPendCount); - } } if (!Settings.DisableGameSpecificHacks) @@ -3636,242 +3608,6 @@ void CMemory::ApplyROMFixes (void) } } - //// CPU speed-ups (CPU_Shutdown()) - - // Force disabling a speed-up hack - // Games which spool sound samples between the SNES and sound CPU using - // H-DMA as the sample is playing. - if (match_na("EARTHWORM JIM 2") || // Earth Worm Jim 2 - match_na("PRIMAL RAGE") || // Primal Rage - match_na("CLAY FIGHTER") || // Clay Fighter - match_na("ClayFighter 2") || // Clay Fighter 2 - match_na("WeaponLord") || // Weapon Lord - match_nn("WAR 2410") || // War 2410 - match_id("ARF") || // Star Ocean - match_id("A4WJ") || // Mini Yonku Shining Scorpion - Let's & Go!! - match_nn("NHL") || - match_nc("MADDEN")) - { - if (Settings.Shutdown) - printf("Disabled CPU shutdown hack.\n"); - Settings.Shutdown = FALSE; - } - - // SA-1 - SA1.WaitAddress = 0xffffffff; - SA1.WaitByteAddress1 = NULL; - SA1.WaitByteAddress2 = NULL; - - if (Settings.SA1) - { - // Itoi Shigesato no Bass Tsuri No.1 (J) - if (match_id("ZBPJ")) - { - SA1.WaitAddress = 0x0093f1; - SA1.WaitByteAddress1 = FillRAM + 0x304a; - } - - // Daisenryaku Expert WWII (J) - if (match_id("AEVJ")) - { - SA1.WaitAddress = 0x0ed18d; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - - // Derby Jockey 2 (J) - if (match_id("A2DJ")) - { - SA1.WaitAddress = 0x008b62; - } - - // Dragon Ball Z - Hyper Dimension (J) - if (match_id("AZIJ")) - { - SA1.WaitAddress = 0x008083; - SA1.WaitByteAddress1 = FillRAM + 0x3020; - } - - // SD Gundam G NEXT (J) - if (match_id("ZX3J")) - { - SA1.WaitAddress = 0x0087f2; - SA1.WaitByteAddress1 = FillRAM + 0x30c4; - } - - // Shougi no Hanamichi (J) - if (match_id("AARJ")) - { - SA1.WaitAddress = 0xc1f85a; - SA1.WaitByteAddress1 = SRAM + 0x0c64; - SA1.WaitByteAddress2 = SRAM + 0x0c66; - } - - // Asahi Shinbun Rensai Katou Hifumi Kudan Shougi Shingiryu (J) - if (match_id("A23J")) - { - SA1.WaitAddress = 0xc25037; - SA1.WaitByteAddress1 = SRAM + 0x0c06; - SA1.WaitByteAddress2 = SRAM + 0x0c08; - } - - // Taikyoku Igo - Idaten (J) - if (match_id("AIIJ")) - { - SA1.WaitAddress = 0xc100be; - SA1.WaitByteAddress1 = SRAM + 0x1002; - SA1.WaitByteAddress2 = SRAM + 0x1004; - } - - // Takemiya Masaki Kudan no Igo Taishou (J) - if (match_id("AITJ")) - { - SA1.WaitAddress = 0x0080b7; - } - - // J. League '96 Dream Stadium (J) - if (match_id("AJ6J")) - { - SA1.WaitAddress = 0xc0f74a; - } - - // Jumpin' Derby (J) - if (match_id("AJUJ")) - { - SA1.WaitAddress = 0x00d926; - } - - // Kakinoki Shougi (J) - if (match_id("AKAJ")) - { - SA1.WaitAddress = 0x00f070; - } - - // Hoshi no Kirby 3 (J), Kirby's Dream Land 3 (U) - if (match_id("AFJJ") || match_id("AFJE")) - { - SA1.WaitAddress = 0x0082d4; - SA1.WaitByteAddress1 = SRAM + 0x72a4; - } - - // Hoshi no Kirby - Super Deluxe (J) - if (match_id("AKFJ")) - { - SA1.WaitAddress = 0x008c93; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - - // Kirby Super Star (U) - if (match_id("AKFE")) - { - SA1.WaitAddress = 0x008cb8; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - - // Super Mario RPG (J), (U) - if (match_id("ARWJ") || match_id("ARWE")) - { - SA1.WaitAddress = 0xc0816f; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - - // Marvelous (J) - if (match_id("AVRJ")) - { - SA1.WaitAddress = 0x0085f2; - SA1.WaitByteAddress1 = FillRAM + 0x3024; - } - - // Harukanaru Augusta 3 - Masters New (J) - if (match_id("AO3J")) - { - SA1.WaitAddress = 0x00dddb; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - - // Jikkyou Oshaberi Parodius (J) - if (match_id("AJOJ")) - { - SA1.WaitAddress = 0x8084e5; - } - - // Super Bomberman - Panic Bomber W (J) - if (match_id("APBJ")) - { - SA1.WaitAddress = 0x00857a; - } - - // Pebble Beach no Hatou New - Tournament Edition (J) - if (match_id("AONJ")) - { - SA1.WaitAddress = 0x00df33; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - - // PGA European Tour (U) - if (match_id("AEPE")) - { - SA1.WaitAddress = 0x003700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - - // PGA Tour 96 (U) - if (match_id("A3GE")) - { - SA1.WaitAddress = 0x003700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - - // Power Rangers Zeo - Battle Racers (U) - if (match_id("A4RE")) - { - SA1.WaitAddress = 0x009899; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - - // SD F-1 Grand Prix (J) - if (match_id("AGFJ")) - { - SA1.WaitAddress = 0x0181bc; - } - - // Saikousoku Shikou Shougi Mahjong (J) - if (match_id("ASYJ")) - { - SA1.WaitAddress = 0x00f2cc; - SA1.WaitByteAddress1 = SRAM + 0x7ffe; - SA1.WaitByteAddress2 = SRAM + 0x7ffc; - } - - // Shougi Saikyou II (J) - if (match_id("AX2J")) - { - SA1.WaitAddress = 0x00d675; - } - - // Mini Yonku Shining Scorpion - Let's & Go!! (J) - if (match_id("A4WJ")) - { - SA1.WaitAddress = 0xc048be; - } - - // Shin Shougi Club (J) - if (match_id("AHJJ")) - { - SA1.WaitAddress = 0xc1002a; - SA1.WaitByteAddress1 = SRAM + 0x0806; - SA1.WaitByteAddress2 = SRAM + 0x0808; - } - - // rest games: - // Habu Meijin no Omoshiro Shougi (J) - // Hayashi Kaihou Kudan no Igo Taidou (J) - // Shougi Saikyou (J) - // Super Robot Wars Gaiden (J) - // Super Shougi 3 - Kitaihei (J) - } - //// SRAM initial value if (!Settings.DisableGameSpecificHacks) diff --git a/source/snes9x/memmap.h b/source/snes9x/memmap.h index ac02b82..153ae17 100644 --- a/source/snes9x/memmap.h +++ b/source/snes9x/memmap.h @@ -360,14 +360,6 @@ struct SMulti extern CMemory Memory; extern SMulti Multi; -#if defined(ZSNES_FX) || defined(ZSNES_C4) -START_EXTERN_C -extern uint8 *ROM; -extern uint8 *SRAM; -extern uint8 *RegRAM; -END_EXTERN_C -#endif - void S9xAutoSaveSRAM (void); bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); diff --git a/source/snes9x/movie.cpp b/source/snes9x/movie.cpp index f8044dd..f4b018b 100644 --- a/source/snes9x/movie.cpp +++ b/source/snes9x/movie.cpp @@ -745,7 +745,8 @@ int S9xMovieUnfreeze (uint8 *buf, uint32 size) } else { - if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) + uint32 space_processed = (Movie.BytesPerSample * (current_sample + 1)); + if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_processed)) return (SNAPSHOT_INCONSISTENT); change_state(MOVIE_STATE_PLAY); @@ -786,8 +787,8 @@ int S9xMovieOpen (const char *filename, bool8 read_only) read_movie_extrarominfo(fd, &Movie); - fn = dup(fileno(fd)); - fclose(fd); + fflush(fd); + fn = fileno(fd); store_previous_settings(); restore_movie_settings(); @@ -853,7 +854,6 @@ int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, co { FILE *fd; STREAM stream; - int fn; if (controllers_mask == 0) return (WRONG_FORMAT); @@ -902,10 +902,9 @@ int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, co write_movie_extrarominfo(fd, &Movie); - fn = dup(fileno(fd)); fclose(fd); - stream = REOPEN_STREAM(fn, "ab"); + stream = OPEN_STREAM(filename, "ab"); if (!stream) return (FILE_NOT_FOUND); @@ -1009,9 +1008,10 @@ int S9xMovieGetInfo (const char *filename, struct MovieInfo *info) strncpy(info->ROMName, local_movie.ROMName, 23); fclose(fd); - - if (access(filename, W_OK)) + if ((fd = fopen(filename, "r+")) == NULL) info->ReadOnly = true; + else + fclose(fd); return (SUCCESS); } diff --git a/source/snes9x/ppu.cpp b/source/snes9x/ppu.cpp index e1d5c39..a9dc271 100644 --- a/source/snes9x/ppu.cpp +++ b/source/snes9x/ppu.cpp @@ -204,9 +204,6 @@ static inline void S9xLatchCounters (bool force) #ifdef DEBUGGER missing.h_v_latch = 1; #endif - #if 0 // #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; - #endif PPU.HVBeamCounterLatched = 1; PPU.VBeamPosLatched = (uint16) CPU.V_Counter; @@ -245,9 +242,6 @@ static inline void S9xTryGunLatch (bool force) #ifdef DEBUGGER missing.h_v_latch = 1; #endif - #if 0 // #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; - #endif PPU.HVBeamCounterLatched = 1; PPU.VBeamPosLatched = (uint16) PPU.GunVLatch; @@ -260,72 +254,16 @@ static inline void S9xTryGunLatch (bool force) } } -void S9xCheckMissingHTimerPosition (int32 hc) -{ - if (PPU.HTimerPosition == hc) - { - if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_IRQ_SOURCE); - else - if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_IRQ_SOURCE); - } -} - -void S9xCheckMissingHTimerHalt (int32 hc_from, int32 range) -{ - if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) - { - if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - CPU.IRQPending = 1; - else - if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - CPU.IRQPending = 1; - } -} - -void S9xCheckMissingHTimerRange (int32 hc_from, int32 range) -{ - if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) - { - if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) - S9xSetIRQ(PPU_IRQ_SOURCE); - else - if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) - S9xSetIRQ(PPU_IRQ_SOURCE); - } -} - void S9xUpdateHVTimerPosition (void) { - if (PPU.HTimerEnabled) + PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles; + if (Timings.H_Max == Timings.H_Max_Master) // 1364 { - #ifdef DEBUGGER - missing.hirq_pos = PPU.IRQHBeamPos; - #endif - if (PPU.IRQHBeamPos != 0) - { - // IRQ_read - PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE; - if (Timings.H_Max == Timings.H_Max_Master) // 1364 - { - if (PPU.IRQHBeamPos > 322) - PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); - if (PPU.IRQHBeamPos > 326) - PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); - } - - PPU.HTimerPosition += 14; - // /IRQ - PPU.HTimerPosition += 4; - // after CPU executing - PPU.HTimerPosition += 6; - } - else - PPU.HTimerPosition = 10 + 4 + 6; + if (PPU.IRQHBeamPos > 322) + PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); + if (PPU.IRQHBeamPos > 326) + PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); } - else - PPU.HTimerPosition = 10 + 4 + 6; PPU.VTimerPosition = PPU.IRQVBeamPos; @@ -338,111 +276,9 @@ void S9xUpdateHVTimerPosition (void) PPU.VTimerPosition = 0; } - if (PPU.HTimerPosition < CPU.Cycles) - { - switch (CPU.WhichEvent) - { - case HC_IRQ_1_3_EVENT: - CPU.WhichEvent = HC_HDMA_START_EVENT; - CPU.NextEvent = Timings.HDMAStart; - break; - - case HC_IRQ_3_5_EVENT: - CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; - CPU.NextEvent = Timings.H_Max; - break; - - case HC_IRQ_5_7_EVENT: - CPU.WhichEvent = HC_HDMA_INIT_EVENT; - CPU.NextEvent = Timings.HDMAInit; - break; - - case HC_IRQ_7_9_EVENT: - CPU.WhichEvent = HC_RENDER_EVENT; - CPU.NextEvent = Timings.RenderPos; - break; - - case HC_IRQ_9_A_EVENT: - CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; - CPU.NextEvent = Timings.WRAMRefreshPos; - break; - - case HC_IRQ_A_1_EVENT: - CPU.WhichEvent = HC_HBLANK_START_EVENT; - CPU.NextEvent = Timings.HBlankStart; - break; - } - } - else - if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent))) - { - CPU.NextEvent = PPU.HTimerPosition; - - switch (CPU.WhichEvent) - { - case HC_HDMA_START_EVENT: - CPU.WhichEvent = HC_IRQ_1_3_EVENT; - break; - - case HC_HCOUNTER_MAX_EVENT: - CPU.WhichEvent = HC_IRQ_3_5_EVENT; - break; - - case HC_HDMA_INIT_EVENT: - CPU.WhichEvent = HC_IRQ_5_7_EVENT; - break; - - case HC_RENDER_EVENT: - CPU.WhichEvent = HC_IRQ_7_9_EVENT; - break; - - case HC_WRAM_REFRESH_EVENT: - CPU.WhichEvent = HC_IRQ_9_A_EVENT; - break; - - case HC_HBLANK_START_EVENT: - CPU.WhichEvent = HC_IRQ_A_1_EVENT; - break; - } - } - else - { - switch (CPU.WhichEvent) - { - case HC_IRQ_1_3_EVENT: - CPU.WhichEvent = HC_HDMA_START_EVENT; - CPU.NextEvent = Timings.HDMAStart; - break; - - case HC_IRQ_3_5_EVENT: - CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; - CPU.NextEvent = Timings.H_Max; - break; - - case HC_IRQ_5_7_EVENT: - CPU.WhichEvent = HC_HDMA_INIT_EVENT; - CPU.NextEvent = Timings.HDMAInit; - break; - - case HC_IRQ_7_9_EVENT: - CPU.WhichEvent = HC_RENDER_EVENT; - CPU.NextEvent = Timings.RenderPos; - break; - - case HC_IRQ_9_A_EVENT: - CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; - CPU.NextEvent = Timings.WRAMRefreshPos; - break; - - case HC_IRQ_A_1_EVENT: - CPU.WhichEvent = HC_HBLANK_START_EVENT; - CPU.NextEvent = Timings.HBlankStart; - break; - } - } - #ifdef DEBUGGER - S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition); + S9xTraceFormattedMessage("--- IRQ Timer set HTimer:%d Pos:%04d VTimer:%d Pos:%03d", + PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition); #endif } @@ -787,7 +623,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address) case 0x2116: // VMADDL PPU.VMA.Address &= 0xff00; PPU.VMA.Address |= Byte; - #ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) { uint32 addr = PPU.VMA.Address; @@ -797,15 +633,13 @@ void S9xSetPPU (uint8 Byte, uint16 Address) } else IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); - #else - IPPU.FirstVRAMRead = TRUE; - #endif + break; case 0x2117: // VMADDH PPU.VMA.Address &= 0x00ff; PPU.VMA.Address |= Byte << 8; - #ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) { uint32 addr = PPU.VMA.Address; @@ -815,22 +649,14 @@ void S9xSetPPU (uint8 Byte, uint16 Address) } else IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); - #else - IPPU.FirstVRAMRead = TRUE; - #endif + break; case 0x2118: // VMDATAL - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif REGISTER_2118(Byte); break; case 0x2119: // VMDATAH - #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; - #endif REGISTER_2119(Byte); break; @@ -1382,7 +1208,6 @@ uint8 S9xGetPPU (uint16 Address) return (PPU.OpenBus1 = byte); case 0x2139: // VMDATALREAD - #ifdef CORRECT_VRAM_READS byte = IPPU.VRAMReadBuffer & 0xff; if (!PPU.VMA.High) { @@ -1398,33 +1223,13 @@ uint8 S9xGetPPU (uint16 Address) PPU.VMA.Address += PPU.VMA.Increment; } - #else - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM[((address << 1) - 2) & 0xffff]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; - if (!PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } - #endif #ifdef DEBUGGER missing.vram_read = 1; #endif return (PPU.OpenBus1 = byte); case 0x213a: // VMDATAHREAD - #ifdef CORRECT_VRAM_READS byte = (IPPU.VRAMReadBuffer >> 8) & 0xff; if (PPU.VMA.High) { @@ -1440,26 +1245,6 @@ uint8 S9xGetPPU (uint16 Address) PPU.VMA.Address += PPU.VMA.Increment; } - #else - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM[((address << 1) - 1) & 0xffff]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xffff]; - - if (PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } - #endif #ifdef DEBUGGER missing.vram_read = 1; #endif @@ -1697,14 +1482,14 @@ void S9xSetCPU (uint8 Byte, uint16 Address) else PPU.HTimerEnabled = FALSE; - S9xUpdateHVTimerPosition(); + if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled) + CPU.IRQTransition = TRUE; - // The case that IRQ will trigger in an instruction such as STA $4200. - // FIXME: not true but good enough for Snes9x, I think. - S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles); - - if (!(Byte & 0x30)) - S9xClearIRQ(PPU_IRQ_SOURCE); + if (!PPU.HTimerEnabled && !PPU.VTimerEnabled) + { + CPU.IRQLine = FALSE; + CPU.IRQTransition = FALSE; + } // NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard. if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && @@ -1712,7 +1497,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address) { // FIXME: triggered at HC+=6, checked just before the final CPU cycle, // then, when to call S9xOpcode_NMI()? - CPU.Flags |= NMI_FLAG; + CPU.NMILine = TRUE; Timings.NMITriggerPos = CPU.Cycles + 6 + 6; } @@ -1826,8 +1611,6 @@ void S9xSetCPU (uint8 Byte, uint16 Address) case 0x420c: // HDMAEN if (CPU.InDMAorHDMA) return; - if (Settings.DisableHDMA) - Byte = 0; Memory.FillRAM[0x420c] = Byte; // Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia PPU.HDMA = Byte & ~PPU.HDMAEnded; @@ -1854,17 +1637,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address) break; case 0x4210: // RDNMI - #if 0 - Memory.FillRAM[0x4210] = Model->_5A22; - #endif - return; - case 0x4211: // TIMEUP - #if 0 - S9xClearIRQ(PPU_IRQ_SOURCE); - #endif - return; - case 0x4212: // HVBJOY case 0x4213: // RDIO case 0x4214: // RDDIVL @@ -1980,22 +1753,17 @@ uint8 S9xGetCPU (uint16 Address) switch (Address) { case 0x4210: // RDNMI - #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif byte = Memory.FillRAM[0x4210]; Memory.FillRAM[0x4210] = Model->_5A22; return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22); case 0x4211: // TIMEUP - byte = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0; - S9xClearIRQ(PPU_IRQ_SOURCE); + byte = CPU.IRQLine ? 0x80 : 0; + CPU.IRQLine = FALSE; + CPU.IRQTransition = FALSE; return (byte | (OpenBus & 0x7f)); case 0x4212: // HVBJOY - #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PBPCAtOpcodeStart; - #endif return (REGISTER_4212() | (OpenBus & 0x3e)); case 0x4213: // RDIO @@ -2189,11 +1957,7 @@ void S9xSoftResetPPU (void) ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); -#ifdef CORRECT_VRAM_READS IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? -#else - IPPU.FirstVRAMRead = FALSE; -#endif IPPU.Interlace = FALSE; IPPU.InterlaceOBJ = FALSE; IPPU.DoubleWidthPixels = FALSE; diff --git a/source/snes9x/ppu.h b/source/snes9x/ppu.h index 7f20e89..c5cb9d7 100644 --- a/source/snes9x/ppu.h +++ b/source/snes9x/ppu.h @@ -197,11 +197,6 @@ #define CLIP_XOR 2 #define CLIP_XNOR 3 -#define PPU_IRQ_SOURCE (1 << 1) -#define GSU_IRQ_SOURCE (1 << 2) -#define SA1_IRQ_SOURCE (1 << 7) -#define SA1_DMA_IRQ_SOURCE (1 << 5) - struct ClipData { uint8 Count; @@ -218,11 +213,7 @@ struct InternalPPU bool8 DirectColourMapsNeedRebuild; uint8 *TileCache[7]; uint8 *TileCached[7]; -#ifdef CORRECT_VRAM_READS uint16 VRAMReadBuffer; -#else - bool8 FirstVRAMRead; -#endif bool8 Interlace; bool8 InterlaceOBJ; bool8 PseudoHires; @@ -385,9 +376,6 @@ uint8 S9xGetPPU (uint16); void S9xSetCPU (uint8, uint16); uint8 S9xGetCPU (uint16); void S9xUpdateHVTimerPosition (void); -void S9xCheckMissingHTimerPosition (int32); -void S9xCheckMissingHTimerRange (int32, int32); -void S9xCheckMissingHTimerHalt (int32, int32); void S9xFixColourBrightness (void); void S9xDoAutoJoypad (void); diff --git a/source/snes9x/sa1.cpp b/source/snes9x/sa1.cpp index c02839c..a35e553 100644 --- a/source/snes9x/sa1.cpp +++ b/source/snes9x/sa1.cpp @@ -1,1136 +1,1096 @@ -/*********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - (c) Copyright 2009 - 2010 BearOso, - OV2 - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com), - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code used in 1.39-1.51 - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - SPC7110 and RTC C++ emulator code used in 1.52+ - (c) Copyright 2009 byuu, - neviksti - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001 - 2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound emulator code used in 1.5-1.51 - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - Sound emulator code used in 1.52+ - (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - NTSC filter - (c) Copyright 2006 - 2007 Shay Green - - GTK+ GUI code - (c) Copyright 2004 - 2010 BearOso - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - (c) Copyright 2009 - 2010 OV2 - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2010 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com/ - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. - ***********************************************************************************/ - - -#include "snes9x.h" -#include "memmap.h" - -uint8 SA1OpenBus; - -static void S9xSA1Reset (void); -static void S9xSA1SetBWRAMMemMap (uint8); -static void S9xSetSA1MemMap (uint32, uint8); -static void S9xSA1CharConv2 (void); -static void S9xSA1DMA (void); -static void S9xSA1ReadVariableLengthData (bool8, bool8); - - -void S9xSA1Init (void) -{ - SA1.IRQActive = FALSE; - SA1.WaitingForInterrupt = FALSE; - SA1.Waiting = FALSE; - SA1.Flags = 0; - SA1.Executing = FALSE; - memset(&Memory.FillRAM[0x2200], 0, 0x200); - Memory.FillRAM[0x2200] = 0x20; - Memory.FillRAM[0x2220] = 0x00; - Memory.FillRAM[0x2221] = 0x01; - Memory.FillRAM[0x2222] = 0x02; - Memory.FillRAM[0x2223] = 0x03; - Memory.FillRAM[0x2228] = 0xff; - SA1.op1 = 0; - SA1.op2 = 0; - SA1.arithmetic_op = 0; - SA1.sum = 0; - SA1.overflow = FALSE; - SA1.S9xOpcodes = NULL; -} - -static void S9xSA1Reset (void) -{ - SA1Registers.PBPC = 0; - SA1Registers.PB = 0; - SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8); - SA1Registers.D.W = 0; - SA1Registers.DB = 0; - SA1Registers.SH = 1; - SA1Registers.SL = 0xFF; - SA1Registers.XH = 0; - SA1Registers.YH = 0; - SA1Registers.P.W = 0; - - SA1.ShiftedPB = 0; - SA1.ShiftedDB = 0; - SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); - SA1ClearFlags(Decimal); - - SA1.WaitingForInterrupt = FALSE; - SA1.PCBase = NULL; - S9xSA1SetPCBase(SA1Registers.PBPC); - SA1.S9xOpcodes = S9xSA1OpcodesM1X1; - SA1.S9xOpLengths = S9xOpLengthsM1X1; - - S9xSA1UnpackStatus(); - S9xSA1FixCycles(); - SA1.Executing = TRUE; - SA1.BWRAM = Memory.SRAM; - Memory.FillRAM[0x2225] = 0; -} - -static void S9xSA1SetBWRAMMemMap (uint8 val) -{ - if (val & 0x80) - { - for (int c = 0; c < 0x400; c += 16) - { - SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - } - - SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; - } - else - { - for (int c = 0; c < 0x400; c += 16) - { - SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; - SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; - SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; - SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; - } - - SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; - } -} - -void S9xSA1PostLoadState (void) -{ - SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; - SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; - - S9xSA1SetPCBase(SA1Registers.PBPC); - S9xSA1UnpackStatus(); - S9xSA1FixCycles(); - SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4; - Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000; - S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]); - - SA1.Waiting = (Memory.FillRAM[0x2200] & 0x60) != 0; - SA1.Executing = !SA1.Waiting; -} - -void S9xSA1ExecuteDuringSleep (void) -{ -#if 0 - if (SA1.Executing) - { - while (CPU.Cycles < CPU.NextEvent) - { - S9xSA1MainLoop(); - CPU.Cycles += TWO_CYCLES * 2; - } - } -#endif -} - -static void S9xSetSA1MemMap (uint32 which1, uint8 map) -{ - int start = which1 * 0x100 + 0xc00; - int start2 = which1 * 0x200; - - if (which1 >= 2) - start2 += 0x400; - - for (int c = 0; c < 0x100; c += 16) - { - uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; - for (int i = c; i < c + 16; i++) - Memory.Map[start + i] = SA1.Map[start + i] = block; - } - - for (int c = 0; c < 0x200; c += 16) - { - uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000]; - for (int i = c + 8; i < c + 16; i++) - Memory.Map[start2 + i] = SA1.Map[start2 + i] = block; - } -} - -uint8 S9xGetSA1 (uint32 address) -{ - switch (address) - { - case 0x2300: - return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); - - case 0x2301: - return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0)); - - case 0x2306: - return ((uint8) SA1.sum); - - case 0x2307: - return ((uint8) (SA1.sum >> 8)); - - case 0x2308: - return ((uint8) (SA1.sum >> 16)); - - case 0x2309: - return ((uint8) (SA1.sum >> 24)); - - case 0x230a: - return ((uint8) (SA1.sum >> 32)); - - case 0x230c: - return (Memory.FillRAM[0x230c]); - - case 0x230d: - { - uint8 byte = Memory.FillRAM[0x230d]; - - if (Memory.FillRAM[0x2258] & 0x80) - S9xSA1ReadVariableLengthData(TRUE, FALSE); - - return (byte); - } - - default: - //printf("R: %04x\n", address); - break; - } - - return (Memory.FillRAM[address]); -} - -void S9xSetSA1 (uint8 byte, uint32 address) -{ - switch (address) - { - case 0x2200: - SA1.Waiting = (byte & 0x60) != 0; - //SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - - if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20)) - S9xSA1Reset(); - - if (byte & 0x80) - { - Memory.FillRAM[0x2301] |= 0x80; - if (Memory.FillRAM[0x220a] & 0x80) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - } - } - - if (byte & 0x10) - { - Memory.FillRAM[0x2301] |= 0x10; - if (Memory.FillRAM[0x220a] & 0x10) - { - SA1.Flags |= NMI_FLAG; - SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - } - } - - break; - - case 0x2201: - if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80)) - S9xSetIRQ(SA1_IRQ_SOURCE); - - if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20)) - S9xSetIRQ(SA1_DMA_IRQ_SOURCE); - - break; - - case 0x2202: - if (byte & 0x80) - { - Memory.FillRAM[0x2300] &= ~0x80; - S9xClearIRQ(SA1_IRQ_SOURCE); - } - - if (byte & 0x20) - { - Memory.FillRAM[0x2300] &= ~0x20; - S9xClearIRQ(SA1_DMA_IRQ_SOURCE); - } - - break; - - case 0x2203: - //printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8)); - break; - - case 0x2204: - //printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]); - break; - - case 0x2205: - //printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8)); - break; - - case 0x2206: - //printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]); - break; - - case 0x2207: - //printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8)); - break; - - case 0x2208: - //printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]); - break; - - case 0x2209: - Memory.FillRAM[0x2209] = byte; - - if (byte & 0x80) - Memory.FillRAM[0x2300] |= 0x80; - - if (byte & Memory.FillRAM[0x2201] & 0x80) - S9xSetIRQ(SA1_IRQ_SOURCE); - - break; - - case 0x220a: - if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= TIMER_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10)) - { - SA1.Flags |= NMI_FLAG; - //SA1.Executing = !SA1.Waiting; - } - - 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) - Memory.FillRAM[0x2301] &= ~0x10; - - if (!SA1.IRQActive) - SA1.Flags &= ~IRQ_FLAG; - - break; - - case 0x220c: - //printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8)); - break; - - case 0x220d: - //printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]); - break; - - case 0x220e: - //printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8)); - break; - - case 0x220f: - //printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]); - break; - - case 0x2210: - #if 0 - printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); - printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); - printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); - #endif - break; - - case 0x2211: - //printf("Timer reset\n"); - break; - - case 0x2212: - //printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8)); - break; - - case 0x2213: - //printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]); - break; - - case 0x2214: - //printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8)); - break; - - case 0x2215: - //printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]); - break; - - case 0x2220: - case 0x2221: - case 0x2222: - case 0x2223: - //printf("MMC: %02x\n", byte); - S9xSetSA1MemMap(address - 0x2220, byte); - break; - - case 0x2224: - //printf("BWRAM image SNES %02x -> 0x6000\n", byte); - Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; - break; - - case 0x2225: - //printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]); - if (byte != Memory.FillRAM[0x2225]) - S9xSA1SetBWRAMMemMap(byte); - break; - - case 0x2226: - //printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2227: - //printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2228: - //printf("BW-RAM write protect area %02x\n", byte); - break; - - case 0x2229: - //printf("I-RAM SNES write protect area %02x\n", byte); - break; - - case 0x222a: - //printf("I-RAM SA1 write protect area %02x\n", byte); - break; - - case 0x2230: - #if 0 - printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); - printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); - printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); - printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); - printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); - printf("DMA source %s\n", DMAsource[byte & 3]); - #endif - break; - - case 0x2231: - if (byte & 0x80) - SA1.in_char_dma = FALSE; - #if 0 - printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); - printf("DMA colour mode %d\n", byte & 3); - printf("virtual VRAM width %d\n", (byte >> 2) & 7); - #endif - break; - - case 0x2232: - case 0x2233: - case 0x2234: - Memory.FillRAM[address] = byte; - #if 0 - printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16)); - #endif - break; - - case 0x2235: - Memory.FillRAM[0x2235] = byte; - break; - - case 0x2236: - Memory.FillRAM[0x2236] = byte; - - if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM - S9xSA1DMA(); - else - if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) - { - Memory.FillRAM[0x2300] |= 0x20; - if (Memory.FillRAM[0x2201] & 0x20) - S9xSetIRQ(SA1_DMA_IRQ_SOURCE); - SA1.in_char_dma = TRUE; - } - - break; - - case 0x2237: - Memory.FillRAM[0x2237] = byte; - - if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM - S9xSA1DMA(); - #if 0 - printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16)); - #endif - break; - - case 0x2238: - case 0x2239: - Memory.FillRAM[address] = byte; - #if 0 - printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8)); - #endif - break; - - case 0x223f: - //printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); - SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; - break; - - case 0x2240: - case 0x2241: - case 0x2242: - case 0x2243: - case 0x2244: - case 0x2245: - case 0x2246: - case 0x2247: - case 0x2248: - case 0x2249: - case 0x224a: - case 0x224b: - case 0x224c: - case 0x224d: - case 0x224e: - #if 0 - if (!(SA1.Flags & TRACE_FLAG)) - { - TraceSA1(); - Trace(); - } - #endif - Memory.FillRAM[address] = byte; - break; - - case 0x224f: - Memory.FillRAM[0x224f] = byte; - - if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled - { - memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16); - SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; - if ((SA1.in_char_dma & 3) == 0) - S9xSA1CharConv2(); - } - - break; - - case 0x2250: - if (byte & 2) - SA1.sum = 0; - SA1.arithmetic_op = byte & 3; - break; - - case 0x2251: - SA1.op1 = (SA1.op1 & 0xff00) | byte; - break; - - case 0x2252: - SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); - break; - - case 0x2253: - SA1.op2 = (SA1.op2 & 0xff00) | byte; - break; - - case 0x2254: - SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); - - switch (SA1.arithmetic_op) - { - case 0: // multiply - SA1.sum = SA1.op1 * SA1.op2; - break; - - case 1: // divide - if (SA1.op2 == 0) - SA1.sum = SA1.op1 << 16; - else - SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); - break; - - case 2: // cumulative sum - default: - SA1.sum += SA1.op1 * SA1.op2; - if (SA1.sum & ((int64) 0xffffff << 32)) - SA1.overflow = TRUE; - break; - } - - break; - - case 0x2258: // Variable bit-field length/auto inc/start. - Memory.FillRAM[0x2258] = byte; - S9xSA1ReadVariableLengthData(TRUE, FALSE); - return; - - case 0x2259: // Variable bit-field start address - case 0x225a: - case 0x225b: - Memory.FillRAM[address] = byte; - // XXX: ??? - SA1.variable_bit_pos = 0; - S9xSA1ReadVariableLengthData(FALSE, TRUE); - return; - - default: - //printf("W: %02x->%04x\n", byte, address); - break; - } - - if (address >= 0x2200 && address <= 0x22ff) - Memory.FillRAM[address] = byte; -} - -static void S9xSA1CharConv2 (void) -{ - uint32 dest = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8); - uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; - int depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; - int bytes_per_char = 8 * depth; - uint8 *p = &Memory.FillRAM[0x3000] + (dest & 0x7ff) + offset * bytes_per_char; - uint8 *q = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; - - switch (depth) - { - case 2: - 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 += 2; - } - - break; - - case 4: - 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 += 2; - } - - break; - - case 8: - for (int l = 0; l < 8; l++, q += 8) - { - for (int b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - - p += 2; - } - - break; - } -} - -static void S9xSA1DMA (void) -{ - uint32 src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16); - uint32 dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16); - uint32 len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8); - uint8 *s, *d; - - switch (Memory.FillRAM[0x2230] & 3) - { - case 0: // ROM - s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)]; - if (s >= (uint8 *) CMemory::MAP_LAST) - s += (src & 0xffff); - else - s = Memory.ROM + (src & 0xffff); - break; - - case 1: // BW-RAM - src &= Memory.SRAMMask; - len &= Memory.SRAMMask; - s = Memory.SRAM + src; - break; - - default: - case 2: - src &= 0x3ff; - len &= 0x3ff; - s = &Memory.FillRAM[0x3000] + src; - break; - } - - if (Memory.FillRAM[0x2230] & 4) - { - dst &= Memory.SRAMMask; - len &= Memory.SRAMMask; - d = Memory.SRAM + dst; - } - else - { - dst &= 0x3ff; - len &= 0x3ff; - d = &Memory.FillRAM[0x3000] + dst; - } - - memmove(d, s, len); - Memory.FillRAM[0x2301] |= 0x20; - - if (Memory.FillRAM[0x220a] & 0x20) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } -} - -static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) -{ - uint32 addr = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16); - uint8 shift = Memory.FillRAM[0x2258] & 15; - - if (no_shift) - shift = 0; - else - if (shift == 0) - shift = 16; - - uint8 s = shift + SA1.variable_bit_pos; - - if (s >= 16) - { - addr += (s >> 4) << 1; - s &= 15; - } - - uint32 data = S9xSA1GetWord(addr) | (S9xSA1GetWord(addr + 2) << 16); - - data >>= s; - Memory.FillRAM[0x230c] = (uint8) data; - Memory.FillRAM[0x230d] = (uint8) (data >> 8); - - if (inc) - { - SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; - Memory.FillRAM[0x2259] = (uint8) addr; - Memory.FillRAM[0x225a] = (uint8) (addr >> 8); - Memory.FillRAM[0x225b] = (uint8) (addr >> 16); - } -} - -uint8 S9xSA1GetByte (uint32 address) -{ - uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (*(GetAddress + (address & 0xffff))); - - switch ((pint) GetAddress) - { - case CMemory::MAP_PPU: - return (S9xGetSA1(address & 0xffff)); - - case CMemory::MAP_LOROM_SRAM: - case CMemory::MAP_SA1RAM: - return (*(Memory.SRAM + (address & 0xffff))); - - case CMemory::MAP_BWRAM: - return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); - - case CMemory::MAP_BWRAM_BITMAP: - address -= 0x600000; - if (SA1.VirtualBitmapFormat == 2) - return ((Memory.SRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); - else - return ((Memory.SRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); - - case CMemory::MAP_BWRAM_BITMAP2: - address = (address & 0xffff) - 0x6000; - if (SA1.VirtualBitmapFormat == 2) - return ((SA1.BWRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); - else - return ((SA1.BWRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); - - default: - return (SA1OpenBus); - } -} - -uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) -{ - PC_t a; - - SA1OpenBus = S9xSA1GetByte(address); - - switch (w) - { - case WRAP_PAGE: - a.xPBPC = address; - a.B.xPCl++; - return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); - - case WRAP_BANK: - a.xPBPC = address; - a.W.xPC++; - return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); - - case WRAP_NONE: - default: - return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8)); - } -} - -void S9xSA1SetByte (uint8 byte, uint32 address) -{ - uint8 *SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT]; - - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) - { - *(SetAddress + (address & 0xffff)) = byte; - return; - } - - switch ((pint) SetAddress) - { - case CMemory::MAP_PPU: - S9xSetSA1(byte, address & 0xffff); - return; - - case CMemory::MAP_LOROM_SRAM: - case CMemory::MAP_SA1RAM: - *(Memory.SRAM + (address & 0xffff)) = byte; - return; - - case CMemory::MAP_BWRAM: - *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; - return; - - case CMemory::MAP_BWRAM_BITMAP: - address -= 0x600000; - if (SA1.VirtualBitmapFormat == 2) - { - uint8 *ptr = &Memory.SRAM[(address >> 2) & 0xffff]; - *ptr &= ~(3 << ((address & 3) << 1)); - *ptr |= (byte & 3) << ((address & 3) << 1); - } - else - { - uint8 *ptr = &Memory.SRAM[(address >> 1) & 0xffff]; - *ptr &= ~(15 << ((address & 1) << 2)); - *ptr |= (byte & 15) << ((address & 1) << 2); - } - - return; - - case CMemory::MAP_BWRAM_BITMAP2: - address = (address & 0xffff) - 0x6000; - if (SA1.VirtualBitmapFormat == 2) - { - uint8 *ptr = &SA1.BWRAM[(address >> 2) & 0xffff]; - *ptr &= ~(3 << ((address & 3) << 1)); - *ptr |= (byte & 3) << ((address & 3) << 1); - } - else - { - uint8 *ptr = &SA1.BWRAM[(address >> 1) & 0xffff]; - *ptr &= ~(15 << ((address & 1) << 2)); - *ptr |= (byte & 15) << ((address & 1) << 2); - } - - return; - - default: - return; - } -} - -void S9xSA1SetWord (uint16 Word, uint32 address, enum s9xwrap_t w, enum s9xwriteorder_t o) -{ - PC_t a; - - if (!o) - S9xSA1SetByte((uint8) Word, address); - - switch (w) - { - case WRAP_PAGE: - a.xPBPC = address; - a.B.xPCl++; - S9xSA1SetByte(Word >> 8, a.xPBPC); - break; - - case WRAP_BANK: - a.xPBPC = address; - a.W.xPC++; - S9xSA1SetByte(Word >> 8, a.xPBPC); - break; - - case WRAP_NONE: - default: - S9xSA1SetByte(Word >> 8, address + 1); - break; - } - - if (o) - S9xSA1SetByte((uint8) Word, address); -} - -void S9xSA1SetPCBase (uint32 address) -{ - SA1Registers.PBPC = address & 0xffffff; - SA1.ShiftedPB = address & 0xff0000; - - uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; - - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - SA1.PCBase = GetAddress; - return; - } - - switch ((pint) GetAddress) - { - case CMemory::MAP_LOROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - SA1.PCBase = NULL; - else - SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff); - return; - - case CMemory::MAP_HIROM_SRAM: - if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) - SA1.PCBase = NULL; - else - SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff); - return; - - case CMemory::MAP_BWRAM: - SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000); - return; - - case CMemory::MAP_SA1RAM: - SA1.PCBase = Memory.SRAM; - return; - - default: - SA1.PCBase = NULL; - return; - } -} - +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +uint8 SA1OpenBus; + +static void S9xSA1SetBWRAMMemMap (uint8); +static void S9xSetSA1MemMap (uint32, uint8); +static void S9xSA1CharConv2 (void); +static void S9xSA1DMA (void); +static void S9xSA1ReadVariableLengthData (bool8, bool8); + + +void S9xSA1Init (void) +{ + SA1.Cycles = 0; + SA1.PrevCycles = 0; + SA1.Flags = 0; + SA1.WaitingForInterrupt = 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] = 0x0f; + + SA1.in_char_dma = FALSE; + SA1.TimerIRQLastState = FALSE; + SA1.HTimerIRQPos = 0; + SA1.VTimerIRQPos = 0; + SA1.HCounter = 0; + SA1.VCounter = 0; + SA1.PrevHCounter = 0; + SA1.arithmetic_op = 0; + SA1.op1 = 0; + SA1.op2 = 0; + SA1.sum = 0; + SA1.overflow = FALSE; + SA1.VirtualBitmapFormat = 0; + SA1.variable_bit_pos = 0; + + SA1Registers.PBPC = 0; + SA1Registers.PB = 0; + SA1Registers.PCw = 0; + SA1Registers.D.W = 0; + SA1Registers.DB = 0; + SA1Registers.SH = 1; + SA1Registers.SL = 0xFF; + SA1Registers.XH = 0; + SA1Registers.YH = 0; + SA1Registers.P.W = 0; + + SA1.ShiftedPB = 0; + SA1.ShiftedDB = 0; + SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + SA1ClearFlags(Decimal); + + SA1.MemSpeed = SLOW_ONE_CYCLE; + SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2; + + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + + S9xSA1SetPCBase(SA1Registers.PBPC); + + S9xSA1UnpackStatus(); + S9xSA1FixCycles(); + + SA1.BWRAM = Memory.SRAM; + + CPU.IRQExternal = FALSE; +} + +static void S9xSA1SetBWRAMMemMap (uint8 val) +{ + if (val & 0x80) + { + for (int c = 0; c < 0x400; c += 16) + { + SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + } + + SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; + } + else + { + for (int c = 0; c < 0x400; c += 16) + { + SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; + SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; + SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; + SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; + } + + SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; + } +} + +void S9xSA1PostLoadState (void) +{ + SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; + SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; + + S9xSA1SetPCBase(SA1Registers.PBPC); + S9xSA1UnpackStatus(); + S9xSA1FixCycles(); + SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4; + Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000; + S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]); +} + +static void S9xSetSA1MemMap (uint32 which1, uint8 map) +{ + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; + + if (which1 >= 2) + start2 += 0x400; + + for (int c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; + for (int i = c; i < c + 16; i++) + Memory.Map[start + i] = SA1.Map[start + i] = block; + } + + for (int c = 0; c < 0x200; c += 16) + { + uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000]; + for (int i = c + 8; i < c + 16; i++) + Memory.Map[start2 + i] = SA1.Map[start2 + i] = block; + } +} + +uint8 S9xGetSA1 (uint32 address) +{ + switch (address) + { + case 0x2300: // S-CPU flag + return ((Memory.FillRAM[0x2209] & 0x5f) | (Memory.FillRAM[0x2300] & 0xa0)); + + case 0x2301: // SA-1 flag + return ((Memory.FillRAM[0x2200] & 0x0f) | (Memory.FillRAM[0x2301] & 0xf0)); + + case 0x2302: // H counter (L) + SA1.HTimerIRQPos = SA1.HCounter / ONE_DOT_CYCLE; + SA1.VTimerIRQPos = SA1.VCounter; + return ((uint8) SA1.HTimerIRQPos); + + case 0x2303: // H counter (H) + return ((uint8) (SA1.HTimerIRQPos >> 8)); + + case 0x2304: // V counter (L) + return ((uint8) SA1.VTimerIRQPos); + + case 0x2305: // V counter (H) + return ((uint8) (SA1.VTimerIRQPos >> 8)); + + case 0x2306: // arithmetic result (LLL) + return ((uint8) SA1.sum); + + case 0x2307: // arithmetic result (LLH) + return ((uint8) (SA1.sum >> 8)); + + case 0x2308: // arithmetic result (LHL) + return ((uint8) (SA1.sum >> 16)); + + case 0x2309: // arithmetic result (LLH) + return ((uint8) (SA1.sum >> 24)); + + case 0x230a: // arithmetic result (HLL) + return ((uint8) (SA1.sum >> 32)); + + case 0x230b: // arithmetic overflow + return (SA1.overflow ? 0x80 : 0); + + case 0x230c: // variable-length data read port (L) + return (Memory.FillRAM[0x230c]); + + case 0x230d: // variable-length data read port (H) + { + uint8 byte = Memory.FillRAM[0x230d]; + + if (Memory.FillRAM[0x2258] & 0x80) + S9xSA1ReadVariableLengthData(TRUE, FALSE); + + return (byte); + } + + case 0x230e: // version code register + return (0x01); + + default: + break; + } + + return (Memory.FillRAM[address]); +} + +void S9xSetSA1 (uint8 byte, uint32 address) +{ + switch (address) + { + case 0x2200: // SA-1 control + #ifdef DEBUGGER + if (byte & 0x60) + printf("SA-1 sleep\n"); + #endif + + // SA-1 reset + if (!(byte & 0x80) && (Memory.FillRAM[0x2200] & 0x20)) + { + #ifdef DEBUGGER + printf("SA-1 reset\n"); + #endif + SA1Registers.PBPC = 0; + SA1Registers.PB = 0; + SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8); + S9xSA1SetPCBase(SA1Registers.PBPC); + } + + // SA-1 IRQ control + if (byte & 0x80) + { + Memory.FillRAM[0x2301] |= 0x80; + if (Memory.FillRAM[0x220a] & 0x80) + Memory.FillRAM[0x220b] &= ~0x80; + } + + // SA-1 NMI control + if (byte & 0x10) + { + Memory.FillRAM[0x2301] |= 0x10; + if (Memory.FillRAM[0x220a] & 0x10) + Memory.FillRAM[0x220b] &= ~0x10; + } + + break; + + case 0x2201: // S-CPU interrupt enable + // S-CPU IRQ enable + if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80)) + { + Memory.FillRAM[0x2202] &= ~0x80; + CPU.IRQExternal = TRUE; + } + + // S-CPU CHDMA IRQ enable + if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20)) + { + Memory.FillRAM[0x2202] &= ~0x20; + CPU.IRQExternal = TRUE; + } + + break; + + case 0x2202: // S-CPU interrupt clear + // S-CPU IRQ clear + if (byte & 0x80) + Memory.FillRAM[0x2300] &= ~0x80; + + // S-CPU CHDMA IRQ clear + if (byte & 0x20) + Memory.FillRAM[0x2300] &= ~0x20; + + if (!(Memory.FillRAM[0x2300] & 0xa0)) + CPU.IRQExternal = FALSE; + + break; + + case 0x2203: // SA-1 reset vector (L) + case 0x2204: // SA-1 reset vector (H) + case 0x2205: // SA-1 NMI vector (L) + case 0x2206: // SA-1 NMI vector (H) + case 0x2207: // SA-1 IRQ vector (L) + case 0x2208: // SA-1 IRQ vector (H) + break; + + case 0x2209: // S-CPU control + // 0x40: S-CPU IRQ overwrite + // 0x20: S-CPU NMI overwrite + + // S-CPU IRQ control + if (byte & 0x80) + { + Memory.FillRAM[0x2300] |= 0x80; + if (Memory.FillRAM[0x2201] & 0x80) + { + Memory.FillRAM[0x2202] &= ~0x80; + CPU.IRQExternal = TRUE; + } + } + + break; + + case 0x220a: // SA-1 interrupt enable + // SA-1 IRQ enable + if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80)) + Memory.FillRAM[0x220b] &= ~0x80; + + // SA-1 timer IRQ enable + if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40)) + Memory.FillRAM[0x220b] &= ~0x40; + + // SA-1 DMA IRQ enable + if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20)) + Memory.FillRAM[0x220b] &= ~0x20; + + // SA-1 NMI enable + if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10)) + Memory.FillRAM[0x220b] &= ~0x10; + + break; + + case 0x220b: // SA-1 interrupt clear + // SA-1 IRQ clear + if (byte & 0x80) + Memory.FillRAM[0x2301] &= ~0x80; + + // SA-1 timer IRQ clear + if (byte & 0x40) + Memory.FillRAM[0x2301] &= ~0x40; + + // SA-1 DMA IRQ clear + if (byte & 0x20) + Memory.FillRAM[0x2301] &= ~0x20; + + // SA-1 NMI clear + if (byte & 0x10) + Memory.FillRAM[0x2301] &= ~0x10; + + break; + + case 0x220c: // S-CPU NMI vector (L) + case 0x220d: // S-CPU NMI vector (H) + case 0x220e: // S-CPU IRQ vector (L) + case 0x220f: // S-CPU IRQ vector (H) + break; + + case 0x2210: // SA-1 timer control + // 0x80: mode (linear / HV) + // 0x02: V timer enable + // 0x01: H timer enable + #ifdef DEBUGGER + printf("SA-1 timer control write:%02x\n", byte); + #endif + break; + + case 0x2211: // SA-1 timer reset + SA1.HCounter = 0; + SA1.VCounter = 0; + break; + + case 0x2212: // SA-1 H-timer (L) + SA1.HTimerIRQPos = byte | (Memory.FillRAM[0x2213] << 8); + break; + + case 0x2213: // SA-1 H-timer (H) + SA1.HTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2212]; + break; + + case 0x2214: // SA-1 V-timer (L) + SA1.VTimerIRQPos = byte | (Memory.FillRAM[0x2215] << 8); + break; + + case 0x2215: // SA-1 V-timer (H) + SA1.VTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2214]; + break; + + case 0x2220: // MMC bank C + case 0x2221: // MMC bank D + case 0x2222: // MMC bank E + case 0x2223: // MMC bank F + S9xSetSA1MemMap(address - 0x2220, byte); + break; + + case 0x2224: // S-CPU BW-RAM mapping + Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; + break; + + case 0x2225: // SA-1 BW-RAM mapping + if (byte != Memory.FillRAM[0x2225]) + S9xSA1SetBWRAMMemMap(byte); + + break; + + case 0x2226: // S-CPU BW-RAM write enable + case 0x2227: // SA-1 BW-RAM write enable + case 0x2228: // BW-RAM write-protected area + case 0x2229: // S-CPU I-RAM write protection + case 0x222a: // SA-1 I-RAM write protection + break; + + case 0x2230: // DMA control + // 0x80: enable + // 0x40: priority (DMA / SA-1) + // 0x20: character conversion / normal + // 0x10: BW-RAM -> I-RAM / SA-1 -> I-RAM + // 0x04: destinatin (BW-RAM / I-RAM) + // 0x03: source + break; + + case 0x2231: // character conversion DMA parameters + // 0x80: CHDEND (complete / incomplete) + // 0x03: color mode + // (byte >> 2) & 7: virtual VRAM width + if (byte & 0x80) + SA1.in_char_dma = FALSE; + + break; + + case 0x2232: // DMA source start address (LL) + case 0x2233: // DMA source start address (LH) + case 0x2234: // DMA source start address (HL) + break; + + case 0x2235: // DMA destination start address (LL) + break; + + case 0x2236: // DMA destination start address (LH) + Memory.FillRAM[0x2236] = byte; + + if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM + S9xSA1DMA(); + else + if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) // CC1 + { + SA1.in_char_dma = TRUE; + + Memory.FillRAM[0x2300] |= 0x20; + if (Memory.FillRAM[0x2201] & 0x20) + { + Memory.FillRAM[0x2202] &= ~0x20; + CPU.IRQExternal = TRUE; + } + } + + break; + + case 0x2237: // DMA destination start address (HL) + Memory.FillRAM[0x2237] = byte; + + if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM + S9xSA1DMA(); + + break; + + case 0x2238: // DMA terminal counter (L) + case 0x2239: // DMA terminal counter (H) + break; + + case 0x223f: // BW-RAM bitmap format + SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; + break; + + case 0x2240: // bitmap register 0 + case 0x2241: // bitmap register 1 + case 0x2242: // bitmap register 2 + case 0x2243: // bitmap register 3 + case 0x2244: // bitmap register 4 + case 0x2245: // bitmap register 5 + case 0x2246: // bitmap register 6 + case 0x2247: // bitmap register 7 + case 0x2248: // bitmap register 8 + case 0x2249: // bitmap register 9 + case 0x224a: // bitmap register A + case 0x224b: // bitmap register B + case 0x224c: // bitmap register C + case 0x224d: // bitmap register D + case 0x224e: // bitmap register E + break; + + case 0x224f: // bitmap register F + Memory.FillRAM[0x224f] = byte; + + if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // CC2 + { + memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16); + SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; + if ((SA1.in_char_dma & 3) == 0) + S9xSA1CharConv2(); + } + + break; + + case 0x2250: // arithmetic control + if (byte & 2) + SA1.sum = 0; + SA1.arithmetic_op = byte & 3; + break; + + case 0x2251: // multiplicand / dividend (L) + SA1.op1 = (SA1.op1 & 0xff00) | byte; + break; + + case 0x2252: // multiplicand / dividend (H) + SA1.op1 = (SA1.op1 & 0x00ff) | (byte << 8); + break; + + case 0x2253: // multiplier / divisor (L) + SA1.op2 = (SA1.op2 & 0xff00) | byte; + break; + + case 0x2254: // multiplier / divisor (H) + SA1.op2 = (SA1.op2 & 0x00ff) | (byte << 8); + + switch (SA1.arithmetic_op) + { + case 0: // signed multiplication + SA1.sum = (int16) SA1.op1 * (int16) SA1.op2; + SA1.op2 = 0; + break; + + case 1: // unsigned division + if (SA1.op2 == 0) + SA1.sum = 0; + else + { + int16 quotient = (int16) SA1.op1 / (uint16) SA1.op2; + uint16 remainder = (int16) SA1.op1 % (uint16) SA1.op2; + SA1.sum = (remainder << 16) | quotient; + } + + SA1.op1 = 0; + SA1.op2 = 0; + break; + + case 2: // cumulative sum + default: + SA1.sum += (int16) SA1.op1 * (int16) SA1.op2; + SA1.overflow = (SA1.sum >= (1ULL << 40)); + SA1.sum &= (1ULL << 40) - 1; + SA1.op2 = 0; + break; + } + + break; + + case 0x2258: // variable bit-field length / auto inc / start + Memory.FillRAM[0x2258] = byte; + S9xSA1ReadVariableLengthData(TRUE, FALSE); + return; + + case 0x2259: // variable bit-field start address (LL) + case 0x225a: // variable bit-field start address (LH) + case 0x225b: // variable bit-field start address (HL) + Memory.FillRAM[address] = byte; + // XXX: ??? + SA1.variable_bit_pos = 0; + S9xSA1ReadVariableLengthData(FALSE, TRUE); + return; + + default: + break; + } + + if (address >= 0x2200 && address <= 0x22ff) + Memory.FillRAM[address] = byte; +} + +static void S9xSA1CharConv2 (void) +{ + uint32 dest = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8); + uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; + int depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; + int bytes_per_char = 8 * depth; + uint8 *p = &Memory.FillRAM[0x3000] + (dest & 0x7ff) + offset * bytes_per_char; + uint8 *q = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; + + switch (depth) + { + case 2: + 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 += 2; + } + + break; + + case 4: + 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 += 2; + } + + break; + + case 8: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + break; + } +} + +static void S9xSA1DMA (void) +{ + uint32 src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16); + uint32 dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16); + uint32 len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8); + uint8 *s, *d; + + switch (Memory.FillRAM[0x2230] & 3) + { + case 0: // ROM + s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)]; + if (s >= (uint8 *) CMemory::MAP_LAST) + s += (src & 0xffff); + else + s = Memory.ROM + (src & 0xffff); + break; + + case 1: // BW-RAM + src &= Memory.SRAMMask; + len &= Memory.SRAMMask; + s = Memory.SRAM + src; + break; + + default: + case 2: + src &= 0x3ff; + len &= 0x3ff; + s = &Memory.FillRAM[0x3000] + src; + break; + } + + if (Memory.FillRAM[0x2230] & 4) + { + dst &= Memory.SRAMMask; + len &= Memory.SRAMMask; + d = Memory.SRAM + dst; + } + else + { + dst &= 0x3ff; + len &= 0x3ff; + d = &Memory.FillRAM[0x3000] + dst; + } + + memmove(d, s, len); + + // SA-1 DMA IRQ control + Memory.FillRAM[0x2301] |= 0x20; + if (Memory.FillRAM[0x220a] & 0x20) + Memory.FillRAM[0x220b] &= ~0x20; +} + +static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) +{ + uint32 addr = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16); + uint8 shift = Memory.FillRAM[0x2258] & 15; + + if (no_shift) + shift = 0; + else + if (shift == 0) + shift = 16; + + uint8 s = shift + SA1.variable_bit_pos; + + if (s >= 16) + { + addr += (s >> 4) << 1; + s &= 15; + } + + uint32 data = S9xSA1GetWord(addr) | (S9xSA1GetWord(addr + 2) << 16); + + data >>= s; + Memory.FillRAM[0x230c] = (uint8) data; + Memory.FillRAM[0x230d] = (uint8) (data >> 8); + + if (inc) + { + SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; + Memory.FillRAM[0x2259] = (uint8) addr; + Memory.FillRAM[0x225a] = (uint8) (addr >> 8); + Memory.FillRAM[0x225b] = (uint8) (addr >> 16); + } +} + +uint8 S9xSA1GetByte (uint32 address) +{ + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (*(GetAddress + (address & 0xffff))); + + switch ((pint) GetAddress) + { + case CMemory::MAP_PPU: + return (S9xGetSA1(address & 0xffff)); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + return (*(Memory.SRAM + (address & 0xffff))); + + case CMemory::MAP_BWRAM: + return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); + + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + return ((Memory.SRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((Memory.SRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + return ((SA1.BWRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((SA1.BWRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + + default: + return (SA1OpenBus); + } +} + +uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) +{ + PC_t a; + + SA1OpenBus = S9xSA1GetByte(address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); + + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); + + case WRAP_NONE: + default: + return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8)); + } +} + +void S9xSA1SetByte (uint8 byte, uint32 address) +{ + uint8 *SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + *(SetAddress + (address & 0xffff)) = byte; + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_PPU: + S9xSetSA1(byte, address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (address & 0xffff)) = byte; + return; + + case CMemory::MAP_BWRAM: + *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; + return; + + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &Memory.SRAM[(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &Memory.SRAM[(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + + return; + + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &SA1.BWRAM[(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &SA1.BWRAM[(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + + return; + + default: + return; + } +} + +void S9xSA1SetWord (uint16 Word, uint32 address, enum s9xwrap_t w, enum s9xwriteorder_t o) +{ + PC_t a; + + if (!o) + S9xSA1SetByte((uint8) Word, address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + S9xSA1SetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + S9xSA1SetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_NONE: + default: + S9xSA1SetByte(Word >> 8, address + 1); + break; + } + + if (o) + S9xSA1SetByte((uint8) Word, address); +} + +void S9xSA1SetPCBase (uint32 address) +{ + SA1Registers.PBPC = address & 0xffffff; + SA1.ShiftedPB = address & 0xff0000; + + // FIXME + SA1.MemSpeed = memory_speed(address); + SA1.MemSpeedx2 = SA1.MemSpeed << 1; + + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + SA1.PCBase = GetAddress; + return; + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + SA1.PCBase = NULL; + else + SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff); + return; + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + SA1.PCBase = NULL; + else + SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff); + return; + + case CMemory::MAP_BWRAM: + SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000); + return; + + case CMemory::MAP_SA1RAM: + SA1.PCBase = Memory.SRAM; + return; + + default: + SA1.PCBase = NULL; + return; + } +} diff --git a/source/snes9x/sa1.h b/source/snes9x/sa1.h index 7849c8c..eef38a2 100644 --- a/source/snes9x/sa1.h +++ b/source/snes9x/sa1.h @@ -198,32 +198,33 @@ struct SSA1 uint8 _Zero; uint8 _Negative; uint8 _Overflow; - bool8 CPUExecuting; uint32 ShiftedPB; uint32 ShiftedDB; uint32 Flags; + int32 Cycles; + int32 PrevCycles; uint8 *PCBase; - bool8 IRQActive; - bool8 Waiting; bool8 WaitingForInterrupt; - uint32 WaitAddress; - uint32 WaitCounter; - uint32 PBPCAtOpcodeStart; - uint8 *WaitByteAddress1; - uint8 *WaitByteAddress2; uint8 *Map[MEMMAP_NUM_BLOCKS]; uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; uint8 *BWRAM; - bool8 Executing; - bool8 overflow; bool8 in_char_dma; - int16 op1; - int16 op2; + bool8 TimerIRQLastState; + uint16 HTimerIRQPos; + uint16 VTimerIRQPos; + int16 HCounter; + int16 VCounter; + int16 PrevHCounter; + int32 MemSpeed; + int32 MemSpeedx2; int32 arithmetic_op; - int64 sum; + uint16 op1; + uint16 op2; + uint64 sum; + bool8 overflow; uint8 VirtualBitmapFormat; uint8 variable_bit_pos; }; @@ -263,13 +264,8 @@ uint8 S9xGetSA1 (uint32); void S9xSetSA1 (uint8, uint32); void S9xSA1Init (void); void S9xSA1MainLoop (void); -void S9xSA1ExecuteDuringSleep (void); void S9xSA1PostLoadState (void); -#define SNES_IRQ_SOURCE (1 << 7) -#define TIMER_IRQ_SOURCE (1 << 6) -#define DMA_IRQ_SOURCE (1 << 5) - static inline void S9xSA1UnpackStatus (void) { SA1._Zero = (SA1Registers.PL & Zero) == 0; diff --git a/source/snes9x/sa1cpu.cpp b/source/snes9x/sa1cpu.cpp index 648266c..994e240 100644 --- a/source/snes9x/sa1cpu.cpp +++ b/source/snes9x/sa1cpu.cpp @@ -1,303 +1,399 @@ -/*********************************************************************************** - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2004 Matthew Kendora - - (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) - - (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) - - (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com) - - (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), - Nach (n-a-c-h@users.sourceforge.net), - zones (kasumitokoduck@yahoo.com) - - (c) Copyright 2006 - 2007 nitsuja - - (c) Copyright 2009 - 2010 BearOso, - OV2 - - - BS-X C emulator code - (c) Copyright 2005 - 2006 Dreamer Nom, - zones - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), - Nach, - zsKnight (zsknight@zsnes.com) - - C4 C++ code - (c) Copyright 2003 - 2006 Brad Jorsch, - Nach - - DSP-1 emulator code - (c) Copyright 1998 - 2006 _Demo_, - Andreas Naive (andreasnaive@gmail.com), - Gary Henderson, - Ivar (ivar@snes9x.com), - John Weidman, - Kris Bleakley, - Matthew Kendora, - Nach, - neviksti (neviksti@hotmail.com) - - DSP-2 emulator code - (c) Copyright 2003 John Weidman, - Kris Bleakley, - Lord Nightmare (lord_nightmare@users.sourceforge.net), - Matthew Kendora, - neviksti - - DSP-3 emulator code - (c) Copyright 2003 - 2006 John Weidman, - Kris Bleakley, - Lancer, - z80 gaiden - - DSP-4 emulator code - (c) Copyright 2004 - 2006 Dreamer Nom, - John Weidman, - Kris Bleakley, - Nach, - z80 gaiden - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, - pagefault (pagefault@zsnes.com), - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code used in 1.39-1.51 - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, - John Weidman, - Dark Force - - SPC7110 and RTC C++ emulator code used in 1.52+ - (c) Copyright 2009 byuu, - neviksti - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive, - John Weidman - - S-RTC C emulator code - (c) Copyright 2001 - 2006 byuu, - John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, - John Weidman, - Kris Bleakley, - Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 _Demo_, - pagefault, - zsKnight - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, - Gary Henderson, - John Weidman - - Sound emulator code used in 1.5-1.51 - (c) Copyright 1998 - 2003 Brad Martin - (c) Copyright 1998 - 2006 Charles Bilyue' - - Sound emulator code used in 1.52+ - (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - 2xSaI filter - (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - - HQ2x, HQ3x, HQ4x filters - (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) - - NTSC filter - (c) Copyright 2006 - 2007 Shay Green - - GTK+ GUI code - (c) Copyright 2004 - 2010 BearOso - - Win32 GUI code - (c) Copyright 2003 - 2006 blip, - funkyass, - Matthew Kendora, - Nach, - nitsuja - (c) Copyright 2009 - 2010 OV2 - - Mac OS GUI code - (c) Copyright 1998 - 2001 John Stiles - (c) Copyright 2001 - 2010 zones - - - Specific ports contains the works of other authors. See headers in - individual files. - - - Snes9x homepage: http://www.snes9x.com/ - - Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear - with all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software or it's derivatives. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes, - but is not limited to, charging money for Snes9x or software derived from - Snes9x, including Snes9x or derivatives in commercial game bundles, and/or - using Snes9x as a promotion for your commercial product. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. - ***********************************************************************************/ - - -#include "snes9x.h" -#include "memmap.h" - -#define CPU SA1 -#define ICPU SA1 -#define Registers SA1Registers -#define OpenBus SA1OpenBus -#define S9xGetByte S9xSA1GetByte -#define S9xGetWord S9xSA1GetWord -#define S9xSetByte S9xSA1SetByte -#define S9xSetWord S9xSA1SetWord -#define S9xSetPCBase S9xSA1SetPCBase -#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 -#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 -#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 -#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 -#define S9xOpcodesE1 S9xSA1OpcodesE1 -#define S9xOpcodesSlow S9xSA1OpcodesSlow -#define S9xOpcode_IRQ S9xSA1Opcode_IRQ -#define S9xOpcode_NMI S9xSA1Opcode_NMI -#define S9xUnpackStatus S9xSA1UnpackStatus -#define S9xPackStatus S9xSA1PackStatus -#define S9xFixCycles S9xSA1FixCycles -#define Immediate8 SA1Immediate8 -#define Immediate16 SA1Immediate16 -#define Relative SA1Relative -#define RelativeLong SA1RelativeLong -#define Absolute SA1Absolute -#define AbsoluteLong SA1AbsoluteLong -#define AbsoluteIndirect SA1AbsoluteIndirect -#define AbsoluteIndirectLong SA1AbsoluteIndirectLong -#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect -#define Direct SA1Direct -#define DirectIndirectIndexed SA1DirectIndirectIndexed -#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong -#define DirectIndexedIndirect SA1DirectIndexedIndirect -#define DirectIndexedX SA1DirectIndexedX -#define DirectIndexedY SA1DirectIndexedY -#define AbsoluteIndexedX SA1AbsoluteIndexedX -#define AbsoluteIndexedY SA1AbsoluteIndexedY -#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX -#define DirectIndirect SA1DirectIndirect -#define DirectIndirectLong SA1DirectIndirectLong -#define StackRelative SA1StackRelative -#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed - -//#undef CPU_SHUTDOWN -#define SA1_OPCODES - -#include "cpuops.cpp" - - -void S9xSA1MainLoop (void) -{ - if (SA1.Flags & NMI_FLAG) - { - if (Memory.FillRAM[0x2200] & 0x10) - { - SA1.Flags &= ~NMI_FLAG; - Memory.FillRAM[0x2301] |= 0x10; - - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; - } - - S9xSA1Opcode_NMI(); - } - } - - if (SA1.Flags & IRQ_FLAG) - { - if (SA1.IRQActive) - { - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; - } - - if (!SA1CheckFlag(IRQ)) - S9xSA1Opcode_IRQ(); - } - else - SA1.Flags &= ~IRQ_FLAG; - } - - for (int i = 0; i < 3 && SA1.Executing; i++) - { - #ifdef DEBUGGER - if (SA1.Flags & TRACE_FLAG) - S9xSA1Trace(); - #endif - - #ifdef CPU_SHUTDOWN - SA1.PBPCAtOpcodeStart = SA1Registers.PBPC; - #endif - - register uint8 Op; - register struct SOpcodes *Opcodes; - - if (SA1.PCBase) - { - SA1OpenBus = Op = SA1.PCBase[Registers.PCw]; - Opcodes = SA1.S9xOpcodes; - } - else - { - Op = S9xSA1GetByte(Registers.PBPC); - Opcodes = S9xOpcodesSlow; - } - - if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) - { - uint32 oldPC = SA1Registers.PBPC; - S9xSA1SetPCBase(SA1Registers.PBPC); - SA1Registers.PBPC = oldPC; - Opcodes = S9xSA1OpcodesSlow; - } - - Registers.PCw++; - (*Opcodes[Op].S9xOpcode)(); - } -} - +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +#define CPU SA1 +#define ICPU SA1 +#define Registers SA1Registers +#define OpenBus SA1OpenBus +#define S9xGetByte S9xSA1GetByte +#define S9xGetWord S9xSA1GetWord +#define S9xSetByte S9xSA1SetByte +#define S9xSetWord S9xSA1SetWord +#define S9xSetPCBase S9xSA1SetPCBase +#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 +#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 +#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 +#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 +#define S9xOpcodesE1 S9xSA1OpcodesE1 +#define S9xOpcodesSlow S9xSA1OpcodesSlow +#define S9xOpcode_IRQ S9xSA1Opcode_IRQ +#define S9xOpcode_NMI S9xSA1Opcode_NMI +#define S9xUnpackStatus S9xSA1UnpackStatus +#define S9xPackStatus S9xSA1PackStatus +#define S9xFixCycles S9xSA1FixCycles +#define Immediate8 SA1Immediate8 +#define Immediate16 SA1Immediate16 +#define Relative SA1Relative +#define RelativeLong SA1RelativeLong +#define Absolute SA1Absolute +#define AbsoluteLong SA1AbsoluteLong +#define AbsoluteIndirect SA1AbsoluteIndirect +#define AbsoluteIndirectLong SA1AbsoluteIndirectLong +#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect +#define Direct SA1Direct +#define DirectIndirectIndexed SA1DirectIndirectIndexed +#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong +#define DirectIndexedIndirect SA1DirectIndexedIndirect +#define DirectIndexedX SA1DirectIndexedX +#define DirectIndexedY SA1DirectIndexedY +#define AbsoluteIndexedX SA1AbsoluteIndexedX +#define AbsoluteIndexedY SA1AbsoluteIndexedY +#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX +#define DirectIndirect SA1DirectIndirect +#define DirectIndirectLong SA1DirectIndirectLong +#define StackRelative SA1StackRelative +#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed + +#define SA1_OPCODES + +#include "cpuops.cpp" + +static void S9xSA1UpdateTimer (void); + + +void S9xSA1MainLoop (void) +{ + if (Memory.FillRAM[0x2200] & 0x60) + { + SA1.Cycles += 6; // FIXME + S9xSA1UpdateTimer(); + return; + } + + // SA-1 NMI + if ((Memory.FillRAM[0x2200] & 0x10) && !(Memory.FillRAM[0x220b] & 0x10)) + { + Memory.FillRAM[0x2301] |= 0x10; + Memory.FillRAM[0x220b] |= 0x10; + + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_NMI(); + } + else + if (!SA1CheckFlag(IRQ)) + { + // SA-1 Timer IRQ + if ((Memory.FillRAM[0x220a] & 0x40) && !(Memory.FillRAM[0x220b] & 0x40)) + { + Memory.FillRAM[0x2301] |= 0x40; + + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_IRQ(); + } + else + // SA-1 DMA IRQ + if ((Memory.FillRAM[0x220a] & 0x20) && !(Memory.FillRAM[0x220b] & 0x20)) + { + Memory.FillRAM[0x2301] |= 0x20; + + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_IRQ(); + } + else + // SA-1 IRQ + if ((Memory.FillRAM[0x2200] & 0x80) && !(Memory.FillRAM[0x220b] & 0x80)) + { + Memory.FillRAM[0x2301] |= 0x80; + + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_IRQ(); + } + } + + for (int i = 0; i < 3 && !(Memory.FillRAM[0x2200] & 0x60); i++) + { + #ifdef DEBUGGER + if (SA1.Flags & TRACE_FLAG) + S9xSA1Trace(); + #endif + + register uint8 Op; + register struct SOpcodes *Opcodes; + + if (SA1.PCBase) + { + SA1OpenBus = Op = SA1.PCBase[Registers.PCw]; + Opcodes = SA1.S9xOpcodes; + } + else + { + Op = S9xSA1GetByte(Registers.PBPC); + Opcodes = S9xOpcodesSlow; + } + + if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + { + uint32 oldPC = SA1Registers.PBPC; + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1Registers.PBPC = oldPC; + Opcodes = S9xSA1OpcodesSlow; + } + + Registers.PCw++; + (*Opcodes[Op].S9xOpcode)(); + } + + S9xSA1UpdateTimer(); +} + +static void S9xSA1UpdateTimer (void) // FIXME +{ + SA1.PrevHCounter = SA1.HCounter; + + if (Memory.FillRAM[0x2210] & 0x80) + { + SA1.HCounter += (SA1.Cycles - SA1.PrevCycles); + if (SA1.HCounter >= 0x800) + { + SA1.HCounter -= 0x800; + SA1.PrevHCounter -= 0x800; + if (++SA1.VCounter >= 0x200) + SA1.VCounter = 0; + } + } + else + { + SA1.HCounter += (SA1.Cycles - SA1.PrevCycles); + if (SA1.HCounter >= Timings.H_Max_Master) + { + SA1.HCounter -= Timings.H_Max_Master; + SA1.PrevHCounter -= Timings.H_Max_Master; + if (++SA1.VCounter >= Timings.V_Max_Master) + SA1.VCounter = 0; + } + } + + if (SA1.Cycles >= Timings.H_Max_Master) + SA1.Cycles -= Timings.H_Max_Master; + + SA1.PrevCycles = SA1.Cycles; + + bool8 thisIRQ = Memory.FillRAM[0x2210] & 0x03; + + if (Memory.FillRAM[0x2210] & 0x01) + { + if (SA1.PrevHCounter >= SA1.HTimerIRQPos * ONE_DOT_CYCLE || SA1.HCounter < SA1.HTimerIRQPos * ONE_DOT_CYCLE) + thisIRQ = FALSE; + } + + if (Memory.FillRAM[0x2210] & 0x02) + { + if (SA1.VCounter != SA1.VTimerIRQPos * ONE_DOT_CYCLE) + thisIRQ = FALSE; + } + + // SA-1 Timer IRQ control + if (!SA1.TimerIRQLastState && thisIRQ) + { + Memory.FillRAM[0x2301] |= 0x40; + if (Memory.FillRAM[0x220a] & 0x40) + { + Memory.FillRAM[0x220b] &= ~0x40; + #ifdef DEBUGGER + S9xTraceFormattedMessage("--- SA-1 Timer IRQ triggered prev HC:%04d curr HC:%04d HTimer:%d Pos:%04d VTimer:%d Pos:%03d", + SA1.PrevHCounter, SA1.HCounter, + (Memory.FillRAM[0x2210] & 0x01) ? 1 : 0, SA1.HTimerIRQPos * ONE_DOT_CYCLE, + (Memory.FillRAM[0x2210] & 0x02) ? 1 : 0, SA1.VTimerIRQPos); + #endif + } + } + + SA1.TimerIRQLastState = thisIRQ; +} diff --git a/source/snes9x/snapshot.cpp b/source/snes9x/snapshot.cpp index 0308c71..468a681 100644 --- a/source/snes9x/snapshot.cpp +++ b/source/snes9x/snapshot.cpp @@ -342,7 +342,7 @@ struct SnapshotScreenshotInfo static struct Obsolete { - uint8 reserved; + uint8 CPU_IRQActive; } Obsolete; #define STRUCT struct SCPUState @@ -353,7 +353,7 @@ static FreezeData SnapCPU[] = INT_ENTRY(6, PrevCycles), INT_ENTRY(6, V_Counter), INT_ENTRY(6, Flags), - INT_ENTRY(6, IRQActive), + OBSOLETE_INT_ENTRY(6, 7, CPU_IRQActive), INT_ENTRY(6, IRQPending), INT_ENTRY(6, MemSpeed), INT_ENTRY(6, MemSpeedx2), @@ -366,9 +366,14 @@ static FreezeData SnapCPU[] = INT_ENTRY(6, WhichEvent), INT_ENTRY(6, NextEvent), INT_ENTRY(6, WaitingForInterrupt), - INT_ENTRY(6, WaitAddress), - INT_ENTRY(6, WaitCounter), - INT_ENTRY(6, PBPCAtOpcodeStart) + DELETED_INT_ENTRY(6, 7, WaitAddress, 4), + DELETED_INT_ENTRY(6, 7, WaitCounter, 4), + DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4), + INT_ENTRY(7, NMILine), + INT_ENTRY(7, IRQLine), + INT_ENTRY(7, IRQTransition), + INT_ENTRY(7, IRQLastState), + INT_ENTRY(7, IRQExternal) }; #undef STRUCT @@ -576,11 +581,11 @@ static FreezeData SnapTimings[] = INT_ENTRY(6, DMACPUSync), INT_ENTRY(6, NMIDMADelay), INT_ENTRY(6, IRQPendCount), - INT_ENTRY(6, APUSpeedup) + INT_ENTRY(6, APUSpeedup), + INT_ENTRY(7, IRQTriggerCycles), + INT_ENTRY(7, APUAllowTimeOverflow) }; -#ifndef ZSNES_FX - #undef STRUCT #define STRUCT struct FxRegs_s @@ -642,24 +647,22 @@ static FreezeData SnapFX[] = INT_ENTRY(6, vSCBRDirty) }; -#endif - #undef STRUCT #define STRUCT struct SSA1 static FreezeData SnapSA1[] = { - INT_ENTRY(6, CPUExecuting), + DELETED_INT_ENTRY(6, 7, CPUExecuting, 1), INT_ENTRY(6, ShiftedPB), INT_ENTRY(6, ShiftedDB), INT_ENTRY(6, Flags), - INT_ENTRY(6, IRQActive), - INT_ENTRY(6, Waiting), + DELETED_INT_ENTRY(6, 7, IRQActive, 1), + DELETED_INT_ENTRY(6, 7, Waiting, 1), INT_ENTRY(6, WaitingForInterrupt), - INT_ENTRY(6, WaitAddress), - INT_ENTRY(6, WaitCounter), - INT_ENTRY(6, PBPCAtOpcodeStart), - INT_ENTRY(6, Executing), + DELETED_INT_ENTRY(6, 7, WaitAddress, 4), + DELETED_INT_ENTRY(6, 7, WaitCounter, 4), + DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4), + DELETED_INT_ENTRY(6, 7, Executing, 1), INT_ENTRY(6, overflow), INT_ENTRY(6, in_char_dma), INT_ENTRY(6, op1), @@ -667,7 +670,17 @@ static FreezeData SnapSA1[] = INT_ENTRY(6, arithmetic_op), INT_ENTRY(6, sum), INT_ENTRY(6, VirtualBitmapFormat), - INT_ENTRY(6, variable_bit_pos) + INT_ENTRY(6, variable_bit_pos), + INT_ENTRY(7, Cycles), + INT_ENTRY(7, PrevCycles), + INT_ENTRY(7, TimerIRQLastState), + INT_ENTRY(7, HTimerIRQPos), + INT_ENTRY(7, VTimerIRQPos), + INT_ENTRY(7, HCounter), + INT_ENTRY(7, VCounter), + INT_ENTRY(7, PrevHCounter), + INT_ENTRY(7, MemSpeed), + INT_ENTRY(7, MemSpeedx2) }; #undef STRUCT @@ -1255,15 +1268,10 @@ bool8 S9xUnfreezeGame (const char *filename) void S9xFreezeToStream (STREAM stream) { char buffer[1024]; - uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; + uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; S9xSetSoundMute(TRUE); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPreSaveState(); -#endif - sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); WRITE_STREAM(buffer, strlen(buffer), stream); @@ -1298,13 +1306,11 @@ void S9xFreezeToStream (STREAM stream) FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings)); -#ifndef ZSNES_FX if (Settings.SuperFX) { GSU.avRegAddr = (uint8 *) &GSU.avReg; FreezeStruct(stream, "SFX", &GSU, SnapFX, COUNT(SnapFX)); } -#endif if (Settings.SA1) { @@ -1323,11 +1329,7 @@ void S9xFreezeToStream (STREAM stream) FreezeStruct(stream, "DP4", &DSP4, SnapDSP4, COUNT(SnapDSP4)); if (Settings.C4) -#ifndef ZSNES_C4 FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); -#else - FreezeBlock (stream, "CX4", C4Ram, 8192); -#endif if (Settings.SETA == ST_010) FreezeStruct(stream, "ST0", &ST010, SnapST010, COUNT(SnapST010)); @@ -1405,11 +1407,6 @@ void S9xFreezeToStream (STREAM stream) } } -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostSaveState(); -#endif - S9xSetSoundMute(FALSE); delete [] soundsnapshot; @@ -1510,11 +1507,9 @@ int S9xUnfreezeFromStream (STREAM stream) if (result != SUCCESS) break; - #ifndef ZSNES_FX result = UnfreezeStructCopy(stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version); if (result != SUCCESS && Settings.SuperFX) break; - #endif result = UnfreezeStructCopy(stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1), version); if (result != SUCCESS && Settings.SA1) @@ -1637,13 +1632,11 @@ int S9xUnfreezeFromStream (STREAM stream) UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version); - #ifndef ZSNES_FX if (local_superfx) { GSU.avRegAddr = (uint8 *) &GSU.avReg; UnfreezeStructFromCopy(&GSU, SnapFX, COUNT(SnapFX), local_superfx, version); } - #endif if (local_sa1) UnfreezeStructFromCopy(&SA1, SnapSA1, COUNT(SnapSA1), local_sa1, version); @@ -1661,11 +1654,7 @@ int S9xUnfreezeFromStream (STREAM stream) UnfreezeStructFromCopy(&DSP4, SnapDSP4, COUNT(SnapDSP4), local_dsp4, version); if (local_cx4_data) - #ifndef ZSNES_C4 memcpy(Memory.C4RAM, local_cx4_data, 8192); - #else - memcpy(C4Ram, local_cx4_data, 8192); - #endif if (local_st010) UnfreezeStructFromCopy(&ST010, SnapST010, COUNT(SnapST010), local_st010, version); @@ -1688,6 +1677,40 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_bsx_data) UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); + if (version < SNAPSHOT_VERSION) + { + printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION); + + CPU.NMILine = (CPU.Flags & (1 << 7)) ? TRUE : FALSE; + CPU.IRQLine = (CPU.Flags & (1 << 11)) ? TRUE : FALSE; + CPU.IRQTransition = FALSE; + CPU.IRQLastState = FALSE; + CPU.IRQExternal = (Obsolete.CPU_IRQActive & ~(1 << 1)) ? TRUE : FALSE; + + switch (CPU.WhichEvent) + { + case 12: case 1: CPU.WhichEvent = 1; break; + case 2: case 3: CPU.WhichEvent = 2; break; + case 4: case 5: CPU.WhichEvent = 3; break; + case 6: case 7: CPU.WhichEvent = 4; break; + case 8: case 9: CPU.WhichEvent = 5; break; + case 10: case 11: CPU.WhichEvent = 6; break; + } + + if (local_sa1) // FIXME + { + SA1.Cycles = SA1.PrevCycles = 0; + SA1.TimerIRQLastState = FALSE; + SA1.HTimerIRQPos = Memory.FillRAM[0x2212] | (Memory.FillRAM[0x2213] << 8); + SA1.VTimerIRQPos = Memory.FillRAM[0x2214] | (Memory.FillRAM[0x2215] << 8); + SA1.HCounter = 0; + SA1.VCounter = 0; + SA1.PrevHCounter = 0; + SA1.MemSpeed = SLOW_ONE_CYCLE; + SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2; + } + } + CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); ICPU.ShiftedPB = Registers.PB << 16; ICPU.ShiftedDB = Registers.DB << 16; @@ -1711,16 +1734,11 @@ int S9xUnfreezeFromStream (STREAM stream) S9xControlPostLoadState(&ctl_snap); - #ifndef ZSNES_FX if (local_superfx) { GSU.pfPlot = fx_PlotTable[GSU.vMode]; GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; } - #else - if (Settings.SuperFX) - S9xSuperFXPostLoadState(); - #endif if (local_sa1 && local_sa1_registers) { @@ -2280,4 +2298,3 @@ bool8 S9xSPCDump (const char *filename) return (TRUE); } - diff --git a/source/snes9x/snapshot.h b/source/snes9x/snapshot.h index b3ead24..55c72d7 100644 --- a/source/snes9x/snapshot.h +++ b/source/snes9x/snapshot.h @@ -179,7 +179,7 @@ #define _SNAPSHOT_H_ #define SNAPSHOT_MAGIC "#!s9xsnp" -#define SNAPSHOT_VERSION 6 +#define SNAPSHOT_VERSION 7 #define SUCCESS 1 #define WRONG_FORMAT (-1) diff --git a/source/snes9x/snes9x.h b/source/snes9x/snes9x.h index a58be71..ccab877 100644 --- a/source/snes9x/snes9x.h +++ b/source/snes9x/snes9x.h @@ -186,8 +186,6 @@ #include "65c816.h" #include "messages.h" -#define S9X_ACCURACY_LEVEL 3 - #ifdef ZLIB #include #define STREAM gzFile @@ -263,8 +261,6 @@ #define TRACE_FLAG (1 << 1) // debugger #define SINGLE_STEP_FLAG (1 << 2) // debugger #define BREAK_FLAG (1 << 3) // debugger -#define NMI_FLAG (1 << 7) // CPU -#define IRQ_FLAG (1 << 11) // CPU #define SCAN_KEYS_FLAG (1 << 4) // CPU #define HALTED_FLAG (1 << 12) // APU #define FRAME_ADVANCE_FLAG (1 << 9) @@ -274,12 +270,16 @@ struct SCPUState { + uint32 Flags; int32 Cycles; int32 PrevCycles; int32 V_Counter; - uint32 Flags; uint8 *PCBase; - bool8 IRQActive; + bool8 NMILine; + bool8 IRQLine; + bool8 IRQTransition; + bool8 IRQLastState; + bool8 IRQExternal; int32 IRQPending; int32 MemSpeed; int32 MemSpeedx2; @@ -293,9 +293,6 @@ struct SCPUState uint8 WhichEvent; int32 NextEvent; bool8 WaitingForInterrupt; - uint32 WaitAddress; - uint32 WaitCounter; - uint32 PBPCAtOpcodeStart; uint32 AutoSaveTimer; bool8 SRAMModified; }; @@ -303,17 +300,11 @@ struct SCPUState enum { HC_HBLANK_START_EVENT = 1, - HC_IRQ_1_3_EVENT = 2, - HC_HDMA_START_EVENT = 3, - HC_IRQ_3_5_EVENT = 4, - HC_HCOUNTER_MAX_EVENT = 5, - HC_IRQ_5_7_EVENT = 6, - HC_HDMA_INIT_EVENT = 7, - HC_IRQ_7_9_EVENT = 8, - HC_RENDER_EVENT = 9, - HC_IRQ_9_A_EVENT = 10, - HC_WRAM_REFRESH_EVENT = 11, - HC_IRQ_A_1_EVENT = 12 + HC_HDMA_START_EVENT = 2, + HC_HCOUNTER_MAX_EVENT = 3, + HC_HDMA_INIT_EVENT = 4, + HC_RENDER_EVENT = 5, + HC_WRAM_REFRESH_EVENT = 6 }; struct STimings @@ -327,12 +318,13 @@ struct STimings int32 HDMAInit; int32 HDMAStart; int32 NMITriggerPos; + int32 IRQTriggerCycles; int32 WRAMRefreshPos; int32 RenderPos; bool8 InterlaceField; int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly. int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly. - int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode. + int32 IRQPendCount; // This value is just a hack. int32 APUSpeedup; bool8 APUAllowTimeOverflow; }; @@ -405,12 +397,8 @@ struct SSettings char CartBName[PATH_MAX + 1]; bool8 DisableGameSpecificHacks; - bool8 ShutdownMaster; - bool8 Shutdown; bool8 BlockInvalidVRAMAccessMaster; bool8 BlockInvalidVRAMAccess; - bool8 DisableIRQ; - bool8 DisableHDMA; int32 HDMATimingHack; bool8 ForcedPause;