Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #10127 from AdmiralCurtiss/riivolution
HLE Riivolution patch support
  • Loading branch information
leoetlino committed Oct 23, 2021
2 parents b997048 + 4f82810 commit 5d5f019
Show file tree
Hide file tree
Showing 37 changed files with 2,915 additions and 227 deletions.
1 change: 1 addition & 0 deletions Source/Core/Common/CommonPaths.h
Expand Up @@ -47,6 +47,7 @@
#define SCREENSHOTS_DIR "ScreenShots"
#define LOAD_DIR "Load"
#define HIRES_TEXTURES_DIR "Textures"
#define RIIVOLUTION_DIR "Riivolution"
#define DUMP_DIR "Dump"
#define DUMP_TEXTURES_DIR "Textures"
#define DUMP_FRAMES_DIR "Frames"
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Common/FileUtil.cpp
Expand Up @@ -943,6 +943,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
s_user_paths[D_SCREENSHOTS_IDX] = s_user_paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
s_user_paths[D_LOAD_IDX] = s_user_paths[D_USER_IDX] + LOAD_DIR DIR_SEP;
s_user_paths[D_HIRESTEXTURES_IDX] = s_user_paths[D_LOAD_IDX] + HIRES_TEXTURES_DIR DIR_SEP;
s_user_paths[D_RIIVOLUTION_IDX] = s_user_paths[D_LOAD_IDX] + RIIVOLUTION_DIR DIR_SEP;
s_user_paths[D_DUMP_IDX] = s_user_paths[D_USER_IDX] + DUMP_DIR DIR_SEP;
s_user_paths[D_DUMPFRAMES_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
s_user_paths[D_DUMPOBJECTS_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_OBJECTS_DIR DIR_SEP;
Expand Down Expand Up @@ -1035,6 +1036,7 @@ static void RebuildUserDirectories(unsigned int dir_index)

case D_LOAD_IDX:
s_user_paths[D_HIRESTEXTURES_IDX] = s_user_paths[D_LOAD_IDX] + HIRES_TEXTURES_DIR DIR_SEP;
s_user_paths[D_RIIVOLUTION_IDX] = s_user_paths[D_LOAD_IDX] + RIIVOLUTION_DIR DIR_SEP;
s_user_paths[D_DYNAMICINPUT_IDX] = s_user_paths[D_LOAD_IDX] + DYNAMICINPUT_DIR DIR_SEP;
break;
}
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Common/FileUtil.h
Expand Up @@ -41,6 +41,7 @@ enum
D_STATESAVES_IDX,
D_SCREENSHOTS_IDX,
D_HIRESTEXTURES_IDX,
D_RIIVOLUTION_IDX,
D_DUMP_IDX,
D_DUMPFRAMES_IDX,
D_DUMPOBJECTS_IDX,
Expand Down
57 changes: 54 additions & 3 deletions Source/Core/Core/Boot/Boot.cpp
Expand Up @@ -57,6 +57,9 @@ namespace fs = std::filesystem;
#include "Core/PowerPC/PowerPC.h"

#include "DiscIO/Enums.h"
#include "DiscIO/GameModDescriptor.h"
#include "DiscIO/RiivolutionParser.h"
#include "DiscIO/RiivolutionPatcher.h"
#include "DiscIO/VolumeDisc.h"
#include "DiscIO/VolumeWad.h"

Expand Down Expand Up @@ -216,6 +219,31 @@ BootParameters::GenerateFromFile(std::vector<std::string> paths,
return std::make_unique<BootParameters>(std::move(*wad), savestate_path);
}

if (extension == ".json")
{
auto descriptor = DiscIO::ParseGameModDescriptorFile(path);
if (descriptor)
{
auto boot_params = GenerateFromFile(descriptor->base_file, savestate_path);
if (!boot_params)
{
PanicAlertFmtT("Could not recognize file {0}", descriptor->base_file);
return nullptr;
}

if (descriptor->riivolution && std::holds_alternative<Disc>(boot_params->parameters))
{
const auto& volume = *std::get<Disc>(boot_params->parameters).volume;
AddRiivolutionPatches(boot_params.get(),
DiscIO::Riivolution::GenerateRiivolutionPatchesFromGameModDescriptor(
*descriptor->riivolution, volume.GetGameID(),
volume.GetRevision(), volume.GetDiscNumber()));
}

return boot_params;
}
}

PanicAlertFmtT("Could not recognize file {0}", path);
return {};
}
Expand Down Expand Up @@ -422,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);
Expand All @@ -432,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();
Expand Down Expand Up @@ -542,11 +573,14 @@ 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::ApplyGeneralMemoryPatches(boot->riivolution_patches);

return true;
}

Expand Down Expand Up @@ -604,3 +638,20 @@ void CreateSystemMenuTitleDirs()
const auto es = IOS::HLE::GetIOS()->GetES();
es->CreateTitleDirectories(Titles::SYSTEM_MENU, IOS::SYSMENU_GID);
}

void AddRiivolutionPatches(BootParameters* boot_params,
std::vector<DiscIO::Riivolution::Patch> riivolution_patches)
{
if (riivolution_patches.empty())
return;
if (!std::holds_alternative<BootParameters::Disc>(boot_params->parameters))
return;

auto& disc = std::get<BootParameters::Disc>(boot_params->parameters);
disc.volume = DiscIO::CreateDisc(DiscIO::DirectoryBlobReader::Create(
std::move(disc.volume),
[&](std::vector<DiscIO::FSTBuilderNode>* fst, DiscIO::FSTBuilderNode* dol_node) {
DiscIO::Riivolution::ApplyPatchesToFiles(riivolution_patches, fst, dol_node);
}));
boot_params->riivolution_patches = std::move(riivolution_patches);
}
17 changes: 13 additions & 4 deletions Source/Core/Core/Boot/Boot.h
Expand Up @@ -15,6 +15,7 @@
#include "Core/IOS/IOSC.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
#include "DiscIO/RiivolutionParser.h"
#include "DiscIO/VolumeDisc.h"
#include "DiscIO/VolumeWad.h"

