diff --git a/docs/EU_INTEGRATION.md b/docs/EU_INTEGRATION.md index 1c02b50..af5fef3 100644 --- a/docs/EU_INTEGRATION.md +++ b/docs/EU_INTEGRATION.md @@ -117,3 +117,6 @@ SCES-01331 builds also accept the En/Es/Pt/Sv/Da **Rev 1** track (SHA-1 revision automatically; `--eu2-revision rev1 --plan` previews its commands. Each build and native cache binds one revision. See the [EU2 guide](../eu2/README.md) for both original inputs, contracts and the bounded EN/ES runtime sample. + +Cover gallery, dashboard quick controls and SCES-01331 language confirmation: +see [European launcher additions](regional/README.md). diff --git a/docs/regional/README.md b/docs/regional/README.md new file mode 100644 index 0000000..813722d --- /dev/null +++ b/docs/regional/README.md @@ -0,0 +1,43 @@ +# European launcher additions (October 2026) + +Contributed by [michaelm-afk](https://github.com/michaelm-afk) in the +24 October 2026 handoff and integrated through the shared framework and +launcher. The German notes in this folder are the contributor's earlier test +records. This page covers only what changed. + +## Cover gallery + +The launcher shows the bundled box art (`eu/launcher_assets/img/boxart.tga`, +from the libretro PS1 box-art set) until you choose your own covers. +**Browse Covers** opens a folder picker for the verified disc; the launcher reads +PNG, JPG, JPEG and TGA files from that folder without copying or changing them. +Files are ordered front, back, disc, then by name; arrows step through them and a +click enlarges the current one. The choice is saved per disc serial in +`artwork//cover-folder.txt` beside the launcher, relative when the folder +is inside the installation. Cover scans and manuals are never part of this +repository or a release package. + +## Quick controls + +EU1 and EU2 set `[launcher] quick_controls = true`. The dashboard then shows a +**Quick Mods** card next to the memory cards, listing Widescreen and Seamless +Loading (their manifests set `quick = true`), and a **Quick Settings** card +with VSync, Internal resolution, Screen mode and Screen model. Any listed mod can +be added or removed with **Show in Quick Mods** on the Mods page. + +## Wait for Language Confirmation (SCES-01331) + +The original SCES-01331 release's language selector continues on its own after a +countdown. This mod holds the countdown until you press Cross, like the existing +SCES-01330 mod. It checks the selector's original code before every write and +does nothing after the selector. `eu2/boot_profile.py` verifies the executable at build time; the mod +is omitted for the Rev 1 disc, whose selector binding is not verified. + +## Not integrated + +- RetroAchievements: held until RetroAchievements approves a recompiled client. +- The Windows-only multi-region entry program (`launcher_entry/`): a + multi-region chooser belongs in the shared launcher on every platform. +- Ore! Tomba (Japan, SLPS-01144): kept on its own branch until it reaches + feature parity with the USA and European builds. +- USA default changes (1080p, VSync off, SPU HQ on): the USA build is unchanged. diff --git a/eu/CMakeLists.txt b/eu/CMakeLists.txt index 0ad859f..3947185 100644 --- a/eu/CMakeLists.txt +++ b/eu/CMakeLists.txt @@ -47,6 +47,7 @@ psxrecomp_add_game_runtime(${tombi_target} DEFAULT_GAME_CONFIG_PATH "${tombi_config}" VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" MAX_PLAYERS 1 + LAUNCHER_BOXART "${CMAKE_CURRENT_SOURCE_DIR}/launcher_assets/img/boxart.tga" GEN_MARKER "${TOMBA_ROOT}/build-eu-prototype/generated/SCES_013.30_dispatch.c" GEN_FULL_GLOB "${TOMBA_ROOT}/build-eu-prototype/generated/SCES_013.30_full_*.c" PRELOADED_MODS_DIR "${tombi_mods}" @@ -117,6 +118,7 @@ if(TOMBI_PC_FEATURES) add_executable(tombi-host-sha-tests tests/test_host_sha256.cpp "${PSXRECOMP_ROOT}/runtime/src/psx_sha256.c") target_include_directories(tombi-host-sha-tests PRIVATE "${PSXRECOMP_ROOT}/runtime/include") target_compile_options(tombi-host-sha-tests PRIVATE -UNDEBUG) + add_test(NAME tombi_host_sha256 COMMAND tombi-host-sha-tests) add_executable(tombi-language-confirmation-tests tests/test_language_confirmation.cpp boot.c) target_include_directories(tombi-language-confirmation-tests PRIVATE "${PSXRECOMP_ROOT}/runtime/include" "${TOMBA_ROOT}/build-eu-seamless/generated") diff --git a/eu/boot.c b/eu/boot.c index d73005a..1548379 100644 --- a/eu/boot.c +++ b/eu/boot.c @@ -5,17 +5,17 @@ #include "eu_boot_profile.inc" static void selector_tick(void) { - if (psx_mod_read_word(0x80010E50u)!=0x27BDFF88u || - psx_mod_read_word(0x800112D4u)!=0x14620039u) return; + if (psx_mod_read_word(TOMBI_SELECTOR_START)!=0x27BDFF88u || + psx_mod_read_word(TOMBI_SELECTOR_BRANCH)!=0x14620039u) return; uint32_t hash=2166136261u; - for (uint32_t pc=0x80010E50u;pc<0x800114A0u;pc+=4) { + for (uint32_t pc=TOMBI_SELECTOR_START;pc>=8;} } if(hash!=TOMBI_SELECTOR_HASH) return; - const uint32_t remaining=psx_mod_read_word(0x800AF064u); + const uint32_t remaining=psx_mod_read_word(TOMBI_SELECTOR_TIMER); if(remaining>0 && remaining<=1000) - psx_mod_write_word(0x800AF064u,1000); + psx_mod_write_word(TOMBI_SELECTOR_TIMER,1000); } PSX_MOD_CONSTRUCTOR(tombi_register_language_confirmation) { diff --git a/eu/boot_profile.py b/eu/boot_profile.py index 165e1b0..a7efaf6 100644 --- a/eu/boot_profile.py +++ b/eu/boot_profile.py @@ -23,7 +23,7 @@ def word(pc):return struct.unpack_from(' +#include +#include +#include +#include +#include +#include +#include + +static uint8_t ram[2*1024*1024]; +static PSXModVBlankCallback tick; +static unsigned writes; +extern "C" int psx_mod_register_vblank_plugin(const char* id, PSXModVBlankCallback callback) { + assert(std::strcmp(id,"tombi.language-confirmation")==0);tick=callback;return 1; +} +extern "C" uint32_t psx_mod_read_word(uint32_t pc) { + uint32_t v;std::memcpy(&v,ram+(pc&0x1fffff),4);return v; +} +static void put(uint32_t pc,uint32_t v){std::memcpy(ram+(pc&0x1fffff),&v,4);} +extern "C" void psx_mod_write_word(uint32_t pc,uint32_t v){assert(pc==0x800AF0A4u && v==1000);++writes;put(pc,v);} +static void load(const std::string& path) { + std::ifstream stream(path,std::ios::binary);assert(stream); + std::vector bytes{std::istreambuf_iterator(stream),{}}; + assert(bytes.size()>2048);std::memset(ram,0,sizeof ram); + assert(bytes.size()-2048