This commit is contained in:
Tygyh 2025-04-19 16:11:05 +00:00 committed by GitHub
commit 08c258884c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 179 additions and 179 deletions

View File

@ -96,9 +96,9 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer, DirectoryBlobReade
if (std::holds_alternative<ContentFile>(m_content_source))
{
const auto& content = std::get<ContentFile>(m_content_source);
File::IOFile file(content.m_filename, "rb");
if (!file.Seek(content.m_offset + offset_in_content, File::SeekOrigin::Begin) ||
const auto& [filename, content_source_offset] = std::get<ContentFile>(m_content_source);
File::IOFile file(filename, "rb");
if (!file.Seek(content_source_offset + offset_in_content, File::SeekOrigin::Begin) ||
!file.ReadBytes(*buffer, bytes_to_read))
{
return false;
@ -111,27 +111,28 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer, DirectoryBlobReade
}
else if (std::holds_alternative<ContentPartition>(m_content_source))
{
const auto& content = std::get<ContentPartition>(m_content_source);
const auto& [content_source_offset, partition_data_offset] =
std::get<ContentPartition>(m_content_source);
const u64 decrypted_size = m_size * VolumeWii::BLOCK_DATA_SIZE / VolumeWii::BLOCK_TOTAL_SIZE;
if (!blob->EncryptPartitionData(content.m_offset + offset_in_content, bytes_to_read, *buffer,
content.m_partition_data_offset, decrypted_size))
if (!blob->EncryptPartitionData(content_source_offset + offset_in_content, bytes_to_read,
*buffer, partition_data_offset, decrypted_size))
{
return false;
}
}
else if (std::holds_alternative<ContentVolume>(m_content_source))
{
const auto& source = std::get<ContentVolume>(m_content_source);
if (!blob->GetWrappedVolume()->Read(source.m_offset + offset_in_content, bytes_to_read,
*buffer, source.m_partition))
const auto& [content_source_offset, partition] = std::get<ContentVolume>(m_content_source);
if (!blob->GetWrappedVolume()->Read(content_source_offset + offset_in_content, bytes_to_read,
*buffer, partition))
{
return false;
}
}
else if (std::holds_alternative<ContentFixedByte>(m_content_source))
{
const ContentFixedByte& source = std::get<ContentFixedByte>(m_content_source);
std::fill_n(*buffer, bytes_to_read, source.m_byte);
const auto& [byte] = std::get<ContentFixedByte>(m_content_source);
std::fill_n(*buffer, bytes_to_read, byte);
}
else
{
@ -867,8 +868,8 @@ static std::vector<u8> ExtractNodeToVector(std::vector<FSTBuilderNode>* nodes, v
return data;
DiscContentContainer tmp;
for (auto& content : it->GetFileContent())
tmp.Add(content.m_offset, content.m_size, std::move(content.m_source));
for (auto& [offset, size, source] : it->GetFileContent())
tmp.Add(offset, size, std::move(source));
data.resize(it->m_size);
tmp.Read(0, it->m_size, data.data(), blob);
return data;
@ -1045,8 +1046,8 @@ u64 DirectoryBlobPartition::SetDOLFromFile(const std::string& path, u64 dol_addr
u64 DirectoryBlobPartition::SetDOL(FSTBuilderNode dol_node, u64 dol_address,
std::vector<u8>* disc_header)
{
for (auto& content : dol_node.GetFileContent())
m_contents.Add(dol_address + content.m_offset, content.m_size, std::move(content.m_source));
for (auto& [offset, size, source] : dol_node.GetFileContent())
m_contents.Add(dol_address + offset, size, std::move(source));
Write32(static_cast<u32>(dol_address >> m_address_shift), 0x0420, disc_header);
@ -1222,10 +1223,9 @@ void DirectoryBlobPartition::WriteDirectory(std::vector<u8>* fst_data,
// write entry to virtual disc
auto& contents = entry.GetFileContent();
for (BuilderContentSource& content : contents)
for (auto& [offset, size, source] : contents)
{
m_contents.Add(*data_offset + content.m_offset, content.m_size,
std::move(content.m_source));
m_contents.Add(*data_offset + offset, size, std::move(source));
}
// 32 KiB aligned - many games are fine with less alignment, but not all

View File

@ -49,17 +49,17 @@ ParseRiivolutionOptions(const picojson::array& array)
if (!option_object.is<picojson::object>())
continue;
auto& option = options.emplace_back();
auto& [section_name, option_id, option_name, choice] = options.emplace_back();
for (const auto& [key, value] : option_object.get<picojson::object>())
{
if (key == "section-name" && value.is<std::string>())
option.section_name = value.get<std::string>();
section_name = value.get<std::string>();
else if (key == "option-id" && value.is<std::string>())
option.option_id = value.get<std::string>();
option_id = value.get<std::string>();
else if (key == "option-name" && value.is<std::string>())
option.option_name = value.get<std::string>();
option_name = value.get<std::string>();
else if (key == "choice" && value.is<double>())
option.choice = MathUtil::SaturatingCast<u32>(value.get<double>());
choice = MathUtil::SaturatingCast<u32>(value.get<double>());
}
}
return options;
@ -78,15 +78,15 @@ static GameModDescriptorRiivolution ParseRiivolutionObject(const std::string& js
if (!patch_object.is<picojson::object>())
continue;
auto& patch = r.patches.emplace_back();
auto& [xml, root, options] = r.patches.emplace_back();
for (const auto& [key, value] : patch_object.get<picojson::object>())
{
if (key == "xml" && value.is<std::string>())
patch.xml = MakeAbsolute(json_directory, value.get<std::string>());
xml = MakeAbsolute(json_directory, value.get<std::string>());
else if (key == "root" && value.is<std::string>())
patch.root = MakeAbsolute(json_directory, value.get<std::string>());
root = MakeAbsolute(json_directory, value.get<std::string>());
else if (key == "options" && value.is<picojson::array>())
patch.options = ParseRiivolutionOptions(value.get<picojson::array>());
options = ParseRiivolutionOptions(value.get<picojson::array>());
}
}
}
@ -152,26 +152,26 @@ static picojson::object
WriteGameModDescriptorRiivolution(const GameModDescriptorRiivolution& riivolution)
{
picojson::array json_patches;
for (const auto& patch : riivolution.patches)
for (const auto& [xml, root, options] : riivolution.patches)
{
picojson::object json_patch;
if (!patch.xml.empty())
json_patch["xml"] = picojson::value(patch.xml);
if (!patch.root.empty())
json_patch["root"] = picojson::value(patch.root);
if (!patch.options.empty())
if (!xml.empty())
json_patch["xml"] = picojson::value(xml);
if (!root.empty())
json_patch["root"] = picojson::value(root);
if (!options.empty())
{
picojson::array json_options;
for (const auto& option : patch.options)
for (const auto& [section_name, option_id, option_name, choice] : options)
{
picojson::object json_option;
if (!option.section_name.empty())
json_option["section-name"] = picojson::value(option.section_name);
if (!option.option_id.empty())
json_option["option-id"] = picojson::value(option.option_id);
if (!option.option_name.empty())
json_option["option-name"] = picojson::value(option.option_name);
json_option["choice"] = picojson::value(static_cast<double>(option.choice));
if (!section_name.empty())
json_option["section-name"] = picojson::value(section_name);
if (!option_id.empty())
json_option["option-id"] = picojson::value(option_id);
if (!option_name.empty())
json_option["option-name"] = picojson::value(option_name);
json_option["choice"] = picojson::value(static_cast<double>(choice));
json_options.emplace_back(std::move(json_option));
}
json_patch["options"] = picojson::value(std::move(json_options));

View File

@ -238,18 +238,18 @@ bool NANDImporter::ExtractCertificates()
{"/rootca.pem", {{0x30, 0x82, 0x03, 0x7D}}},
}};
for (const PEMCertificate& certificate : certificates)
for (const auto& [filename, search_bytes] : certificates)
{
const auto search_result = std::ranges::search(content_bytes, certificate.search_bytes);
const auto search_result = std::ranges::search(content_bytes, search_bytes);
if (search_result.empty())
{
ERROR_LOG_FMT(DISCIO, "ExtractCertificates: Could not find offset for certficate '{}'",
certificate.filename);
filename);
return false;
}
const std::string pem_file_path = m_nand_root + std::string(certificate.filename);
const std::string pem_file_path = m_nand_root + std::string(filename);
const ptrdiff_t certificate_offset =
std::distance(content_bytes.begin(), search_result.begin());
constexpr int min_offset = 2;
@ -271,8 +271,8 @@ bool NANDImporter::ExtractCertificates()
certificate_size, available_size);
return false;
}
INFO_LOG_FMT(DISCIO, "ExtractCertificates: '{}' offset: {:#x} size: {:#x}",
certificate.filename, certificate_offset, certificate_size);
INFO_LOG_FMT(DISCIO, "ExtractCertificates: '{}' offset: {:#x} size: {:#x}", filename,
certificate_offset, certificate_size);
File::IOFile pem_file(pem_file_path, "wb");
if (!pem_file.WriteBytes(&content_bytes[certificate_offset], certificate_size))

View File

@ -59,9 +59,8 @@ std::vector<NFSLBARange> NFSFileReader::GetLBARanges(const NFSHeader& header)
for (size_t i = 0; i < lba_range_count; ++i)
{
const NFSLBARange& unswapped_lba_range = header.lba_ranges[i];
lba_ranges.push_back(NFSLBARange{Common::swap32(unswapped_lba_range.start_block),
Common::swap32(unswapped_lba_range.num_blocks)});
const auto& [start_block, num_blocks] = header.lba_ranges[i];
lba_ranges.push_back(NFSLBARange{Common::swap32(start_block), Common::swap32(num_blocks)});
}
return lba_ranges;
@ -108,8 +107,8 @@ std::vector<File::IOFile> NFSFileReader::OpenFiles(const std::string& directory,
u64 NFSFileReader::CalculateExpectedRawSize(const std::vector<NFSLBARange>& lba_ranges)
{
u64 total_blocks = 0;
for (const NFSLBARange& range : lba_ranges)
total_blocks += range.num_blocks;
for (const auto& [start_block, num_blocks] : lba_ranges)
total_blocks += num_blocks;
return sizeof(NFSHeader) + total_blocks * BLOCK_SIZE;
}
@ -117,8 +116,8 @@ u64 NFSFileReader::CalculateExpectedRawSize(const std::vector<NFSLBARange>& lba_
u64 NFSFileReader::CalculateExpectedDataSize(const std::vector<NFSLBARange>& lba_ranges)
{
u32 greatest_block_index = 0;
for (const NFSLBARange& range : lba_ranges)
greatest_block_index = std::max(greatest_block_index, range.start_block + range.num_blocks);
for (const auto& [start_block, num_blocks] : lba_ranges)
greatest_block_index = std::max(greatest_block_index, start_block + num_blocks);
return u64(greatest_block_index) * BLOCK_SIZE;
}
@ -188,15 +187,14 @@ u64 NFSFileReader::ToPhysicalBlockIndex(u64 logical_block_index)
{
u64 physical_blocks_so_far = 0;
for (const NFSLBARange& range : m_lba_ranges)
for (const auto& [start_block, num_blocks] : m_lba_ranges)
{
if (logical_block_index >= range.start_block &&
logical_block_index < range.start_block + range.num_blocks)
if (logical_block_index >= start_block && logical_block_index < start_block + num_blocks)
{
return physical_blocks_so_far + (logical_block_index - range.start_block);
return physical_blocks_so_far + (logical_block_index - start_block);
}
physical_blocks_so_far += range.num_blocks;
physical_blocks_so_far += num_blocks;
}
return std::numeric_limits<u64>::max();

View File

@ -118,25 +118,25 @@ std::optional<Disc> ParseString(std::string_view xml, std::string xml_path)
{
for (const auto& section_node : options.children("section"))
{
Section& section = disc.m_sections.emplace_back();
section.m_name = section_node.attribute("name").as_string();
auto& [section_name, section_options] = disc.m_sections.emplace_back();
section_name = section_node.attribute("name").as_string();
for (const auto& option_node : section_node.children("option"))
{
Option& option = section.m_options.emplace_back();
option.m_id = option_node.attribute("id").as_string();
option.m_name = option_node.attribute("name").as_string();
option.m_selected_choice = option_node.attribute("default").as_uint(0);
auto& [option_name, option_id, choices, selected_choice] = section_options.emplace_back();
option_id = option_node.attribute("id").as_string();
option_name = option_node.attribute("name").as_string();
selected_choice = option_node.attribute("default").as_uint(0);
auto option_params = ReadParams(option_node);
for (const auto& choice_node : option_node.children("choice"))
{
Choice& choice = option.m_choices.emplace_back();
choice.m_name = choice_node.attribute("name").as_string();
auto& [choice_name, patch_references] = choices.emplace_back();
choice_name = choice_node.attribute("name").as_string();
auto choice_params = ReadParams(choice_node, option_params);
for (const auto& patchref_node : choice_node.children("patch"))
{
PatchReference& patchref = choice.m_patch_references.emplace_back();
patchref.m_id = patchref_node.attribute("id").as_string();
patchref.m_params = ReadParams(patchref_node, choice_params);
auto& [patch_reference_id, params] = patch_references.emplace_back();
patch_reference_id = patchref_node.attribute("id").as_string();
params = ReadParams(patchref_node, choice_params);
}
}
}
@ -144,17 +144,17 @@ std::optional<Disc> ParseString(std::string_view xml, std::string xml_path)
for (const auto& macro_node : options.children("macros"))
{
const std::string macro_id = macro_node.attribute("id").as_string();
for (auto& section : disc.m_sections)
for (auto& [name, section_options] : disc.m_sections)
{
auto option_to_clone = std::ranges::find(section.m_options, macro_id, &Option::m_id);
if (option_to_clone == section.m_options.end())
auto option_to_clone = std::ranges::find(section_options, macro_id, &Option::m_id);
if (option_to_clone == section_options.end())
continue;
Option cloned_option = *option_to_clone;
cloned_option.m_name = macro_node.attribute("name").as_string();
for (auto& choice : cloned_option.m_choices)
for (auto& patch_ref : choice.m_patch_references)
patch_ref.m_params = ReadParams(macro_node, patch_ref.m_params);
for (auto& [choice_name, patch_references] : cloned_option.m_choices)
for (auto& [patch_reference_id, params] : patch_references)
params = ReadParams(macro_node, params);
}
}
}
@ -173,44 +173,46 @@ std::optional<Disc> ParseString(std::string_view xml, std::string xml_path)
const std::string_view patch_name(patch_subnode.name());
if (patch_name == "file" || patch_name == "dolphin_sys_file")
{
auto& file = patch_name == "dolphin_sys_file" ? patch.m_sys_file_patches.emplace_back() :
patch.m_file_patches.emplace_back();
file.m_disc = patch_subnode.attribute("disc").as_string();
file.m_external = patch_subnode.attribute("external").as_string();
file.m_resize = patch_subnode.attribute("resize").as_bool(true);
file.m_create = patch_subnode.attribute("create").as_bool(false);
file.m_offset = patch_subnode.attribute("offset").as_uint(0);
file.m_fileoffset = patch_subnode.attribute("fileoffset").as_uint(0);
file.m_length = patch_subnode.attribute("length").as_uint(0);
auto& [patch_disc, external, resize, create, offset, fileoffset, length] =
patch_name == "dolphin_sys_file" ? patch.m_sys_file_patches.emplace_back() :
patch.m_file_patches.emplace_back();
patch_disc = patch_subnode.attribute("disc").as_string();
external = patch_subnode.attribute("external").as_string();
resize = patch_subnode.attribute("resize").as_bool(true);
create = patch_subnode.attribute("create").as_bool(false);
offset = patch_subnode.attribute("offset").as_uint(0);
fileoffset = patch_subnode.attribute("fileoffset").as_uint(0);
length = patch_subnode.attribute("length").as_uint(0);
}
else if (patch_name == "folder" || patch_name == "dolphin_sys_folder")
{
auto& folder = patch_name == "dolphin_sys_folder" ?
patch.m_sys_folder_patches.emplace_back() :
patch.m_folder_patches.emplace_back();
folder.m_disc = patch_subnode.attribute("disc").as_string();
folder.m_external = patch_subnode.attribute("external").as_string();
folder.m_resize = patch_subnode.attribute("resize").as_bool(true);
folder.m_create = patch_subnode.attribute("create").as_bool(false);
folder.m_recursive = patch_subnode.attribute("recursive").as_bool(true);
folder.m_length = patch_subnode.attribute("length").as_uint(0);
auto& [patch_disc, external, resize, create, recursive, length] =
patch_name == "dolphin_sys_folder" ? patch.m_sys_folder_patches.emplace_back() :
patch.m_folder_patches.emplace_back();
patch_disc = patch_subnode.attribute("disc").as_string();
external = patch_subnode.attribute("external").as_string();
resize = patch_subnode.attribute("resize").as_bool(true);
create = patch_subnode.attribute("create").as_bool(false);
recursive = patch_subnode.attribute("recursive").as_bool(true);
length = patch_subnode.attribute("length").as_uint(0);
}
else if (patch_name == "savegame")
{
auto& savegame = patch.m_savegame_patches.emplace_back();
savegame.m_external = patch_subnode.attribute("external").as_string();
savegame.m_clone = patch_subnode.attribute("clone").as_bool(true);
auto& [external, clone] = patch.m_savegame_patches.emplace_back();
external = patch_subnode.attribute("external").as_string();
clone = patch_subnode.attribute("clone").as_bool(true);
}
else if (patch_name == "memory")
{
auto& memory = patch.m_memory_patches.emplace_back();
memory.m_offset = patch_subnode.attribute("offset").as_uint(0);
memory.m_value = ReadHexString(patch_subnode.attribute("value").as_string());
memory.m_valuefile = patch_subnode.attribute("valuefile").as_string();
memory.m_original = ReadHexString(patch_subnode.attribute("original").as_string());
memory.m_ocarina = patch_subnode.attribute("ocarina").as_bool(false);
memory.m_search = patch_subnode.attribute("search").as_bool(false);
memory.m_align = patch_subnode.attribute("align").as_uint(1);
auto& [offset, value, valuefile, original, ocarina, search, align] =
patch.m_memory_patches.emplace_back();
offset = patch_subnode.attribute("offset").as_uint(0);
value = ReadHexString(patch_subnode.attribute("value").as_string());
valuefile = patch_subnode.attribute("valuefile").as_string();
original = ReadHexString(patch_subnode.attribute("original").as_string());
ocarina = patch_subnode.attribute("ocarina").as_bool(false);
search = patch_subnode.attribute("search").as_bool(false);
align = patch_subnode.attribute("align").as_uint(1);
}
}
}
@ -273,13 +275,13 @@ std::vector<Patch> Disc::GeneratePatches(const std::string& game_id) const
while (!sv.empty())
{
bool replaced = false;
for (const auto& r : replacements)
for (const auto& [first, second] : replacements)
{
if (sv.starts_with(r.first))
if (sv.starts_with(first))
{
for (char c : r.second)
for (char c : second)
result.push_back(c);
sv = sv.substr(r.first.size());
sv = sv.substr(first.size());
replaced = true;
break;
}
@ -294,17 +296,17 @@ std::vector<Patch> Disc::GeneratePatches(const std::string& game_id) const
// Take only selected patches, replace placeholders in all strings, and return them.
std::vector<Patch> active_patches;
for (const auto& section : m_sections)
for (const auto& [name, options] : m_sections)
{
for (const auto& option : section.m_options)
for (const auto& option : options)
{
const u32 selected = option.m_selected_choice;
if (selected == 0 || selected > option.m_choices.size())
continue;
const Choice& choice = option.m_choices[selected - 1];
for (const auto& patch_ref : choice.m_patch_references)
const auto& [choice_name, patch_references] = option.m_choices[selected - 1];
for (const auto& [id, params] : patch_references)
{
const auto patch = std::ranges::find(m_patches, patch_ref.m_id, &Patch::m_id);
const auto patch = std::ranges::find(m_patches, id, &Patch::m_id);
if (patch == m_patches.end())
continue;
@ -312,8 +314,8 @@ std::vector<Patch> Disc::GeneratePatches(const std::string& game_id) const
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});
for (const auto& param : patch_ref.m_params)
replacements.emplace_back(std::pair{"{$" + param.first + "}", param.second});
for (const auto& [first, second] : params)
replacements.emplace_back(std::pair{"{$" + first + "}", second});
Patch& new_patch = active_patches.emplace_back(*patch);
new_patch.m_root = replace_variables(new_patch.m_root, replacements);
@ -327,9 +329,9 @@ std::vector<Patch> Disc::GeneratePatches(const std::string& game_id) const
folder.m_disc = replace_variables(folder.m_disc, replacements);
folder.m_external = replace_variables(folder.m_external, replacements);
}
for (auto& savegame : new_patch.m_savegame_patches)
for (auto& [external, clone] : new_patch.m_savegame_patches)
{
savegame.m_external = replace_variables(savegame.m_external, replacements);
external = replace_variables(external, replacements);
}
for (auto& memory : new_patch.m_memory_patches)
{
@ -347,38 +349,38 @@ std::vector<Patch> GenerateRiivolutionPatchesFromGameModDescriptor(
std::optional<u16> revision, std::optional<u8> disc_number)
{
std::vector<Patch> result;
for (const auto& patch_info : descriptor.patches)
for (const auto& [xml, root, options] : descriptor.patches)
{
auto parsed = ParseFile(patch_info.xml);
auto parsed = ParseFile(xml);
if (!parsed || !parsed->IsValidForGame(game_id, revision, disc_number))
continue;
for (auto& section : parsed->m_sections)
for (auto& [section_name, section_options] : parsed->m_sections)
{
for (auto& option : section.m_options)
for (auto& [option_name, id, choices, selected_choice] : section_options)
{
const auto* info = [&]() -> const GameModDescriptorRiivolutionPatchOption* {
for (const auto& o : patch_info.options)
for (const auto& o : options)
{
if (o.section_name == section.m_name)
if (o.section_name == section_name)
{
if (!o.option_id.empty() && o.option_id == option.m_id)
if (!o.option_id.empty() && o.option_id == id)
return &o;
if (!o.option_name.empty() && o.option_name == option.m_name)
if (!o.option_name.empty() && o.option_name == option_name)
return &o;
}
}
return nullptr;
}();
if (info && info->choice <= option.m_choices.size())
option.m_selected_choice = info->choice;
if (info && info->choice <= choices.size())
selected_choice = info->choice;
}
}
for (auto& p : parsed->GeneratePatches(game_id))
{
p.m_file_data_loader =
std::make_shared<FileDataLoaderHostFS>(patch_info.root, parsed->m_xml_path, p.m_root);
std::make_shared<FileDataLoaderHostFS>(root, parsed->m_xml_path, p.m_root);
result.emplace_back(std::move(p));
}
}
@ -451,9 +453,9 @@ std::optional<Config> ParseConfigString(std::string_view xml)
const auto options = riivolution.children("option");
for (const auto& option_node : options)
{
auto& option = config.m_options.emplace_back();
option.m_id = option_node.attribute("id").as_string();
option.m_default = option_node.attribute("default").as_uint(0);
auto& [option_id, option_default] = config.m_options.emplace_back();
option_id = option_node.attribute("id").as_string();
option_default = option_node.attribute("default").as_uint(0);
}
return config;
@ -464,11 +466,11 @@ std::string WriteConfigString(const Config& config)
pugi::xml_document doc;
auto riivolution = doc.append_child("riivolution");
riivolution.append_attribute("version").set_value(config.m_version);
for (const auto& option : config.m_options)
for (const auto& [option_id, option_default] : config.m_options)
{
auto option_node = riivolution.append_child("option");
option_node.append_attribute("id").set_value(option.m_id.c_str());
option_node.append_attribute("default").set_value(option.m_default);
option_node.append_attribute("id").set_value(option_id.c_str());
option_node.append_attribute("default").set_value(option_default);
}
std::stringstream ss;
@ -495,21 +497,21 @@ bool WriteConfigFile(const std::string& filename, const Config& config)
void ApplyConfigDefaults(Disc* disc, const Config& config)
{
for (const auto& config_option : config.m_options)
for (const auto& [option_id, option_default] : config.m_options)
{
auto* matching_option = [&]() -> Option* {
for (auto& section : disc->m_sections)
for (auto& [name, options] : disc->m_sections)
{
for (auto& option : section.m_options)
for (auto& option : options)
{
if (option.m_id.empty())
{
if ((section.m_name + option.m_name) == config_option.m_id)
if ((name + option.m_name) == option_id)
return &option;
}
else
{
if (option.m_id == config_option.m_id)
if (option.m_id == option_id)
return &option;
}
}
@ -517,7 +519,7 @@ void ApplyConfigDefaults(Disc* disc, const Config& config)
return nullptr;
}();
if (matching_option)
matching_option->m_selected_choice = config_option.m_default;
matching_option->m_selected_choice = option_default;
}
}
} // namespace DiscIO::Riivolution

View File

@ -450,7 +450,7 @@ static void ApplyFolderPatchToFST(const Patch& patch, const Folder& folder,
std::string_view external_path)
{
const auto external_files = patch.m_file_data_loader->GetFolderContents(external_path);
for (const auto& child : external_files)
for (const auto& [filename, is_directory] : external_files)
{
const auto combine_paths = [](std::string_view a, std::string_view b) {
if (a.empty())
@ -463,10 +463,10 @@ static void ApplyFolderPatchToFST(const Patch& patch, const Folder& folder,
b.remove_prefix(1);
return fmt::format("{}/{}", a, b);
};
std::string child_disc_path = combine_paths(disc_path, child.m_filename);
std::string child_external_path = combine_paths(external_path, child.m_filename);
std::string child_disc_path = combine_paths(disc_path, filename);
std::string child_external_path = combine_paths(external_path, filename);
if (child.m_is_directory)
if (is_directory)
{
if (folder.m_recursive)
ApplyFolderPatchToFST(patch, folder, fst, dol_node, child_disc_path, child_external_path);
@ -665,10 +665,10 @@ std::optional<SavegameRedirect> ExtractSavegameRedirect(std::span<const Patch> r
{
if (!patch.m_savegame_patches.empty())
{
const auto& save_patch = patch.m_savegame_patches[0];
auto resolved = patch.m_file_data_loader->ResolveSavegameRedirectPath(save_patch.m_external);
const auto& [external, clone] = patch.m_savegame_patches[0];
auto resolved = patch.m_file_data_loader->ResolveSavegameRedirectPath(external);
if (resolved)
return SavegameRedirect{std::move(*resolved), save_patch.m_clone};
return SavegameRedirect{std::move(*resolved), clone};
return std::nullopt;
}
}

View File

@ -59,10 +59,9 @@ std::unique_ptr<SplitPlainFileReader> SplitPlainFileReader::Create(std::string_v
std::unique_ptr<BlobReader> SplitPlainFileReader::CopyReader() const
{
std::vector<SingleFile> new_files{};
for (const SingleFile& file : m_files)
for (const auto& [file, offset, size] : m_files)
{
new_files.push_back(
{.file = file.file.Duplicate("rb"), .offset = file.offset, .size = file.size});
new_files.push_back({.file = file.Duplicate("rb"), .offset = offset, .size = size});
}
return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(new_files)));
}
@ -75,16 +74,15 @@ bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
u64 current_offset = offset;
u64 rest = nbytes;
u8* out = out_ptr;
for (auto& file : m_files)
for (auto& [file, file_offset, size] : m_files)
{
if (current_offset >= file.offset && current_offset < file.offset + file.size)
if (current_offset >= file_offset && current_offset < file_offset + size)
{
auto& f = file.file;
const u64 seek_offset = current_offset - file.offset;
const u64 current_read = std::min(file.size - seek_offset, rest);
if (!f.Seek(seek_offset, File::SeekOrigin::Begin) || !f.ReadBytes(out, current_read))
const u64 seek_offset = current_offset - file_offset;
const u64 current_read = std::min(size - seek_offset, rest);
if (!file.Seek(seek_offset, File::SeekOrigin::Begin) || !file.ReadBytes(out, current_read))
{
f.ClearError();
file.ClearError();
return false;
}

View File

@ -217,26 +217,27 @@ VolumeGC::ConvertedGCBanner VolumeGC::ExtractBannerInformation(const GCBanner& b
for (u32 i = 0; i < number_of_languages; ++i)
{
const GCBannerInformation& info = banner_file.information[i];
const auto& [info_short_name, info_short_maker, info_long_name, info_long_maker,
info_description] = banner_file.information[i];
Language language = static_cast<Language>(static_cast<int>(start_language) + i);
std::string description = DecodeString(info.description);
std::string description = DecodeString(info_description);
if (!description.empty())
banner.descriptions.emplace(language, description);
std::string short_name = DecodeString(info.short_name);
std::string short_name = DecodeString(info_short_name);
if (!short_name.empty())
banner.short_names.emplace(language, short_name);
std::string long_name = DecodeString(info.long_name);
std::string long_name = DecodeString(info_long_name);
if (!long_name.empty())
banner.long_names.emplace(language, long_name);
std::string short_maker = DecodeString(info.short_maker);
std::string short_maker = DecodeString(info_short_maker);
if (!short_maker.empty())
banner.short_makers.emplace(language, short_maker);
std::string long_maker = DecodeString(info.long_maker);
std::string long_maker = DecodeString(info_long_maker);
if (!long_maker.empty())
banner.long_makers.emplace(language, long_maker);
}

View File

@ -295,12 +295,12 @@ std::vector<RedumpVerifier::PotentialMatch> RedumpVerifier::ScanDatfile(const st
continue;
}
PotentialMatch& potential_match = potential_matches.emplace_back();
auto& [size, hashes] = potential_matches.emplace_back();
const pugi::xml_node rom = game.child("rom");
potential_match.size = rom.attribute("size").as_ullong();
potential_match.hashes.crc32 = ParseHash(rom.attribute("crc").value());
potential_match.hashes.md5 = ParseHash(rom.attribute("md5").value());
potential_match.hashes.sha1 = ParseHash(rom.attribute("sha1").value());
size = rom.attribute("size").as_ullong();
hashes.crc32 = ParseHash(rom.attribute("crc").value());
hashes.md5 = ParseHash(rom.attribute("md5").value());
hashes.sha1 = ParseHash(rom.attribute("sha1").value());
}
if (!serials_exist || !versions_exist)
@ -335,10 +335,11 @@ RedumpVerifier::Result RedumpVerifier::Finish(const Hashes<std::vector<u8>>& has
return m_result;
const std::vector<PotentialMatch> potential_matches = m_future.get();
for (PotentialMatch p : potential_matches)
for (auto [potential_match_size, potential_match_hashes] : potential_matches)
{
if (HashesMatch(hashes.crc32, p.hashes.crc32) && HashesMatch(hashes.md5, p.hashes.md5) &&
HashesMatch(hashes.sha1, p.hashes.sha1) && m_size == p.size)
if (HashesMatch(hashes.crc32, potential_match_hashes.crc32) &&
HashesMatch(hashes.md5, potential_match_hashes.md5) &&
HashesMatch(hashes.sha1, potential_match_hashes.sha1) && m_size == potential_match_size)
{
return {Status::GoodDump, Common::GetStringT("Good dump")};
}
@ -1232,15 +1233,15 @@ void VolumeVerifier::Process()
{
m_group_future = std::async(std::launch::async, [this, read_failed,
group_index = m_group_index] {
const GroupToVerify& group = m_groups[group_index];
const auto& [partition, offset, block_index_start, block_index_end] = m_groups[group_index];
u64 offset_in_group = 0;
for (u64 block_index = group.block_index_start; block_index < group.block_index_end;
for (u64 block_index = block_index_start; block_index < block_index_end;
++block_index, offset_in_group += VolumeWii::BLOCK_TOTAL_SIZE)
{
const u64 block_offset = group.offset + offset_in_group;
const u64 block_offset = offset + offset_in_group;
if (!read_failed && m_volume.CheckBlockIntegrity(
block_index, m_data.data() + offset_in_group, group.partition))
if (!read_failed &&
m_volume.CheckBlockIntegrity(block_index, m_data.data() + offset_in_group, partition))
{
m_biggest_verified_offset =
std::max(m_biggest_verified_offset, block_offset + VolumeWii::BLOCK_TOTAL_SIZE);
@ -1250,12 +1251,12 @@ void VolumeVerifier::Process()
if (m_scrubber.CanBlockBeScrubbed(block_offset))
{
WARN_LOG_FMT(DISCIO, "Integrity check failed for unused block at {:#x}", block_offset);
m_unused_block_errors[group.partition]++;
m_unused_block_errors[partition]++;
}
else
{
WARN_LOG_FMT(DISCIO, "Integrity check failed for block at {:#x}", block_offset);
m_block_errors[group.partition]++;
m_block_errors[partition]++;
}
}
}