Current state (v0.0.2-alpha): Ape Escape boots from the PS1 BIOS and plays as
a native Windows program — through the intro, title, and gameplay, with dual-
analog controller input. It has not yet been verified all the way to the end, so
treat it as a very playable preview rather than a certified full playthrough.
Memory-card save/load now works (issue #4 fixed in v0.0.2) — progress saves
and loads back on standard .mcd images.
An experimental 16:9 / 21:9 widescreen mode is available in the launcher (off by default). It uses Ape’s stable GTE projection-and-stretch path for a wider 3D field of view. Regular 4:3 is the accurate default and is unaffected.
In widescreen, the title and some menu screens draw their sky as a GTE-projected 3D dome mesh authored to fill a 4:3 frame. Its curved edge doesn’t reach the corners of the wider frame, so those corners show black. The 3D world, gameplay skies, and cutscene skies all fill correctly — this is specific to the finite sky-dome billboards on a few screens.
Fixed by identifying the title overlay’s exact 16x16 sky-mesh projection
call (0x8013660C, return 0x80136614). Only that producer bypasses the normal
widescreen X squash, preserving its authored 4:3 coverage for the final frame
stretch. The old depth-gated experiment is not used, so attract-demo geometry
is untouched.
The ferris cabins remain submitted throughout the amusement-park shot on Ape’s original projection-and-stretch widescreen path. The unrelated native-wide compositor and broad automatic/per-object cull experiments were removed from the game config; those experiments caused severe attract-demo geometry wedges without owning the cabin behavior.
Separate from the edge culling above: the game stops drawing objects beyond a fixed distance from the camera (a classic PS1 draw-distance / far-clip cull). A wider field of view — especially at 21:9 — lets you see farther toward that limit, so distant objects can be seen spawning in and out by range rather than at the screen edge. This is a Z/distance cull, not an aspect-ratio one, so the edge-cull widening doesn’t touch it.
Desired: make the draw distance configurable (push it out so the player never sees distant objects pop in/out, in whatever aspect they’re playing). That means tracing the game’s distance-cull constant(s) and widening them behind a per-game config knob (an opt-in, since a larger draw distance costs some performance and changes the authored look). Same investigation shape as #1/#2 — deferred with them.
First opt-in pass (2026-10-15): The new Extended Draw Distance mod clamps ten
traced GTE SZ3 depth-bucket producer sites with expected-instruction guards.
It avoids raising the game’s ordering-table bounds and remains disabled by
default. This targets far primitives dropped at the ordering-table depth limit;
it does not remove every separate game-side far-clip test, so this issue
stays open until the effect and any remaining pop-in are checked in gameplay.
Reaching the memory-card screen to save or load progress did not complete. The low-level card protocol worked on both this runtime and the Beetle oracle (card reads succeed, an empty card reports empty, the SwCARD I/O-complete flag sets and the card fhandler runs), so this was a higher-layer timing race, not a dead card path. Two nondeterministic failure modes were seen: a soft stall on “Checking… MEMORY CARD” (the interrupt-driven async card read aborted partway), and, less often, a hard freeze from a register smear at the card-op consumer.
Fixed by a framework-level change to how a cooperative in-exception thread-switch is deferred across interrupt delivery. The deferred switch is now kept pending at dirty-interpreter pump sites (where a candidate resume PC is committed but the live CPU state may not yet be materialized) and is not deferred at all when the interrupted PC is in low BIOS/kernel space (which would otherwise re-enter the same VBlank handler forever and starve the target thread). The switch is honored only at a boundary where the resumed thread’s CPU state is coherent, so the card read/write completes cleanly. Class-level fix in the framework (no per-game poke); validated on Ape Escape and regression-checked against MegaManX6 and Tomba (1).
On the projection-and-stretch widescreen path, 3D geometry is squashed at GTE projection time so the final frame stretch restores its proportions. Screen-space 2D elements (HUD, menu text, cursors) are not projected through the squashed RTPS path, so the final stretch widens them: the HUD and UI render proportionally stretched in 16:9 / 21:9. Reported during play validation of the v0.0.3-era widescreen build.
Investigated 2026-07-10 (GP0 ring + wtrace provenance, Fossil Field).
hud_sprt_squash therefore cannot cover it, and untagged polys can’t be
blanket-squashed (the world is polys).func_8005BF70 (2588 B, jump-table-invoked, no static JAL callers) is the
UI/HUD orchestrator. It calls the gadget-cross drawer 0x80043A8C (dedicated,
builder 0x80044EF4), the L2-chip drawer 0x800691F8 (dedicated, SPRT-store
leaf 0x8002B380), and the HUD cookie-stack path 0x80063628 → 0x80017CD4 →
0x800180B8. Below 0x800180B8 the model-draw helpers (0x8001B3CC, the
0x8001A3xx store loops) are shared with world object rendering — the
HUD/world discrimination point is the orchestrator subtree, not the builders.Failed validation 2026-07-19. Function-bracketing and packet-writer guesses did not cover the title screen, the four-button gadget UI, or all character draw paths. A 21:9 gameplay capture also showed squashed Spike and unacceptable scene gaps. Those per-game hooks are disabled. The replacement must distinguish GTE-projected geometry from screen-space UI at the submitted packet itself and must pass paired 4:3 / 16:9 / 21:9 image checks before this issue is closed.
Fixed 2026-07-27. The framework now implements the auto_ui_squash
configuration already selected by Ape. Before a GPU DMA linked list is
executed, a read-only pass finds the highest ordering-table rank that actually
contains eligible textured UI. It groups adjacent glyphs/icons by texture and
screen row, computes the complete run bounds, and assigns one left/centre/right
anchor to every primitive in that run. The streamed GP0 commands are then
proportion-corrected around that shared anchor. This removes the old per-glyph
thirds decision that pulled the first and last letters of centred text in
opposite directions.
The classifier uses current-frame submission provenance rather than guest function names, packet addresses, or one-frame-old geometry. Depth-sorted world packets (including Spike) are below the selected UI layer, large backdrops are excluded, and trailing empty ordering-table buckets no longer hide the real front layer.
Validated on OpenGL with:
Capture 3 monkeys), gameplay HUD, pause wheel, exit
confirmation, and captured-monkey counter;The grouping math has a standalone regression test covering centred glyph runs, right-edge icon runs, separated left/right runs, and dense menu anchoring.
Near the beginning of the title/attract sequence, when Spike puts on his hat, the circus balls can appear or disappear within the visible 21:9 frame. This is not an FMV: it is a live rendered scene, and the original timing only guarantees that these objects enter outside the 4:3 viewport.
Investigation stopping point (2026-07-28):
0x80136000. Its event loop dispatches object
record opcode 0x0F through the handler at 0x80138404, which ultimately
submits the object through 0x800160EC.0x800BFAC0. In an unmodified control run its first submission occurs at
title-local frame 153 (host frame 1815). The exact 36-byte stream record was
captured, so this path can be recognized again without repeating the broad
search.Before resuming, compare the exact widescreen/culling configuration and build state from the better-looking run against the latest run. Capture paired frames around the hat animation and trace both ball objects, including their changing transforms and visibility decisions. Do not treat an earlier static submission by itself as closure.
The frame-smoothing guard was reviewed separately from the known widescreen issues. Phase value 3 is the active-gameplay phase used by the project’s gameplay plugins; the frame-replay hook had been rejecting that phase and therefore disabling interpolation during normal play. The guard now excludes transition/loading phases 4–6 but lets active gameplay reach its guarded capture/replay path. This is a source-level fix; verify smoothness, transition safety, and audio synchronization on actual hardware before declaring it glitch-free.
The remaining reproducible visual targets are documented above (#3 and #6). The broader regression checklist will track title/attract, FMVs, stage transitions, pause/resume, save/load, stock 4:3 and widescreen. No global audio engine setting or stock 4:3 rendering behavior was changed without a confirmed defect.
Reported 2026-10-18/19 in Nightly testing. PGXP still leaves obvious wobble, floor seams and warped textures and can look worse when enabled. Shaking is also visible with PGXP disabled.
The earlier mitigation only changed PGXP precision configuration and did not enable renderer-side seam correction. The recorded submodule pin also disagreed with framework_pins.txt. On 2026-10-19 the project was moved to framework revision 4102438ab4c5aadf010878029d0324ef6382e521, the narrow upstream revision that adds the PGXP depth buffer and seam-expansion renderer. game.toml now enables pgxp_depth_buffer = true and pgxp_seam = "wide"; the optional PGXP manifest exposes precise culling and enables it when (and only when) PGXP is selected. This targets two additional crack classes: high-resolution T-junction gaps and polygons dropped by integer-coordinate culling. The changes remain unverified against a live game capture; they are not closure.
Some sub-pixel vertex wobble when PGXP is off is normal PS1 behavior: GTE screen coordinates lose their fractional pixel position and large polygons use affine texture mapping. However, broad scene shaking, stutter, or additional anomalies cannot be declared authentic without a matched 4:3, PGXP-off comparison against the rebuilt runtime.
User reports visible and off-putting widescreen artifacts. The current widescreen feature still uses the projection-squash-and-stretch path, so the PGXP renderer upgrade does not fix its separate world-culling/background geometry defects (including issues #3 and #6 above). Keep Widescreen explicitly experimental and disabled by default; do not describe it as fixed. This change deliberately does not enable the shelved native-wide path because prior experiments produced geometry wedges. Validate widescreen separately with matched 4:3/16:9/21:9 captures.