Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
72 changes: 52 additions & 20 deletions components/tpm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down
37 changes: 21 additions & 16 deletions components/tpm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
30 changes: 19 additions & 11 deletions components/tpm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 "<your disc>.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
Expand Down
2 changes: 1 addition & 1 deletion components/tpm/tpm-decomp
Loading