/**************************************************************************** * * * Project 64 - 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" #pragma warning(disable:4355) // Disable 'this' : used in base member initializer list #include CN64System::CN64System ( CPlugins * Plugins, bool SavesReadOnly ) : CSystemEvents(this), m_SyncPlugins(NULL), m_SyncWindow(NULL), m_Reg(this,this), m_MMU_VM(this,SavesReadOnly), m_TLB(this), m_FPS(g_Notify), m_Plugins(Plugins), m_Cheats(NULL), m_SyncCPU(NULL), m_Recomp(NULL), m_InReset(false), m_EndEmulation(false), m_bCleanFrameBox(true), m_bInitilized(false), m_SystemTimer(m_NextTimer), m_DMAUsed(false), m_CPU_Handle(NULL), m_CPU_ThreadID(0), m_TestTimer(false), m_NextInstruction(0), m_JumpToLocation(0), m_TLBLoadAddress(0), m_TLBStoreAddress(0), m_SaveUsing((SAVE_CHIP_TYPE)g_Settings->LoadDword(Game_SaveChip)), m_RspBroke(true), m_SyncCount(0) { DWORD gameHertz = g_Settings->LoadDword(Game_ScreenHertz); if (gameHertz == 0) { gameHertz = (SystemType() == SYSTEM_PAL) ? 50 : 60; } m_hPauseEvent = CreateEvent(NULL,true,false,NULL); m_Limitor.SetHertz(gameHertz); g_Settings->SaveDword(GameRunning_ScreenHertz,gameHertz); m_Cheats.LoadCheats(!g_Settings->LoadDword(Setting_RememberCheats)); } CN64System::~CN64System ( void ) { SetActiveSystem(false); 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; } if (m_SyncWindow) { delete m_SyncWindow; m_SyncWindow = 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: if (!g_Settings->LoadBool(GameRunning_CPU_Paused)) { QueueEvent(action); } break; case SysEvent_ResumeCPU_FromMenu: // always resume if from menu SetEvent(m_hPauseEvent); break; case SysEvent_ResumeCPU_AppGainedFocus: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_AppLostFocus ) { SetEvent(m_hPauseEvent); } break; case SysEvent_ResumeCPU_AppGainedActive: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_AppLostActive ) { SetEvent(m_hPauseEvent); } break; case SysEvent_ResumeCPU_SaveGame: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_SaveGame ) { SetEvent(m_hPauseEvent); } break; case SysEvent_ResumeCPU_LoadGame: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_LoadGame ) { SetEvent(m_hPauseEvent); } break; case SysEvent_ResumeCPU_DumpMemory: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_DumpMemory ) { SetEvent(m_hPauseEvent); } break; case SysEvent_ResumeCPU_SearchMemory: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_SearchMemory ) { SetEvent(m_hPauseEvent); } break; case SysEvent_ResumeCPU_Settings: if (g_Settings->LoadDword(GameRunning_CPU_PausedType) == PauseType_Settings ) { SetEvent(m_hPauseEvent); } break; default: WriteTraceF(TraceError,__FUNCTION__ ": Unknown event %d",action); g_Notify->BreakPoint(__FILE__,__LINE__); } } bool CN64System::RunFileImage ( const char * FileLoc ) { CloseSystem(); if (g_Settings->LoadBool(GameRunning_LoadingInProgress)) { return false; } g_Settings->SaveBool(GameRunning_LoadingInProgress,true); WriteTrace(TraceDebug,__FUNCTION__ ": Mark Rom as loading"); //Mark the rom as loading g_Settings->SaveBool(GameRunning_LoadingInProgress,true); g_Notify->RefreshMenu(); //Try to load the passed N64 rom if (g_Rom == NULL) { WriteTrace(TraceDebug,__FUNCTION__ ": Allocating global rom object"); g_Rom = new CN64Rom(); } else { WriteTrace(TraceDebug,__FUNCTION__ ": Use existing global rom object"); } WriteTraceF(TraceDebug,__FUNCTION__ ": Loading \"%s\"",FileLoc); if (g_Rom->LoadN64Image(FileLoc)) { g_System->RefreshGameSettings(); WriteTrace(TraceDebug,__FUNCTION__ ": Add Recent Rom"); g_Notify->AddRecentRom(FileLoc); g_Notify->SetWindowCaption(g_Settings->LoadString(Game_GoodName).c_str()); if (g_Settings->LoadDword(Setting_AutoStart) != 0) { g_BaseSystem = new CN64System(g_Plugins,false); if (g_BaseSystem) { g_BaseSystem->StartEmulation(true); } } g_Settings->SaveBool(GameRunning_LoadingInProgress,false); g_Notify->RefreshMenu(); } else { WriteTraceF(TraceError,__FUNCTION__ ": LoadN64Image failed (\"%s\")",FileLoc); g_Notify->DisplayError(g_Rom->GetError()); delete g_Rom; g_Rom = NULL; g_Settings->SaveBool(GameRunning_LoadingInProgress,false); g_Notify->RefreshMenu(); return false; } return true; } void CN64System::CloseSystem ( void ) { if (g_BaseSystem) { g_BaseSystem->CloseCpu(); delete g_BaseSystem; g_BaseSystem = NULL; } } bool CN64System::EmulationStarting ( HANDLE hThread, DWORD ThreadId ) { bool bRes = true; WriteTrace(TraceDebug, __FUNCTION__ ": Setting N64 system as active"); if (g_BaseSystem->SetActiveSystem(true)) { g_BaseSystem->m_CPU_Handle = hThread; g_BaseSystem->m_CPU_ThreadID = ThreadId; WriteTrace(TraceDebug,__FUNCTION__ ": Setting up N64 system done"); g_Settings->SaveBool(GameRunning_LoadingInProgress,false); g_Notify->RefreshMenu(); try { WriteTrace(TraceDebug,__FUNCTION__ ": Game set to auto start, starting"); g_BaseSystem->StartEmulation2(false); WriteTrace(TraceDebug,__FUNCTION__ ": Game Done"); } catch (...) { WriteTraceF(TraceError,__FUNCTION__ ": Exception caught\nFile: %s\nLine: %d",__FILE__,__LINE__); char Message[600]; sprintf(Message,__FUNCTION__ ": Exception caught\nFile: %s\nLine: %d",__FILE__,__LINE__); MessageBox(NULL,Message,"Exception",MB_OK); } } else { WriteTrace(TraceError,__FUNCTION__ ": SetActiveSystem failed"); g_Notify->DisplayError(__FUNCTION__ ": Failed to Initialize N64 System"); g_Settings->SaveBool(GameRunning_LoadingInProgress,false); g_Notify->RefreshMenu(); bRes = false; } return bRes; } void CN64System::StartEmulation2 ( bool NewThread ) { if (NewThread) { WriteTrace(TraceDebug,__FUNCTION__ ": Starting"); g_Notify->HideRomBrowser(); if (bHaveDebugger()) { LogOptions.GenerateLog = g_Settings->LoadDword(Debugger_GenerateDebugLog); LoadLogOptions(&LogOptions, FALSE); StartLog(); } CInterpreterCPU::BuildCPU(); DWORD 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) { g_Notify->DisplayMessage(5,"Copy Plugins"); g_Plugins->CopyPlugins(g_Settings->LoadString(Directory_PluginSync)); m_SyncWindow = new CMainGui(false); m_SyncPlugins = new CPlugins( g_Settings->LoadString(Directory_PluginSync) ); m_SyncPlugins->SetRenderWindows(m_SyncWindow,m_SyncWindow); 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); g_Notify->RefreshMenu(); g_Notify->ShowRomBrowser(); } g_Notify->MakeWindowOnTop(g_Settings->LoadBool(UserInterface_AlwaysOnTop)); #ifdef BETA_RELEASE if (!g_Settings->LoadBool(Beta_IsValidExe)) { return; } #endif ThreadInfo * Info = new ThreadInfo; HANDLE * hThread = new HANDLE; *hThread = NULL; //create the needed info into a structure to pass as one parameter //for creating a thread Info->ThreadHandle = hThread; *hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)StartEmulationThread,Info,0, &Info->ThreadID); } else { //mark the emulation as starting and fix up menus g_Notify->DisplayMessage(5,MSG_EMULATION_STARTED); if (g_Settings->LoadBool(Setting_AutoFullscreen)) { WriteTrace(TraceDebug,__FUNCTION__ " 15"); CIniFile RomIniFile(g_Settings->LoadString(SupportFile_RomDatabase).c_str()); stdstr Status = g_Settings->LoadString(Rdb_Status); char String[100]; RomIniFile.GetString("Rom Status",stdstr_f("%s.AutoFullScreen", Status.c_str()).c_str(),"true",String,sizeof(String)); if (_stricmp(String,"true") == 0) { g_Notify->ChangeFullScreen(); } } ExecuteCPU(); } } void CN64System::StartEmulation ( bool NewThread ) { __try { StartEmulation2(NewThread); } __except( g_MMU->MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) { char Message[600]; sprintf(Message,"Exception caught\nFile: %s\nLine: %d",__FILE__,__LINE__); MessageBox(NULL,Message,"Exception",MB_OK); } } void CN64System::StartEmulationThread ( ThreadInfo * Info ) { CoInitialize(NULL); EmulationStarting(*Info->ThreadHandle,Info->ThreadID); delete Info->ThreadHandle; delete Info; CoUninitialize(); } void CN64System::CloseCpu ( void ) { if (m_CPU_Handle == NULL) { return; } m_EndEmulation = true; if (g_Settings->LoadBool(GameRunning_CPU_Paused)) { SetEvent(m_hPauseEvent); } if (GetCurrentThreadId() == m_CPU_ThreadID) { ExternalEvent(SysEvent_CloseCPU); return; } HANDLE hThread = m_CPU_Handle; for (int count = 0; count < 200; count ++ ) { Sleep(100); if (g_Notify->ProcessGuiMessages()) { return; } DWORD ExitCode; if (GetExitCodeThread(hThread,&ExitCode)) { if (ExitCode != STILL_ACTIVE) { break; } } } if (hThread) { DWORD ExitCode; GetExitCodeThread(hThread,&ExitCode); if (ExitCode == STILL_ACTIVE) { TerminateThread(hThread,0); } } CpuStopped(); } void CN64System::SelectCheats ( HWND hParent ) { m_Cheats.SelectCheats(hParent,false); } void CN64System::DisplayRomInfo ( HWND hParent ) { if (!g_Rom) { return; } RomInformation Info(g_Rom); Info.DisplayInformation(hParent); } void CN64System::Pause(void) { if (m_EndEmulation) { return; } ResetEvent(m_hPauseEvent); g_Settings->SaveBool(GameRunning_CPU_Paused,true); g_Notify->RefreshMenu(); g_Notify->DisplayMessage(5,MSG_CPU_PAUSED); WaitForSingleObject(m_hPauseEvent, INFINITE); ResetEvent(m_hPauseEvent); g_Settings->SaveBool(GameRunning_CPU_Paused,(DWORD)false); g_Notify->RefreshMenu(); g_Notify->DisplayMessage(5,MSG_CPU_RESUMED); } stdstr CN64System::ChooseFileToOpen ( HWND hParent ) { OPENFILENAME openfilename; char FileName[_MAX_PATH],Directory[_MAX_PATH]; memset(&FileName, 0, sizeof(FileName)); memset(&openfilename, 0, sizeof(openfilename)); strcpy(Directory,g_Settings->LoadString(Directory_Game).c_str()); openfilename.lStructSize = sizeof( openfilename ); openfilename.hwndOwner = (HWND)hParent; openfilename.lpstrFilter = "N64 ROMs (*.zip, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0"; openfilename.lpstrFile = FileName; openfilename.lpstrInitialDir = Directory; openfilename.nMaxFile = MAX_PATH; openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if (GetOpenFileName (&openfilename)) { return stdstr(FileName); } return stdstr(""); } bool CN64System::IsDialogMsg( MSG * msg ) { if (m_Cheats.IsCheatMessage(msg)) { return true; } return false; } void CN64System::GameReset (void) { 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 ( void ) { 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; } } } g_Notify->RefreshMenu(); if (m_Recomp) { m_Recomp->Reset(); } m_Plugins->RomOpened(); if (m_SyncCPU) { m_SyncCPU->m_Plugins->RomOpened(); } } void CN64System::Reset (bool bInitReg, bool ClearMenory) { RefreshGameSettings(); m_Audio.Reset(); m_MMU_VM.Reset(ClearMenory); Debug_Reset(); 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); } } 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_bInitilized) { if (!m_MMU_VM.Initialize()) { return false; } bReset = true; m_bInitilized = 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(TraceDebug,__FUNCTION__ ": Reseting Plugins"); g_Notify->DisplayMessage(5,MSG_PLUGIN_INIT); m_Plugins->CreatePlugins(); bRes = m_Plugins->Initiate(this); if (!bRes) { WriteTrace(TraceError, __FUNCTION__ ": g_Plugins->Initiate Failed"); } } if (bReset) { Reset(true,true); } return bRes; } void CN64System::InitRegisters( bool bPostPif, CMipsMemory & 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; //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_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 ( void ) { //reset code g_Settings->SaveBool(GameRunning_CPU_Running,true); g_Settings->SaveBool(GameRunning_CPU_Paused,false); g_Notify->DisplayMessage(5,MSG_EMULATION_STARTED); m_EndEmulation = false; g_Notify->RefreshMenu(); m_Plugins->RomOpened(); if (m_SyncCPU) { m_SyncCPU->m_Plugins->RomOpened(); } switch ((CPU_TYPE)g_Settings->LoadDword(Game_CpuType)) { case CPU_Recompiler: ExecuteRecompiler(); break; case CPU_SyncCores: ExecuteSyncCPU(); break; default: ExecuteInterpret(); break; } g_Settings->SaveBool(GameRunning_CPU_Running,(DWORD)false); g_Notify->WindowMode(); 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 () { g_Notify->BringToTop(); m_Recomp->Run(); } void CN64System::CpuStopped ( void ) { g_Settings->SaveBool(GameRunning_CPU_Running,(DWORD)false); g_Notify->WindowMode(); if (!m_InReset) { if (m_hPauseEvent) { CloseHandle(m_hPauseEvent); m_hPauseEvent = NULL; } g_Notify->RefreshMenu(); g_Notify->MakeWindowOnTop(false); g_Notify->DisplayMessage(5,MSG_EMULATION_ENDED); if (g_Settings->LoadDword(RomBrowser_Enabled)) { g_Notify->ShowRomBrowser(); } } if (m_SyncCPU) { m_SyncCPU->CpuStopped(); } } void CN64System::UpdateSyncCPU (CN64System * const SecondCPU, DWORD 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() != (DWORD)(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",(DWORD)m_NextTimer,(DWORD)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() != (DWORD)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))) { Error.LogF("MemoryStack = %X should be: %X\r\n",m_Recomp->MemoryStackPos(), (DWORD)(m_MMU_VM.Rdram() + (m_Reg.m_GPR[29].W[0] & 0x1FFFFFFF))); } } DWORD * Rdram = (DWORD *)m_MMU_VM.Rdram(), * Rdram2 = (DWORD *)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]); } } DWORD * Imem = (DWORD *)m_MMU_VM.Imem(), * Imem2 = (DWORD *)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]); } } DWORD * Dmem = (DWORD *)m_MMU_VM.Dmem(), * Dmem2 = (DWORD *)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++) { DWORD 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++) { DWORD 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__); // AddEvent(CloseCPU); } bool CN64System::SaveState(void) { WriteTrace(TraceDebug,__FUNCTION__ ": 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->LoadString(GameRunning_InstantSaveFile); if (CurrentSaveName.empty()) { int Slot = g_Settings->LoadDword(Game_CurrentSaveState); if (Slot != 0) { CurrentSaveName.Format("%s.pj%d",g_Settings->LoadString(Game_GoodName).c_str(), Slot); } else { CurrentSaveName.Format("%s.pj",g_Settings->LoadString(Game_GoodName).c_str()); } FileName.Format("%s%s",g_Settings->LoadString(Directory_InstantSave).c_str(),CurrentSaveName.c_str()); stdstr_f ZipFileName("%s.zip",FileName.c_str()); //Make sure the target dir exists CreateDirectory(g_Settings->LoadString(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 { FileName.Format("%s%s",CurrentSaveName.c_str(), g_Settings->LoadDword(Setting_AutoZipInstantSave) ? ".pj.zip" : ".pj"); ExtraInfoFileName.Format("%s.dat",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); } } DWORD dwWritten, SaveID_0 = 0x23D8A6C8, SaveID_1 = 0x56D2CD23; DWORD RdramSize = g_Settings->LoadDword(Game_RDRamSize); DWORD MiInterReg = g_Reg->MI_INTR_REG; DWORD 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(DWORD)); zipWriteInFileInZip(file,g_Rom->GetRomAddress(),0x40); zipWriteInFileInZip(file,&NextViTimer,sizeof(DWORD)); zipWriteInFileInZip(file,&m_Reg.m_PROGRAM_COUNTER,sizeof(m_Reg.m_PROGRAM_COUNTER)); zipWriteInFileInZip(file,m_Reg.m_GPR,sizeof(__int64)*32); zipWriteInFileInZip(file,m_Reg.m_FPR,sizeof(__int64)*32); zipWriteInFileInZip(file,m_Reg.m_CP0,sizeof(DWORD)*32); zipWriteInFileInZip(file,m_Reg.m_FPCR,sizeof(DWORD)*32); zipWriteInFileInZip(file,&m_Reg.m_HI,sizeof(__int64)); zipWriteInFileInZip(file,&m_Reg.m_LO,sizeof(__int64)); zipWriteInFileInZip(file,m_Reg.m_RDRAM_Registers,sizeof(DWORD)*10); zipWriteInFileInZip(file,m_Reg.m_SigProcessor_Interface,sizeof(DWORD)*10); zipWriteInFileInZip(file,m_Reg.m_Display_ControlReg,sizeof(DWORD)*10); zipWriteInFileInZip(file,m_Reg.m_Mips_Interface,sizeof(DWORD)*4); zipWriteInFileInZip(file,m_Reg.m_Video_Interface,sizeof(DWORD)*14); zipWriteInFileInZip(file,m_Reg.m_Audio_Interface,sizeof(DWORD)*6); zipWriteInFileInZip(file,m_Reg.m_Peripheral_Interface,sizeof(DWORD)*13); zipWriteInFileInZip(file,m_Reg.m_RDRAM_Interface,sizeof(DWORD)*8); zipWriteInFileInZip(file,m_Reg.m_SerialInterface,sizeof(DWORD)*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); WriteFile( hSaveFile,&SaveID_0,sizeof(DWORD),&dwWritten,NULL); WriteFile( hSaveFile,&RdramSize,sizeof(DWORD),&dwWritten,NULL); WriteFile( hSaveFile,g_Rom->GetRomAddress(),0x40,&dwWritten,NULL); WriteFile( hSaveFile,&NextViTimer,sizeof(DWORD),&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)*32,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_FPR,sizeof(__int64)*32,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_CP0,sizeof(DWORD)*32,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_FPCR,sizeof(DWORD)*32,&dwWritten,NULL); WriteFile( hSaveFile,&m_Reg.m_HI,sizeof(__int64),&dwWritten,NULL); WriteFile( hSaveFile,&m_Reg.m_LO,sizeof(__int64),&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_RDRAM_Registers,sizeof(DWORD)*10,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_SigProcessor_Interface,sizeof(DWORD)*10,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_Display_ControlReg,sizeof(DWORD)*10,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_Mips_Interface,sizeof(DWORD)*4,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_Video_Interface,sizeof(DWORD)*14,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_Audio_Interface,sizeof(DWORD)*6,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_Peripheral_Interface,sizeof(DWORD)*13,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_RDRAM_Interface,sizeof(DWORD)*8,&dwWritten,NULL); WriteFile( hSaveFile,m_Reg.m_SerialInterface,sizeof(DWORD)*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,""); stdstr SaveMessage = _Lang->GetString(MSG_SAVED_STATE); CPath SavedFileName(FileName); g_Notify->DisplayMessage(5,"%s %s",SaveMessage.c_str(),SavedFileName.GetNameExtension().c_str()); g_Notify->RefreshMenu(); WriteTrace(TraceDebug,__FUNCTION__ ": Done"); return true; } bool CN64System::LoadState(void) { stdstr InstantFileName = g_Settings->LoadString(GameRunning_InstantSaveFile); if (!InstantFileName.empty()) { bool Result = LoadState(InstantFileName.c_str()); g_Settings->SaveString(GameRunning_InstantSaveFile,""); return Result; } CPath FileName; FileName.SetDriveDirectory(g_Settings->LoadString(Directory_InstantSave).c_str()); if (g_Settings->LoadDword(Game_CurrentSaveState) != 0) { FileName.SetNameExtension(stdstr_f("%s.pj%d",g_Settings->LoadString(Game_GoodName).c_str(),g_Settings->LoadDword(Game_CurrentSaveState)).c_str()); } else { FileName.SetNameExtension(stdstr_f("%s.pj",g_Settings->LoadString(Game_GoodName).c_str()).c_str()); } CPath ZipFileName; ZipFileName = (stdstr&)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->LoadString(Game_GameName).c_str(),g_Settings->LoadDword(Game_CurrentSaveState)).c_str()); } else { FileName.SetNameExtension(stdstr_f("%s.pj",g_Settings->LoadString(Game_GameName).c_str()).c_str()); } return LoadState(FileName); } bool CN64System::LoadState(LPCSTR FileName) { DWORD dwRead, Value,SaveRDRAMSize, NextVITimer = 0; bool LoadedZipFile = false; WriteTraceF((TraceType)(TraceDebug | TraceRecompiler),__FUNCTION__ "(%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); } DWORD 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 BYTE LoadHeader[64]; unzReadCurrentFile(file,LoadHeader,0x40); if (memcmp(LoadHeader,g_Rom->GetRomAddress(),0x40) != 0) { //if (inFullScreen) { return FALSE; } int result = MessageBox(NULL,GS(MSG_SAVE_STATE_HEADER),GS(MSG_MSGBOX_TITLE), 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)*32); unzReadCurrentFile(file,m_Reg.m_FPR,sizeof(__int64)*32); unzReadCurrentFile(file,m_Reg.m_CP0,sizeof(DWORD)*32); unzReadCurrentFile(file,m_Reg.m_FPCR,sizeof(DWORD)*32); unzReadCurrentFile(file,&m_Reg.m_HI,sizeof(__int64)); unzReadCurrentFile(file,&m_Reg.m_LO,sizeof(__int64)); unzReadCurrentFile(file,m_Reg.m_RDRAM_Registers,sizeof(DWORD)*10); unzReadCurrentFile(file,m_Reg.m_SigProcessor_Interface,sizeof(DWORD)*10); unzReadCurrentFile(file,m_Reg.m_Display_ControlReg,sizeof(DWORD)*10); unzReadCurrentFile(file,m_Reg.m_Mips_Interface,sizeof(DWORD)*4); unzReadCurrentFile(file,m_Reg.m_Video_Interface,sizeof(DWORD)*14); unzReadCurrentFile(file,m_Reg.m_Audio_Interface,sizeof(DWORD)*6); unzReadCurrentFile(file,m_Reg.m_Peripheral_Interface,sizeof(DWORD)*13); unzReadCurrentFile(file,m_Reg.m_RDRAM_Interface,sizeof(DWORD)*8); unzReadCurrentFile(file,m_Reg.m_SerialInterface,sizeof(DWORD)*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,"%s %s",GS(MSG_UNABLED_LOAD_STATE),FileNameStr.c_str()); return false; } SetFilePointer(hSaveFile,0,NULL,FILE_BEGIN); ReadFile( hSaveFile,&Value,sizeof(Value),&dwRead,NULL); if (Value != 0x23D8A6C8) { return FALSE; } ReadFile( hSaveFile,&SaveRDRAMSize,sizeof(SaveRDRAMSize),&dwRead,NULL); //Check header BYTE LoadHeader[64]; ReadFile( hSaveFile,LoadHeader,0x40,&dwRead,NULL); if (memcmp(LoadHeader,g_Rom->GetRomAddress(),0x40) != 0) { //if (inFullScreen) { return FALSE; } int result = MessageBox(NULL,GS(MSG_SAVE_STATE_HEADER),GS(MSG_MSGBOX_TITLE), 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)*32,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_FPR,sizeof(__int64)*32,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_CP0,sizeof(DWORD)*32,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_FPCR,sizeof(DWORD)*32,&dwRead,NULL); ReadFile( hSaveFile,&m_Reg.m_HI,sizeof(__int64),&dwRead,NULL); ReadFile( hSaveFile,&m_Reg.m_LO,sizeof(__int64),&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_RDRAM_Registers,sizeof(DWORD)*10,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_SigProcessor_Interface,sizeof(DWORD)*10,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_Display_ControlReg,sizeof(DWORD)*10,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_Mips_Interface,sizeof(DWORD)*4,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_Video_Interface,sizeof(DWORD)*14,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_Audio_Interface,sizeof(DWORD)*6,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_Peripheral_Interface,sizeof(DWORD)*13,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_RDRAM_Interface,sizeof(DWORD)*8,&dwRead,NULL); ReadFile( hSaveFile,m_Reg.m_SerialInterface,sizeof(DWORD)*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 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(TraceDebug,__FUNCTION__ ": 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(TraceDebug,__FUNCTION__ ": 5"); m_TLB.Reset(false); WriteTrace(TraceDebug,__FUNCTION__ ": 6"); m_CPU_Usage.ResetCounters(); WriteTrace(TraceDebug,__FUNCTION__ ": 7"); m_Profile.ResetCounters(); WriteTrace(TraceDebug,__FUNCTION__ ": 8"); m_FPS.Reset(true); WriteTrace(TraceDebug,__FUNCTION__ ": 9"); if (bLogX86Code()) { Stop_x86_Log(); Start_x86_Log(); } WriteTrace(TraceDebug,__FUNCTION__ ": 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(TraceDebug,__FUNCTION__ ": 13"); stdstr LoadMsg = _Lang->GetString(MSG_LOADED_STATE); g_Notify->DisplayMessage(5,"%s %s",LoadMsg.c_str(),CPath(FileNameStr).GetNameExtension().c_str()); WriteTrace(TraceDebug,__FUNCTION__ ": Done"); return true; } void CN64System::RunRSP ( void ) { WriteTraceF(TraceRSP, __FUNCTION__ ": 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*/; DWORD 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, __FUNCTION__ ": Dlist that is frozen"); return; } switch (Task) { case 1: WriteTrace(TraceRSP, __FUNCTION__ ": *** Display list ***"); m_DlistCount += 1; m_FPS.UpdateDlCounter(); break; case 2: WriteTrace(TraceRSP, __FUNCTION__ ": *** Audio list ***"); m_AlistCount += 1; break; default: WriteTrace(TraceRSP, __FUNCTION__ ": *** Unknown list ***"); m_UnknownCount += 1; break; } if (bShowDListAListCount()) { g_Notify->DisplayMessage(0,"Dlist: %d Alist: %d Unknown: %d",m_DlistCount,m_AlistCount,m_UnknownCount); } 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, __FUNCTION__ ": do cycles - starting"); g_Plugins->RSP()->DoRspCycles(100); WriteTrace(TraceRSP, __FUNCTION__ ": do cycles - Done"); } __except( g_MMU->MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) { WriteTrace(TraceError, __FUNCTION__ ": 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, __FUNCTION__ ": check interrupts"); g_Reg->CheckInterrupts(); } } WriteTraceF(TraceRSP, __FUNCTION__ ": Done (SP Status %X)",m_Reg.SP_STATUS_REG); } void CN64System::SyncToAudio ( void ) { 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) { WriteTraceF(TraceAudio, __FUNCTION__ ": Audio Interrupt done (%d)",i); break; } Sleep(1); } if (bShowCPUPer()) { m_CPU_Usage.StartTimer(CPU_UsageAddr != Timer_None ? CPU_UsageAddr : Timer_R4300 ); } } void CN64System::RefreshScreen ( void ) { SPECIAL_TIMERS CPU_UsageAddr = Timer_None/*, ProfilingAddr = Timer_None*/; DWORD 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,__FUNCTION__ ": Starting"); g_Plugins->Gfx()->UpdateScreen(); WriteTrace(TraceGfxPlugin,__FUNCTION__ ": Done"); } __except (g_MMU->MemoryFilter( GetExceptionCode(), GetExceptionInformation())) { WriteTrace(TraceGfxPlugin,__FUNCTION__ ": Exception caught"); WriteTrace(TraceError,__FUNCTION__ ": Exception caught"); } g_MMU->UpdateFieldSerration((m_Reg.VI_STATUS_REG & 0x40) != 0); if ((bBasicMode() || bLimitFPS() ) && !bSyncToAudio()) { if (bShowCPUPer()) { m_CPU_Usage.StartTimer(Timer_Idel); } DWORD FrameRate; if (m_Limitor.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 (g_BaseSystem == NULL) return; if (g_BaseSystem->m_Cheats.CheatsSlectionChanged()) g_BaseSystem->m_Cheats.LoadCheats(false); g_BaseSystem->m_Cheats.ApplyCheats(g_MMU); } // if (bProfiling) { m_Profile.StartTimer(ProfilingAddr != Timer_None ? ProfilingAddr : Timer_R4300); } } bool CN64System::WriteToProtectedMemory (DWORD Address, int length) { WriteTraceF(TraceDebug,__FUNCTION__ ": Address: %X Len: %d",Address,length); if (m_Recomp) { g_Notify->BreakPoint(__FILE__,__LINE__); #ifdef tofix return m_Recomp->ClearRecompCode_Phys(Address,length,CRecompiler::Remove_ProtectedMem); #endif } return false; } void CN64System::TLB_Mapped ( DWORD VAddr, DWORD Len, DWORD PAddr, bool bReadOnly ) { m_MMU_VM.TLB_Mapped(VAddr,Len,PAddr,bReadOnly); } void CN64System::TLB_Unmaped ( DWORD VAddr, DWORD 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 ( void ) { Debug_RefreshTLBWindow(); }