diff --git a/Source/Project64-rsp-core/Hle/HleTask.cpp b/Source/Project64-rsp-core/Hle/HleTask.cpp index 2564314a7..8ae6c5f40 100644 --- a/Source/Project64-rsp-core/Hle/HleTask.cpp +++ b/Source/Project64-rsp-core/Hle/HleTask.cpp @@ -1,15 +1,25 @@ #include +#include +#include #include #include CHleTask::CHleTask(CRSPSystem & System) : + CGPRRegisters(System.m_Reg.m_GPR), m_hle(System), m_System(System), + m_Recompiler(System.m_Recompiler), + m_RSPRegisterHandler(System.m_RSPRegisterHandler), + m_MI_INTR_REG(System.m_MI_INTR_REG), m_SP_STATUS_REG(System.m_SP_STATUS_REG), + m_SP_DMA_FULL_REG(System.m_SP_DMA_FULL_REG), + m_SP_DMA_BUSY_REG(System.m_SP_DMA_BUSY_REG), m_SP_PC_REG(System.m_SP_PC_REG), + m_SP_SEMAPHORE_REG(System.m_SP_SEMAPHORE_REG), m_DPC_STATUS_REG(System.m_DPC_STATUS_REG), m_DMEM(System.m_DMEM), m_IMEM(System.m_IMEM), + m_UcodeCRC(0), CheckInterrupts(System.CheckInterrupts), ProcessDList(System.ProcessDList) { @@ -30,6 +40,200 @@ bool CHleTask::IsHleTask(void) return false; } +void CHleTask::SetupCommandList(TASK_INFO & TaskInfo) +{ + uint32_t JumpTableLength = 0x7E, JumpTablePos = 0x10; + if ((HLETaskType)(TaskInfo.Type) == HLETaskType::Audio) + { + if (*((uint32_t *)&m_DMEM[0]) == 0x00000001 && *((uint32_t *)&m_DMEM[0x30]) == 0xf0000f00) + { + JumpTableLength = 0x10; + JumpTablePos = 0x10; + } + } + + uint32_t JumpTableCRC = crc32(0L, m_IMEM + JumpTablePos, JumpTableLength << 1); + TaskFunctionMap::iterator itr = m_FunctionMap.find(JumpTableCRC); + if (itr != m_FunctionMap.end()) + { + m_TaskFunctions = &itr->second; + return; + } + + if (m_FunctionMap.size() > 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + m_TaskFunctions = nullptr; + + memset(&m_Recompiler.m_CurrentBlock, 0, sizeof(m_Recompiler.m_CurrentBlock)); + m_Recompiler.BuildBranchLabels(); + TaskFunctions JumpFunctions; + for (uint32_t i = 0, n = JumpTableLength; i < n; i++) + { + uint16_t FuncAddress = *((uint16_t *)(m_DMEM + (((i << 1) + JumpTablePos) ^ 2))); + if (FuncAddress != 0x1118) + { + m_Recompiler.CompileHLETask(FuncAddress); + void * FuncPtr = *(JumpTable + ((FuncAddress & 0xFFF) >> 2)); + JumpFunctions.emplace_back(TaskFunctionAddress(FuncAddress, FuncPtr)); + } + else + { + JumpFunctions.emplace_back(TaskFunctionAddress(FuncAddress, nullptr)); + } + } + m_Recompiler.LinkBranches(&m_Recompiler.m_CurrentBlock); + m_FunctionMap[JumpTableCRC] = JumpFunctions; + itr = m_FunctionMap.find(JumpTableCRC); + if (itr == m_FunctionMap.end()) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + m_TaskFunctions = &itr->second; +} + +void CHleTask::ExecuteTask_1a13a51a(TASK_INFO & TaskInfo) +{ + *((uint32_t *)(m_DMEM + 0x320)) = 0; + GPR_T8 = 0x360; + GPR_S7 = 0xF90; + if ((*m_DPC_STATUS_REG & 1) != 0 || *m_SP_SEMAPHORE_REG != 0 || *m_SP_DMA_FULL_REG != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + m_RSPRegisterHandler->WriteReg(RSPRegister_MEM_ADDR, 0x380); + m_RSPRegisterHandler->WriteReg(RSPRegister_DRAM_ADDR, TaskInfo.DataPtr); + m_RSPRegisterHandler->WriteReg(RSPRegister_RD_LEN, 0x13F); + if (*m_SP_DMA_BUSY_REG != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + *m_SP_SEMAPHORE_REG = 0; + if (SyncCPU) + { + *m_SP_PC_REG = 0x0E4; + RSPSystem.SyncSystem()->ExecuteOps(200, *m_SP_PC_REG); + RSPSystem.BasicSyncCheck(); + } + + GPR_GP = TaskInfo.DataPtr; + GPR_K1 = TaskInfo.DataSize; + GPR_SP = 0x380; + GPR_S8 = 0x140; + static uint32_t TaskCount = 0; + for (;;) + { + GPR_K0 = *((uint32_t *)(m_DMEM + GPR_SP)); + GPR_T9 = *((uint32_t *)(m_DMEM + GPR_SP + 4)); + + uint32_t Index = (GPR_K0 >> 0x18) & 0x7F; + GPR_GP += 8; + GPR_K1 -= 8; + GPR_SP += 8; + GPR_S8 -= 8; + if (Index >= m_TaskFunctions->size()) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + TaskFunctionAddress FunctionAddress = (*m_TaskFunctions)[Index]; + *m_SP_PC_REG = FunctionAddress.first; + if (SyncCPU) + { + RSPSystem.SyncSystem()->ExecuteOps(0x10000, 0x118); + } +#if defined(_M_IX86) && defined(_MSC_VER) + void * Block = FunctionAddress.second; + _asm { + pushad + call Block + popad + } +#else + g_Notify->BreakPoint(__FILE__, __LINE__); +#endif + if (SyncCPU) + { + RSPSystem.BasicSyncCheck(); + RSPSystem.SyncSystem()->ExecuteOps(2, (uint32_t)-1); + } + if (GPR_S8 == 0) + { + if (GPR_K1 <= 0) + { + m_RSPRegisterHandler->WriteReg(RSPRegister_STATUS, 0x4000); + RSPSystem.m_Op.Special_BREAK(); + if (SyncCPU) + { + *m_SP_PC_REG = 0x144; + RSPSystem.SyncSystem()->ExecuteOps(100, 0x144); + RSPSystem.BasicSyncCheck(); + } + break; + } + uint32_t ReadLen = (GPR_K1 > 0x140) ? 0x140 : GPR_K1; + GPR_S8 = ReadLen; + if (*m_SP_SEMAPHORE_REG != 0 || *m_SP_DMA_FULL_REG != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + m_RSPRegisterHandler->WriteReg(RSPRegister_MEM_ADDR, 0x380); + m_RSPRegisterHandler->WriteReg(RSPRegister_DRAM_ADDR, GPR_GP); + m_RSPRegisterHandler->WriteReg(RSPRegister_RD_LEN, ReadLen - 1); + GPR_SP = 0x380; + if (*m_SP_DMA_BUSY_REG != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + *m_SP_SEMAPHORE_REG = 0; + if (SyncCPU) + { + *m_SP_PC_REG = 0x0E4; + RSPSystem.SyncSystem()->ExecuteOps(400, 0x0E4); + RSPSystem.BasicSyncCheck(); + } + } + TaskCount += 1; + } +} + +void CHleTask::SetupTask(TASK_INFO & TaskInfo) +{ + if (TaskInfo.Flags != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + if (*m_SP_DMA_FULL_REG != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + m_RSPRegisterHandler->WriteReg(RSPRegister_MEM_ADDR, 0); + m_RSPRegisterHandler->WriteReg(RSPRegister_DRAM_ADDR, TaskInfo.UcodeData); + m_RSPRegisterHandler->WriteReg(RSPRegister_RD_LEN, TaskInfo.UcodeDataSize); + if (*m_SP_DMA_BUSY_REG != 0 || (*m_SP_STATUS_REG & 0x80) != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + m_RSPRegisterHandler->WriteReg(RSPRegister_MEM_ADDR, 0x1080); + m_RSPRegisterHandler->WriteReg(RSPRegister_DRAM_ADDR, TaskInfo.Ucode); + m_RSPRegisterHandler->WriteReg(RSPRegister_RD_LEN, 0x0F7F); + if (*m_SP_DMA_BUSY_REG != 0 || (*m_SP_STATUS_REG & 0x80) != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + *m_SP_SEMAPHORE_REG = 0; + if (SyncCPU) + { + *m_SP_PC_REG = 0x80; + RSPSystem.SyncSystem()->ExecuteOps(200, 0x080); + RSPSystem.BasicSyncCheck(); + } + SetupCommandList(TaskInfo); +} + bool CHleTask::ProcessHleTask(void) { TASK_INFO & TaskInfo = *((TASK_INFO *)(m_DMEM + 0xFC0)); @@ -37,18 +241,18 @@ bool CHleTask::ProcessHleTask(void) if (((HLETaskType)TaskInfo.Type) == HLETaskType::Video && GraphicsHle && TaskInfo.DataPtr != 0) { - if (ProcessDList != nullptr) + if (ProcessDList == nullptr) { - ProcessDList(); + return false; } + ProcessDList(); *m_SP_STATUS_REG |= (0x0203); if ((*m_SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0) { - *RSPInfo.MI_INTR_REG |= MI_INTR_SP; - RSPInfo.CheckInterrupts(); + *m_MI_INTR_REG |= MI_INTR_SP; + CheckInterrupts(); } - - *RSPInfo.DPC_STATUS_REG &= ~0x0002; + *m_DPC_STATUS_REG &= ~0x0002; return true; } else if (TaskInfo.Type == 7) @@ -56,6 +260,30 @@ bool CHleTask::ProcessHleTask(void) RSPInfo.ShowCFB(); } + if (CRSPSettings::CPUMethod() == RSPCpuMethod::RecompilerTasks) + { + if (SyncCPU) + { + RSPSystem.SetupSyncCPU(); + } + SetupTask(TaskInfo); + uint32_t UcodeSize = TaskInfo.UcodeSize; + if (UcodeSize < 0x4 || TaskInfo.UcodeSize > 0x0F80) + { + UcodeSize = 0x0F80; + } + m_UcodeCRC = crc32(0L, m_IMEM + 0x80, UcodeSize); + if (m_UcodeCRC == 0x1a13a51a) + { + ExecuteTask_1a13a51a(TaskInfo); + } + else + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + return true; + } + if (CRSPSettings::CPUMethod() == RSPCpuMethod::HighLevelEmulation && m_hle.try_fast_audio_dispatching()) { *m_SP_STATUS_REG |= SP_STATUS_SIG2 | SP_STATUS_BROKE | SP_STATUS_HALT; diff --git a/Source/Project64-rsp-core/Hle/HleTask.h b/Source/Project64-rsp-core/Hle/HleTask.h index 4d963410a..79c594768 100644 --- a/Source/Project64-rsp-core/Hle/HleTask.h +++ b/Source/Project64-rsp-core/Hle/HleTask.h @@ -1,14 +1,23 @@ #pragma once #include +#include #include +#include #include +#include class CRSPSystem; class RSPRegisterHandlerPlugin; +class CRSPRecompiler; class CHle; -class CHleTask +class CHleTask : + private CGPRRegisters { + typedef std::pair TaskFunctionAddress; + typedef std::vector TaskFunctions; + typedef std::map TaskFunctionMap; + struct TASK_INFO { uint32_t Type; @@ -46,14 +55,27 @@ private: CHleTask(const CHleTask & copy); CHleTask & operator=(const CHleTask & rhs); + void SetupCommandList(TASK_INFO & TaskInfo); + void ExecuteTask_1a13a51a(TASK_INFO & TaskInfo); + void SetupTask(TASK_INFO & TaskInfo); + void (*&CheckInterrupts)(void); void (*&ProcessDList)(void); CHle m_hle; + TaskFunctionMap m_FunctionMap; + const TaskFunctions * m_TaskFunctions; CRSPSystem & m_System; + CRSPRecompiler & m_Recompiler; + RSPRegisterHandlerPlugin *& m_RSPRegisterHandler; + uint32_t *& m_MI_INTR_REG; uint32_t *& m_SP_STATUS_REG; + uint32_t *& m_SP_DMA_FULL_REG; + uint32_t *& m_SP_DMA_BUSY_REG; uint32_t *& m_SP_PC_REG; + uint32_t *& m_SP_SEMAPHORE_REG; uint32_t *& m_DPC_STATUS_REG; uint8_t *& m_DMEM; uint8_t *& m_IMEM; + uint32_t m_UcodeCRC; }; diff --git a/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.cpp b/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.cpp index 7beef1afe..30ab3be11 100644 --- a/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.cpp +++ b/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.cpp @@ -42,6 +42,7 @@ p_Recompfunc RSP_Recomp_Sc2[32]; CRSPRecompiler::CRSPRecompiler(CRSPSystem & System) : m_System(System), + m_RecompilerOps(System, *this), m_RSPRegisterHandler(System.m_RSPRegisterHandler), m_CompilePC(0), m_OpCode(System.m_OpCode), @@ -718,7 +719,7 @@ sections as well as set the jump table to points within a block that are safe. */ -void BuildBranchLabels(void) +void CRSPRecompiler::BuildBranchLabels(void) { RSPOpcode RspOp; uint32_t i, Dest; @@ -810,8 +811,6 @@ void CRSPRecompiler::CompilerLinkBlocks(void) void CRSPRecompiler::CompilerRSPBlock(void) { - CRSPRecompilerOps RecompilerOps(RSPSystem, *this); - uint8_t * IMEM_SAVE = (uint8_t *)malloc(0x1000); const size_t X86BaseAddress = (size_t)RecompPos; m_NextInstruction = RSPPIPELINE_NORMAL; @@ -877,7 +876,7 @@ void CRSPRecompiler::CompilerRSPBlock(void) if (Compiler.bSections) { - if (RecompilerOps.RSP_DoSections()) + if (m_RecompilerOps.RSP_DoSections()) { continue; } @@ -898,7 +897,7 @@ void CRSPRecompiler::CompilerRSPBlock(void) } else { - (RecompilerOps.*RSP_Recomp_Opcode[m_OpCode.op])(); + (m_RecompilerOps.*RSP_Recomp_Opcode[m_OpCode.op])(); } switch (m_NextInstruction) @@ -910,6 +909,10 @@ void CRSPRecompiler::CompilerRSPBlock(void) m_NextInstruction = RSPPIPELINE_DELAY_SLOT; m_CompilePC += 4; break; + case RSPPIPELINE_DO_DELAY_SLOT_TASK_EXIT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_TASK_EXIT; + m_CompilePC += 4; + break; case RSPPIPELINE_DELAY_SLOT: m_NextInstruction = RSPPIPELINE_DELAY_SLOT_DONE; m_CompilePC = (m_CompilePC - 4 & 0xFFC); @@ -918,6 +921,10 @@ void CRSPRecompiler::CompilerRSPBlock(void) m_NextInstruction = RSPPIPELINE_DELAY_SLOT_EXIT_DONE; m_CompilePC = (m_CompilePC - 4 & 0xFFC); break; + case RSPPIPELINE_DELAY_SLOT_TASK_EXIT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_TASK_EXIT_DONE; + m_CompilePC = (m_CompilePC - 4 & 0xFFC); + break; case RSPPIPELINE_FINISH_SUB_BLOCK: m_NextInstruction = RSPPIPELINE_NORMAL; m_CompilePC += 8; @@ -940,7 +947,9 @@ void CRSPRecompiler::CompilerRSPBlock(void) CompilerLinkBlocks(); } break; - + case RSPPIPELINE_FINISH_TASK_SUB_BLOCK: + m_NextInstruction = RSPPIPELINE_FINISH_BLOCK; + break; case RSPPIPELINE_FINISH_BLOCK: break; default: g_Notify->DisplayError(stdstr_f("RSP main loop\n\nWTF m_NextInstruction = %d", m_NextInstruction).c_str()); @@ -1059,6 +1068,126 @@ void CRSPRecompiler::RunCPU(void) } } +void CRSPRecompiler::CompileHLETask(uint32_t Address) +{ + uint32_t EndPC = 0x1000; + m_CompilePC = (Address & 0xFFF); + m_NextInstruction = RSPPIPELINE_NORMAL; + + m_CurrentBlock.StartPC = Address; + m_CurrentBlock.CurrPC = Address; + + CPU_Message("====== Block %d ======", BlockID++); + CPU_Message("x86 code at: %X", RecompPos); + CPU_Message("Jump table: %X", Table); + CPU_Message("Start of block: %X", m_CurrentBlock.StartPC); + CPU_Message("====== Recompiled code ======"); + + *(JumpTable + (m_CompilePC >> 2)) = RecompPos; + do + { + if (m_NextInstruction == RSPPIPELINE_NORMAL && IsJumpLabel(m_CompilePC)) + { + // Jumps come around twice + if (NULL == *(JumpTable + (m_CompilePC >> 2))) + { + CPU_Message("***** Adding jump table entry for PC: %04X at X86: %08X *****", m_CompilePC, RecompPos); + CPU_Message(""); + *(JumpTable + (m_CompilePC >> 2)) = RecompPos; + + // Reorder from here to next label or branch + m_CurrentBlock.CurrPC = m_CompilePC; + ReOrderSubBlock(&m_CurrentBlock); + } + else if (m_NextInstruction != RSPPIPELINE_DELAY_SLOT_DONE) + { + + // We could link the blocks here, but performance-wise it might be better to just let it run + } + } +#ifdef X86_RECOMP_VERBOSE + if (!IsOpcodeNop(m_CompilePC)) + { + CPU_Message("X86 Address: %08X", RecompPos); + } +#endif + RSP_LW_IMEM(m_CompilePC, &m_OpCode.Value); + (m_RecompilerOps.*RSP_Recomp_Opcode[m_OpCode.op])(); + + switch (m_NextInstruction) + { + case RSPPIPELINE_NORMAL: + m_CompilePC += 4; + break; + case RSPPIPELINE_DO_DELAY_SLOT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT; + m_CompilePC += 4; + break; + case RSPPIPELINE_DO_DELAY_SLOT_EXIT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_EXIT; + m_CompilePC += 4; + break; + case RSPPIPELINE_DO_DELAY_SLOT_TASK_EXIT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_TASK_EXIT; + m_CompilePC += 4; + break; + case RSPPIPELINE_DELAY_SLOT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_DONE; + m_CompilePC = (m_CompilePC - 4 & 0xFFC); + break; + case RSPPIPELINE_DELAY_SLOT_EXIT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_EXIT_DONE; + m_CompilePC = (m_CompilePC - 4 & 0xFFC); + break; + case RSPPIPELINE_DELAY_SLOT_TASK_EXIT: + m_NextInstruction = RSPPIPELINE_DELAY_SLOT_TASK_EXIT_DONE; + m_CompilePC = (m_CompilePC - 4 & 0xFFC); + break; + case RSPPIPELINE_FINISH_SUB_BLOCK: + m_NextInstruction = RSPPIPELINE_NORMAL; + m_CompilePC += 8; + if (m_CompilePC >= 0x1000) + { + m_NextInstruction = RSPPIPELINE_FINISH_BLOCK; + } + else if (NULL == *(JumpTable + (m_CompilePC >> 2))) + { + // This is for the new block being compiled now + CPU_Message("***** Continuing static SubBlock (jump table entry added for PC: %04X at X86: %08X) *****", m_CompilePC, RecompPos); + *(JumpTable + (m_CompilePC >> 2)) = RecompPos; + + m_CurrentBlock.CurrPC = m_CompilePC; + // Reorder from after delay to next label or branch + ReOrderSubBlock(&m_CurrentBlock); + } + else + { + CompilerLinkBlocks(); + } + break; + case RSPPIPELINE_FINISH_BLOCK: break; + case RSPPIPELINE_FINISH_TASK_SUB_BLOCK: + m_NextInstruction = RSPPIPELINE_FINISH_BLOCK; + break; + default: + g_Notify->DisplayError(stdstr_f("RSP main loop\n\nWTF m_NextInstruction = %d", m_NextInstruction).c_str()); + m_CompilePC += 4; + break; + } + + if (m_CompilePC >= EndPC && *m_System.m_SP_PC_REG != 0 && EndPC != *m_System.m_SP_PC_REG) + { + m_CompilePC = 0; + EndPC = *m_System.m_SP_PC_REG; + } + } while (m_NextInstruction != RSPPIPELINE_FINISH_BLOCK && (m_CompilePC < EndPC || m_NextInstruction == RSPPIPELINE_DELAY_SLOT || m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)); + if (m_CompilePC >= EndPC) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + CPU_Message("===== End of recompiled code ====="); +} + void CRSPRecompiler::Branch_AddRef(uint32_t Target, uint32_t * X86Loc) { if (m_CurrentBlock.ResolveCount >= 150) diff --git a/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.h b/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.h index a048b9d14..ce0641dad 100644 --- a/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.h +++ b/Source/Project64-rsp-core/Recompiler/RspRecompilerCPU.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -12,6 +13,7 @@ class RSPRegisterHandlerPlugin; class CRSPRecompiler { friend class CRSPRecompilerOps; + friend class CHleTask; typedef struct { @@ -38,15 +40,18 @@ private: CRSPRecompiler(const CRSPRecompiler &); CRSPRecompiler & operator=(const CRSPRecompiler &); + void BuildBranchLabels(void); void BuildRecompilerCPU(void); void CompilerLinkBlocks(void); void CompilerRSPBlock(void); + void CompileHLETask(uint32_t Address); void LinkBranches(RSP_BLOCK * Block); void ReOrderSubBlock(RSP_BLOCK * Block); void ReOrderInstructions(uint32_t StartPC, uint32_t EndPC); void ResetJumpTables(void); CRSPSystem & m_System; + CRSPRecompilerOps m_RecompilerOps; RSPRegisterHandlerPlugin *& m_RSPRegisterHandler; RSPOpcode & m_OpCode; uint32_t m_CompilePC; diff --git a/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.cpp b/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.cpp index f16ff2cf8..d1d1c6907 100644 --- a/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.cpp +++ b/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.cpp @@ -168,6 +168,10 @@ void CRSPRecompilerOps::J(void) { CPU_Message(" %X %s", m_CompilePC, RSPInstruction(m_CompilePC, m_OpCode.Value).NameAndParam().c_str()); m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT; + if (CRSPSettings::CPUMethod() == RSPCpuMethod::RecompilerTasks && m_OpCode.Value == EndHleTaskOp::J_0x1118) + { + m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT_TASK_EXIT; + } } else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE) { @@ -175,10 +179,10 @@ void CRSPRecompilerOps::J(void) m_Recompiler.Branch_AddRef((m_OpCode.target << 2) & 0xFFC, (uint32_t *)(RecompPos - 4)); m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK; } - else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE) + else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE || m_NextInstruction == RSPPIPELINE_DELAY_SLOT_TASK_EXIT_DONE) { MoveConstToVariable((m_OpCode.target << 2) & 0xFFC, m_System.m_SP_PC_REG, "RSP PC"); - m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK; + m_NextInstruction = m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE ? RSPPIPELINE_FINISH_SUB_BLOCK : RSPPIPELINE_FINISH_TASK_SUB_BLOCK; Ret(); } else @@ -1494,17 +1498,14 @@ void CRSPRecompilerOps::Special_JR(void) TestX86RegToX86Reg(x86_EAX, x86_EAX); JeLabel8("Null", 0); Jump = RecompPos - 1; - - // Before we branch quickly update our stats - /*if (m_CompilePC == 0x080) { - Pushad(); - Call_Direct((void *)UpdateAudioTimer, "UpdateAudioTimer"); - Popad(); - }*/ JumpX86Reg(x86_EAX); x86_SetBranch8b(Jump, RecompPos); CPU_Message(" Null:"); + if (CRSPSettings::CPUMethod() == RSPCpuMethod::HighLevelEmulation) + { + BreakPoint(); + } Ret(); ChangedPC = false; m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK; diff --git a/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.h b/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.h index 092561b04..99d592a3c 100644 --- a/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.h +++ b/Source/Project64-rsp-core/Recompiler/RspRecompilerOps.h @@ -1,8 +1,9 @@ -// Opcode functions +#pragma once #include class CRSPSystem; class CRSPRegisters; +class CRSPRecompiler; class CRSPRecompilerOps { @@ -11,6 +12,11 @@ class CRSPRecompilerOps HIT_BRANCH = 0x2, }; + enum EndHleTaskOp + { + J_0x1118 = 0x09000446 + }; + public: CRSPRecompilerOps(CRSPSystem & System, CRSPRecompiler & Recompiler); diff --git a/Source/Project64-rsp-core/Settings/RspSettings.cpp b/Source/Project64-rsp-core/Settings/RspSettings.cpp index b6ec3d63a..cc02bab74 100644 --- a/Source/Project64-rsp-core/Settings/RspSettings.cpp +++ b/Source/Project64-rsp-core/Settings/RspSettings.cpp @@ -14,7 +14,7 @@ RSPCpuMethod CRSPSettings::m_CPUMethod = RSPCpuMethod::Interpreter; #endif uint16_t Set_AudioHle = 0, Set_GraphicsHle = 0, Set_MultiThreaded = 0, Set_AllocatedRdramSize = 0, Set_DirectoryLog = 0; -bool GraphicsHle = true, AudioHle, ConditionalMove, HleAlistTask = false, RspMultiThreaded = false; +bool GraphicsHle = true, AudioHle, ConditionalMove, SyncCPU = false, HleAlistTask = false, RspMultiThreaded = false; bool DebuggingEnabled = false, Profiling, IndvidualBlock, ShowErrors, BreakOnStart = false, LogRDP = false, LogX86Code = false; void CRSPSettings::EnableDebugging(bool Enabled) @@ -40,6 +40,7 @@ void CRSPSettings::InitializeRspSetting(void) RegisterSetting(Set_IndvidualBlock, Data_DWORD_General, "Individual Block", NULL, IndvidualBlock, NULL); RegisterSetting(Set_ShowErrors, Data_DWORD_General, "Show Errors", NULL, ShowErrors, NULL); RegisterSetting(Set_HleAlistTask, Data_DWORD_General, "Hle Alist Task", NULL, HleAlistTask, NULL); + RegisterSetting(Set_SyncCPU, Data_DWORD_General, "Sync CPU", NULL, SyncCPU, NULL); // Compiler settings RegisterSetting(Set_CheckDest, Data_DWORD_General, "Check Destination Vector", NULL, Compiler.bDest, NULL); diff --git a/Source/Project64-rsp-core/Settings/RspSettings.h b/Source/Project64-rsp-core/Settings/RspSettings.h index b54404071..e25c3217b 100644 --- a/Source/Project64-rsp-core/Settings/RspSettings.h +++ b/Source/Project64-rsp-core/Settings/RspSettings.h @@ -2,14 +2,15 @@ #include extern uint16_t Set_AudioHle, Set_GraphicsHle, Set_AllocatedRdramSize, Set_DirectoryLog; -extern bool GraphicsHle, AudioHle, ConditionalMove, HleAlistTask, RspMultiThreaded; +extern bool GraphicsHle, AudioHle, ConditionalMove, SyncCPU, HleAlistTask, RspMultiThreaded; extern bool DebuggingEnabled, Profiling, IndvidualBlock, ShowErrors, BreakOnStart, LogRDP, LogX86Code; enum class RSPCpuMethod { Interpreter = 0, Recompiler = 1, - HighLevelEmulation = 2, + RecompilerTasks = 2, + HighLevelEmulation = 3, }; class CRSPSettings diff --git a/Source/Project64-rsp-core/Settings/RspSettingsID.h b/Source/Project64-rsp-core/Settings/RspSettingsID.h index e7eae627b..073fe6d38 100644 --- a/Source/Project64-rsp-core/Settings/RspSettingsID.h +++ b/Source/Project64-rsp-core/Settings/RspSettingsID.h @@ -10,6 +10,7 @@ enum Set_IndvidualBlock, Set_ShowErrors, Set_HleAlistTask, + Set_SyncCPU, // Compiler settings Set_CheckDest, diff --git a/Source/Project64-rsp-core/cpu/RSPCpu.cpp b/Source/Project64-rsp-core/cpu/RSPCpu.cpp index 3f1b4ceb9..f0e25b982 100644 --- a/Source/Project64-rsp-core/cpu/RSPCpu.cpp +++ b/Source/Project64-rsp-core/cpu/RSPCpu.cpp @@ -112,6 +112,7 @@ uint32_t DoRspCycles(uint32_t Cycles) RSPSystem.RunRecompiler(); break; case RSPCpuMethod::Interpreter: + case RSPCpuMethod::RecompilerTasks: case RSPCpuMethod::HighLevelEmulation: RSPSystem.ExecuteOps((uint32_t)-1, (uint32_t)-1); break; diff --git a/Source/Project64-rsp-core/cpu/RSPInterpreterOps.cpp b/Source/Project64-rsp-core/cpu/RSPInterpreterOps.cpp index 0396de639..d592e8d45 100644 --- a/Source/Project64-rsp-core/cpu/RSPInterpreterOps.cpp +++ b/Source/Project64-rsp-core/cpu/RSPInterpreterOps.cpp @@ -12,8 +12,6 @@ #include #include -extern bool AudioHle, GraphicsHle; - uint32_t clz32(uint32_t val) { #if defined(__GNUC__) diff --git a/Source/Project64-rsp-core/cpu/RSPInterpreterOps.h b/Source/Project64-rsp-core/cpu/RSPInterpreterOps.h index 833aeefa7..f5506354e 100644 --- a/Source/Project64-rsp-core/cpu/RSPInterpreterOps.h +++ b/Source/Project64-rsp-core/cpu/RSPInterpreterOps.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -12,6 +13,7 @@ class RSPOp : { friend class CRSPSystem; friend class CRSPRecompilerOps; + friend class CHleTask; public: RSPOp(CRSPSystem & System); diff --git a/Source/Project64-rsp-core/cpu/RSPRegister.cpp b/Source/Project64-rsp-core/cpu/RSPRegister.cpp index 1c9dbcba4..c04ff984f 100644 --- a/Source/Project64-rsp-core/cpu/RSPRegister.cpp +++ b/Source/Project64-rsp-core/cpu/RSPRegister.cpp @@ -37,6 +37,42 @@ const char * GPR_Strings[32] = { "RA", }; +CGPRRegisters::CGPRRegisters(UWORD32 (&m_GPR)[32]) : + GPR_R0(m_GPR[0].UW), + GPR_AT(m_GPR[1].UW), + GPR_V0(m_GPR[2].UW), + GPR_V1(m_GPR[3].UW), + GPR_A0(m_GPR[4].UW), + GPR_A1(m_GPR[5].UW), + GPR_A2(m_GPR[6].UW), + GPR_A3(m_GPR[7].UW), + GPR_T0(m_GPR[8].UW), + GPR_T1(m_GPR[9].UW), + GPR_T2(m_GPR[10].UW), + GPR_T3(m_GPR[11].UW), + GPR_T4(m_GPR[12].UW), + GPR_T5(m_GPR[13].UW), + GPR_T6(m_GPR[14].UW), + GPR_T7(m_GPR[15].UW), + GPR_S0(m_GPR[16].UW), + GPR_S1(m_GPR[17].UW), + GPR_S2(m_GPR[18].UW), + GPR_S3(m_GPR[19].UW), + GPR_S4(m_GPR[20].UW), + GPR_S5(m_GPR[21].UW), + GPR_S6(m_GPR[22].UW), + GPR_S7(m_GPR[23].UW), + GPR_T8(m_GPR[24].UW), + GPR_T9(m_GPR[25].UW), + GPR_K0(m_GPR[26].UW), + GPR_K1(m_GPR[27].UW), + GPR_GP(m_GPR[28].UW), + GPR_SP(m_GPR[29].UW), + GPR_S8(m_GPR[30].UW), + GPR_RA(m_GPR[31].UW) +{ +} + CRSPRegisters::CRSPRegisters() : VCOL(m_Flags[0].UB[0]), VCOH(m_Flags[0].UB[1]), diff --git a/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp index 182e6c8e4..255bcff89 100644 --- a/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp +++ b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp @@ -20,7 +20,8 @@ RSPRegisterHandler::RSPRegisterHandler(uint32_t * SignalProcessorInterface, uint m_IMEM(IMEM), m_DMEM(DMEM), m_PendingSPMemAddr(0), - m_PendingSPDramAddr(0) + m_PendingSPDramAddr(0), + m_IgnoreWrites(false) { } @@ -39,7 +40,8 @@ RSPRegisterHandler::RSPRegisterHandler(CRSPSystem & System) : m_IMEM(System.m_IMEM), m_DMEM(System.m_DMEM), m_PendingSPMemAddr(0), - m_PendingSPDramAddr(0) + m_PendingSPDramAddr(0), + m_IgnoreWrites(System.m_BaseSystem != nullptr) { } @@ -166,7 +168,7 @@ void RSPRegisterHandler::SP_DMA_WRITE() { CopyAmount = CopyLength; } - if (CopyAmount > 0) + if (CopyAmount > 0 && !m_IgnoreWrites) { memcpy(&Dest[WritePos], &Source[Pos], CopyAmount); } @@ -183,7 +185,7 @@ void RSPRegisterHandler::SP_DMA_WRITE() { CopyAmount = CopyLength; } - if (CopyAmount > 0) + if (CopyAmount > 0 && !m_IgnoreWrites) { memcpy(&Dest[WritePos], &Source[Pos], CopyAmount); } diff --git a/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h index 567e39704..39bef0901 100644 --- a/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h +++ b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h @@ -63,4 +63,5 @@ protected: uint8_t * m_DMEM; uint32_t m_PendingSPMemAddr; uint32_t m_PendingSPDramAddr; + bool m_IgnoreWrites; }; diff --git a/Source/Project64-rsp-core/cpu/RSPRegisters.h b/Source/Project64-rsp-core/cpu/RSPRegisters.h index 15dd09ab1..8e3ac3ee3 100644 --- a/Source/Project64-rsp-core/cpu/RSPRegisters.h +++ b/Source/Project64-rsp-core/cpu/RSPRegisters.h @@ -71,6 +71,49 @@ enum MI_INTR_SP = 0x01, // Bit 0: SP INTR }; +class CGPRRegisters +{ +public: + CGPRRegisters(UWORD32 (&m_GPR)[32]); + +private: + CGPRRegisters(); + +protected: + uint32_t & GPR_R0; + uint32_t & GPR_AT; + uint32_t & GPR_V0; + uint32_t & GPR_V1; + uint32_t & GPR_A0; + uint32_t & GPR_A1; + uint32_t & GPR_A2; + uint32_t & GPR_A3; + uint32_t & GPR_T0; + uint32_t & GPR_T1; + uint32_t & GPR_T2; + uint32_t & GPR_T3; + uint32_t & GPR_T4; + uint32_t & GPR_T5; + uint32_t & GPR_T6; + uint32_t & GPR_T7; + uint32_t & GPR_S0; + uint32_t & GPR_S1; + uint32_t & GPR_S2; + uint32_t & GPR_S3; + uint32_t & GPR_S4; + uint32_t & GPR_S5; + uint32_t & GPR_S6; + uint32_t & GPR_S7; + uint32_t & GPR_T8; + uint32_t & GPR_T9; + uint32_t & GPR_K0; + uint32_t & GPR_K1; + uint32_t & GPR_GP; + uint32_t & GPR_SP; + uint32_t & GPR_S8; + uint32_t & GPR_RA; +}; + class CRSPRegisters { public: diff --git a/Source/Project64-rsp-core/cpu/RspPipelineStage.h b/Source/Project64-rsp-core/cpu/RspPipelineStage.h index 2436acd05..a47d7abed 100644 --- a/Source/Project64-rsp-core/cpu/RspPipelineStage.h +++ b/Source/Project64-rsp-core/cpu/RspPipelineStage.h @@ -2,15 +2,20 @@ enum RSPPIPELINE_STAGE { - RSPPIPELINE_NORMAL = 0, - RSPPIPELINE_DO_DELAY_SLOT = 1, - RSPPIPELINE_DELAY_SLOT = 2, - RSPPIPELINE_DELAY_SLOT_DONE = 3, - RSPPIPELINE_DELAY_SLOT_EXIT = 4, - RSPPIPELINE_DELAY_SLOT_EXIT_DONE = 5, - RSPPIPELINE_JUMP = 6, - RSPPIPELINE_SINGLE_STEP = 7, - RSPPIPELINE_SINGLE_STEP_DONE = 8, - RSPPIPELINE_FINISH_BLOCK = 9, - RSPPIPELINE_FINISH_SUB_BLOCK = 10, + RSPPIPELINE_NORMAL, + RSPPIPELINE_DO_DELAY_SLOT, + RSPPIPELINE_DO_DELAY_SLOT_EXIT, + RSPPIPELINE_DO_DELAY_SLOT_TASK_EXIT, + RSPPIPELINE_DELAY_SLOT, + RSPPIPELINE_DELAY_SLOT_DONE, + RSPPIPELINE_DELAY_SLOT_EXIT, + RSPPIPELINE_DELAY_SLOT_EXIT_DONE, + RSPPIPELINE_DELAY_SLOT_TASK_EXIT, + RSPPIPELINE_DELAY_SLOT_TASK_EXIT_DONE, + RSPPIPELINE_JUMP, + RSPPIPELINE_SINGLE_STEP, + RSPPIPELINE_SINGLE_STEP_DONE, + RSPPIPELINE_FINISH_BLOCK, + RSPPIPELINE_FINISH_SUB_BLOCK, + RSPPIPELINE_FINISH_TASK_SUB_BLOCK, }; \ No newline at end of file diff --git a/Source/Project64-rsp-core/cpu/RspSystem.cpp b/Source/Project64-rsp-core/cpu/RspSystem.cpp index 154d62505..ab94dc214 100644 --- a/Source/Project64-rsp-core/cpu/RspSystem.cpp +++ b/Source/Project64-rsp-core/cpu/RspSystem.cpp @@ -11,6 +11,8 @@ CRSPSystem RSPSystem; CRSPSystem::CRSPSystem() : CHleTask(*this), + m_SyncSystem(nullptr), + m_BaseSystem(nullptr), m_Recompiler(*this), m_RSPRegisterHandler(nullptr), m_Op(*this), @@ -38,9 +40,10 @@ CRSPSystem::CRSPSystem() : m_DPC_BUFBUSY_REG(nullptr), m_DPC_PIPEBUSY_REG(nullptr), m_DPC_TMEM_REG(nullptr), - CheckInterrupts(nullptr), - ProcessDList(nullptr), - ProcessRdpList(nullptr), + CheckInterrupts(NullCheckInterrupts), + ProcessDList(NullProcessDList), + ProcessRdpList(NullProcessRdpList), + m_SyncReg(nullptr), m_RdramSize(0) { m_OpCode.Value = 0; @@ -48,6 +51,29 @@ CRSPSystem::CRSPSystem() : CRSPSystem::~CRSPSystem() { + if (m_SyncSystem->m_BaseSystem != nullptr) + { + if (m_IMEM != nullptr) + { + delete[] m_IMEM; + m_IMEM = nullptr; + } + if (m_DMEM != nullptr) + { + delete[] m_DMEM; + m_DMEM = nullptr; + } + } + if (m_SyncReg != nullptr) + { + delete m_SyncReg; + m_SyncReg = nullptr; + } + if (m_SyncSystem) + { + delete m_SyncSystem; + m_SyncSystem = nullptr; + } if (m_RSPRegisterHandler != nullptr) { delete m_RSPRegisterHandler; @@ -61,29 +87,33 @@ void CRSPSystem::Reset(RSP_INFO & Info) m_HEADER = Info.HEADER; m_RDRAM = Info.RDRAM; - m_DMEM = Info.DMEM; - m_IMEM = Info.IMEM; - m_MI_INTR_REG = Info.MI_INTR_REG; - m_SP_MEM_ADDR_REG = Info.SP_MEM_ADDR_REG; - m_SP_DRAM_ADDR_REG = Info.SP_DRAM_ADDR_REG; - m_SP_RD_LEN_REG = Info.SP_RD_LEN_REG; - m_SP_WR_LEN_REG = Info.SP_WR_LEN_REG; - m_SP_STATUS_REG = Info.SP_STATUS_REG; - m_SP_DMA_FULL_REG = Info.SP_DMA_FULL_REG; - m_SP_DMA_BUSY_REG = Info.SP_DMA_BUSY_REG; - m_SP_PC_REG = Info.SP_PC_REG; - m_SP_SEMAPHORE_REG = Info.SP_SEMAPHORE_REG; - m_DPC_START_REG = Info.DPC_START_REG; - m_DPC_END_REG = Info.DPC_END_REG; - m_DPC_CURRENT_REG = Info.DPC_CURRENT_REG; - m_DPC_STATUS_REG = Info.DPC_STATUS_REG; - m_DPC_CLOCK_REG = Info.DPC_CLOCK_REG; - m_DPC_BUFBUSY_REG = Info.DPC_BUFBUSY_REG; - m_DPC_PIPEBUSY_REG = Info.DPC_PIPEBUSY_REG; - m_DPC_TMEM_REG = Info.DPC_TMEM_REG; - CheckInterrupts = Info.CheckInterrupts; - ProcessDList = Info.ProcessDList; - ProcessRdpList = Info.ProcessRdpList; + + if (m_BaseSystem == nullptr) + { + m_DMEM = Info.DMEM; + m_IMEM = Info.IMEM; + m_MI_INTR_REG = Info.MI_INTR_REG; + m_SP_MEM_ADDR_REG = Info.SP_MEM_ADDR_REG; + m_SP_DRAM_ADDR_REG = Info.SP_DRAM_ADDR_REG; + m_SP_RD_LEN_REG = Info.SP_RD_LEN_REG; + m_SP_WR_LEN_REG = Info.SP_WR_LEN_REG; + m_SP_STATUS_REG = Info.SP_STATUS_REG; + m_SP_DMA_FULL_REG = Info.SP_DMA_FULL_REG; + m_SP_DMA_BUSY_REG = Info.SP_DMA_BUSY_REG; + m_SP_PC_REG = Info.SP_PC_REG; + m_SP_SEMAPHORE_REG = Info.SP_SEMAPHORE_REG; + m_DPC_START_REG = Info.DPC_START_REG; + m_DPC_END_REG = Info.DPC_END_REG; + m_DPC_CURRENT_REG = Info.DPC_CURRENT_REG; + m_DPC_STATUS_REG = Info.DPC_STATUS_REG; + m_DPC_CLOCK_REG = Info.DPC_CLOCK_REG; + m_DPC_BUFBUSY_REG = Info.DPC_BUFBUSY_REG; + m_DPC_PIPEBUSY_REG = Info.DPC_PIPEBUSY_REG; + m_DPC_TMEM_REG = Info.DPC_TMEM_REG; + CheckInterrupts = Info.CheckInterrupts; + ProcessDList = Info.ProcessDList; + ProcessRdpList = Info.ProcessRdpList; + } m_RdramSize = Set_AllocatedRdramSize != 0 ? GetSystemSetting(Set_AllocatedRdramSize) : 0; if (m_RdramSize == 0) @@ -91,6 +121,11 @@ void CRSPSystem::Reset(RSP_INFO & Info) m_RdramSize = 0x00400000; } m_RSPRegisterHandler = new RSPRegisterHandlerPlugin(*this); + + if (m_SyncSystem != nullptr) + { + m_SyncSystem->Reset(Info); + } } void CRSPSystem::RomClosed(void) @@ -159,3 +194,166 @@ void CRSPSystem::ExecuteOps(uint32_t Cycles, uint32_t TargetPC) } } } + +void CRSPSystem::SetupSyncCPU() +{ + if (m_SyncSystem == nullptr) + { + m_SyncSystem = new CRSPSystem(); + m_SyncSystem->m_BaseSystem = this; + m_SyncSystem->m_HEADER = m_HEADER; + m_SyncSystem->m_RDRAM = m_RDRAM; + m_SyncSystem->m_IMEM = new uint8_t[0x1000]; + m_SyncSystem->m_DMEM = new uint8_t[0x1000]; + m_SyncSystem->m_SyncReg = new uint32_t[18]; + m_SyncSystem->m_MI_INTR_REG = &m_SyncSystem->m_SyncReg[0]; + m_SyncSystem->m_SP_MEM_ADDR_REG = &m_SyncSystem->m_SyncReg[1]; + m_SyncSystem->m_SP_DRAM_ADDR_REG = &m_SyncSystem->m_SyncReg[2]; + m_SyncSystem->m_SP_RD_LEN_REG = &m_SyncSystem->m_SyncReg[3]; + m_SyncSystem->m_SP_WR_LEN_REG = &m_SyncSystem->m_SyncReg[4]; + m_SyncSystem->m_SP_STATUS_REG = &m_SyncSystem->m_SyncReg[5]; + m_SyncSystem->m_SP_DMA_FULL_REG = &m_SyncSystem->m_SyncReg[6]; + m_SyncSystem->m_SP_DMA_BUSY_REG = &m_SyncSystem->m_SyncReg[7]; + m_SyncSystem->m_SP_PC_REG = &m_SyncSystem->m_SyncReg[8]; + m_SyncSystem->m_SP_SEMAPHORE_REG = &m_SyncSystem->m_SyncReg[9]; + m_SyncSystem->m_DPC_START_REG = &m_SyncSystem->m_SyncReg[10]; + m_SyncSystem->m_DPC_END_REG = &m_SyncSystem->m_SyncReg[11]; + m_SyncSystem->m_DPC_CURRENT_REG = &m_SyncSystem->m_SyncReg[12]; + m_SyncSystem->m_DPC_STATUS_REG = &m_SyncSystem->m_SyncReg[13]; + m_SyncSystem->m_DPC_CLOCK_REG = &m_SyncSystem->m_SyncReg[14]; + m_SyncSystem->m_DPC_BUFBUSY_REG = &m_SyncSystem->m_SyncReg[15]; + m_SyncSystem->m_DPC_PIPEBUSY_REG = &m_SyncSystem->m_SyncReg[16]; + m_SyncSystem->m_DPC_TMEM_REG = &m_SyncSystem->m_SyncReg[17]; + + m_SyncSystem->m_Reg.Reset(); + m_SyncSystem->m_RdramSize = m_RdramSize; + m_SyncSystem->m_RSPRegisterHandler = new RSPRegisterHandlerPlugin(*m_SyncSystem); + } + if (m_IMEM != nullptr) + { + memcpy(m_SyncSystem->m_IMEM, m_IMEM, 0x1000); + } + if (m_DMEM != nullptr) + { + memcpy(m_SyncSystem->m_DMEM, m_DMEM, 0x1000); + } + *m_SyncSystem->m_MI_INTR_REG = *m_MI_INTR_REG; + *m_SyncSystem->m_SP_MEM_ADDR_REG = *m_SP_MEM_ADDR_REG; + *m_SyncSystem->m_SP_DRAM_ADDR_REG = *m_SP_DRAM_ADDR_REG; + *m_SyncSystem->m_SP_RD_LEN_REG = *m_SP_RD_LEN_REG; + *m_SyncSystem->m_SP_WR_LEN_REG = *m_SP_WR_LEN_REG; + *m_SyncSystem->m_SP_STATUS_REG = *m_SP_STATUS_REG; + *m_SyncSystem->m_SP_DMA_FULL_REG = *m_SP_DMA_FULL_REG; + *m_SyncSystem->m_SP_DMA_BUSY_REG = *m_SP_DMA_BUSY_REG; + *m_SyncSystem->m_SP_PC_REG = *m_SP_PC_REG; + *m_SyncSystem->m_SP_SEMAPHORE_REG = *m_SP_SEMAPHORE_REG; + *m_SyncSystem->m_DPC_START_REG = *m_DPC_START_REG; + *m_SyncSystem->m_DPC_END_REG = *m_DPC_END_REG; + *m_SyncSystem->m_DPC_CURRENT_REG = *m_DPC_CURRENT_REG; + *m_SyncSystem->m_DPC_STATUS_REG = *m_DPC_STATUS_REG; + *m_SyncSystem->m_DPC_CLOCK_REG = *m_DPC_CLOCK_REG; + *m_SyncSystem->m_DPC_BUFBUSY_REG = *m_DPC_BUFBUSY_REG; + *m_SyncSystem->m_DPC_PIPEBUSY_REG = *m_DPC_PIPEBUSY_REG; + *m_SyncSystem->m_DPC_TMEM_REG = *m_DPC_TMEM_REG; +} + +bool CRSPSystem::IsSyncSystem(void) +{ + return m_BaseSystem != nullptr; +} + +CRSPSystem * CRSPSystem::SyncSystem(void) +{ + if (m_SyncSystem == nullptr) + { + SetupSyncCPU(); + } + return m_SyncSystem; +} + +void CRSPSystem::BasicSyncCheck(void) +{ + bool SyncFailed = false; + if (memcmp(m_IMEM, m_SyncSystem->m_IMEM, 0x1000) != 0) + { + SyncFailed = true; + } + if (memcmp(m_DMEM, m_SyncSystem->m_DMEM, 0x1000) != 0) + { + SyncFailed = true; + for (uint32_t i = 0, n = 0x1000; i < n; i++) + { + if (m_DMEM[i] != m_SyncSystem->m_DMEM[i]) + { + SyncFailed = true; + break; + } + } + } + if (*m_MI_INTR_REG != *m_SyncSystem->m_MI_INTR_REG) + { + SyncFailed = true; + } + if (*m_SP_MEM_ADDR_REG != *m_SyncSystem->m_SP_MEM_ADDR_REG) + { + SyncFailed = true; + } + if (*m_SP_DRAM_ADDR_REG != *m_SyncSystem->m_SP_DRAM_ADDR_REG) + { + SyncFailed = true; + } + if (*m_SP_RD_LEN_REG != *m_SyncSystem->m_SP_RD_LEN_REG) + { + SyncFailed = true; + } + if (*m_SP_WR_LEN_REG != *m_SyncSystem->m_SP_WR_LEN_REG) + { + SyncFailed = true; + } + if (*m_SP_STATUS_REG != *m_SyncSystem->m_SP_STATUS_REG) + { + SyncFailed = true; + } + if (*m_SP_DMA_FULL_REG != *m_SyncSystem->m_SP_DMA_FULL_REG) + { + SyncFailed = true; + } + if (*m_SP_DMA_BUSY_REG != *m_SyncSystem->m_SP_DMA_BUSY_REG) + { + SyncFailed = true; + } + if (*m_SP_PC_REG != *m_SyncSystem->m_SP_PC_REG) + { + SyncFailed = true; + } + if (*m_SP_SEMAPHORE_REG != *m_SyncSystem->m_SP_SEMAPHORE_REG) + { + SyncFailed = true; + } + if (SyncFailed) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } +} + +void * CRSPSystem::operator new(size_t size) +{ + return _aligned_malloc(size, 16); +} + +void CRSPSystem::operator delete(void * ptr) +{ + _aligned_free(ptr); +} + +void CRSPSystem::NullProcessDList(void) +{ +} + +void CRSPSystem::NullProcessRdpList(void) +{ +} + +void CRSPSystem::NullCheckInterrupts(void) +{ +} diff --git a/Source/Project64-rsp-core/cpu/RspSystem.h b/Source/Project64-rsp-core/cpu/RspSystem.h index cc7d98c8c..f6afcd063 100644 --- a/Source/Project64-rsp-core/cpu/RspSystem.h +++ b/Source/Project64-rsp-core/cpu/RspSystem.h @@ -34,11 +34,23 @@ public: void RunRecompiler(void); void ExecuteOps(uint32_t Cycles, uint32_t TargetPC); + void SetupSyncCPU(); + bool IsSyncSystem(void); + CRSPSystem * SyncSystem(void); + void BasicSyncCheck(void); + void * operator new(size_t size); + void operator delete(void * ptr); private: CRSPSystem(const CRSPSystem &); CRSPSystem & operator=(const CRSPSystem &); + static void NullProcessDList(void); + static void NullProcessRdpList(void); + static void NullCheckInterrupts(void); + + CRSPSystem * m_SyncSystem; + CRSPSystem * m_BaseSystem; CRSPRecompiler m_Recompiler; RSPRegisterHandlerPlugin * m_RSPRegisterHandler; CRSPRegisters m_Reg; @@ -69,6 +81,7 @@ private: uint32_t * m_DPC_PIPEBUSY_REG; uint32_t * m_DPC_TMEM_REG; uint32_t m_RdramSize; + uint32_t * m_SyncReg; void (*CheckInterrupts)(void); void (*ProcessDList)(void); void (*ProcessRdpList)(void); diff --git a/Source/Project64-rsp/Main.cpp b/Source/Project64-rsp/Main.cpp index 3c730c965..c6a6e8929 100644 --- a/Source/Project64-rsp/Main.cpp +++ b/Source/Project64-rsp/Main.cpp @@ -179,9 +179,11 @@ void FixMenuState(void) CheckMenuItem(hRSPMenu, ID_CPUMETHOD_RECOMPILER, MF_BYCOMMAND | ((RSPCpuMethod)GetSetting(Set_CPUCore) == RSPCpuMethod::Recompiler ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_CPUMETHOD_INTERPT, MF_BYCOMMAND | ((RSPCpuMethod)GetSetting(Set_CPUCore) == RSPCpuMethod::Interpreter ? MFS_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hRSPMenu, ID_CPUMETHOD_RECOMPILER_TASKS, MF_BYCOMMAND | ((RSPCpuMethod)GetSetting(Set_CPUCore) == RSPCpuMethod::RecompilerTasks ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_CPUMETHOD_HLE, MF_BYCOMMAND | ((RSPCpuMethod)GetSetting(Set_CPUCore) == RSPCpuMethod::HighLevelEmulation ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_BREAKONSTARTOFTASK, MF_BYCOMMAND | (BreakOnStart ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_LOGRDPCOMMANDS, MF_BYCOMMAND | (LogRDP ? MFS_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hRSPMenu, ID_SETTINGS_SYNCCPU, MF_BYCOMMAND | (SyncCPU ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_SETTINGS_HLEALISTTASK, MF_BYCOMMAND | (HleAlistTask ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_SETTINGS_LOGX86CODE, MF_BYCOMMAND | (LogX86Code ? MFS_CHECKED : MF_UNCHECKED)); CheckMenuItem(hRSPMenu, ID_SETTINGS_MULTITHREADED, MF_BYCOMMAND | (MultiThreadedDefault ? MFS_CHECKED : MF_UNCHECKED)); @@ -384,6 +386,13 @@ void ProcessMenuItem(int32_t ID) } break; } + case ID_SETTINGS_SYNCCPU: + { + bool Checked = (GetMenuState(hRSPMenu, ID_SETTINGS_SYNCCPU, MF_BYCOMMAND) & MFS_CHECKED) != 0; + CheckMenuItem(hRSPMenu, ID_SETTINGS_SYNCCPU, MF_BYCOMMAND | (Checked ? MFS_UNCHECKED : MFS_CHECKED)); + SetSetting(Set_SyncCPU, !Checked); + break; + } case ID_SETTINGS_HLEALISTTASK: { bool Checked = (GetMenuState(hRSPMenu, ID_SETTINGS_HLEALISTTASK, MF_BYCOMMAND) & MFS_CHECKED) != 0; @@ -410,6 +419,10 @@ void ProcessMenuItem(int32_t ID) SetSetting(Set_CPUCore, (int)RSPCpuMethod::Interpreter); FixMenuState(); break; + case ID_CPUMETHOD_RECOMPILER_TASKS: + SetSetting(Set_CPUCore, (int)RSPCpuMethod::RecompilerTasks); + FixMenuState(); + break; case ID_CPUMETHOD_HLE: SetSetting(Set_CPUCore, (int)RSPCpuMethod::HighLevelEmulation); FixMenuState(); @@ -551,7 +564,6 @@ BOOL CALLBACK ConfigDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM /*lParam hWndItem = GetDlgItem(hDlg, IDC_COMPILER_SELECT); ComboBox_AddString(hWndItem, "Interpreter"); ComboBox_AddString(hWndItem, "Recompiler"); - //ComboBox_SetCurSel(hWndItem, g_CPUCore); break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) @@ -596,6 +608,7 @@ EXPORT void EnableDebugging(int Enabled) IndvidualBlock = GetSetting(Set_IndvidualBlock) != 0; ShowErrors = GetSetting(Set_ShowErrors) != 0; HleAlistTask = GetSetting(Set_HleAlistTask) != 0; + SyncCPU = GetSetting(Set_SyncCPU) != 0; Compiler.bDest = GetSetting(Set_CheckDest) != 0; Compiler.bAccum = GetSetting(Set_Accum) != 0; diff --git a/Source/Project64-rsp/Project64-rsp.rc b/Source/Project64-rsp/Project64-rsp.rc index fd8d8eab8..556959f81 100644 --- a/Source/Project64-rsp/Project64-rsp.rc +++ b/Source/Project64-rsp/Project64-rsp.rc @@ -170,6 +170,7 @@ BEGIN POPUP "CPU Method" BEGIN MENUITEM "Recompiler", ID_CPUMETHOD_RECOMPILER + MENUITEM "Recompiler Tasks", ID_CPUMETHOD_RECOMPILER_TASKS MENUITEM "Interpreter", ID_CPUMETHOD_INTERPT MENUITEM "HLE", ID_CPUMETHOD_HLE END @@ -196,6 +197,7 @@ BEGIN MENUITEM "Break on start of task", ID_BREAKONSTARTOFTASK MENUITEM "Log RDP Commands", ID_LOGRDPCOMMANDS MENUITEM "Log X86 code", ID_SETTINGS_LOGX86CODE + MENUITEM "Sync CPU", ID_SETTINGS_SYNCCPU MENUITEM "Multithreaded", ID_SETTINGS_MULTITHREADED END END diff --git a/Source/Project64-rsp/resource.h b/Source/Project64-rsp/resource.h index 7a90e418b..729366a00 100644 --- a/Source/Project64-rsp/resource.h +++ b/Source/Project64-rsp/resource.h @@ -40,13 +40,15 @@ #define ID_SETTINGS_MULTITHREADED 5020 #define ID_SETTINGS_HLEALISTTASK 5021 #define ID_CPUMETHOD_HLE 5022 +#define ID_CPUMETHOD_RECOMPILER_TASKS 5023 +#define ID_SETTINGS_SYNCCPU 5024 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 108 -#define _APS_NEXT_COMMAND_VALUE 5023 +#define _APS_NEXT_COMMAND_VALUE 5025 #define _APS_NEXT_CONTROL_VALUE 1032 #define _APS_NEXT_SYMED_VALUE 101 #endif