From df7be8626c111615fe35564bff6b195374fc5a32 Mon Sep 17 00:00:00 2001 From: dborth Date: Tue, 2 Nov 2010 19:14:13 +0000 Subject: [PATCH] Added SA-1 NMI and fixed its override mode. (zones) --- source/snes9x/cpuexec.cpp | 1195 +++--- source/snes9x/cpuops.cpp | 8045 +++++++++++++++++++------------------ source/snes9x/sa1.cpp | 2274 ++++++----- source/snes9x/sa1cpu.cpp | 602 +-- 4 files changed, 6064 insertions(+), 6052 deletions(-) diff --git a/source/snes9x/cpuexec.cpp b/source/snes9x/cpuexec.cpp index 1b9d892..0d372e4 100644 --- a/source/snes9x/cpuexec.cpp +++ b/source/snes9x/cpuexec.cpp @@ -1,597 +1,598 @@ -/*********************************************************************************** - 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 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 + + +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 +} + diff --git a/source/snes9x/cpuops.cpp b/source/snes9x/cpuops.cpp index ea8d865..e67a869 100644 --- a/source/snes9x/cpuops.cpp +++ b/source/snes9x/cpuops.cpp @@ -1,4018 +1,4027 @@ -/*********************************************************************************** - 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) - S9xTraceMessage("*** IRQ"); -#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) - S9xTraceMessage("*** NMI"); -#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] & 0x20)) - { - OpenBus = Memory.FillRAM[0x220d]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFEA); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } - else - { - PushWE(Registers.PCw); - S9xPackStatus(); - PushBE(Registers.PL); - OpenBus = Registers.PL; - ClearDecimal(); - SetIRQ(); - - #ifdef SA1_OPCODES - OpenBus = Memory.FillRAM[0x2206]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); - #else - if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) - { - OpenBus = Memory.FillRAM[0x220d]; - AddCycles(2 * SLOW_ONE_CYCLE); - S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); - } - else - { - uint16 addr = S9xGetWord(0xFFFA); - OpenBus = addr >> 8; - S9xSetPCBase(addr); - } - #endif - } -} - -/* 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) { } +#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 } +}; + diff --git a/source/snes9x/sa1.cpp b/source/snes9x/sa1.cpp index f8d8892..c02839c 100644 --- a/source/snes9x/sa1.cpp +++ b/source/snes9x/sa1.cpp @@ -1,1138 +1,1136 @@ -/*********************************************************************************** - 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; - #ifdef DEBUGGER - printf("###SA1 NMI\n"); - #endif - if (Memory.FillRAM[0x220a] & 0x10) - { - // - } - } - - break; - - case 0x2201: - if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80)) - S9xSetIRQ(SA1_IRQ_SOURCE); - - if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20)) - S9xSetIRQ(SA1_DMA_IRQ_SOURCE); - - break; - - case 0x2202: - if (byte & 0x80) - { - Memory.FillRAM[0x2300] &= ~0x80; - S9xClearIRQ(SA1_IRQ_SOURCE); - } - - if (byte & 0x20) - { - Memory.FillRAM[0x2300] &= ~0x20; - S9xClearIRQ(SA1_DMA_IRQ_SOURCE); - } - - break; - - case 0x2203: - //printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8)); - break; - - case 0x2204: - //printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]); - break; - - case 0x2205: - //printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8)); - break; - - case 0x2206: - //printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]); - break; - - case 0x2207: - //printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8)); - break; - - case 0x2208: - //printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]); - break; - - case 0x2209: - Memory.FillRAM[0x2209] = byte; - - if (byte & 0x80) - Memory.FillRAM[0x2300] |= 0x80; - - if (byte & Memory.FillRAM[0x2201] & 0x80) - S9xSetIRQ(SA1_IRQ_SOURCE); - - break; - - case 0x220a: - if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= TIMER_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20)) - { - SA1.Flags |= IRQ_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - //SA1.Executing = !SA1.Waiting; - } - - if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10)) - { - #ifdef DEBUGGER - printf("###SA1 NMI\n"); - #endif - } - - break; - - case 0x220b: - if (byte & 0x80) - { - SA1.IRQActive &= ~SNES_IRQ_SOURCE; - Memory.FillRAM[0x2301] &= ~0x80; - } - - if (byte & 0x40) - { - SA1.IRQActive &= ~TIMER_IRQ_SOURCE; - Memory.FillRAM[0x2301] &= ~0x40; - } - - if (byte & 0x20) - { - SA1.IRQActive &= ~DMA_IRQ_SOURCE; - Memory.FillRAM[0x2301] &= ~0x20; - } - - if (byte & 0x10) // Clear NMI - Memory.FillRAM[0x2301] &= ~0x10; - - if (!SA1.IRQActive) - SA1.Flags &= ~IRQ_FLAG; - - break; - - case 0x220c: - //printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8)); - break; - - case 0x220d: - //printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]); - break; - - case 0x220e: - //printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8)); - break; - - case 0x220f: - //printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]); - break; - - case 0x2210: - #if 0 - printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); - printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); - printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); - #endif - break; - - case 0x2211: - //printf("Timer reset\n"); - break; - - case 0x2212: - //printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8)); - break; - - case 0x2213: - //printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]); - break; - - case 0x2214: - //printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8)); - break; - - case 0x2215: - //printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]); - break; - - case 0x2220: - case 0x2221: - case 0x2222: - case 0x2223: - //printf("MMC: %02x\n", byte); - S9xSetSA1MemMap(address - 0x2220, byte); - break; - - case 0x2224: - //printf("BWRAM image SNES %02x -> 0x6000\n", byte); - Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; - break; - - case 0x2225: - //printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]); - if (byte != Memory.FillRAM[0x2225]) - S9xSA1SetBWRAMMemMap(byte); - break; - - case 0x2226: - //printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2227: - //printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); - break; - - case 0x2228: - //printf("BW-RAM write protect area %02x\n", byte); - break; - - case 0x2229: - //printf("I-RAM SNES write protect area %02x\n", byte); - break; - - case 0x222a: - //printf("I-RAM SA1 write protect area %02x\n", byte); - break; - - case 0x2230: - #if 0 - printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); - printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); - printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); - printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); - printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); - printf("DMA source %s\n", DMAsource[byte & 3]); - #endif - break; - - case 0x2231: - if (byte & 0x80) - SA1.in_char_dma = FALSE; - #if 0 - printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); - printf("DMA colour mode %d\n", byte & 3); - printf("virtual VRAM width %d\n", (byte >> 2) & 7); - #endif - break; - - case 0x2232: - case 0x2233: - case 0x2234: - Memory.FillRAM[address] = byte; - #if 0 - printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16)); - #endif - break; - - case 0x2235: - Memory.FillRAM[0x2235] = byte; - break; - - case 0x2236: - Memory.FillRAM[0x2236] = byte; - - if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM - S9xSA1DMA(); - else - if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) - { - Memory.FillRAM[0x2300] |= 0x20; - if (Memory.FillRAM[0x2201] & 0x20) - S9xSetIRQ(SA1_DMA_IRQ_SOURCE); - SA1.in_char_dma = TRUE; - } - - break; - - case 0x2237: - Memory.FillRAM[0x2237] = byte; - - if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM - S9xSA1DMA(); - #if 0 - printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16)); - #endif - break; - - case 0x2238: - case 0x2239: - Memory.FillRAM[address] = byte; - #if 0 - printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8)); - #endif - break; - - case 0x223f: - //printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); - SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; - break; - - case 0x2240: - case 0x2241: - case 0x2242: - case 0x2243: - case 0x2244: - case 0x2245: - case 0x2246: - case 0x2247: - case 0x2248: - case 0x2249: - case 0x224a: - case 0x224b: - case 0x224c: - case 0x224d: - case 0x224e: - #if 0 - if (!(SA1.Flags & TRACE_FLAG)) - { - TraceSA1(); - Trace(); - } - #endif - Memory.FillRAM[address] = byte; - break; - - case 0x224f: - Memory.FillRAM[0x224f] = byte; - - if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled - { - memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16); - SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; - if ((SA1.in_char_dma & 3) == 0) - S9xSA1CharConv2(); - } - - break; - - case 0x2250: - if (byte & 2) - SA1.sum = 0; - SA1.arithmetic_op = byte & 3; - break; - - case 0x2251: - SA1.op1 = (SA1.op1 & 0xff00) | byte; - break; - - case 0x2252: - SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); - break; - - case 0x2253: - SA1.op2 = (SA1.op2 & 0xff00) | byte; - break; - - case 0x2254: - SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); - - switch (SA1.arithmetic_op) - { - case 0: // multiply - SA1.sum = SA1.op1 * SA1.op2; - break; - - case 1: // divide - if (SA1.op2 == 0) - SA1.sum = SA1.op1 << 16; - else - SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); - break; - - case 2: // cumulative sum - default: - SA1.sum += SA1.op1 * SA1.op2; - if (SA1.sum & ((int64) 0xffffff << 32)) - SA1.overflow = TRUE; - break; - } - - break; - - case 0x2258: // Variable bit-field length/auto inc/start. - Memory.FillRAM[0x2258] = byte; - S9xSA1ReadVariableLengthData(TRUE, FALSE); - return; - - case 0x2259: // Variable bit-field start address - case 0x225a: - case 0x225b: - Memory.FillRAM[address] = byte; - // XXX: ??? - SA1.variable_bit_pos = 0; - S9xSA1ReadVariableLengthData(FALSE, TRUE); - return; - - default: - //printf("W: %02x->%04x\n", byte, address); - break; - } - - if (address >= 0x2200 && address <= 0x22ff) - Memory.FillRAM[address] = byte; -} - -static void S9xSA1CharConv2 (void) -{ - uint32 dest = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8); - uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; - int depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; - int bytes_per_char = 8 * depth; - uint8 *p = &Memory.FillRAM[0x3000] + (dest & 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 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; + } +} + diff --git a/source/snes9x/sa1cpu.cpp b/source/snes9x/sa1cpu.cpp index dd79509..648266c 100644 --- a/source/snes9x/sa1cpu.cpp +++ b/source/snes9x/sa1cpu.cpp @@ -1,299 +1,303 @@ -/*********************************************************************************** - 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 0 - if (SA1.Flags & NMI_FLAG) - { - SA1.Flags &= ~NMI_FLAG; - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; - } - - S9xSA1Opcode_NMI(); - } -#endif - - if (SA1.Flags & IRQ_FLAG) - { - if (SA1.IRQActive) - { - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1Registers.PCw++; - } - - if (!SA1CheckFlag(IRQ)) - S9xSA1Opcode_IRQ(); - } - else - SA1.Flags &= ~IRQ_FLAG; - } - - for (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 + +//#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)(); + } +} +