Preserve current segmented dispatch, active-plan mod hooks and software scale limits. Extend function filters through the active plan, retain the last-store pointer with overlay ABI 25, and keep default config fingerprints stable. Refresh BIOS emitter stamps after byte-identical regeneration and reconcile regression fixtures.
docs/SEGMENT_AWARE_CODE.md:
- §5.7 gains "Implemented in PR E": capture's per-segment bitmaps and schema
v3; compile_overlays.py's segment views (including dispatch-less records and
declared demands); the static fragment images; overlay_codegen_config() for
config code sites; the cache layout and the S record; the loader's
per-segment lookups and counters (unmapped segments included) and the
overlay_candidates fields; the full-VA compares; tests.
- §3.4, §5.3 and §5.4 point at it.
- §7.1 describes the overlay acceptance cases and the overlay-segment-shards
guard; the ledger stays at zero gaps.
- §7.2 records the probe's new overlay phase against Beetle (both BIOSes,
cold, warm and interpreter), the LLE boot after E, and R4's KUSEG and KSEG1
kernel shards with segment_alias_interp at 0 on a warm cache.
- §8 E is recorded.
AOT_OVERLAY_PLAN (the manifest contract and capture schema), AOT_SHARDING,
OVERLAY_CACHE_V2, COMPILING_OVERLAYS (the cache layout) and OVERLAY_XREF
(schema v3) follow the design, and MOD_PACKAGES notes that function-entry
hooks reach overlay shards of every segment. FAITHFUL_TIMING_PLAN and
ACCURACY_BURNDOWN get dated entries: overlay segments are closed, the last
masked return compares (the overlay shadow run's) are now exact, mod hooks
reach KUSEG/KSEG1 shards, and axis 5 records the probe's BIOS file read taking
about half Beetle's cycles (found here, not caused here).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/SEGMENT_AWARE_CODE.md: §5.4 and §5.5 gain "Implemented in PR D"
(variant planning and compilation, the BIOS variants and BIOS segment
misses, the multi-row lookup, the five exact return checks, seeds outside
the physical segments); §3.3, §5.2 and §5.6 point at them; §5.2 and §5.4
say that the jump-table rule applies to every game and overlay compile, not
only to variants; the §7.1 ledger is at zero gaps with the new
exact-return-contract guard; §7.2 records the probe's compiled column after
D, the LLE boot after D (SCPH-1001 first hits at 0, shell entry -445), with
#435 on top (0 through the shell entry on both BIOSes) and after the review
fixes (every hit unchanged, no BIOS segment miss); §8 D and §9's IsC note
are updated.
FAITHFUL_TIMING_PLAN and ACCURACY_BURNDOWN get dated entries: the SCPH-1001
KSEG1 kernel entry and the masked call-contract checks are closed, and BIOS
alias entries without a variant are recorded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/SEGMENT_AWARE_CODE.md:
- Status names PR C. §3.1, §3.2 and §3.3 describe the folded parser and
the physical lookup in the past tense and point at §5.3/§5.5.
- §5.2: the dispatch rows are now tested (B's two surviving mutants), and
the code segment's default is the link segment.
- §5.3 and §5.5 record what PR C implements: link-segment compile, the JAL
scans, seed and config-site checks, KSEG1 home images, the exact lookup,
the segment-miss ring and its TCP/exit-report surfaces, and why
psx_call_contract stays masked until D (the BIOS dispatch loop's four
return checks share the contract).
- §5.4: until D a variant seed is reported, not compiled.
- §7.1: eight ids closed and kept as regression guards; two open.
- §7.2: the probe's compiled column after C equals Beetle and the
interpreter; cycle watch, spin totals and the segment-miss ring.
- §5.3 also records the seeds directives, collect_game_misses, which
config-site kinds are refused (exact matches) and which are not
(physical matches), and two consequences until later PRs: a KUSEG title's
overlay code runs interpreted until E, and a KSEG0 title's alias entries
into its own text run interpreted until D.
- §8: C's validation and cross-title impact (codegen hash: overlay caches
recompile once, pre-C savestates are refused); D also makes the five
masked return checks exact; E returns KUSEG titles' overlays to shards.
FAITHFUL_TIMING_PLAN gets the dated log entry. ACCURACY_BURNDOWN records the
closed axis-6 item, the axis-4 progress, and the masked call-contract checks
as an open item for D.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/SEGMENT_AWARE_CODE.md:
- §3.1 names emitter functions instead of line numbers, adds the
delay-slot jalr link and the VSync-query hook, and moves cosim_* out of
the identity keys.
- §5.2 records what PR B routes through runtime_pc(), what keeps the
compile address, the code segment's default (the image's own), and
what the tests cover (the dispatch rows wait for PR C).
- §5.4 notes that D's variants must tail-transfer jump-table cases in
another segment.
- §5.6 records that B routes emit_pre_icache's uncached test.
- §7.1 lists the two new regression guards; KNOWN_GAPS stays at 10.
- §7.2 adds the probe's interpreter and compiled columns next to
Beetle's.
- §8 records B's validation.
- §9 records the re-keyed store-PC keys and their SCPH-1001 gate, the
filters' Beetle divergence, and the confirmed game-syscall EPC gap
(its own change).
FAITHFUL_TIMING_PLAN and ACCURACY_BURNDOWN get the dated entries; the
burndown also records the RAM 0x0-0xF boot-scratch divergence from
Beetle. STRING_TRANSLATION's note that attributed GP0 quads to ROM
0xBFC38B1C now names the runtime key.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#429 charges psx_icache_fetch before every instruction whose runtime PC is
uncached, in both emitters, and makes the BIOS emitter's cache-line start
test use the runtime PC. The OpenBIOS check finds no uncharged KSEG1 site,
so segment_aware_codegen passes with 10 known gaps; bios-kseg1-fetch-charge
has not been in KNOWN_GAPS since the ledger's first commit in this series.
The check stays as a regression guard: an uncharged site reports the id as
a new gap.
docs/SEGMENT_AWARE_CODE.md:
- §5.6 describes the charge as landed, including the runtime-PC line-start
fix. The game emitter already has the predicate, but emit_pre_icache
tests the compile address: PR B must route both its psx_fetch_uncached()
argument and the fetch tag through runtime_pc(), and D adds the KSEG1
variants they reach.
- §7.1 lists ten open ids and records how A's id left the ledger.
- §8 marks A merged, with its Beetle parity (shell entry -126 on OpenBIOS,
-454 on SCPH-1001; the residuals are the IsC gap and SCPH-1001's KSEG1
kernel entry). D now only needs the KSEG1 variants; kseg1-fetch-charge
stays open until D. The macOS oracle recipe is docs/beetle-macos.md (#431).
- §1, §3.5 and the header say the BIOS undercharge is fixed. §10 is
unchanged.
- §3.1, §3.5 and §5.2 cite the emitter lines as they are after #429
(code_generator.cpp +6, full_function_emitter.cpp +10).
FAITHFUL_TIMING_PLAN §5 gets a log entry for the rebase.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Rebased onto master: #417 (the old base), #418 and #420 merged on
2026-09-29. The status line says so, and every cited source line is
refreshed for current master.
- PR A is #429. §7.2 records its passed LLE land gate against live Beetle
(shell entry -126 OpenBIOS, -454 SCPH-1001; ruler #1 64/64, ruler #2
14/14). The residue is the IsC gap (§9, now with per-flush numbers and the
prototype result) and SCPH-1001's KSEG1 kernel entry 0xA0000500 (§3.3, -9),
which PR D closes (§8).
- §7.2 records the synthetic EXE's first Beetle runs (macOS oracle recipe:
#431). Disc boot works on both BIOSes; sideloading does not, because
Beetle's loader forces a KSEG0 start. With the probe fixes, Beetle reads
56/56/82 cycles for KUSEG/KSEG0/KSEG1, a 26-cycle surcharge equal to the
fetch model's.
- Ledger values follow the new probe layout (probe_run 0x000100F0; 30 fetch
tags; leaf 22 vs Beetle 11). Still 10 ids.
- ACCURACY_BURNDOWN points the KSEG1 fetch item at #429; FAITHFUL_TIMING_PLAN
gets a dated log entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
memory.c:1292 also reads g_debug_last_store_pc in every build: a GP0 write
from 0xBFC38B1C gets a RAM source key for the widescreen prim matching. That
key lies in SCPH1001's Shell window (runtime 0x80050B1C), so it has to be
re-keyed with the other six when the BIOS stamp moves to runtime_pc().
List it in §3.1, §5.2, §9 and the FAITHFUL_TIMING_PLAN entry, and give each
relocated key its runtime PC.
§8: PR C closes eight ledger ids (§5.3's seven plus segment-miss), so
C and D close all ten; A (#429) closed the eleventh gap,
bios-kseg1-fetch-charge, on master. B's store-PC hole ships with the re-key of
all seven keys.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner settled §10's four questions on 2026-09-29, all as recommended:
- I-cache tags follow Beetle; the hardware bit-31 difference is recorded
in ACCURACY_BURNDOWN axis 4.
- Segment misses in static game code interpret loudly until the title is
regenerated.
- Extra segments are requested through segment-qualified seeds.
- The overlay cache uses per-segment subdirectories.
The doc called g_debug_last_store_pc a debug/identity hook. It is not:
memory.c's RAM 0x0-0xF store filters compare it with exact PCs in every
build, the interpreter stamps the full PC, and #420 (ABI v24) forwards
overlay stamps to the host. §3.1 now lists it as a baked PC, and §5.2
routes it through runtime_pc(). Consequences:
- Option A, re-measured with the 1,261 store-PC stamps in the three R4
shards: +3.8 % / +27.6 % __TEXT (was +3.2 % / +27.2 %).
- New ledger id store-pc-segment (10 KSEG0 stamps in the synthetic EXE's
home bodies), closed by §5.3. The ledger now has 10 known gaps.
- §9: several filter keys are ROM addresses of BIOS code that runs
relocated in SCPH1001. The BIOS emitter stamps ROM addresses and the
interpreter stamps runtime PCs, so the keys must be re-keyed when the
BIOS stamp moves to runtime_pc().
§8 notes that rollout PR A (fix/uncached-fetch-per-insn, based on master)
is being prepared. A has since landed as #429, so the ledger does not
list bios-kseg1-fetch-charge.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compiled code bakes KSEG0 into link values, CPS/IRQ resume PCs and I-cache
tags. KUSEG-linked EXEs run KUSEG PCs through those bodies (and their KUSEG
seeds are dropped), and overlay code executed at KUSEG/KSEG1 stays
interpreted after #417. Until #429, both emitters also charged the uncached
KSEG1 fetch only at cache-line leaders, so compiled BIOS ROM code was 4
cycles short on 5,477 of OpenBIOS's 9,592 KSEG1 instruction sites (Beetle
and the interp charge every fetch).
docs/SEGMENT_AWARE_CODE.md recommends per-segment compiled variants (code
identity = full VA, emitter segment as a per-compile constant, exact-segment
dispatch, per-instruction fetch in uncached bodies, segment-aware capture
and cache keys) over segment-relative emission, which measures +3.2 % /
+27.2 % __TEXT on R4 shards.
tools/segment_testrom/gen_segment_exe.py emits a synthetic KUSEG-linked
PS-X EXE that also works as an oracle probe. The new ctest
segment_aware_codegen runs the real recompilers on it and on OpenBIOS and
checks emitted PCs, the emitted dispatch lookup and fetch cycles (through
runtime/src/psx_icache.c) against a Beetle ReadInstruction transcription.
It passes only while the observed gaps equal its ledger (9 today).
#429 (rollout A) fixed the BIOS undercharge on master before this landed,
so KNOWN_GAPS does not list bios-kseg1-fetch-charge: the OpenBIOS check
finds no uncharged KSEG1 site and stays as a regression guard that reports
the id as a new gap. The last commit of this series brings the doc up to
date with #429.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only CPU stores are cache-isolated. Mods, the FMV skip, debug pokes, the
bg2d ring fill and the exception sentinel write guest memory from the host;
they now go through psx_host_write_*, which bypasses isc_store the way DMA
does, so a host store inside a FlushCache window reaches memory instead of
rewriting an I-cache tag. The render-pass checkpoint restores the new depth
counter like the DMA depth. isc_store_test covers it (a lane-0 host store in
tag-test mode would otherwise mark a cold line valid).
Docs: the SCPH-1001 residual starts at kernel init 0x598, and without #429
the fix removes 113 of the 126 OpenBIOS flush cycles.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FAITHFUL_TIMING_PLAN §5 (2026-09-29): with #429 on master, the LLE boot
now matches Beetle at every anchor to the shell on OpenBIOS (was -126)
and sits at -9 on SCPH-1001 (was -454), the KSEG1 kernel entry PR D
closes. Also measured without #429, the rulers (unchanged), R4's game
entry (+342 default boot, +18 LLE boot, 0 dispatch misses) and the
unchanged codegen hash.
ACCURACY_BURNDOWN axis 4: IsC item ticked; the SWL/SWR corner cases are
a new open item; the P2 scratchpad-under-IsC note points at Beetle's
rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The branch was rebased onto master 470f03b7, which now carries #418, so
the gate was re-checked on that tree without local merges. The
regenerated OpenBIOS and SCPH-1001 C is byte-identical to the gated
build's. Every boot anchor gives the same cycle (native - Beetle at the
shell entry: -126 on OpenBIOS, -454 on SCPH-1001). Ruler #1 matches Beetle
on all 64 passes, and ruler #2 on all 14 components on an HLE and an LLE
boot. uncached_fetch_charge and uncached_fetch_codegen_test pass. The
recompiler suite passes apart from the three environmental failures
master also shows on this Mac.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The land-gate entry said cyc_watch was armed from power-on on both
backends, but did not say how, and cited a local branch for the psx-beetle
build. The arming is PSX_CYC_WATCH / PSX_CYC_WATCH_N on psx-runtime and
psx-beetle (plus PSX_BEETLE_UNPACED=1 for a headless Beetle), documented in
docs/beetle-macos.md step 7 with the psx-beetle build; the entry now cites
both.
It also listed the shell entry as 0x80030000 on both sides. Both BIOS
profiles declare the shell window dispatch_key = "rom", so native keys it
at its ROM copy: the native anchor was 0xBFC0A500 (OpenBIOS) and
0xBFC18000 (SCPH-1001), and a native watch on 0x80030000 records nothing.
The numbers are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SEGMENT_AWARE_CODE.md §7.2 gates this change on an LLE boot with per-anchor
cycle parity against psx-beetle to the shell, plus ruler #1. Both ran on
macOS, each twice: with OpenBIOS (SHA-1 95419841b5104d552b14810b1ecbe6c1358bcdf1)
and with the owner's own SCPH-1001 dump (SHA-1
10155d8d6e6e832d6ea66db9bc098321fb5e8ebf), the same image on both sides. Native
master and this branch were built with #418 merged locally, so the mult/div
flush could not mask the result.
At the shell entry, native minus Beetle goes from -2,165,591 to -126 cycles on
OpenBIOS and from -7,049,462 to -454 on SCPH-1001. The ROM boot path is exact
on both. Two known gaps explain what is left:
- IsC stores do not reach the I-cache model, so a FlushCache leaves native
kernel lines valid that Beetle refills. A local prototype of Beetle's IsC
tag write takes OpenBIOS to 0 and SCPH-1001 to -9. It is recorded as an
axis-4 item here, not part of this change.
- SCPH-1001 enters its copied kernel through the KSEG1 alias 0xA0000500. The
four trampoline words run uncached in Beetle and cached natively (-9). That
is the KSEG1-alias gap in SEGMENT_AWARE_CODE.md §3.3.
Ruler #1 on SCPH-1001 matches Beetle on all 64 passes, on master and this
branch. Ruler #2 stays exact on all 15 loops. Beetle also confirms the memcpy
cost the branch now charges: 39 cycles per byte during boot, and 42 per byte,
860 and 3,884 cycles per call in R4.
The land gate item is ticked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 2026-09-29 log entry marked the live-Beetle validation OPEN inside a
done item. SEGMENT_AWARE_CODE.md §7.2 makes it a precondition for landing:
an LLE boot with per-anchor cycle parity against psx-beetle to the shell,
plus ruler #1. ACCURACY_BURNDOWN now carries it as its own unchecked gate
item, and the timing-plan entry says the PR stays draft until it runs on an
oracle machine.
The entry also framed the change as boot-only. OpenBIOS runs its A0/B0/C0
services in place, and 148 of its 192 A0 entries point into ROM, so the
per-instruction charge also applies during gameplay. Measured in an R4
race: memcpy's byte loop goes from 25 to 42 cycles per byte, and R4's two
memcpy calls per game frame go from 2,824 to 4,744 cycles (about 0.17% of
the frame). An LLE boot of R4 reaches the game entry 2,934,910 cycles
(1.10%) later, identical on two boots of each build, with 0 dispatch misses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cached line-leader rule charges a fetch at every 16-byte line start of
the runtime PC. The BIOS emitter tested bits[3:0] of the ROM address instead
and assumed every copy window preserves them. OpenBIOS copies its kernel from
ROM 0x1FC1E4D4 to RAM 0x500, which shifts them by 4. Each kernel line
crossing was charged one instruction early, where it is a hit, and the real
crossing went uncharged. 1,152 kernel instruction sites differed from the
interpreter.
The test now uses the runtime PC that relocate_ra already computes. In the
OpenBIOS kernel, 823 misplaced fetch sites go and 773 are added at runtime
line starts. Retail profiles are unaffected: SCPH-1001's copy windows are
16-byte aligned and SCPH-101/5552 declare none. The uncached_fetch_charge
ctest now also replays every cached OpenBIOS run from a cold cache against
the interpreter's fetch path and the Beetle transcription.
R4 (OpenBIOS, recompiled kernel, HLE boot) reaches the game entry 6,013
guest cycles later than with the uncached fix alone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Beetle's ReadInstruction never fills an I-cache line for a fetch at
0xA0000000 or above: every such fetch costs +4 and clears the pending load
give-back. The dirty-RAM interpreter charges that by fetching at every PC.
Both static emitters emitted psx_icache_fetch only at cache-line leaders,
which is exact for cached code only. In OpenBIOS, 5,477 of the 9,592
in-place ROM (KSEG1) instruction sites were uncharged: 21,908 cycles short
per pass through that code, each also missing its give-back clear.
Both emitters now charge a fetch before every instruction whose runtime PC
is uncached. The predicate is psx_fetch_uncached in psx_instr_cost.h, which
psx_icache.c now uses too. The A0/B0/C0 call-vector native stubs charge one
fetch per executed word, so a KSEG1 call pays like the interpreter. Cached
code keeps the leader rule. R4's regenerated game C is byte-identical, and
the OpenBIOS diff is insertions only. psx_instr_cost.h joins the codegen
hash list, since the emitters fold it into emitted code.
Tests:
- ctest uncached_fetch_charge runs psxrecomp-bios on OpenBIOS and compares
per-instruction fetch charges three ways: the compiled fetches, the
interpreter's fetch path (psx_icache_fetch_interp) at every PC, and a
Beetle transcription.
- uncached_fetch_codegen_test checks the game emitter at KSEG1 and KSEG0.
Both tests fail on master. This closes bios-kseg1-fetch-charge in the
segment_aware_codegen ledger (#419).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 2026-06-27 MMIO entry in FAITHFUL_TIMING_PLAN.md says the 13 prior
loops were unchanged when mmio_timer and mmio_spu were added. icache_miss
was not: the two new loops sit before it and move its loop top from
0x80010144 to 0x80010170, so each of its two misses costs one cycle more
and it reads +16 on both backends (re-measured against live psx-beetle; the
cycle_testrom README already explains the shift). The entry now carries a
dated correction, and the beetle-macos.md intro no longer points readers
at +14 as the current value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FAITHFUL_TIMING_PLAN gets the dated session entry and ACCURACY_BURNDOWN's
backend-equivalence item names the tool and the R4 warm/cold result.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Matched Ape Escape retail SCPH1001 LLE builds identify 0661ce77 as the visible boot regression: parent 155e269b reaches game code, while 0661ce77 stalls near BIOS frame 375. Revert its four dependent follow-ups too; retain PR #326 readback bounds and PR #328 Vulkan aspect changes.
The row-by-row raster dispatcher amplifies an existing malformed DMA list into massive GL work. Keep the broader CPU/DMA arbitration experiment separate for compatibility testing. Document attribution, validation, and the temporarily restored interlace limitation.
Validation: full Ape target reaches title/menu and frame 11669 on retail LLE; OpenBIOS control reaches frame 3701. Eight focused tests pass; retained GL readback fixture passes 71 checks at both 1x and 4x after linking local SDL with iconv. Beads: beads-iisy; DMA follow-up: beads-eio.3.122.
The repository root carried seven markdown files that were not onboarding
material, plus two that had been superseded by the code they described. This
sorts them: reader-facing docs to docs/, working notes to docs/internal/, and
the two superseded ones merged into the docs that replaced them.
Moved to docs/: WIDESCREEN.md, ENHANCEMENTS.md, TCP_COMMANDS.md
Moved to docs/internal/: PRINCIPLES.md, ISSUES.md, DEBUG.md, GTE_LM_FIX.md,
and from docs/: bios-hardening.md, overlay-status.md,
overlay-plan.md, overlay-recompilation-design.md,
overlay-discovery.md, TOMBA2_EXC_CONSULT_RESPONSE.md,
CASE_A_AOT_GAP.md, audit_inventory.md
Moved to docs/internal/upstream/: UPSTREAM_2026-08-20.md
The root keeps only what belongs there: README.md, CONTRIBUTING.md, LICENSE,
CLAUDE.md, THIRD_PARTY_ATTRIBUTION.md, RELEASE_NOTES.md, the dotfiles and
psxrecomp_cli.py.
MERGES
SPLITGEN_MIGRATION.md folded into docs/BUILDING.md as "Split generated C". Its
migration instructions were stale in a way that mattered: it told every game
repo to hand-edit its CMakeLists and add a file(GLOB ...) over
<serial>_full*.c, but runtime/runtime.cmake now does that itself. GEN_FULL_GLOB
is a multi-value argument of psxrecomp_add_game_runtime(); the loop at
runtime.cmake:1985 makes each pattern absolute against CMAKE_CURRENT_SOURCE_DIR,
expands it with file(GLOB), and concatenates the hits into
GAME_GENERATED_FULL_C. So a title names the pattern and gets however many shards
a regeneration produced. The rewritten section describes that, the two-step
fallback when the globs match nothing (GEN_FULL_FALLBACK, else <serial>_full.c
derived from the dispatch marker by substituting _dispatch.c), and the one
caveat the code actually has: that file(GLOB) is plain, not CONFIGURE_DEPENDS,
so a regeneration which changes the shard COUNT needs a re-configure to be seen.
psxrecomp-toml-readme.md folded into docs/GAME_PROJECT_SETUP.md as "EXE-only
autofill (psxrecomp-toml)", placed after "Disc autofill (probe_disc.py)" and
before "Project Studio" so the two autofill paths sit together. Its documented
flags were checked against the usage text in recompiler/src/main_toml.cpp:28-42
and against the argument parser at :150-165 -- all seven options match with no
drift, so the flag list is reproduced as-is. Added a pointer that probe_disc.py
is preferable when a cue exists, since that tool does the same EXE-header work
plus disc identity and netplay gates.
FUNCTIONAL FIXES
tools/gen_tcp_commands.py wrote to REPO/"TCP_COMMANDS.md". After the move that
path does not exist, so the generator would have created a new stray root file
and --check would have failed against it forever. Retargeted to
REPO/"docs"/"TCP_COMMANDS.md", along with the seven docstring and message
strings that name the path.
Running it surfaced two further problems, both fixed here:
* The doc was genuinely stale -- pre-existing drift, not introduced by this
commit (the moved file is byte-identical to origin/master, and no
debug-server command table is touched here). Four commands registered since
the last regeneration were missing from the index -- cdrom_timing_dump,
savestate_status, ws_ui_groups, xprobe_watch -- and scanline had gained a
backend. Regenerated: 307 -> 311 commands, and the change is confined to the
AUTOGEN block (the hand-written head and tail are byte-identical to master).
tools/gen_tcp_commands.py --check now exits 0.
* DOC.write_text() has no newline argument, so Python translated every newline
to os.linesep. On Windows that rewrote all 585 lines of the file to CRLF and
turned a four-line index update into a whole-file diff -- measured: 589 CRLF
/ 0 LF after a run, against 0 CRLF / 585 LF in the repo. Now written through
an explicit newline="" handle, verified to leave the file at 0 CRLF.
runtime/include/debug_server.h:9 and runtime/src/debug_server.c:8 cited "TCP.md
and DEBUG.md". TCP.md has never existed in this repo under that name; both now
name docs/TCP_COMMANDS.md and docs/internal/DEBUG.md.
LINK AND REFERENCE FIXES
Every inbound reference to a moved file was located by grepping each basename
across the whole tracked tree, not just the markdown. Markdown hrefs in
README.md, CONTRIBUTING.md, docs/ARCHITECTURE.md, docs/COMPILING_OVERLAYS.md,
docs/AOT_OVERLAY_PLAN.md, docs/RELOCATION_MANIFEST_FORMAT.md,
docs/config_schema.md, docs/OVERLAY_XREF.md, docs/TCP_COMMANDS.md and several
docs/internal/ files now point at the new locations; where two files became
siblings under docs/internal/ the path was shortened rather than lengthened
(bios-hardening.md's reference to overlay-discovery.md, for instance).
docs/COMPILING_OVERLAYS.md's "in this folder" phrasing was wrong once two of the
three files it listed moved, so it now names internal/ explicitly.
24 source-comment mentions of ENHANCEMENTS.md sections G1.x across 19 files
(recompiler, runtime, cmake) were retargeted to docs/ENHANCEMENTS.md with the
section numbers untouched. docs/SHADOW_ENHANCEMENTS.md is a DIFFERENT file and
was deliberately excluded.
20 rationale strings citing docs/CASE_A_AOT_GAP.md across the four
recompiler/seeds/*.json files were updated. Done as a byte-level substring
replacement rather than a JSON round-trip: two of those files are stored with
CRLF endings and two with LF, and re-serializing them reformatted 5,700 lines.
The byte-level version changes exactly 20 lines and each file still parses.
References that look similar but point elsewhere were deliberately left alone,
and are worth naming so a future pass does not "fix" them:
* "recomp-template PRINCIPLES.md" / "NES recomp template PRINCIPLES.md" in
CLAUDE.md:43, docs/SHADOW_ENHANCEMENTS.md:28,
docs/internal/HLE_SCHEDULER_CARVEOUT_PLAN.md:5,
runtime/src/debug_server.c:4934 and tools/parity_diff.py:8 are a different
repository's file. Only the five that mean this repo's PRINCIPLES.md were
updated.
* Every remaining bare ISSUES.md mention is a GAME repo's tracker
(MegaManX6Recomp 2/7/8/9, TombaRecomp 6), not this repo's.
* docs/disc-speed.md:4,54,56 and docs/internal/bios-hardening.md:5 name
overlay-discovery as a BRANCH, not a file, so no path applies.
INDEXES
README.md's "New here?" table gains rows for docs/WIDESCREEN.md,
docs/ENHANCEMENTS.md and docs/TCP_COMMANDS.md. docs/internal/README.md gains
sections indexing all fourteen documents that moved in, plus an "Upstream
contributor reviews" section describing upstream/ and the new sweep file, plus a
"Removed" bullet for CYCLE_TIMING_ARCH.md (deleted in the previous commit)
pointing at FAITHFUL_TIMING_PLAN.md, CYCLE_MODEL_BEETLE.md and
PRECISE_IRQ_SLICE.md -- following the SLJIT_PERSIST_CACHE.md precedent already
in that file.
docs/ENHANCEMENTS.md:7 claimed framework bugs live in "game repos' ISSUES.md
until a framework tracker exists". A framework tracker does exist; it now says
so and names the Beads epic.
VERIFICATION
A link checker was written to scan every tracked *.md for relative links,
resolving each against the tree being scanned. Baseline at origin/master: 129
files, 137 relative links, 3 broken. After both commits: 127 files, 159 relative
links, 3 broken -- the SAME three, all pre-existing and untouched here:
docs/DATA_SHARDS.md -> INSTANT_LOADS_PARKED.md (never existed)
docs/DATA_SHARDS.md -> INSTANT_LOADS_SPIKE2.md (never existed)
docs/NETPLAY.md -> ../lib/recomp-net/README.md (inside a submodule)
Zero new broken links. The checker's own coverage was checked against a raw grep
for markdown link openers: the 3-link difference is C++ lambdas inside code
blocks, correctly not treated as links.
Also verified: py_compile over all 113 tracked tools/*.py plus psxrecomp_cli.py;
all four seed JSONs still parse; the test-registration guard still reports 123
test files all registered; recompiler/tests/test_coverage_vault.py still passes;
and no file in this commit had its line endings flipped (checked mechanically
across all 50 modified files, after two files were caught and redone).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>