mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
DolphinQt: Properly lock CPU before accessing emulated memory
This fixes a problem I was having where using frame advance with the debugger open would frequently cause panic alerts about invalid addresses due to the CPU thread changing MSR.DR while the host thread was trying to access memory. To aid in tracking down all the places where we weren't properly locking the CPU, I've created a new type (in Core.h) that you have to pass as a reference or pointer to functions that require running as the CPU thread.
This commit is contained in:
@@ -122,14 +122,14 @@ InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& ins
|
||||
return tmp_attributes;
|
||||
}
|
||||
|
||||
TraceOutput CodeTrace::SaveCurrentInstruction() const
|
||||
TraceOutput CodeTrace::SaveCurrentInstruction(const Core::CPUThreadGuard* guard) const
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
|
||||
// Quickly save instruction and memory target for fast logging.
|
||||
TraceOutput output;
|
||||
const std::string instr = PowerPC::debug_interface.Disassemble(ppc_state.pc);
|
||||
const std::string instr = PowerPC::debug_interface.Disassemble(guard, ppc_state.pc);
|
||||
output.instruction = instr;
|
||||
output.address = ppc_state.pc;
|
||||
|
||||
@@ -139,14 +139,15 @@ TraceOutput CodeTrace::SaveCurrentInstruction() const
|
||||
return output;
|
||||
}
|
||||
|
||||
AutoStepResults CodeTrace::AutoStepping(bool continue_previous, AutoStop stop_on)
|
||||
AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool continue_previous,
|
||||
AutoStop stop_on)
|
||||
{
|
||||
AutoStepResults results;
|
||||
|
||||
if (!CPU::IsStepping() || m_recording)
|
||||
if (m_recording)
|
||||
return results;
|
||||
|
||||
TraceOutput pc_instr = SaveCurrentInstruction();
|
||||
TraceOutput pc_instr = SaveCurrentInstruction(&guard);
|
||||
const InstructionAttributes instr = GetInstructionAttributes(pc_instr);
|
||||
|
||||
// Not an instruction we should start autostepping from (ie branches).
|
||||
@@ -187,7 +188,6 @@ AutoStepResults CodeTrace::AutoStepping(bool continue_previous, AutoStop stop_on
|
||||
else if (stop_on == AutoStop::Changed)
|
||||
stop_condition = HitType::ACTIVE;
|
||||
|
||||
CPU::PauseAndLock(true, false);
|
||||
PowerPC::breakpoints.ClearAllTemporary();
|
||||
using clock = std::chrono::steady_clock;
|
||||
clock::time_point timeout = clock::now() + std::chrono::seconds(4);
|
||||
@@ -199,7 +199,7 @@ AutoStepResults CodeTrace::AutoStepping(bool continue_previous, AutoStop stop_on
|
||||
{
|
||||
PowerPC::SingleStep();
|
||||
|
||||
pc_instr = SaveCurrentInstruction();
|
||||
pc_instr = SaveCurrentInstruction(&guard);
|
||||
hit = TraceLogic(pc_instr);
|
||||
results.count += 1;
|
||||
} while (clock::now() < timeout && hit < stop_condition &&
|
||||
@@ -210,7 +210,6 @@ AutoStepResults CodeTrace::AutoStepping(bool continue_previous, AutoStop stop_on
|
||||
results.timed_out = true;
|
||||
|
||||
PowerPC::SetMode(old_mode);
|
||||
CPU::PauseAndLock(false, false);
|
||||
m_recording = false;
|
||||
|
||||
results.reg_tracked = m_reg_autotrack;
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
}
|
||||
|
||||
struct InstructionAttributes
|
||||
{
|
||||
u32 address = 0;
|
||||
@@ -63,11 +68,12 @@ public:
|
||||
};
|
||||
|
||||
void SetRegTracked(const std::string& reg);
|
||||
AutoStepResults AutoStepping(bool continue_previous = false, AutoStop stop_on = AutoStop::Always);
|
||||
AutoStepResults AutoStepping(const Core::CPUThreadGuard& guard, bool continue_previous = false,
|
||||
AutoStop stop_on = AutoStop::Always);
|
||||
|
||||
private:
|
||||
InstructionAttributes GetInstructionAttributes(const TraceOutput& line) const;
|
||||
TraceOutput SaveCurrentInstruction() const;
|
||||
TraceOutput SaveCurrentInstruction(const Core::CPUThreadGuard* guard) const;
|
||||
HitType TraceLogic(const TraceOutput& current_instr, bool first_hit = false);
|
||||
|
||||
bool m_recording = false;
|
||||
|
||||
@@ -23,36 +23,37 @@ MemoryPatch::MemoryPatch(u32 address_, u32 value_)
|
||||
MemoryPatches::MemoryPatches() = default;
|
||||
MemoryPatches::~MemoryPatches() = default;
|
||||
|
||||
void MemoryPatches::SetPatch(u32 address, u32 value)
|
||||
void MemoryPatches::SetPatch(const Core::CPUThreadGuard& guard, u32 address, u32 value)
|
||||
{
|
||||
const std::size_t index = m_patches.size();
|
||||
m_patches.emplace_back(address, value);
|
||||
Patch(index);
|
||||
Patch(guard, index);
|
||||
}
|
||||
|
||||
void MemoryPatches::SetPatch(u32 address, std::vector<u8> value)
|
||||
void MemoryPatches::SetPatch(const Core::CPUThreadGuard& guard, u32 address, std::vector<u8> value)
|
||||
{
|
||||
UnsetPatch(address);
|
||||
UnsetPatch(guard, address);
|
||||
const std::size_t index = m_patches.size();
|
||||
m_patches.emplace_back(address, std::move(value));
|
||||
Patch(index);
|
||||
Patch(guard, index);
|
||||
}
|
||||
|
||||
void MemoryPatches::SetFramePatch(u32 address, u32 value)
|
||||
void MemoryPatches::SetFramePatch(const Core::CPUThreadGuard& guard, u32 address, u32 value)
|
||||
{
|
||||
const std::size_t index = m_patches.size();
|
||||
m_patches.emplace_back(address, value);
|
||||
m_patches.back().type = MemoryPatch::ApplyType::EachFrame;
|
||||
Patch(index);
|
||||
Patch(guard, index);
|
||||
}
|
||||
|
||||
void MemoryPatches::SetFramePatch(u32 address, std::vector<u8> value)
|
||||
void MemoryPatches::SetFramePatch(const Core::CPUThreadGuard& guard, u32 address,
|
||||
std::vector<u8> value)
|
||||
{
|
||||
UnsetPatch(address);
|
||||
UnsetPatch(guard, address);
|
||||
const std::size_t index = m_patches.size();
|
||||
m_patches.emplace_back(address, std::move(value));
|
||||
m_patches.back().type = MemoryPatch::ApplyType::EachFrame;
|
||||
Patch(index);
|
||||
Patch(guard, index);
|
||||
}
|
||||
|
||||
const std::vector<MemoryPatch>& MemoryPatches::GetPatches() const
|
||||
@@ -60,7 +61,7 @@ const std::vector<MemoryPatch>& MemoryPatches::GetPatches() const
|
||||
return m_patches;
|
||||
}
|
||||
|
||||
void MemoryPatches::UnsetPatch(u32 address)
|
||||
void MemoryPatches::UnsetPatch(const Core::CPUThreadGuard& guard, u32 address)
|
||||
{
|
||||
const auto it = std::find_if(m_patches.begin(), m_patches.end(),
|
||||
[address](const auto& patch) { return patch.address == address; });
|
||||
@@ -69,23 +70,23 @@ void MemoryPatches::UnsetPatch(u32 address)
|
||||
return;
|
||||
|
||||
const std::size_t index = std::distance(m_patches.begin(), it);
|
||||
RemovePatch(index);
|
||||
RemovePatch(guard, index);
|
||||
}
|
||||
|
||||
void MemoryPatches::EnablePatch(std::size_t index)
|
||||
void MemoryPatches::EnablePatch(const Core::CPUThreadGuard& guard, std::size_t index)
|
||||
{
|
||||
if (m_patches[index].is_enabled == MemoryPatch::State::Enabled)
|
||||
return;
|
||||
m_patches[index].is_enabled = MemoryPatch::State::Enabled;
|
||||
Patch(index);
|
||||
Patch(guard, index);
|
||||
}
|
||||
|
||||
void MemoryPatches::DisablePatch(std::size_t index)
|
||||
void MemoryPatches::DisablePatch(const Core::CPUThreadGuard& guard, std::size_t index)
|
||||
{
|
||||
if (m_patches[index].is_enabled == MemoryPatch::State::Disabled)
|
||||
return;
|
||||
m_patches[index].is_enabled = MemoryPatch::State::Disabled;
|
||||
Patch(index);
|
||||
Patch(guard, index);
|
||||
}
|
||||
|
||||
bool MemoryPatches::HasEnabledPatch(u32 address) const
|
||||
@@ -95,19 +96,19 @@ bool MemoryPatches::HasEnabledPatch(u32 address) const
|
||||
});
|
||||
}
|
||||
|
||||
void MemoryPatches::RemovePatch(std::size_t index)
|
||||
void MemoryPatches::RemovePatch(const Core::CPUThreadGuard& guard, std::size_t index)
|
||||
{
|
||||
DisablePatch(index);
|
||||
DisablePatch(guard, index);
|
||||
UnPatch(index);
|
||||
m_patches.erase(m_patches.begin() + index);
|
||||
}
|
||||
|
||||
void MemoryPatches::ClearPatches()
|
||||
void MemoryPatches::ClearPatches(const Core::CPUThreadGuard& guard)
|
||||
{
|
||||
const std::size_t size = m_patches.size();
|
||||
for (std::size_t index = 0; index < size; ++index)
|
||||
{
|
||||
DisablePatch(index);
|
||||
DisablePatch(guard, index);
|
||||
UnPatch(index);
|
||||
}
|
||||
m_patches.clear();
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
}
|
||||
|
||||
namespace Common::Debug
|
||||
{
|
||||
struct MemoryPatch
|
||||
@@ -40,21 +45,21 @@ public:
|
||||
MemoryPatches();
|
||||
virtual ~MemoryPatches();
|
||||
|
||||
void SetPatch(u32 address, u32 value);
|
||||
void SetPatch(u32 address, std::vector<u8> value);
|
||||
void SetFramePatch(u32 address, u32 value);
|
||||
void SetFramePatch(u32 address, std::vector<u8> value);
|
||||
void SetPatch(const Core::CPUThreadGuard& guard, u32 address, u32 value);
|
||||
void SetPatch(const Core::CPUThreadGuard& guard, u32 address, std::vector<u8> value);
|
||||
void SetFramePatch(const Core::CPUThreadGuard& guard, u32 address, u32 value);
|
||||
void SetFramePatch(const Core::CPUThreadGuard& guard, u32 address, std::vector<u8> value);
|
||||
const std::vector<MemoryPatch>& GetPatches() const;
|
||||
void UnsetPatch(u32 address);
|
||||
void EnablePatch(std::size_t index);
|
||||
void DisablePatch(std::size_t index);
|
||||
void UnsetPatch(const Core::CPUThreadGuard& guard, u32 address);
|
||||
void EnablePatch(const Core::CPUThreadGuard& guard, std::size_t index);
|
||||
void DisablePatch(const Core::CPUThreadGuard& guard, std::size_t index);
|
||||
bool HasEnabledPatch(u32 address) const;
|
||||
void RemovePatch(std::size_t index);
|
||||
void ClearPatches();
|
||||
virtual void ApplyExistingPatch(std::size_t index) = 0;
|
||||
void RemovePatch(const Core::CPUThreadGuard& guard, std::size_t index);
|
||||
void ClearPatches(const Core::CPUThreadGuard& guard);
|
||||
virtual void ApplyExistingPatch(const Core::CPUThreadGuard& guard, std::size_t index) = 0;
|
||||
|
||||
protected:
|
||||
virtual void Patch(std::size_t index) = 0;
|
||||
virtual void Patch(const Core::CPUThreadGuard& guard, std::size_t index) = 0;
|
||||
virtual void UnPatch(std::size_t index) = 0;
|
||||
|
||||
std::vector<MemoryPatch> m_patches;
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
};
|
||||
|
||||
namespace Common::Debug
|
||||
{
|
||||
struct PartialContext
|
||||
@@ -41,7 +46,7 @@ public:
|
||||
LWPThread, // devkitPro libogc thread
|
||||
};
|
||||
|
||||
virtual PartialContext GetContext() const = 0;
|
||||
virtual PartialContext GetContext(const Core::CPUThreadGuard& guard) const = 0;
|
||||
virtual u32 GetAddress() const = 0;
|
||||
virtual u16 GetState() const = 0;
|
||||
virtual bool IsSuspended() const = 0;
|
||||
@@ -53,8 +58,8 @@ public:
|
||||
virtual std::size_t GetStackSize() const = 0;
|
||||
virtual s32 GetErrno() const = 0;
|
||||
// Implementation specific, used to store arbitrary data
|
||||
virtual std::string GetSpecific() const = 0;
|
||||
virtual bool IsValid() const = 0;
|
||||
virtual std::string GetSpecific(const Core::CPUThreadGuard& guard) const = 0;
|
||||
virtual bool IsValid(const Core::CPUThreadGuard& guard) const = 0;
|
||||
};
|
||||
|
||||
using Threads = std::vector<std::unique_ptr<ThreadView>>;
|
||||
|
||||
@@ -16,6 +16,11 @@ struct MemoryPatch;
|
||||
struct Watch;
|
||||
} // namespace Common::Debug
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
} // namespace Core
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class DebugInterface
|
||||
@@ -42,24 +47,29 @@ public:
|
||||
virtual void ClearWatches() = 0;
|
||||
|
||||
// Memory Patches
|
||||
virtual void SetPatch(u32 address, u32 value) = 0;
|
||||
virtual void SetPatch(u32 address, std::vector<u8> value) = 0;
|
||||
virtual void SetFramePatch(u32 address, u32 value) = 0;
|
||||
virtual void SetFramePatch(u32 address, std::vector<u8> value) = 0;
|
||||
virtual void SetPatch(const Core::CPUThreadGuard& guard, u32 address, u32 value) = 0;
|
||||
virtual void SetPatch(const Core::CPUThreadGuard& guard, u32 address, std::vector<u8> value) = 0;
|
||||
virtual void SetFramePatch(const Core::CPUThreadGuard& guard, u32 address, u32 value) = 0;
|
||||
virtual void SetFramePatch(const Core::CPUThreadGuard& guard, u32 address,
|
||||
std::vector<u8> value) = 0;
|
||||
virtual const std::vector<Debug::MemoryPatch>& GetPatches() const = 0;
|
||||
virtual void UnsetPatch(u32 address) = 0;
|
||||
virtual void EnablePatch(std::size_t index) = 0;
|
||||
virtual void DisablePatch(std::size_t index) = 0;
|
||||
virtual void UnsetPatch(const Core::CPUThreadGuard& guard, u32 address) = 0;
|
||||
virtual void EnablePatch(const Core::CPUThreadGuard& guard, std::size_t index) = 0;
|
||||
virtual void DisablePatch(const Core::CPUThreadGuard& guard, std::size_t index) = 0;
|
||||
virtual bool HasEnabledPatch(u32 address) const = 0;
|
||||
virtual void RemovePatch(std::size_t index) = 0;
|
||||
virtual void ClearPatches() = 0;
|
||||
virtual void ApplyExistingPatch(std::size_t index) = 0;
|
||||
virtual void RemovePatch(const Core::CPUThreadGuard& guard, std::size_t index) = 0;
|
||||
virtual void ClearPatches(const Core::CPUThreadGuard& guard) = 0;
|
||||
virtual void ApplyExistingPatch(const Core::CPUThreadGuard& guard, std::size_t index) = 0;
|
||||
|
||||
// Threads
|
||||
virtual Debug::Threads GetThreads() const = 0;
|
||||
virtual Debug::Threads GetThreads(const Core::CPUThreadGuard& guard) const = 0;
|
||||
|
||||
virtual std::string Disassemble(u32 /*address*/) const { return "NODEBUGGER"; }
|
||||
virtual std::string GetRawMemoryString(int /*memory*/, u32 /*address*/) const
|
||||
virtual std::string Disassemble(const Core::CPUThreadGuard* /*guard*/, u32 /*address*/) const
|
||||
{
|
||||
return "NODEBUGGER";
|
||||
}
|
||||
virtual std::string GetRawMemoryString(const Core::CPUThreadGuard& /*guard*/, int /*memory*/,
|
||||
u32 /*address*/) const
|
||||
{
|
||||
return "NODEBUGGER";
|
||||
}
|
||||
@@ -72,10 +82,20 @@ public:
|
||||
virtual void ClearAllMemChecks() {}
|
||||
virtual bool IsMemCheck(u32 /*address*/, size_t /*size*/) const { return false; }
|
||||
virtual void ToggleMemCheck(u32 /*address*/, bool /*read*/, bool /*write*/, bool /*log*/) {}
|
||||
virtual u32 ReadMemory(u32 /*address*/) const { return 0; }
|
||||
virtual void WriteExtraMemory(int /*memory*/, u32 /*value*/, u32 /*address*/) {}
|
||||
virtual u32 ReadExtraMemory(int /*memory*/, u32 /*address*/) const { return 0; }
|
||||
virtual u32 ReadInstruction(u32 /*address*/) const { return 0; }
|
||||
virtual u32 ReadMemory(const Core::CPUThreadGuard& /*guard*/, u32 /*address*/) const { return 0; }
|
||||
virtual void WriteExtraMemory(const Core::CPUThreadGuard& /*guard*/, int /*memory*/,
|
||||
u32 /*value*/, u32 /*address*/)
|
||||
{
|
||||
}
|
||||
virtual u32 ReadExtraMemory(const Core::CPUThreadGuard& /*guard*/, int /*memory*/,
|
||||
u32 /*address*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual u32 ReadInstruction(const Core::CPUThreadGuard& /*guard*/, u32 /*address*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual std::optional<u32>
|
||||
GetMemoryAddressFromInstruction(const std::string& /*instruction*/) const
|
||||
{
|
||||
@@ -85,8 +105,11 @@ public:
|
||||
virtual void SetPC(u32 /*address*/) {}
|
||||
virtual void Step() {}
|
||||
virtual void RunToBreakpoint() {}
|
||||
virtual u32 GetColor(u32 /*address*/) const { return 0xFFFFFFFF; }
|
||||
virtual u32 GetColor(const Core::CPUThreadGuard* /*guard*/, u32 /*address*/) const
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
virtual std::string GetDescription(u32 /*address*/) const = 0;
|
||||
virtual void Clear() = 0;
|
||||
virtual void Clear(const Core::CPUThreadGuard& guard) = 0;
|
||||
};
|
||||
} // namespace Common
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
}
|
||||
|
||||
namespace Common
|
||||
{
|
||||
struct SCall
|
||||
@@ -68,7 +73,7 @@ public:
|
||||
virtual ~SymbolDB();
|
||||
|
||||
virtual Symbol* GetSymbolFromAddr(u32 addr) { return nullptr; }
|
||||
virtual Symbol* AddFunction(u32 start_addr) { return nullptr; }
|
||||
virtual Symbol* AddFunction(const Core::CPUThreadGuard& guard, u32 start_addr) { return nullptr; }
|
||||
void AddCompleteSymbol(const Symbol& symbol);
|
||||
|
||||
Symbol* GetSymbolFromName(std::string_view name);
|
||||
|
||||
@@ -358,7 +358,8 @@ bool IsSelfLogging()
|
||||
|
||||
// ----------------------
|
||||
// Code Functions
|
||||
static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
||||
static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARAddr& addr,
|
||||
const u32 data)
|
||||
{
|
||||
const u32 new_addr = addr.GCAddress();
|
||||
|
||||
@@ -374,7 +375,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
||||
const u32 repeat = data >> 8;
|
||||
for (u32 i = 0; i <= repeat; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U8(data & 0xFF, new_addr + i);
|
||||
PowerPC::HostWrite_U8(guard, data & 0xFF, new_addr + i);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", data & 0xFF, new_addr + i);
|
||||
}
|
||||
LogInfo("--------");
|
||||
@@ -388,7 +389,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
||||
const u32 repeat = data >> 16;
|
||||
for (u32 i = 0; i <= repeat; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U16(data & 0xFFFF, new_addr + i * 2);
|
||||
PowerPC::HostWrite_U16(guard, data & 0xFFFF, new_addr + i * 2);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", data & 0xFFFF, new_addr + i * 2);
|
||||
}
|
||||
LogInfo("--------");
|
||||
@@ -399,7 +400,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
||||
case DATATYPE_32BIT: // Dword write
|
||||
LogInfo("32-bit Write");
|
||||
LogInfo("--------");
|
||||
PowerPC::HostWrite_U32(data, new_addr);
|
||||
PowerPC::HostWrite_U32(guard, data, new_addr);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", data, new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
@@ -415,10 +416,11 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
||||
static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAddr& addr,
|
||||
const u32 data)
|
||||
{
|
||||
const u32 new_addr = addr.GCAddress();
|
||||
const u32 ptr = PowerPC::HostRead_U32(new_addr);
|
||||
const u32 ptr = PowerPC::HostRead_U32(guard, new_addr);
|
||||
|
||||
LogInfo("Hardware Address: {:08x}", new_addr);
|
||||
LogInfo("Size: {:08x}", addr.size);
|
||||
@@ -434,7 +436,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
||||
LogInfo("Pointer: {:08x}", ptr);
|
||||
LogInfo("Byte: {:08x}", thebyte);
|
||||
LogInfo("Offset: {:08x}", offset);
|
||||
PowerPC::HostWrite_U8(thebyte, ptr + offset);
|
||||
PowerPC::HostWrite_U8(guard, thebyte, ptr + offset);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", thebyte, ptr + offset);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
@@ -449,7 +451,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
||||
LogInfo("Pointer: {:08x}", ptr);
|
||||
LogInfo("Byte: {:08x}", theshort);
|
||||
LogInfo("Offset: {:08x}", offset);
|
||||
PowerPC::HostWrite_U16(theshort, ptr + offset);
|
||||
PowerPC::HostWrite_U16(guard, theshort, ptr + offset);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", theshort, ptr + offset);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
@@ -459,7 +461,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
||||
case DATATYPE_32BIT:
|
||||
LogInfo("Write 32-bit to pointer");
|
||||
LogInfo("--------");
|
||||
PowerPC::HostWrite_U32(data, ptr);
|
||||
PowerPC::HostWrite_U32(guard, data, ptr);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", data, ptr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
@@ -474,7 +476,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Subtype_AddCode(const ARAddr& addr, const u32 data)
|
||||
static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& addr, const u32 data)
|
||||
{
|
||||
// Used to increment/decrement a value in memory
|
||||
const u32 new_addr = addr.GCAddress();
|
||||
@@ -487,24 +489,24 @@ static bool Subtype_AddCode(const ARAddr& addr, const u32 data)
|
||||
case DATATYPE_8BIT:
|
||||
LogInfo("8-bit Add");
|
||||
LogInfo("--------");
|
||||
PowerPC::HostWrite_U8(PowerPC::HostRead_U8(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote {:02x} to address {:08x}", PowerPC::HostRead_U8(new_addr), new_addr);
|
||||
PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, new_addr) + data, new_addr);
|
||||
LogInfo("Wrote {:02x} to address {:08x}", PowerPC::HostRead_U8(guard, new_addr), new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
||||
case DATATYPE_16BIT:
|
||||
LogInfo("16-bit Add");
|
||||
LogInfo("--------");
|
||||
PowerPC::HostWrite_U16(PowerPC::HostRead_U16(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote {:04x} to address {:08x}", PowerPC::HostRead_U16(new_addr), new_addr);
|
||||
PowerPC::HostWrite_U16(guard, PowerPC::HostRead_U16(guard, new_addr) + data, new_addr);
|
||||
LogInfo("Wrote {:04x} to address {:08x}", PowerPC::HostRead_U16(guard, new_addr), new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
||||
case DATATYPE_32BIT:
|
||||
LogInfo("32-bit Add");
|
||||
LogInfo("--------");
|
||||
PowerPC::HostWrite_U32(PowerPC::HostRead_U32(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U32(new_addr), new_addr);
|
||||
PowerPC::HostWrite_U32(guard, PowerPC::HostRead_U32(guard, new_addr) + data, new_addr);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U32(guard, new_addr), new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
||||
@@ -513,12 +515,12 @@ static bool Subtype_AddCode(const ARAddr& addr, const u32 data)
|
||||
LogInfo("32-bit floating Add");
|
||||
LogInfo("--------");
|
||||
|
||||
const u32 read = PowerPC::HostRead_U32(new_addr);
|
||||
const u32 read = PowerPC::HostRead_U32(guard, new_addr);
|
||||
const float read_float = Common::BitCast<float>(read);
|
||||
// data contains an (unsigned?) integer value
|
||||
const float fread = read_float + static_cast<float>(data);
|
||||
const u32 newval = Common::BitCast<u32>(fread);
|
||||
PowerPC::HostWrite_U32(newval, new_addr);
|
||||
PowerPC::HostWrite_U32(guard, newval, new_addr);
|
||||
LogInfo("Old Value {:08x}", read);
|
||||
LogInfo("Increment {:08x}", data);
|
||||
LogInfo("New value {:08x}", newval);
|
||||
@@ -550,7 +552,8 @@ static bool Subtype_MasterCodeAndWriteToCCXXXXXX(const ARAddr& addr, const u32 d
|
||||
}
|
||||
|
||||
// This needs more testing
|
||||
static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const u32 data)
|
||||
static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 val_last,
|
||||
const ARAddr& addr, const u32 data)
|
||||
{
|
||||
const u32 new_addr = ARAddr(val_last).GCAddress();
|
||||
const u8 size = ARAddr(val_last).size;
|
||||
@@ -575,7 +578,7 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
||||
LogInfo("--------");
|
||||
for (int i = 0; i < write_num; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U8(val & 0xFF, curr_addr);
|
||||
PowerPC::HostWrite_U8(guard, val & 0xFF, curr_addr);
|
||||
curr_addr += addr_incr;
|
||||
val += val_incr;
|
||||
LogInfo("Write {:08x} to address {:08x}", val & 0xFF, curr_addr);
|
||||
@@ -591,7 +594,7 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
||||
LogInfo("--------");
|
||||
for (int i = 0; i < write_num; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U16(val & 0xFFFF, curr_addr);
|
||||
PowerPC::HostWrite_U16(guard, val & 0xFFFF, curr_addr);
|
||||
LogInfo("Write {:08x} to address {:08x}", val & 0xFFFF, curr_addr);
|
||||
curr_addr += addr_incr * 2;
|
||||
val += val_incr;
|
||||
@@ -606,7 +609,7 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
||||
LogInfo("--------");
|
||||
for (int i = 0; i < write_num; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U32(val, curr_addr);
|
||||
PowerPC::HostWrite_U32(guard, val, curr_addr);
|
||||
LogInfo("Write {:08x} to address {:08x}", val, curr_addr);
|
||||
curr_addr += addr_incr * 4;
|
||||
val += val_incr;
|
||||
@@ -629,7 +632,8 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
||||
// kenobi's "memory copy" Z-code. Requires an additional master code
|
||||
// on a real AR device. Documented here:
|
||||
// https://github.com/dolphin-emu/dolphin/wiki/GameCube-Action-Replay-Code-Types#type-z4-size-3--memory-copy
|
||||
static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u32 data)
|
||||
static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val_last,
|
||||
const ARAddr& addr, const u32 data)
|
||||
{
|
||||
const u32 addr_dest = val_last & ~0x06000000;
|
||||
const u32 addr_src = addr.GCAddress();
|
||||
@@ -646,14 +650,15 @@ static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u3
|
||||
{ // Memory Copy With Pointers Support
|
||||
LogInfo("Memory Copy With Pointers Support");
|
||||
LogInfo("--------");
|
||||
const u32 ptr_dest = PowerPC::HostRead_U32(addr_dest);
|
||||
const u32 ptr_dest = PowerPC::HostRead_U32(guard, addr_dest);
|
||||
LogInfo("Resolved Dest Address to: {:08x}", ptr_dest);
|
||||
const u32 ptr_src = PowerPC::HostRead_U32(addr_src);
|
||||
const u32 ptr_src = PowerPC::HostRead_U32(guard, addr_src);
|
||||
LogInfo("Resolved Src Address to: {:08x}", ptr_src);
|
||||
for (int i = 0; i < num_bytes; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U8(PowerPC::HostRead_U8(ptr_src + i), ptr_dest + i);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(ptr_src + i), ptr_dest + i);
|
||||
PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, ptr_src + i), ptr_dest + i);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(guard, ptr_src + i),
|
||||
ptr_dest + i);
|
||||
}
|
||||
LogInfo("--------");
|
||||
}
|
||||
@@ -663,8 +668,8 @@ static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u3
|
||||
LogInfo("--------");
|
||||
for (int i = 0; i < num_bytes; ++i)
|
||||
{
|
||||
PowerPC::HostWrite_U8(PowerPC::HostRead_U8(addr_src + i), addr_dest + i);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(addr_src + i),
|
||||
PowerPC::HostWrite_U8(guard, PowerPC::HostRead_U8(guard, addr_src + i), addr_dest + i);
|
||||
LogInfo("Wrote {:08x} to address {:08x}", PowerPC::HostRead_U8(guard, addr_src + i),
|
||||
addr_dest + i);
|
||||
}
|
||||
LogInfo("--------");
|
||||
@@ -681,25 +686,25 @@ static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u3
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NormalCode(const ARAddr& addr, const u32 data)
|
||||
static bool NormalCode(const Core::CPUThreadGuard& guard, const ARAddr& addr, const u32 data)
|
||||
{
|
||||
switch (addr.subtype)
|
||||
{
|
||||
case SUB_RAM_WRITE: // Ram write (and fill)
|
||||
LogInfo("Doing Ram Write And Fill");
|
||||
if (!Subtype_RamWriteAndFill(addr, data))
|
||||
if (!Subtype_RamWriteAndFill(guard, addr, data))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SUB_WRITE_POINTER: // Write to pointer
|
||||
LogInfo("Doing Write To Pointer");
|
||||
if (!Subtype_WriteToPointer(addr, data))
|
||||
if (!Subtype_WriteToPointer(guard, addr, data))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SUB_ADD_CODE: // Increment Value
|
||||
LogInfo("Doing Add Code");
|
||||
if (!Subtype_AddCode(addr, data))
|
||||
if (!Subtype_AddCode(guard, addr, data))
|
||||
return false;
|
||||
break;
|
||||
|
||||
@@ -759,7 +764,8 @@ static bool CompareValues(const u32 val1, const u32 val2, const int type)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkipCount)
|
||||
static bool ConditionalCode(const Core::CPUThreadGuard& guard, const ARAddr& addr, const u32 data,
|
||||
int* const pSkipCount)
|
||||
{
|
||||
const u32 new_addr = addr.GCAddress();
|
||||
|
||||
@@ -771,16 +777,16 @@ static bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkip
|
||||
switch (addr.size)
|
||||
{
|
||||
case DATATYPE_8BIT:
|
||||
result = CompareValues(PowerPC::HostRead_U8(new_addr), (data & 0xFF), addr.type);
|
||||
result = CompareValues(PowerPC::HostRead_U8(guard, new_addr), (data & 0xFF), addr.type);
|
||||
break;
|
||||
|
||||
case DATATYPE_16BIT:
|
||||
result = CompareValues(PowerPC::HostRead_U16(new_addr), (data & 0xFFFF), addr.type);
|
||||
result = CompareValues(PowerPC::HostRead_U16(guard, new_addr), (data & 0xFFFF), addr.type);
|
||||
break;
|
||||
|
||||
case DATATYPE_32BIT_FLOAT:
|
||||
case DATATYPE_32BIT:
|
||||
result = CompareValues(PowerPC::HostRead_U32(new_addr), data, addr.type);
|
||||
result = CompareValues(PowerPC::HostRead_U32(guard, new_addr), data, addr.type);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -819,7 +825,7 @@ static bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkip
|
||||
}
|
||||
|
||||
// NOTE: Lock needed to give mutual exclusion to s_current_code and LogInfo
|
||||
static bool RunCodeLocked(const ARCode& arcode)
|
||||
static bool RunCodeLocked(const Core::CPUThreadGuard& guard, const ARCode& arcode)
|
||||
{
|
||||
// The mechanism is different than what the real AR uses, so there may be compatibility problems.
|
||||
|
||||
@@ -873,7 +879,7 @@ static bool RunCodeLocked(const ARCode& arcode)
|
||||
{
|
||||
do_fill_and_slide = false;
|
||||
LogInfo("Doing Fill And Slide");
|
||||
if (false == ZeroCode_FillAndSlide(val_last, addr, data))
|
||||
if (false == ZeroCode_FillAndSlide(guard, val_last, addr, data))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
@@ -883,7 +889,7 @@ static bool RunCodeLocked(const ARCode& arcode)
|
||||
{
|
||||
do_memory_copy = false;
|
||||
LogInfo("Doing Memory Copy");
|
||||
if (false == ZeroCode_MemoryCopy(val_last, addr, data))
|
||||
if (false == ZeroCode_MemoryCopy(guard, val_last, addr, data))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
@@ -962,13 +968,13 @@ static bool RunCodeLocked(const ARCode& arcode)
|
||||
switch (addr.type)
|
||||
{
|
||||
case 0x00:
|
||||
if (false == NormalCode(addr, data))
|
||||
if (false == NormalCode(guard, addr, data))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
LogInfo("This Normal Code is a Conditional Code");
|
||||
if (false == ConditionalCode(addr, data, &skip_count))
|
||||
if (false == ConditionalCode(guard, addr, data, &skip_count))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -977,7 +983,7 @@ static bool RunCodeLocked(const ARCode& arcode)
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunAllActive()
|
||||
void RunAllActive(const Core::CPUThreadGuard& cpu_guard)
|
||||
{
|
||||
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
|
||||
return;
|
||||
@@ -987,8 +993,8 @@ void RunAllActive()
|
||||
// be contested.
|
||||
std::lock_guard guard(s_lock);
|
||||
s_active_codes.erase(std::remove_if(s_active_codes.begin(), s_active_codes.end(),
|
||||
[](const ARCode& code) {
|
||||
bool success = RunCodeLocked(code);
|
||||
[&cpu_guard](const ARCode& code) {
|
||||
bool success = RunCodeLocked(cpu_guard, code);
|
||||
LogInfo("\n");
|
||||
return !success;
|
||||
}),
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
|
||||
class IniFile;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
};
|
||||
|
||||
namespace ActionReplay
|
||||
{
|
||||
struct AREntry
|
||||
@@ -35,7 +40,7 @@ struct ARCode
|
||||
bool user_defined = false;
|
||||
};
|
||||
|
||||
void RunAllActive();
|
||||
void RunAllActive(const Core::CPUThreadGuard& cpu_guard);
|
||||
|
||||
void ApplyCodes(std::span<const ARCode> codes);
|
||||
void SetSyncedCodesAsActive();
|
||||
|
||||
@@ -375,11 +375,11 @@ bool CBoot::FindMapFile(std::string* existing_map_file, std::string* writable_ma
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBoot::LoadMapFromFilename()
|
||||
bool CBoot::LoadMapFromFilename(const Core::CPUThreadGuard& guard)
|
||||
{
|
||||
std::string strMapFilename;
|
||||
bool found = FindMapFile(&strMapFilename, nullptr);
|
||||
if (found && g_symbolDB.LoadMap(strMapFilename))
|
||||
if (found && g_symbolDB.LoadMap(guard, strMapFilename))
|
||||
{
|
||||
UpdateDebugger_MapLoaded();
|
||||
return true;
|
||||
@@ -486,7 +486,8 @@ static void CopyDefaultExceptionHandlers(Core::System& system)
|
||||
}
|
||||
|
||||
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp
|
||||
bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||
std::unique_ptr<BootParameters> boot)
|
||||
{
|
||||
SConfig& config = SConfig::GetInstance();
|
||||
|
||||
@@ -502,8 +503,10 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
|
||||
struct BootTitle
|
||||
{
|
||||
BootTitle(Core::System& system_, const std::vector<DiscIO::Riivolution::Patch>& patches)
|
||||
: system(system_), config(SConfig::GetInstance()), riivolution_patches(patches)
|
||||
BootTitle(Core::System& system_, const Core::CPUThreadGuard& guard_,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& patches)
|
||||
: system(system_), guard(guard_), config(SConfig::GetInstance()),
|
||||
riivolution_patches(patches)
|
||||
{
|
||||
}
|
||||
bool operator()(BootParameters::Disc& disc) const
|
||||
@@ -515,10 +518,10 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
if (!volume)
|
||||
return false;
|
||||
|
||||
if (!EmulatedBS2(system, config.bWii, *volume, riivolution_patches))
|
||||
if (!EmulatedBS2(system, guard, config.bWii, *volume, riivolution_patches))
|
||||
return false;
|
||||
|
||||
SConfig::OnNewTitleLoad();
|
||||
SConfig::OnNewTitleLoad(guard);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -551,7 +554,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupGCMemory(system);
|
||||
SetupGCMemory(system, guard);
|
||||
}
|
||||
|
||||
if (!executable.reader->LoadIntoMemory())
|
||||
@@ -560,11 +563,11 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
return false;
|
||||
}
|
||||
|
||||
SConfig::OnNewTitleLoad();
|
||||
SConfig::OnNewTitleLoad(guard);
|
||||
|
||||
ppc_state.pc = executable.reader->GetEntryPoint();
|
||||
|
||||
if (executable.reader->LoadSymbols())
|
||||
if (executable.reader->LoadSymbols(guard))
|
||||
{
|
||||
UpdateDebugger_MapLoaded();
|
||||
HLE::PatchFunctions(system);
|
||||
@@ -578,7 +581,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
if (!Boot_WiiWAD(system, wad))
|
||||
return false;
|
||||
|
||||
SConfig::OnNewTitleLoad();
|
||||
SConfig::OnNewTitleLoad(guard);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -588,7 +591,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
if (!BootNANDTitle(system, nand_title.id))
|
||||
return false;
|
||||
|
||||
SConfig::OnNewTitleLoad();
|
||||
SConfig::OnNewTitleLoad(guard);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -613,7 +616,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
SetDisc(DiscIO::CreateDisc(ipl.disc->path), ipl.disc->auto_disc_change_paths);
|
||||
}
|
||||
|
||||
SConfig::OnNewTitleLoad();
|
||||
SConfig::OnNewTitleLoad(guard);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -625,14 +628,15 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
const Core::CPUThreadGuard& guard;
|
||||
const SConfig& config;
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches;
|
||||
};
|
||||
|
||||
if (!std::visit(BootTitle(system, boot->riivolution_patches), boot->parameters))
|
||||
if (!std::visit(BootTitle(system, guard, boot->riivolution_patches), boot->parameters))
|
||||
return false;
|
||||
|
||||
DiscIO::Riivolution::ApplyGeneralMemoryPatches(boot->riivolution_patches);
|
||||
DiscIO::Riivolution::ApplyGeneralMemoryPatches(guard, boot->riivolution_patches);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
class System;
|
||||
}
|
||||
} // namespace Core
|
||||
|
||||
namespace File
|
||||
{
|
||||
@@ -153,7 +154,8 @@ struct BootParameters
|
||||
class CBoot
|
||||
{
|
||||
public:
|
||||
static bool BootUp(Core::System& system, std::unique_ptr<BootParameters> boot);
|
||||
static bool BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||
std::unique_ptr<BootParameters> boot);
|
||||
|
||||
// Tries to find a map file for the current game by looking first in the
|
||||
// local user directory, then in the shared user directory.
|
||||
@@ -166,7 +168,7 @@ public:
|
||||
//
|
||||
// Returns true if a map file exists, false if none could be found.
|
||||
static bool FindMapFile(std::string* existing_map_file, std::string* writable_map_file);
|
||||
static bool LoadMapFromFilename();
|
||||
static bool LoadMapFromFilename(const Core::CPUThreadGuard& guard);
|
||||
|
||||
private:
|
||||
static bool DVDRead(const DiscIO::VolumeDisc& disc, u64 dvd_offset, u32 output_address,
|
||||
@@ -182,17 +184,21 @@ private:
|
||||
static void SetupMSR(PowerPC::PowerPCState& ppc_state);
|
||||
static void SetupHID(PowerPC::PowerPCState& ppc_state, bool is_wii);
|
||||
static void SetupBAT(Core::System& system, bool is_wii);
|
||||
static bool RunApploader(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
static bool RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volume,
|
||||
static bool EmulatedBS2_GC(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volume,
|
||||
static bool EmulatedBS2_Wii(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool EmulatedBS2(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
static bool EmulatedBS2(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool Load_BS2(Core::System& system, const std::string& boot_rom_filename);
|
||||
|
||||
static void SetupGCMemory(Core::System& system);
|
||||
static void SetupGCMemory(Core::System& system, const Core::CPUThreadGuard& guard);
|
||||
static bool SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType console_type);
|
||||
};
|
||||
|
||||
@@ -208,7 +214,7 @@ public:
|
||||
virtual bool IsValid() const = 0;
|
||||
virtual bool IsWii() const = 0;
|
||||
virtual bool LoadIntoMemory(bool only_in_mem1 = false) const = 0;
|
||||
virtual bool LoadSymbols() const = 0;
|
||||
virtual bool LoadSymbols(const Core::CPUThreadGuard& guard) const = 0;
|
||||
|
||||
protected:
|
||||
std::vector<u8> m_bytes;
|
||||
|
||||
@@ -44,14 +44,14 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
void PresetTimeBaseTicks()
|
||||
void PresetTimeBaseTicks(const Core::CPUThreadGuard& guard)
|
||||
{
|
||||
const u64 emulated_time =
|
||||
ExpansionInterface::CEXIIPL::GetEmulatedTime(ExpansionInterface::CEXIIPL::GC_EPOCH);
|
||||
|
||||
const u64 time_base_ticks = emulated_time * 40500000ULL;
|
||||
|
||||
PowerPC::HostWrite_U64(time_base_ticks, 0x800030D8);
|
||||
PowerPC::HostWrite_U64(guard, time_base_ticks, 0x800030D8);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
@@ -131,7 +131,8 @@ void CBoot::SetupBAT(Core::System& system, bool is_wii)
|
||||
PowerPC::IBATUpdated();
|
||||
}
|
||||
|
||||
bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
const DiscIO::Partition partition = volume.GetGamePartition();
|
||||
@@ -166,8 +167,8 @@ bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::Volume
|
||||
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderInit");
|
||||
PowerPC::HostWrite_U32(0x4E800020, 0x81300000); // Write BLR
|
||||
HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
|
||||
PowerPC::HostWrite_U32(guard, 0x4E800020, 0x81300000); // Write BLR
|
||||
HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
|
||||
ppc_state.gpr[3] = 0x81300000;
|
||||
RunFunction(system, iAppLoaderInit);
|
||||
|
||||
@@ -196,7 +197,8 @@ bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::Volume
|
||||
ram_address, length);
|
||||
DVDRead(volume, dvd_offset, ram_address, length, partition);
|
||||
|
||||
DiscIO::Riivolution::ApplyApploaderMemoryPatches(riivolution_patches, ram_address, length);
|
||||
DiscIO::Riivolution::ApplyApploaderMemoryPatches(guard, riivolution_patches, ram_address,
|
||||
length);
|
||||
|
||||
ppc_state.gpr[3] = 0x81300004;
|
||||
ppc_state.gpr[4] = 0x81300008;
|
||||
@@ -216,36 +218,37 @@ bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::Volume
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBoot::SetupGCMemory(Core::System& system)
|
||||
void CBoot::SetupGCMemory(Core::System& system, const Core::CPUThreadGuard& guard)
|
||||
{
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
// Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020);
|
||||
PowerPC::HostWrite_U32(guard, 0x0D15EA5E, 0x80000020);
|
||||
|
||||
// Physical Memory Size (24MB on retail)
|
||||
PowerPC::HostWrite_U32(memory.GetRamSizeReal(), 0x80000028);
|
||||
PowerPC::HostWrite_U32(guard, memory.GetRamSizeReal(), 0x80000028);
|
||||
|
||||
// Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
|
||||
// TODO: determine why some games fail when using a retail ID.
|
||||
// (Seem to take different EXI paths, see Ikaruga for example)
|
||||
const u32 console_type = static_cast<u32>(Core::ConsoleType::LatestDevkit);
|
||||
PowerPC::HostWrite_U32(console_type, 0x8000002C);
|
||||
PowerPC::HostWrite_U32(guard, console_type, 0x8000002C);
|
||||
|
||||
// Fake the VI Init of the IPL (YAGCD 4.2.1.4)
|
||||
PowerPC::HostWrite_U32(DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, 0x800000CC);
|
||||
PowerPC::HostWrite_U32(guard, DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1,
|
||||
0x800000CC);
|
||||
|
||||
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external
|
||||
// (retail consoles have no external ARAM)
|
||||
// ARAM Size. 16MB main + 4/16/32MB external. (retail consoles have no external ARAM)
|
||||
PowerPC::HostWrite_U32(guard, 0x01000000, 0x800000d0);
|
||||
|
||||
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
PowerPC::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DSI Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI Handler: rfi
|
||||
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
PresetTimeBaseTicks();
|
||||
PresetTimeBaseTicks(guard);
|
||||
|
||||
// HIO checks this
|
||||
// PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||
@@ -255,7 +258,8 @@ void CBoot::SetupGCMemory(Core::System& system)
|
||||
// GameCube Bootstrap 2 HLE:
|
||||
// copy the apploader to 0x81200000
|
||||
// execute the apploader, function by function, using the above utility.
|
||||
bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volume,
|
||||
bool CBoot::EmulatedBS2_GC(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
INFO_LOG_FMT(BOOT, "Faking GC BS2...");
|
||||
@@ -266,7 +270,7 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volum
|
||||
SetupHID(ppc_state, /*is_wii*/ false);
|
||||
SetupBAT(system, /*is_wii*/ false);
|
||||
|
||||
SetupGCMemory(system);
|
||||
SetupGCMemory(system, guard);
|
||||
|
||||
// Datel titles don't initialize the postMatrices, but they have dual-texture coordinate
|
||||
// transformation enabled. We initialize all of xfmem to 0, which results in everything using
|
||||
@@ -309,7 +313,7 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volum
|
||||
// Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
|
||||
ppc_state.gpr[13] = ntsc ? 0x81465320 : 0x814b4fc0;
|
||||
|
||||
return RunApploader(system, /*is_wii*/ false, volume, riivolution_patches);
|
||||
return RunApploader(system, guard, /*is_wii*/ false, volume, riivolution_patches);
|
||||
}
|
||||
|
||||
static DiscIO::Region CodeRegion(char c)
|
||||
@@ -507,7 +511,8 @@ static void WriteEmptyPlayRecord()
|
||||
// Wii Bootstrap 2 HLE:
|
||||
// copy the apploader to 0x81200000
|
||||
// execute the apploader
|
||||
bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volume,
|
||||
bool CBoot::EmulatedBS2_Wii(Core::System& system, const Core::CPUThreadGuard& guard,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
INFO_LOG_FMT(BOOT, "Faking Wii BS2...");
|
||||
@@ -578,7 +583,7 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volu
|
||||
|
||||
ppc_state.gpr[1] = 0x816ffff0; // StackPointer
|
||||
|
||||
if (!RunApploader(system, /*is_wii*/ true, volume, riivolution_patches))
|
||||
if (!RunApploader(system, guard, /*is_wii*/ true, volume, riivolution_patches))
|
||||
return false;
|
||||
|
||||
// The Apploader probably just overwrote values needed for RAM Override. Run this again!
|
||||
@@ -593,9 +598,10 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volu
|
||||
|
||||
// Returns true if apploader has run successfully. If is_wii is true, the disc
|
||||
// that volume refers to must currently be inserted into the emulated disc drive.
|
||||
bool CBoot::EmulatedBS2(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
bool CBoot::EmulatedBS2(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
|
||||
const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
return is_wii ? EmulatedBS2_Wii(system, volume, riivolution_patches) :
|
||||
EmulatedBS2_GC(system, volume, riivolution_patches);
|
||||
return is_wii ? EmulatedBS2_Wii(system, guard, volume, riivolution_patches) :
|
||||
EmulatedBS2_GC(system, guard, volume, riivolution_patches);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
bool IsAncast() const { return m_is_ancast; };
|
||||
u32 GetEntryPoint() const override { return m_dolheader.entryPoint; }
|
||||
bool LoadIntoMemory(bool only_in_mem1 = false) const override;
|
||||
bool LoadSymbols() const override { return false; }
|
||||
bool LoadSymbols(const Core::CPUThreadGuard& guard) const override { return false; }
|
||||
|
||||
private:
|
||||
enum
|
||||
|
||||
@@ -181,7 +181,7 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ElfReader::LoadSymbols() const
|
||||
bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard) const
|
||||
{
|
||||
bool hasSymbols = false;
|
||||
SectionID sec = GetSectionByName(".symtab");
|
||||
@@ -219,7 +219,7 @@ bool ElfReader::LoadSymbols() const
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
g_symbolDB.AddKnownSymbol(value, size, name, symtype);
|
||||
g_symbolDB.AddKnownSymbol(guard, value, size, name, symtype);
|
||||
hasSymbols = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
u32 GetEntryPoint() const override { return entryPoint; }
|
||||
u32 GetFlags() const { return (u32)(header->e_flags); }
|
||||
bool LoadIntoMemory(bool only_in_mem1 = false) const override;
|
||||
bool LoadSymbols() const override;
|
||||
bool LoadSymbols(const Core::CPUThreadGuard& guard) const override;
|
||||
// TODO: actually check for validity.
|
||||
bool IsValid() const override { return true; }
|
||||
bool IsWii() const override;
|
||||
|
||||
@@ -103,41 +103,47 @@ namespace
|
||||
{
|
||||
template <typename T>
|
||||
static std::optional<PowerPC::ReadResult<T>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space);
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space);
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<u8>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
return PowerPC::HostTryReadU8(addr, space);
|
||||
return PowerPC::HostTryReadU8(guard, addr, space);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<u16>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
return PowerPC::HostTryReadU16(addr, space);
|
||||
return PowerPC::HostTryReadU16(guard, addr, space);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<u32>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
return PowerPC::HostTryReadU32(addr, space);
|
||||
return PowerPC::HostTryReadU32(guard, addr, space);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<u64>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
return PowerPC::HostTryReadU64(addr, space);
|
||||
return PowerPC::HostTryReadU64(guard, addr, space);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<s8>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
auto tmp = PowerPC::HostTryReadU8(addr, space);
|
||||
auto tmp = PowerPC::HostTryReadU8(guard, addr, space);
|
||||
if (!tmp)
|
||||
return std::nullopt;
|
||||
return PowerPC::ReadResult<s8>(tmp->translated, Common::BitCast<s8>(tmp->value));
|
||||
@@ -145,9 +151,10 @@ TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<s16>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
auto tmp = PowerPC::HostTryReadU16(addr, space);
|
||||
auto tmp = PowerPC::HostTryReadU16(guard, addr, space);
|
||||
if (!tmp)
|
||||
return std::nullopt;
|
||||
return PowerPC::ReadResult<s16>(tmp->translated, Common::BitCast<s16>(tmp->value));
|
||||
@@ -155,9 +162,10 @@ TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<s32>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
auto tmp = PowerPC::HostTryReadU32(addr, space);
|
||||
auto tmp = PowerPC::HostTryReadU32(guard, addr, space);
|
||||
if (!tmp)
|
||||
return std::nullopt;
|
||||
return PowerPC::ReadResult<s32>(tmp->translated, Common::BitCast<s32>(tmp->value));
|
||||
@@ -165,9 +173,10 @@ TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<s64>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
auto tmp = PowerPC::HostTryReadU64(addr, space);
|
||||
auto tmp = PowerPC::HostTryReadU64(guard, addr, space);
|
||||
if (!tmp)
|
||||
return std::nullopt;
|
||||
return PowerPC::ReadResult<s64>(tmp->translated, Common::BitCast<s64>(tmp->value));
|
||||
@@ -175,22 +184,25 @@ TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<float>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
return PowerPC::HostTryReadF32(addr, space);
|
||||
return PowerPC::HostTryReadF32(guard, addr, space);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::optional<PowerPC::ReadResult<double>>
|
||||
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
|
||||
TryReadValueFromEmulatedMemory(const Core::CPUThreadGuard& guard, u32 addr,
|
||||
PowerPC::RequestedAddressSpace space)
|
||||
{
|
||||
return PowerPC::HostTryReadF64(addr, space);
|
||||
return PowerPC::HostTryReadF64(guard, addr, space);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename T>
|
||||
Common::Result<Cheats::SearchErrorCode, std::vector<Cheats::SearchResult<T>>>
|
||||
Cheats::NewSearch(const std::vector<Cheats::MemoryRange>& memory_ranges,
|
||||
Cheats::NewSearch(const Core::CPUThreadGuard& guard,
|
||||
const std::vector<Cheats::MemoryRange>& memory_ranges,
|
||||
PowerPC::RequestedAddressSpace address_space, bool aligned,
|
||||
const std::function<bool(const T& value)>& validator)
|
||||
{
|
||||
@@ -229,7 +241,7 @@ Cheats::NewSearch(const std::vector<Cheats::MemoryRange>& memory_ranges,
|
||||
for (u64 i = 0; i < length; i += increment_per_loop)
|
||||
{
|
||||
const u32 addr = start_address + i;
|
||||
const auto current_value = TryReadValueFromEmulatedMemory<T>(addr, address_space);
|
||||
const auto current_value = TryReadValueFromEmulatedMemory<T>(guard, addr, address_space);
|
||||
if (!current_value)
|
||||
continue;
|
||||
|
||||
@@ -252,7 +264,8 @@ Cheats::NewSearch(const std::vector<Cheats::MemoryRange>& memory_ranges,
|
||||
|
||||
template <typename T>
|
||||
Common::Result<Cheats::SearchErrorCode, std::vector<Cheats::SearchResult<T>>>
|
||||
Cheats::NextSearch(const std::vector<Cheats::SearchResult<T>>& previous_results,
|
||||
Cheats::NextSearch(const Core::CPUThreadGuard& guard,
|
||||
const std::vector<Cheats::SearchResult<T>>& previous_results,
|
||||
PowerPC::RequestedAddressSpace address_space,
|
||||
const std::function<bool(const T& new_value, const T& old_value)>& validator)
|
||||
{
|
||||
@@ -277,7 +290,7 @@ Cheats::NextSearch(const std::vector<Cheats::SearchResult<T>>& previous_results,
|
||||
for (const auto& previous_result : previous_results)
|
||||
{
|
||||
const u32 addr = previous_result.m_address;
|
||||
const auto current_value = TryReadValueFromEmulatedMemory<T>(addr, address_space);
|
||||
const auto current_value = TryReadValueFromEmulatedMemory<T>(guard, addr, address_space);
|
||||
if (!current_value)
|
||||
{
|
||||
auto& r = results.emplace_back();
|
||||
@@ -429,7 +442,7 @@ MakeCompareFunctionForLastValue(Cheats::CompareType op)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Cheats::SearchErrorCode Cheats::CheatSearchSession<T>::RunSearch()
|
||||
Cheats::SearchErrorCode Cheats::CheatSearchSession<T>::RunSearch(const Core::CPUThreadGuard& guard)
|
||||
{
|
||||
Common::Result<SearchErrorCode, std::vector<SearchResult<T>>> result =
|
||||
Cheats::SearchErrorCode::InvalidParameters;
|
||||
@@ -442,12 +455,12 @@ Cheats::SearchErrorCode Cheats::CheatSearchSession<T>::RunSearch()
|
||||
if (m_first_search_done)
|
||||
{
|
||||
result = Cheats::NextSearch<T>(
|
||||
m_search_results, m_address_space,
|
||||
guard, m_search_results, m_address_space,
|
||||
[&func](const T& new_value, const T& old_value) { return func(new_value); });
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Cheats::NewSearch<T>(m_memory_ranges, m_address_space, m_aligned, func);
|
||||
result = Cheats::NewSearch<T>(guard, m_memory_ranges, m_address_space, m_aligned, func);
|
||||
}
|
||||
}
|
||||
else if (m_filter_type == FilterType::CompareAgainstLastValue)
|
||||
@@ -455,19 +468,19 @@ Cheats::SearchErrorCode Cheats::CheatSearchSession<T>::RunSearch()
|
||||
if (!m_first_search_done)
|
||||
return Cheats::SearchErrorCode::InvalidParameters;
|
||||
|
||||
result = Cheats::NextSearch<T>(m_search_results, m_address_space,
|
||||
result = Cheats::NextSearch<T>(guard, m_search_results, m_address_space,
|
||||
MakeCompareFunctionForLastValue<T>(m_compare_type));
|
||||
}
|
||||
else if (m_filter_type == FilterType::DoNotFilter)
|
||||
{
|
||||
if (m_first_search_done)
|
||||
{
|
||||
result = Cheats::NextSearch<T>(m_search_results, m_address_space,
|
||||
result = Cheats::NextSearch<T>(guard, m_search_results, m_address_space,
|
||||
[](const T& v1, const T& v2) { return true; });
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Cheats::NewSearch<T>(m_memory_ranges, m_address_space, m_aligned,
|
||||
result = Cheats::NewSearch<T>(guard, m_memory_ranges, m_address_space, m_aligned,
|
||||
[](const T& v) { return true; });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
#include "Common/Result.h"
|
||||
#include "Core/PowerPC/MMU.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
};
|
||||
|
||||
namespace Cheats
|
||||
{
|
||||
enum class CompareType
|
||||
@@ -108,7 +113,7 @@ std::vector<u8> GetValueAsByteVector(const SearchValue& value);
|
||||
// for which the given validator returns true.
|
||||
template <typename T>
|
||||
Common::Result<SearchErrorCode, std::vector<SearchResult<T>>>
|
||||
NewSearch(const std::vector<MemoryRange>& memory_ranges,
|
||||
NewSearch(const Core::CPUThreadGuard& guard, const std::vector<MemoryRange>& memory_ranges,
|
||||
PowerPC::RequestedAddressSpace address_space, bool aligned,
|
||||
const std::function<bool(const T& value)>& validator);
|
||||
|
||||
@@ -116,7 +121,7 @@ NewSearch(const std::vector<MemoryRange>& memory_ranges,
|
||||
// which the given validator returns true.
|
||||
template <typename T>
|
||||
Common::Result<SearchErrorCode, std::vector<SearchResult<T>>>
|
||||
NextSearch(const std::vector<SearchResult<T>>& previous_results,
|
||||
NextSearch(const Core::CPUThreadGuard& guard, const std::vector<SearchResult<T>>& previous_results,
|
||||
PowerPC::RequestedAddressSpace address_space,
|
||||
const std::function<bool(const T& new_value, const T& old_value)>& validator);
|
||||
|
||||
@@ -138,7 +143,7 @@ public:
|
||||
virtual void ResetResults() = 0;
|
||||
|
||||
// Run either a new search or a next search based on the current state of this session.
|
||||
virtual SearchErrorCode RunSearch() = 0;
|
||||
virtual SearchErrorCode RunSearch(const Core::CPUThreadGuard& guard) = 0;
|
||||
|
||||
virtual size_t GetMemoryRangeCount() const = 0;
|
||||
virtual MemoryRange GetMemoryRange(size_t index) const = 0;
|
||||
@@ -184,7 +189,7 @@ public:
|
||||
bool SetValueFromString(const std::string& value_as_string, bool force_parse_as_hex) override;
|
||||
|
||||
void ResetResults() override;
|
||||
SearchErrorCode RunSearch() override;
|
||||
SearchErrorCode RunSearch(const Core::CPUThreadGuard& guard) override;
|
||||
|
||||
size_t GetMemoryRangeCount() const override;
|
||||
MemoryRange GetMemoryRange(size_t index) const override;
|
||||
|
||||
@@ -191,7 +191,7 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri
|
||||
DolphinAnalytics::Instance().ReportGameStart();
|
||||
}
|
||||
|
||||
void SConfig::OnNewTitleLoad()
|
||||
void SConfig::OnNewTitleLoad(const Core::CPUThreadGuard& guard)
|
||||
{
|
||||
if (!Core::IsRunning())
|
||||
return;
|
||||
@@ -201,7 +201,7 @@ void SConfig::OnNewTitleLoad()
|
||||
g_symbolDB.Clear();
|
||||
Host_NotifyMapLoaded();
|
||||
}
|
||||
CBoot::LoadMapFromFilename();
|
||||
CBoot::LoadMapFromFilename(guard);
|
||||
auto& system = Core::System::GetInstance();
|
||||
HLE::Reload(system);
|
||||
PatchEngine::Reload();
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
class IniFile;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
}
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
enum class Language;
|
||||
@@ -68,7 +73,7 @@ struct SConfig
|
||||
void SetRunningGameMetadata(const std::string& game_id);
|
||||
// Reloads title-specific map files, patches, custom textures, etc.
|
||||
// This should only be called after the new title has been loaded into memory.
|
||||
static void OnNewTitleLoad();
|
||||
static void OnNewTitleLoad(const Core::CPUThreadGuard& guard);
|
||||
|
||||
void LoadDefaults();
|
||||
static std::string MakeGameID(std::string_view file_name);
|
||||
|
||||
@@ -166,7 +166,12 @@ void OnFrameEnd()
|
||||
{
|
||||
#ifdef USE_MEMORYWATCHER
|
||||
if (s_memory_watcher)
|
||||
s_memory_watcher->Step();
|
||||
{
|
||||
ASSERT(IsCPUThread());
|
||||
CPUThreadGuard guard;
|
||||
|
||||
s_memory_watcher->Step(guard);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -537,7 +542,9 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
||||
|
||||
PatchEngine::Shutdown();
|
||||
HLE::Clear();
|
||||
PowerPC::debug_interface.Clear();
|
||||
|
||||
CPUThreadGuard guard;
|
||||
PowerPC::debug_interface.Clear(guard);
|
||||
}};
|
||||
|
||||
VideoBackendBase::PopulateBackendInfo();
|
||||
@@ -587,8 +594,12 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
||||
if (SConfig::GetInstance().bWii)
|
||||
savegame_redirect = DiscIO::Riivolution::ExtractSavegameRedirect(boot->riivolution_patches);
|
||||
|
||||
if (!CBoot::BootUp(system, std::move(boot)))
|
||||
return;
|
||||
{
|
||||
ASSERT(IsCPUThread());
|
||||
CPUThreadGuard guard;
|
||||
if (!CBoot::BootUp(system, guard, std::move(boot)))
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialise Wii filesystem contents.
|
||||
// This is done here after Boot and not in BootManager to ensure that we operate
|
||||
@@ -1036,4 +1047,16 @@ void UpdateInputGate(bool require_focus, bool require_full_focus)
|
||||
ControlReference::SetInputGate(focus_passes && full_focus_passes);
|
||||
}
|
||||
|
||||
CPUThreadGuard::CPUThreadGuard() : m_was_cpu_thread(IsCPUThread())
|
||||
{
|
||||
if (!m_was_cpu_thread)
|
||||
m_was_unpaused = PauseAndLock(true, true);
|
||||
}
|
||||
|
||||
CPUThreadGuard::~CPUThreadGuard()
|
||||
{
|
||||
if (!m_was_cpu_thread)
|
||||
PauseAndLock(false, m_was_unpaused);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user