RSP: Be able to compile sections based off tasks

This commit is contained in:
zilmar 2024-09-19 12:15:11 +09:30
parent 3340c032c3
commit c098a6a464
22 changed files with 781 additions and 71 deletions

View File

@ -1,15 +1,25 @@
#include <Project64-rsp-core/Hle/HleTask.h>
#include <Project64-rsp-core/cpu/RSPRegisterHandlerPlugin.h>
#include <Project64-rsp-core/cpu/RspMemory.h>
#include <Project64-rsp-core/cpu/RspSystem.h>
#include <zlib/zlib.h>
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;

View File

@ -1,14 +1,23 @@
#pragma once
#include <Project64-rsp-core/Hle/hle.h>
#include <Project64-rsp-core/cpu/RSPRegisters.h>
#include <Project64-rsp-core/cpu/RspTypes.h>
#include <map>
#include <stdint.h>
#include <vector>
class CRSPSystem;
class RSPRegisterHandlerPlugin;
class CRSPRecompiler;
class CHle;
class CHleTask
class CHleTask :
private CGPRRegisters
{
typedef std::pair<uint32_t, void *> TaskFunctionAddress;
typedef std::vector<TaskFunctionAddress> TaskFunctions;
typedef std::map<uint32_t, TaskFunctions> 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;
};

View File

@ -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)

View File

@ -1,5 +1,6 @@
#pragma once
#include <Project64-rsp-core/Recompiler/RspRecompilerOps.h>
#include <Project64-rsp-core/Settings/RspSettings.h>
#include <Project64-rsp-core/cpu/RSPOpcode.h>
#include <Project64-rsp-core/cpu/RspPipelineStage.h>
@ -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;

View File

@ -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;

View File

@ -1,8 +1,9 @@
// Opcode functions
#pragma once
#include <Project64-rsp-core/cpu/RSPInterpreterOps.h>
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);

View File

@ -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);

View File

@ -2,14 +2,15 @@
#include <stdint.h>
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

View File

@ -10,6 +10,7 @@ enum
Set_IndvidualBlock,
Set_ShowErrors,
Set_HleAlistTask,
Set_SyncCPU,
// Compiler settings
Set_CheckDest,

View File

@ -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;

View File

@ -12,8 +12,6 @@
#include <float.h>
#include <math.h>
extern bool AudioHle, GraphicsHle;
uint32_t clz32(uint32_t val)
{
#if defined(__GNUC__)

View File

@ -1,4 +1,5 @@
#pragma once
#include <Project64-rsp-core/Settings/RspSettings.h>
#include <Project64-rsp-core/cpu/RSPOpcode.h>
#include <Project64-rsp-core/cpu/RspPipelineStage.h>
#include <Project64-rsp-core/cpu/RspTypes.h>
@ -12,6 +13,7 @@ class RSPOp :
{
friend class CRSPSystem;
friend class CRSPRecompilerOps;
friend class CHleTask;
public:
RSPOp(CRSPSystem & System);

View File

@ -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]),

View File

@ -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);
}

View File

@ -63,4 +63,5 @@ protected:
uint8_t * m_DMEM;
uint32_t m_PendingSPMemAddr;
uint32_t m_PendingSPDramAddr;
bool m_IgnoreWrites;
};

View File

@ -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:

View File

@ -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,
};

View File

@ -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,6 +87,9 @@ void CRSPSystem::Reset(RSP_INFO & Info)
m_HEADER = Info.HEADER;
m_RDRAM = Info.RDRAM;
if (m_BaseSystem == nullptr)
{
m_DMEM = Info.DMEM;
m_IMEM = Info.IMEM;
m_MI_INTR_REG = Info.MI_INTR_REG;
@ -84,6 +113,7 @@ void CRSPSystem::Reset(RSP_INFO & Info)
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)
{
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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