diff --git a/README.md b/README.md index ac71c5b..6950175 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ run from decompiled source. `tpm-decomp/tools/recomp.py` translates every MIPS instruction of the executable into C, mechanically. That C is effectively Sony's executable in another form, so it is never committed or distributed. It is generated in the build directory from **your own** copy -of `SLUS_008.84` (`CONFIG_TPM_EXE_PATH`), so a playable TPM needs a local -build. The firmware from CI, built without the executable, carries only the +of the game (`CONFIG_TPM_DISC_PATH`, see Build below), so a playable TPM +needs a local build. The firmware from CI, built without the executable, carries only the cart's load-screen viewer. The goal is a real, matching decompilation: hand-written C that compiles back @@ -189,6 +189,13 @@ idf.py build flash monitor (Do not recurse into the engine's own submodules; they are desktop-only dependencies.) +The Phantom Menace is recompiled from your own disc at build time: set +`CONFIG_TPM_DISC_PATH` to your USA Rev 1 disc image (the `.bin` of a bin/cue +rip) in `idf.py menuconfig`, under "Star Wars Episode I: The Phantom +Menace", before building. Without it the build succeeds with a warning and +the TPM cart only shows the game's load screens. See +[components/tpm/README.md](components/tpm/README.md#building). + ## Controls Touch (virtual gamepad): diff --git a/components/tpm/CMakeLists.txt b/components/tpm/CMakeLists.txt index a9ce0c4..96148d2 100644 --- a/components/tpm/CMakeLists.txt +++ b/components/tpm/CMakeLists.txt @@ -17,36 +17,68 @@ set(TPM_ENGINE_READY OFF) set(TPM_GEN ${CMAKE_CURRENT_BINARY_DIR}/recomp) if(CONFIG_TPM_ENGINE) + idf_build_get_property(python PYTHON) + if(NOT python) + set(python python3) + endif() + # the disc image: the movie player overlay comes from it, and so does the + # executable when there is none at CONFIG_TPM_EXE_PATH + set(disc "${CONFIG_TPM_DISC_PATH}") + if(disc) + if(NOT IS_ABSOLUTE "${disc}") + set(disc "${CMAKE_SOURCE_DIR}/${disc}") + endif() + if(EXISTS "${disc}") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${disc}") + else() + message(WARNING "tpm: ${disc} not found (CONFIG_TPM_DISC_PATH)") + set(disc) + endif() + endif() set(exe "${CONFIG_TPM_EXE_PATH}") - if(NOT IS_ABSOLUTE "${exe}") + if(exe AND NOT IS_ABSOLUTE "${exe}") set(exe "${CMAKE_SOURCE_DIR}/${exe}") endif() - if(NOT EXISTS "${exe}") - message(WARNING "tpm: ${exe} not found (CONFIG_TPM_EXE_PATH): building without the game; " + if((NOT exe OR NOT EXISTS "${exe}") AND disc) + set(exe ${CMAKE_CURRENT_BINARY_DIR}/disc/SLUS_008.84) + endif() + if(disc AND exe STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/disc/SLUS_008.84" + AND (NOT EXISTS "${exe}" OR "${disc}" IS_NEWER_THAN "${exe}")) + execute_process( + COMMAND ${python} ${TPM_DECOMP}/tools/extract_disc.py "${disc}" ${CMAKE_CURRENT_BINARY_DIR}/disc SLUS_008.84 + RESULT_VARIABLE rc OUTPUT_QUIET ERROR_VARIABLE err) + if(NOT rc EQUAL 0) + message(WARNING "tpm: could not extract SLUS_008.84 from ${disc}:\n${err}") + file(REMOVE "${exe}") + endif() + endif() + # only USA Rev 1 works: the recompiler's configuration names its addresses + set(sha1_ok OFF) + if(exe AND EXISTS "${exe}") + file(SHA1 "${exe}" sha1) + if(sha1 STREQUAL "02f73ad2115f2fbb5bd1880615db0f9ac7b5055c") + set(sha1_ok ON) + endif() + endif() + if(NOT exe OR NOT EXISTS "${exe}") + message(WARNING "tpm: no SLUS_008.84: set CONFIG_TPM_DISC_PATH to your disc image (or " + "CONFIG_TPM_EXE_PATH to the executable). Building without the game; " "the cart will show the load screens only") + elseif(NOT sha1_ok) + message(WARNING "tpm: ${exe} is not the USA Rev 1 executable (SLUS_008.84, sha1 " + "02f73ad2...): building without the game") elseif(NOT EXISTS "${TPM_PSYZ}/psyz/src/platform/soft_raster.inc.c") message(WARNING "tpm: psyz missing at ${TPM_PSYZ} (git submodule update --init components/mgs/psyz)") else() - idf_build_get_property(python PYTHON) - if(NOT python) - set(python python3) - endif() - # Re-run when the executable or the recompiler changes - # the access sites that go to the scratchpad check it first - # the movie player overlay comes from the disc image, when there is one + message(STATUS "tpm: ${exe}") set(disc_arg) - set(disc "${CONFIG_TPM_DISC_PATH}") if(disc) - if(NOT IS_ABSOLUTE "${disc}") - set(disc "${CMAKE_SOURCE_DIR}/${disc}") - endif() - if(EXISTS "${disc}") - set(disc_arg --disc "${disc}") - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${disc}") - else() - message(WARNING "tpm: ${disc} not found (CONFIG_TPM_DISC_PATH): no movies") - endif() + set(disc_arg --disc "${disc}") + else() + message(WARNING "tpm: no disc image (CONFIG_TPM_DISC_PATH): no movies") endif() + # Re-run when the executable or the recompiler changes + # the access sites that go to the scratchpad check it first set(sites ${TPM_DECOMP}/config/scratch_sites.us.txt) set(sites_arg) if(EXISTS "${sites}") diff --git a/components/tpm/Kconfig b/components/tpm/Kconfig index 69ce846..da4ea32 100644 --- a/components/tpm/Kconfig +++ b/components/tpm/Kconfig @@ -6,28 +6,33 @@ menu "Star Wars Episode I: The Phantom Menace (tpm-decomp)" help Recompile the game's executable to C at configure time (tpm-decomp/tools/recomp.py) and build it with tpm-decomp's - runtime on psyz. Needs the USA Rev 1 executable at - TPM_EXE_PATH; without it the build carries on and the cart shows - the game's load screens (the data and display path) instead. + runtime on psyz. Needs your USA Rev 1 disc image at + TPM_DISC_PATH (or the executable at TPM_EXE_PATH); without it the + build carries on and the cart shows the game's load screens (the + data and display path) instead. - config TPM_EXE_PATH - string "Path of SLUS_008.84 (USA Rev 1), relative to the project" - default "components/tpm/tpm-decomp/disks/us/SLUS_008.84" + config TPM_DISC_PATH + string "Path of your disc image (.bin)" + default "" depends on TPM_ENGINE help - Your own copy of the game's executable, e.g. extracted with - tpm-decomp/tools/extract_disc.py. It is only read at build time; - nothing derived from it is committed. + Your own raw image of the game's disc, USA Rev 1 (the .bin of a + bin/cue rip, 2352-byte sectors), absolute or relative to the + project. This is the only setting a build needs: the executable + (SLUS_008.84) is extracted from it into the build directory, and + the movie player overlay (FMV.CPE) is recompiled from it. It is + only read at build time; nothing derived from it is committed. + Empty: give TPM_EXE_PATH instead, and the cart skips the movies. - config TPM_DISC_PATH - string "Path of the disc image (.bin), for the movies" - default "" + config TPM_EXE_PATH + string "Path of SLUS_008.84 (optional, relative to the project)" + default "components/tpm/tpm-decomp/disks/us/SLUS_008.84" depends on TPM_ENGINE help - Your own raw image of the game's disc (2352-byte sectors), absolute - or relative to the project. It is only read at build time: the - movie player overlay (FMV.CPE) is recompiled from it. Empty: the - cart skips the movies. + The game's executable (USA Rev 1), when you have it on its own, + e.g. extracted with tpm-decomp/tools/extract_disc.py. Used when + the file exists; otherwise it is extracted from TPM_DISC_PATH. + Only read at build time; nothing derived from it is committed. config TPM_MOVIES bool "Play the cutscene movies" diff --git a/components/tpm/README.md b/components/tpm/README.md index ee1b192..0449290 100644 --- a/components/tpm/README.md +++ b/components/tpm/README.md @@ -42,27 +42,35 @@ the game data read from the card. Help is very welcome; see tpm-decomp's ## Building -The recompiler needs **your own** copy of the executable at build time -(see above: nothing derived from it is committed). Extract it from your disc image and -put it where `CONFIG_TPM_EXE_PATH` points (the default): +The recompiler needs **your own** copy of the game at build time (see +above: nothing derived from it is committed). Point `CONFIG_TPM_DISC_PATH` +at your disc image (`idf.py menuconfig` > "Star Wars Episode I: The Phantom +Menace" > "Path of your disc image", absolute or relative to the project) and +build: ```sh -python3 components/tpm/tpm-decomp/tools/extract_disc.py ".bin" /tmp/tpm -cp /tmp/tpm/SLUS_008.84 components/tpm/tpm-decomp/disks/us/ +idf.py menuconfig # or put it in sdkconfig: + # CONFIG_TPM_DISC_PATH="/path/to/Star Wars - Episode I - The Phantom Menace (USA) (Rev 1).bin" idf.py build ``` -For the cutscene movies, point `CONFIG_TPM_DISC_PATH` at your disc image -too (read at build time only): the movie player overlay (`FMV.CPE`) is -recompiled from it, and the movies then play natively (tpm-decomp's -`rt_movie.c`; Start or Cross skips one). Without it they are skipped. +That is the only setting. At configure time CMake extracts the executable +(`SLUS_008.84`) from the image into `build/esp-idf/tpm/disc/` (again only +when the image changes), checks that it is USA Rev 1 by its SHA-1, and +recompiles it along with the movie player overlay (`FMV.CPE`), so the movies +play natively (tpm-decomp's `rt_movie.c`; Start or Cross skips one). `CONFIG_TPM_MOVIES` turns them off; builds with `CONFIG_TPM_AUTOPRESS` skip them anyway, for the scripted timeline. +If you already have the executable on its own, `CONFIG_TPM_EXE_PATH` +(default `components/tpm/tpm-decomp/disks/us/SLUS_008.84`, gitignored) is +used when the file exists; without a disc image the movies are skipped. + CMake runs `tools/recomp.py` when it configures (and again whenever the executable or the recompiler changes); the C lands in the build directory. -Without the executable the build still succeeds, with a warning, and the -cart falls back to the load-screen viewer below. +Without the game (or with another revision) the build still succeeds, with +a warning saying what is missing, and the cart falls back to the +load-screen viewer below. `components/mgs` links its own psyz under the same names, so the game, the runtime and their psyz pieces are linked into one relocatable object and diff --git a/components/tpm/tpm-decomp b/components/tpm/tpm-decomp index 83289bd..00fcb3b 160000 --- a/components/tpm/tpm-decomp +++ b/components/tpm/tpm-decomp @@ -1 +1 @@ -Subproject commit 83289bded547087e4b31c1e7973dd8c77cba59d3 +Subproject commit 00fcb3bd8f23f925644eab30d1c1e54d3ef922fb