Renamed load_mod to open_mod and ModLoadError to ModOpenError

This commit is contained in:
Mr-Wiseguy 2024-07-05 14:52:00 -04:00
parent 729155f0f1
commit 71cd05807f
2 changed files with 57 additions and 57 deletions

View file

@ -15,7 +15,7 @@
namespace recomp { namespace recomp {
namespace mods { namespace mods {
enum class ModLoadError { enum class ModOpenError {
Good, Good,
DoesNotExist, DoesNotExist,
NotAFileOrFolder, NotAFileOrFolder,
@ -41,7 +41,7 @@ namespace recomp {
std::unique_ptr<mz_zip_archive> archive; std::unique_ptr<mz_zip_archive> archive;
ZipModHandle() = default; ZipModHandle() = default;
ZipModHandle(const std::filesystem::path& mod_path, ModLoadError& error); ZipModHandle(const std::filesystem::path& mod_path, ModOpenError& error);
~ZipModHandle() final; ~ZipModHandle() final;
std::vector<char> read_file(const std::string& filepath, bool& exists) const final; std::vector<char> read_file(const std::string& filepath, bool& exists) const final;
@ -52,7 +52,7 @@ namespace recomp {
std::filesystem::path root_path; std::filesystem::path root_path;
LooseModHandle() = default; LooseModHandle() = default;
LooseModHandle(const std::filesystem::path& mod_path, ModLoadError& error); LooseModHandle(const std::filesystem::path& mod_path, ModOpenError& error);
~LooseModHandle() final; ~LooseModHandle() final;
std::vector<char> read_file(const std::string& filepath, bool& exists) const final; std::vector<char> read_file(const std::string& filepath, bool& exists) const final;
@ -77,10 +77,10 @@ namespace recomp {
std::unique_ptr<ModHandle> mod_handle; std::unique_ptr<ModHandle> mod_handle;
}; };
ModManifest load_mod(const std::filesystem::path& mod_path, ModLoadError& error, std::string& error_string); ModManifest open_mod(const std::filesystem::path& mod_path, ModOpenError& error, std::string& error_string);
bool load_mod_(uint8_t* rdram, int32_t target_vram, const std::filesystem::path& symbol_file, const std::filesystem::path& binary_file); bool load_mod_(uint8_t* rdram, int32_t target_vram, const std::filesystem::path& symbol_file, const std::filesystem::path& binary_file);
std::string error_to_string(ModLoadError); std::string error_to_string(ModOpenError);
} }
}; };

View file

@ -16,26 +16,26 @@ recomp::mods::ZipModHandle::~ZipModHandle() {
archive = {}; archive = {};
} }
recomp::mods::ZipModHandle::ZipModHandle(const std::filesystem::path& mod_path, ModLoadError& error) { recomp::mods::ZipModHandle::ZipModHandle(const std::filesystem::path& mod_path, ModOpenError& error) {
#ifdef _WIN32 #ifdef _WIN32
if (_wfopen_s(&file_handle, mod_path.c_str(), L"rb") != 0) { if (_wfopen_s(&file_handle, mod_path.c_str(), L"rb") != 0) {
error = ModLoadError::FileError; error = ModOpenError::FileError;
return; return;
} }
#else #else
file_handle = fopen(mod_path.c_str(), L"rb"); file_handle = fopen(mod_path.c_str(), L"rb");
if (!file_handle) { if (!file_handle) {
error = ModLoadError::FileError; error = ModOpenError::FileError;
return; return;
} }
#endif #endif
archive = std::make_unique<mz_zip_archive>(); archive = std::make_unique<mz_zip_archive>();
if (!mz_zip_reader_init_cfile(archive.get(), file_handle, 0, 0)) { if (!mz_zip_reader_init_cfile(archive.get(), file_handle, 0, 0)) {
error = ModLoadError::InvalidZip; error = ModOpenError::InvalidZip;
return; return;
} }
error = ModLoadError::Good; error = ModOpenError::Good;
} }
std::vector<char> recomp::mods::ZipModHandle::read_file(const std::string& filepath, bool& exists) const { std::vector<char> recomp::mods::ZipModHandle::read_file(const std::string& filepath, bool& exists) const {
@ -76,19 +76,19 @@ recomp::mods::LooseModHandle::~LooseModHandle() {
// Nothing to do here, members will be destroyed automatically. // Nothing to do here, members will be destroyed automatically.
} }
recomp::mods::LooseModHandle::LooseModHandle(const std::filesystem::path& mod_path, ModLoadError& error) { recomp::mods::LooseModHandle::LooseModHandle(const std::filesystem::path& mod_path, ModOpenError& error) {
root_path = mod_path; root_path = mod_path;
std::error_code ec; std::error_code ec;
if (!std::filesystem::is_directory(root_path, ec)) { if (!std::filesystem::is_directory(root_path, ec)) {
error = ModLoadError::NotAFileOrFolder; error = ModOpenError::NotAFileOrFolder;
} }
if (ec) { if (ec) {
error = ModLoadError::FileError; error = ModOpenError::FileError;
} }
error = ModLoadError::Good; error = ModOpenError::Good;
} }
std::vector<char> recomp::mods::LooseModHandle::read_file(const std::string& filepath, bool& exists) const { std::vector<char> recomp::mods::LooseModHandle::read_file(const std::string& filepath, bool& exists) const {
@ -173,17 +173,17 @@ bool get_to(const nlohmann::json& val, T2& out) {
return true; return true;
} }
bool parse_manifest(recomp::mods::ModManifest& ret, const std::vector<char>& manifest_data, recomp::mods::ModLoadError& error, std::string& error_param) { bool parse_manifest(recomp::mods::ModManifest& ret, const std::vector<char>& manifest_data, recomp::mods::ModOpenError& error, std::string& error_param) {
using json = nlohmann::json; using json = nlohmann::json;
json manifest_json = json::parse(manifest_data.begin(), manifest_data.end(), nullptr, false); json manifest_json = json::parse(manifest_data.begin(), manifest_data.end(), nullptr, false);
if (manifest_json.is_discarded()) { if (manifest_json.is_discarded()) {
error = recomp::mods::ModLoadError::FailedToParseManifest; error = recomp::mods::ModOpenError::FailedToParseManifest;
return false; return false;
} }
if (!manifest_json.is_object()) { if (!manifest_json.is_object()) {
error = recomp::mods::ModLoadError::InvalidManifestSchema; error = recomp::mods::ModOpenError::InvalidManifestSchema;
return false; return false;
} }
@ -191,7 +191,7 @@ bool parse_manifest(recomp::mods::ModManifest& ret, const std::vector<char>& man
const auto find_key_it = field_map.find(key); const auto find_key_it = field_map.find(key);
if (find_key_it == field_map.end()) { if (find_key_it == field_map.end()) {
// Unrecognized field // Unrecognized field
error = recomp::mods::ModLoadError::UnrecognizedManifestField; error = recomp::mods::ModOpenError::UnrecognizedManifestField;
error_param = key; error_param = key;
return false; return false;
} }
@ -200,56 +200,56 @@ bool parse_manifest(recomp::mods::ModManifest& ret, const std::vector<char>& man
switch (field) { switch (field) {
case ManifestField::Id: case ManifestField::Id:
if (!get_to<json::string_t>(val, ret.mod_id)) { if (!get_to<json::string_t>(val, ret.mod_id)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::MajorVersion: case ManifestField::MajorVersion:
if (!get_to<json::number_unsigned_t>(val, ret.major_version)) { if (!get_to<json::number_unsigned_t>(val, ret.major_version)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::MinorVersion: case ManifestField::MinorVersion:
if (!get_to<json::number_unsigned_t>(val, ret.minor_version)) { if (!get_to<json::number_unsigned_t>(val, ret.minor_version)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::PatchVersion: case ManifestField::PatchVersion:
if (!get_to<json::number_unsigned_t>(val, ret.patch_version)) { if (!get_to<json::number_unsigned_t>(val, ret.patch_version)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::BinaryPath: case ManifestField::BinaryPath:
if (!get_to<json::string_t>(val, ret.binary_path)) { if (!get_to<json::string_t>(val, ret.binary_path)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::BinarySymsPath: case ManifestField::BinarySymsPath:
if (!get_to<json::string_t>(val, ret.binary_syms_path)) { if (!get_to<json::string_t>(val, ret.binary_syms_path)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::RomPatchPath: case ManifestField::RomPatchPath:
if (!get_to<json::string_t>(val, ret.rom_patch_path)) { if (!get_to<json::string_t>(val, ret.rom_patch_path)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
break; break;
case ManifestField::RomPatchSymsPath: case ManifestField::RomPatchSymsPath:
if (!get_to<json::string_t>(val, ret.rom_patch_syms_path)) { if (!get_to<json::string_t>(val, ret.rom_patch_syms_path)) {
error = recomp::mods::ModLoadError::IncorrectManifestFieldType; error = recomp::mods::ModOpenError::IncorrectManifestFieldType;
error_param = key; error_param = key;
return false; return false;
} }
@ -260,47 +260,47 @@ bool parse_manifest(recomp::mods::ModManifest& ret, const std::vector<char>& man
return true; return true;
} }
bool validate_file_exists(const recomp::mods::ModManifest& manifest, const std::string& filepath, recomp::mods::ModLoadError& error, std::string& error_param) { bool validate_file_exists(const recomp::mods::ModManifest& manifest, const std::string& filepath, recomp::mods::ModOpenError& error, std::string& error_param) {
// No file provided, so nothing to check for. // No file provided, so nothing to check for.
if (filepath.empty()) { if (filepath.empty()) {
return true; return true;
} }
if (!manifest.mod_handle->file_exists(filepath)) { if (!manifest.mod_handle->file_exists(filepath)) {
error = recomp::mods::ModLoadError::InnerFileDoesNotExist; error = recomp::mods::ModOpenError::InnerFileDoesNotExist;
error_param = filepath; error_param = filepath;
return false; return false;
} }
return true; return true;
} }
bool validate_manifest(const recomp::mods::ModManifest& manifest, recomp::mods::ModLoadError& error, std::string& error_param) { bool validate_manifest(const recomp::mods::ModManifest& manifest, recomp::mods::ModOpenError& error, std::string& error_param) {
using namespace recomp::mods; using namespace recomp::mods;
// Check for required fields. // Check for required fields.
if (manifest.mod_id.empty()) { if (manifest.mod_id.empty()) {
error = ModLoadError::MissingManifestField; error = ModOpenError::MissingManifestField;
error_param = mod_id_key; error_param = mod_id_key;
return false; return false;
} }
if (manifest.major_version == -1) { if (manifest.major_version == -1) {
error = ModLoadError::MissingManifestField; error = ModOpenError::MissingManifestField;
error_param = major_version_key; error_param = major_version_key;
return false; return false;
} }
if (manifest.minor_version == -1) { if (manifest.minor_version == -1) {
error = ModLoadError::MissingManifestField; error = ModOpenError::MissingManifestField;
error_param = minor_version_key; error_param = minor_version_key;
return false; return false;
} }
if (manifest.patch_version == -1) { if (manifest.patch_version == -1) {
error = ModLoadError::MissingManifestField; error = ModOpenError::MissingManifestField;
error_param = patch_version_key; error_param = patch_version_key;
return false; return false;
} }
// If either a binary file or binary symbol file is provided, the other must be as well. // If either a binary file or binary symbol file is provided, the other must be as well.
if (manifest.binary_path.empty() != manifest.binary_syms_path.empty()) { if (manifest.binary_path.empty() != manifest.binary_syms_path.empty()) {
error = ModLoadError::MissingManifestField; error = ModOpenError::MissingManifestField;
if (manifest.binary_path.empty()) { if (manifest.binary_path.empty()) {
error_param = binary_path_key; error_param = binary_path_key;
} }
@ -312,7 +312,7 @@ bool validate_manifest(const recomp::mods::ModManifest& manifest, recomp::mods::
// If a ROM patch symbol file is provided, a ROM patch file must be as well. // If a ROM patch symbol file is provided, a ROM patch file must be as well.
if (!manifest.rom_patch_syms_path.empty() && manifest.rom_patch_path.empty()) { if (!manifest.rom_patch_syms_path.empty() && manifest.rom_patch_path.empty()) {
error = ModLoadError::MissingManifestField; error = ModOpenError::MissingManifestField;
error_param = rom_patch_path_key; error_param = rom_patch_path_key;
return false; return false;
} }
@ -334,31 +334,31 @@ bool validate_manifest(const recomp::mods::ModManifest& manifest, recomp::mods::
return true; return true;
} }
recomp::mods::ModManifest recomp::mods::load_mod(const std::filesystem::path& mod_path, ModLoadError& error, std::string& error_param) { recomp::mods::ModManifest recomp::mods::open_mod(const std::filesystem::path& mod_path, ModOpenError& error, std::string& error_param) {
ModManifest ret{}; ModManifest ret{};
std::error_code ec; std::error_code ec;
error_param = ""; error_param = "";
if (!std::filesystem::exists(mod_path, ec) || ec) { if (!std::filesystem::exists(mod_path, ec) || ec) {
error = ModLoadError::DoesNotExist; error = ModOpenError::DoesNotExist;
return {}; return {};
} }
// TODO support symlinks? // TODO support symlinks?
bool is_file = std::filesystem::is_regular_file(mod_path, ec); bool is_file = std::filesystem::is_regular_file(mod_path, ec);
if (ec) { if (ec) {
error = ModLoadError::FileError; error = ModOpenError::FileError;
return {}; return {};
} }
bool is_directory = std::filesystem::is_directory(mod_path, ec); bool is_directory = std::filesystem::is_directory(mod_path, ec);
if (ec) { if (ec) {
error = ModLoadError::FileError; error = ModOpenError::FileError;
return {}; return {};
} }
// Load the directory or zip file. // Load the directory or zip file.
ModLoadError handle_error; ModOpenError handle_error;
if (is_file) { if (is_file) {
ret.mod_handle = std::make_unique<recomp::mods::ZipModHandle>(mod_path, handle_error); ret.mod_handle = std::make_unique<recomp::mods::ZipModHandle>(mod_path, handle_error);
} }
@ -366,11 +366,11 @@ recomp::mods::ModManifest recomp::mods::load_mod(const std::filesystem::path& mo
ret.mod_handle = std::make_unique<recomp::mods::LooseModHandle>(mod_path, handle_error); ret.mod_handle = std::make_unique<recomp::mods::LooseModHandle>(mod_path, handle_error);
} }
else { else {
error = ModLoadError::NotAFileOrFolder; error = ModOpenError::NotAFileOrFolder;
return {}; return {};
} }
if (handle_error != ModLoadError::Good) { if (handle_error != ModOpenError::Good) {
error = handle_error; error = handle_error;
return {}; return {};
} }
@ -379,7 +379,7 @@ recomp::mods::ModManifest recomp::mods::load_mod(const std::filesystem::path& mo
bool exists; bool exists;
std::vector<char> manifest_data = ret.mod_handle->read_file("manifest.json", exists); std::vector<char> manifest_data = ret.mod_handle->read_file("manifest.json", exists);
if (!exists) { if (!exists) {
error = ModLoadError::NoManifest; error = ModOpenError::NoManifest;
return {}; return {};
} }
@ -393,35 +393,35 @@ recomp::mods::ModManifest recomp::mods::load_mod(const std::filesystem::path& mo
} }
// Return the loaded mod manifest // Return the loaded mod manifest
error = ModLoadError::Good; error = ModOpenError::Good;
return ret; return ret;
} }
std::string recomp::mods::error_to_string(ModLoadError error) { std::string recomp::mods::error_to_string(ModOpenError error) {
switch (error) { switch (error) {
case ModLoadError::Good: case ModOpenError::Good:
return "Good"; return "Good";
case ModLoadError::DoesNotExist: case ModOpenError::DoesNotExist:
return "Mod does not exist"; return "Mod does not exist";
case ModLoadError::NotAFileOrFolder: case ModOpenError::NotAFileOrFolder:
return "Mod is not a file or folder"; return "Mod is not a file or folder";
case ModLoadError::FileError: case ModOpenError::FileError:
return "Error reading mod file(s)"; return "Error reading mod file(s)";
case ModLoadError::InvalidZip: case ModOpenError::InvalidZip:
return "Mod is an invalid zip file"; return "Mod is an invalid zip file";
case ModLoadError::NoManifest: case ModOpenError::NoManifest:
return "Mod is missing a manifest.json"; return "Mod is missing a manifest.json";
case ModLoadError::FailedToParseManifest: case ModOpenError::FailedToParseManifest:
return "Failed to parse mod's manifest.json"; return "Failed to parse mod's manifest.json";
case ModLoadError::InvalidManifestSchema: case ModOpenError::InvalidManifestSchema:
return "Mod's manifest.json has an invalid schema"; return "Mod's manifest.json has an invalid schema";
case ModLoadError::UnrecognizedManifestField: case ModOpenError::UnrecognizedManifestField:
return "Unrecognized field in manifest.json"; return "Unrecognized field in manifest.json";
case ModLoadError::IncorrectManifestFieldType: case ModOpenError::IncorrectManifestFieldType:
return "Incorrect type for field in manifest.json"; return "Incorrect type for field in manifest.json";
case ModLoadError::MissingManifestField: case ModOpenError::MissingManifestField:
return "Missing required field in manifest"; return "Missing required field in manifest";
case ModLoadError::InnerFileDoesNotExist: case ModOpenError::InnerFileDoesNotExist:
return "File inside mod does not exist"; return "File inside mod does not exist";
} }
return "Unknown error " + std::to_string((int)error); return "Unknown error " + std::to_string((int)error);