mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
feat: add feature-oriented mod resolution
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "mod_runtime.h"
|
||||
#include "psx_sha256.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
@@ -6,6 +7,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -35,10 +37,36 @@ static void write_text(const fs::path& path, const std::string& text) {
|
||||
out << text;
|
||||
}
|
||||
|
||||
static void write_bytes(const fs::path& path, const std::vector<uint8_t>& bytes) {
|
||||
fs::create_directories(path.parent_path());
|
||||
std::ofstream out(path, std::ios::binary);
|
||||
out.write((const char*)bytes.data(), (std::streamsize)bytes.size());
|
||||
}
|
||||
|
||||
static std::string sha256_hex(const std::vector<uint8_t>& bytes) {
|
||||
uint8_t digest[32];
|
||||
psx_sha256_compute(bytes.data(), bytes.size(), digest);
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
std::string out(64, '0');
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
out[i * 2] = hex[digest[i] >> 4];
|
||||
out[i * 2 + 1] = hex[digest[i] & 15];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int main() {
|
||||
const fs::path root = fs::temp_directory_path() / "psxrecomp-mod-runtime-test";
|
||||
std::error_code ec;
|
||||
fs::remove_all(root, ec);
|
||||
const std::vector<uint8_t> stock(8 * 2352, 0);
|
||||
std::vector<uint8_t> overlay(3000);
|
||||
for (size_t i = 0; i < overlay.size(); ++i)
|
||||
overlay[i] = (uint8_t)(i * 17u + 3u);
|
||||
const fs::path stock_path = root / "stock.bin";
|
||||
write_bytes(stock_path, stock);
|
||||
write_bytes(root / "packages/runtime.test/1.0.0/assets/overlay.bin",
|
||||
overlay);
|
||||
write_text(root / "packages/runtime.test/1.0.0/manifest.toml",
|
||||
"format_version = 1\n"
|
||||
"id = \"runtime.test\"\n"
|
||||
@@ -46,28 +74,72 @@ int main() {
|
||||
"name = \"Runtime Test\"\n"
|
||||
"[[target]]\n"
|
||||
"game_id = \"SLUS-RUNTIME\"\n"
|
||||
"disc_sha256 = \"" + sha256_hex(stock) + "\"\n"
|
||||
"[[feature]]\n"
|
||||
"id = \"main-code\"\n"
|
||||
"name = \"Main Code\"\n"
|
||||
"[[feature]]\n"
|
||||
"id = \"disc-byte\"\n"
|
||||
"name = \"Disc Byte\"\n"
|
||||
"[[feature]]\n"
|
||||
"id = \"asset-overlay\"\n"
|
||||
"name = \"Asset Overlay\"\n"
|
||||
"[[feature]]\n"
|
||||
"id = \"user-byte\"\n"
|
||||
"name = \"User Byte\"\n"
|
||||
"[[patch]]\n"
|
||||
"feature = \"main-code\"\n"
|
||||
"target = \"main_exe\"\n"
|
||||
"address = 2147487744\n"
|
||||
"expected = \"01020304\"\n"
|
||||
"replace = \"a1a2a3a4\"\n"
|
||||
"[[patch]]\n"
|
||||
"feature = \"disc-byte\"\n"
|
||||
"target = \"disc_raw\"\n"
|
||||
"offset = 4714\n"
|
||||
"expected = \"aa\"\n"
|
||||
"replace = \"bb\"\n");
|
||||
"replace = \"bb\"\n"
|
||||
"[[patch]]\n"
|
||||
"feature = \"user-byte\"\n"
|
||||
"target = \"disc_user\"\n"
|
||||
"offset = 6154\n"
|
||||
"expected = \"cc\"\n"
|
||||
"replace = \"dd\"\n"
|
||||
"[[overlay]]\n"
|
||||
"feature = \"asset-overlay\"\n"
|
||||
"target = \"disc_raw\"\n"
|
||||
"offset = 11408\n"
|
||||
"file = \"assets/overlay.bin\"\n"
|
||||
"sha256 = \"" + sha256_hex(overlay) + "\"\n"
|
||||
"expected_sha256 = \"" +
|
||||
sha256_hex(std::vector<uint8_t>(overlay.size(), 0)) + "\"\n");
|
||||
write_text(root / "state.toml",
|
||||
"format_version = 1\n"
|
||||
"format_version = 2\n"
|
||||
"[[package]]\n"
|
||||
"id = \"runtime.test\"\n"
|
||||
"version = \"1.0.0\"\n"
|
||||
"[[feature]]\n"
|
||||
"package_id = \"runtime.test\"\n"
|
||||
"id = \"main-code\"\n"
|
||||
"enabled = true\n"
|
||||
"version = \"1.0.0\"\n");
|
||||
"[[feature]]\n"
|
||||
"package_id = \"runtime.test\"\n"
|
||||
"id = \"disc-byte\"\n"
|
||||
"enabled = true\n"
|
||||
"[[feature]]\n"
|
||||
"package_id = \"runtime.test\"\n"
|
||||
"id = \"asset-overlay\"\n"
|
||||
"enabled = true\n"
|
||||
"[[feature]]\n"
|
||||
"package_id = \"runtime.test\"\n"
|
||||
"id = \"user-byte\"\n"
|
||||
"enabled = true\n");
|
||||
|
||||
std::string error;
|
||||
check(PSXRecompV4::mod_runtime_initialize(
|
||||
root, "SLUS-RUNTIME", 0x80002000, {}, &error),
|
||||
error.c_str());
|
||||
check(PSXRecompV4::mod_runtime_commit({}, &error), error.c_str());
|
||||
check(PSXRecompV4::mod_runtime_commit(stock_path, &error), error.c_str());
|
||||
|
||||
ram[0x1000] = 1; ram[0x1001] = 2; ram[0x1002] = 3; ram[0x1003] = 4;
|
||||
mod_runtime_on_dispatch(0x80001000);
|
||||
@@ -84,6 +156,42 @@ int main() {
|
||||
mod_runtime_patch_disc_sector(2, 1, sector.data(), (uint32_t)sector.size());
|
||||
check(sector[10] == 0xbb, "raw disc overlay must patch matching sectors");
|
||||
|
||||
std::array<uint8_t, 2352> overlay_sector{};
|
||||
mod_runtime_patch_disc_sector(
|
||||
4, 1, overlay_sector.data(), (uint32_t)overlay_sector.size());
|
||||
check(overlay_sector[1999] == 0 &&
|
||||
overlay_sector[2000] == overlay[0] &&
|
||||
overlay_sector[2351] == overlay[351],
|
||||
"file overlay must patch the tail of its first sector");
|
||||
overlay_sector.fill(0);
|
||||
mod_runtime_patch_disc_sector(
|
||||
5, 1, overlay_sector.data(), (uint32_t)overlay_sector.size());
|
||||
check(overlay_sector.front() == overlay[352] &&
|
||||
overlay_sector.back() == overlay[2703],
|
||||
"file overlay must patch complete middle sectors");
|
||||
overlay_sector.fill(0);
|
||||
mod_runtime_patch_disc_sector(
|
||||
6, 1, overlay_sector.data(), (uint32_t)overlay_sector.size());
|
||||
check(overlay_sector[0] == overlay[2704] &&
|
||||
overlay_sector[295] == overlay[2999] &&
|
||||
overlay_sector[296] == 0,
|
||||
"file overlay must patch the head of its final sector");
|
||||
|
||||
std::array<uint8_t, 2352> mode2_sector{};
|
||||
mode2_sector[15] = 2;
|
||||
mode2_sector[18] = 0;
|
||||
mode2_sector[24 + 10] = 0xcc;
|
||||
mod_runtime_patch_disc_sector(
|
||||
3, 1, mode2_sector.data(), (uint32_t)mode2_sector.size());
|
||||
check(mode2_sector[24 + 10] == 0xdd,
|
||||
"disc_user operations must apply to raw Mode2 Form1 user data");
|
||||
std::array<uint8_t, 2352> audio_sector{};
|
||||
audio_sector[24 + 10] = 0xcc;
|
||||
mod_runtime_patch_disc_sector(
|
||||
3, 1, audio_sector.data(), (uint32_t)audio_sector.size());
|
||||
check(audio_sector[24 + 10] == 0xcc,
|
||||
"disc_user operations must not modify CDDA/non-data sectors");
|
||||
|
||||
fs::remove_all(root, ec);
|
||||
if (failures) return 1;
|
||||
std::cout << "mod runtime tests passed\n";
|
||||
|
||||
Reference in New Issue
Block a user