uint8 asm_S9xGetByte(uint32 Address) { #ifdef __debug_c_io__ printf("gb\n"); #endif return S9xGetByte(Address); }
static uint8 dreadb(uint32 addr) { if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) { //$[00-3f|80-bf]:[2000-5fff] //do not read MMIO registers within debugger return 0x00; } return S9xGetByte(addr, true); }
static INLINE bool8 HDMAReadLineCount (int d) { /* CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. */ uint8 line; line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); CPU.Cycles += SLOW_ONE_CYCLE; DMA[d].LineCount = 128; if (!line) { DMA[d].Repeat = FALSE; if (DMA[d].HDMAIndirectAddressing) { if (PPU.HDMA & (0xfe << d)) { DMA[d].Address++; CPU.Cycles += (SLOW_ONE_CYCLE << 1); } else CPU.Cycles += SLOW_ONE_CYCLE; DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address, WRAP_NONE); DMA[d].Address++; } DMA[d].Address++; HDMAMemPointers[d] = NULL; return (FALSE); } else if (line == 0x80) DMA[d].Repeat = TRUE; else { DMA[d].Repeat = !(line & 0x80); DMA[d].LineCount = line & 0x7f; } DMA[d].Address++; DMA[d].DoTransfer = TRUE; if (DMA[d].HDMAIndirectAddressing) { CPU.Cycles += (SLOW_ONE_CYCLE << 1); DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address, WRAP_NONE); DMA[d].Address += 2; HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); } else HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address); return (TRUE); }
static uint8 S9xGetByteFree (uint32 address) { int32 Cycles = CPU.Cycles; int32 NextEvent = CPU.NextEvent; uint8 byte; CPU.NextEvent = 0x7FFFFFFF; byte = S9xGetByte(address); CPU.NextEvent = NextEvent; CPU.Cycles = Cycles; return (byte); }
void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte) { if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0])) { Cheat.c [Cheat.num_cheats].address = address; Cheat.c [Cheat.num_cheats].byte = byte; Cheat.c [Cheat.num_cheats].enabled = TRUE; if (save_current_value) { Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address, &CPU); Cheat.c [Cheat.num_cheats].saved = TRUE; } Cheat.num_cheats++; } }
void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte) { if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0])) { Cheat.c [Cheat.num_cheats].address = address; Cheat.c [Cheat.num_cheats].byte = byte; #ifdef __MACOSX__ Cheat.c [Cheat.num_cheats].enabled = enable; #else Cheat.c [Cheat.num_cheats].enabled = TRUE; #endif if (save_current_value) { Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address); Cheat.c [Cheat.num_cheats].saved = TRUE; } Cheat.num_cheats++; } }
void S9xMainLoop (void) { for (;;) { APU_EXECUTE(); 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 CHECK_SOUND(); if (CPU.Flags & IRQ_PENDING_FLAG) { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } if (CPU.IRQActive && !Settings.DisableIRQ) { if (!CheckFlag(IRQ)) S9xOpcode_IRQ(); } else CPU.Flags &= ~IRQ_PENDING_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; 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 = GetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); if (oldPCBase!=CPU.PCBase || (Registers.PCw&~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) Opcodes = S9xOpcodesSlow; } Registers.PCw++; (*Opcodes[Op].S9xOpcode)(); S9xUpdateAPUTimer(); if (SA1.Executing) S9xSA1MainLoop(); if (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } S9xPackStatus(); APURegisters.PC = IAPU.PC - IAPU.RAM; S9xAPUPackStatus(); if (CPU.Flags & SCAN_KEYS_FLAG) { #ifdef DEBUGGER if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) #endif S9xSyncSpeed(); CPU.Flags &= ~SCAN_KEYS_FLAG; } }
void S9xMainLoop(void) { int i; for (;;) { for (i=0;i<32;i++) render_snescast(); if (CPU.NMILine) { if (Timings.NMITriggerPos <= CPU.Cycles) { CPU.NMILine = FALSE; Timings.NMITriggerPos = 0xffff; if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } S9xOpcode_NMI(); } } if (CPU.IRQTransition || CPU.IRQExternal) { if (CPU.IRQPending) CPU.IRQPending--; else { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } CPU.IRQTransition = FALSE; CPU.IRQPending = Timings.IRQPendCount; if (!CheckFlag(IRQ)) S9xOpcode_IRQ(); } } #ifdef DEBUGGER if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) { for (int Break = 0; Break != 6; Break++) { if (S9xBreakpoint[Break].Enabled && S9xBreakpoint[Break].Bank == Registers.PB && S9xBreakpoint[Break].Address == Registers.PCw) { if (S9xBreakpoint[Break].Enabled == 2) S9xBreakpoint[Break].Enabled = TRUE; else CPU.Flags |= DEBUG_MODE_FLAG; } } } if (CPU.Flags & DEBUG_MODE_FLAG) break; if (CPU.Flags & TRACE_FLAG) S9xTrace(); if (CPU.Flags & SINGLE_STEP_FLAG) { CPU.Flags &= ~SINGLE_STEP_FLAG; CPU.Flags |= DEBUG_MODE_FLAG; } #endif if (CPU.Flags & SCAN_KEYS_FLAG) break; register uint8 Op; register struct SOpcodes *Opcodes; if (CPU.PCBase) { Op = CPU.PCBase[Registers.PCw]; CPU.PrevCycles = CPU.Cycles; CPU.Cycles += CPU.MemSpeed; S9xCheckInterrupts(); Opcodes = ICPU.S9xOpcodes; } else { Op = S9xGetByte(Registers.PBPC); OpenBus = Op; Opcodes = S9xOpcodesSlow; } if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) { uint8 *oldPCBase = CPU.PCBase; CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) Opcodes = S9xOpcodesSlow; } Registers.PCw++; (*Opcodes[Op].S9xOpcode)(); if (Settings.SA1) S9xSA1MainLoop(); } S9xPackStatus(); if (CPU.Flags & SCAN_KEYS_FLAG) { #ifdef DEBUGGER if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) #endif S9xSyncSpeed(); CPU.Flags &= ~SCAN_KEYS_FLAG; } }
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 S9xMainLoop (void) { #define CHECK_FOR_IRQ_CHANGE() \ if (Timings.IRQFlagChanging) \ { \ if (Timings.IRQFlagChanging & IRQ_TRIGGER_NMI) \ { \ CPU.NMIPending = TRUE; \ Timings.NMITriggerPos = CPU.Cycles + 6; \ } \ if (Timings.IRQFlagChanging & IRQ_CLEAR_FLAG) \ ClearIRQ(); \ else if (Timings.IRQFlagChanging & IRQ_SET_FLAG) \ SetIRQ(); \ Timings.IRQFlagChanging = IRQ_NONE; \ } if (CPU.Flags & SCAN_KEYS_FLAG) { CPU.Flags &= ~SCAN_KEYS_FLAG; S9xMovieUpdate(); } for (;;) { if (CPU.NMIPending) { #ifdef DEBUGGER if (Settings.TraceHCEvent) S9xTraceFormattedMessage ("Comparing %d to %d\n", Timings.NMITriggerPos, CPU.Cycles); #endif if (Timings.NMITriggerPos <= CPU.Cycles) { CPU.NMIPending = FALSE; Timings.NMITriggerPos = 0xffff; if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2; while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } CHECK_FOR_IRQ_CHANGE(); S9xOpcode_NMI(); } } if (CPU.Cycles >= Timings.NextIRQTimer) { #ifdef DEBUGGER S9xTraceMessage ("Timer triggered\n"); #endif S9xUpdateIRQPositions(false); CPU.IRQLine = TRUE; } if (CPU.IRQLine || CPU.IRQExternal) { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2; while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } if (!CheckFlag(IRQ)) { /* The flag pushed onto the stack is the new value */ CHECK_FOR_IRQ_CHANGE(); S9xOpcode_IRQ(); } } /* Change IRQ flag for instructions that set it only on last cycle */ CHECK_FOR_IRQ_CHANGE(); #ifdef DEBUGGER if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) { for (int Break = 0; Break != 6; Break++) { if (S9xBreakpoint[Break].Enabled && S9xBreakpoint[Break].Bank == Registers.PB && S9xBreakpoint[Break].Address == Registers.PCw) { if (S9xBreakpoint[Break].Enabled == 2) S9xBreakpoint[Break].Enabled = TRUE; else CPU.Flags |= DEBUG_MODE_FLAG; } } } if (CPU.Flags & DEBUG_MODE_FLAG) break; if (CPU.Flags & TRACE_FLAG) S9xTrace(); if (CPU.Flags & SINGLE_STEP_FLAG) { CPU.Flags &= ~SINGLE_STEP_FLAG; CPU.Flags |= DEBUG_MODE_FLAG; } #endif if (CPU.Flags & SCAN_KEYS_FLAG) { #ifdef DEBUGGER if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) #endif { S9xSyncSpeed(); } break; } uint8 Op; struct SOpcodes *Opcodes; 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 (Settings.SA1) S9xSA1MainLoop(); } S9xPackStatus(); }
void S9xMainLoop (void) { static int loop_times=0; int loops2=0; //printf("Enter S9xMainLoop %d %x\n", loop_times, Registers.PCw); for (;;) { loops2++; //printf("S9xMainLoop %d for loop %d flags=%d\n", loop_times, loops2, CPU.Flags); if (CPU.NMILine) { //printf("case 1\n"); if (Timings.NMITriggerPos <= CPU.Cycles) { CPU.NMILine = FALSE; Timings.NMITriggerPos = 0xffff; if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } S9xOpcode_NMI(); } } if (CPU.IRQTransition || CPU.IRQExternal) { //printf("case 2\n"); if (CPU.IRQPending) CPU.IRQPending--; else { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } CPU.IRQTransition = FALSE; CPU.IRQPending = Timings.IRQPendCount; if (!CheckFlag(IRQ)) S9xOpcode_IRQ(); } } #ifdef DEBUGGER if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) { for (int Break = 0; Break != 6; Break++) { if (S9xBreakpoint[Break].Enabled && S9xBreakpoint[Break].Bank == Registers.PB && S9xBreakpoint[Break].Address == Registers.PCw) { if (S9xBreakpoint[Break].Enabled == 2) S9xBreakpoint[Break].Enabled = TRUE; else CPU.Flags |= DEBUG_MODE_FLAG; } } } if (CPU.Flags & DEBUG_MODE_FLAG) break; if (CPU.Flags & TRACE_FLAG) S9xTrace(); if (CPU.Flags & SINGLE_STEP_FLAG) { CPU.Flags &= ~SINGLE_STEP_FLAG; CPU.Flags |= DEBUG_MODE_FLAG; } #endif if (CPU.Flags & SCAN_KEYS_FLAG) break; register uint8 Op; register Opcode *Opcodes; if (CPU.PCBase) { Op = CPU.PCBase[Registers.PCw]; CPU.PrevCycles = CPU.Cycles; CPU.Cycles += CPU.MemSpeed; S9xCheckInterrupts(); Opcodes = ICPU.S9xOpcodes; //printf("case 3 %x %x %d %d\n", Registers.PCw, Op, CPU.PrevCycles, CPU.Cycles); } else { //printf("case 4\n"); Op = S9xGetByte(Registers.PBPC); OpenBus = Op; Opcodes = S9xOpcodesSlow; } if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) { uint8 *oldPCBase = CPU.PCBase; //printf("case 5\n"); CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) Opcodes = S9xOpcodesSlow; } //printf("case 3.1 %d\n", CPU.Cycles); Registers.PCw++; Opcodes[Op](); //printf("case 3.2 %d\n", CPU.Cycles); if (Settings.SA1){ //printf("case 6\n"); S9xSA1MainLoop(); } } S9xPackStatus(); if (CPU.Flags & SCAN_KEYS_FLAG) { //printf("case 7\n"); #ifdef DEBUGGER if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) #endif S9xSyncSpeed(); CPU.Flags &= ~SCAN_KEYS_FLAG; } //printf("Exit S9xMainLoop %d loops2=%d\n", loop_times++, loops2); }
static uint8 S9xDoHDMA (uint8 byte) { uint8 mask; uint32 ShiftedIBank; uint16 IAddr; bool8 temp; int32 tmpch; int d; struct SDMA *p; p = &DMA[0]; d = 0; CPU.InHDMA = TRUE; CPU.InDMAorHDMA = TRUE; CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; temp = CPU.InWRAMDMAorHDMA; tmpch = CPU.CurrentDMAorHDMAChannel; /* XXX: Not quite right... */ CPU.Cycles += Timings.DMACPUSync; for ( mask = 1; mask; mask <<= 1, p++, d++) { if (byte & mask) { CPU.InWRAMDMAorHDMA = FALSE; CPU.CurrentDMAorHDMAChannel = d; if (p->HDMAIndirectAddressing) { ShiftedIBank = (p->IndirectBank << 16); IAddr = p->IndirectAddress; } else { ShiftedIBank = (p->ABank << 16); IAddr = p->Address; } if (!HDMAMemPointers[d]) HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr); if (p->DoTransfer) { /* XXX: Hack for Uniracers, because we don't understand OAM Address Invalidation */ if (p->BAddress == 0x04 && SNESGameFixes.Uniracers) { PPU.OAMAddr = 0x10c; PPU.OAMFlip = 0; } if (!p->ReverseTransfer) { if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) { /* HDMA REALLY-SLOW PATH */ HDMAMemPointers[d] = NULL; #define DOBYTE(Addr, RegOff) \ CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16) (Addr))), 0x2100 + p->BAddress + (RegOff)); DOBYTE(IAddr, 0); CPU.Cycles += SLOW_ONE_CYCLE; switch (p->TransferMode) { case 0: break; case 5: DOBYTE(IAddr + 1, 1); CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr + 2, 0); CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr + 3, 1); CPU.Cycles += SLOW_ONE_CYCLE; break; case 1: DOBYTE(IAddr + 1, 1); CPU.Cycles += SLOW_ONE_CYCLE; break; case 2: case 6: DOBYTE(IAddr + 1, 0); CPU.Cycles += SLOW_ONE_CYCLE; break; case 3: case 7: DOBYTE(IAddr + 1, 0); CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr + 2, 1); CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr + 3, 1); CPU.Cycles += SLOW_ONE_CYCLE; break; case 4: DOBYTE(IAddr + 1, 1); CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr + 2, 2); CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr + 3, 3); CPU.Cycles += SLOW_ONE_CYCLE; break; } #undef DOBYTE } else { CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && IAddr < 0x2000)); if (!HDMAMemPointers[d]) { /* HDMA SLOW PATH */ uint32 Addr = ShiftedIBank + IAddr; switch (p->TransferMode) { case 0: S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; break; case 5: S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; Addr += 2; /* fall through */ case 1: S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; break; case 2: case 6: S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; break; case 3: case 7: S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; break; case 4: S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; break; } } else { /* HDMA FAST PATH */ switch (p->TransferMode) { case 0: S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; break; case 5: S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; HDMAMemPointers[d] += 2; /* fall through */ case 1: S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; HDMAMemPointers[d] += 2; break; case 2: case 6: S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; HDMAMemPointers[d] += 2; break; case 3: case 7: S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; HDMAMemPointers[d] += 4; break; case 4: S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); CPU.Cycles += SLOW_ONE_CYCLE; HDMAMemPointers[d] += 4; break; } } } } if (p->HDMAIndirectAddressing) p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; else p->Address += HDMA_ModeByteCounts[p->TransferMode]; } p->DoTransfer = !p->Repeat; if (!--p->LineCount) { if (!HDMAReadLineCount(d)) { byte &= ~mask; PPU.HDMAEnded |= mask; p->DoTransfer = FALSE; continue; } } else CPU.Cycles += SLOW_ONE_CYCLE; } } CPU.InHDMA = FALSE; CPU.InDMAorHDMA = CPU.InDMA; CPU.InWRAMDMAorHDMA = temp; CPU.CurrentDMAorHDMAChannel = tmpch; return (byte); }
void S9xMainLoop (void) { do { register uint8 Op; register struct SOpcodes *Opcodes; /* Speedhack - skip idle loop if exists. */ if (idle_loop_elimination_enable && (Registers.PBPC == idle_loop_target_pc) && (CPU.Cycles < CPU.NextEvent)) CPU.Cycles = CPU.NextEvent; 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(); } } if (CPU.Flags & IRQ_FLAG) { if (CPU.IRQPending) CPU.IRQPending--; /* FIXME: In case of IRQ during WRAM refresh */ else { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } if (CPU.IRQActive) { /* in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared. */ if (!CheckFlag(IRQ)) S9xOpcode_IRQ(); } else CPU.Flags &= ~IRQ_FLAG; } } if (CPU.Flags & SCAN_KEYS_FLAG) break; } Opcodes = S9xOpcodesSlow; 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; } if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) { uint8 *oldPCBase = CPU.PCBase; CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) Opcodes = S9xOpcodesSlow; } Registers.PCw++; (*Opcodes[Op].S9xOpcode)(); if (Settings.SA1) S9xSA1MainLoop(); #if (S9X_ACCURACY_LEVEL <= 2) while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); #endif }while(1); S9xPackStatus(); if (CPU.Flags & SCAN_KEYS_FLAG) { CPU.Flags &= ~SCAN_KEYS_FLAG; } }