Expand Down Expand Up @@ -78,6 +79,7 @@ struct BootParameters
BootParameters(Parameters&& parameters_, const std::optional<std::string>& savestate_path_ = {});

Parameters parameters;
std::vector<DiscIO::Riivolution::Patch> riivolution_patches;
std::optional<std::string> savestate_path;
bool delete_savestate = false;
};
Expand Down Expand Up @@ -113,10 +115,14 @@ class CBoot

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();
Expand Down Expand Up @@ -161,3 +167,6 @@ void UpdateStateFlags(std::function<void(StateFlags*)> update_function);
/// Normally, this is automatically done by ES when the System Menu is installed,
/// but we cannot rely on this because we don't require any system titles to be installed.
void CreateSystemMenuTitleDirs();

void AddRiivolutionPatches(BootParameters* boot_params,
std::vector<DiscIO::Riivolution::Patch> riivolution_patches);
22 changes: 15 additions & 7 deletions Source/Core/Core/Boot/Boot_BS2Emu.cpp
Expand Up @@ -33,6 +33,7 @@
#include "Core/PowerPC/PowerPC.h"

#include "DiscIO/Enums.h"
#include "DiscIO/RiivolutionPatcher.h"
#include "DiscIO/VolumeDisc.h"

namespace
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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...");

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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!
Expand All @@ -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);
}
4 changes: 4 additions & 0 deletions Source/Core/Core/BootManager.cpp
Expand Up @@ -418,6 +418,10 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
if (StartUp.bWii && DiscIO::IsNTSC(StartUp.m_region) && Config::Get(Config::SYSCONF_PAL60))
Config::SetCurrent(Config::SYSCONF_PAL60, false);

// Disable loading time emulation for Riivolution-patched games until we have proper emulation.
if (!boot->riivolution_patches.empty())
StartUp.bFastDiscSpeed = true;

Core::UpdateWantDeterminism(/*initial*/ true);

if (StartUp.bWii)
Expand Down
8 changes: 7 additions & 1 deletion Source/Core/Core/Core.cpp
Expand Up @@ -73,6 +73,8 @@
#include "Core/MemoryWatcher.h"
#endif

#include "DiscIO/RiivolutionPatcher.h"

#include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/GCAdapter.h"
Expand Down Expand Up @@ -603,6 +605,10 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
else
cpuThreadFunc = CpuThread;

std::optional<DiscIO::Riivolution::SavegameRedirect> savegame_redirect = std::nullopt;
if (SConfig::GetInstance().bWii)
savegame_redirect = DiscIO::Riivolution::ExtractSavegameRedirect(boot->riivolution_patches);

if (!CBoot::BootUp(std::move(boot)))
return;

Expand All @@ -611,7 +617,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
// with the correct title context since save copying requires title directories to exist.
Common::ScopeGuard wiifs_guard{&Core::CleanUpWiiFileSystemContents};
if (SConfig::GetInstance().bWii)
Core::InitializeWiiFileSystemContents();
Core::InitializeWiiFileSystemContents(savegame_redirect);
else
wiifs_guard.Dismiss();

Expand Down
14 changes: 13 additions & 1 deletion Source/Core/Core/IOS/FS/FileSystem.h
Expand Up @@ -72,6 +72,15 @@ enum class SeekMode : u32

using FileAttribute = u8;

struct NandRedirect
{
// A Wii FS path, eg. "/title/00010000/534d4e45/data".
std::string source_path;

// An absolute host filesystem path the above should be redirected to.
std::string target_path;
};

struct Modes
{
Mode owner, group, other;
Expand Down Expand Up @@ -239,6 +248,8 @@ class FileSystem
virtual Result<NandStats> GetNandStats() = 0;
/// Get usage information about a directory (used cluster and inode counts).
virtual Result<DirectoryStats> GetDirectoryStats(const std::string& path) = 0;

virtual void SetNandRedirects(std::vector<NandRedirect> nand_redirects) = 0;
};

template <typename T>
Expand Down Expand Up @@ -269,7 +280,8 @@ enum class Location
Session,
};

std::unique_ptr<FileSystem> MakeFileSystem(Location location = Location::Session);
std::unique_ptr<FileSystem> MakeFileSystem(Location location = Location::Session,
std::vector<NandRedirect> nand_redirects = {});

/// Convert a FS result code to an IOS error code.
IOS::HLE::ReturnCode ConvertResult(ResultCode code);
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/IOS/FS/FileSystemCommon.cpp
Expand Up @@ -28,11 +28,12 @@ SplitPathResult SplitPathAndBasename(std::string_view path)
std::string(path.substr(last_separator + 1))};
}

std::unique_ptr<FileSystem> MakeFileSystem(Location location)
std::unique_ptr<FileSystem> MakeFileSystem(Location location,
std::vector<NandRedirect> nand_redirects)
{
const std::string nand_root =
File::GetUserPath(location == Location::Session ? D_SESSION_WIIROOT_IDX : D_WIIROOT_IDX);
return std::make_unique<HostFileSystem>(nand_root);
return std::make_unique<HostFileSystem>(nand_root, std::move(nand_redirects));
}

IOS::HLE::ReturnCode ConvertResult(ResultCode code)
Expand Down

0 comments on commit 5d5f019

Please sign in to comment.