Merge pull request #11554 from JosJuice/host-lock-cpu

DolphinQt: Properly lock CPU before accessing emulated memory
This commit is contained in:
Scott Mansell
2023-02-13 16:08:36 +13:00
committed by GitHub
79 changed files with 1799 additions and 1187 deletions
+7 -8
View File
@@ -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;
+8 -2
View File
@@ -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;
+21 -20
View File
@@ -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();
+16 -11
View File
@@ -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;
+8 -3
View File
@@ -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>>;
+42 -19
View File
@@ -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
+6 -1
View File
@@ -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);
+51 -45
View File
@@ -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;
}),
+6 -1
View File
@@ -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();
+19 -15
View File
@@ -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;
}
+15 -9
View File
@@ -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;
+33 -27
View File
@@ -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);
}
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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;
}
}
+1 -1
View File
@@ -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;
+44 -31
View File
@@ -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; });
}
}
+9 -4
View File
@@ -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;
+2 -2
View File
@@ -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();
+6 -1
View File
@@ -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);
+27 -4
View File
@@ -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