From 90d854e48bfee3c1e13520d5fcf3bdf5a852a748 Mon Sep 17 00:00:00 2001 From: endercodezz Date: Wed, 4 Nov 2026 22:30:14 +0200 Subject: [PATCH] fix(profile): share P3P build settings and mod alias Generate the Builder layout from the profile and share the mod prefix across runners. Verified: Windows Release, CTest 27/27, devkitARM runner objects and three matching PC event traces (1a5f566002148933522c869ed3febb9eae3d652764501d20e8437b3b1898e605). --- CMakeLists.txt | 3 +++ docs/CURRENT_STATE.md | 6 ++++++ docs/VERIFICATION.md | 2 +- platform/3ds/main.cpp | 5 +++-- platform/pc/builder/fun_facts.hpp | 2 +- platform/pc/builder/pipeline.cpp | 11 ++++++----- platform/pc/main.cpp | 9 +++++---- profiles/p3p/config/aot_layout.hpp.in | 10 ++++++++++ profiles/p3p/config/mod_paths.hpp | 8 ++++++++ 9 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 profiles/p3p/config/aot_layout.hpp.in create mode 100644 profiles/p3p/config/mod_paths.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9972189c..566a1262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ add_executable(p3p_pc_bootstrap target_include_directories(p3p_pc_bootstrap PRIVATE core/include recomp/PSPRecomp/include + profiles/p3p/config ) target_link_libraries(p3p_pc_bootstrap PRIVATE @@ -339,6 +340,8 @@ else() target_link_libraries(p3p3ds_builder PRIVATE p3p3ds_builder_core p3p3ds_core) endif() set_target_properties(p3p3ds_builder PROPERTIES OUTPUT_NAME "P3P3DS-Builder") +configure_file(profiles/p3p/config/aot_layout.hpp.in generated/aot_layout.hpp @ONLY) +target_include_directories(p3p3ds_builder PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/generated") add_executable(test_psp_eboot tests/test_psp_eboot.cpp) target_link_libraries(test_psp_eboot PRIVATE p3p3ds_builder_core p3p3ds_core) file(GLOB P3P_LOCAL_ISOS "${CMAKE_CURRENT_SOURCE_DIR}/*.iso") diff --git a/docs/CURRENT_STATE.md b/docs/CURRENT_STATE.md index 04f6f9d8..70704f4a 100644 --- a/docs/CURRENT_STATE.md +++ b/docs/CURRENT_STATE.md @@ -2,6 +2,12 @@ This is the current source of truth, newest entries first. Evidence concerns ULUS-10512; each section says whether it was measured on the PC runner, in Azahar or on a real New 3DS. +## Builder AOT layout and runner mod paths use the P3P profile (2026-11-04) + +- [VERIFIED] `profiles/p3p/config/aot_layout.cmake` supplies the load base, span and count to CMake and to the Builder through its configured header. The PC and New 3DS runners use the mod alias in `profiles/p3p/config/mod_paths.hpp`, from `p3p/p3p-patches/ULUS10512.ini:6-9`. +- [VERIFIED] Windows Release build, `ctest --test-dir build -j6 --output-on-failure` (27/27), `python tools/verify_aot_layout.py build/generated/auto 237 16384`, stable bootstrap and devkitARM `cmake --build build/3ds --target p3p3ds_objects -j4` passed. +- [VERIFIED] Two PC runs with `--run-until-blocker --max-dispatches 20000000 --ms0 .tmp/issue27/ms0 --mods .tmp/issue27/mods --dump-events ` and the pre-change run all reached the dispatch limit at `0x08A87150`. Their event dumps (`.tmp/issue27/baseline.json`, `run1.json`, `run2.json` in the same directory) share SHA-256 `1a5f566002148933522c869ed3febb9eae3d652764501d20e8437b3b1898e605`. No new execution blocker was observed. [UNVERIFIED] Mod loading on physical New 3DS hardware. + ## Known issues tracked on GitHub; issue -> pull request workflow (2026-11-04) No runtime change; the frontier is the same as in the entry below (logo fix 4d198db in master, not released). diff --git a/docs/VERIFICATION.md b/docs/VERIFICATION.md index bf9827a0..eaeaf448 100644 --- a/docs/VERIFICATION.md +++ b/docs/VERIFICATION.md @@ -70,7 +70,7 @@ Current execution and coverage measurements: [CURRENT_STATE.md](CURRENT_STATE.md | Codegen lowering covers 99.91% of .text (912,275 / 913,059) | `[VERIFIED]` | Audit of `codegen_main.cpp` lowering rules in `verify_p3p_decoder` | 912,275 instructions directly lowerable; 62 decoded instructions (10 `vfpu1`, 52 `vfpu4`) hit unlowered generic VFPU stub. | | Intro Skip Hook address is `0x002594A4` (`li $v0, 6`) | `[VERIFIED]` | `p3p/p3p-patches/ULUS10512.ini:4` | Forces title screen state. | | Mod Loader path prefix is `ms0:/PSP/GAME/P3P/%s` at `0x00395EE4` | `[WRONG]` | `p3p/p3p-patches/ULUS10512.ini:6-9` | The four words `0x3A30736D 0x5053502F 0x5033502F 0x0073252F` (little-endian) spell `ms0:/PSP/P3P/%s`, as used by the runners and `CURRENT_STATE.md`. | -| Mod Loader path prefix is `ms0:/PSP/P3P/%s` at `0x00395EE4` | `[VERIFIED]` | `p3p/p3p-patches/ULUS10512.ini:6-9`; `platform/pc/main.cpp`, `platform/3ds/main.cpp` | Memory string replacement for loose file redirection. The prefix is hardcoded in both runners instead of `profiles/p3p/config/` (CLAUDE.md section 8). | +| Mod Loader path prefix is `ms0:/PSP/P3P/%s` at `0x00395EE4` | `[VERIFIED]` | `p3p/p3p-patches/ULUS10512.ini:6-9`; `profiles/p3p/config/mod_paths.hpp` | Memory string replacement for loose file redirection. Both runners mount the alias at the profile's prefix. | | Mod Loader search sequence is `bind/` -> `mod.cpk` -> `mod1.cpk` -> `mod2.cpk` -> `mod3.cpk` | `[VERIFIED]` | `p3p/p3p-patches/ULUS10512.ini:10-24` | Verified from community CWCheat table. | | P3P event scripts are compiled `.bf` bytecode, not native MIPS | `[VERIFIED]` | `tools/Atlus-Script-Tools/Source/AtlusScriptCompiler/`, `p3p/Persona-3-Portable-Mod-Menu/ModMenu.flow` | Game engine uses an internal bytecode interpreter. | | P3P uses CriWare CPK archives (`data.cpk`) | `[WRONG]` for the name: ULUS-10512 uses `USRDIR/umd0.cpk`, `umd1.cpk`, `MEMST.CPK` (ISO9660 listing); CPK format itself `[VERIFIED]` | `tools/CriFsV2Lib`, `tools/CriPakTools`, UMD file structure | Main asset container. | diff --git a/platform/3ds/main.cpp b/platform/3ds/main.cpp index 86ca9c3c..7dcf6227 100644 --- a/platform/3ds/main.cpp +++ b/platform/3ds/main.cpp @@ -5,7 +5,7 @@ // written to sdmc:/p3p3ds/report.txt every few seconds and on exit. // // Game data: sdmc:/p3p3ds/*.iso (the user's ULUS-10512 image) mounted as -// disc0:, sdmc:/p3p3ds/ms0 as ms0:, sdmc:/p3p3ds/mods as ms0:/PSP/P3P. +// disc0:, sdmc:/p3p3ds/ms0 as ms0:, sdmc:/p3p3ds/mods as the profile's mod directory. // The decrypted executable is read from romfs:/eboot.elf (embedded at build // time from the local build; it must match the generated AOT code). // @@ -30,6 +30,7 @@ #include "p3p3ds/profile.hpp" #include "p3p3ds/vfs.hpp" #include "bootstrap_expectations.hpp" +#include "mod_paths.hpp" #include "gpu_renderer.hpp" #include "p3p3ds/ge/async_renderer.hpp" #include "psprecomp/elf32.hpp" @@ -825,7 +826,7 @@ int main() { kernel.io().mount("ms0:", std::make_shared(ms0), true); kernel.savedata().root = ms0 + "/PSP/SAVEDATA"; // Read-only and unchanged while the game runs: lookups cached (vfs.hpp). - kernel.io().alias("ms0:/PSP/P3P", std::make_shared(std::string(kBase) + "/mods", true)); + kernel.io().alias(p3p3ds::profile::kModPrefix, std::make_shared(std::string(kBase) + "/mods", true)); kernel.threads().init_root_thread("root", entry, sp, module->gp); std::set stubs; std::vector> imports; diff --git a/platform/pc/builder/fun_facts.hpp b/platform/pc/builder/fun_facts.hpp index 54365dba..7e51aa32 100644 --- a/platform/pc/builder/fun_facts.hpp +++ b/platform/pc/builder/fun_facts.hpp @@ -21,7 +21,7 @@ inline constexpr const wchar_t *kFunFacts[] = { L"Persona 3 Portable was re-released for modern consoles and PC in January 2023.", L"Persona 3 Reload (2024) remade the game from scratch, but without the female protagonist.", L"P3P3DS does not emulate the PSP processor on your 3DS: the game's 3.6 MB of MIPS code is translated to C++ and compiled to about 44 MB of ARM code - right now, on your PC.", - L"About 750,000 PSP instructions are being translated in this build, grouped into 237 C++ files of 16 KiB of game code each.", + L"About 750,000 PSP instructions are being translated in this build and split across C++ files for parallel compilation.", L"On the 3DS, the PICA200 graphics chip draws what the PSP's Graphics Engine drew. The 480x272 picture is scaled to the 400x240 top screen.", L"Your ISO stays on the SD card: P3P3DS reads the game's CPK archives from it while you play.", L"Mods made for the community \"Mod Support\" patch (mod.cpk, bind/) go to sdmc:/p3p3ds/mods/.", diff --git a/platform/pc/builder/pipeline.cpp b/platform/pc/builder/pipeline.cpp index db35bb43..b9a3d608 100644 --- a/platform/pc/builder/pipeline.cpp +++ b/platform/pc/builder/pipeline.cpp @@ -1,5 +1,6 @@ // See pipeline.hpp. #include "pipeline.hpp" +#include "aot_layout.hpp" #include "psp_eboot.hpp" #include "p3p3ds/vfs.hpp" @@ -34,9 +35,6 @@ namespace fs = std::filesystem; namespace p3p3ds::builder { namespace { -constexpr unsigned kUnitCount = 237; // profiles/p3p/config/aot_layout.cmake -constexpr const char *kLoadBase = "0x08804000"; -constexpr const char *kUnitSpan = "16384"; // Measured on the largest unit and the whole program (docs/3DS_PLATFORM.md // section 8.5): GCSE and instruction scheduling cost 27 % of the compile // time for 0.8 % of code size. @@ -316,14 +314,17 @@ void Pipeline::generate() { std::error_code ec; fs::remove_all(gen_, ec); fs::create_directories(gen_); - const Args cmd = {tool(s_.sdk / "bin", "psp_recomp"), elf_, "--auto", gen_, kLoadBase, kUnitSpan, s_.sdk / "patches.txt", + const Args cmd = {tool(s_.sdk / "bin", "psp_recomp"), elf_, "--auto", gen_, profile::kAotLoadBase, profile::kAotUnitSpan, s_.sdk / "patches.txt", "--no-transfer-records"}; const fs::path log = s_.work / "generate.log"; if (run_tool(cmd, log) != 0) throw std::runtime_error("Code generation failed:\n" + read_text(log)); unsigned units = 0; for (const auto &e : fs::directory_iterator(gen_)) if (e.path().filename().string().rfind("generated_unit_", 0) == 0) ++units; - if (units != kUnitCount) throw std::runtime_error("Code generation produced " + std::to_string(units) + " units, expected 237."); + if (units != profile::kAotUnitCount) { + throw std::runtime_error("Code generation produced " + std::to_string(units) + + " units, expected " + std::to_string(profile::kAotUnitCount) + "."); + } write_text(stamp, want); } diff --git a/platform/pc/main.cpp b/platform/pc/main.cpp index 5bf401f7..43402629 100644 --- a/platform/pc/main.cpp +++ b/platform/pc/main.cpp @@ -9,6 +9,7 @@ #include "host_input.hpp" #include "p3p3ds/profile.hpp" #include "sampler.hpp" +#include "mod_paths.hpp" #include #include @@ -113,8 +114,8 @@ int main(int argc,char **argv) { } else std::cout<<"UMD image: none (disc0: unmounted)\n"; kernel.io().trace_reads=!io_trace_path.empty(); { - // ms0: memory stick root; the community Mod Support patch reads - // ms0:/PSP/P3P/{bind/,mod.cpk,mod1-3.cpk}, mapped onto --mods. + // Mount the memory stick root and optionally map the profile's + // Mod Support directory onto --mods. std::filesystem::create_directories(ms0_path); kernel.io().mount("ms0:",std::make_shared(ms0_path),true); // Saves: ms0:/PSP/SAVEDATA. The list dialogs have no window here, so @@ -130,8 +131,8 @@ int main(int argc,char **argv) { return best>=0 ? best : (d.kind==p3p3ds::hle::SavedataDialog::Kind::Save ? 0 : -1); }; if(!mods_path.empty()) { - kernel.io().alias("ms0:/PSP/P3P",std::make_shared(mods_path,true)); // read-only: cached lookups - std::cout<<"Mods: ms0:/PSP/P3P -> "<(mods_path,true)); // read-only: cached lookups + std::cout<<"Mods: "< "<gp); diff --git a/profiles/p3p/config/aot_layout.hpp.in b/profiles/p3p/config/aot_layout.hpp.in new file mode 100644 index 00000000..3b567fec --- /dev/null +++ b/profiles/p3p/config/aot_layout.hpp.in @@ -0,0 +1,10 @@ +#pragma once + +namespace p3p3ds::profile { + +// Values and verification evidence come from aot_layout.cmake. +inline constexpr unsigned kAotUnitCount = @P3P_AOT_UNIT_COUNT@; +inline constexpr char kAotLoadBase[] = "@P3P_AOT_LOAD_BASE@"; +inline constexpr char kAotUnitSpan[] = "@P3P_AOT_UNIT_SPAN@"; + +} // namespace p3p3ds::profile diff --git a/profiles/p3p/config/mod_paths.hpp b/profiles/p3p/config/mod_paths.hpp new file mode 100644 index 00000000..d195089f --- /dev/null +++ b/profiles/p3p/config/mod_paths.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace p3p3ds::profile { + +// [VERIFIED] p3p/p3p-patches/ULUS10512.ini:6-9 (Mod Support). +inline constexpr char kModPrefix[] = "ms0:/PSP/P3P"; + +} // namespace p3p3ds::profile