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) { for (;;) { #ifdef DEBUG_MAXCOUNT CPU.GlobalLoopCount++; if(Settings.MaxCount && CPU.GlobalLoopCount == Settings.MaxCount) { fprintf(stderr, "Max loop count reached: %ld \n", Settings.MaxCount); S9xExit(); } #endif APU_EXECUTE (); if (CPU.Flags) { if (CPU.Flags & NMI_FLAG) { if (--CPU.NMICycleCount == 0) { CPU.Flags &= ~NMI_FLAG; if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; CPU.PC++; } S9xOpcode_NMI (); } } #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 == CPU.PC - CPU.PCBase) { 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.IRQCycleCount == 0) { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; CPU.PC++; } if (CPU.IRQActive && !Settings.DisableIRQ) { if (!CheckFlag (IRQ)) S9xOpcode_IRQ (); } else CPU.Flags &= ~IRQ_PENDING_FLAG; } else { if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) CPU.IRQCycleCount=1; } } #ifdef DEBUGGER if (CPU.Flags & DEBUG_MODE_FLAG) break; #endif if (CPU.Flags & SCAN_KEYS_FLAG) break; #ifdef DEBUGGER 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.PCAtOpcodeStart = CPU.PC; #endif CPU.Cycles += CPU.MemSpeed; (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); S9xUpdateAPUTimer(); if (SA1.Executing) S9xSA1MainLoop (); DO_HBLANK_CHECK(); } Registers.PC = CPU.PC - CPU.PCBase; 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; } #ifdef DETECT_NASTY_FX_INTERLEAVE if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) { CPU.TriedInterleavedMode2 = TRUE; CPU.BRKTriggered = FALSE; S9xDeinterleaveMode2 (); } #endif }
void S9xMainLoop (void) { struct SCPUState *cpu = &CPU; struct SICPU *icpu = &ICPU; struct SIAPU *iapu = &IAPU; struct SAPU *apu = &APU; struct SRegisters *reg = &Registers; struct SAPURegisters *areg = &APURegisters; for (;;) { APU_EXECUTE (); if (cpu->Flags) { if (cpu->Flags & NMI_FLAG) { if (--cpu->NMICycleCount == 0) { cpu->Flags &= ~NMI_FLAG; if (cpu->WaitingForInterrupt) { cpu->WaitingForInterrupt = FALSE; ++cpu->PC; } S9xOpcode_NMI (); } } #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 == cpu->PC - cpu->PCBase) { 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->IRQCycleCount == 0) { if (cpu->WaitingForInterrupt) { cpu->WaitingForInterrupt = FALSE; cpu->PC++; } if (cpu->IRQActive) // if (cpu->IRQActive && !Settings.DisableIRQ) { if (!CHECKFLAG (IRQ)) S9xOpcode_IRQ (); } else cpu->Flags &= ~IRQ_PENDING_FLAG; } else cpu->IRQCycleCount--; } #ifdef DEBUGGER if (cpu->Flags & DEBUG_MODE_FLAG) break; #endif if (cpu->Flags & SCAN_KEYS_FLAG) break; #ifdef DEBUGGER 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) #ifdef CPU_SHUTDOWN cpu->PCAtOpcodeStart = cpu->PC; #endif #ifdef VAR_CYCLES cpu->Cycles += cpu->MemSpeed; #else cpu->Cycles += icpu->Speed [*cpu->PC]; #endif (*icpu->S9xOpcodes [*cpu->PC++].S9xOpcode) (reg, icpu, cpu); #ifndef _ZAURUS if (SA1.Executing) S9xSA1MainLoop (); #endif DO_HBLANK_CHECK(); } // for(;;) Registers.PC = cpu->PC - cpu->PCBase; S9xPackStatus (); areg->PC = iapu->PC - iapu->RAM; S9xAPUPackStatus_OP (); if (cpu->Flags & SCAN_KEYS_FLAG) { #ifdef DEBUGGER if (!(cpu->Flags & FRAME_ADVANCE_FLAG)) #endif S9xSyncSpeed (); cpu->Flags &= ~SCAN_KEYS_FLAG; } #ifndef _ZAURUS if (cpu->BRKTriggered && Settings.SuperFX && !cpu->TriedInterleavedMode2) { cpu->TriedInterleavedMode2 = TRUE; cpu->BRKTriggered = FALSE; S9xDeinterleaveMode2 (); } #endif }
void S9xMainLoop (void) { if(ICPU.SavedAtOp) { ICPU.SavedAtOp = FALSE; Registers.PCw = CPU.PBPCAtOpcodeStart; if(CPU.PCBase) CPU.Cycles -= CPU.MemSpeed; goto doOp; } for (;;) { if (CPU.Flags) { 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_FLAG) { if (CPU.IRQPending) // FIXME: In case of IRQ during WRAM refresh CPU.IRQPending = 0; 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 doOp: 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 = 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)(); if(ICPU.SavedAtOp) { ICPU.SavedAtOp = false; continue; } S9xAPUExecute(); if (SA1.Executing) S9xSA1MainLoop(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } S9xPackStatus(); APURegisters.PC = IAPU.PC - IAPU.RAM; S9xAPUPackStatus(); if (CPU.Flags & SCAN_KEYS_FLAG) { #ifdef DEBUGGER if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) #endif S9xSyncSpeed(); CPU.Flags &= ~SCAN_KEYS_FLAG; } }
void S9xMainLoop (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu) { #else void S9xMainLoop (void) { struct SICPU * icpu = &ICPU; struct SCPUState * cpu = &CPU; struct SRegisters * reg = &Registers; #endif for (;;) { APU_EXECUTE (); if (CPU.Flags) { if (CPU.Flags & NMI_FLAG) { if (--CPU.NMICycleCount == 0) { CPU.Flags &= ~NMI_FLAG; if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; ++CPU.PC; } S9xOpcode_NMI (); } } #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 == CPU.PC - CPU.PCBase) { 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.IRQCycleCount == 0) { if (CPU.WaitingForInterrupt) { CPU.WaitingForInterrupt = FALSE; CPU.PC++; } if (CPU.IRQActive && !Settings.DisableIRQ) { if (!CHECKFLAG (IRQ)) S9xOpcode_IRQ (); } else CPU.Flags &= ~IRQ_PENDING_FLAG; } else CPU.IRQCycleCount--; } #ifdef DEBUGGER if (CPU.Flags & DEBUG_MODE_FLAG) break; #endif if (CPU.Flags & SCAN_KEYS_FLAG) break; #ifdef DEBUGGER 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) #ifdef CPU_SHUTDOWN CPU.PCAtOpcodeStart = CPU.PC; #endif #ifdef VAR_CYCLES CPU.Cycles += CPU.MemSpeed; #else CPU.Cycles += ICPU.Speed [*CPU.PC]; #endif (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (&Registers, &ICPU, &CPU); if (SA1.Executing) S9xSA1MainLoop (); DO_HBLANK_CHECK(); } // for(;;) Registers.PC = CPU.PC - CPU.PCBase; 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; } if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) { CPU.TriedInterleavedMode2 = TRUE; CPU.BRKTriggered = FALSE; S9xDeinterleaveMode2 (); } } void S9xSetIRQ (uint32 source) { CPU.IRQActive |= source; CPU.Flags |= IRQ_PENDING_FLAG; CPU.IRQCycleCount = 3; if (CPU.WaitingForInterrupt) { // Force IRQ to trigger immediately after WAI - // Final Fantasy Mystic Quest crashes without this. CPU.IRQCycleCount = 0; CPU.WaitingForInterrupt = FALSE; CPU.PC++; } }