RiivolutionPatcher: Modify memory patching logic to be more accurate to actual Riivolution.
This commit is contained in:
parent
dd64c0e423
commit
ba3373b476
|
@ -450,7 +450,10 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)
|
|||
|
||||
struct BootTitle
|
||||
{
|
||||
BootTitle() : config(SConfig::GetInstance()) {}
|
||||
BootTitle(const std::vector<DiscIO::Riivolution::Patch>& patches)
|
||||
: config(SConfig::GetInstance()), riivolution_patches(patches)
|
||||
{
|
||||
}
|
||||
bool operator()(BootParameters::Disc& disc) const
|
||||
{
|
||||
NOTICE_LOG_FMT(BOOT, "Booting from disc: {}", disc.path);
|
||||
|
@ -460,7 +463,7 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)
|
|||
if (!volume)
|
||||
return false;
|
||||
|
||||
if (!EmulatedBS2(config.bWii, *volume))
|
||||
if (!EmulatedBS2(config.bWii, *volume, riivolution_patches))
|
||||
return false;
|
||||
|
||||
SConfig::OnNewTitleLoad();
|
||||
|
@ -570,12 +573,13 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)
|
|||
|
||||
private:
|
||||
const SConfig& config;
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches;
|
||||
};
|
||||
|
||||
if (!std::visit(BootTitle(), boot->parameters))
|
||||
if (!std::visit(BootTitle(boot->riivolution_patches), boot->parameters))
|
||||
return false;
|
||||
|
||||
DiscIO::Riivolution::ApplyPatchesToMemory(boot->riivolution_patches);
|
||||
DiscIO::Riivolution::ApplyGeneralMemoryPatches(boot->riivolution_patches);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -115,10 +115,14 @@ private:
|
|||
|
||||
static void SetupMSR();
|
||||
static void SetupBAT(bool is_wii);
|
||||
static bool RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume);
|
||||
static bool EmulatedBS2_GC(const DiscIO::VolumeDisc& volume);
|
||||
static bool EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume);
|
||||
static bool EmulatedBS2(bool is_wii, const DiscIO::VolumeDisc& volume);
|
||||
static bool RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool EmulatedBS2_GC(const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool EmulatedBS2(bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
|
||||
static bool Load_BS2(const std::string& boot_rom_filename);
|
||||
|
||||
static void SetupGCMemory();
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/RiivolutionPatcher.h"
|
||||
#include "DiscIO/VolumeDisc.h"
|
||||
|
||||
namespace
|
||||
|
@ -87,7 +88,8 @@ void CBoot::SetupBAT(bool is_wii)
|
|||
PowerPC::IBATUpdated();
|
||||
}
|
||||
|
||||
bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume)
|
||||
bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
const DiscIO::Partition partition = volume.GetGamePartition();
|
||||
|
||||
|
@ -148,6 +150,8 @@ bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume)
|
|||
ram_address, length);
|
||||
DVDRead(volume, dvd_offset, ram_address, length, partition);
|
||||
|
||||
DiscIO::Riivolution::ApplyApploaderMemoryPatches(riivolution_patches, ram_address, length);
|
||||
|
||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||
PowerPC::ppcState.gpr[4] = 0x81300008;
|
||||
PowerPC::ppcState.gpr[5] = 0x8130000c;
|
||||
|
@ -203,7 +207,8 @@ void CBoot::SetupGCMemory()
|
|||
// GameCube Bootstrap 2 HLE:
|
||||
// copy the apploader to 0x81200000
|
||||
// execute the apploader, function by function, using the above utility.
|
||||
bool CBoot::EmulatedBS2_GC(const DiscIO::VolumeDisc& volume)
|
||||
bool CBoot::EmulatedBS2_GC(const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
INFO_LOG_FMT(BOOT, "Faking GC BS2...");
|
||||
|
||||
|
@ -240,7 +245,7 @@ bool CBoot::EmulatedBS2_GC(const DiscIO::VolumeDisc& volume)
|
|||
// Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
|
||||
PowerPC::ppcState.gpr[13] = ntsc ? 0x81465320 : 0x814b4fc0;
|
||||
|
||||
return RunApploader(/*is_wii*/ false, volume);
|
||||
return RunApploader(/*is_wii*/ false, volume, riivolution_patches);
|
||||
}
|
||||
|
||||
static DiscIO::Region CodeRegion(char c)
|
||||
|
@ -436,7 +441,8 @@ static void WriteEmptyPlayRecord()
|
|||
// Wii Bootstrap 2 HLE:
|
||||
// copy the apploader to 0x81200000
|
||||
// execute the apploader
|
||||
bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume)
|
||||
bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
INFO_LOG_FMT(BOOT, "Faking Wii BS2...");
|
||||
if (volume.GetVolumeType() != DiscIO::Platform::WiiDisc)
|
||||
|
@ -493,7 +499,7 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume)
|
|||
|
||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||
|
||||
if (!RunApploader(/*is_wii*/ true, volume))
|
||||
if (!RunApploader(/*is_wii*/ true, volume, riivolution_patches))
|
||||
return false;
|
||||
|
||||
// The Apploader probably just overwrote values needed for RAM Override. Run this again!
|
||||
|
@ -508,7 +514,9 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume)
|
|||
|
||||
// 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(bool is_wii, const DiscIO::VolumeDisc& volume)
|
||||
bool CBoot::EmulatedBS2(bool is_wii, const DiscIO::VolumeDisc& volume,
|
||||
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
|
||||
{
|
||||
return is_wii ? EmulatedBS2_Wii(volume) : EmulatedBS2_GC(volume);
|
||||
return is_wii ? EmulatedBS2_Wii(volume, riivolution_patches) :
|
||||
EmulatedBS2_GC(volume, riivolution_patches);
|
||||
}
|
||||
|
|
|
@ -527,20 +527,23 @@ static std::vector<u8> GetMemoryPatchValue(const Patch& patch, const Memory& mem
|
|||
|
||||
static void ApplyMemoryPatch(const Patch& patch, const Memory& memory_patch)
|
||||
{
|
||||
if (memory_patch.m_offset == 0)
|
||||
return;
|
||||
|
||||
ApplyMemoryPatch(memory_patch.m_offset | 0x80000000, GetMemoryPatchValue(patch, memory_patch),
|
||||
memory_patch.m_original);
|
||||
}
|
||||
|
||||
static void ApplySearchMemoryPatch(const Patch& patch, const Memory& memory_patch)
|
||||
static void ApplySearchMemoryPatch(const Patch& patch, const Memory& memory_patch, u32 ram_start,
|
||||
u32 length)
|
||||
{
|
||||
if (memory_patch.m_original.empty())
|
||||
if (memory_patch.m_original.empty() || memory_patch.m_align == 0)
|
||||
return;
|
||||
|
||||
const u32 ram_size = ::Memory::GetRamSize();
|
||||
const u32 stride = memory_patch.m_align < 1 ? 1 : memory_patch.m_align;
|
||||
for (u32 i = 0; i < ram_size - (stride - 1); i += stride)
|
||||
const u32 stride = memory_patch.m_align;
|
||||
for (u32 i = 0; i < length - (stride - 1); i += stride)
|
||||
{
|
||||
const u32 address = i | 0x80000000;
|
||||
const u32 address = ram_start + i;
|
||||
if (MemoryMatchesAt(address, memory_patch.m_original))
|
||||
{
|
||||
ApplyMemoryPatch(address, GetMemoryPatchValue(patch, memory_patch), {});
|
||||
|
@ -549,22 +552,25 @@ static void ApplySearchMemoryPatch(const Patch& patch, const Memory& memory_patc
|
|||
}
|
||||
}
|
||||
|
||||
static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_patch)
|
||||
static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_patch, u32 ram_start,
|
||||
u32 length)
|
||||
{
|
||||
if (memory_patch.m_value.empty())
|
||||
if (memory_patch.m_offset == 0)
|
||||
return;
|
||||
const std::vector<u8> value = GetMemoryPatchValue(patch, memory_patch);
|
||||
if (value.empty())
|
||||
return;
|
||||
|
||||
const u32 ram_size = ::Memory::GetRamSize();
|
||||
for (u32 i = 0; i < ram_size; i += 4)
|
||||
for (u32 i = 0; i < length; i += 4)
|
||||
{
|
||||
// first find the pattern
|
||||
const u32 address = i | 0x80000000;
|
||||
if (MemoryMatchesAt(address, memory_patch.m_value))
|
||||
const u32 address = ram_start + i;
|
||||
if (MemoryMatchesAt(address, value))
|
||||
{
|
||||
for (; i < ram_size; i += 4)
|
||||
for (; i < length; i += 4)
|
||||
{
|
||||
// from the pattern find the next blr instruction
|
||||
const u32 blr_address = i | 0x80000000;
|
||||
const u32 blr_address = ram_start + i;
|
||||
auto blr = PowerPC::HostTryReadU32(blr_address);
|
||||
if (blr && blr->value == 0x4e800020)
|
||||
{
|
||||
|
@ -580,22 +586,40 @@ static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_pat
|
|||
}
|
||||
}
|
||||
|
||||
void ApplyPatchesToMemory(const std::vector<Patch>& patches)
|
||||
void ApplyGeneralMemoryPatches(const std::vector<Patch>& patches)
|
||||
{
|
||||
for (const auto& patch : patches)
|
||||
{
|
||||
for (const auto& memory : patch.m_memory_patches)
|
||||
{
|
||||
if (memory.m_ocarina)
|
||||
ApplyOcarinaMemoryPatch(patch, memory);
|
||||
else if (memory.m_search)
|
||||
ApplySearchMemoryPatch(patch, memory);
|
||||
continue;
|
||||
|
||||
if (memory.m_search)
|
||||
ApplySearchMemoryPatch(patch, memory, 0x80000000, ::Memory::GetRamSize());
|
||||
else
|
||||
ApplyMemoryPatch(patch, memory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyApploaderMemoryPatches(const std::vector<Patch>& patches, u32 ram_address, u32 ram_length)
|
||||
{
|
||||
for (const auto& patch : patches)
|
||||
{
|
||||
for (const auto& memory : patch.m_memory_patches)
|
||||
{
|
||||
if (!memory.m_ocarina && !memory.m_search)
|
||||
continue;
|
||||
|
||||
if (memory.m_ocarina)
|
||||
ApplyOcarinaMemoryPatch(patch, memory, ram_address, ram_length);
|
||||
else
|
||||
ApplySearchMemoryPatch(patch, memory, ram_address, ram_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<SavegameRedirect>
|
||||
ExtractSavegameRedirect(const std::vector<Patch>& riivolution_patches)
|
||||
{
|
||||
|
|
|
@ -68,7 +68,9 @@ private:
|
|||
void ApplyPatchesToFiles(const std::vector<Patch>& patches,
|
||||
std::vector<DiscIO::FSTBuilderNode>* fst,
|
||||
DiscIO::FSTBuilderNode* dol_node);
|
||||
void ApplyPatchesToMemory(const std::vector<Patch>& patches);
|
||||
void ApplyGeneralMemoryPatches(const std::vector<Patch>& patches);
|
||||
void ApplyApploaderMemoryPatches(const std::vector<Patch>& patches, u32 ram_address,
|
||||
u32 ram_length);
|
||||
std::optional<SavegameRedirect>
|
||||
ExtractSavegameRedirect(const std::vector<Patch>& riivolution_patches);
|
||||
} // namespace DiscIO::Riivolution
|
||||
|
|
Loading…
Reference in New Issue