Merge pull request #11429 from AdmiralCurtiss/globals-ppc

Reduce usage of ppcState global.
This commit is contained in:
Pierre Bourdon
2023-01-27 19:06:30 +01:00
committed by GitHub
69 changed files with 1717 additions and 1427 deletions
+9 -3
View File
@@ -11,6 +11,7 @@
#include "Core/Debugger/PPCDebugInterface.h"
#include "Core/HW/CPU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace
{
@@ -56,11 +57,13 @@ void CodeTrace::SetRegTracked(const std::string& reg)
InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& instruction) const
{
auto& system = Core::System::GetInstance();
// Slower process of breaking down saved instruction. Only used when stepping through code if a
// decision has to be made, otherwise used afterwards on a log file.
InstructionAttributes tmp_attributes;
tmp_attributes.instruction = instruction.instruction;
tmp_attributes.address = PC;
tmp_attributes.address = system.GetPPCState().pc;
std::string instr = instruction.instruction;
std::smatch match;
@@ -106,11 +109,14 @@ InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& ins
TraceOutput CodeTrace::SaveCurrentInstruction() 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(PC);
const std::string instr = PowerPC::debug_interface.Disassemble(ppc_state.pc);
output.instruction = instr;
output.address = PC;
output.address = ppc_state.pc;
if (IsInstructionLoadStore(output.instruction))
output.memory_target = PowerPC::debug_interface.GetMemoryAddressFromInstruction(instr);
+22 -19
View File
@@ -458,22 +458,23 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename)
memory.CopyToEmu(0x01200000, data.data() + 0x100, 0x700);
memory.CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00);
PowerPC::ppcState.gpr[3] = 0xfff0001f;
PowerPC::ppcState.gpr[4] = 0x00002030;
PowerPC::ppcState.gpr[5] = 0x0000009c;
auto& ppc_state = system.GetPPCState();
ppc_state.gpr[3] = 0xfff0001f;
ppc_state.gpr[4] = 0x00002030;
ppc_state.gpr[5] = 0x0000009c;
MSR.FP = 1;
MSR.DR = 1;
MSR.IR = 1;
ppc_state.msr.FP = 1;
ppc_state.msr.DR = 1;
ppc_state.msr.IR = 1;
PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464;
PowerPC::ppcState.spr[SPR_IBAT3U] = 0xfff0001f;
PowerPC::ppcState.spr[SPR_IBAT3L] = 0xfff00001;
PowerPC::ppcState.spr[SPR_DBAT3U] = 0xfff0001f;
PowerPC::ppcState.spr[SPR_DBAT3L] = 0xfff00001;
SetupBAT(/*is_wii*/ false);
ppc_state.spr[SPR_HID0] = 0x0011c464;
ppc_state.spr[SPR_IBAT3U] = 0xfff0001f;
ppc_state.spr[SPR_IBAT3L] = 0xfff00001;
ppc_state.spr[SPR_DBAT3U] = 0xfff0001f;
ppc_state.spr[SPR_DBAT3L] = 0xfff00001;
SetupBAT(system, /*is_wii*/ false);
PC = 0x81200150;
ppc_state.pc = 0x81200150;
return true;
}
@@ -543,16 +544,18 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
SetDefaultDisc();
SetupMSR();
SetupHID(config.bWii);
SetupBAT(config.bWii);
auto& ppc_state = system.GetPPCState();
SetupMSR(ppc_state);
SetupHID(ppc_state, config.bWii);
SetupBAT(system, config.bWii);
CopyDefaultExceptionHandlers(system);
if (config.bWii)
{
// Set a value for the SP. It doesn't matter where this points to,
// as long as it is a valid location. This value is taken from a homebrew binary.
PowerPC::ppcState.gpr[1] = 0x8004d4bc;
ppc_state.gpr[1] = 0x8004d4bc;
// Because there is no TMD to get the requested system (IOS) version from,
// we default to IOS58, which is the version used by the Homebrew Channel.
@@ -572,12 +575,12 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
SConfig::OnNewTitleLoad();
PC = executable.reader->GetEntryPoint();
ppc_state.pc = executable.reader->GetEntryPoint();
if (executable.reader->LoadSymbols())
{
UpdateDebugger_MapLoaded();
HLE::PatchFunctions();
HLE::PatchFunctions(system);
}
return true;
}
+10 -5
View File
@@ -34,6 +34,11 @@ namespace IOS::HLE::FS
class FileSystem;
}
namespace PowerPC
{
struct PowerPCState;
}
struct RegionSetting
{
std::string area;
@@ -167,17 +172,17 @@ private:
static bool DVDRead(const DiscIO::VolumeDisc& disc, u64 dvd_offset, u32 output_address,
u32 length, const DiscIO::Partition& partition);
static bool DVDReadDiscID(const DiscIO::VolumeDisc& disc, u32 output_address);
static void RunFunction(u32 address);
static void RunFunction(Core::System& system, u32 address);
static void UpdateDebugger_MapLoaded();
static bool Boot_WiiWAD(Core::System& system, const DiscIO::VolumeWAD& wad);
static bool BootNANDTitle(Core::System& system, u64 title_id);
static void SetupMSR();
static void SetupHID(bool is_wii);
static void SetupBAT(bool is_wii);
static bool RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
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,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
static bool EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
+83 -74
View File
@@ -55,80 +55,83 @@ void PresetTimeBaseTicks()
}
} // Anonymous namespace
void CBoot::RunFunction(u32 address)
void CBoot::RunFunction(Core::System& system, u32 address)
{
PC = address;
LR = 0x00;
auto& ppc_state = system.GetPPCState();
while (PC != 0x00)
ppc_state.pc = address;
LR(ppc_state) = 0x00;
while (ppc_state.pc != 0x00)
PowerPC::SingleStep();
}
void CBoot::SetupMSR()
void CBoot::SetupMSR(PowerPC::PowerPCState& ppc_state)
{
// 0x0002032
MSR.RI = 1;
MSR.DR = 1;
MSR.IR = 1;
MSR.FP = 1;
ppc_state.msr.RI = 1;
ppc_state.msr.DR = 1;
ppc_state.msr.IR = 1;
ppc_state.msr.FP = 1;
}
void CBoot::SetupHID(bool is_wii)
void CBoot::SetupHID(PowerPC::PowerPCState& ppc_state, bool is_wii)
{
// HID0 is 0x0011c464 on GC, 0x0011c664 on Wii
HID0.BHT = 1;
HID0.BTIC = 1;
HID0.DCFA = 1;
HID0(ppc_state).BHT = 1;
HID0(ppc_state).BTIC = 1;
HID0(ppc_state).DCFA = 1;
if (is_wii)
HID0.SPD = 1;
HID0.DCFI = 1;
HID0.DCE = 1;
HID0(ppc_state).SPD = 1;
HID0(ppc_state).DCFI = 1;
HID0(ppc_state).DCE = 1;
// Note that Datel titles will fail to boot if the instruction cache is not enabled; see
// https://bugs.dolphin-emu.org/issues/8223
HID0.ICE = 1;
HID0.NHR = 1;
HID0.DPM = 1;
HID0(ppc_state).ICE = 1;
HID0(ppc_state).NHR = 1;
HID0(ppc_state).DPM = 1;
// HID1 is initialized in PowerPC.cpp to 0x80000000
// HID2 is 0xe0000000
HID2.PSE = 1;
HID2.WPE = 1;
HID2.LSQE = 1;
HID2(ppc_state).PSE = 1;
HID2(ppc_state).WPE = 1;
HID2(ppc_state).LSQE = 1;
// HID4 is 0 on GC and 0x83900000 on Wii
if (is_wii)
{
HID4.L2CFI = 1;
HID4.LPE = 1;
HID4.ST0 = 1;
HID4.SBE = 1;
HID4.reserved_3 = 1;
HID4(ppc_state).L2CFI = 1;
HID4(ppc_state).LPE = 1;
HID4(ppc_state).ST0 = 1;
HID4(ppc_state).SBE = 1;
HID4(ppc_state).reserved_3 = 1;
}
}
void CBoot::SetupBAT(bool is_wii)
void CBoot::SetupBAT(Core::System& system, bool is_wii)
{
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
auto& ppc_state = system.GetPPCState();
ppc_state.spr[SPR_IBAT0U] = 0x80001fff;
ppc_state.spr[SPR_IBAT0L] = 0x00000002;
ppc_state.spr[SPR_DBAT0U] = 0x80001fff;
ppc_state.spr[SPR_DBAT0L] = 0x00000002;
ppc_state.spr[SPR_DBAT1U] = 0xc0001fff;
ppc_state.spr[SPR_DBAT1L] = 0x0000002a;
if (is_wii)
{
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
HID4.SBE = 1;
ppc_state.spr[SPR_IBAT4U] = 0x90001fff;
ppc_state.spr[SPR_IBAT4L] = 0x10000002;
ppc_state.spr[SPR_DBAT4U] = 0x90001fff;
ppc_state.spr[SPR_DBAT4L] = 0x10000002;
ppc_state.spr[SPR_DBAT5U] = 0xd0001fff;
ppc_state.spr[SPR_DBAT5L] = 0x1000002a;
HID4(ppc_state).SBE = 1;
}
PowerPC::DBATUpdated();
PowerPC::IBATUpdated();
}
bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
{
const DiscIO::Partition partition = volume.GetGamePartition();
@@ -148,40 +151,42 @@ bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
auto& ppc_state = system.GetPPCState();
// Call iAppLoaderEntry.
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderEntry");
const u32 iAppLoaderFuncAddr = is_wii ? 0x80004000 : 0x80003100;
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(*entry);
ppc_state.gpr[3] = iAppLoaderFuncAddr + 0;
ppc_state.gpr[4] = iAppLoaderFuncAddr + 4;
ppc_state.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(system, *entry);
const u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
const u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
const u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
// iAppLoaderInit
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderInit");
PowerPC::HostWrite_U32(0x4E800020, 0x81300000); // Write BLR
HLE::Patch(0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit);
PowerPC::HostWrite_U32(0x4E800020, 0x81300000); // Write BLR
HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
ppc_state.gpr[3] = 0x81300000;
RunFunction(system, iAppLoaderInit);
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
// To give you an idea about where the stuff is located on the disc take a look at yagcd
// ch 13.
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderMain");
PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008;
PowerPC::ppcState.gpr[5] = 0x8130000c;
ppc_state.gpr[3] = 0x81300004;
ppc_state.gpr[4] = 0x81300008;
ppc_state.gpr[5] = 0x8130000c;
RunFunction(iAppLoaderMain);
RunFunction(system, iAppLoaderMain);
// iAppLoaderMain returns 1 if the pointers in R3/R4/R5 were filled with values for DVD copy
// Typical behaviour is doing it once for each section defined in the DOL header. Some unlicensed
// titles don't have a properly constructed DOL and maintain a table of these values in apploader.
// iAppLoaderMain returns 0 when there are no more sections to copy.
while (PowerPC::ppcState.gpr[3] != 0x00)
while (ppc_state.gpr[3] != 0x00)
{
const u32 ram_address = PowerPC::Read_U32(0x81300004);
const u32 length = PowerPC::Read_U32(0x81300008);
@@ -193,20 +198,20 @@ bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
DiscIO::Riivolution::ApplyApploaderMemoryPatches(riivolution_patches, ram_address, length);
PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008;
PowerPC::ppcState.gpr[5] = 0x8130000c;
ppc_state.gpr[3] = 0x81300004;
ppc_state.gpr[4] = 0x81300008;
ppc_state.gpr[5] = 0x8130000c;
RunFunction(iAppLoaderMain);
RunFunction(system, iAppLoaderMain);
}
// iAppLoaderClose
DEBUG_LOG_FMT(BOOT, "call iAppLoaderClose");
RunFunction(iAppLoaderClose);
HLE::UnPatch("AppLoaderReport");
RunFunction(system, iAppLoaderClose);
HLE::UnPatch(system, "AppLoaderReport");
// return
PC = PowerPC::ppcState.gpr[3];
ppc_state.pc = ppc_state.gpr[3];
return true;
}
@@ -255,9 +260,11 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volum
{
INFO_LOG_FMT(BOOT, "Faking GC BS2...");
SetupMSR();
SetupHID(/*is_wii*/ false);
SetupBAT(/*is_wii*/ false);
auto& ppc_state = system.GetPPCState();
SetupMSR(ppc_state);
SetupHID(ppc_state, /*is_wii*/ false);
SetupBAT(system, /*is_wii*/ false);
SetupGCMemory(system);
@@ -296,13 +303,13 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volum
// Setup pointers like real BS2 does
// StackPointer, used to be set to 0x816ffff0
PowerPC::ppcState.gpr[1] = ntsc ? 0x81566550 : 0x815edca8;
ppc_state.gpr[1] = ntsc ? 0x81566550 : 0x815edca8;
// Global pointer to Small Data Area 2 Base (haven't seen anything use it...meh)
PowerPC::ppcState.gpr[2] = ntsc ? 0x81465cc0 : 0x814b5b20;
ppc_state.gpr[2] = ntsc ? 0x81465cc0 : 0x814b5b20;
// Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
PowerPC::ppcState.gpr[13] = ntsc ? 0x81465320 : 0x814b4fc0;
ppc_state.gpr[13] = ntsc ? 0x81465320 : 0x814b4fc0;
return RunApploader(/*is_wii*/ false, volume, riivolution_patches);
return RunApploader(system, /*is_wii*/ false, volume, riivolution_patches);
}
static DiscIO::Region CodeRegion(char c)
@@ -559,17 +566,19 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volu
// after this check during booting.
DVDRead(volume, 0, 0x3180, 4, partition);
SetupMSR();
SetupHID(/*is_wii*/ true);
SetupBAT(/*is_wii*/ true);
auto& ppc_state = system.GetPPCState();
SetupMSR(ppc_state);
SetupHID(ppc_state, /*is_wii*/ true);
SetupBAT(system, /*is_wii*/ true);
memory.Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
memory.Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
memory.Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
ppc_state.gpr[1] = 0x816ffff0; // StackPointer
if (!RunApploader(/*is_wii*/ true, volume, riivolution_patches))
if (!RunApploader(system, /*is_wii*/ true, volume, riivolution_patches))
return false;
// The Apploader probably just overwrote values needed for RAM Override. Run this again!
+7 -2
View File
@@ -20,6 +20,7 @@
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
Cheats::DataType Cheats::GetDataType(const Cheats::SearchValue& value)
{
@@ -204,7 +205,9 @@ Cheats::NewSearch(const std::vector<Cheats::MemoryRange>& memory_ranges,
return;
}
if (address_space == PowerPC::RequestedAddressSpace::Virtual && !MSR.DR)
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
if (address_space == PowerPC::RequestedAddressSpace::Virtual && !ppc_state.msr.DR)
{
error_code = Cheats::SearchErrorCode::VirtualAddressesCurrentlyNotAccessible;
return;
@@ -263,7 +266,9 @@ Cheats::NextSearch(const std::vector<Cheats::SearchResult<T>>& previous_results,
return;
}
if (address_space == PowerPC::RequestedAddressSpace::Virtual && !MSR.DR)
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
if (address_space == PowerPC::RequestedAddressSpace::Virtual && !ppc_state.msr.DR)
{
error_code = Cheats::SearchErrorCode::VirtualAddressesCurrentlyNotAccessible;
return;
+3 -1
View File
@@ -51,6 +51,7 @@
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "Core/TitleDatabase.h"
#include "VideoCommon/HiresTextures.h"
@@ -202,7 +203,8 @@ void SConfig::OnNewTitleLoad()
Host_NotifyMapLoaded();
}
CBoot::LoadMapFromFilename();
HLE::Reload();
auto& system = Core::System::GetInstance();
HLE::Reload(system);
PatchEngine::Reload();
HiresTexture::Update();
}
+20 -13
View File
@@ -44,6 +44,10 @@ static void EmptyTimedCallback(Core::System& system, u64 userdata, s64 cyclesLat
{
}
CoreTimingManager::CoreTimingManager(Core::System& system) : m_system(system)
{
}
// Changing the CPU speed in Dolphin isn't actually done by changing the physical clock rate,
// but by changing the amount of work done in a particular amount of time. This tends to be more
// compatible because it stops the games from actually knowing directly that the clock rate has
@@ -90,7 +94,7 @@ void CoreTimingManager::Init()
m_last_oc_factor = m_config_oc_factor;
m_globals.last_OC_factor_inverted = m_config_oc_inv_factor;
PowerPC::ppcState.downcount = CyclesToDowncount(MAX_SLICE_LENGTH);
m_system.GetPPCState().downcount = CyclesToDowncount(MAX_SLICE_LENGTH);
m_globals.slice_length = MAX_SLICE_LENGTH;
m_globals.global_timer = 0;
m_idled_cycles = 0;
@@ -195,7 +199,7 @@ u64 CoreTimingManager::GetTicks() const
u64 ticks = static_cast<u64>(m_globals.global_timer);
if (!m_is_global_timer_sane)
{
int downcount = DowncountToCycles(PowerPC::ppcState.downcount);
int downcount = DowncountToCycles(m_system.GetPPCState().downcount);
ticks += m_globals.slice_length - downcount;
}
return ticks;
@@ -277,13 +281,13 @@ void CoreTimingManager::RemoveAllEvents(EventType* event_type)
void CoreTimingManager::ForceExceptionCheck(s64 cycles)
{
cycles = std::max<s64>(0, cycles);
if (DowncountToCycles(PowerPC::ppcState.downcount) > cycles)
auto& ppc_state = m_system.GetPPCState();
if (DowncountToCycles(ppc_state.downcount) > cycles)
{
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int here.
// Account for cycles already executed by adjusting the m_globals.slice_length
m_globals.slice_length -=
DowncountToCycles(PowerPC::ppcState.downcount) - static_cast<int>(cycles);
PowerPC::ppcState.downcount = CyclesToDowncount(static_cast<int>(cycles));
m_globals.slice_length -= DowncountToCycles(ppc_state.downcount) - static_cast<int>(cycles);
ppc_state.downcount = CyclesToDowncount(static_cast<int>(cycles));
}
}
@@ -299,11 +303,12 @@ void CoreTimingManager::MoveEvents()
void CoreTimingManager::Advance()
{
auto& system = Core::System::GetInstance();
auto& system = m_system;
auto& ppc_state = m_system.GetPPCState();
MoveEvents();
int cyclesExecuted = m_globals.slice_length - DowncountToCycles(PowerPC::ppcState.downcount);
int cyclesExecuted = m_globals.slice_length - DowncountToCycles(ppc_state.downcount);
m_globals.global_timer += cyclesExecuted;
m_last_oc_factor = m_config_oc_factor;
m_globals.last_OC_factor_inverted = m_config_oc_inv_factor;
@@ -330,7 +335,7 @@ void CoreTimingManager::Advance()
std::min<s64>(m_event_queue.front().time - m_globals.global_timer, MAX_SLICE_LENGTH));
}
PowerPC::ppcState.downcount = CyclesToDowncount(m_globals.slice_length);
ppc_state.downcount = CyclesToDowncount(m_globals.slice_length);
// Check for any external exceptions.
// It's important to do this after processing events otherwise any exceptions will be delayed
@@ -438,18 +443,20 @@ void CoreTimingManager::AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clo
void CoreTimingManager::Idle()
{
auto& system = m_system;
auto& ppc_state = m_system.GetPPCState();
if (m_config_sync_on_skip_idle)
{
// When the FIFO is processing data we must not advance because in this way
// the VI will be desynchronized. So, We are waiting until the FIFO finish and
// while we process only the events required by the FIFO.
auto& system = Core::System::GetInstance();
system.GetFifo().FlushGpu(system);
}
PowerPC::UpdatePerformanceMonitor(PowerPC::ppcState.downcount, 0, 0);
m_idled_cycles += DowncountToCycles(PowerPC::ppcState.downcount);
PowerPC::ppcState.downcount = 0;
PowerPC::UpdatePerformanceMonitor(ppc_state.downcount, 0, 0, ppc_state);
m_idled_cycles += DowncountToCycles(ppc_state.downcount);
ppc_state.downcount = 0;
}
std::string CoreTimingManager::GetScheduledEventsSummary() const
+4
View File
@@ -75,6 +75,8 @@ void GlobalIdle();
class CoreTimingManager
{
public:
explicit CoreTimingManager(Core::System& system);
// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
// required to end slice -1 and start slice 0 before the first cycle of code is executed.
void Init();
@@ -151,6 +153,8 @@ public:
private:
Globals m_globals;
Core::System& m_system;
// unordered_map stores each element separately as a linked list node so pointers to elements
// remain stable regardless of rehashes/resizing.
std::unordered_map<std::string, EventType> m_event_types;
@@ -16,6 +16,7 @@
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace Dolphin_Debugger
{
@@ -43,11 +44,13 @@ static bool IsStackBottom(u32 addr)
return !addr || !PowerPC::HostIsRAMAddress(addr);
}
static void WalkTheStack(const std::function<void(u32)>& stack_step)
static void WalkTheStack(Core::System& system, const std::function<void(u32)>& stack_step)
{
if (!IsStackBottom(PowerPC::ppcState.gpr[1]))
auto& ppc_state = system.GetPPCState();
if (!IsStackBottom(ppc_state.gpr[1]))
{
u32 addr = PowerPC::HostRead_U32(PowerPC::ppcState.gpr[1]); // SP
u32 addr = PowerPC::HostRead_U32(ppc_state.gpr[1]); // SP
// Walk the stack chain
for (int count = 0; !IsStackBottom(addr + 4) && (count++ < 20); ++count)
@@ -66,12 +69,14 @@ static void WalkTheStack(const std::function<void(u32)>& stack_step)
// Returns callstack "formatted for debugging" - meaning that it
// includes LR as the last item, and all items are the last step,
// instead of "pointing ahead"
bool GetCallstack(std::vector<CallstackEntry>& output)
bool GetCallstack(Core::System& system, std::vector<CallstackEntry>& output)
{
if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(PowerPC::ppcState.gpr[1]))
auto& ppc_state = system.GetPPCState();
if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(ppc_state.gpr[1]))
return false;
if (LR == 0)
if (LR(ppc_state) == 0)
{
CallstackEntry entry;
entry.Name = "(error: LR=0)";
@@ -81,11 +86,12 @@ bool GetCallstack(std::vector<CallstackEntry>& output)
}
CallstackEntry entry;
entry.Name = fmt::format(" * {} [ LR = {:08x} ]\n", g_symbolDB.GetDescription(LR), LR - 4);
entry.vAddress = LR - 4;
entry.Name = fmt::format(" * {} [ LR = {:08x} ]\n", g_symbolDB.GetDescription(LR(ppc_state)),
LR(ppc_state) - 4);
entry.vAddress = LR(ppc_state) - 4;
output.push_back(entry);
WalkTheStack([&entry, &output](u32 func_addr) {
WalkTheStack(system, [&entry, &output](u32 func_addr) {
std::string func_desc = g_symbolDB.GetDescription(func_addr);
if (func_desc.empty() || func_desc == "Invalid")
func_desc = "(unknown)";
@@ -97,21 +103,24 @@ bool GetCallstack(std::vector<CallstackEntry>& output)
return true;
}
void PrintCallstack(Common::Log::LogType type, Common::Log::LogLevel level)
void PrintCallstack(Core::System& system, Common::Log::LogType type, Common::Log::LogLevel level)
{
GENERIC_LOG_FMT(type, level, "== STACK TRACE - SP = {:08x} ==", PowerPC::ppcState.gpr[1]);
auto& ppc_state = system.GetPPCState();
if (LR == 0)
GENERIC_LOG_FMT(type, level, "== STACK TRACE - SP = {:08x} ==", ppc_state.gpr[1]);
if (LR(ppc_state) == 0)
{
GENERIC_LOG_FMT(type, level, " LR = 0 - this is bad");
}
if (g_symbolDB.GetDescription(PC) != g_symbolDB.GetDescription(LR))
if (g_symbolDB.GetDescription(ppc_state.pc) != g_symbolDB.GetDescription(LR(ppc_state)))
{
GENERIC_LOG_FMT(type, level, " * {} [ LR = {:08x} ]", g_symbolDB.GetDescription(LR), LR);
GENERIC_LOG_FMT(type, level, " * {} [ LR = {:08x} ]", g_symbolDB.GetDescription(LR(ppc_state)),
LR(ppc_state));
}
WalkTheStack([type, level](u32 func_addr) {
WalkTheStack(system, [type, level](u32 func_addr) {
std::string func_desc = g_symbolDB.GetDescription(func_addr);
if (func_desc.empty() || func_desc == "Invalid")
func_desc = "(unknown)";
@@ -10,6 +10,11 @@
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
namespace Core
{
class System;
}
namespace Dolphin_Debugger
{
struct CallstackEntry
@@ -18,8 +23,8 @@ struct CallstackEntry
u32 vAddress = 0;
};
bool GetCallstack(std::vector<CallstackEntry>& output);
void PrintCallstack(Common::Log::LogType type, Common::Log::LogLevel level);
bool GetCallstack(Core::System& system, std::vector<CallstackEntry>& output);
void PrintCallstack(Core::System& system, Common::Log::LogType type, Common::Log::LogLevel level);
void PrintDataBuffer(Common::Log::LogType type, const u8* data, size_t size,
std::string_view title);
void AddAutoBreakpoints();
@@ -23,6 +23,7 @@
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
void ApplyMemoryPatch(Common::Debug::MemoryPatch& patch, bool store_existing_value)
{
@@ -81,7 +82,10 @@ void PPCPatches::UnPatch(std::size_t index)
PatchEngine::RemoveMemoryPatch(index);
}
PPCDebugInterface::PPCDebugInterface() = default;
PPCDebugInterface::PPCDebugInterface(Core::System& system) : m_system(system)
{
}
PPCDebugInterface::~PPCDebugInterface() = default;
std::size_t PPCDebugInterface::SetWatch(u32 address, std::string name)
@@ -449,7 +453,7 @@ PPCDebugInterface::GetMemoryAddressFromInstruction(const std::string& instructio
if (is_reg == offset_match[0])
{
const int register_index = std::stoi(offset_match.substr(1), nullptr, 10);
offset = (register_index == 0 ? 0 : GPR(register_index));
offset = (register_index == 0 ? 0 : m_system.GetPPCState().gpr[register_index]);
}
else
{
@@ -468,7 +472,7 @@ PPCDebugInterface::GetMemoryAddressFromInstruction(const std::string& instructio
else
i = std::stoi(register_match, nullptr, 10);
const u32 base_address = GPR(i);
const u32 base_address = m_system.GetPPCState().gpr[i];
if (!match.str(1).empty())
return base_address - offset;
@@ -478,12 +482,12 @@ PPCDebugInterface::GetMemoryAddressFromInstruction(const std::string& instructio
u32 PPCDebugInterface::GetPC() const
{
return PowerPC::ppcState.pc;
return m_system.GetPPCState().pc;
}
void PPCDebugInterface::SetPC(u32 address)
{
PowerPC::ppcState.pc = address;
m_system.GetPPCState().pc = address;
}
void PPCDebugInterface::RunToBreakpoint()
@@ -12,6 +12,11 @@
#include "Common/DebugInterface.h"
#include "Core/NetworkCaptureLogger.h"
namespace Core
{
class System;
}
void ApplyMemoryPatch(Common::Debug::MemoryPatch& patch, bool store_existing_value = true);
class PPCPatches final : public Common::Debug::MemoryPatches
@@ -29,7 +34,7 @@ private:
class PPCDebugInterface final : public Common::DebugInterface
{
public:
PPCDebugInterface();
explicit PPCDebugInterface(Core::System& system);
~PPCDebugInterface() override;
// Watches
@@ -102,4 +107,5 @@ private:
Common::Debug::Watches m_watches;
PPCPatches m_patches;
std::shared_ptr<Core::NetworkCaptureLogger> m_network_logger;
Core::System& m_system;
};
+14 -10
View File
@@ -514,6 +514,7 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end)
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& gpfifo = system.GetGPFifo();
auto& ppc_state = system.GetPPCState();
// Write up to 256 bytes at a time
while (written < end)
@@ -528,8 +529,8 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end)
u32 burstEnd = std::min(written + 255, lastBurstEnd);
std::copy(data + written, data + burstEnd, PowerPC::ppcState.gather_pipe_ptr);
PowerPC::ppcState.gather_pipe_ptr += burstEnd - written;
std::copy(data + written, data + burstEnd, ppc_state.gather_pipe_ptr);
ppc_state.gather_pipe_ptr += burstEnd - written;
written = burstEnd;
gpfifo.Write8(data[written++]);
@@ -539,7 +540,7 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end)
u32 cyclesUsed = elapsedCycles - m_ElapsedCycles;
m_ElapsedCycles = elapsedCycles;
PowerPC::ppcState.downcount -= cyclesUsed;
ppc_state.downcount -= cyclesUsed;
core_timing.Advance();
}
}
@@ -629,16 +630,19 @@ void FifoPlayer::ClearEfb()
void FifoPlayer::LoadMemory()
{
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
UReg_MSR newMSR;
newMSR.DR = 1;
newMSR.IR = 1;
MSR.Hex = newMSR.Hex;
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
ppc_state.msr.Hex = newMSR.Hex;
ppc_state.spr[SPR_IBAT0U] = 0x80001fff;
ppc_state.spr[SPR_IBAT0L] = 0x00000002;
ppc_state.spr[SPR_DBAT0U] = 0x80001fff;
ppc_state.spr[SPR_DBAT0L] = 0x00000002;
ppc_state.spr[SPR_DBAT1U] = 0xc0001fff;
ppc_state.spr[SPR_DBAT1L] = 0x0000002a;
PowerPC::DBATUpdated();
PowerPC::IBATUpdated();
+23 -15
View File
@@ -19,6 +19,7 @@
#include "Core/ConfigManager.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace Gecko
{
@@ -204,10 +205,13 @@ static Installation InstallCodeHandlerLocked()
// Turn on codes
PowerPC::HostWrite_U8(1, INSTALLER_BASE_ADDRESS + 7);
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
// Invalidate the icache and any asm codes
for (unsigned int j = 0; j < (INSTALLER_END_ADDRESS - INSTALLER_BASE_ADDRESS); j += 32)
{
PowerPC::ppcState.iCache.Invalidate(INSTALLER_BASE_ADDRESS + j);
ppc_state.iCache.Invalidate(INSTALLER_BASE_ADDRESS + j);
}
return Installation::Installed;
}
@@ -253,36 +257,40 @@ void RunCodeHandler()
}
}
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
// We always do this to avoid problems with the stack since we're branching in random locations.
// Even with function call return hooks (PC == LR), hand coded assembler won't necessarily
// follow the ABI. [Volatile FPR, GPR, CR may not be volatile]
// The codehandler will STMW all of the GPR registers, but we need to fix the Stack's Red
// Zone, the LR, PC (return address) and the volatile floating point registers.
// Build a function call stack frame.
u32 SFP = GPR(1); // Stack Frame Pointer
GPR(1) -= 256; // Stack's Red Zone
GPR(1) -= 16 + 2 * 14 * sizeof(u64); // Our stack frame (HLE_Misc::GeckoReturnTrampoline)
GPR(1) -= 8; // Fake stack frame for codehandler
GPR(1) &= 0xFFFFFFF0; // Align stack to 16bytes
u32 SP = GPR(1); // Stack Pointer
u32 SFP = ppc_state.gpr[1]; // Stack Frame Pointer
ppc_state.gpr[1] -= 256; // Stack's Red Zone
ppc_state.gpr[1] -= 16 + 2 * 14 * sizeof(u64); // Our stack frame
// (HLE_Misc::GeckoReturnTrampoline)
ppc_state.gpr[1] -= 8; // Fake stack frame for codehandler
ppc_state.gpr[1] &= 0xFFFFFFF0; // Align stack to 16bytes
u32 SP = ppc_state.gpr[1]; // Stack Pointer
PowerPC::HostWrite_U32(SP + 8, SP);
// SP + 4 is reserved for the codehandler to save LR to the stack.
PowerPC::HostWrite_U32(SFP, SP + 8); // Real stack frame
PowerPC::HostWrite_U32(PC, SP + 12);
PowerPC::HostWrite_U32(LR, SP + 16);
PowerPC::HostWrite_U32(PowerPC::ppcState.cr.Get(), SP + 20);
PowerPC::HostWrite_U32(ppc_state.pc, SP + 12);
PowerPC::HostWrite_U32(LR(ppc_state), SP + 16);
PowerPC::HostWrite_U32(ppc_state.cr.Get(), SP + 20);
// Registers FPR0->13 are volatile
for (int i = 0; i < 14; ++i)
{
PowerPC::HostWrite_U64(rPS(i).PS0AsU64(), SP + 24 + 2 * i * sizeof(u64));
PowerPC::HostWrite_U64(rPS(i).PS1AsU64(), SP + 24 + (2 * i + 1) * sizeof(u64));
PowerPC::HostWrite_U64(ppc_state.ps[i].PS0AsU64(), SP + 24 + 2 * i * sizeof(u64));
PowerPC::HostWrite_U64(ppc_state.ps[i].PS1AsU64(), SP + 24 + (2 * i + 1) * sizeof(u64));
}
DEBUG_LOG_FMT(ACTIONREPLAY,
"GeckoCodes: Initiating phantom branch-and-link. "
"PC = {:#010x}, SP = {:#010x}, SFP = {:#010x}",
PC, SP, SFP);
LR = HLE_TRAMPOLINE_ADDRESS;
PC = NPC = ENTRY_POINT;
ppc_state.pc, SP, SFP);
LR(ppc_state) = HLE_TRAMPOLINE_ADDRESS;
ppc_state.pc = ppc_state.npc = ENTRY_POINT;
}
} // namespace Gecko
+24 -18
View File
@@ -63,20 +63,21 @@ constexpr std::array<Hook, 23> os_patches{{
}};
// clang-format on
void Patch(u32 addr, std::string_view func_name)
void Patch(Core::System& system, u32 addr, std::string_view func_name)
{
auto& ppc_state = system.GetPPCState();
for (u32 i = 1; i < os_patches.size(); ++i)
{
if (os_patches[i].name == func_name)
{
s_hooked_addresses[addr] = i;
PowerPC::ppcState.iCache.Invalidate(addr);
ppc_state.iCache.Invalidate(addr);
return;
}
}
}
void PatchFixedFunctions()
void PatchFixedFunctions(Core::System& system)
{
// MIOS puts patch data in low MEM1 (0x1800-0x3000) for its own use.
// Overwriting data in this range can cause the IPL to crash when launching games
@@ -90,28 +91,29 @@ void PatchFixedFunctions()
// handler
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
{
Patch(0x80001800, "HBReload");
auto& system = Core::System::GetInstance();
Patch(system, 0x80001800, "HBReload");
auto& memory = system.GetMemory();
memory.CopyToEmu(0x00001804, "STUBHAXX", 8);
}
// Not part of the binary itself, but either we or Gecko OS might insert
// this, and it doesn't clear the icache properly.
Patch(Gecko::ENTRY_POINT, "GeckoCodehandler");
Patch(system, Gecko::ENTRY_POINT, "GeckoCodehandler");
// This has to always be installed even if cheats are not enabled because of the possiblity of
// loading a savestate where PC is inside the code handler while cheats are disabled.
Patch(Gecko::HLE_TRAMPOLINE_ADDRESS, "GeckoHandlerReturnTrampoline");
Patch(system, Gecko::HLE_TRAMPOLINE_ADDRESS, "GeckoHandlerReturnTrampoline");
}
void PatchFunctions()
void PatchFunctions(Core::System& system)
{
auto& ppc_state = system.GetPPCState();
// Remove all hooks that aren't fixed address hooks
for (auto i = s_hooked_addresses.begin(); i != s_hooked_addresses.end();)
{
if (os_patches[i->second].flags != HookFlag::Fixed)
{
PowerPC::ppcState.iCache.Invalidate(i->first);
ppc_state.iCache.Invalidate(i->first);
i = s_hooked_addresses.erase(i);
}
else
@@ -131,7 +133,7 @@ void PatchFunctions()
for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
{
s_hooked_addresses[addr] = i;
PowerPC::ppcState.iCache.Invalidate(addr);
ppc_state.iCache.Invalidate(addr);
}
INFO_LOG_FMT(OSHLE, "Patching {} {:08x}", os_patches[i].name, symbol->address);
}
@@ -143,11 +145,11 @@ void Clear()
s_hooked_addresses.clear();
}
void Reload()
void Reload(Core::System& system)
{
Clear();
PatchFixedFunctions();
PatchFunctions();
PatchFixedFunctions(system);
PatchFunctions(system);
}
void Execute(u32 current_pc, u32 hook_index)
@@ -196,13 +198,15 @@ bool IsEnabled(HookFlag flag)
PowerPC::GetMode() == PowerPC::CoreMode::Interpreter;
}
u32 UnPatch(std::string_view patch_name)
u32 UnPatch(Core::System& system, std::string_view patch_name)
{
const auto patch = std::find_if(std::begin(os_patches), std::end(os_patches),
[&](const Hook& p) { return patch_name == p.name; });
if (patch == std::end(os_patches))
return 0;
auto& ppc_state = system.GetPPCState();
if (patch->flags == HookFlag::Fixed)
{
const u32 patch_idx = static_cast<u32>(std::distance(os_patches.begin(), patch));
@@ -213,7 +217,7 @@ u32 UnPatch(std::string_view patch_name)
if (i->second == patch_idx)
{
addr = i->first;
PowerPC::ppcState.iCache.Invalidate(i->first);
ppc_state.iCache.Invalidate(i->first);
i = s_hooked_addresses.erase(i);
}
else
@@ -231,7 +235,7 @@ u32 UnPatch(std::string_view patch_name)
for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
{
s_hooked_addresses.erase(addr);
PowerPC::ppcState.iCache.Invalidate(addr);
ppc_state.iCache.Invalidate(addr);
}
return symbol->address;
}
@@ -239,8 +243,10 @@ u32 UnPatch(std::string_view patch_name)
return 0;
}
u32 UnpatchRange(u32 start_addr, u32 end_addr)
u32 UnpatchRange(Core::System& system, u32 start_addr, u32 end_addr)
{
auto& ppc_state = system.GetPPCState();
u32 count = 0;
auto i = s_hooked_addresses.lower_bound(start_addr);
@@ -248,7 +254,7 @@ u32 UnpatchRange(u32 start_addr, u32 end_addr)
{
INFO_LOG_FMT(OSHLE, "Unpatch HLE hooks [{:08x};{:08x}): {} at {:08x}", start_addr, end_addr,
os_patches[i->second].name, i->first);
PowerPC::ppcState.iCache.Invalidate(i->first);
ppc_state.iCache.Invalidate(i->first);
i = s_hooked_addresses.erase(i);
count += 1;
}
+11 -6
View File
@@ -7,6 +7,11 @@
#include "Common/CommonTypes.h"
namespace Core
{
class System;
}
namespace HLE
{
using HookFunction = void (*)();
@@ -33,14 +38,14 @@ struct Hook
HookFlag flags;
};
void PatchFixedFunctions();
void PatchFunctions();
void PatchFixedFunctions(Core::System& system);
void PatchFunctions(Core::System& system);
void Clear();
void Reload();
void Reload(Core::System& system);
void Patch(u32 pc, std::string_view func_name);
u32 UnPatch(std::string_view patch_name);
u32 UnpatchRange(u32 start_addr, u32 end_addr);
void Patch(Core::System& system, u32 pc, std::string_view func_name);
u32 UnPatch(Core::System& system, std::string_view patch_name);
u32 UnpatchRange(Core::System& system, u32 start_addr, u32 end_addr);
void Execute(u32 current_pc, u32 hook_index);
// Returns the HLE hook index of the address
+18 -9
View File
@@ -10,6 +10,7 @@
#include "Core/Host.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace HLE_Misc
{
@@ -17,7 +18,9 @@ namespace HLE_Misc
// According to the PPC ABI, the return value is always in r3.
void UnimplementedFunction()
{
NPC = LR;
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
ppc_state.npc = LR(ppc_state);
}
void HBReload()
@@ -29,6 +32,9 @@ void HBReload()
void GeckoCodeHandlerICacheFlush()
{
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
// Work around the codehandler not properly invalidating the icache, but
// only the first few frames.
// (Project M uses a conditional to only apply patches after something has
@@ -46,7 +52,7 @@ void GeckoCodeHandlerICacheFlush()
}
PowerPC::HostWrite_U32(gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS);
PowerPC::ppcState.iCache.Reset();
ppc_state.iCache.Reset();
}
// Because Dolphin messes around with the CPU state instead of patching the game binary, we
@@ -55,16 +61,19 @@ void GeckoCodeHandlerICacheFlush()
// and PC before the magic, invisible BL instruction happened.
void GeckoReturnTrampoline()
{
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
// Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler.
u32 SP = GPR(1);
GPR(1) = PowerPC::HostRead_U32(SP + 8);
NPC = PowerPC::HostRead_U32(SP + 12);
LR = PowerPC::HostRead_U32(SP + 16);
PowerPC::ppcState.cr.Set(PowerPC::HostRead_U32(SP + 20));
u32 SP = ppc_state.gpr[1];
ppc_state.gpr[1] = PowerPC::HostRead_U32(SP + 8);
ppc_state.npc = PowerPC::HostRead_U32(SP + 12);
LR(ppc_state) = PowerPC::HostRead_U32(SP + 16);
ppc_state.cr.Set(PowerPC::HostRead_U32(SP + 20));
for (int i = 0; i < 14; ++i)
{
rPS(i).SetBoth(PowerPC::HostRead_U64(SP + 24 + 2 * i * sizeof(u64)),
PowerPC::HostRead_U64(SP + 24 + (2 * i + 1) * sizeof(u64)));
ppc_state.ps[i].SetBoth(PowerPC::HostRead_U64(SP + 24 + 2 * i * sizeof(u64)),
PowerPC::HostRead_U64(SP + 24 + (2 * i + 1) * sizeof(u64)));
}
}
} // namespace HLE_Misc
+57 -32
View File
@@ -13,6 +13,7 @@
#include "Core/HLE/HLE_VarArgs.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace HLE_OS
{
@@ -22,7 +23,7 @@ enum class ParameterType : bool
VariableArgumentList = true
};
std::string GetStringVA(u32 str_reg = 3,
std::string GetStringVA(Core::System& system, u32 str_reg = 3,
ParameterType parameter_type = ParameterType::ParameterList);
void HLE_GeneralDebugPrint(ParameterType parameter_type);
void HLE_LogDPrint(ParameterType parameter_type);
@@ -30,56 +31,64 @@ void HLE_LogFPrint(ParameterType parameter_type);
void HLE_OSPanic()
{
std::string error = GetStringVA();
std::string msg = GetStringVA(5);
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
std::string error = GetStringVA(system);
std::string msg = GetStringVA(system, 5);
StringPopBackIf(&error, '\n');
StringPopBackIf(&msg, '\n');
PanicAlertFmt("OSPanic: {}: {}", error, msg);
ERROR_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| OSPanic: {}: {}", LR, PC, error, msg);
ERROR_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| OSPanic: {}: {}", LR(ppc_state), ppc_state.pc, error,
msg);
NPC = LR;
ppc_state.npc = LR(ppc_state);
}
// Generalized function for printing formatted string.
void HLE_GeneralDebugPrint(ParameterType parameter_type)
{
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
std::string report_message;
// Is gpr3 pointing to a pointer (including nullptr) rather than an ASCII string
if (PowerPC::HostIsRAMAddress(GPR(3)) &&
(PowerPC::HostIsRAMAddress(PowerPC::HostRead_U32(GPR(3))) ||
PowerPC::HostRead_U32(GPR(3)) == 0))
if (PowerPC::HostIsRAMAddress(ppc_state.gpr[3]) &&
(PowerPC::HostIsRAMAddress(PowerPC::HostRead_U32(ppc_state.gpr[3])) ||
PowerPC::HostRead_U32(ppc_state.gpr[3]) == 0))
{
if (PowerPC::HostIsRAMAddress(GPR(4)))
if (PowerPC::HostIsRAMAddress(ppc_state.gpr[4]))
{
// ___blank(void* this, const char* fmt, ...);
report_message = GetStringVA(4, parameter_type);
report_message = GetStringVA(system, 4, parameter_type);
}
else
{
// ___blank(void* this, int log_type, const char* fmt, ...);
report_message = GetStringVA(5, parameter_type);
report_message = GetStringVA(system, 5, parameter_type);
}
}
else
{
if (PowerPC::HostIsRAMAddress(GPR(3)))
if (PowerPC::HostIsRAMAddress(ppc_state.gpr[3]))
{
// ___blank(const char* fmt, ...);
report_message = GetStringVA(3, parameter_type);
report_message = GetStringVA(system, 3, parameter_type);
}
else
{
// ___blank(int log_type, const char* fmt, ...);
report_message = GetStringVA(4, parameter_type);
report_message = GetStringVA(system, 4, parameter_type);
}
}
StringPopBackIf(&report_message, '\n');
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR, PC, SHIFTJISToUTF8(report_message));
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR(ppc_state), ppc_state.pc,
SHIFTJISToUTF8(report_message));
}
// Generalized function for printing formatted string using parameter list.
@@ -97,10 +106,13 @@ void HLE_GeneralDebugVPrint()
// __write_console(int fd, const void* buffer, const u32* size)
void HLE_write_console()
{
std::string report_message = GetStringVA(4);
if (PowerPC::HostIsRAMAddress(GPR(5)))
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
std::string report_message = GetStringVA(system, 4);
if (PowerPC::HostIsRAMAddress(ppc_state.gpr[5]))
{
const u32 size = PowerPC::Read_U32(GPR(5));
const u32 size = PowerPC::Read_U32(ppc_state.gpr[5]);
if (size > report_message.size())
WARN_LOG_FMT(OSREPORT_HLE, "__write_console uses an invalid size of {:#010x}", size);
else if (size == 0)
@@ -115,18 +127,23 @@ void HLE_write_console()
StringPopBackIf(&report_message, '\n');
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR, PC, SHIFTJISToUTF8(report_message));
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR(ppc_state), ppc_state.pc,
SHIFTJISToUTF8(report_message));
}
// Log (v)dprintf message if fd is 1 (stdout) or 2 (stderr)
void HLE_LogDPrint(ParameterType parameter_type)
{
if (GPR(3) != 1 && GPR(3) != 2)
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
if (ppc_state.gpr[3] != 1 && ppc_state.gpr[3] != 2)
return;
std::string report_message = GetStringVA(4, parameter_type);
std::string report_message = GetStringVA(system, 4, parameter_type);
StringPopBackIf(&report_message, '\n');
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR, PC, SHIFTJISToUTF8(report_message));
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR(ppc_state), ppc_state.pc,
SHIFTJISToUTF8(report_message));
}
// Log dprintf message
@@ -146,25 +163,30 @@ void HLE_LogVDPrint()
// Log (v)fprintf message if FILE is stdout or stderr
void HLE_LogFPrint(ParameterType parameter_type)
{
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
// The structure FILE is implementation defined.
// Both libogc and Dolphin SDK seem to store the fd at the same address.
int fd = -1;
if (PowerPC::HostIsRAMAddress(GPR(3)) && PowerPC::HostIsRAMAddress(GPR(3) + 0xF))
if (PowerPC::HostIsRAMAddress(ppc_state.gpr[3]) &&
PowerPC::HostIsRAMAddress(ppc_state.gpr[3] + 0xF))
{
// The fd is stored as a short at FILE+0xE.
fd = static_cast<short>(PowerPC::HostRead_U16(GPR(3) + 0xE));
fd = static_cast<short>(PowerPC::HostRead_U16(ppc_state.gpr[3] + 0xE));
}
if (fd != 1 && fd != 2)
{
// On RVL SDK it seems stored at FILE+0x2.
fd = static_cast<short>(PowerPC::HostRead_U16(GPR(3) + 0x2));
fd = static_cast<short>(PowerPC::HostRead_U16(ppc_state.gpr[3] + 0x2));
}
if (fd != 1 && fd != 2)
return;
std::string report_message = GetStringVA(4, parameter_type);
std::string report_message = GetStringVA(system, 4, parameter_type);
StringPopBackIf(&report_message, '\n');
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR, PC, SHIFTJISToUTF8(report_message));
NOTICE_LOG_FMT(OSREPORT_HLE, "{:08x}->{:08x}| {}", LR(ppc_state), ppc_state.pc,
SHIFTJISToUTF8(report_message));
}
// Log fprintf message
@@ -181,14 +203,17 @@ void HLE_LogVFPrint()
HLE_LogFPrint(ParameterType::VariableArgumentList);
}
std::string GetStringVA(u32 str_reg, ParameterType parameter_type)
std::string GetStringVA(Core::System& system, u32 str_reg, ParameterType parameter_type)
{
auto& ppc_state = system.GetPPCState();
std::string ArgumentBuffer;
std::string result;
std::string string = PowerPC::HostGetString(GPR(str_reg));
auto ap = parameter_type == ParameterType::VariableArgumentList ?
std::make_unique<HLE::SystemVABI::VAListStruct>(GPR(str_reg + 1)) :
std::make_unique<HLE::SystemVABI::VAList>(GPR(1) + 0x8, str_reg + 1);
std::string string = PowerPC::HostGetString(ppc_state.gpr[str_reg]);
auto ap =
parameter_type == ParameterType::VariableArgumentList ?
std::make_unique<HLE::SystemVABI::VAListStruct>(system, ppc_state.gpr[str_reg + 1]) :
std::make_unique<HLE::SystemVABI::VAList>(system, ppc_state.gpr[1] + 0x8, str_reg + 1);
for (size_t i = 0; i < string.size(); i++)
{
+8 -6
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/HLE/HLE_VarArgs.h"
#include "Core/System.h"
#include "Common/Logging/Log.h"
@@ -9,18 +10,19 @@ HLE::SystemVABI::VAList::~VAList() = default;
u32 HLE::SystemVABI::VAList::GetGPR(u32 gpr) const
{
return GPR(gpr);
return m_system.GetPPCState().gpr[gpr];
}
double HLE::SystemVABI::VAList::GetFPR(u32 fpr) const
{
return rPS(fpr).PS0AsDouble();
return m_system.GetPPCState().ps[fpr].PS0AsDouble();
}
HLE::SystemVABI::VAListStruct::VAListStruct(u32 address)
: VAList(0), m_va_list{PowerPC::HostRead_U8(address), PowerPC::HostRead_U8(address + 1),
PowerPC::HostRead_U32(address + 4), PowerPC::HostRead_U32(address + 8)},
m_address(address), m_has_fpr_area(PowerPC::ppcState.cr.GetBit(6) == 1)
HLE::SystemVABI::VAListStruct::VAListStruct(Core::System& system, u32 address)
: VAList(system, 0), m_va_list{PowerPC::HostRead_U8(address), PowerPC::HostRead_U8(address + 1),
PowerPC::HostRead_U32(address + 4),
PowerPC::HostRead_U32(address + 8)},
m_address(address), m_has_fpr_area(system.GetPPCState().cr.GetBit(6) == 1)
{
m_stack = m_va_list.overflow_arg_area;
m_gpr += m_va_list.gpr;
+11 -3
View File
@@ -11,6 +11,11 @@
#include <type_traits>
namespace Core
{
class System;
}
namespace HLE::SystemVABI
{
// SFINAE
@@ -32,8 +37,10 @@ constexpr bool IS_ARG_REAL = std::is_floating_point<T>();
class VAList
{
public:
explicit VAList(u32 stack, u32 gpr = 3, u32 fpr = 1, u32 gpr_max = 10, u32 fpr_max = 8)
: m_gpr(gpr), m_fpr(fpr), m_gpr_max(gpr_max), m_fpr_max(fpr_max), m_stack(stack)
explicit VAList(Core::System& system, u32 stack, u32 gpr = 3, u32 fpr = 1, u32 gpr_max = 10,
u32 fpr_max = 8)
: m_system(system), m_gpr(gpr), m_fpr(fpr), m_gpr_max(gpr_max), m_fpr_max(fpr_max),
m_stack(stack)
{
}
virtual ~VAList();
@@ -127,6 +134,7 @@ public:
}
protected:
Core::System& m_system;
u32 m_gpr = 3;
u32 m_fpr = 1;
const u32 m_gpr_max = 10;
@@ -147,7 +155,7 @@ private:
class VAListStruct : public VAList
{
public:
explicit VAListStruct(u32 address);
explicit VAListStruct(Core::System& system, u32 address);
~VAListStruct() = default;
private:

Some files were not shown because too many files have changed in this diff Show More