diff --git a/Source/Project64-core/N64System/N64Class.cpp b/Source/Project64-core/N64System/N64Class.cpp index 152d54ad2..397775318 100644 --- a/Source/Project64-core/N64System/N64Class.cpp +++ b/Source/Project64-core/N64System/N64Class.cpp @@ -1,2054 +1,2062 @@ -/**************************************************************************** -* * -* Project64 - A Nintendo 64 emulator. * -* http://www.pj64-emu.com/ * -* Copyright (C) 2012 Project64. All rights reserved. * -* * -* License: * -* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * -* * -****************************************************************************/ -#include "stdafx.h" -#include "N64Class.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma warning(disable:4355) // Disable 'this' : used in base member initializer list - -#include -#include - -CN64System::CN64System(CPlugins * Plugins, bool SavesReadOnly) : -CSystemEvents(this, Plugins), -m_EndEmulation(false), -m_SaveUsing((SAVE_CHIP_TYPE)g_Settings->LoadDword(Game_SaveChip)), -m_Plugins(Plugins), -m_SyncCPU(NULL), -m_SyncPlugins(NULL), -m_MMU_VM(SavesReadOnly), -m_TLB(this), -m_Reg(this, this), -m_Recomp(NULL), -m_InReset(false), -m_NextTimer(0), -m_SystemTimer(m_NextTimer), -m_bCleanFrameBox(true), -m_bInitialized(false), -m_RspBroke(true), -m_DMAUsed(false), -m_TestTimer(false), -m_NextInstruction(0), -m_JumpToLocation(0), -m_TLBLoadAddress(0), -m_TLBStoreAddress(0), -m_SyncCount(0), -m_CPU_Handle(NULL), -m_CPU_ThreadID(0), -m_hPauseEvent(true), -m_CheatsSlectionChanged(false) -{ - uint32_t gameHertz = g_Settings->LoadDword(Game_ScreenHertz); - if (gameHertz == 0) - { - gameHertz = (SystemType() == SYSTEM_PAL) ? 50 : 60; - } - m_Limiter.SetHertz(gameHertz); - g_Settings->SaveDword(GameRunning_ScreenHertz, gameHertz); - m_Cheats.LoadCheats(!g_Settings->LoadDword(Setting_RememberCheats), Plugins); -} - -CN64System::~CN64System() -{ - SetActiveSystem(false); - Mempak::Close(); - if (m_SyncCPU) - { - m_SyncCPU->CpuStopped(); - delete m_SyncCPU; - m_SyncCPU = NULL; - } - if (m_Recomp) - { - delete m_Recomp; - m_Recomp = NULL; - } - if (m_SyncPlugins) - { - delete m_SyncPlugins; - m_SyncPlugins = NULL; - } -} - -void CN64System::ExternalEvent(SystemEvent action) -{ - switch (action) - { - case SysEvent_Profile_GenerateLogs: - case SysEvent_Profile_StartStop: - case SysEvent_Profile_ResetLogs: - case SysEvent_ExecuteInterrupt: - case SysEvent_SaveMachineState: - case SysEvent_LoadMachineState: - case SysEvent_ChangingFullScreen: - case SysEvent_GSButtonPressed: - case SysEvent_ResetCPU_SoftDone: - case SysEvent_Interrupt_SP: - case SysEvent_Interrupt_SI: - case SysEvent_Interrupt_AI: - case SysEvent_Interrupt_VI: - case SysEvent_Interrupt_PI: - case SysEvent_Interrupt_DP: - case SysEvent_ResetCPU_Hard: - case SysEvent_ResetCPU_Soft: - case SysEvent_CloseCPU: - case SysEvent_ChangePlugins: - QueueEvent(action); - break; - case SysEvent_PauseCPU_FromMenu: - case SysEvent_PauseCPU_AppLostFocus: - case SysEvent_PauseCPU_AppLostActive: - case SysEvent_PauseCPU_SaveGame: - case SysEvent_PauseCPU_LoadGame: - case SysEvent_PauseCPU_DumpMemory: - case SysEvent_PauseCPU_SearchMemory: - case SysEvent_PauseCPU_Settings: - case SysEvent_PauseCPU_Cheats: - if (!g_Settings->LoadBool(GameRunning_CPU_Paused)) - { - QueueEvent(action); - } - break; - case SysEvent_ResumeCPU_FromMenu: - // always resume if from menu - m_hPauseEvent.Trigger(); - break; - case SysEvent_ResumeCPU_AppGainedFocus: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_AppLostFocus) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_AppGainedActive: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_AppLostActive) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_SaveGame: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_SaveGame) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_LoadGame: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_LoadGame) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_DumpMemory: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_DumpMemory) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_SearchMemory: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_SearchMemory) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_Settings: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_Settings) - { - m_hPauseEvent.Trigger(); - } - break; - case SysEvent_ResumeCPU_Cheats: - if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_Cheats) - { - m_hPauseEvent.Trigger(); - } - break; - default: - WriteTrace(TraceN64System, TraceError, "Unknown event %d", action); - g_Notify->BreakPoint(__FILE__, __LINE__); - } -} - -bool CN64System::RunFileImage(const char * FileLoc) -{ - CloseSystem(); - g_Settings->SaveBool(Setting_EnableDisk, false); - if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) - { - return false; - } - - //Mark the rom as loading - WriteTrace(TraceN64System, TraceDebug, "Mark Rom as loading"); - g_Settings->SaveString(Game_File, ""); - g_Settings->SaveBool(GameRunning_LoadingInProgress, true); - - //Try to load the passed N64 rom - if (g_Rom == NULL) - { - WriteTrace(TraceN64System, TraceDebug, "Allocating global rom object"); - g_Rom = new CN64Rom(); - } - else - { - WriteTrace(TraceN64System, TraceDebug, "Use existing global rom object"); - } - - WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc); - if (g_Rom->LoadN64Image(FileLoc)) - { - if (g_Rom->CicChipID() == CIC_NUS_8303) - { - //64DD IPL - g_DDRom = g_Rom; - g_Settings->SaveString(File_DiskIPLPath, FileLoc); - } - - if (g_DDRom != NULL) - { - g_Settings->SaveBool(Setting_EnableDisk, true); - } - - g_System->RefreshGameSettings(); - - g_Settings->SaveString(Game_File, FileLoc); - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - - if (g_Settings->LoadDword(Setting_AutoStart) != 0) - { - g_BaseSystem = new CN64System(g_Plugins, false); - if (g_BaseSystem) - { - g_BaseSystem->StartEmulation(true); - } - } - } - else - { - WriteTrace(TraceN64System, TraceError, "LoadN64Image failed (\"%s\")", FileLoc); - g_Notify->DisplayError(g_Rom->GetError()); - delete g_Rom; - g_Rom = NULL; - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - return false; - } - return true; -} - -bool CN64System::RunFileImageIPL(const char * FileLoc) -{ - CloseSystem(); - if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) - { - return false; - } - - //Mark the rom as loading - WriteTrace(TraceN64System, TraceDebug, "Mark DDRom as loading"); - //g_Settings->SaveString(Game_File, ""); - g_Settings->SaveBool(GameRunning_LoadingInProgress, true); - - //Try to load the passed N64 DDrom - if (g_DDRom == NULL) - { - WriteTrace(TraceN64System, TraceDebug, "Allocating global DDrom object"); - g_DDRom = new CN64Rom(); - } - else - { - WriteTrace(TraceN64System, TraceDebug, "Use existing global DDrom object"); - } - - WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc); - if (g_DDRom->LoadN64ImageIPL(FileLoc)) - { - if (g_DDRom->CicChipID() != CIC_NUS_8303) - { - //If not 64DD IPL then it's wrong - WriteTrace(TraceN64System, TraceError, "LoadN64ImageIPL failed (\"%s\")", FileLoc); - g_Notify->DisplayError(g_DDRom->GetError()); - delete g_DDRom; - g_DDRom = NULL; - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - return false; - } - - g_System->RefreshGameSettings(); - - g_Settings->SaveString(File_DiskIPLPath, FileLoc); - - //g_Settings->SaveString(Game_File, FileLoc); - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - } - else - { - WriteTrace(TraceN64System, TraceError, "LoadN64ImageIPL failed (\"%s\")", FileLoc); - g_Notify->DisplayError(g_DDRom->GetError()); - delete g_DDRom; - g_DDRom = NULL; - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - return false; - } - return true; -} - -bool CN64System::RunDiskImage(const char * FileLoc) -{ - CloseSystem(); - if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) - { - return false; - } - - //Mark the rom as loading - WriteTrace(TraceN64System, TraceDebug, "Mark Disk as loading"); - //g_Settings->SaveString(Game_File, ""); - g_Settings->SaveBool(GameRunning_LoadingInProgress, true); - - //Try to load the passed N64 Disk - if (g_Disk == NULL) - { - WriteTrace(TraceN64System, TraceDebug, "Allocating global Disk object"); - g_Disk = new CN64Disk(); - } - else - { - WriteTrace(TraceN64System, TraceDebug, "Use existing global Disk object"); - } - - WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc); - if (g_Disk->LoadDiskImage(FileLoc)) - { - g_System->RefreshGameSettings(); - - //g_Settings->SaveString(Game_File, FileLoc); - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - } - else - { - WriteTrace(TraceN64System, TraceError, "LoadDiskImage failed (\"%s\")", FileLoc); - g_Notify->DisplayError(g_Disk->GetError()); - delete g_Disk; - g_Disk = NULL; - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - return false; - } - return true; -} - -void CN64System::CloseSystem() -{ - if (g_BaseSystem) - { - g_BaseSystem->CloseCpu(); - delete g_BaseSystem; - g_BaseSystem = NULL; - } -} - -bool CN64System::EmulationStarting(void * hThread, uint32_t ThreadId) -{ - bool bRes = true; - - WriteTrace(TraceN64System, TraceDebug, "Setting N64 system as active"); - if (g_BaseSystem->SetActiveSystem(true)) - { - g_BaseSystem->m_CPU_Handle = hThread; - g_BaseSystem->m_CPU_ThreadID = ThreadId; - WriteTrace(TraceN64System, TraceDebug, "Setting up N64 system done"); - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - try - { - WriteTrace(TraceN64System, TraceDebug, "Game set to auto start, starting"); - g_BaseSystem->StartEmulation2(false); - WriteTrace(TraceN64System, TraceDebug, "Game Done"); - } - catch (...) - { - g_Notify->DisplayError(stdstr_f(__FUNCTION__ ": Exception caught\nFile: %s\nLine: %d", __FILE__, __LINE__).c_str()); - } - } - else - { - WriteTrace(TraceN64System, TraceError, "SetActiveSystem failed"); - g_Notify->DisplayError(__FUNCTION__ ": Failed to Initialize N64 System"); - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - bRes = false; - } - return bRes; -} - -void CN64System::StartEmulation2(bool NewThread) -{ - if (NewThread) - { - WriteTrace(TraceN64System, TraceDebug, "Starting"); - if (bHaveDebugger()) - { - StartLog(); - } - - CInterpreterCPU::BuildCPU(); - - uint32_t CpuType = g_Settings->LoadDword(Game_CpuType); - - if (CpuType == CPU_SyncCores && !g_Settings->LoadBool(Debugger_Enabled)) - { - g_Settings->SaveDword(Game_CpuType, CPU_Recompiler); - CpuType = CPU_Recompiler; - } - - if (CpuType == CPU_SyncCores) - { - if (g_Plugins->SyncWindow() == NULL) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } - g_Notify->DisplayMessage(5, "Copy Plugins"); - g_Plugins->CopyPlugins(g_Settings->LoadStringVal(Directory_PluginSync)); - m_SyncPlugins = new CPlugins(g_Settings->LoadStringVal(Directory_PluginSync)); - m_SyncPlugins->SetRenderWindows(g_Plugins->SyncWindow(), NULL); - m_SyncCPU = new CN64System(m_SyncPlugins, true); - } - - if (CpuType == CPU_Recompiler || CpuType == CPU_SyncCores) - { - m_Recomp = new CRecompiler(m_Reg, m_Profile, m_EndEmulation); - } - - bool bSetActive = true; - if (m_SyncCPU) - { - bSetActive = m_SyncCPU->SetActiveSystem(); - } - - if (bSetActive) - { - bSetActive = SetActiveSystem(); - } - - if (!bSetActive) - { - g_Settings->SaveBool(GameRunning_LoadingInProgress, false); - g_Notify->DisplayError(MSG_PLUGIN_NOT_INIT); - } - else - { - StartEmulationThead(); - } - } - else - { - //mark the emulation as starting and fix up menus - g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED); - - ExecuteCPU(); - } -} - -void CN64System::StartEmulation(bool NewThread) -{ - __try - { - StartEmulation2(NewThread); - } - __except (g_MMU->MemoryFilter(GetExceptionCode(), GetExceptionInformation())) - { - char message[400]; - sprintf(message, "Exception caught\nFile: %s\nLine: %d", __FILE__, __LINE__); - g_Notify->DisplayError(message); - } -} - -void CN64System::Pause() -{ - if (m_EndEmulation) - { - return; - } - m_hPauseEvent.Reset(); - g_Settings->SaveBool(GameRunning_CPU_Paused, true); - g_Notify->DisplayMessage(5, MSG_CPU_PAUSED); - m_hPauseEvent.IsTriggered(SyncEvent::INFINITE_TIMEOUT); - m_hPauseEvent.Reset(); - g_Settings->SaveBool(GameRunning_CPU_Paused, (uint32_t)false); - g_Notify->DisplayMessage(5, MSG_CPU_RESUMED); -} - -void CN64System::GameReset() -{ - m_SystemTimer.SetTimer(CSystemTimer::SoftResetTimer, 0x3000000, false); - m_Plugins->Gfx()->ShowCFB(); - m_Reg.FAKE_CAUSE_REGISTER |= CAUSE_IP4; - m_Plugins->Gfx()->SoftReset(); - if (m_SyncCPU) - { - m_SyncCPU->GameReset(); - } -} - -void CN64System::PluginReset() -{ - if (!m_Plugins->ResetInUiThread(this)) - { - g_Notify->DisplayMessage(5, MSG_PLUGIN_NOT_INIT); - if (g_BaseSystem) - { - g_BaseSystem->m_EndEmulation = true; - } - } - if (m_SyncCPU) - { - if (!m_SyncCPU->m_Plugins->ResetInUiThread(m_SyncCPU)) - { - g_Notify->DisplayMessage(5, MSG_PLUGIN_NOT_INIT); - if (g_BaseSystem) - { - g_BaseSystem->m_EndEmulation = true; - } - } - } - if (m_Recomp) - { - m_Recomp->Reset(); - } - m_Plugins->RomOpened(); - if (m_SyncCPU) - { - m_SyncCPU->m_Plugins->RomOpened(); - } -#ifndef _WIN64 - _controlfp(_PC_53, _MCW_PC); -#endif -} - -void CN64System::Reset(bool bInitReg, bool ClearMenory) -{ - g_Settings->SaveBool(GameRunning_InReset, true); - RefreshGameSettings(); - m_Audio.Reset(); - m_MMU_VM.Reset(ClearMenory); - Mempak::Close(); - - m_CyclesToSkip = 0; - m_AlistCount = 0; - m_DlistCount = 0; - m_UnknownCount = 0; - m_DMAUsed = false; - m_RspBroke = true; - m_SyncCount = 0; - - for (int i = 0, n = (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])); i < n; i++) - { - m_LastSuccessSyncPC[i] = 0; - } - - if (bInitReg) - { - bool PostPif = true; - - InitRegisters(PostPif, m_MMU_VM); - if (PostPif) - { - memcpy((m_MMU_VM.Dmem() + 0x40), (g_Rom->GetRomAddress() + 0x040), 0xFBC); - } - } - else - { - m_Reg.Reset(); - } - - m_SystemTimer.Reset(); - m_SystemTimer.SetTimer(CSystemTimer::CompareTimer, m_Reg.COMPARE_REGISTER - m_Reg.COUNT_REGISTER, false); - - if (m_Recomp) - { - m_Recomp->Reset(); - } - if (m_Plugins) { m_Plugins->GameReset(); } - if (m_SyncCPU) - { - m_SyncCPU->Reset(bInitReg, ClearMenory); - } - g_Settings->SaveBool(GameRunning_InReset, true); -} - -bool CN64System::SetActiveSystem(bool bActive) -{ - bool bInitPlugin = false; - bool bReset = false; - bool bRes = true; - - if (bActive && g_System == this) - { - return true; - } - - if (bActive) - { - m_Reg.SetAsCurrentSystem(); - - if (g_System) - { - g_System->m_TestTimer = R4300iOp::m_TestTimer; - g_System->m_NextInstruction = R4300iOp::m_NextInstruction; - g_System->m_JumpToLocation = R4300iOp::m_JumpToLocation; - } - - g_System = this; - if (g_BaseSystem == this) - { - g_SyncSystem = m_SyncCPU; - } - g_Recompiler = m_Recomp; - g_MMU = &m_MMU_VM; - g_TLB = &m_TLB; - g_Reg = &m_Reg; - g_Audio = &m_Audio; - g_SystemTimer = &m_SystemTimer; - g_TransVaddr = &m_MMU_VM; - g_SystemEvents = this; - g_NextTimer = &m_NextTimer; - g_Plugins = m_Plugins; - g_TLBLoadAddress = &m_TLBLoadAddress; - g_TLBStoreAddress = &m_TLBStoreAddress; - R4300iOp::m_TestTimer = m_TestTimer; - R4300iOp::m_NextInstruction = m_NextInstruction; - R4300iOp::m_JumpToLocation = m_JumpToLocation; - - if (!m_bInitialized) - { - if (!m_MMU_VM.Initialize()) - { - return false; - } - bReset = true; - m_bInitialized = true; - bInitPlugin = true; - } - } - else - { - if (this == g_BaseSystem) - { - g_System = NULL; - g_SyncSystem = NULL; - g_Recompiler = NULL; - g_MMU = NULL; - g_TLB = NULL; - g_Reg = NULL; - g_Audio = NULL; - g_SystemTimer = NULL; - g_TransVaddr = NULL; - g_SystemEvents = NULL; - g_NextTimer = NULL; - g_Plugins = m_Plugins; - g_TLBLoadAddress = NULL; - g_TLBStoreAddress = NULL; - } - } - - if (bInitPlugin) - { - WriteTrace(TraceN64System, TraceDebug, "Reseting Plugins"); - g_Notify->DisplayMessage(5, MSG_PLUGIN_INIT); - m_Plugins->CreatePlugins(); - bRes = m_Plugins->Initiate(this); - if (!bRes) - { - WriteTrace(TraceN64System, TraceError, "g_Plugins->Initiate Failed"); - } - } - - if (bReset) - { - Reset(true, true); - } - return bRes; -} - -void CN64System::InitRegisters(bool bPostPif, CMipsMemoryVM & MMU) -{ - m_Reg.Reset(); - - //COP0 Registers - m_Reg.RANDOM_REGISTER = 0x1F; - m_Reg.COUNT_REGISTER = 0x5000; - m_Reg.MI_VERSION_REG = 0x02020102; - m_Reg.SP_STATUS_REG = 0x00000001; - m_Reg.CAUSE_REGISTER = 0x0000005C; - m_Reg.CONTEXT_REGISTER = 0x007FFFF0; - m_Reg.EPC_REGISTER = 0xFFFFFFFF; - m_Reg.BAD_VADDR_REGISTER = 0xFFFFFFFF; - m_Reg.ERROREPC_REGISTER = 0xFFFFFFFF; - m_Reg.CONFIG_REGISTER = 0x0006E463; - m_Reg.STATUS_REGISTER = 0x34000000; - - //64DD Registers - m_Reg.ASIC_STATUS = DD_STATUS_RST_STATE; - m_Reg.ASIC_ID_REG = 0x00030000; - - //m_Reg.REVISION_REGISTER = 0x00000511; - m_Reg.FixFpuLocations(); - - if (bPostPif) - { - m_Reg.m_PROGRAM_COUNTER = 0xA4000040; - - m_Reg.m_GPR[0].DW = 0x0000000000000000; - m_Reg.m_GPR[6].DW = 0xFFFFFFFFA4001F0C; - m_Reg.m_GPR[7].DW = 0xFFFFFFFFA4001F08; - m_Reg.m_GPR[8].DW = 0x00000000000000C0; - m_Reg.m_GPR[9].DW = 0x0000000000000000; - m_Reg.m_GPR[10].DW = 0x0000000000000040; - m_Reg.m_GPR[11].DW = 0xFFFFFFFFA4000040; - m_Reg.m_GPR[16].DW = 0x0000000000000000; - m_Reg.m_GPR[17].DW = 0x0000000000000000; - m_Reg.m_GPR[18].DW = 0x0000000000000000; - m_Reg.m_GPR[19].DW = 0x0000000000000000; - m_Reg.m_GPR[21].DW = 0x0000000000000000; - m_Reg.m_GPR[26].DW = 0x0000000000000000; - m_Reg.m_GPR[27].DW = 0x0000000000000000; - m_Reg.m_GPR[28].DW = 0x0000000000000000; - m_Reg.m_GPR[29].DW = 0xFFFFFFFFA4001FF0; - m_Reg.m_GPR[30].DW = 0x0000000000000000; - - switch (g_Rom->GetCountry()) - { - case Germany: case french: case Italian: - case Europe: case Spanish: case Australia: - case X_PAL: case Y_PAL: - switch (g_Rom->CicChipID()) - { - case CIC_UNKNOWN: - case CIC_NUS_6102: - m_Reg.m_GPR[5].DW = 0xFFFFFFFFC0F1D859; - m_Reg.m_GPR[14].DW = 0x000000002DE108EA; - m_Reg.m_GPR[24].DW = 0x0000000000000000; - break; - case CIC_NUS_6103: - m_Reg.m_GPR[5].DW = 0xFFFFFFFFD4646273; - m_Reg.m_GPR[14].DW = 0x000000001AF99984; - m_Reg.m_GPR[24].DW = 0x0000000000000000; - break; - case CIC_NUS_6105: - MMU.SW_VAddr(0xA4001004, 0xBDA807FC); - m_Reg.m_GPR[5].DW = 0xFFFFFFFFDECAAAD1; - m_Reg.m_GPR[14].DW = 0x000000000CF85C13; - m_Reg.m_GPR[24].DW = 0x0000000000000002; - break; - case CIC_NUS_6106: - m_Reg.m_GPR[5].DW = 0xFFFFFFFFB04DC903; - m_Reg.m_GPR[14].DW = 0x000000001AF99984; - m_Reg.m_GPR[24].DW = 0x0000000000000002; - break; - } - m_Reg.m_GPR[20].DW = 0x0000000000000000; - m_Reg.m_GPR[23].DW = 0x0000000000000006; - m_Reg.m_GPR[31].DW = 0xFFFFFFFFA4001554; - break; - case NTSC_BETA: case X_NTSC: case USA: case Japan: - default: - switch (g_Rom->CicChipID()) - { - case CIC_UNKNOWN: - case CIC_NUS_6102: - m_Reg.m_GPR[5].DW = 0xFFFFFFFFC95973D5; - m_Reg.m_GPR[14].DW = 0x000000002449A366; - break; - case CIC_NUS_6103: - m_Reg.m_GPR[5].DW = 0xFFFFFFFF95315A28; - m_Reg.m_GPR[14].DW = 0x000000005BACA1DF; - break; - case CIC_NUS_6105: - MMU.SW_VAddr(0xA4001004, 0x8DA807FC); - m_Reg.m_GPR[5].DW = 0x000000005493FB9A; - m_Reg.m_GPR[14].DW = 0xFFFFFFFFC2C20384; - case CIC_NUS_6106: - m_Reg.m_GPR[5].DW = 0xFFFFFFFFE067221F; - m_Reg.m_GPR[14].DW = 0x000000005CD2B70F; - break; - } - m_Reg.m_GPR[20].DW = 0x0000000000000001; - m_Reg.m_GPR[23].DW = 0x0000000000000000; - m_Reg.m_GPR[24].DW = 0x0000000000000003; - m_Reg.m_GPR[31].DW = 0xFFFFFFFFA4001550; - } - - switch (g_Rom->CicChipID()) - { - case CIC_NUS_6101: - m_Reg.m_GPR[22].DW = 0x000000000000003F; - break; - case CIC_NUS_8303: //64DD IPL CIC - case CIC_NUS_5167: //64DD CONVERSION CIC - m_Reg.m_GPR[22].DW = 0x00000000000000DD; - break; - case CIC_UNKNOWN: - case CIC_NUS_6102: - m_Reg.m_GPR[1].DW = 0x0000000000000001; - m_Reg.m_GPR[2].DW = 0x000000000EBDA536; - m_Reg.m_GPR[3].DW = 0x000000000EBDA536; - m_Reg.m_GPR[4].DW = 0x000000000000A536; - m_Reg.m_GPR[12].DW = 0xFFFFFFFFED10D0B3; - m_Reg.m_GPR[13].DW = 0x000000001402A4CC; - m_Reg.m_GPR[15].DW = 0x000000003103E121; - m_Reg.m_GPR[22].DW = 0x000000000000003F; - m_Reg.m_GPR[25].DW = 0xFFFFFFFF9DEBB54F; - break; - case CIC_NUS_6103: - m_Reg.m_GPR[1].DW = 0x0000000000000001; - m_Reg.m_GPR[2].DW = 0x0000000049A5EE96; - m_Reg.m_GPR[3].DW = 0x0000000049A5EE96; - m_Reg.m_GPR[4].DW = 0x000000000000EE96; - m_Reg.m_GPR[12].DW = 0xFFFFFFFFCE9DFBF7; - m_Reg.m_GPR[13].DW = 0xFFFFFFFFCE9DFBF7; - m_Reg.m_GPR[15].DW = 0x0000000018B63D28; - m_Reg.m_GPR[22].DW = 0x0000000000000078; - m_Reg.m_GPR[25].DW = 0xFFFFFFFF825B21C9; - break; - case CIC_NUS_6105: - MMU.SW_VAddr(0xA4001000, 0x3C0DBFC0); - MMU.SW_VAddr(0xA4001008, 0x25AD07C0); - MMU.SW_VAddr(0xA400100C, 0x31080080); - MMU.SW_VAddr(0xA4001010, 0x5500FFFC); - MMU.SW_VAddr(0xA4001014, 0x3C0DBFC0); - MMU.SW_VAddr(0xA4001018, 0x8DA80024); - MMU.SW_VAddr(0xA400101C, 0x3C0BB000); - m_Reg.m_GPR[1].DW = 0x0000000000000000; - m_Reg.m_GPR[2].DW = 0xFFFFFFFFF58B0FBF; - m_Reg.m_GPR[3].DW = 0xFFFFFFFFF58B0FBF; - m_Reg.m_GPR[4].DW = 0x0000000000000FBF; - m_Reg.m_GPR[12].DW = 0xFFFFFFFF9651F81E; - m_Reg.m_GPR[13].DW = 0x000000002D42AAC5; - m_Reg.m_GPR[15].DW = 0x0000000056584D60; - m_Reg.m_GPR[22].DW = 0x0000000000000091; - m_Reg.m_GPR[25].DW = 0xFFFFFFFFCDCE565F; - break; - case CIC_NUS_6106: - m_Reg.m_GPR[1].DW = 0x0000000000000000; - m_Reg.m_GPR[2].DW = 0xFFFFFFFFA95930A4; - m_Reg.m_GPR[3].DW = 0xFFFFFFFFA95930A4; - m_Reg.m_GPR[4].DW = 0x00000000000030A4; - m_Reg.m_GPR[12].DW = 0xFFFFFFFFBCB59510; - m_Reg.m_GPR[13].DW = 0xFFFFFFFFBCB59510; - m_Reg.m_GPR[15].DW = 0x000000007A3C07F4; - m_Reg.m_GPR[22].DW = 0x0000000000000085; - m_Reg.m_GPR[25].DW = 0x00000000465E3F72; - break; - } - } - else - { - m_Reg.m_PROGRAM_COUNTER = 0xBFC00000; - /* PIF_Ram[36] = 0x00; PIF_Ram[39] = 0x3F; //common pif ram start values - - switch (g_Rom->CicChipID()) { - case CIC_NUS_6101: PIF_Ram[37] = 0x06; PIF_Ram[38] = 0x3F; break; - case CIC_UNKNOWN: - case CIC_NUS_6102: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x3F; break; - case CIC_NUS_6103: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x78; break; - case CIC_NUS_6105: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x91; break; - case CIC_NUS_6106: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x85; break; - }*/ - } -} - -void CN64System::ExecuteCPU() -{ - //reset code - g_Settings->SaveBool(GameRunning_CPU_Paused, false); - g_Settings->SaveBool(GameRunning_CPU_Running, true); - g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED); - - m_EndEmulation = false; - - m_Plugins->RomOpened(); - if (m_SyncCPU) - { - m_SyncCPU->m_Plugins->RomOpened(); - } -#ifndef _WIN64 - _controlfp(_PC_53, _MCW_PC); -#endif - - switch ((CPU_TYPE)g_Settings->LoadDword(Game_CpuType)) - { - // Currently the compiler is 32-bit only. We might have to ignore that RDB setting for now. -#ifndef _WIN64 - case CPU_Recompiler: ExecuteRecompiler(); break; - case CPU_SyncCores: ExecuteSyncCPU(); break; -#endif - default: ExecuteInterpret(); break; - } - g_Settings->SaveBool(GameRunning_CPU_Running, (uint32_t)false); - m_Plugins->RomClosed(); - if (m_SyncCPU) - { - m_SyncCPU->m_Plugins->RomClosed(); - } -} - -void CN64System::ExecuteInterpret() -{ - SetActiveSystem(); - CInterpreterCPU::ExecuteCPU(); -} - -void CN64System::ExecuteRecompiler() -{ - m_Recomp->Run(); -} - -void CN64System::ExecuteSyncCPU() -{ - m_Recomp->Run(); -} - -void CN64System::CpuStopped() -{ - if (!m_InReset) - { - g_Settings->SaveBool(GameRunning_CPU_Running, (uint32_t)false); - g_Notify->DisplayMessage(5, MSG_EMULATION_ENDED); - } - if (m_SyncCPU) - { - m_SyncCPU->CpuStopped(); - } - m_CPU_Handle = NULL; -} - -void CN64System::UpdateSyncCPU(CN64System * const SecondCPU, uint32_t const Cycles) -{ - int CyclesToExecute = Cycles - m_CyclesToSkip; - - //Update the number of cycles to skip - m_CyclesToSkip -= Cycles; - if (m_CyclesToSkip < 0) { m_CyclesToSkip = 0; } - - //Run the other CPU For the same amount of cycles - if (CyclesToExecute < 0) { return; } - - SecondCPU->SetActiveSystem(true); - - CInterpreterCPU::ExecuteOps(Cycles); - - SetActiveSystem(true); -} - -void CN64System::SyncCPUPC(CN64System * const SecondCPU) -{ - bool ErrorFound = false; - - g_SystemTimer->UpdateTimers(); - if (m_Reg.m_PROGRAM_COUNTER != SecondCPU->m_Reg.m_PROGRAM_COUNTER) - { - ErrorFound = true; - } - - if (m_TLB != SecondCPU->m_TLB) { ErrorFound = true; } - if (m_SystemTimer != SecondCPU->m_SystemTimer) { ErrorFound = true; } - if (m_NextTimer != SecondCPU->m_NextTimer) { ErrorFound = true; } - - if (ErrorFound) { DumpSyncErrors(SecondCPU); } - - for (int i = (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])) - 1; i > 0; i--) - { - m_LastSuccessSyncPC[i] = m_LastSuccessSyncPC[i - 1]; - } - m_LastSuccessSyncPC[0] = m_Reg.m_PROGRAM_COUNTER; -} - -void CN64System::SyncCPU(CN64System * const SecondCPU) -{ - bool ErrorFound = false; - - m_SyncCount += 1; - //WriteTraceF(TraceError,"SyncCPU PC = %08X",m_Reg.m_PROGRAM_COUNTER); - g_SystemTimer->UpdateTimers(); - -#ifdef TEST_SP_TRACKING - if (m_CurrentSP != GPR[29].UW[0]) { - ErrorFound = true; - } -#endif - if (m_Reg.m_PROGRAM_COUNTER != SecondCPU->m_Reg.m_PROGRAM_COUNTER) - { - ErrorFound = true; - } - if (b32BitCore()) - { - for (int count = 0; count < 32; count++) - { - if (m_Reg.m_GPR[count].W[0] != SecondCPU->m_Reg.m_GPR[count].W[0]) - { - ErrorFound = true; - } - if (m_Reg.m_FPR[count].DW != SecondCPU->m_Reg.m_FPR[count].DW) - { - ErrorFound = true; - } - if (m_Reg.m_CP0[count] != SecondCPU->m_Reg.m_CP0[count]) - { - ErrorFound = true; - } - } - } - else - { - for (int count = 0; count < 32; count++) - { - if (m_Reg.m_GPR[count].DW != SecondCPU->m_Reg.m_GPR[count].DW) - { - ErrorFound = true; - } - if (m_Reg.m_FPR[count].DW != SecondCPU->m_Reg.m_FPR[count].DW) - { - ErrorFound = true; - } - if (m_Reg.m_CP0[count] != SecondCPU->m_Reg.m_CP0[count]) - { - ErrorFound = true; - } - } - } - - if (m_TLB != SecondCPU->m_TLB) { ErrorFound = true; } - if (m_Reg.m_FPCR[0] != SecondCPU->m_Reg.m_FPCR[0]) { ErrorFound = true; } - if (m_Reg.m_FPCR[31] != SecondCPU->m_Reg.m_FPCR[31]) { ErrorFound = true; } - if (m_Reg.m_HI.DW != SecondCPU->m_Reg.m_HI.DW) { ErrorFound = true; } - if (m_Reg.m_LO.DW != SecondCPU->m_Reg.m_LO.DW) { ErrorFound = true; } - /*if (m_SyncCount > 4788000) - { - if (memcmp(m_MMU_VM.Rdram(),SecondCPU->m_MMU_VM.Rdram(),RdramSize()) != 0) - { - ErrorFound = true; - } - } - if (memcmp(m_MMU_VM.Imem(),SecondCPU->m_MMU_VM.Imem(),0x1000) != 0) - { - ErrorFound = true; - } - if (memcmp(m_MMU_VM.Dmem(),SecondCPU->m_MMU_VM.Dmem(),0x1000) != 0) - { - ErrorFound = true; - }*/ - - /*for (int z = 0; z < 0x100; z++) - { - if (m_MMU_VM.Rdram()[0x00206970 + z] != SecondCPU->m_MMU_VM.Rdram()[0x00206970 + z]) - { - ErrorFound = true; - break; - } - }*/ - - if (bFastSP() && m_Recomp) - { - if (m_Recomp->MemoryStackPos() != (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))) - { - ErrorFound = true; - } - } - - if (m_SystemTimer != SecondCPU->m_SystemTimer) { ErrorFound = true; } - if (m_NextTimer != SecondCPU->m_NextTimer) { ErrorFound = true; } - if (m_Reg.m_RoundingModel != SecondCPU->m_Reg.m_RoundingModel) { ErrorFound = true; } - - for (int i = 0, n = sizeof(m_Reg.m_Mips_Interface) / sizeof(m_Reg.m_Mips_Interface[0]); i < n; i++) - { - if (m_Reg.m_Mips_Interface[i] != SecondCPU->m_Reg.m_Mips_Interface[i]) - { - ErrorFound = true; - } - } - - for (int i = 0, n = sizeof(m_Reg.m_SigProcessor_Interface) / sizeof(m_Reg.m_SigProcessor_Interface[0]); i < n; i++) - { - if (m_Reg.m_SigProcessor_Interface[i] != SecondCPU->m_Reg.m_SigProcessor_Interface[i]) - { - ErrorFound = true; - } - } - - for (int i = 0, n = sizeof(m_Reg.m_Display_ControlReg) / sizeof(m_Reg.m_Display_ControlReg[0]); i < n; i++) - { - if (m_Reg.m_Display_ControlReg[i] != SecondCPU->m_Reg.m_Display_ControlReg[i]) - { - ErrorFound = true; - } - } - - if (ErrorFound) { DumpSyncErrors(SecondCPU); } - - for (int i = (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])) - 1; i > 0; i--) - { - m_LastSuccessSyncPC[i] = m_LastSuccessSyncPC[i - 1]; - } - m_LastSuccessSyncPC[0] = m_Reg.m_PROGRAM_COUNTER; - // if (PROGRAM_COUNTER == 0x8009BBD8) { - // g_Notify->BreakPoint(__FILE__, __LINE__); - // } -} - -void CN64System::SyncSystem() -{ - SyncCPU(g_SyncSystem); -} - -void CN64System::SyncSystemPC() -{ - SyncCPUPC(g_SyncSystem); -} - -void CN64System::DumpSyncErrors(CN64System * SecondCPU) -{ - int count; - - { - CPath ErrorFile(CPath::MODULE_DIRECTORY); - ErrorFile.AppendDirectory("Logs"); - ErrorFile.SetNameExtension("Sync Errors.txt"); - - CLog Error; - Error.Open(ErrorFile); - Error.Log("Errors:\r\n"); - Error.Log("Register, Recompiler, Interpter\r\n"); -#ifdef TEST_SP_TRACKING - if (m_CurrentSP != GPR[29].UW[0]) { - Error.Log("m_CurrentSP,%X,%X\r\n", m_CurrentSP, GPR[29].UW[0]); - } -#endif - if (m_Reg.m_PROGRAM_COUNTER != SecondCPU->m_Reg.m_PROGRAM_COUNTER) { - Error.LogF("PROGRAM_COUNTER 0x%X, 0x%X\r\n", m_Reg.m_PROGRAM_COUNTER, SecondCPU->m_Reg.m_PROGRAM_COUNTER); - } - if (b32BitCore()) - { - for (count = 0; count < 32; count++) - { - if (m_Reg.m_GPR[count].UW[0] != SecondCPU->m_Reg.m_GPR[count].UW[0]) - { - Error.LogF("GPR[%s] 0x%08X%08X, 0x%08X%08X\r\n", CRegName::GPR[count], - m_Reg.m_GPR[count].W[1], m_Reg.m_GPR[count].W[0], - SecondCPU->m_Reg.m_GPR[count].W[1], SecondCPU->m_Reg.m_GPR[count].W[0]); - } - } - } - else - { - for (count = 0; count < 32; count++) - { - if (m_Reg.m_GPR[count].DW != SecondCPU->m_Reg.m_GPR[count].DW) - { - Error.LogF("GPR[%s] 0x%08X%08X, 0x%08X%08X\r\n", CRegName::GPR[count], - m_Reg.m_GPR[count].W[1], m_Reg.m_GPR[count].W[0], - SecondCPU->m_Reg.m_GPR[count].W[1], SecondCPU->m_Reg.m_GPR[count].W[0]); - } - } - } - for (count = 0; count < 32; count++) - { - if (m_Reg.m_FPR[count].DW != SecondCPU->m_Reg.m_FPR[count].DW) - { - Error.LogF("FPR[%s] 0x%08X%08X, 0x%08X%08X\r\n", CRegName::FPR[count], - m_Reg.m_FPR[count].W[1], m_Reg.m_FPR[count].W[0], - SecondCPU->m_Reg.m_FPR[count].W[1], SecondCPU->m_Reg.m_FPR[count].W[0]); - } - } - for (count = 0; count < 32; count++) - { - if (m_Reg.m_FPCR[count] != SecondCPU->m_Reg.m_FPCR[count]) - { - Error.LogF("FPCR[%s] 0x%08X, 0x%08X\r\n", CRegName::FPR_Ctrl[count], - m_Reg.m_FPCR[count], SecondCPU->m_Reg.m_FPCR[count]); - } - } - for (count = 0; count < 32; count++) - { - if (m_Reg.m_CP0[count] != SecondCPU->m_Reg.m_CP0[count]) - { - Error.LogF("CP0[%s] 0x%08X, 0x%08X\r\n", CRegName::Cop0[count], - m_Reg.m_CP0[count], SecondCPU->m_Reg.m_CP0[count]); - } - } - if (m_Reg.m_HI.DW != SecondCPU->m_Reg.m_HI.DW) - { - Error.LogF("HI Reg 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_HI.UW[1], m_Reg.m_HI.UW[0], SecondCPU->m_Reg.m_HI.UW[1], SecondCPU->m_Reg.m_HI.UW[0]); - } - if (m_Reg.m_LO.DW != SecondCPU->m_Reg.m_LO.DW) - { - Error.LogF("LO Reg 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_LO.UW[1], m_Reg.m_LO.UW[0], SecondCPU->m_Reg.m_LO.UW[1], SecondCPU->m_Reg.m_LO.UW[0]); - } - for (int i = 0, n = sizeof(m_Reg.m_Mips_Interface) / sizeof(m_Reg.m_Mips_Interface[0]); i < n; i++) - { - if (m_Reg.m_Mips_Interface[i] != SecondCPU->m_Reg.m_Mips_Interface[i]) - { - Error.LogF("Mips_Interface[%d] 0x%08X, 0x%08X\r\n", i, m_Reg.m_Mips_Interface[i], SecondCPU->m_Reg.m_Mips_Interface[i]); - } - } - - for (int i = 0, n = sizeof(m_Reg.m_SigProcessor_Interface) / sizeof(m_Reg.m_SigProcessor_Interface[0]); i < n; i++) - { - if (m_Reg.m_SigProcessor_Interface[i] != SecondCPU->m_Reg.m_SigProcessor_Interface[i]) - { - Error.LogF("SigProcessor_Interface[%d] 0x%08X, 0x%08X\r\n", i, m_Reg.m_SigProcessor_Interface[i], SecondCPU->m_Reg.m_SigProcessor_Interface[i]); - } - } - for (int i = 0, n = sizeof(m_Reg.m_Display_ControlReg) / sizeof(m_Reg.m_Display_ControlReg[0]); i < n; i++) - { - if (m_Reg.m_Display_ControlReg[i] != SecondCPU->m_Reg.m_Display_ControlReg[i]) - { - Error.LogF("Display_ControlReg[%d] 0x%08X, 0x%08X\r\n", i, m_Reg.m_Display_ControlReg[i], SecondCPU->m_Reg.m_Display_ControlReg[i]); - } - } - - if (m_NextTimer != SecondCPU->m_NextTimer) - { - Error.LogF("Current Time: %X %X\r\n", (uint32_t)m_NextTimer, (uint32_t)SecondCPU->m_NextTimer); - } - m_TLB.RecordDifference(Error, SecondCPU->m_TLB); - m_SystemTimer.RecordDifference(Error, SecondCPU->m_SystemTimer); - if (m_Reg.m_RoundingModel != SecondCPU->m_Reg.m_RoundingModel) - { - Error.LogF("RoundingModel: %X %X\r\n", m_Reg.m_RoundingModel, SecondCPU->m_Reg.m_RoundingModel); - } - if (bFastSP() && m_Recomp) - { - if (m_Recomp->MemoryStackPos() != (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))) - { - Error.LogF("MemoryStack = %X should be: %X\r\n", m_Recomp->MemoryStackPos(), (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))); - } - } - - uint32_t * Rdram = (uint32_t *)m_MMU_VM.Rdram(), *Rdram2 = (uint32_t *)SecondCPU->m_MMU_VM.Rdram(); - for (int z = 0, n = (RdramSize() >> 2); z < n; z++) - { - if (Rdram[z] != Rdram2[z]) - { - Error.LogF("Rdram[%X]: %X %X\r\n", z << 2, Rdram[z], Rdram2[z]); - } - } - - uint32_t * Imem = (uint32_t *)m_MMU_VM.Imem(), *Imem2 = (uint32_t *)SecondCPU->m_MMU_VM.Imem(); - for (int z = 0; z < (0x1000 >> 2); z++) - { - if (Imem[z] != Imem2[z]) - { - Error.LogF("Imem[%X]: %X %X\r\n", z << 2, Imem[z], Imem2[z]); - } - } - uint32_t * Dmem = (uint32_t *)m_MMU_VM.Dmem(), *Dmem2 = (uint32_t *)SecondCPU->m_MMU_VM.Dmem(); - for (int z = 0; z < (0x1000 >> 2); z++) - { - if (Dmem[z] != Dmem2[z]) - { - Error.LogF("Dmem[%X]: %X %X\r\n", z << 2, Dmem[z], Dmem2[z]); - } - } - Error.Log("\r\n"); - Error.Log("Information:\r\n"); - Error.Log("\r\n"); - Error.LogF("PROGRAM_COUNTER,0x%X\r\n", m_Reg.m_PROGRAM_COUNTER); - Error.LogF("Current Timer,0x%X\r\n", m_NextTimer); - Error.LogF("Timer Type,0x%X\r\n", m_SystemTimer.CurrentType()); - Error.Log("\r\n"); - for (int i = 0; i < (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])); i++) - { - Error.LogF("LastSuccessSyncPC[%d],0x%X\r\n", i, m_LastSuccessSyncPC[i]); - } - Error.Log("\r\n"); - for (count = 0; count < 32; count++) - { - Error.LogF("GPR[%s], 0x%08X%08X, 0x%08X%08X\r\n", CRegName::GPR[count], - m_Reg.m_GPR[count].W[1], m_Reg.m_GPR[count].W[0], - SecondCPU->m_Reg.m_GPR[count].W[1], SecondCPU->m_Reg.m_GPR[count].W[0]); - } - Error.Log("\r\n"); - for (count = 0; count < 32; count++) - { - Error.LogF("FPR[%s],%*s0x%08X%08X, 0x%08X%08X\r\n", CRegName::FPR[count], - count < 10 ? 9 : 8, " ", m_Reg.m_FPR[count].W[1], m_Reg.m_FPR[count].W[0], - SecondCPU->m_Reg.m_FPR[count].W[1], SecondCPU->m_Reg.m_FPR[count].W[0]); - } - Error.Log("\r\n"); - for (count = 0; count < 32; count++) - { - Error.LogF("FPR_S[%s],%*s%f, %f\r\n", CRegName::FPR[count], - count < 10 ? 7 : 6, " ", *(m_Reg.m_FPR_S[count]), *(SecondCPU->m_Reg.m_FPR_S[count])); - } - Error.Log("\r\n"); - for (count = 0; count < 32; count++) - { - Error.LogF("FPR_D[%s],%*s%f, %f\r\n", CRegName::FPR[count], - count < 10 ? 7 : 6, " ", *(m_Reg.m_FPR_D[count]), *(SecondCPU->m_Reg.m_FPR_D[count])); - } - Error.Log("\r\n"); - Error.LogF("Rounding Model, 0x%08X, 0x%08X\r\n", m_Reg.m_RoundingModel, SecondCPU->m_Reg.m_RoundingModel); - Error.Log("\r\n"); - for (count = 0; count < 32; count++) - { - Error.LogF("CP0[%s],%*s0x%08X, 0x%08X\r\n", CRegName::Cop0[count], - 12 - strlen(CRegName::Cop0[count]), "", - m_Reg.m_CP0[count], SecondCPU->m_Reg.m_CP0[count]); - } - Error.Log("\r\n"); - Error.LogF("HI 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_HI.UW[1], m_Reg.m_HI.UW[0], - SecondCPU->m_Reg.m_HI.UW[1], SecondCPU->m_Reg.m_HI.UW[0]); - Error.LogF("LO 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_LO.UW[1], m_Reg.m_LO.UW[0], - SecondCPU->m_Reg.m_LO.UW[1], SecondCPU->m_Reg.m_LO.UW[0]); - bool bHasTlb = false; - for (count = 0; count < 32; count++) - { - if (!m_TLB.TlbEntry(count).EntryDefined) { continue; } - if (!bHasTlb) - { - Error.Log("\r\n"); - Error.Log(" Hi Recomp, PageMask, Hi Interp, PageMask\r\n"); - bHasTlb = true; - } - Error.LogF("TLB[%2d], %08X, %08X, %08X, %08X\r\n", count, - m_TLB.TlbEntry(count).EntryHi.Value, m_TLB.TlbEntry(count).PageMask.Value, - SecondCPU->m_TLB.TlbEntry(count).EntryHi.Value, SecondCPU->m_TLB.TlbEntry(count).PageMask.Value - ); - } - Error.Log("\r\n"); - Error.Log("Code at PC:\r\n"); - for (count = -10; count < 10; count++) - { - uint32_t OpcodeValue, Addr = m_Reg.m_PROGRAM_COUNTER + (count << 2); - if (g_MMU->LW_VAddr(Addr, OpcodeValue)) - { - Error.LogF("%X: %s\r\n", Addr, R4300iOpcodeName(OpcodeValue, Addr)); - } - } - Error.Log("\r\n"); - Error.Log("Code at Last Sync PC:\r\n"); - for (count = 0; count < 50; count++) - { - uint32_t OpcodeValue, Addr = m_LastSuccessSyncPC[0] + (count << 2); - if (g_MMU->LW_VAddr(Addr, OpcodeValue)) - { - Error.LogF("%X: %s\r\n", Addr, R4300iOpcodeName(OpcodeValue, Addr)); - } - } - } - - g_Notify->DisplayError("Sync Error"); - g_Notify->BreakPoint(__FILE__, __LINE__); -} - -bool CN64System::SaveState() -{ - WriteTrace(TraceN64System, TraceDebug, "Start"); - - // if (!m_SystemTimer.SaveAllowed()) { return false; } - if ((m_Reg.STATUS_REGISTER & STATUS_EXL) != 0) { return false; } - - //Get the file Name - stdstr FileName, ExtraInfoFileName, CurrentSaveName = g_Settings->LoadStringVal(GameRunning_InstantSaveFile); - if (CurrentSaveName.empty()) - { - int Slot = g_Settings->LoadDword(Game_CurrentSaveState); - if (Slot != 0) - { - CurrentSaveName.Format("%s.pj%d", g_Settings->LoadStringVal(Game_GoodName).c_str(), Slot); - } - else - { - CurrentSaveName.Format("%s.pj", g_Settings->LoadStringVal(Game_GoodName).c_str()); - } - FileName.Format("%s%s", g_Settings->LoadStringVal(Directory_InstantSave).c_str(), CurrentSaveName.c_str()); - stdstr_f ZipFileName("%s.zip", FileName.c_str()); - //Make sure the target dir exists - CreateDirectory(g_Settings->LoadStringVal(Directory_InstantSave).c_str(), NULL); - //delete any old save - DeleteFile(FileName.c_str()); - DeleteFile(ZipFileName.c_str()); - ExtraInfoFileName.Format("%s.dat", CurrentSaveName.c_str()); - - //If ziping save add .zip on the end - if (g_Settings->LoadDword(Setting_AutoZipInstantSave)) - { - FileName = ZipFileName; - } - g_Settings->SaveDword(Game_LastSaveSlot, g_Settings->LoadDword(Game_CurrentSaveState)); - } - else - { - char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; - _splitpath(CurrentSaveName.c_str(), drive, dir, fname, ext); - - FileName.Format("%s.pj", CurrentSaveName.c_str()); - - CurrentSaveName.Format("%s.pj", fname); - ExtraInfoFileName.Format("%s.dat", fname); - - //If ziping save add .zip on the end - if (g_Settings->LoadDword(Setting_AutoZipInstantSave)) - { - FileName.Format("%s.zip", FileName.c_str()); - } - } - if (FileName.empty()) { return true; } - - //Open the file - if (g_Settings->LoadDword(Game_FuncLookupMode) == FuncFind_ChangeMemory) - { - if (m_Recomp) - { - m_Recomp->ResetRecompCode(true); - } - } - - uint32_t SaveID_0 = 0x23D8A6C8, SaveID_1 = 0x56D2CD23; - uint32_t RdramSize = g_Settings->LoadDword(Game_RDRamSize); - uint32_t MiInterReg = g_Reg->MI_INTR_REG; - uint32_t NextViTimer = m_SystemTimer.GetTimer(CSystemTimer::ViTimer); - if (g_Settings->LoadDword(Setting_AutoZipInstantSave)) - { - zipFile file; - - file = zipOpen(FileName.c_str(), 0); - zipOpenNewFileInZip(file, CurrentSaveName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); - zipWriteInFileInZip(file, &SaveID_0, sizeof(SaveID_0)); - zipWriteInFileInZip(file, &RdramSize, sizeof(uint32_t)); - zipWriteInFileInZip(file, g_Rom->GetRomAddress(), 0x40); - zipWriteInFileInZip(file, &NextViTimer, sizeof(uint32_t)); - zipWriteInFileInZip(file, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER)); - zipWriteInFileInZip(file, m_Reg.m_GPR, sizeof(int64_t) * 32); - zipWriteInFileInZip(file, m_Reg.m_FPR, sizeof(int64_t) * 32); - zipWriteInFileInZip(file, m_Reg.m_CP0, sizeof(uint32_t) * 32); - zipWriteInFileInZip(file, m_Reg.m_FPCR, sizeof(uint32_t) * 32); - zipWriteInFileInZip(file, &m_Reg.m_HI, sizeof(int64_t)); - zipWriteInFileInZip(file, &m_Reg.m_LO, sizeof(int64_t)); - zipWriteInFileInZip(file, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10); - zipWriteInFileInZip(file, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10); - zipWriteInFileInZip(file, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10); - zipWriteInFileInZip(file, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4); - zipWriteInFileInZip(file, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14); - zipWriteInFileInZip(file, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6); - zipWriteInFileInZip(file, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13); - zipWriteInFileInZip(file, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8); - zipWriteInFileInZip(file, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4); - zipWriteInFileInZip(file, (void *const)&m_TLB.TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32); - zipWriteInFileInZip(file, m_MMU_VM.PifRam(), 0x40); - zipWriteInFileInZip(file, m_MMU_VM.Rdram(), RdramSize); - zipWriteInFileInZip(file, m_MMU_VM.Dmem(), 0x1000); - zipWriteInFileInZip(file, m_MMU_VM.Imem(), 0x1000); - zipCloseFileInZip(file); - - zipOpenNewFileInZip(file, ExtraInfoFileName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); - zipWriteInFileInZip(file, &SaveID_1, sizeof(SaveID_1)); - m_SystemTimer.SaveData(file); - zipCloseFileInZip(file); - - zipClose(file, ""); - } - else - { - HANDLE hSaveFile = CreateFile(FileName.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); - if (hSaveFile == INVALID_HANDLE_VALUE) - { - g_Notify->DisplayError(GS(MSG_FAIL_OPEN_SAVE)); - m_Reg.MI_INTR_REG = MiInterReg; - return true; - } - - //Write info to file - SetFilePointer(hSaveFile, 0, NULL, FILE_BEGIN); - DWORD dwWritten; - WriteFile(hSaveFile, &SaveID_0, sizeof(uint32_t), &dwWritten, NULL); - WriteFile(hSaveFile, &RdramSize, sizeof(uint32_t), &dwWritten, NULL); - WriteFile(hSaveFile, g_Rom->GetRomAddress(), 0x40, &dwWritten, NULL); - WriteFile(hSaveFile, &NextViTimer, sizeof(uint32_t), &dwWritten, NULL); - WriteFile(hSaveFile, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER), &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_GPR, sizeof(int64_t) * 32, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_FPR, sizeof(int64_t) * 32, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_CP0, sizeof(uint32_t) * 32, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_FPCR, sizeof(uint32_t) * 32, &dwWritten, NULL); - WriteFile(hSaveFile, &m_Reg.m_HI, sizeof(int64_t), &dwWritten, NULL); - WriteFile(hSaveFile, &m_Reg.m_LO, sizeof(int64_t), &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8, &dwWritten, NULL); - WriteFile(hSaveFile, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4, &dwWritten, NULL); - WriteFile(hSaveFile, &g_TLB->TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32, &dwWritten, NULL); - WriteFile(hSaveFile, g_MMU->PifRam(), 0x40, &dwWritten, NULL); - WriteFile(hSaveFile, g_MMU->Rdram(), RdramSize, &dwWritten, NULL); - WriteFile(hSaveFile, g_MMU->Dmem(), 0x1000, &dwWritten, NULL); - WriteFile(hSaveFile, g_MMU->Imem(), 0x1000, &dwWritten, NULL); - - CloseHandle(hSaveFile); - } - m_Reg.MI_INTR_REG = MiInterReg; - g_Settings->SaveString(GameRunning_InstantSaveFile, ""); - std::string SaveMessage = g_Lang->GetString(MSG_SAVED_STATE); - - CPath SavedFileName(FileName); - - g_Notify->DisplayMessage(5, stdstr_f("%s %s", SaveMessage.c_str(), stdstr(SavedFileName.GetNameExtension()).c_str()).c_str()); - //Notify().RefreshMenu(); - WriteTrace(TraceN64System, TraceDebug, "Done"); - return true; -} - -bool CN64System::LoadState() -{ - stdstr InstantFileName = g_Settings->LoadStringVal(GameRunning_InstantSaveFile); - if (!InstantFileName.empty()) - { - bool Result = LoadState(InstantFileName.c_str()); - g_Settings->SaveString(GameRunning_InstantSaveFile, ""); - return Result; - } - - CPath FileName; - FileName.SetDriveDirectory(g_Settings->LoadStringVal(Directory_InstantSave).c_str()); - if (g_Settings->LoadDword(Game_CurrentSaveState) != 0) - { - FileName.SetNameExtension(stdstr_f("%s.pj%d", g_Settings->LoadStringVal(Game_GoodName).c_str(), g_Settings->LoadDword(Game_CurrentSaveState)).c_str()); - } - else - { - FileName.SetNameExtension(stdstr_f("%s.pj", g_Settings->LoadStringVal(Game_GoodName).c_str()).c_str()); - } - - CPath ZipFileName; - ZipFileName = (std::string)FileName + ".zip"; - - if ((g_Settings->LoadDword(Setting_AutoZipInstantSave) && ZipFileName.Exists()) || FileName.Exists()) - { - if (LoadState(FileName)) - { - return true; - } - } - - //Use old file Name - if (g_Settings->LoadDword(Game_CurrentSaveState) != 0) - { - FileName.SetNameExtension(stdstr_f("%s.pj%d", g_Settings->LoadStringVal(Game_GameName).c_str(), g_Settings->LoadDword(Game_CurrentSaveState)).c_str()); - } - else - { - FileName.SetNameExtension(stdstr_f("%s.pj", g_Settings->LoadStringVal(Game_GameName).c_str()).c_str()); - } - return LoadState(FileName); -} - -bool CN64System::LoadState(const char * FileName) -{ - uint32_t Value, SaveRDRAMSize, NextVITimer = 0, old_status, old_width, old_dacrate; - bool LoadedZipFile = false, AudioResetOnLoad; - old_status = g_Reg->VI_STATUS_REG; - old_width = g_Reg->VI_WIDTH_REG; - old_dacrate = g_Reg->AI_DACRATE_REG; - - WriteTrace(TraceN64System, TraceDebug, "(%s): Start", FileName); - - char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; - _splitpath(FileName, drive, dir, fname, ext); - - stdstr FileNameStr(FileName); - if (g_Settings->LoadDword(Setting_AutoZipInstantSave) || _stricmp(ext, ".zip") == 0) - { - //If ziping save add .zip on the end - if (_stricmp(ext, ".zip") != 0) - { - FileNameStr += ".zip"; - } - unzFile file = unzOpen(FileNameStr.c_str()); - int port = -1; - if (file != NULL) - { - port = unzGoToFirstFile(file); - } - uint32_t Value; - while (port == UNZ_OK) - { - unz_file_info info; - char zname[132]; - - unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0); - if (unzLocateFile(file, zname, 1) != UNZ_OK) - { - unzClose(file); - port = -1; - continue; - } - if (unzOpenCurrentFile(file) != UNZ_OK) - { - unzClose(file); - port = -1; - continue; - } - unzReadCurrentFile(file, &Value, 4); - if (Value != 0x23D8A6C8 && Value != 0x56D2CD23) - { - unzCloseCurrentFile(file); - port = unzGoToNextFile(file); - continue; - } - if (!LoadedZipFile && Value == 0x23D8A6C8 && port == UNZ_OK) - { - unzReadCurrentFile(file, &SaveRDRAMSize, sizeof(SaveRDRAMSize)); - //Check header - - uint8_t LoadHeader[64]; - unzReadCurrentFile(file, LoadHeader, 0x40); - if (memcmp(LoadHeader, g_Rom->GetRomAddress(), 0x40) != 0) - { - //if (inFullScreen) { return false; } - int result = MessageBoxW(NULL, wGS(MSG_SAVE_STATE_HEADER).c_str(), wGS(MSG_MSGBOX_TITLE).c_str(), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2); - - if (result == IDNO) - { - return false; - } - } - Reset(false, true); - - g_MMU->UnProtectMemory(0x80000000, 0x80000000 + g_Settings->LoadDword(Game_RDRamSize) - 4); - g_MMU->UnProtectMemory(0xA4000000, 0xA4001FFC); - g_Settings->SaveDword(Game_RDRamSize, SaveRDRAMSize); - unzReadCurrentFile(file, &NextVITimer, sizeof(NextVITimer)); - unzReadCurrentFile(file, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER)); - unzReadCurrentFile(file, m_Reg.m_GPR, sizeof(int64_t) * 32); - unzReadCurrentFile(file, m_Reg.m_FPR, sizeof(int64_t) * 32); - unzReadCurrentFile(file, m_Reg.m_CP0, sizeof(uint32_t) * 32); - unzReadCurrentFile(file, m_Reg.m_FPCR, sizeof(uint32_t) * 32); - unzReadCurrentFile(file, &m_Reg.m_HI, sizeof(int64_t)); - unzReadCurrentFile(file, &m_Reg.m_LO, sizeof(int64_t)); - unzReadCurrentFile(file, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10); - unzReadCurrentFile(file, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10); - unzReadCurrentFile(file, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10); - unzReadCurrentFile(file, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4); - unzReadCurrentFile(file, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14); - unzReadCurrentFile(file, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6); - unzReadCurrentFile(file, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13); - unzReadCurrentFile(file, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8); - unzReadCurrentFile(file, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4); - unzReadCurrentFile(file, (void *const)&g_TLB->TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32); - unzReadCurrentFile(file, m_MMU_VM.PifRam(), 0x40); - unzReadCurrentFile(file, m_MMU_VM.Rdram(), SaveRDRAMSize); - unzReadCurrentFile(file, m_MMU_VM.Dmem(), 0x1000); - unzReadCurrentFile(file, m_MMU_VM.Imem(), 0x1000); - unzCloseCurrentFile(file); - port = unzGoToFirstFile(file); - LoadedZipFile = true; - continue; - } - if (LoadedZipFile && Value == 0x56D2CD23 && port == UNZ_OK) - { - m_SystemTimer.LoadData(file); - } - unzCloseCurrentFile(file); - port = unzGoToNextFile(file); - } - unzClose(file); - } - if (!LoadedZipFile) - { - HANDLE hSaveFile = CreateFile(FileNameStr.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); - if (hSaveFile == INVALID_HANDLE_VALUE) - { - g_Notify->DisplayMessage(5, stdstr_f("%s %s", GS(MSG_UNABLED_LOAD_STATE), FileNameStr.c_str()).c_str()); - return false; - } - - SetFilePointer(hSaveFile, 0, NULL, FILE_BEGIN); - DWORD dwRead; - ReadFile(hSaveFile, &Value, sizeof(Value), &dwRead, NULL); - if (Value != 0x23D8A6C8) - { - return false; - } - - ReadFile(hSaveFile, &SaveRDRAMSize, sizeof(SaveRDRAMSize), &dwRead, NULL); - //Check header - uint8_t LoadHeader[64]; - ReadFile(hSaveFile, LoadHeader, 0x40, &dwRead, NULL); - if (memcmp(LoadHeader, g_Rom->GetRomAddress(), 0x40) != 0) - { - //if (inFullScreen) { return false; } - int result = MessageBoxW(NULL, wGS(MSG_SAVE_STATE_HEADER).c_str(), wGS(MSG_MSGBOX_TITLE).c_str(), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2); - - if (result == IDNO) - { - return false; - } - } - Reset(false, true); - m_MMU_VM.UnProtectMemory(0x80000000, 0x80000000 + g_Settings->LoadDword(Game_RDRamSize) - 4); - m_MMU_VM.UnProtectMemory(0xA4000000, 0xA4001FFC); - g_Settings->SaveDword(Game_RDRamSize, SaveRDRAMSize); - - ReadFile(hSaveFile, &NextVITimer, sizeof(NextVITimer), &dwRead, NULL); - ReadFile(hSaveFile, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER), &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_GPR, sizeof(int64_t) * 32, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_FPR, sizeof(int64_t) * 32, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_CP0, sizeof(uint32_t) * 32, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_FPCR, sizeof(uint32_t) * 32, &dwRead, NULL); - ReadFile(hSaveFile, &m_Reg.m_HI, sizeof(int64_t), &dwRead, NULL); - ReadFile(hSaveFile, &m_Reg.m_LO, sizeof(int64_t), &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8, &dwRead, NULL); - ReadFile(hSaveFile, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4, &dwRead, NULL); - ReadFile(hSaveFile, (void *const)&g_TLB->TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32, &dwRead, NULL); - ReadFile(hSaveFile, m_MMU_VM.PifRam(), 0x40, &dwRead, NULL); - ReadFile(hSaveFile, m_MMU_VM.Rdram(), SaveRDRAMSize, &dwRead, NULL); - ReadFile(hSaveFile, m_MMU_VM.Dmem(), 0x1000, &dwRead, NULL); - ReadFile(hSaveFile, m_MMU_VM.Imem(), 0x1000, &dwRead, NULL); - CloseHandle(hSaveFile); - } - - //Fix losing audio in certain games with certain plugins - AudioResetOnLoad = g_Settings->LoadBool(Game_AudioResetOnLoad); - if (AudioResetOnLoad) - { - m_Reg.m_AudioIntrReg |= MI_INTR_AI; - m_Reg.AI_STATUS_REG &= ~AI_STATUS_FIFO_FULL; - g_Reg->MI_INTR_REG |= MI_INTR_AI; - } - - if (bFixedAudio()) - { - m_Audio.SetFrequency(m_Reg.AI_DACRATE_REG, g_System->SystemType()); - } - - if (old_status != g_Reg->VI_STATUS_REG) - { - g_Plugins->Gfx()->ViStatusChanged(); - } - - if (old_width != g_Reg->VI_WIDTH_REG) - { - g_Plugins->Gfx()->ViWidthChanged(); - } - - if (old_dacrate != g_Reg->AI_DACRATE_REG) - { - g_Plugins->Audio()->DacrateChanged(g_System->SystemType()); - } - - //Fix Random Register - while ((int)m_Reg.RANDOM_REGISTER < (int)m_Reg.WIRED_REGISTER) - { - m_Reg.RANDOM_REGISTER += 32 - m_Reg.WIRED_REGISTER; - } - //Fix up timer - WriteTrace(TraceN64System, TraceDebug, "2"); - m_SystemTimer.SetTimer(CSystemTimer::CompareTimer, m_Reg.COMPARE_REGISTER - m_Reg.COUNT_REGISTER, false); - m_SystemTimer.SetTimer(CSystemTimer::ViTimer, NextVITimer, false); - m_Reg.FixFpuLocations(); - WriteTrace(TraceN64System, TraceDebug, "5"); - m_TLB.Reset(false); - WriteTrace(TraceN64System, TraceDebug, "6"); - m_CPU_Usage.ResetCounters(); - WriteTrace(TraceN64System, TraceDebug, "7"); - m_Profile.ResetCounters(); - WriteTrace(TraceN64System, TraceDebug, "8"); - m_FPS.Reset(true); - WriteTrace(TraceN64System, TraceDebug, "9"); - if (bLogX86Code()) - { - Stop_x86_Log(); - Start_x86_Log(); - } - WriteTrace(TraceN64System, TraceDebug, "Done"); - -#ifdef TEST_SP_TRACKING - m_CurrentSP = GPR[29].UW[0]; -#endif - if (bFastSP() && m_Recomp) { m_Recomp->ResetMemoryStackPos(); } - - if (g_Settings->LoadDword(Game_CpuType) == CPU_SyncCores) - { - if (m_SyncCPU) - { - for (int i = 0; i < (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])); i++) - { - m_LastSuccessSyncPC[i] = 0; - } - m_SyncCPU->SetActiveSystem(true); - m_SyncCPU->LoadState(FileNameStr.c_str()); - SetActiveSystem(true); - SyncCPU(m_SyncCPU); - } - } - WriteTrace(TraceN64System, TraceDebug, "13"); - std::string LoadMsg = g_Lang->GetString(MSG_LOADED_STATE); - g_Notify->DisplayMessage(5, stdstr_f("%s %s", LoadMsg.c_str(), stdstr(CPath(FileNameStr).GetNameExtension()).c_str()).c_str()); - WriteTrace(TraceN64System, TraceDebug, "Done"); - return true; -} - -void CN64System::DisplayRSPListCount() -{ - g_Notify->DisplayMessage(0, stdstr_f("Dlist: %d Alist: %d Unknown: %d", m_DlistCount, m_AlistCount, m_UnknownCount).c_str()); -} - -void CN64System::RunRSP() -{ - WriteTrace(TraceRSP, TraceDebug, "Start (SP Status %X)", m_Reg.SP_STATUS_REG); - if ((m_Reg.SP_STATUS_REG & SP_STATUS_HALT) == 0) - { - if ((m_Reg.SP_STATUS_REG & SP_STATUS_BROKE) == 0) - { - SPECIAL_TIMERS CPU_UsageAddr = Timer_None/*, ProfileAddr = Timer_None*/; - - uint32_t Task = 0; - if (m_RspBroke) - { - g_MMU->LW_VAddr(0xA4000FC0, Task); - if (Task == 1 && (m_Reg.DPC_STATUS_REG & DPC_STATUS_FREEZE) != 0) - { - WriteTrace(TraceRSP, TraceDebug, "Dlist that is frozen"); - return; - } - - switch (Task) - { - case 1: - WriteTrace(TraceRSP, TraceDebug, "*** Display list ***"); - m_DlistCount += 1; - m_FPS.UpdateDlCounter(); - break; - case 2: - WriteTrace(TraceRSP, TraceDebug, "*** Audio list ***"); - m_AlistCount += 1; - break; - default: - WriteTrace(TraceRSP, TraceDebug, "*** Unknown list ***"); - m_UnknownCount += 1; - break; - } - - if (bShowDListAListCount()) - { - DisplayRSPListCount(); - } - if (bShowCPUPer()) - { - switch (Task) - { - case 1: CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RSP_Dlist); break; - case 2: CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RSP_Alist); break; - default: CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RSP_Unknown); break; - } - } - } - - __try - { - WriteTrace(TraceRSP, TraceDebug, "do cycles - starting"); - g_Plugins->RSP()->DoRspCycles(100); - WriteTrace(TraceRSP, TraceDebug, "do cycles - Done"); - } - __except (g_MMU->MemoryFilter(GetExceptionCode(), GetExceptionInformation())) - { - WriteTrace(TraceRSP, TraceError, "exception generated"); - g_Notify->FatalError(__FUNCTION__ "\nUnknown memory action\n\nEmulation stop"); - } - - if (Task == 1 && bDelayDP() && ((m_Reg.m_GfxIntrReg & MI_INTR_DP) != 0)) - { - g_SystemTimer->SetTimer(CSystemTimer::RSPTimerDlist, 0x1000, false); - m_Reg.m_GfxIntrReg &= ~MI_INTR_DP; - } - if (bShowCPUPer()) { m_CPU_Usage.StartTimer(CPU_UsageAddr); } - //if (bProfiling) { m_Profile.StartTimer(ProfileAddr); } - - if ((m_Reg.SP_STATUS_REG & SP_STATUS_HALT) == 0 && - (m_Reg.SP_STATUS_REG & SP_STATUS_BROKE) == 0 && - m_Reg.m_RspIntrReg == 0) - { - g_SystemTimer->SetTimer(CSystemTimer::RspTimer, 0x200, false); - m_RspBroke = false; - } - else - { - m_RspBroke = true; - } - WriteTrace(TraceRSP, TraceDebug, "check interrupts"); - g_Reg->CheckInterrupts(); - } - } - WriteTrace(TraceRSP, TraceDebug, "Done (SP Status %X)", m_Reg.SP_STATUS_REG); -} - -void CN64System::SyncToAudio() -{ - if (!bSyncToAudio() || !bLimitFPS()) - { - return; - } - SPECIAL_TIMERS CPU_UsageAddr = Timer_None; - - if (bShowCPUPer()) { CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_Idel); } - - for (int i = 0; i < 50; i++) - { - if (g_Reg->m_AudioIntrReg != 0) - { - WriteTrace(TraceAudio, TraceDebug, "Audio Interrupt done (%d)", i); - break; - } - pjutil::Sleep(1); - } - if (bShowCPUPer()) - { - m_CPU_Usage.StartTimer(CPU_UsageAddr != Timer_None ? CPU_UsageAddr : Timer_R4300); - } -} - -void CN64System::RefreshScreen() -{ - SPECIAL_TIMERS CPU_UsageAddr = Timer_None/*, ProfilingAddr = Timer_None*/; - uint32_t VI_INTR_TIME = 500000; - - if (bShowCPUPer()) { CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RefreshScreen); } - //if (bProfiling) { ProfilingAddr = m_Profile.StartTimer(Timer_RefreshScreen); } - - //Calculate how many cycles to next refresh - if (m_Reg.VI_V_SYNC_REG == 0) - { - VI_INTR_TIME = 500000; - } - else - { - VI_INTR_TIME = (m_Reg.VI_V_SYNC_REG + 1) * ViRefreshRate(); - if ((m_Reg.VI_V_SYNC_REG % 1) != 0) - { - VI_INTR_TIME -= 38; - } - } - g_SystemTimer->SetTimer(CSystemTimer::ViTimer, VI_INTR_TIME, true); - if (bFixedAudio()) - { - g_Audio->SetViIntr(VI_INTR_TIME); - } - if (g_Plugins->Control()->GetKeys) - { - BUTTONS Keys; - memset(&Keys, 0, sizeof(Keys)); - - for (int Control = 0; Control < 4; Control++) - { - g_Plugins->Control()->GetKeys(Control, &Keys); - m_Buttons[Control] = Keys.Value; - } - } - - if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_UpdateScreen); } - // if (bProfiling) { m_Profile.StartTimer(Timer_UpdateScreen); } - - __try - { - WriteTrace(TraceGFXPlugin, TraceDebug, "Starting"); - g_Plugins->Gfx()->UpdateScreen(); - WriteTrace(TraceGFXPlugin, TraceDebug, "Done"); - } - __except (g_MMU->MemoryFilter(GetExceptionCode(), GetExceptionInformation())) - { - WriteTrace(TraceGFXPlugin, TraceError, "Exception caught"); - } - g_MMU->UpdateFieldSerration((m_Reg.VI_STATUS_REG & 0x40) != 0); - - if ((bBasicMode() || bLimitFPS()) && !bSyncToAudio()) - { - if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_Idel); } - uint32_t FrameRate; - if (m_Limiter.Timer_Process(&FrameRate) && bDisplayFrameRate()) - { - m_FPS.DisplayViCounter(FrameRate); - m_bCleanFrameBox = true; - } - } - else if (bDisplayFrameRate()) - { - if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_UpdateFPS); } - m_FPS.UpdateViCounter(); - m_bCleanFrameBox = true; - } - - if (m_bCleanFrameBox && !bDisplayFrameRate()) - { - m_FPS.Reset(true); - m_bCleanFrameBox = false; - } - - if (bShowCPUPer()) - { - m_CPU_Usage.StopTimer(); - m_CPU_Usage.ShowCPU_Usage(); - m_CPU_Usage.StartTimer(CPU_UsageAddr != Timer_None ? CPU_UsageAddr : Timer_R4300); - } - if ((m_Reg.STATUS_REGISTER & STATUS_IE) != 0) - { - if (HasCheatsSlectionChanged()) - { - if (this == g_BaseSystem && g_SyncSystem != NULL) - { - g_SyncSystem->SetCheatsSlectionChanged(true); - } - SetCheatsSlectionChanged(false); - m_Cheats.LoadCheats(false, g_BaseSystem->m_Plugins); - } - m_Cheats.ApplyCheats(g_MMU); - } - // if (bProfiling) { m_Profile.StartTimer(ProfilingAddr != Timer_None ? ProfilingAddr : Timer_R4300); } -} - -void CN64System::TLB_Mapped(uint32_t VAddr, uint32_t Len, uint32_t PAddr, bool bReadOnly) -{ - m_MMU_VM.TLB_Mapped(VAddr, Len, PAddr, bReadOnly); -} - -void CN64System::TLB_Unmaped(uint32_t VAddr, uint32_t Len) -{ - m_MMU_VM.TLB_Unmaped(VAddr, Len); - if (m_Recomp && bSMM_TLB()) - { - m_Recomp->ClearRecompCode_Virt(VAddr, Len, CRecompiler::Remove_TLB); - } -} - -void CN64System::TLB_Changed() -{ - if (g_Debugger) - { - g_Debugger->TLBChanged(); - } +/**************************************************************************** +* * +* Project64 - A Nintendo 64 emulator. * +* http://www.pj64-emu.com/ * +* Copyright (C) 2012 Project64. All rights reserved. * +* * +* License: * +* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * +* * +****************************************************************************/ +#include "stdafx.h" +#include "N64Class.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma warning(disable:4355) // Disable 'this' : used in base member initializer list + +#include +#include + +CN64System::CN64System(CPlugins * Plugins, bool SavesReadOnly) : +CSystemEvents(this, Plugins), +m_EndEmulation(false), +m_SaveUsing((SAVE_CHIP_TYPE)g_Settings->LoadDword(Game_SaveChip)), +m_Plugins(Plugins), +m_SyncCPU(NULL), +m_SyncPlugins(NULL), +m_MMU_VM(SavesReadOnly), +m_TLB(this), +m_Reg(this, this), +m_Recomp(NULL), +m_InReset(false), +m_NextTimer(0), +m_SystemTimer(m_NextTimer), +m_bCleanFrameBox(true), +m_bInitialized(false), +m_RspBroke(true), +m_DMAUsed(false), +m_TestTimer(false), +m_NextInstruction(0), +m_JumpToLocation(0), +m_TLBLoadAddress(0), +m_TLBStoreAddress(0), +m_SyncCount(0), +m_CPU_Handle(NULL), +m_CPU_ThreadID(0), +m_hPauseEvent(true), +m_CheatsSlectionChanged(false) +{ + uint32_t gameHertz = g_Settings->LoadDword(Game_ScreenHertz); + if (gameHertz == 0) + { + gameHertz = (SystemType() == SYSTEM_PAL) ? 50 : 60; + } + m_Limiter.SetHertz(gameHertz); + g_Settings->SaveDword(GameRunning_ScreenHertz, gameHertz); + m_Cheats.LoadCheats(!g_Settings->LoadDword(Setting_RememberCheats), Plugins); +} + +CN64System::~CN64System() +{ + SetActiveSystem(false); + Mempak::Close(); + if (m_SyncCPU) + { + m_SyncCPU->CpuStopped(); + delete m_SyncCPU; + m_SyncCPU = NULL; + } + if (m_Recomp) + { + delete m_Recomp; + m_Recomp = NULL; + } + if (m_SyncPlugins) + { + delete m_SyncPlugins; + m_SyncPlugins = NULL; + } +} + +void CN64System::ExternalEvent(SystemEvent action) +{ + switch (action) + { + case SysEvent_Profile_GenerateLogs: + case SysEvent_Profile_StartStop: + case SysEvent_Profile_ResetLogs: + case SysEvent_ExecuteInterrupt: + case SysEvent_SaveMachineState: + case SysEvent_LoadMachineState: + case SysEvent_ChangingFullScreen: + case SysEvent_GSButtonPressed: + case SysEvent_ResetCPU_SoftDone: + case SysEvent_Interrupt_SP: + case SysEvent_Interrupt_SI: + case SysEvent_Interrupt_AI: + case SysEvent_Interrupt_VI: + case SysEvent_Interrupt_PI: + case SysEvent_Interrupt_DP: + case SysEvent_ResetCPU_Hard: + case SysEvent_ResetCPU_Soft: + case SysEvent_CloseCPU: + case SysEvent_ChangePlugins: + QueueEvent(action); + break; + case SysEvent_PauseCPU_FromMenu: + case SysEvent_PauseCPU_AppLostFocus: + case SysEvent_PauseCPU_AppLostActive: + case SysEvent_PauseCPU_SaveGame: + case SysEvent_PauseCPU_LoadGame: + case SysEvent_PauseCPU_DumpMemory: + case SysEvent_PauseCPU_SearchMemory: + case SysEvent_PauseCPU_Settings: + case SysEvent_PauseCPU_Cheats: + if (!g_Settings->LoadBool(GameRunning_CPU_Paused)) + { + QueueEvent(action); + } + break; + case SysEvent_ResumeCPU_FromMenu: + // always resume if from menu + m_hPauseEvent.Trigger(); + break; + case SysEvent_ResumeCPU_AppGainedFocus: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_AppLostFocus) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_AppGainedActive: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_AppLostActive) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_SaveGame: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_SaveGame) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_LoadGame: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_LoadGame) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_DumpMemory: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_DumpMemory) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_SearchMemory: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_SearchMemory) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_Settings: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_Settings) + { + m_hPauseEvent.Trigger(); + } + break; + case SysEvent_ResumeCPU_Cheats: + if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_Cheats) + { + m_hPauseEvent.Trigger(); + } + break; + default: + WriteTrace(TraceN64System, TraceError, "Unknown event %d", action); + g_Notify->BreakPoint(__FILE__, __LINE__); + } +} + +bool CN64System::RunFileImage(const char * FileLoc) +{ + WriteTrace(TraceN64System, TraceDebug, "FileLoc: %s", FileLoc); + CloseSystem(); + g_Settings->SaveBool(Setting_EnableDisk, false); + if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) + { + WriteTrace(TraceN64System, TraceError, "game loading is in progress, can not load new file"); + return false; + } + + //Mark the rom as loading + WriteTrace(TraceN64System, TraceDebug, "Mark Rom as loading"); + g_Settings->SaveString(Game_File, ""); + g_Settings->SaveBool(GameRunning_LoadingInProgress, true); + + //Try to load the passed N64 rom + if (g_Rom == NULL) + { + WriteTrace(TraceN64System, TraceDebug, "Allocating global rom object"); + g_Rom = new CN64Rom(); + } + else + { + WriteTrace(TraceN64System, TraceDebug, "Use existing global rom object"); + } + + WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc); + if (g_Rom->LoadN64Image(FileLoc)) + { + if (g_Rom->CicChipID() == CIC_NUS_8303) + { + //64DD IPL + g_DDRom = g_Rom; + g_Settings->SaveString(File_DiskIPLPath, FileLoc); + } + + if (g_DDRom != NULL) + { + g_Settings->SaveBool(Setting_EnableDisk, true); + } + + g_System->RefreshGameSettings(); + + g_Settings->SaveString(Game_File, FileLoc); + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + + WriteTrace(TraceN64System, TraceDebug, "Finished Loading (GoodName: %s)", g_Settings->LoadStringVal(Game_GoodName).c_str()); + + if (g_Settings->LoadBool(Setting_AutoStart) != 0) + { + WriteTrace(TraceN64System, TraceDebug, "Automattically starting rom"); + g_BaseSystem = new CN64System(g_Plugins, false); + if (g_BaseSystem) + { + g_BaseSystem->StartEmulation(true); + } + } + } + else + { + WriteTrace(TraceN64System, TraceError, "LoadN64Image failed (\"%s\")", FileLoc); + g_Notify->DisplayError(g_Rom->GetError()); + delete g_Rom; + g_Rom = NULL; + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + return false; + } + return true; +} + +bool CN64System::RunFileImageIPL(const char * FileLoc) +{ + CloseSystem(); + if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) + { + return false; + } + + //Mark the rom as loading + WriteTrace(TraceN64System, TraceDebug, "Mark DDRom as loading"); + //g_Settings->SaveString(Game_File, ""); + g_Settings->SaveBool(GameRunning_LoadingInProgress, true); + + //Try to load the passed N64 DDrom + if (g_DDRom == NULL) + { + WriteTrace(TraceN64System, TraceDebug, "Allocating global DDrom object"); + g_DDRom = new CN64Rom(); + } + else + { + WriteTrace(TraceN64System, TraceDebug, "Use existing global DDrom object"); + } + + WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc); + if (g_DDRom->LoadN64ImageIPL(FileLoc)) + { + if (g_DDRom->CicChipID() != CIC_NUS_8303) + { + //If not 64DD IPL then it's wrong + WriteTrace(TraceN64System, TraceError, "LoadN64ImageIPL failed (\"%s\")", FileLoc); + g_Notify->DisplayError(g_DDRom->GetError()); + delete g_DDRom; + g_DDRom = NULL; + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + return false; + } + + g_System->RefreshGameSettings(); + + g_Settings->SaveString(File_DiskIPLPath, FileLoc); + + //g_Settings->SaveString(Game_File, FileLoc); + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + } + else + { + WriteTrace(TraceN64System, TraceError, "LoadN64ImageIPL failed (\"%s\")", FileLoc); + g_Notify->DisplayError(g_DDRom->GetError()); + delete g_DDRom; + g_DDRom = NULL; + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + return false; + } + return true; +} + +bool CN64System::RunDiskImage(const char * FileLoc) +{ + CloseSystem(); + if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) + { + return false; + } + + //Mark the rom as loading + WriteTrace(TraceN64System, TraceDebug, "Mark Disk as loading"); + //g_Settings->SaveString(Game_File, ""); + g_Settings->SaveBool(GameRunning_LoadingInProgress, true); + + //Try to load the passed N64 Disk + if (g_Disk == NULL) + { + WriteTrace(TraceN64System, TraceDebug, "Allocating global Disk object"); + g_Disk = new CN64Disk(); + } + else + { + WriteTrace(TraceN64System, TraceDebug, "Use existing global Disk object"); + } + + WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc); + if (g_Disk->LoadDiskImage(FileLoc)) + { + g_System->RefreshGameSettings(); + + //g_Settings->SaveString(Game_File, FileLoc); + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + } + else + { + WriteTrace(TraceN64System, TraceError, "LoadDiskImage failed (\"%s\")", FileLoc); + g_Notify->DisplayError(g_Disk->GetError()); + delete g_Disk; + g_Disk = NULL; + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + return false; + } + return true; +} + +void CN64System::CloseSystem() +{ + if (g_BaseSystem) + { + g_BaseSystem->CloseCpu(); + delete g_BaseSystem; + g_BaseSystem = NULL; + } +} + +bool CN64System::EmulationStarting(void * hThread, uint32_t ThreadId) +{ + bool bRes = true; + + WriteTrace(TraceN64System, TraceDebug, "Setting N64 system as active"); + if (g_BaseSystem->SetActiveSystem(true)) + { + g_BaseSystem->m_CPU_Handle = hThread; + g_BaseSystem->m_CPU_ThreadID = ThreadId; + WriteTrace(TraceN64System, TraceDebug, "Setting up N64 system done"); + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + try + { + WriteTrace(TraceN64System, TraceDebug, "Game starting"); + g_BaseSystem->StartEmulation2(false); + WriteTrace(TraceN64System, TraceDebug, "Game Done"); + } + catch (...) + { + g_Notify->DisplayError(stdstr_f("%s: Exception caught\nFile: %s\nLine: %d", __FUNCTION__, __FILE__, __LINE__).c_str()); + } + } + else + { + WriteTrace(TraceN64System, TraceError, "SetActiveSystem failed"); + g_Notify->DisplayError(stdstr_f("%s: Failed to Initialize N64 System", __FUNCTION__).c_str()); + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + bRes = false; + } + return bRes; +} + +void CN64System::StartEmulation2(bool NewThread) +{ + if (NewThread) + { + WriteTrace(TraceN64System, TraceDebug, "Starting"); + if (bHaveDebugger()) + { + StartLog(); + } + + CInterpreterCPU::BuildCPU(); + + uint32_t CpuType = g_Settings->LoadDword(Game_CpuType); + + if (CpuType == CPU_SyncCores && !g_Settings->LoadBool(Debugger_Enabled)) + { + g_Settings->SaveDword(Game_CpuType, CPU_Recompiler); + CpuType = CPU_Recompiler; + } + + if (CpuType == CPU_SyncCores) + { + if (g_Plugins->SyncWindow() == NULL) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + g_Notify->DisplayMessage(5, "Copy Plugins"); + g_Plugins->CopyPlugins(g_Settings->LoadStringVal(Directory_PluginSync)); + m_SyncPlugins = new CPlugins(g_Settings->LoadStringVal(Directory_PluginSync)); + m_SyncPlugins->SetRenderWindows(g_Plugins->SyncWindow(), NULL); + m_SyncCPU = new CN64System(m_SyncPlugins, true); + } + + if (CpuType == CPU_Recompiler || CpuType == CPU_SyncCores) + { + m_Recomp = new CRecompiler(m_Reg, m_Profile, m_EndEmulation); + } + + bool bSetActive = true; + if (m_SyncCPU) + { + bSetActive = m_SyncCPU->SetActiveSystem(); + } + + if (bSetActive) + { + bSetActive = SetActiveSystem(); + } + + if (!bSetActive) + { + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + g_Notify->DisplayError(MSG_PLUGIN_NOT_INIT); + } + else + { + StartEmulationThead(); + } + } + else + { + //mark the emulation as starting and fix up menus + g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED); + + ExecuteCPU(); + } +} + +void CN64System::StartEmulation(bool NewThread) +{ + WriteTrace(TraceN64System, TraceDebug, "Start"); + __except_try() + { + StartEmulation2(NewThread); + } + __except_catch() + { + char message[400]; + sprintf(message, "Exception caught\nFile: %s\nLine: %d", __FILE__, __LINE__); + g_Notify->DisplayError(message); + } + WriteTrace(TraceN64System, TraceDebug, "Done"); +} + +void CN64System::Pause() +{ + if (m_EndEmulation) + { + return; + } + m_hPauseEvent.Reset(); + g_Settings->SaveBool(GameRunning_CPU_Paused, true); + g_Notify->DisplayMessage(5, MSG_CPU_PAUSED); + m_hPauseEvent.IsTriggered(SyncEvent::INFINITE_TIMEOUT); + m_hPauseEvent.Reset(); + g_Settings->SaveBool(GameRunning_CPU_Paused, (uint32_t)false); + g_Notify->DisplayMessage(5, MSG_CPU_RESUMED); +} + +void CN64System::GameReset() +{ + m_SystemTimer.SetTimer(CSystemTimer::SoftResetTimer, 0x3000000, false); + m_Plugins->Gfx()->ShowCFB(); + m_Reg.FAKE_CAUSE_REGISTER |= CAUSE_IP4; + m_Plugins->Gfx()->SoftReset(); + if (m_SyncCPU) + { + m_SyncCPU->GameReset(); + } +} + +void CN64System::PluginReset() +{ + if (!m_Plugins->ResetInUiThread(this)) + { + g_Notify->DisplayMessage(5, MSG_PLUGIN_NOT_INIT); + if (g_BaseSystem) + { + g_BaseSystem->m_EndEmulation = true; + } + } + if (m_SyncCPU) + { + if (!m_SyncCPU->m_Plugins->ResetInUiThread(m_SyncCPU)) + { + g_Notify->DisplayMessage(5, MSG_PLUGIN_NOT_INIT); + if (g_BaseSystem) + { + g_BaseSystem->m_EndEmulation = true; + } + } + } + if (m_Recomp) + { + m_Recomp->Reset(); + } + m_Plugins->RomOpened(); + if (m_SyncCPU) + { + m_SyncCPU->m_Plugins->RomOpened(); + } +#ifdef _WIN32 + _controlfp(_PC_53, _MCW_PC); +#endif +} + +void CN64System::Reset(bool bInitReg, bool ClearMenory) +{ + g_Settings->SaveBool(GameRunning_InReset, true); + RefreshGameSettings(); + m_Audio.Reset(); + m_MMU_VM.Reset(ClearMenory); + Mempak::Close(); + + m_CyclesToSkip = 0; + m_AlistCount = 0; + m_DlistCount = 0; + m_UnknownCount = 0; + m_DMAUsed = false; + m_RspBroke = true; + m_SyncCount = 0; + + for (int i = 0, n = (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])); i < n; i++) + { + m_LastSuccessSyncPC[i] = 0; + } + + if (bInitReg) + { + bool PostPif = true; + + InitRegisters(PostPif, m_MMU_VM); + if (PostPif) + { + memcpy((m_MMU_VM.Dmem() + 0x40), (g_Rom->GetRomAddress() + 0x040), 0xFBC); + } + } + else + { + m_Reg.Reset(); + } + + m_SystemTimer.Reset(); + m_SystemTimer.SetTimer(CSystemTimer::CompareTimer, m_Reg.COMPARE_REGISTER - m_Reg.COUNT_REGISTER, false); + + if (m_Recomp) + { + m_Recomp->Reset(); + } + if (m_Plugins) { m_Plugins->GameReset(); } + if (m_SyncCPU) + { + m_SyncCPU->Reset(bInitReg, ClearMenory); + } + g_Settings->SaveBool(GameRunning_InReset, true); +} + +bool CN64System::SetActiveSystem(bool bActive) +{ + bool bInitPlugin = false; + bool bReset = false; + bool bRes = true; + + if (bActive && g_System == this) + { + return true; + } + + if (bActive) + { + m_Reg.SetAsCurrentSystem(); + + if (g_System) + { + g_System->m_TestTimer = R4300iOp::m_TestTimer; + g_System->m_NextInstruction = R4300iOp::m_NextInstruction; + g_System->m_JumpToLocation = R4300iOp::m_JumpToLocation; + } + + g_System = this; + if (g_BaseSystem == this) + { + g_SyncSystem = m_SyncCPU; + } + g_Recompiler = m_Recomp; + g_MMU = &m_MMU_VM; + g_TLB = &m_TLB; + g_Reg = &m_Reg; + g_Audio = &m_Audio; + g_SystemTimer = &m_SystemTimer; + g_TransVaddr = &m_MMU_VM; + g_SystemEvents = this; + g_NextTimer = &m_NextTimer; + g_Plugins = m_Plugins; + g_TLBLoadAddress = &m_TLBLoadAddress; + g_TLBStoreAddress = &m_TLBStoreAddress; + R4300iOp::m_TestTimer = m_TestTimer; + R4300iOp::m_NextInstruction = m_NextInstruction; + R4300iOp::m_JumpToLocation = m_JumpToLocation; + + if (!m_bInitialized) + { + if (!m_MMU_VM.Initialize()) + { + return false; + } + bReset = true; + m_bInitialized = true; + bInitPlugin = true; + } + } + else + { + if (this == g_BaseSystem) + { + g_System = NULL; + g_SyncSystem = NULL; + g_Recompiler = NULL; + g_MMU = NULL; + g_TLB = NULL; + g_Reg = NULL; + g_Audio = NULL; + g_SystemTimer = NULL; + g_TransVaddr = NULL; + g_SystemEvents = NULL; + g_NextTimer = NULL; + g_Plugins = m_Plugins; + g_TLBLoadAddress = NULL; + g_TLBStoreAddress = NULL; + } + } + + if (bInitPlugin) + { + WriteTrace(TraceN64System, TraceDebug, "Reseting Plugins"); + g_Notify->DisplayMessage(5, MSG_PLUGIN_INIT); + m_Plugins->CreatePlugins(); + bRes = m_Plugins->Initiate(this); + if (!bRes) + { + WriteTrace(TraceN64System, TraceError, "g_Plugins->Initiate Failed"); + } + } + + if (bReset) + { + Reset(true, true); + } + return bRes; +} + +void CN64System::InitRegisters(bool bPostPif, CMipsMemoryVM & MMU) +{ + m_Reg.Reset(); + + //COP0 Registers + m_Reg.RANDOM_REGISTER = 0x1F; + m_Reg.COUNT_REGISTER = 0x5000; + m_Reg.MI_VERSION_REG = 0x02020102; + m_Reg.SP_STATUS_REG = 0x00000001; + m_Reg.CAUSE_REGISTER = 0x0000005C; + m_Reg.CONTEXT_REGISTER = 0x007FFFF0; + m_Reg.EPC_REGISTER = 0xFFFFFFFF; + m_Reg.BAD_VADDR_REGISTER = 0xFFFFFFFF; + m_Reg.ERROREPC_REGISTER = 0xFFFFFFFF; + m_Reg.CONFIG_REGISTER = 0x0006E463; + m_Reg.STATUS_REGISTER = 0x34000000; + + //64DD Registers + m_Reg.ASIC_STATUS = DD_STATUS_RST_STATE; + m_Reg.ASIC_ID_REG = 0x00030000; + + //m_Reg.REVISION_REGISTER = 0x00000511; + m_Reg.FixFpuLocations(); + + if (bPostPif) + { + m_Reg.m_PROGRAM_COUNTER = 0xA4000040; + + m_Reg.m_GPR[0].DW = 0x0000000000000000; + m_Reg.m_GPR[6].DW = 0xFFFFFFFFA4001F0C; + m_Reg.m_GPR[7].DW = 0xFFFFFFFFA4001F08; + m_Reg.m_GPR[8].DW = 0x00000000000000C0; + m_Reg.m_GPR[9].DW = 0x0000000000000000; + m_Reg.m_GPR[10].DW = 0x0000000000000040; + m_Reg.m_GPR[11].DW = 0xFFFFFFFFA4000040; + m_Reg.m_GPR[16].DW = 0x0000000000000000; + m_Reg.m_GPR[17].DW = 0x0000000000000000; + m_Reg.m_GPR[18].DW = 0x0000000000000000; + m_Reg.m_GPR[19].DW = 0x0000000000000000; + m_Reg.m_GPR[21].DW = 0x0000000000000000; + m_Reg.m_GPR[26].DW = 0x0000000000000000; + m_Reg.m_GPR[27].DW = 0x0000000000000000; + m_Reg.m_GPR[28].DW = 0x0000000000000000; + m_Reg.m_GPR[29].DW = 0xFFFFFFFFA4001FF0; + m_Reg.m_GPR[30].DW = 0x0000000000000000; + + switch (g_Rom->GetCountry()) + { + case Germany: case french: case Italian: + case Europe: case Spanish: case Australia: + case X_PAL: case Y_PAL: + switch (g_Rom->CicChipID()) + { + case CIC_UNKNOWN: + case CIC_NUS_6102: + m_Reg.m_GPR[5].DW = 0xFFFFFFFFC0F1D859; + m_Reg.m_GPR[14].DW = 0x000000002DE108EA; + m_Reg.m_GPR[24].DW = 0x0000000000000000; + break; + case CIC_NUS_6103: + m_Reg.m_GPR[5].DW = 0xFFFFFFFFD4646273; + m_Reg.m_GPR[14].DW = 0x000000001AF99984; + m_Reg.m_GPR[24].DW = 0x0000000000000000; + break; + case CIC_NUS_6105: + MMU.SW_VAddr(0xA4001004, 0xBDA807FC); + m_Reg.m_GPR[5].DW = 0xFFFFFFFFDECAAAD1; + m_Reg.m_GPR[14].DW = 0x000000000CF85C13; + m_Reg.m_GPR[24].DW = 0x0000000000000002; + break; + case CIC_NUS_6106: + m_Reg.m_GPR[5].DW = 0xFFFFFFFFB04DC903; + m_Reg.m_GPR[14].DW = 0x000000001AF99984; + m_Reg.m_GPR[24].DW = 0x0000000000000002; + break; + } + m_Reg.m_GPR[20].DW = 0x0000000000000000; + m_Reg.m_GPR[23].DW = 0x0000000000000006; + m_Reg.m_GPR[31].DW = 0xFFFFFFFFA4001554; + break; + case NTSC_BETA: case X_NTSC: case USA: case Japan: + default: + switch (g_Rom->CicChipID()) + { + case CIC_UNKNOWN: + case CIC_NUS_6102: + m_Reg.m_GPR[5].DW = 0xFFFFFFFFC95973D5; + m_Reg.m_GPR[14].DW = 0x000000002449A366; + break; + case CIC_NUS_6103: + m_Reg.m_GPR[5].DW = 0xFFFFFFFF95315A28; + m_Reg.m_GPR[14].DW = 0x000000005BACA1DF; + break; + case CIC_NUS_6105: + MMU.SW_VAddr(0xA4001004, 0x8DA807FC); + m_Reg.m_GPR[5].DW = 0x000000005493FB9A; + m_Reg.m_GPR[14].DW = 0xFFFFFFFFC2C20384; + case CIC_NUS_6106: + m_Reg.m_GPR[5].DW = 0xFFFFFFFFE067221F; + m_Reg.m_GPR[14].DW = 0x000000005CD2B70F; + break; + } + m_Reg.m_GPR[20].DW = 0x0000000000000001; + m_Reg.m_GPR[23].DW = 0x0000000000000000; + m_Reg.m_GPR[24].DW = 0x0000000000000003; + m_Reg.m_GPR[31].DW = 0xFFFFFFFFA4001550; + } + + switch (g_Rom->CicChipID()) + { + case CIC_NUS_6101: + m_Reg.m_GPR[22].DW = 0x000000000000003F; + break; + case CIC_NUS_8303: //64DD IPL CIC + case CIC_NUS_5167: //64DD CONVERSION CIC + m_Reg.m_GPR[22].DW = 0x00000000000000DD; + break; + case CIC_UNKNOWN: + case CIC_NUS_6102: + m_Reg.m_GPR[1].DW = 0x0000000000000001; + m_Reg.m_GPR[2].DW = 0x000000000EBDA536; + m_Reg.m_GPR[3].DW = 0x000000000EBDA536; + m_Reg.m_GPR[4].DW = 0x000000000000A536; + m_Reg.m_GPR[12].DW = 0xFFFFFFFFED10D0B3; + m_Reg.m_GPR[13].DW = 0x000000001402A4CC; + m_Reg.m_GPR[15].DW = 0x000000003103E121; + m_Reg.m_GPR[22].DW = 0x000000000000003F; + m_Reg.m_GPR[25].DW = 0xFFFFFFFF9DEBB54F; + break; + case CIC_NUS_6103: + m_Reg.m_GPR[1].DW = 0x0000000000000001; + m_Reg.m_GPR[2].DW = 0x0000000049A5EE96; + m_Reg.m_GPR[3].DW = 0x0000000049A5EE96; + m_Reg.m_GPR[4].DW = 0x000000000000EE96; + m_Reg.m_GPR[12].DW = 0xFFFFFFFFCE9DFBF7; + m_Reg.m_GPR[13].DW = 0xFFFFFFFFCE9DFBF7; + m_Reg.m_GPR[15].DW = 0x0000000018B63D28; + m_Reg.m_GPR[22].DW = 0x0000000000000078; + m_Reg.m_GPR[25].DW = 0xFFFFFFFF825B21C9; + break; + case CIC_NUS_6105: + MMU.SW_VAddr(0xA4001000, 0x3C0DBFC0); + MMU.SW_VAddr(0xA4001008, 0x25AD07C0); + MMU.SW_VAddr(0xA400100C, 0x31080080); + MMU.SW_VAddr(0xA4001010, 0x5500FFFC); + MMU.SW_VAddr(0xA4001014, 0x3C0DBFC0); + MMU.SW_VAddr(0xA4001018, 0x8DA80024); + MMU.SW_VAddr(0xA400101C, 0x3C0BB000); + m_Reg.m_GPR[1].DW = 0x0000000000000000; + m_Reg.m_GPR[2].DW = 0xFFFFFFFFF58B0FBF; + m_Reg.m_GPR[3].DW = 0xFFFFFFFFF58B0FBF; + m_Reg.m_GPR[4].DW = 0x0000000000000FBF; + m_Reg.m_GPR[12].DW = 0xFFFFFFFF9651F81E; + m_Reg.m_GPR[13].DW = 0x000000002D42AAC5; + m_Reg.m_GPR[15].DW = 0x0000000056584D60; + m_Reg.m_GPR[22].DW = 0x0000000000000091; + m_Reg.m_GPR[25].DW = 0xFFFFFFFFCDCE565F; + break; + case CIC_NUS_6106: + m_Reg.m_GPR[1].DW = 0x0000000000000000; + m_Reg.m_GPR[2].DW = 0xFFFFFFFFA95930A4; + m_Reg.m_GPR[3].DW = 0xFFFFFFFFA95930A4; + m_Reg.m_GPR[4].DW = 0x00000000000030A4; + m_Reg.m_GPR[12].DW = 0xFFFFFFFFBCB59510; + m_Reg.m_GPR[13].DW = 0xFFFFFFFFBCB59510; + m_Reg.m_GPR[15].DW = 0x000000007A3C07F4; + m_Reg.m_GPR[22].DW = 0x0000000000000085; + m_Reg.m_GPR[25].DW = 0x00000000465E3F72; + break; + } + } + else + { + m_Reg.m_PROGRAM_COUNTER = 0xBFC00000; + /* PIF_Ram[36] = 0x00; PIF_Ram[39] = 0x3F; //common pif ram start values + + switch (g_Rom->CicChipID()) { + case CIC_NUS_6101: PIF_Ram[37] = 0x06; PIF_Ram[38] = 0x3F; break; + case CIC_UNKNOWN: + case CIC_NUS_6102: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x3F; break; + case CIC_NUS_6103: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x78; break; + case CIC_NUS_6105: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x91; break; + case CIC_NUS_6106: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x85; break; + }*/ + } +} + +void CN64System::ExecuteCPU() +{ + //reset code + g_Settings->SaveBool(GameRunning_CPU_Paused, false); + g_Settings->SaveBool(GameRunning_CPU_Running, true); + g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED); + + m_EndEmulation = false; + + m_Plugins->RomOpened(); + if (m_SyncCPU) + { + m_SyncCPU->m_Plugins->RomOpened(); + } +#ifdef _WIN32 + _controlfp(_PC_53, _MCW_PC); +#endif + + switch ((CPU_TYPE)g_Settings->LoadDword(Game_CpuType)) + { + // Currently the compiler is 32-bit only. We might have to ignore that RDB setting for now. +#ifdef _WIN32 + case CPU_Recompiler: ExecuteRecompiler(); break; + case CPU_SyncCores: ExecuteSyncCPU(); break; +#endif + default: ExecuteInterpret(); break; + } + g_Settings->SaveBool(GameRunning_CPU_Running, (uint32_t)false); + m_Plugins->RomClosed(); + if (m_SyncCPU) + { + m_SyncCPU->m_Plugins->RomClosed(); + } +} + +void CN64System::ExecuteInterpret() +{ + SetActiveSystem(); + CInterpreterCPU::ExecuteCPU(); +} + +void CN64System::ExecuteRecompiler() +{ + m_Recomp->Run(); +} + +void CN64System::ExecuteSyncCPU() +{ + m_Recomp->Run(); +} + +void CN64System::CpuStopped() +{ + if (!m_InReset) + { + g_Settings->SaveBool(GameRunning_CPU_Running, (uint32_t)false); + g_Notify->DisplayMessage(5, MSG_EMULATION_ENDED); + } + if (m_SyncCPU) + { + m_SyncCPU->CpuStopped(); + } + m_CPU_Handle = NULL; +} + +void CN64System::UpdateSyncCPU(CN64System * const SecondCPU, uint32_t const Cycles) +{ + int CyclesToExecute = Cycles - m_CyclesToSkip; + + //Update the number of cycles to skip + m_CyclesToSkip -= Cycles; + if (m_CyclesToSkip < 0) { m_CyclesToSkip = 0; } + + //Run the other CPU For the same amount of cycles + if (CyclesToExecute < 0) { return; } + + SecondCPU->SetActiveSystem(true); + + CInterpreterCPU::ExecuteOps(Cycles); + + SetActiveSystem(true); +} + +void CN64System::SyncCPUPC(CN64System * const SecondCPU) +{ + bool ErrorFound = false; + + g_SystemTimer->UpdateTimers(); + if (m_Reg.m_PROGRAM_COUNTER != SecondCPU->m_Reg.m_PROGRAM_COUNTER) + { + ErrorFound = true; + } + + if (m_TLB != SecondCPU->m_TLB) { ErrorFound = true; } + if (m_SystemTimer != SecondCPU->m_SystemTimer) { ErrorFound = true; } + if (m_NextTimer != SecondCPU->m_NextTimer) { ErrorFound = true; } + + if (ErrorFound) { DumpSyncErrors(SecondCPU); } + + for (int i = (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])) - 1; i > 0; i--) + { + m_LastSuccessSyncPC[i] = m_LastSuccessSyncPC[i - 1]; + } + m_LastSuccessSyncPC[0] = m_Reg.m_PROGRAM_COUNTER; +} + +void CN64System::SyncCPU(CN64System * const SecondCPU) +{ + bool ErrorFound = false; + + m_SyncCount += 1; + //WriteTraceF(TraceError,"SyncCPU PC = %08X",m_Reg.m_PROGRAM_COUNTER); + g_SystemTimer->UpdateTimers(); + +#ifdef TEST_SP_TRACKING + if (m_CurrentSP != GPR[29].UW[0]) { + ErrorFound = true; + } +#endif + if (m_Reg.m_PROGRAM_COUNTER != SecondCPU->m_Reg.m_PROGRAM_COUNTER) + { + ErrorFound = true; + } + if (b32BitCore()) + { + for (int count = 0; count < 32; count++) + { + if (m_Reg.m_GPR[count].W[0] != SecondCPU->m_Reg.m_GPR[count].W[0]) + { + ErrorFound = true; + } + if (m_Reg.m_FPR[count].DW != SecondCPU->m_Reg.m_FPR[count].DW) + { + ErrorFound = true; + } + if (m_Reg.m_CP0[count] != SecondCPU->m_Reg.m_CP0[count]) + { + ErrorFound = true; + } + } + } + else + { + for (int count = 0; count < 32; count++) + { + if (m_Reg.m_GPR[count].DW != SecondCPU->m_Reg.m_GPR[count].DW) + { + ErrorFound = true; + } + if (m_Reg.m_FPR[count].DW != SecondCPU->m_Reg.m_FPR[count].DW) + { + ErrorFound = true; + } + if (m_Reg.m_CP0[count] != SecondCPU->m_Reg.m_CP0[count]) + { + ErrorFound = true; + } + } + } + + if (m_TLB != SecondCPU->m_TLB) { ErrorFound = true; } + if (m_Reg.m_FPCR[0] != SecondCPU->m_Reg.m_FPCR[0]) { ErrorFound = true; } + if (m_Reg.m_FPCR[31] != SecondCPU->m_Reg.m_FPCR[31]) { ErrorFound = true; } + if (m_Reg.m_HI.DW != SecondCPU->m_Reg.m_HI.DW) { ErrorFound = true; } + if (m_Reg.m_LO.DW != SecondCPU->m_Reg.m_LO.DW) { ErrorFound = true; } + /*if (m_SyncCount > 4788000) + { + if (memcmp(m_MMU_VM.Rdram(),SecondCPU->m_MMU_VM.Rdram(),RdramSize()) != 0) + { + ErrorFound = true; + } + } + if (memcmp(m_MMU_VM.Imem(),SecondCPU->m_MMU_VM.Imem(),0x1000) != 0) + { + ErrorFound = true; + } + if (memcmp(m_MMU_VM.Dmem(),SecondCPU->m_MMU_VM.Dmem(),0x1000) != 0) + { + ErrorFound = true; + }*/ + + /*for (int z = 0; z < 0x100; z++) + { + if (m_MMU_VM.Rdram()[0x00206970 + z] != SecondCPU->m_MMU_VM.Rdram()[0x00206970 + z]) + { + ErrorFound = true; + break; + } + }*/ + + if (bFastSP() && m_Recomp) + { + if (m_Recomp->MemoryStackPos() != (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))) + { + ErrorFound = true; + } + } + + if (m_SystemTimer != SecondCPU->m_SystemTimer) { ErrorFound = true; } + if (m_NextTimer != SecondCPU->m_NextTimer) { ErrorFound = true; } + if (m_Reg.m_RoundingModel != SecondCPU->m_Reg.m_RoundingModel) { ErrorFound = true; } + + for (int i = 0, n = sizeof(m_Reg.m_Mips_Interface) / sizeof(m_Reg.m_Mips_Interface[0]); i < n; i++) + { + if (m_Reg.m_Mips_Interface[i] != SecondCPU->m_Reg.m_Mips_Interface[i]) + { + ErrorFound = true; + } + } + + for (int i = 0, n = sizeof(m_Reg.m_SigProcessor_Interface) / sizeof(m_Reg.m_SigProcessor_Interface[0]); i < n; i++) + { + if (m_Reg.m_SigProcessor_Interface[i] != SecondCPU->m_Reg.m_SigProcessor_Interface[i]) + { + ErrorFound = true; + } + } + + for (int i = 0, n = sizeof(m_Reg.m_Display_ControlReg) / sizeof(m_Reg.m_Display_ControlReg[0]); i < n; i++) + { + if (m_Reg.m_Display_ControlReg[i] != SecondCPU->m_Reg.m_Display_ControlReg[i]) + { + ErrorFound = true; + } + } + + if (ErrorFound) { DumpSyncErrors(SecondCPU); } + + for (int i = (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])) - 1; i > 0; i--) + { + m_LastSuccessSyncPC[i] = m_LastSuccessSyncPC[i - 1]; + } + m_LastSuccessSyncPC[0] = m_Reg.m_PROGRAM_COUNTER; + // if (PROGRAM_COUNTER == 0x8009BBD8) { + // g_Notify->BreakPoint(__FILE__, __LINE__); + // } +} + +void CN64System::SyncSystem() +{ + SyncCPU(g_SyncSystem); +} + +void CN64System::SyncSystemPC() +{ + SyncCPUPC(g_SyncSystem); +} + +void CN64System::DumpSyncErrors(CN64System * SecondCPU) +{ + int count; + + { + CPath ErrorFile(CPath::MODULE_DIRECTORY); + ErrorFile.AppendDirectory("Logs"); + ErrorFile.SetNameExtension("Sync Errors.txt"); + + CLog Error; + Error.Open(ErrorFile); + Error.Log("Errors:\r\n"); + Error.Log("Register, Recompiler, Interpter\r\n"); +#ifdef TEST_SP_TRACKING + if (m_CurrentSP != GPR[29].UW[0]) + { + Error.Log("m_CurrentSP,%X,%X\r\n", m_CurrentSP, GPR[29].UW[0]); + } +#endif + if (m_Reg.m_PROGRAM_COUNTER != SecondCPU->m_Reg.m_PROGRAM_COUNTER) + { + Error.LogF("PROGRAM_COUNTER 0x%X, 0x%X\r\n", m_Reg.m_PROGRAM_COUNTER, SecondCPU->m_Reg.m_PROGRAM_COUNTER); + } + if (b32BitCore()) + { + for (count = 0; count < 32; count++) + { + if (m_Reg.m_GPR[count].UW[0] != SecondCPU->m_Reg.m_GPR[count].UW[0]) + { + Error.LogF("GPR[%s] 0x%08X%08X, 0x%08X%08X\r\n", CRegName::GPR[count], + m_Reg.m_GPR[count].W[1], m_Reg.m_GPR[count].W[0], + SecondCPU->m_Reg.m_GPR[count].W[1], SecondCPU->m_Reg.m_GPR[count].W[0]); + } + } + } + else + { + for (count = 0; count < 32; count++) + { + if (m_Reg.m_GPR[count].DW != SecondCPU->m_Reg.m_GPR[count].DW) + { + Error.LogF("GPR[%s] 0x%08X%08X, 0x%08X%08X\r\n", CRegName::GPR[count], + m_Reg.m_GPR[count].W[1], m_Reg.m_GPR[count].W[0], + SecondCPU->m_Reg.m_GPR[count].W[1], SecondCPU->m_Reg.m_GPR[count].W[0]); + } + } + } + for (count = 0; count < 32; count++) + { + if (m_Reg.m_FPR[count].DW != SecondCPU->m_Reg.m_FPR[count].DW) + { + Error.LogF("FPR[%s] 0x%08X%08X, 0x%08X%08X\r\n", CRegName::FPR[count], + m_Reg.m_FPR[count].W[1], m_Reg.m_FPR[count].W[0], + SecondCPU->m_Reg.m_FPR[count].W[1], SecondCPU->m_Reg.m_FPR[count].W[0]); + } + } + for (count = 0; count < 32; count++) + { + if (m_Reg.m_FPCR[count] != SecondCPU->m_Reg.m_FPCR[count]) + { + Error.LogF("FPCR[%s] 0x%08X, 0x%08X\r\n", CRegName::FPR_Ctrl[count], + m_Reg.m_FPCR[count], SecondCPU->m_Reg.m_FPCR[count]); + } + } + for (count = 0; count < 32; count++) + { + if (m_Reg.m_CP0[count] != SecondCPU->m_Reg.m_CP0[count]) + { + Error.LogF("CP0[%s] 0x%08X, 0x%08X\r\n", CRegName::Cop0[count], + m_Reg.m_CP0[count], SecondCPU->m_Reg.m_CP0[count]); + } + } + if (m_Reg.m_HI.DW != SecondCPU->m_Reg.m_HI.DW) + { + Error.LogF("HI Reg 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_HI.UW[1], m_Reg.m_HI.UW[0], SecondCPU->m_Reg.m_HI.UW[1], SecondCPU->m_Reg.m_HI.UW[0]); + } + if (m_Reg.m_LO.DW != SecondCPU->m_Reg.m_LO.DW) + { + Error.LogF("LO Reg 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_LO.UW[1], m_Reg.m_LO.UW[0], SecondCPU->m_Reg.m_LO.UW[1], SecondCPU->m_Reg.m_LO.UW[0]); + } + for (int i = 0, n = sizeof(m_Reg.m_Mips_Interface) / sizeof(m_Reg.m_Mips_Interface[0]); i < n; i++) + { + if (m_Reg.m_Mips_Interface[i] != SecondCPU->m_Reg.m_Mips_Interface[i]) + { + Error.LogF("Mips_Interface[%d] 0x%08X, 0x%08X\r\n", i, m_Reg.m_Mips_Interface[i], SecondCPU->m_Reg.m_Mips_Interface[i]); + } + } + + for (int i = 0, n = sizeof(m_Reg.m_SigProcessor_Interface) / sizeof(m_Reg.m_SigProcessor_Interface[0]); i < n; i++) + { + if (m_Reg.m_SigProcessor_Interface[i] != SecondCPU->m_Reg.m_SigProcessor_Interface[i]) + { + Error.LogF("SigProcessor_Interface[%d] 0x%08X, 0x%08X\r\n", i, m_Reg.m_SigProcessor_Interface[i], SecondCPU->m_Reg.m_SigProcessor_Interface[i]); + } + } + for (int i = 0, n = sizeof(m_Reg.m_Display_ControlReg) / sizeof(m_Reg.m_Display_ControlReg[0]); i < n; i++) + { + if (m_Reg.m_Display_ControlReg[i] != SecondCPU->m_Reg.m_Display_ControlReg[i]) + { + Error.LogF("Display_ControlReg[%d] 0x%08X, 0x%08X\r\n", i, m_Reg.m_Display_ControlReg[i], SecondCPU->m_Reg.m_Display_ControlReg[i]); + } + } + + if (m_NextTimer != SecondCPU->m_NextTimer) + { + Error.LogF("Current Time: %X %X\r\n", (uint32_t)m_NextTimer, (uint32_t)SecondCPU->m_NextTimer); + } + m_TLB.RecordDifference(Error, SecondCPU->m_TLB); + m_SystemTimer.RecordDifference(Error, SecondCPU->m_SystemTimer); + if (m_Reg.m_RoundingModel != SecondCPU->m_Reg.m_RoundingModel) + { + Error.LogF("RoundingModel: %X %X\r\n", m_Reg.m_RoundingModel, SecondCPU->m_Reg.m_RoundingModel); + } + if (bFastSP() && m_Recomp) + { + if (m_Recomp->MemoryStackPos() != (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))) + { + Error.LogF("MemoryStack = %X should be: %X\r\n", m_Recomp->MemoryStackPos(), (uint32_t)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))); + } + } + + uint32_t * Rdram = (uint32_t *)m_MMU_VM.Rdram(), *Rdram2 = (uint32_t *)SecondCPU->m_MMU_VM.Rdram(); + for (int z = 0, n = (RdramSize() >> 2); z < n; z++) + { + if (Rdram[z] != Rdram2[z]) + { + Error.LogF("Rdram[%X]: %X %X\r\n", z << 2, Rdram[z], Rdram2[z]); + } + } + + uint32_t * Imem = (uint32_t *)m_MMU_VM.Imem(), *Imem2 = (uint32_t *)SecondCPU->m_MMU_VM.Imem(); + for (int z = 0; z < (0x1000 >> 2); z++) + { + if (Imem[z] != Imem2[z]) + { + Error.LogF("Imem[%X]: %X %X\r\n", z << 2, Imem[z], Imem2[z]); + } + } + uint32_t * Dmem = (uint32_t *)m_MMU_VM.Dmem(), *Dmem2 = (uint32_t *)SecondCPU->m_MMU_VM.Dmem(); + for (int z = 0; z < (0x1000 >> 2); z++) + { + if (Dmem[z] != Dmem2[z]) + { + Error.LogF("Dmem[%X]: %X %X\r\n", z << 2, Dmem[z], Dmem2[z]); + } + } + Error.Log("\r\n"); + Error.Log("Information:\r\n"); + Error.Log("\r\n"); + Error.LogF("PROGRAM_COUNTER,0x%X\r\n", m_Reg.m_PROGRAM_COUNTER); + Error.LogF("Current Timer,0x%X\r\n", m_NextTimer); + Error.LogF("Timer Type,0x%X\r\n", m_SystemTimer.CurrentType()); + Error.Log("\r\n"); + for (int i = 0; i < (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])); i++) + { + Error.LogF("LastSuccessSyncPC[%d],0x%X\r\n", i, m_LastSuccessSyncPC[i]); + } + Error.Log("\r\n"); + for (count = 0; count < 32; count++) + { + Error.LogF("GPR[%s], 0x%08X%08X, 0x%08X%08X\r\n", CRegName::GPR[count], + m_Reg.m_GPR[count].W[1], m_Reg.m_GPR[count].W[0], + SecondCPU->m_Reg.m_GPR[count].W[1], SecondCPU->m_Reg.m_GPR[count].W[0]); + } + Error.Log("\r\n"); + for (count = 0; count < 32; count++) + { + Error.LogF("FPR[%s],%*s0x%08X%08X, 0x%08X%08X\r\n", CRegName::FPR[count], + count < 10 ? 9 : 8, " ", m_Reg.m_FPR[count].W[1], m_Reg.m_FPR[count].W[0], + SecondCPU->m_Reg.m_FPR[count].W[1], SecondCPU->m_Reg.m_FPR[count].W[0]); + } + Error.Log("\r\n"); + for (count = 0; count < 32; count++) + { + Error.LogF("FPR_S[%s],%*s%f, %f\r\n", CRegName::FPR[count], + count < 10 ? 7 : 6, " ", *(m_Reg.m_FPR_S[count]), *(SecondCPU->m_Reg.m_FPR_S[count])); + } + Error.Log("\r\n"); + for (count = 0; count < 32; count++) + { + Error.LogF("FPR_D[%s],%*s%f, %f\r\n", CRegName::FPR[count], + count < 10 ? 7 : 6, " ", *(m_Reg.m_FPR_D[count]), *(SecondCPU->m_Reg.m_FPR_D[count])); + } + Error.Log("\r\n"); + Error.LogF("Rounding Model, 0x%08X, 0x%08X\r\n", m_Reg.m_RoundingModel, SecondCPU->m_Reg.m_RoundingModel); + Error.Log("\r\n"); + for (count = 0; count < 32; count++) + { + Error.LogF("CP0[%s],%*s0x%08X, 0x%08X\r\n", CRegName::Cop0[count], + 12 - strlen(CRegName::Cop0[count]), "", + m_Reg.m_CP0[count], SecondCPU->m_Reg.m_CP0[count]); + } + Error.Log("\r\n"); + Error.LogF("HI 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_HI.UW[1], m_Reg.m_HI.UW[0], + SecondCPU->m_Reg.m_HI.UW[1], SecondCPU->m_Reg.m_HI.UW[0]); + Error.LogF("LO 0x%08X%08X, 0x%08X%08X\r\n", m_Reg.m_LO.UW[1], m_Reg.m_LO.UW[0], + SecondCPU->m_Reg.m_LO.UW[1], SecondCPU->m_Reg.m_LO.UW[0]); + bool bHasTlb = false; + for (count = 0; count < 32; count++) + { + if (!m_TLB.TlbEntry(count).EntryDefined) { continue; } + if (!bHasTlb) + { + Error.Log("\r\n"); + Error.Log(" Hi Recomp, PageMask, Hi Interp, PageMask\r\n"); + bHasTlb = true; + } + Error.LogF("TLB[%2d], %08X, %08X, %08X, %08X\r\n", count, + m_TLB.TlbEntry(count).EntryHi.Value, m_TLB.TlbEntry(count).PageMask.Value, + SecondCPU->m_TLB.TlbEntry(count).EntryHi.Value, SecondCPU->m_TLB.TlbEntry(count).PageMask.Value + ); + } + Error.Log("\r\n"); + Error.Log("Code at PC:\r\n"); + for (count = -10; count < 10; count++) + { + uint32_t OpcodeValue, Addr = m_Reg.m_PROGRAM_COUNTER + (count << 2); + if (g_MMU->LW_VAddr(Addr, OpcodeValue)) + { + Error.LogF("%X: %s\r\n", Addr, R4300iOpcodeName(OpcodeValue, Addr)); + } + } + Error.Log("\r\n"); + Error.Log("Code at Last Sync PC:\r\n"); + for (count = 0; count < 50; count++) + { + uint32_t OpcodeValue, Addr = m_LastSuccessSyncPC[0] + (count << 2); + if (g_MMU->LW_VAddr(Addr, OpcodeValue)) + { + Error.LogF("%X: %s\r\n", Addr, R4300iOpcodeName(OpcodeValue, Addr)); + } + } + } + + g_Notify->DisplayError("Sync Error"); + g_Notify->BreakPoint(__FILE__, __LINE__); +} + +bool CN64System::SaveState() +{ + WriteTrace(TraceN64System, TraceDebug, "Start"); + + // if (!m_SystemTimer.SaveAllowed()) { return false; } + if ((m_Reg.STATUS_REGISTER & STATUS_EXL) != 0) { return false; } + + //Get the file Name + stdstr FileName, ExtraInfoFileName, CurrentSaveName = g_Settings->LoadStringVal(GameRunning_InstantSaveFile); + if (CurrentSaveName.empty()) + { + int Slot = g_Settings->LoadDword(Game_CurrentSaveState); + if (Slot != 0) + { + CurrentSaveName.Format("%s.pj%d", g_Settings->LoadStringVal(Game_GoodName).c_str(), Slot); + } + else + { + CurrentSaveName.Format("%s.pj", g_Settings->LoadStringVal(Game_GoodName).c_str()); + } + FileName.Format("%s%s", g_Settings->LoadStringVal(Directory_InstantSave).c_str(), CurrentSaveName.c_str()); + stdstr_f ZipFileName("%s.zip", FileName.c_str()); + //Make sure the target dir exists + CreateDirectory(g_Settings->LoadStringVal(Directory_InstantSave).c_str(), NULL); + //delete any old save + DeleteFile(FileName.c_str()); + DeleteFile(ZipFileName.c_str()); + ExtraInfoFileName.Format("%s.dat", CurrentSaveName.c_str()); + + //If ziping save add .zip on the end + if (g_Settings->LoadDword(Setting_AutoZipInstantSave)) + { + FileName = ZipFileName; + } + g_Settings->SaveDword(Game_LastSaveSlot, g_Settings->LoadDword(Game_CurrentSaveState)); + } + else + { + char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; + _splitpath(CurrentSaveName.c_str(), drive, dir, fname, ext); + + FileName.Format("%s.pj", CurrentSaveName.c_str()); + + CurrentSaveName.Format("%s.pj", fname); + ExtraInfoFileName.Format("%s.dat", fname); + + //If ziping save add .zip on the end + if (g_Settings->LoadDword(Setting_AutoZipInstantSave)) + { + FileName.Format("%s.zip", FileName.c_str()); + } + } + if (FileName.empty()) { return true; } + + //Open the file + if (g_Settings->LoadDword(Game_FuncLookupMode) == FuncFind_ChangeMemory) + { + if (m_Recomp) + { + m_Recomp->ResetRecompCode(true); + } + } + + uint32_t SaveID_0 = 0x23D8A6C8, SaveID_1 = 0x56D2CD23; + uint32_t RdramSize = g_Settings->LoadDword(Game_RDRamSize); + uint32_t MiInterReg = g_Reg->MI_INTR_REG; + uint32_t NextViTimer = m_SystemTimer.GetTimer(CSystemTimer::ViTimer); + if (g_Settings->LoadDword(Setting_AutoZipInstantSave)) + { + zipFile file; + + file = zipOpen(FileName.c_str(), 0); + zipOpenNewFileInZip(file, CurrentSaveName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + zipWriteInFileInZip(file, &SaveID_0, sizeof(SaveID_0)); + zipWriteInFileInZip(file, &RdramSize, sizeof(uint32_t)); + zipWriteInFileInZip(file, g_Rom->GetRomAddress(), 0x40); + zipWriteInFileInZip(file, &NextViTimer, sizeof(uint32_t)); + zipWriteInFileInZip(file, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER)); + zipWriteInFileInZip(file, m_Reg.m_GPR, sizeof(int64_t) * 32); + zipWriteInFileInZip(file, m_Reg.m_FPR, sizeof(int64_t) * 32); + zipWriteInFileInZip(file, m_Reg.m_CP0, sizeof(uint32_t) * 32); + zipWriteInFileInZip(file, m_Reg.m_FPCR, sizeof(uint32_t) * 32); + zipWriteInFileInZip(file, &m_Reg.m_HI, sizeof(int64_t)); + zipWriteInFileInZip(file, &m_Reg.m_LO, sizeof(int64_t)); + zipWriteInFileInZip(file, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10); + zipWriteInFileInZip(file, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10); + zipWriteInFileInZip(file, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10); + zipWriteInFileInZip(file, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4); + zipWriteInFileInZip(file, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14); + zipWriteInFileInZip(file, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6); + zipWriteInFileInZip(file, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13); + zipWriteInFileInZip(file, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8); + zipWriteInFileInZip(file, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4); + zipWriteInFileInZip(file, (void *const)&m_TLB.TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32); + zipWriteInFileInZip(file, m_MMU_VM.PifRam(), 0x40); + zipWriteInFileInZip(file, m_MMU_VM.Rdram(), RdramSize); + zipWriteInFileInZip(file, m_MMU_VM.Dmem(), 0x1000); + zipWriteInFileInZip(file, m_MMU_VM.Imem(), 0x1000); + zipCloseFileInZip(file); + + zipOpenNewFileInZip(file, ExtraInfoFileName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + zipWriteInFileInZip(file, &SaveID_1, sizeof(SaveID_1)); + m_SystemTimer.SaveData(file); + zipCloseFileInZip(file); + + zipClose(file, ""); + } + else + { + HANDLE hSaveFile = CreateFile(FileName.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + if (hSaveFile == INVALID_HANDLE_VALUE) + { + g_Notify->DisplayError(GS(MSG_FAIL_OPEN_SAVE)); + m_Reg.MI_INTR_REG = MiInterReg; + return true; + } + + //Write info to file + SetFilePointer(hSaveFile, 0, NULL, FILE_BEGIN); + DWORD dwWritten; + WriteFile(hSaveFile, &SaveID_0, sizeof(uint32_t), &dwWritten, NULL); + WriteFile(hSaveFile, &RdramSize, sizeof(uint32_t), &dwWritten, NULL); + WriteFile(hSaveFile, g_Rom->GetRomAddress(), 0x40, &dwWritten, NULL); + WriteFile(hSaveFile, &NextViTimer, sizeof(uint32_t), &dwWritten, NULL); + WriteFile(hSaveFile, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER), &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_GPR, sizeof(int64_t) * 32, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_FPR, sizeof(int64_t) * 32, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_CP0, sizeof(uint32_t) * 32, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_FPCR, sizeof(uint32_t) * 32, &dwWritten, NULL); + WriteFile(hSaveFile, &m_Reg.m_HI, sizeof(int64_t), &dwWritten, NULL); + WriteFile(hSaveFile, &m_Reg.m_LO, sizeof(int64_t), &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8, &dwWritten, NULL); + WriteFile(hSaveFile, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4, &dwWritten, NULL); + WriteFile(hSaveFile, &g_TLB->TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32, &dwWritten, NULL); + WriteFile(hSaveFile, g_MMU->PifRam(), 0x40, &dwWritten, NULL); + WriteFile(hSaveFile, g_MMU->Rdram(), RdramSize, &dwWritten, NULL); + WriteFile(hSaveFile, g_MMU->Dmem(), 0x1000, &dwWritten, NULL); + WriteFile(hSaveFile, g_MMU->Imem(), 0x1000, &dwWritten, NULL); + + CloseHandle(hSaveFile); + } + m_Reg.MI_INTR_REG = MiInterReg; + g_Settings->SaveString(GameRunning_InstantSaveFile, ""); + std::string SaveMessage = g_Lang->GetString(MSG_SAVED_STATE); + + CPath SavedFileName(FileName); + + g_Notify->DisplayMessage(5, stdstr_f("%s %s", SaveMessage.c_str(), stdstr(SavedFileName.GetNameExtension()).c_str()).c_str()); + //Notify().RefreshMenu(); + WriteTrace(TraceN64System, TraceDebug, "Done"); + return true; +} + +bool CN64System::LoadState() +{ + stdstr InstantFileName = g_Settings->LoadStringVal(GameRunning_InstantSaveFile); + if (!InstantFileName.empty()) + { + bool Result = LoadState(InstantFileName.c_str()); + g_Settings->SaveString(GameRunning_InstantSaveFile, ""); + return Result; + } + + CPath FileName(g_Settings->LoadStringVal(Directory_InstantSave).c_str(), ""); + if (g_Settings->LoadDword(Game_CurrentSaveState) != 0) + { + FileName.SetNameExtension(stdstr_f("%s.pj%d", g_Settings->LoadStringVal(Game_GoodName).c_str(), g_Settings->LoadDword(Game_CurrentSaveState)).c_str()); + } + else + { + FileName.SetNameExtension(stdstr_f("%s.pj", g_Settings->LoadStringVal(Game_GoodName).c_str()).c_str()); + } + + CPath ZipFileName; + ZipFileName = (const std::string &)FileName + ".zip"; + + if ((g_Settings->LoadDword(Setting_AutoZipInstantSave) && ZipFileName.Exists()) || FileName.Exists()) + { + if (LoadState(FileName)) + { + return true; + } + } + + //Use old file Name + if (g_Settings->LoadDword(Game_CurrentSaveState) != 0) + { + FileName.SetNameExtension(stdstr_f("%s.pj%d", g_Settings->LoadStringVal(Game_GameName).c_str(), g_Settings->LoadDword(Game_CurrentSaveState)).c_str()); + } + else + { + FileName.SetNameExtension(stdstr_f("%s.pj", g_Settings->LoadStringVal(Game_GameName).c_str()).c_str()); + } + return LoadState(FileName); +} + +bool CN64System::LoadState(const char * FileName) +{ + uint32_t Value, SaveRDRAMSize, NextVITimer = 0, old_status, old_width, old_dacrate; + bool LoadedZipFile = false, AudioResetOnLoad; + old_status = g_Reg->VI_STATUS_REG; + old_width = g_Reg->VI_WIDTH_REG; + old_dacrate = g_Reg->AI_DACRATE_REG; + + WriteTrace(TraceN64System, TraceDebug, "(%s): Start", FileName); + + char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; + _splitpath(FileName, drive, dir, fname, ext); + + stdstr FileNameStr(FileName); + if (g_Settings->LoadDword(Setting_AutoZipInstantSave) || _stricmp(ext, ".zip") == 0) + { + //If ziping save add .zip on the end + if (_stricmp(ext, ".zip") != 0) + { + FileNameStr += ".zip"; + } + unzFile file = unzOpen(FileNameStr.c_str()); + int port = -1; + if (file != NULL) + { + port = unzGoToFirstFile(file); + } + uint32_t Value; + while (port == UNZ_OK) + { + unz_file_info info; + char zname[132]; + + unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0); + if (unzLocateFile(file, zname, 1) != UNZ_OK) + { + unzClose(file); + port = -1; + continue; + } + if (unzOpenCurrentFile(file) != UNZ_OK) + { + unzClose(file); + port = -1; + continue; + } + unzReadCurrentFile(file, &Value, 4); + if (Value != 0x23D8A6C8 && Value != 0x56D2CD23) + { + unzCloseCurrentFile(file); + port = unzGoToNextFile(file); + continue; + } + if (!LoadedZipFile && Value == 0x23D8A6C8 && port == UNZ_OK) + { + unzReadCurrentFile(file, &SaveRDRAMSize, sizeof(SaveRDRAMSize)); + //Check header + + uint8_t LoadHeader[64]; + unzReadCurrentFile(file, LoadHeader, 0x40); + if (memcmp(LoadHeader, g_Rom->GetRomAddress(), 0x40) != 0) + { + //if (inFullScreen) { return false; } + int result = MessageBoxW(NULL, wGS(MSG_SAVE_STATE_HEADER).c_str(), wGS(MSG_MSGBOX_TITLE).c_str(), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2); + + if (result == IDNO) + { + return false; + } + } + Reset(false, true); + + g_MMU->UnProtectMemory(0x80000000, 0x80000000 + g_Settings->LoadDword(Game_RDRamSize) - 4); + g_MMU->UnProtectMemory(0xA4000000, 0xA4001FFC); + g_Settings->SaveDword(Game_RDRamSize, SaveRDRAMSize); + unzReadCurrentFile(file, &NextVITimer, sizeof(NextVITimer)); + unzReadCurrentFile(file, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER)); + unzReadCurrentFile(file, m_Reg.m_GPR, sizeof(int64_t) * 32); + unzReadCurrentFile(file, m_Reg.m_FPR, sizeof(int64_t) * 32); + unzReadCurrentFile(file, m_Reg.m_CP0, sizeof(uint32_t) * 32); + unzReadCurrentFile(file, m_Reg.m_FPCR, sizeof(uint32_t) * 32); + unzReadCurrentFile(file, &m_Reg.m_HI, sizeof(int64_t)); + unzReadCurrentFile(file, &m_Reg.m_LO, sizeof(int64_t)); + unzReadCurrentFile(file, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10); + unzReadCurrentFile(file, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10); + unzReadCurrentFile(file, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10); + unzReadCurrentFile(file, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4); + unzReadCurrentFile(file, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14); + unzReadCurrentFile(file, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6); + unzReadCurrentFile(file, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13); + unzReadCurrentFile(file, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8); + unzReadCurrentFile(file, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4); + unzReadCurrentFile(file, (void *const)&g_TLB->TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32); + unzReadCurrentFile(file, m_MMU_VM.PifRam(), 0x40); + unzReadCurrentFile(file, m_MMU_VM.Rdram(), SaveRDRAMSize); + unzReadCurrentFile(file, m_MMU_VM.Dmem(), 0x1000); + unzReadCurrentFile(file, m_MMU_VM.Imem(), 0x1000); + unzCloseCurrentFile(file); + port = unzGoToFirstFile(file); + LoadedZipFile = true; + continue; + } + if (LoadedZipFile && Value == 0x56D2CD23 && port == UNZ_OK) + { + m_SystemTimer.LoadData(file); + } + unzCloseCurrentFile(file); + port = unzGoToNextFile(file); + } + unzClose(file); + } + if (!LoadedZipFile) + { + HANDLE hSaveFile = CreateFile(FileNameStr.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + if (hSaveFile == INVALID_HANDLE_VALUE) + { + g_Notify->DisplayMessage(5, stdstr_f("%s %s", GS(MSG_UNABLED_LOAD_STATE), FileNameStr.c_str()).c_str()); + return false; + } + + SetFilePointer(hSaveFile, 0, NULL, FILE_BEGIN); + DWORD dwRead; + ReadFile(hSaveFile, &Value, sizeof(Value), &dwRead, NULL); + if (Value != 0x23D8A6C8) + { + return false; + } + + ReadFile(hSaveFile, &SaveRDRAMSize, sizeof(SaveRDRAMSize), &dwRead, NULL); + //Check header + uint8_t LoadHeader[64]; + ReadFile(hSaveFile, LoadHeader, 0x40, &dwRead, NULL); + if (memcmp(LoadHeader, g_Rom->GetRomAddress(), 0x40) != 0) + { + //if (inFullScreen) { return false; } + int result = MessageBoxW(NULL, wGS(MSG_SAVE_STATE_HEADER).c_str(), wGS(MSG_MSGBOX_TITLE).c_str(), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2); + + if (result == IDNO) + { + return false; + } + } + Reset(false, true); + m_MMU_VM.UnProtectMemory(0x80000000, 0x80000000 + g_Settings->LoadDword(Game_RDRamSize) - 4); + m_MMU_VM.UnProtectMemory(0xA4000000, 0xA4001FFC); + g_Settings->SaveDword(Game_RDRamSize, SaveRDRAMSize); + + ReadFile(hSaveFile, &NextVITimer, sizeof(NextVITimer), &dwRead, NULL); + ReadFile(hSaveFile, &m_Reg.m_PROGRAM_COUNTER, sizeof(m_Reg.m_PROGRAM_COUNTER), &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_GPR, sizeof(int64_t) * 32, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_FPR, sizeof(int64_t) * 32, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_CP0, sizeof(uint32_t) * 32, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_FPCR, sizeof(uint32_t) * 32, &dwRead, NULL); + ReadFile(hSaveFile, &m_Reg.m_HI, sizeof(int64_t), &dwRead, NULL); + ReadFile(hSaveFile, &m_Reg.m_LO, sizeof(int64_t), &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_RDRAM_Registers, sizeof(uint32_t) * 10, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_SigProcessor_Interface, sizeof(uint32_t) * 10, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_Display_ControlReg, sizeof(uint32_t) * 10, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_Mips_Interface, sizeof(uint32_t) * 4, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_Video_Interface, sizeof(uint32_t) * 14, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_Audio_Interface, sizeof(uint32_t) * 6, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_Peripheral_Interface, sizeof(uint32_t) * 13, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_RDRAM_Interface, sizeof(uint32_t) * 8, &dwRead, NULL); + ReadFile(hSaveFile, m_Reg.m_SerialInterface, sizeof(uint32_t) * 4, &dwRead, NULL); + ReadFile(hSaveFile, (void *const)&g_TLB->TlbEntry(0), sizeof(CTLB::TLB_ENTRY) * 32, &dwRead, NULL); + ReadFile(hSaveFile, m_MMU_VM.PifRam(), 0x40, &dwRead, NULL); + ReadFile(hSaveFile, m_MMU_VM.Rdram(), SaveRDRAMSize, &dwRead, NULL); + ReadFile(hSaveFile, m_MMU_VM.Dmem(), 0x1000, &dwRead, NULL); + ReadFile(hSaveFile, m_MMU_VM.Imem(), 0x1000, &dwRead, NULL); + CloseHandle(hSaveFile); + } + + //Fix losing audio in certain games with certain plugins + AudioResetOnLoad = g_Settings->LoadBool(Game_AudioResetOnLoad); + if (AudioResetOnLoad) + { + m_Reg.m_AudioIntrReg |= MI_INTR_AI; + m_Reg.AI_STATUS_REG &= ~AI_STATUS_FIFO_FULL; + g_Reg->MI_INTR_REG |= MI_INTR_AI; + } + + if (bFixedAudio()) + { + m_Audio.SetFrequency(m_Reg.AI_DACRATE_REG, g_System->SystemType()); + } + + if (old_status != g_Reg->VI_STATUS_REG) + { + g_Plugins->Gfx()->ViStatusChanged(); + } + + if (old_width != g_Reg->VI_WIDTH_REG) + { + g_Plugins->Gfx()->ViWidthChanged(); + } + + if (old_dacrate != g_Reg->AI_DACRATE_REG) + { + g_Plugins->Audio()->DacrateChanged(g_System->SystemType()); + } + + //Fix Random Register + while ((int)m_Reg.RANDOM_REGISTER < (int)m_Reg.WIRED_REGISTER) + { + m_Reg.RANDOM_REGISTER += 32 - m_Reg.WIRED_REGISTER; + } + //Fix up timer + WriteTrace(TraceN64System, TraceDebug, "2"); + m_SystemTimer.SetTimer(CSystemTimer::CompareTimer, m_Reg.COMPARE_REGISTER - m_Reg.COUNT_REGISTER, false); + m_SystemTimer.SetTimer(CSystemTimer::ViTimer, NextVITimer, false); + m_Reg.FixFpuLocations(); + WriteTrace(TraceN64System, TraceDebug, "5"); + m_TLB.Reset(false); + WriteTrace(TraceN64System, TraceDebug, "6"); + m_CPU_Usage.ResetCounters(); + WriteTrace(TraceN64System, TraceDebug, "7"); + m_Profile.ResetCounters(); + WriteTrace(TraceN64System, TraceDebug, "8"); + m_FPS.Reset(true); + WriteTrace(TraceN64System, TraceDebug, "9"); + if (bLogX86Code()) + { + Stop_x86_Log(); + Start_x86_Log(); + } + WriteTrace(TraceN64System, TraceDebug, "Done"); + +#ifdef TEST_SP_TRACKING + m_CurrentSP = GPR[29].UW[0]; +#endif + if (bFastSP() && m_Recomp) { m_Recomp->ResetMemoryStackPos(); } + + if (g_Settings->LoadDword(Game_CpuType) == CPU_SyncCores) + { + if (m_SyncCPU) + { + for (int i = 0; i < (sizeof(m_LastSuccessSyncPC) / sizeof(m_LastSuccessSyncPC[0])); i++) + { + m_LastSuccessSyncPC[i] = 0; + } + m_SyncCPU->SetActiveSystem(true); + m_SyncCPU->LoadState(FileNameStr.c_str()); + SetActiveSystem(true); + SyncCPU(m_SyncCPU); + } + } + WriteTrace(TraceN64System, TraceDebug, "13"); + std::string LoadMsg = g_Lang->GetString(MSG_LOADED_STATE); + g_Notify->DisplayMessage(5, stdstr_f("%s %s", LoadMsg.c_str(), stdstr(CPath(FileNameStr).GetNameExtension()).c_str()).c_str()); + WriteTrace(TraceN64System, TraceDebug, "Done"); + return true; +} + +void CN64System::DisplayRSPListCount() +{ + g_Notify->DisplayMessage(0, stdstr_f("Dlist: %d Alist: %d Unknown: %d", m_DlistCount, m_AlistCount, m_UnknownCount).c_str()); +} + +void CN64System::RunRSP() +{ + WriteTrace(TraceRSP, TraceDebug, "Start (SP Status %X)", m_Reg.SP_STATUS_REG); + if ((m_Reg.SP_STATUS_REG & SP_STATUS_HALT) == 0) + { + if ((m_Reg.SP_STATUS_REG & SP_STATUS_BROKE) == 0) + { + SPECIAL_TIMERS CPU_UsageAddr = Timer_None/*, ProfileAddr = Timer_None*/; + + uint32_t Task = 0; + if (m_RspBroke) + { + g_MMU->LW_VAddr(0xA4000FC0, Task); + if (Task == 1 && (m_Reg.DPC_STATUS_REG & DPC_STATUS_FREEZE) != 0) + { + WriteTrace(TraceRSP, TraceDebug, "Dlist that is frozen"); + return; + } + + switch (Task) + { + case 1: + WriteTrace(TraceRSP, TraceDebug, "*** Display list ***"); + m_DlistCount += 1; + m_FPS.UpdateDlCounter(); + break; + case 2: + WriteTrace(TraceRSP, TraceDebug, "*** Audio list ***"); + m_AlistCount += 1; + break; + default: + WriteTrace(TraceRSP, TraceDebug, "*** Unknown list ***"); + m_UnknownCount += 1; + break; + } + + if (bShowDListAListCount()) + { + DisplayRSPListCount(); + } + if (bShowCPUPer()) + { + switch (Task) + { + case 1: CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RSP_Dlist); break; + case 2: CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RSP_Alist); break; + default: CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RSP_Unknown); break; + } + } + } + + __except_try() + { + WriteTrace(TraceRSP, TraceDebug, "do cycles - starting"); + g_Plugins->RSP()->DoRspCycles(100); + WriteTrace(TraceRSP, TraceDebug, "do cycles - Done"); + } + __except_catch() + { + WriteTrace(TraceRSP, TraceError, "exception generated"); + g_Notify->FatalError("CN64System::RunRSP()\nUnknown memory action\n\nEmulation stop"); + } + + if (Task == 1 && bDelayDP() && ((m_Reg.m_GfxIntrReg & MI_INTR_DP) != 0)) + { + g_SystemTimer->SetTimer(CSystemTimer::RSPTimerDlist, 0x1000, false); + m_Reg.m_GfxIntrReg &= ~MI_INTR_DP; + } + if (bShowCPUPer()) { m_CPU_Usage.StartTimer(CPU_UsageAddr); } + //if (bProfiling) { m_Profile.StartTimer(ProfileAddr); } + + if ((m_Reg.SP_STATUS_REG & SP_STATUS_HALT) == 0 && + (m_Reg.SP_STATUS_REG & SP_STATUS_BROKE) == 0 && + m_Reg.m_RspIntrReg == 0) + { + g_SystemTimer->SetTimer(CSystemTimer::RspTimer, 0x200, false); + m_RspBroke = false; + } + else + { + m_RspBroke = true; + } + WriteTrace(TraceRSP, TraceDebug, "check interrupts"); + g_Reg->CheckInterrupts(); + } + } + WriteTrace(TraceRSP, TraceDebug, "Done (SP Status %X)", m_Reg.SP_STATUS_REG); +} + +void CN64System::SyncToAudio() +{ + if (!bSyncToAudio() || !bLimitFPS()) + { + return; + } + SPECIAL_TIMERS CPU_UsageAddr = Timer_None; + + if (bShowCPUPer()) { CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_Idel); } + + for (int i = 0; i < 50; i++) + { + if (g_Reg->m_AudioIntrReg != 0) + { + WriteTrace(TraceAudio, TraceDebug, "Audio Interrupt done (%d)", i); + break; + } + pjutil::Sleep(1); + } + if (bShowCPUPer()) + { + m_CPU_Usage.StartTimer(CPU_UsageAddr != Timer_None ? CPU_UsageAddr : Timer_R4300); + } +} + +void CN64System::RefreshScreen() +{ + SPECIAL_TIMERS CPU_UsageAddr = Timer_None/*, ProfilingAddr = Timer_None*/; + uint32_t VI_INTR_TIME = 500000; + + if (bShowCPUPer()) { CPU_UsageAddr = m_CPU_Usage.StartTimer(Timer_RefreshScreen); } + //if (bProfiling) { ProfilingAddr = m_Profile.StartTimer(Timer_RefreshScreen); } + + //Calculate how many cycles to next refresh + if (m_Reg.VI_V_SYNC_REG == 0) + { + VI_INTR_TIME = 500000; + } + else + { + VI_INTR_TIME = (m_Reg.VI_V_SYNC_REG + 1) * ViRefreshRate(); + if ((m_Reg.VI_V_SYNC_REG % 1) != 0) + { + VI_INTR_TIME -= 38; + } + } + g_SystemTimer->SetTimer(CSystemTimer::ViTimer, VI_INTR_TIME, true); + if (bFixedAudio()) + { + g_Audio->SetViIntr(VI_INTR_TIME); + } + if (g_Plugins->Control()->GetKeys) + { + BUTTONS Keys; + memset(&Keys, 0, sizeof(Keys)); + + for (int Control = 0; Control < 4; Control++) + { + g_Plugins->Control()->GetKeys(Control, &Keys); + m_Buttons[Control] = Keys.Value; + } + } + + if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_UpdateScreen); } + // if (bProfiling) { m_Profile.StartTimer(Timer_UpdateScreen); } + + __except_try() + { + WriteTrace(TraceGFXPlugin, TraceDebug, "Starting"); + g_Plugins->Gfx()->UpdateScreen(); + WriteTrace(TraceGFXPlugin, TraceDebug, "Done"); + } + __except_catch() + { + WriteTrace(TraceGFXPlugin, TraceError, "Exception caught"); + } + g_MMU->UpdateFieldSerration((m_Reg.VI_STATUS_REG & 0x40) != 0); + + if ((bBasicMode() || bLimitFPS()) && !bSyncToAudio()) + { + if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_Idel); } + uint32_t FrameRate; + if (m_Limiter.Timer_Process(&FrameRate) && bDisplayFrameRate()) + { + m_FPS.DisplayViCounter(FrameRate); + m_bCleanFrameBox = true; + } + } + else if (bDisplayFrameRate()) + { + if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_UpdateFPS); } + m_FPS.UpdateViCounter(); + m_bCleanFrameBox = true; + } + + if (m_bCleanFrameBox && !bDisplayFrameRate()) + { + m_FPS.Reset(true); + m_bCleanFrameBox = false; + } + + if (bShowCPUPer()) + { + m_CPU_Usage.StopTimer(); + m_CPU_Usage.ShowCPU_Usage(); + m_CPU_Usage.StartTimer(CPU_UsageAddr != Timer_None ? CPU_UsageAddr : Timer_R4300); + } + if ((m_Reg.STATUS_REGISTER & STATUS_IE) != 0) + { + if (HasCheatsSlectionChanged()) + { + if (this == g_BaseSystem && g_SyncSystem != NULL) + { + g_SyncSystem->SetCheatsSlectionChanged(true); + } + SetCheatsSlectionChanged(false); + m_Cheats.LoadCheats(false, g_BaseSystem->m_Plugins); + } + m_Cheats.ApplyCheats(g_MMU); + } + // if (bProfiling) { m_Profile.StartTimer(ProfilingAddr != Timer_None ? ProfilingAddr : Timer_R4300); } +} + +void CN64System::TLB_Mapped(uint32_t VAddr, uint32_t Len, uint32_t PAddr, bool bReadOnly) +{ + m_MMU_VM.TLB_Mapped(VAddr, Len, PAddr, bReadOnly); +} + +void CN64System::TLB_Unmaped(uint32_t VAddr, uint32_t Len) +{ + m_MMU_VM.TLB_Unmaped(VAddr, Len); + if (m_Recomp && bSMM_TLB()) + { + m_Recomp->ClearRecompCode_Virt(VAddr, Len, CRecompiler::Remove_TLB); + } +} + +void CN64System::TLB_Changed() +{ + if (g_Debugger) + { + g_Debugger->TLBChanged(); + } } \ No newline at end of file