707 lines
18 KiB
C++
707 lines
18 KiB
C++
#include "main.h"
|
|
#include "CPU.h"
|
|
#include "debugger.h"
|
|
|
|
//int NextInstruction, ManualPaused;
|
|
//int DlistCount, AlistCount;
|
|
//SYSTEM_TIMERS Timers;
|
|
//DWORD MemoryStack;
|
|
DWORD JumpToLocation;
|
|
|
|
void InitializeCPUCore ( void )
|
|
{
|
|
LARGE_INTEGER PerformanceFrequency;
|
|
|
|
BuildInterpreter();
|
|
CurrentFrame = 0;
|
|
|
|
QueryPerformanceFrequency(&PerformanceFrequency);
|
|
Frequency = PerformanceFrequency.QuadPart;
|
|
|
|
{
|
|
BYTE Country = *(ROM + 0x3D);
|
|
switch (Country)
|
|
{
|
|
case Germany: case french: case Italian:
|
|
case Europe: case Spanish: case Australia:
|
|
case X_PAL: case Y_PAL:
|
|
Timer_Initialize(50);
|
|
g_SystemType = SYSTEM_PAL;
|
|
break;
|
|
default:
|
|
Timer_Initialize(60);
|
|
g_SystemType = SYSTEM_NTSC;
|
|
break;
|
|
}
|
|
}
|
|
#ifndef EXTERNAL_RELEASE
|
|
LogOptions.GenerateLog = g_GenerateLog;
|
|
LoadLogOptions(&LogOptions, FALSE);
|
|
StartLog();
|
|
#endif
|
|
|
|
// switch (CPU_Type) {
|
|
// case CPU_Interpreter: StartInterpreterCPU(); break;
|
|
// case CPU_Recompiler: StartRecompilerCPU(); break;
|
|
// case CPU_SyncCores: StartRecompilerCPU(); break;
|
|
// default:
|
|
// DisplayError("Unhandled CPU %d",CPU_Type);
|
|
// }
|
|
// if (TargetInfo)
|
|
// {
|
|
// VirtualFree(TargetInfo,0,MEM_RELEASE);
|
|
// TargetInfo = NULL;
|
|
// }
|
|
|
|
}
|
|
|
|
int DelaySlotEffectsJump (DWORD JumpPC) {
|
|
OPCODE Command;
|
|
|
|
if (!r4300i_LW_VAddr(JumpPC, &Command.Hex)) { return TRUE; }
|
|
|
|
switch (Command.op) {
|
|
case R4300i_SPECIAL:
|
|
switch (Command.funct) {
|
|
case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(JumpPC,Command.rs,0);
|
|
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(JumpPC,Command.rs,31);
|
|
}
|
|
break;
|
|
case R4300i_REGIMM:
|
|
switch (Command.rt) {
|
|
case R4300i_REGIMM_BLTZ:
|
|
case R4300i_REGIMM_BGEZ:
|
|
case R4300i_REGIMM_BLTZL:
|
|
case R4300i_REGIMM_BGEZL:
|
|
case R4300i_REGIMM_BLTZAL:
|
|
case R4300i_REGIMM_BGEZAL:
|
|
return DelaySlotEffectsCompare(JumpPC,Command.rs,0);
|
|
}
|
|
break;
|
|
case R4300i_JAL:
|
|
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(JumpPC,31,0); break;
|
|
case R4300i_J: return FALSE;
|
|
case R4300i_BEQ:
|
|
case R4300i_BNE:
|
|
case R4300i_BLEZ:
|
|
case R4300i_BGTZ:
|
|
return DelaySlotEffectsCompare(JumpPC,Command.rs,Command.rt);
|
|
case R4300i_CP1:
|
|
switch (Command.fmt) {
|
|
case R4300i_COP1_BC:
|
|
switch (Command.ft) {
|
|
case R4300i_COP1_BC_BCF:
|
|
case R4300i_COP1_BC_BCT:
|
|
case R4300i_COP1_BC_BCFL:
|
|
case R4300i_COP1_BC_BCTL:
|
|
{
|
|
int EffectDelaySlot;
|
|
OPCODE NewCommand;
|
|
|
|
if (!r4300i_LW_VAddr(JumpPC + 4, &NewCommand.Hex)) { return TRUE; }
|
|
|
|
EffectDelaySlot = FALSE;
|
|
if (NewCommand.op == R4300i_CP1) {
|
|
if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30 ) {
|
|
EffectDelaySlot = TRUE;
|
|
}
|
|
if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30 ) {
|
|
EffectDelaySlot = TRUE;
|
|
}
|
|
}
|
|
return EffectDelaySlot;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case R4300i_BEQL:
|
|
case R4300i_BNEL:
|
|
case R4300i_BLEZL:
|
|
case R4300i_BGTZL:
|
|
return DelaySlotEffectsCompare(JumpPC,Command.rs,Command.rt);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void DoSomething ( void ) {
|
|
if (CPU_Action.CloseCPU) {
|
|
return;
|
|
}
|
|
|
|
if (CPU_Action.SoftReset)
|
|
{
|
|
CPU_Action.SoftReset = false;
|
|
|
|
ChangeTimer(SoftResetTimer,0x3000000);
|
|
ShowCFB();
|
|
FAKE_CAUSE_REGISTER |= CAUSE_IP4;
|
|
CheckInterrupts();
|
|
g_Plugins->Gfx()->SoftReset();
|
|
}
|
|
|
|
if (CPU_Action.GenerateInterrupt)
|
|
{
|
|
CPU_Action.GenerateInterrupt = FALSE;
|
|
MI_INTR_REG |= CPU_Action.InterruptFlag;
|
|
CPU_Action.InterruptFlag = 0;
|
|
CheckInterrupts();
|
|
}
|
|
if (CPU_Action.CheckInterrupts) {
|
|
CPU_Action.CheckInterrupts = FALSE;
|
|
CheckInterrupts();
|
|
}
|
|
if (CPU_Action.ProfileStartStop) {
|
|
CPU_Action.ProfileStartStop = FALSE;
|
|
ResetTimer();
|
|
}
|
|
if (CPU_Action.ProfileResetStats) {
|
|
CPU_Action.ProfileResetStats = FALSE;
|
|
ResetTimer();
|
|
}
|
|
if (CPU_Action.ProfileGenerateLogs) {
|
|
CPU_Action.ProfileGenerateLogs = FALSE;
|
|
GenerateProfileLog();
|
|
}
|
|
|
|
if (CPU_Action.DoInterrupt) {
|
|
CPU_Action.DoInterrupt = FALSE;
|
|
if (DoIntrException(FALSE) && !CPU_Action.InterruptExecuted)
|
|
{
|
|
CPU_Action.InterruptExecuted = TRUE;
|
|
ClearRecompCodeInitialCode();
|
|
}
|
|
}
|
|
|
|
if (CPU_Action.ChangeWindow) {
|
|
CPU_Action.ChangeWindow = FALSE;
|
|
ChangeFullScreenFunc();
|
|
}
|
|
|
|
if (CPU_Action.Pause) {
|
|
PauseExecution();
|
|
CPU_Action.Pause = FALSE;
|
|
}
|
|
if (CPU_Action.ChangePlugin) {
|
|
ChangePluginFunc();
|
|
CPU_Action.ChangePlugin = FALSE;
|
|
}
|
|
if (CPU_Action.GSButton) {
|
|
ApplyGSButtonCheats();
|
|
CPU_Action.GSButton = FALSE;
|
|
}
|
|
|
|
CPU_Action.DoSomething = FALSE;
|
|
|
|
if (CPU_Action.SaveState) {
|
|
//test if allowed
|
|
CPU_Action.SaveState = FALSE;
|
|
if (!Machine_SaveState()) {
|
|
CPU_Action.SaveState = TRUE;
|
|
CPU_Action.DoSomething = TRUE;
|
|
}
|
|
}
|
|
if (CPU_Action.RestoreState) {
|
|
CPU_Action.RestoreState = FALSE;
|
|
Machine_LoadState();
|
|
}
|
|
if (CPU_Action.DoInterrupt == TRUE) { CPU_Action.DoSomething = TRUE; }
|
|
}
|
|
|
|
void TimerDone (void) {
|
|
DWORD LastTimer;
|
|
if (Profiling) {
|
|
LastTimer = StartTimer(Timer_Done);
|
|
}
|
|
#if (!defined(EXTERNAL_RELEASE))
|
|
if (LogOptions.GenerateLog && LogOptions.LogExceptions && !LogOptions.NoInterrupts) {
|
|
LogMessage("%08X: Timer Done (Type: %d CurrentTimer: %d)", PROGRAM_COUNTER, *g_CurrentTimerType, *g_Timer );
|
|
}
|
|
#endif
|
|
|
|
switch (*g_CurrentTimerType) {
|
|
case CompareTimer:
|
|
FAKE_CAUSE_REGISTER |= CAUSE_IP7;
|
|
CheckInterrupts();
|
|
ChangeCompareTimer();
|
|
break;
|
|
case SoftResetTimer:
|
|
ChangeTimer(SoftResetTimer,0);
|
|
g_N64System->SoftReset();
|
|
break;
|
|
case SiTimer:
|
|
ChangeTimer(SiTimer,0);
|
|
MI_INTR_REG |= MI_INTR_SI;
|
|
SI_STATUS_REG |= SI_STATUS_INTERRUPT;
|
|
CheckInterrupts();
|
|
break;
|
|
case PiTimer:
|
|
ChangeTimer(PiTimer,0);
|
|
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
MI_INTR_REG |= MI_INTR_PI;
|
|
CheckInterrupts();
|
|
break;
|
|
case ViTimer:
|
|
RefreshScreen();
|
|
MI_INTR_REG |= MI_INTR_VI;
|
|
CheckInterrupts();
|
|
break;
|
|
case RspTimer:
|
|
ChangeTimer(RspTimer,0);
|
|
RunRsp();
|
|
break;
|
|
case AiTimer:
|
|
ChangeTimer(AiTimer,0);
|
|
MI_INTR_REG |= MI_INTR_AI;
|
|
CheckInterrupts();
|
|
g_Audio->AiCallBack();
|
|
break;
|
|
default:
|
|
BreakPoint(__FILE__,__LINE__);
|
|
}
|
|
//CheckTimer();
|
|
if (Profiling) {
|
|
StartTimer(LastTimer);
|
|
}
|
|
}
|
|
|
|
void InPermLoop (void) {
|
|
// *** Changed ***/
|
|
if (CPU_Action.DoInterrupt)
|
|
{
|
|
CPU_Action.DoSomething = TRUE;
|
|
return;
|
|
}
|
|
|
|
//if (CPU_Type == CPU_SyncCores) { SyncRegisters.CP0[9] +=5; }
|
|
|
|
/* Interrupts enabled */
|
|
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { goto InterruptsDisabled; }
|
|
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { goto InterruptsDisabled; }
|
|
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { goto InterruptsDisabled; }
|
|
if (( STATUS_REGISTER & 0xFF00) == 0) { goto InterruptsDisabled; }
|
|
|
|
/* check sound playing */
|
|
g_N64System->SyncToAudio();
|
|
|
|
/* check RSP running */
|
|
/* check RDP running */
|
|
|
|
if (*g_Timer > 0) {
|
|
COUNT_REGISTER += *g_Timer + 1;
|
|
//if (CPU_Type == CPU_SyncCores) { SyncRegisters.CP0[9] += Timers.Timer + 1; }
|
|
*g_Timer = -1;
|
|
}
|
|
return;
|
|
|
|
InterruptsDisabled:
|
|
if (UpdateScreen != NULL) { UpdateScreen(); }
|
|
//CurrentFrame = 0;
|
|
//CurrentPercent = 0;
|
|
//DisplayFPS();
|
|
DisplayError(GS(MSG_PERM_LOOP));
|
|
StopEmulation();
|
|
|
|
}
|
|
|
|
int DelaySlotEffectsCompare (DWORD PC, DWORD Reg1, DWORD Reg2) {
|
|
OPCODE Command;
|
|
|
|
if (!r4300i_LW_VAddr(PC + 4, &Command.Hex)) {
|
|
//DisplayError("Failed to load word 2");
|
|
//ExitThread(0);
|
|
return TRUE;
|
|
}
|
|
|
|
switch (Command.op) {
|
|
case R4300i_SPECIAL:
|
|
switch (Command.funct) {
|
|
case R4300i_SPECIAL_SLL:
|
|
case R4300i_SPECIAL_SRL:
|
|
case R4300i_SPECIAL_SRA:
|
|
case R4300i_SPECIAL_SLLV:
|
|
case R4300i_SPECIAL_SRLV:
|
|
case R4300i_SPECIAL_SRAV:
|
|
case R4300i_SPECIAL_MFHI:
|
|
case R4300i_SPECIAL_MTHI:
|
|
case R4300i_SPECIAL_MFLO:
|
|
case R4300i_SPECIAL_MTLO:
|
|
case R4300i_SPECIAL_DSLLV:
|
|
case R4300i_SPECIAL_DSRLV:
|
|
case R4300i_SPECIAL_DSRAV:
|
|
case R4300i_SPECIAL_ADD:
|
|
case R4300i_SPECIAL_ADDU:
|
|
case R4300i_SPECIAL_SUB:
|
|
case R4300i_SPECIAL_SUBU:
|
|
case R4300i_SPECIAL_AND:
|
|
case R4300i_SPECIAL_OR:
|
|
case R4300i_SPECIAL_XOR:
|
|
case R4300i_SPECIAL_NOR:
|
|
case R4300i_SPECIAL_SLT:
|
|
case R4300i_SPECIAL_SLTU:
|
|
case R4300i_SPECIAL_DADD:
|
|
case R4300i_SPECIAL_DADDU:
|
|
case R4300i_SPECIAL_DSUB:
|
|
case R4300i_SPECIAL_DSUBU:
|
|
case R4300i_SPECIAL_DSLL:
|
|
case R4300i_SPECIAL_DSRL:
|
|
case R4300i_SPECIAL_DSRA:
|
|
case R4300i_SPECIAL_DSLL32:
|
|
case R4300i_SPECIAL_DSRL32:
|
|
case R4300i_SPECIAL_DSRA32:
|
|
if (Command.rd == 0) { return FALSE; }
|
|
if (Command.rd == Reg1) { return TRUE; }
|
|
if (Command.rd == Reg2) { return TRUE; }
|
|
break;
|
|
case R4300i_SPECIAL_MULT:
|
|
case R4300i_SPECIAL_MULTU:
|
|
case R4300i_SPECIAL_DIV:
|
|
case R4300i_SPECIAL_DIVU:
|
|
case R4300i_SPECIAL_DMULT:
|
|
case R4300i_SPECIAL_DMULTU:
|
|
case R4300i_SPECIAL_DDIV:
|
|
case R4300i_SPECIAL_DDIVU:
|
|
break;
|
|
default:
|
|
#ifndef EXTERNAL_RELEASE
|
|
DisplayError("Does %s effect Delay slot at %X?",R4300iOpcodeName(Command.Hex,PC+4), PC);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case R4300i_CP0:
|
|
switch (Command.rs) {
|
|
case R4300i_COP0_MT: break;
|
|
case R4300i_COP0_MF:
|
|
if (Command.rt == 0) { return FALSE; }
|
|
if (Command.rt == Reg1) { return TRUE; }
|
|
if (Command.rt == Reg2) { return TRUE; }
|
|
break;
|
|
default:
|
|
if ( (Command.rs & 0x10 ) != 0 ) {
|
|
switch( Opcode.funct ) {
|
|
case R4300i_COP0_CO_TLBR: break;
|
|
case R4300i_COP0_CO_TLBWI: break;
|
|
case R4300i_COP0_CO_TLBWR: break;
|
|
case R4300i_COP0_CO_TLBP: break;
|
|
default:
|
|
#ifndef EXTERNAL_RELEASE
|
|
DisplayError("Does %s effect Delay slot at %X?\n6",R4300iOpcodeName(Command.Hex,PC+4), PC);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
#ifndef EXTERNAL_RELEASE
|
|
DisplayError("Does %s effect Delay slot at %X?\n7",R4300iOpcodeName(Command.Hex,PC+4), PC);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case R4300i_CP1:
|
|
switch (Command.fmt) {
|
|
case R4300i_COP1_MF:
|
|
if (Command.rt == 0) { return FALSE; }
|
|
if (Command.rt == Reg1) { return TRUE; }
|
|
if (Command.rt == Reg2) { return TRUE; }
|
|
break;
|
|
case R4300i_COP1_CF: break;
|
|
case R4300i_COP1_MT: break;
|
|
case R4300i_COP1_CT: break;
|
|
case R4300i_COP1_S: break;
|
|
case R4300i_COP1_D: break;
|
|
case R4300i_COP1_W: break;
|
|
case R4300i_COP1_L: break;
|
|
#ifndef EXTERNAL_RELEASE
|
|
default:
|
|
DisplayError("Does %s effect Delay slot at %X?",R4300iOpcodeName(Command.Hex,PC+4), PC);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case R4300i_ANDI:
|
|
case R4300i_ORI:
|
|
case R4300i_XORI:
|
|
case R4300i_LUI:
|
|
case R4300i_ADDI:
|
|
case R4300i_ADDIU:
|
|
case R4300i_SLTI:
|
|
case R4300i_SLTIU:
|
|
case R4300i_DADDI:
|
|
case R4300i_DADDIU:
|
|
case R4300i_LB:
|
|
case R4300i_LH:
|
|
case R4300i_LW:
|
|
case R4300i_LWL:
|
|
case R4300i_LWR:
|
|
case R4300i_LDL:
|
|
case R4300i_LDR:
|
|
case R4300i_LBU:
|
|
case R4300i_LHU:
|
|
case R4300i_LD:
|
|
case R4300i_LWC1:
|
|
case R4300i_LDC1:
|
|
if (Command.rt == 0) { return FALSE; }
|
|
if (Command.rt == Reg1) { return TRUE; }
|
|
if (Command.rt == Reg2) { return TRUE; }
|
|
break;
|
|
case R4300i_CACHE: break;
|
|
case R4300i_SB: break;
|
|
case R4300i_SH: break;
|
|
case R4300i_SW: break;
|
|
case R4300i_SWR: break;
|
|
case R4300i_SWL: break;
|
|
case R4300i_SWC1: break;
|
|
case R4300i_SDC1: break;
|
|
case R4300i_SD: break;
|
|
default:
|
|
#ifndef EXTERNAL_RELEASE
|
|
DisplayError("Does %s effect Delay slot at %X?",R4300iOpcodeName(Command.Hex,PC+4), PC);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void ChangeCompareTimer(void) {
|
|
DWORD NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
|
|
if ((NextCompare & 0x80000000) != 0) { NextCompare = 0x7FFFFFFF; }
|
|
if (NextCompare == 0) { NextCompare = 0x1; }
|
|
ChangeTimer(CompareTimer,NextCompare);
|
|
}
|
|
|
|
//void ChangeTimer(enum TimerType Type, int Value) {
|
|
// _Reg->ChangeTimerFixed(CompareTimer,COMPARE_REGISTER - COUNT_REGISTER);
|
|
|
|
/*if (Value == 0) {
|
|
Timers.NextTimer[Type] = 0;
|
|
Timers.Active[Type] = FALSE;
|
|
return;
|
|
}
|
|
Timers.NextTimer[Type] = Value - Timers.Timer;
|
|
Timers.Active[Type] = TRUE;
|
|
CheckTimer();*/
|
|
// _asm int 3
|
|
//}
|
|
|
|
void CheckTimer (void) {
|
|
BreakPoint(__FILE__,__LINE__);
|
|
/* int count;
|
|
|
|
for (count = 0; count < MaxTimers; count++) {
|
|
if (!Timers.Active[count]) { continue; }
|
|
if (!(count == CompareTimer && Timers.NextTimer[count] == 0x7FFFFFFF)) {
|
|
Timers.NextTimer[count] += Timers.Timer;
|
|
}
|
|
}
|
|
Timers.CurrentTimerType = -1;
|
|
Timers.Timer = 0x7FFFFFFF;
|
|
for (count = 0; count < MaxTimers; count++) {
|
|
if (!Timers.Active[count]) { continue; }
|
|
if (Timers.NextTimer[count] >= Timers.Timer) { continue; }
|
|
Timers.Timer = Timers.NextTimer[count];
|
|
Timers.CurrentTimerType = count;
|
|
}
|
|
if (Timers.CurrentTimerType == -1) {
|
|
DisplayError("No active timers ???\nEmulation Stoped");
|
|
ExitThread(0);
|
|
}
|
|
for (count = 0; count < MaxTimers; count++) {
|
|
if (!Timers.Active[count]) { continue; }
|
|
if (!(count == CompareTimer && Timers.NextTimer[count] == 0x7FFFFFFF)) {
|
|
Timers.NextTimer[count] -= Timers.Timer;
|
|
}
|
|
}
|
|
|
|
if (Timers.NextTimer[CompareTimer] == 0x7FFFFFFF) {
|
|
DWORD NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
|
|
if ((NextCompare & 0x80000000) == 0 && NextCompare != 0x7FFFFFFF) {
|
|
ChangeCompareTimer();
|
|
}
|
|
}*/
|
|
}
|
|
|
|
/*void RefreshScreen (void ){
|
|
static DWORD OLD_VI_V_SYNC_REG = 0, VI_INTR_TIME = 500000;
|
|
LARGE_INTEGER Time;
|
|
char Label[100];
|
|
|
|
if (Profiling || ShowCPUPer) { memcpy(Label,ProfilingLabel,sizeof(Label)); }
|
|
if (Profiling) { StartTimer("RefreshScreen"); }
|
|
|
|
if (OLD_VI_V_SYNC_REG != VI_V_SYNC_REG) {
|
|
if (VI_V_SYNC_REG == 0) {
|
|
VI_INTR_TIME = 500000;
|
|
} else {
|
|
VI_INTR_TIME = (VI_V_SYNC_REG + 1) * 1500;
|
|
if ((VI_V_SYNC_REG % 1) != 0) {
|
|
VI_INTR_TIME -= 38;
|
|
}
|
|
}
|
|
}
|
|
ChangeTimerRelative(ViTimer,VI_INTR_TIME);
|
|
if (g_FixedAudio)
|
|
{
|
|
UpdateAudioTimer (VI_INTR_TIME);
|
|
}
|
|
|
|
if ((VI_STATUS_REG & 0x10) != 0) {
|
|
if (ViFieldNumber == 0) {
|
|
ViFieldNumber = 1;
|
|
} else {
|
|
ViFieldNumber = 0;
|
|
}
|
|
} else {
|
|
ViFieldNumber = 0;
|
|
}
|
|
|
|
if (ShowCPUPer || Profiling) { StartTimer("CPU Idel"); }
|
|
if (Limit_FPS()) { Timer_Process(NULL); }
|
|
if (ShowCPUPer || Profiling) { StopTimer(); }
|
|
if (Profiling) { StartTimer("RefreshScreen: Update FPS"); }
|
|
if ((CurrentFrame & 7) == 0) {
|
|
//Disables Screen saver
|
|
//mouse_event(MOUSEEVENTF_MOVE,1,1,0,GetMessageExtraInfo());
|
|
//mouse_event(MOUSEEVENTF_MOVE,-1,-1,0,GetMessageExtraInfo());
|
|
|
|
QueryPerformanceCounter(&Time);
|
|
Frames[(CurrentFrame >> 3) % NoOfFrames] = Time.QuadPart - LastFrame;
|
|
LastFrame = Time.QuadPart;
|
|
DisplayFPS();
|
|
}
|
|
if (Profiling) { StopTimer(); }
|
|
if (ShowCPUPer) { DisplayCPUPer(); }
|
|
CurrentFrame += 1;
|
|
|
|
if (Profiling) { StartTimer("RefreshScreen: Update Screen"); }
|
|
__try {
|
|
if (UpdateScreen != NULL)
|
|
{
|
|
UpdateScreen();
|
|
}
|
|
} __except( r4300i_CPU_MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) {
|
|
DisplayError("Unknown memory action in trying to update the screen\n\nEmulation stop");
|
|
ExitThread(0);
|
|
}
|
|
if (Profiling) { StartTimer("RefreshScreen: Cheats"); }
|
|
if ((STATUS_REGISTER & STATUS_IE) != 0 ) { ApplyCheats(); }
|
|
if (Profiling || ShowCPUPer) { StartTimer(Label); }
|
|
}
|
|
|
|
void RunRsp (void) {
|
|
if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) {
|
|
if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) {
|
|
DWORD Task = *( DWORD *)(DMEM + 0xFC0);
|
|
|
|
if (Task == 1 && (DPC_STATUS_REG & DPC_STATUS_FREEZE) != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (Task) {
|
|
case 1:
|
|
DlistCount += 1;
|
|
/*if ((DlistCount % 2) == 0) {
|
|
SP_STATUS_REG |= (0x0203 );
|
|
MI_INTR_REG |= MI_INTR_SP | MI_INTR_DP;
|
|
CheckInterrupts();
|
|
return;
|
|
}*/
|
|
/* break;
|
|
case 2:
|
|
AlistCount += 1;
|
|
break;
|
|
}
|
|
|
|
if (ShowDListAListCount) {
|
|
DisplayMessage("Dlist: %d Alist: %d",DlistCount,AlistCount);
|
|
}
|
|
if (Profiling || DisplayCPUPer) {
|
|
char Label[100];
|
|
|
|
strncpy(Label,ProfilingLabel,sizeof(Label));
|
|
|
|
if (IndvidualBlock && !DisplayCPUPer) {
|
|
StartTimer("RSP");
|
|
} else {
|
|
switch (*( DWORD *)(DMEM + 0xFC0)) {
|
|
case 1: StartTimer("RSP: Dlist"); break;
|
|
case 2: StartTimer("RSP: Alist"); break;
|
|
default: StartTimer("RSP: Unknown"); break;
|
|
}
|
|
}
|
|
DoRspCycles(100);
|
|
StartTimer(Label);
|
|
} else {
|
|
DoRspCycles(100);
|
|
}
|
|
#ifdef CFB_READ
|
|
if (VI_ORIGIN_REG > 0x280) {
|
|
SetFrameBuffer(VI_ORIGIN_REG, (DWORD)(VI_WIDTH_REG * (VI_WIDTH_REG *.75)));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
void DisplayFPS (void) {
|
|
if (CurrentFrame > (NoOfFrames << 3)) {
|
|
__int64 Total = 0;
|
|
int count;
|
|
|
|
for (count = 0; count < NoOfFrames; count ++) {
|
|
Total += Frames[count];
|
|
}
|
|
DisplayMessage2("FPS: %.2f", (__int64)Frequency/ ((double)Total / (NoOfFrames << 3)));
|
|
} else {
|
|
DisplayMessage2("FPS: -.--" );
|
|
}
|
|
}
|
|
|
|
void CloseCpu (void) {
|
|
// DWORD ExitCode, count, OldProtect;
|
|
//
|
|
// if (!CPURunning) { return; }
|
|
// ManualPaused = FALSE;
|
|
// if (CPU_Paused) { PauseCpu (); Sleep(1000); }
|
|
//
|
|
// {
|
|
// BOOL Temp = AlwaysOnTop;
|
|
// AlwaysOnTop = FALSE;
|
|
// AlwaysOnTopWindow(hMainWindow);
|
|
// AlwaysOnTop = Temp;
|
|
// }
|
|
//
|
|
// for (count = 0; count < 20; count ++ ) {
|
|
// CPU_Action.CloseCPU = TRUE;
|
|
// CPU_Action.Stepping = FALSE;
|
|
// CPU_Action.DoSomething = TRUE;
|
|
// PulseEvent( CPU_Action.hStepping );
|
|
// Sleep(100);
|
|
// GetExitCodeThread(hCPU,&ExitCode);
|
|
// if (ExitCode != STILL_ACTIVE) {
|
|
// hCPU = NULL;
|
|
// count = 100;
|
|
// }
|
|
// }
|
|
// if (hCPU != NULL) { TerminateThread(hCPU,0); hCPU = NULL; }
|
|
// CPURunning = FALSE;
|
|
// VirtualProtect(N64MEM,RdramSize,PAGE_READWRITE,&OldProtect);
|
|
// VirtualProtect(N64MEM + 0x04000000,0x2000,PAGE_READWRITE,&OldProtect);
|
|
// Timer_Stop();
|
|
// SetCurrentSaveState(hMainWindow,ID_CURRENTSAVE_DEFAULT);
|
|
// CloseEeprom();
|
|
// CloseMempak();
|
|
// CloseSram();
|
|
// FreeSyncMemory();
|
|
// if (GfxRomClosed != NULL) { GfxRomClosed(); }
|
|
// if (AiRomClosed != NULL) { AiRomClosed(); }
|
|
// if (ContRomClosed != NULL) { ContRomClosed(); }
|
|
// if (RSPRomClosed) { RSPRomClosed(); }
|
|
// if (Profiling) { GenerateTimerResults(); }
|
|
// CloseHandle(CPU_Action.hStepping);
|
|
// SendMessage( hStatusWnd, SB_SETTEXT, 0, (LPARAM)GS(MSG_EMULATION_ENDED) );
|
|
}
|
|
|