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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ concurrency:

jobs:
ci:
uses: THPS64Recomp/THPS64Host/.github/workflows/game-ci.yml@v0.2.0
uses: THPS64Recomp/THPS64Host/.github/workflows/game-ci.yml@v0.3.0
with:
game: thps2
host-tag: v0.2.0
host-tag: v0.3.0
secrets:
# Only while the repositories are private (RELEASING.md); empty, and unused, once they are public.
THPS64_READ_TOKEN: ${{ secrets.THPS64_READ_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ concurrency:

jobs:
release:
uses: THPS64Recomp/THPS64Host/.github/workflows/game-release.yml@v0.2.0
uses: THPS64Recomp/THPS64Host/.github/workflows/game-release.yml@v0.3.0
permissions:
contents: write # the draft release; the called workflow narrows it per job
with:
game: thps2
host-tag: v0.2.0
host-tag: v0.3.0
version: ${{ inputs.version }}
arch: ${{ inputs.arch }}
replace-assets: ${{ inputs.replace-assets }}
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ All notable changes to THPS2 64: Recompiled are listed here. The format is based

## [Unreleased]

### Changed
- Built on THPS64Host v0.3.0.
- Draw distance at Full draws the areas the courses hide by zone again, and only those: each course's trigger file is read at
its start to tell the zones the game hides for distance from the ones that hold course state (The Hangar's crashed ceiling
and its floor's light overlays), which stay as the game sets them. Rooms (a zone the course hides from its own doors, one
each in School II and Skatestreet) are left to the game.
- Tests: test rides claim a controller before steering, and an opt-in session records and replays a complete ride. Recorded
rides use a consistent replay step for the game's coupled timing values.

### Fixed
- School II at Full draw distance: patches of the sunlit ground no longer flash flat. The renderer was splitting those frames
into many separate passes; School II, NY City, Bullring and Philadelphia draw them in one pass again, which also takes about
1 ms less per frame.
- Philadelphia: trees at the edge of the view no longer smear and buildings no longer open holes as you turn, with frame
interpolation on.
- Skating tests read the actual physics dispatch state, so airborne and rail observations describe the skater correctly.

## [0.2.0-preview] - 2026-10-27

The second early preview, built on THPS64Host v0.2.0: split screen, Picture Border, rebinding, draw distance and the
Expand Down
2 changes: 1 addition & 1 deletion decomp/common
Submodule common updated 59 files
+1 −1 .github/workflows/ci.yml
+1 −1 .github/workflows/game-ci.yml
+3 −3 .github/workflows/game-release.yml
+61 −1 CHANGELOG.md
+9 −4 MAINTAINING.md
+43 −1 README.md
+120 −2 gen_versions.py
+36 −1 host/cmake/thps_host.cmake
+27 −3 host/docs/interpolation-ids.md
+2 −0 host/patches/README.md
+22 −0 host/patches/rt64-tlut-range.patch
+31 −0 host/patches/rt64-viewport-behind-camera.patch
+17 −1 host/src/control.cpp
+20 −0 host/src/dl_inspect.cpp
+63 −1 host/src/draw_distance.cpp
+18 −0 host/src/draw_distance.h
+884 −0 host/src/draw_distance_thps23.cpp
+30 −0 host/src/draw_distance_thps23.h
+3 −1 host/src/game_abi.h
+2 −0 host/src/game_imports.def
+40 −0 host/src/guest_mem.h
+1 −0 host/src/host.h
+44 −0 host/src/input_events.h
+93 −7 host/src/interp_ids.cpp
+33 −0 host/src/interpolation.cpp
+22 −1 host/src/main.cpp
+655 −0 host/src/ride.cpp
+22 −0 host/src/ride.h
+78 −0 host/src/ride_step_state.h
+110 −0 host/src/ride_v3_format.h
+11 −2 host/src/rt64_context.cpp
+9 −0 host/src/thps_hooks.h
+187 −0 host/src/trigger_zones.h
+3 −3 host/src/ui/ui_host.cpp
+2 −1 host/src/ui/ui_host.h
+224 −0 host/src/zone_ownership.cpp
+159 −0 host/src/zone_ownership.h
+1 −1 host/tests/cheat_sessions.py
+90 −0 host/tests/check_ctest_test.sh
+2 −1 host/tests/course_cycle.py
+4 −2 host/tests/hfr_steps.py
+90 −0 host/tests/input_events_test.cpp
+76 −0 host/tests/ride_format_test.py
+135 −0 host/tests/ride_harness_test.py
+38 −0 host/tests/ride_sessions.py
+128 −0 host/tests/ride_step_profile_test.py
+170 −0 host/tests/ride_step_runtime_test.cpp
+42 −0 host/tests/ride_step_state_test.cpp
+32 −0 host/tests/ride_test_host.h
+85 −0 host/tests/ride_v3_format_test.cpp
+138 −0 host/tests/run.py
+133 −0 host/tests/trigger_zones_test.cpp
+156 −0 host/tests/zone_ownership_test.cpp
+32 −2 host/tools/check.sh
+1 −0 host/tools/gen.py
+25 −0 host/tools/mingw_check.py
+2 −0 host/tools/package_split.py
+12 −0 host/tools/rom_free_ctest.sh
+4 −2 host/tools/setup_runtime.py
2 changes: 2 additions & 0 deletions decomp/thps2/recomp-host/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ set(THPS_HOST_ROOT "${THPS_HOST_ROOT}" CACHE PATH "The shared host tree (THPS64H
if (NOT EXISTS "${THPS_HOST_ROOT}/host/cmake/thps_host.cmake")
message(FATAL_ERROR "The shared host (THPS64Host) was not found: run `git submodule update --init`, or pass -DTHPS_HOST_ROOT=<a THPS64Host checkout>")
endif()
# The THPS2/3 engine's draw distance is shared in the Host (game/draw_distance.cpp here has only the profile).
set(THPS_GAME_EXTRA_SOURCES "${THPS_HOST_ROOT}/host/src/draw_distance_thps23.cpp")
include("${THPS_HOST_ROOT}/host/cmake/thps_host.cmake")
854 changes: 17 additions & 837 deletions decomp/thps2/recomp-host/game/draw_distance.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion decomp/thps2/recomp-host/recipes/eu/thps2.host.syms.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2315,7 +2315,7 @@ functions = [
{ name = "func_800A1824", vram = 0x800A1824, size = 0x1AC },
{ name = "func_800A19D0", vram = 0x800A19D0, size = 0x37C },
{ name = "SendSuspendOrActivate_maybe", vram = 0x800A1D4C, size = 0x154 },
{ name = "func_800A1EA0", vram = 0x800A1EA0, size = 0x340 },
{ name = "Trig_SkipCommand", vram = 0x800A1EA0, size = 0x340 },
{ name = "func_800A21E0", vram = 0x800A21E0, size = 0x1388 },
{ name = "func_800A3568", vram = 0x800A3568, size = 0x1C0 },
{ name = "func_800A3728", vram = 0x800A3728, size = 0x108 },
Expand Down
2 changes: 1 addition & 1 deletion decomp/thps2/recomp-host/recipes/us/thps2.host.syms.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2315,7 +2315,7 @@ functions = [
{ name = "func_800A17F4", vram = 0x800A17F4, size = 0x1AC },
{ name = "func_800A19A0", vram = 0x800A19A0, size = 0x37C },
{ name = "SendSuspendOrActivate_maybe", vram = 0x800A1D1C, size = 0x154 },
{ name = "func_800A1E70", vram = 0x800A1E70, size = 0x340 },
{ name = "Trig_SkipCommand", vram = 0x800A1E70, size = 0x340 },
{ name = "func_800A21B0", vram = 0x800A21B0, size = 0x1388 },
{ name = "func_800A3538", vram = 0x800A3538, size = 0x1C0 },
{ name = "func_800A36F8", vram = 0x800A36F8, size = 0x108 },
Expand Down
48 changes: 36 additions & 12 deletions decomp/thps2/recomp-host/tests/scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@
*([("press", "RIGHT"), ("wait", 45)] if lv == "school" else []),
("press", "A"), ("wait", 120), ("shot", "goals_" + lv),
("go", "A", "goals" if lv == "hangar" else "level_select", "in_level", 90),
("wait", 30), ("vpad", "attach"),
("wait", 30), ("vpad", "attach"), ("vpress", "a"),
("ctl", "projids"), ("ctl", "hfr"), ("ctl", "vpsplit"),
("ctl", "pcap 1 build/feel/" + lv), ("ctl", "vpad axis lefty -32000"),
*(_FEEL_TRICKS if __import__("os").environ.get("FEEL_TRICKS") else [
Expand Down Expand Up @@ -683,7 +683,7 @@
dict(name="cheats-explore", config="cheats-explore-config", fresh_files=["cheats.cfg"], fresh_pak=True, wav=False, optin=True, args=["--skip-intro"] + _os.environ.get("CS_ARGS", "").split(), scenarios=[
("cheats_explore", "exploration: first level, forward + ollie + flip + grind presses; skater state / rail balance / time scale samples", [
*BOOT_TO_MENU, *CAREER_TO_GOALS, ("go", "A", "goals", "in_level", 90), ("wait", 30),
("vpad", "attach"),
("vpad", "attach"), ("vpress", "a"),
("skater_watch", 80, _CS_TRY, ["Skater_PhysState", "Skater_RailBalance", "@gTimeScale"]),
("ctl", "vpad axis lefty 0"),
("go", "START", "in_level", "pause"), ("wait", 20), ("shot", "pause"),
Expand All @@ -705,7 +705,7 @@

# Draw distance (2026-10-17): career (unlocked levels), one level with the setting under test.
# Same steps as THPS1's dd-probe: a paused spot compared per factor (DD_AB), then a ride with frame times. Exploration only (optin).
# DD_RIGHTS: RIGHT presses at the level select; DD_TAG / DD_OUT: output; DD_ARGS: extra host args; DD_RIDE "lefty:frames ..." (x=... for leftx).
# DD_RIGHTS: RIGHT presses at the level select; DD_TAG / DD_OUT: output; DD_ARGS: extra host args; DD_RIDE "lefty:frames ..." (raw SDL axes, -32768..32767) (x=... for leftx).
_DD_DIR = _os.path.join(_os.environ.get("DD_OUT", "/tmp/dd"), _os.environ.get("DD_TAG", "run"))
_DD_SHOT = lambda name: [("ctl", f"pcap 1 {_DD_DIR}/{name}"), ("wait", 3), ("ctl", "pcap 0"), ("wait", 10)]
# DD_AB "K[:S] ...": factor K, with `dd showall S` first when given (1:0 = the game's own picture inside `full`); DD_TRACE=1: `dltrace 1` after
Expand Down Expand Up @@ -736,7 +736,7 @@
# DD_PRE "KEY:frames ...": presses before the ride, with a shot after each (e.g. with --skip-to-restart in DD_ARGS: the pause menu's
# SKIP TO RESTART to one of the course's restart points: repeatable spots all over the course)
*[s for st in _os.environ.get("DD_PRE", "").split() for s in (("press", st.split(":")[0]), ("wait", int(st.split(":")[1])), ("shot", "pre"))],
("vpad", "attach"),
("vpad", "attach"), ("vpress", "a"), ("wait", 20), # claim port 1 before any stick input
*[s for st in _os.environ.get("DD_RIDE", "").split() for s in (
(("ctl", f"vpad axis leftx {st.split(':')[0][2:]}"),) if st.startswith("x=") else (("ctl", f"vpad axis lefty {st.split(':')[0]}"),)) +
(("wait", int(st.split(':')[1])),)],
Expand Down Expand Up @@ -805,7 +805,8 @@
# Heap headroom with the always-allocated 2048-matrix pools (2026-10-22, the private development notes; optin, measurement): one career
# course (DH_COURSE: list position), loaded, skated ~12 s and ended from the pause menu (END RUN), `dd heap` (low-water marks since the
# start) after the load, after the ride and after the end. DD_ARGS: extra host args (e.g. "--draw-distance full", "--dd-buffers original").
_DH_PLAY = [("ctl", "vpad axis lefty -32767"),
_DH_PLAY = [("vpress", "a"), # claim port 1 before the stick-only route
("ctl", "vpad axis lefty -32767"),
*[x for k in range(12) for x in (("ctl", f"vpad axis leftx {(-32767, 0, 32767, 0)[k % 4]}"),
("ctl", "vpad button a 1"), ("wait", 8), ("ctl", "vpad button a 0"), ("wait", 22))],
("ctl", "vpad axis lefty 0"), ("ctl", "vpad axis leftx 0")]
Expand All @@ -831,7 +832,7 @@
# input, then pause -> END RUN and on through the end-of-run screens (DD_LONG_NAV: presses after END RUN) to the next course. Exploration
# only (optin): shots at every step, `dd` stats after each course (buffer peaks, governor), `stats` at the end.
_DDL_COURSES = [int(x) for x in _os.environ.get("DD_LONG_COURSES", "0 1 2").split()] # increasing list positions
_DDL_PLAY = lambda s: [("ctl", "vpad axis lefty -32767"), *[x for k in range(max(1, s // 2)) for x in (
_DDL_PLAY = lambda s: [("vpress", "a"), ("ctl", "vpad axis lefty -32767"), *[x for k in range(max(1, s // 2)) for x in (
("ctl", f"vpad axis leftx {(-32767, 0, 32767, 0)[k % 4]}"), ("ctl", "vpad button a 1"), ("wait", 8), ("ctl", "vpad button a 0"), ("wait", 52))],
("ctl", "vpad axis lefty 0"), ("ctl", "vpad axis leftx 0")]
_DDL_NAV = [s for p in _os.environ.get("DD_LONG_NAV", "A:120 DOWN:20 DOWN:20 A:150").split() for s in (("press", p.split(":")[0]), ("wait", int(p.split(":")[1])), ("shot", "nav"))]
Expand Down Expand Up @@ -965,7 +966,7 @@
("ctl_match", "dd", r"mode=original .* mtx_cap=420 "),
("ui", "esc"), ("ui_state", "open=1"), ("ui", "tab 2"), ("ui", "click #lbl_dd_full"), ("log", r"draw distance: full"), ("ui", "esc"),
("ctl", "dd reset"),
("vpad", "attach"),
("vpad", "attach"), ("vpress", "a"),
("ctl", "vpad axis lefty -32767"), ("wait", 150),
*[s for k in range(6) for s in (("ctl", f"vpad axis leftx {32767 if k % 2 else -32767}"), ("wait", 20), ("ctl", "vpad axis leftx 0"), ("wait", 20))],
("ctl", "vpad axis lefty 0"), ("wait", 30),
Expand All @@ -986,7 +987,8 @@
# guards are on (`dd dlprobe` canary 1; until 2026-10-26 it only asked for the variable in this comment, and `canary_bad 0` passed with no
# guard at all). Expected: no guard word changed, no budget cut at the default budget, no panic, no failed heap request. The forced cuts
# are dd-cut's.
_DS_RIDE = [("ctl", "vpad axis lefty -32767"),
_DS_RIDE = [("vpress", "a"), # claim port 1 before the stick-only route
("ctl", "vpad axis lefty -32767"),
*[x for k in range(6) for x in (("ctl", f"vpad axis leftx {(-32767, 32767)[k % 2]}"), ("wait", 15), ("ctl", "vpad axis leftx 0"), ("wait", 10))],
("ctl", "dd mode original"), ("wait", 4), ("ctl", "dd mode full"), ("wait", 4), ("ctl", "dd mode 2x"), ("wait", 4), ("ctl", "dd mode full"),
*[x for k in range(4) for x in (("ctl", f"vpad axis leftx {(32767, -32767)[k % 2]}"), ("wait", 20))],
Expand Down Expand Up @@ -1018,7 +1020,8 @@
# Frame pacing in a visible window (2026-10-23, the user's "stuttery" report; optin): the title left alone until the attract demo runs
# (frame times over PACE_DEMO frames), or with PACE_MODE=ride the first course (frame times over a 12 s ride). PACE_ARGS: host args (e.g.
# "--refresh 60"; another rate, test-only: THPS_TEST_REFRESH=display|N in the environment). Run it with THPS2_BINARY of the build to compare.
_PACE_RIDE = [("ctl", "vpad axis lefty -32767"),
_PACE_RIDE = [("vpress", "a"), # claim port 1 before the stick-only route
("ctl", "vpad axis lefty -32767"),
*[x for k in range(12) for x in (("ctl", f"vpad axis leftx {(-32767, 0, 32767, 0)[k % 4]}"), ("wait", 30))],
("ctl", "vpad axis lefty 0"), ("ctl", "vpad axis leftx 0")]
SESSIONS += [
Expand All @@ -1037,7 +1040,7 @@

# Fog (src/fog.cpp, graphics setting `fog`; optin, evidence): one course's run start, paused (FS_PAUSE=0: not paused), captured with the
# game's fog, Soft and Off, then the game's fog again (a second capture of the same state shows what moves on its own). FS_RIGHTS picks
# the course, FS_ARGS adds flags (e.g. `--draw-distance full`), FS_RIDE "lefty:frames ..." (x=leftx:frames turns) rides to another spot
# the course, FS_ARGS adds flags (e.g. `--draw-distance full`), FS_RIDE "lefty:frames ..." (raw SDL axes, -32768..32767) (x=leftx:frames turns) rides to another spot
# first, FS_STEPS "ctl command;shot NAME;..." adds steps (`fog soft 0.5;shot s50`: Soft starting at half the far plane). Captures:
# <out>/fs_<name>/ (composited frames at --present-size), the `fog` counters in the notes.
_FS_SHOT = lambda name: [("pcap", 3, f"fs_{name}")]
Expand All @@ -1053,7 +1056,7 @@
_FS_ARGS = ["--skip-intro", "--hidden", "--unlock-levels", "--present-size", "960x540", "--aspect", "16:9", "--window", "1280x720",
"--refresh", "60"] + _os.environ.get("FS_ARGS", "").split()
_FS_PAUSE = [
*([("vpad", "attach"),
*([("vpad", "attach"), ("vpress", "a"), ("wait", 20), # claim port 1 before any stick input
*[s for st in _os.environ["FS_RIDE"].split() for s in (
("ctl", f"vpad axis leftx {st[2:].split(':')[0]}") if st.startswith("x=") else ("ctl", f"vpad axis lefty {st.split(':')[0]}"),
("wait", int(st.split(":")[1])))],
Expand Down Expand Up @@ -1101,6 +1104,22 @@ def _fs_to_run(rights, settle=2):
from menu_session import fresh_defaults_session # noqa: E402
SESSIONS.append(fresh_defaults_session(_fs_to_run(1)))

# Culling boxes and state boxes (v0.3, game/draw_distance.cpp: the trigger table). One course's run start at Full (DZ_RIGHTS: RIGHT
# presses at the level select, 0 = The Hangar): the host prints the course's table once ("zones: ... culling boxes N (items M), state
# boxes ..."), to compare with the research table; exploration only (optin). DZ_STEPS "ctl command;..." adds steps after it.
SESSIONS += [
dict(name="dd-zones", config="dd-zones-config", fresh_pak=True, wav=False, optin=True,
args=["--skip-intro", "--hidden", "--unlock-levels", "--draw-distance", "full", "--window", "960x540"] + _os.environ.get("DZ_ARGS", "").split(),
scenarios=[
("dd_zones", "the course's trigger table: culling and state boxes (the host log)", [
*_fs_to_run(int(_os.environ.get("DZ_RIGHTS", "0")), 60),
("log", r"draw distance: zones: trigger file of [1-9]"),
("ctl", "dd"),
*[s for c in _os.environ.get("DZ_STEPS", "").split(";") if c.strip() for s in (("ctl", c.strip()), ("wait", 20))],
]),
]),
]

# A RETRY and the zone record (review 2026-10-26, finding 7): School II at Full. RETRY runs the course set-up again and rebuilds the item
# list at the same address and count, so the record (which items the zone culling hid, which an event owns) must start again: an item made
# event-owned in the first run (`dd own`, as an event naming it would) is not after the RETRY, and the items the set-up named are the same
Expand Down Expand Up @@ -1136,7 +1155,8 @@ def _fs_to_run(rights, settle=2):
# its bound, so the cuts leave out the farthest and none is made after the passes began (late_cuts=0: before the fix the passes after the
# first were counted at their average and an expensive far pass left the nearest ones out). The guard bytes are on (THPS_DD_CANARY) and
# intact. dd-stress checks the default budget (no cut at all).
_DC_RIDE = [("ctl", "vpad axis lefty -32767"),
_DC_RIDE = [("vpress", "a"), # claim port 1 before the stick-only route
("ctl", "vpad axis lefty -32767"),
*[x for k in range(8) for x in (("ctl", f"vpad axis leftx {(-32767, 32767)[k % 2]}"), ("wait", 15), ("ctl", "vpad axis leftx 0"), ("wait", 10))],
("ctl", "vpad axis lefty 0"), ("wait", 20)]
SESSIONS += [
Expand Down Expand Up @@ -1178,3 +1198,7 @@ def _fs_to_run(rights, settle=2):
]),
]),
]

# Input-only canonical rides (local recordings; shared harness steps consume playback through EOF).
from ride_sessions import ride_sessions # noqa: E402
SESSIONS += ride_sessions(_fs_to_run(0, 2), _CS_TRY, start_after="level_select", required_states={1: 10})
4 changes: 3 additions & 1 deletion decomp/thps2/recomp-host/versions/eu/data_syms.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ gWorldItems = 0x800DD7B4 # us + 0xC0 (translate_data.py, 26 votes)
gTimeScale = 0x800E886C # gPhysicsFrameTime * 7680 each frame (the frame update; Slow-Nic: / 4 while the skater does a trick)
gMusNumChannels = 0x801020A0 # MUS library globals: channel count; USA + 0xC0 (MusHandleStop 0x800D403C)
gMusChannels = 0x801020A8 # MUS library globals: the channel records (304 bytes each)
gTrgNodes = 0x800F3C10 # us + 0xC0 (the same loads in Trig_LoadTRG, eu 0x800A3728)
gTrgNodeCount = 0x800F3C14

[field]
View_Frustum = 0x160
Skater_ControlPtr = 0x1B04
Skater_PhysState = 0x1960
Skater_PhysState = 0x1EF0 # physics dispatch state: 0 ground, 1 air, 4 rail (USA 0x8008D7F4; Europe 0x8008D824)
Skater_RailBalance = 0x1D28 # rail lean; Cheat_IsOn(Perfect Balance) -> 0 in the rail physics
Intro_Timer = 0x250 # t2_intro screen: legal-text timer (float)
Intro_State = 0x260 # t2_intro screen: state word
1 change: 1 addition & 0 deletions decomp/thps2/recomp-host/versions/eu/host_force.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ splits = [0x800B6390] # USA 0x800B6360 + 0x30: the same hidden start after the
"0x800C50D0" = "Mesh_PassBegin" # = USA + 0x20 (the same body)
"0x800C50F0" = "Mesh_PassEnd" # = USA + 0x20 (the same body)
"0x800C6200" = "Mesh_QueueEmit" # = USA + 0x20 (the same body; the renderer offsets +0x21CC / +0x2AD8 are the same)
"0x800A1EA0" = "Trig_SkipCommand" # = USA + 0x30 (the same body; only its jumps differ)
"0x80042EA4" = "World_FindItem" # (list, name checksum) -> item: how the scripts' per-item commands (show / hide / kill by name) and the gameplay code find an item
"0x800B6848" = "Tv_IsHomeRegion" # returns gTvType == 0 (PAL console; USA's has the opposite sense): the region check
"0x800D1EF4" = "Music_LoadSong" # = USA 0x800D1E34 + 0xC0 (same code)
Expand Down
3 changes: 3 additions & 0 deletions decomp/thps2/recomp-host/versions/host_syms.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ funcs = [
"Gfx_SetupCourse", # (): the course gfx set-up (each course start, RETRY): display lists, matrix and vertex pools (draw distance: bigger display lists)
"Mesh_QueueEmit", # (renderer): draws the renderer's mesh queue and sorted list of one pass (draw distance: game/draw_distance.cpp)
"Music_LoadSong", # (player, song): the music player copies the next song over the playing one (src/music.cpp)
"Trig_SkipCommand", # (command) -> the next command of a trigger command list, 0 at its end (draw distance: the zone classification)
]

# Functions inside the front-end overlays, named by decomp/common/overlay_recomp.py from each class's
Expand Down Expand Up @@ -47,6 +48,8 @@ addr = [
"gRenderer", # draw distance: pointer to the renderer (mesh queue: 512 entries at +0x1CC, count +0x21CC; sorted list: 96 at +0x21D8, count +0x2AD8)
"gMusNumChannels", # MUS library: number of channels (word)
"gMusChannels", # MUS library: pointer to the channel records (304 bytes each; src/music.cpp)
"gTrgNodes", # draw distance: pointer to the course trigger file's node table (pointers to the nodes; Trig_LoadTRG)
"gTrgNodeCount", # draw distance: the number of trigger nodes (word)
]

# Struct field offsets (versions/<class>/data_syms.toml [field]): layout can differ between builds.
Expand Down
Loading
Loading