RiivolutionParser: Add more patch types
This commit is contained in:
parent
19c71db782
commit
09bfad7ae0
|
@ -96,6 +96,11 @@ static GameModDescriptorRiivolution ParseRiivolutionObject(const std::string& js
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (element_key == "force-console-ng-id" && element_value.is<double>())
|
||||
{
|
||||
// JSON contains hardcoded console ID, use that instead of the one from the NAND
|
||||
r.console_ng_id = MathUtil::SaturatingCast<u32>(element_value.get<double>());
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ struct GameModDescriptorRiivolutionPatch
|
|||
struct GameModDescriptorRiivolution
|
||||
{
|
||||
std::vector<GameModDescriptorRiivolutionPatch> patches;
|
||||
u32 console_ng_id = 0;
|
||||
};
|
||||
|
||||
struct GameModDescriptor
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Common/FileSearch.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/IOFile.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "DiscIO/GameModDescriptor.h"
|
||||
#include "DiscIO/RiivolutionPatcher.h"
|
||||
|
@ -87,6 +88,12 @@ std::optional<Disc> ParseString(std::string_view xml, std::string xml_path)
|
|||
return std::nullopt;
|
||||
const std::string default_root = wiidisc.attribute("root").as_string();
|
||||
|
||||
const auto riifs_server = wiidisc.child("network");
|
||||
if (riifs_server)
|
||||
{
|
||||
WARN_LOG_FMT(IOS, "Riivolution patch tries to use a RiiFS server - this is not supported.");
|
||||
}
|
||||
|
||||
const auto id = wiidisc.child("id");
|
||||
if (id)
|
||||
{
|
||||
|
@ -210,6 +217,14 @@ std::optional<Disc> ParseString(std::string_view xml, std::string xml_path)
|
|||
memory.m_search = patch_subnode.attribute("search").as_bool(false);
|
||||
memory.m_align = patch_subnode.attribute("align").as_uint(1);
|
||||
}
|
||||
else if (patch_name == "shift" || patch_name == "dlc")
|
||||
{
|
||||
// "shift" seems to be intended to move a file on disc ("source") to another location
|
||||
// ("destination"), but I'm not sure how exactly it needs to be implemented. Probably needs
|
||||
// to be checked in the Riivolution source code. Same for "dlc", which is used to redirect
|
||||
// DLC read accesses to SD/USB.
|
||||
WARN_LOG_FMT(IOS, "Unsupported Riivolution patch type '{}'", patch_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,8 +271,18 @@ bool Disc::IsValidForGame(const std::string& game_id, std::optional<u16> revisio
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<Patch> Disc::GeneratePatches(const std::string& game_id) const
|
||||
std::vector<Patch> Disc::GeneratePatches(const std::string& game_id, u32 ng_id) const
|
||||
{
|
||||
IOS::HLE::Kernel m_ios;
|
||||
if (ng_id == 0)
|
||||
{
|
||||
// If the patch did not include a hard-coded device ID, use the one from the emulated console.
|
||||
ng_id = m_ios.GetIOSC().GetDeviceId();
|
||||
}
|
||||
|
||||
const std::string ng_id_str = fmt::format("{0:08X}", ng_id);
|
||||
|
||||
const std::string_view ng_console_id = std::string_view(ng_id_str);
|
||||
const std::string_view game_id_full = std::string_view(game_id);
|
||||
const std::string_view game_id_no_region = game_id_full.substr(0, 3);
|
||||
const std::string_view game_region = game_id_full.substr(3, 1);
|
||||
|
@ -308,6 +333,7 @@ std::vector<Patch> Disc::GeneratePatches(const std::string& game_id) const
|
|||
continue;
|
||||
|
||||
std::vector<std::pair<std::string, std::string_view>> replacements;
|
||||
replacements.emplace_back(std::pair{"{$__ngid}", ng_console_id});
|
||||
replacements.emplace_back(std::pair{"{$__gameid}", game_id_no_region});
|
||||
replacements.emplace_back(std::pair{"{$__region}", game_region});
|
||||
replacements.emplace_back(std::pair{"{$__maker}", game_developer});
|
||||
|
@ -374,7 +400,7 @@ std::vector<Patch> GenerateRiivolutionPatchesFromGameModDescriptor(
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& p : parsed->GeneratePatches(game_id))
|
||||
for (auto& p : parsed->GeneratePatches(game_id, descriptor.console_ng_id))
|
||||
{
|
||||
p.m_file_data_loader =
|
||||
std::make_shared<FileDataLoaderHostFS>(patch_info.root, parsed->m_xml_path, p.m_root);
|
||||
|
@ -406,7 +432,7 @@ std::vector<Patch> GenerateRiivolutionPatchesFromConfig(const std::string root_d
|
|||
if (config)
|
||||
ApplyConfigDefaults(&*parsed, *config);
|
||||
|
||||
for (auto& patch : parsed->GeneratePatches(game_id))
|
||||
for (auto& patch : parsed->GeneratePatches(game_id, 0))
|
||||
{
|
||||
patch.m_file_data_loader =
|
||||
std::make_shared<FileDataLoaderHostFS>(root_directory, parsed->m_xml_path, patch.m_root);
|
||||
|
|
|
@ -195,7 +195,7 @@ struct Disc
|
|||
|
||||
// Transforms an abstract XML-parsed patch set into a concrete one, with only the selected
|
||||
// patches applied and all placeholders replaced.
|
||||
std::vector<Patch> GeneratePatches(const std::string& game_id) const;
|
||||
std::vector<Patch> GeneratePatches(const std::string& game_id, u32 ng_id) const;
|
||||
};
|
||||
|
||||
// Config format that remembers which patches are enabled/disabled for the next run.
|
||||
|
|
|
@ -271,7 +271,7 @@ void RiivolutionBootWidget::BootGame()
|
|||
m_patches.clear();
|
||||
for (const auto& disc : m_discs)
|
||||
{
|
||||
auto patches = disc.disc.GeneratePatches(m_game_id);
|
||||
auto patches = disc.disc.GeneratePatches(m_game_id, 0);
|
||||
|
||||
// set the file loader for each patch
|
||||
for (auto& patch : patches)
|
||||
|
@ -296,7 +296,7 @@ void RiivolutionBootWidget::SaveAsPreset()
|
|||
for (const auto& disc : m_discs)
|
||||
{
|
||||
// filter out XMLs that don't actually contribute to the preset
|
||||
auto patches = disc.disc.GeneratePatches(m_game_id);
|
||||
auto patches = disc.disc.GeneratePatches(m_game_id, 0);
|
||||
if (patches.empty())
|
||||
continue;
|
||||
|
||||
|
|
Loading…
Reference in New Issue