mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #11554 from JosJuice/host-lock-cpu
DolphinQt: Properly lock CPU before accessing emulated memory
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