⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpuexec.cpp

📁 著名SFC模拟器Snes9x的源代码。
💻 CPP
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and *                           Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code  * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and *                           Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */#include "snes9x.h"#include "memmap.h"#include "cpuops.h"#include "ppu.h"#include "cpuexec.h"#include "debug.h"#include "snapshot.h"#include "gfx.h"#include "missing.h"#include "apu.h"#include "dma.h"#include "fxemu.h"#include "sa1.h"void S9xMainLoop (void){    for (;;)    {	APU_EXECUTE ();	if (CPU.Flags)	{	    if (CPU.Flags & NMI_FLAG)	    {		if (--CPU.NMICycleCount == 0)		{		    CPU.Flags &= ~NMI_FLAG;		    if (CPU.WaitingForInterrupt)		    {			CPU.WaitingForInterrupt = FALSE;			CPU.PC++;		    }		    S9xOpcode_NMI ();		}	    }#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	}#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) ();		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;    }    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++;    }}void S9xClearIRQ (uint32 source){    CLEAR_IRQ_SOURCE (source);}void S9xDoHBlankProcessing (){#ifdef CPU_SHUTDOWN    CPU.WaitCounter++;#endif    switch (CPU.WhichEvent)    {    case HBLANK_START_EVENT:	if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)	    IPPU.HDMA = S9xDoHDMA (IPPU.HDMA);	break;    case HBLANK_END_EVENT:	S9xSuperFXExec ();#ifndef STORM	if (Settings.SoundSync)	    S9xGenerateSound ();#endif	CPU.Cycles -= Settings.H_Max;	if (IAPU.APUExecuting)	    APU.Cycles -= Settings.H_Max;	else	    APU.Cycles = 0;	CPU.NextEvent = -1;	ICPU.Scanline++;	if (++CPU.V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))	{	    PPU.OAMAddr = PPU.SavedOAMAddr;	    PPU.OAMFlip = 0;	    CPU.V_Counter = 0;	    CPU.NMIActive = FALSE;	    ICPU.Frame++;	    PPU.HVBeamCounterLatched = 0;	    CPU.Flags |= SCAN_KEYS_FLAG;	    S9xStartHDMA ();	}	if (PPU.VTimerEnabled && !PPU.HTimerEnabled &&	    CPU.V_Counter == PPU.IRQVBeamPos)	{	    S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE);	}	if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)	{	    // Start of V-blank	    S9xEndScreenRefresh ();	    PPU.FirstSprite = 0;	    IPPU.HDMA = 0;	    // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.	    missing.dma_this_frame = 0;	    IPPU.MaxBrightness = PPU.Brightness;	    PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1;	    Memory.FillRAM[0x4210] = 0x80;	    if (Memory.FillRAM[0x4200] & 0x80)	    {		CPU.NMIActive = TRUE;		CPU.Flags |= NMI_FLAG;		CPU.NMICycleCount = CPU.NMITriggerPoint;	    }#ifdef OLD_SNAPSHOT_CODE	    if (CPU.Flags & SAVE_SNAPSHOT_FLAG)	    {		CPU.Flags &= ~SAVE_SNAPSHOT_FLAG;		Registers.PC = CPU.PC - CPU.PCBase;		S9xPackStatus ();		S9xAPUPackStatus ();		Snapshot (NULL);	    }#endif        }	if (CPU.V_Counter == PPU.ScreenHeight + 3)	    S9xUpdateJoypads ();	if (CPU.V_Counter == FIRST_VISIBLE_LINE)	{	    Memory.FillRAM[0x4210] = 0;	    CPU.Flags &= ~NMI_FLAG;	    S9xStartScreenRefresh ();	}	if (CPU.V_Counter >= FIRST_VISIBLE_LINE &&	    CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE)	{	    RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE);	}	// Use TimerErrorCounter to skip update of SPC700 timers once	// every 128 updates. Needed because this section of code is called	// once every emulated 63.5 microseconds, which coresponds to	// 15.750KHz, but the SPC700 timers need to be updated at multiples	// of 8KHz, hence the error correction.//	IAPU.TimerErrorCounter++;//	if (IAPU.TimerErrorCounter >= )//	    IAPU.TimerErrorCounter = 0;//	else	{	    if (APU.TimerEnabled [2])	    {		APU.Timer [2] += 4;		while (APU.Timer [2] >= APU.TimerTarget [2])		{		    IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf;		    APU.Timer [2] -= APU.TimerTarget [2];#ifdef SPC700_SHUTDOWN				    IAPU.WaitCounter++;		    IAPU.APUExecuting = TRUE;#endif				}	    }	    if (CPU.V_Counter & 1)	    {		if (APU.TimerEnabled [0])		{		    APU.Timer [0]++;		    if (APU.Timer [0] >= APU.TimerTarget [0])		    {			IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf;			APU.Timer [0] = 0;#ifdef SPC700_SHUTDOWN					IAPU.WaitCounter++;			IAPU.APUExecuting = TRUE;#endif		    		    }		}		if (APU.TimerEnabled [1])		{		    APU.Timer [1]++;		    if (APU.Timer [1] >= APU.TimerTarget [1])		    {			IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf;			APU.Timer [1] = 0;#ifdef SPC700_SHUTDOWN					IAPU.WaitCounter++;			IAPU.APUExecuting = TRUE;#endif		    		    }		}	    }	}	break;    case HTIMER_BEFORE_EVENT:    case HTIMER_AFTER_EVENT:	if (PPU.HTimerEnabled &&	    (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos))	{	    S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE);	}	break;    }    S9xReschedule ();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -