mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 19:07:47 -04:00
4b2fdfadc35858cc68614d50737e2320baef265c
15 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
16d3672526 | Add build-selected execution contracts and stateless HLE GTE service | ||
|
|
e6ce5006b4 |
docs: move root and stale docs into docs/ and docs/internal/
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>
|
||
|
|
77d036bfb6 |
docs: production-friendly contributor docs + declutter root
Make the repo approachable for outside contributors and an IDE integrator:
- New contributor docs:
- docs/EXECUTION_MODEL.md — semi-technical tour of the static / native-overlay
/ interpreter execution model and how coverage gaps get plugged.
- docs/ARCHITECTURE.md — component-level view (recompiler, runtime, LLE+HLE
BIOS, overlay backend static->gcc->tcc, renderers, oracle model).
- docs/BUILDING.md — accurate dependency table, per-platform prereqs, build
steps, and the submodule + local-junction framework-linking setup.
- CONTRIBUTING.md — distilled core rules, verification expectations, PR flow.
- Declutter root: move ~14 internal dev-logs into docs/internal/ (history
preserved via rename) with an index README; repoint CLAUDE.md references.
- README: correct build recipe, LLE+HLE + overlay-backend summary, links to the
new docs.
- code_provider.c: update the stale backend comment to the real static->gcc->tcc
resolution (dead SLJIT.md reference removed).
- config_schema.md: drop the obsolete "once Phase A2/A3 ships --config" note.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
864ac4039d |
bios_hle: default ON (HLE boot-skip is the shipping default)
Flip the framework default bios_hle false->true so every game boots via the HLE shell-skip by default (instant boot for players) instead of the real BIOS intro. This changes NOTHING institutional: LLE (the recompiled BIOS) is still what we BUILD against, the reference implementation, and the oracle — fully linked, load-bearing, and the target of every accuracy check. HLE is a QoL layer on top; the faithful core is proven, so defaulting the convenience on is an enhancement-phase load-time win, not an architecture change. Opt OUT per-game with [runtime] bios_hle = false or env PSX_BIOS_HLE=0. Codegen-neutral (config_loader is not a codegen-hash source); games inherit it on next build. New bring-up + all verification stay on LLE. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c3c43e68ae |
launcher: drop the "Skip PSX BIOS" toggle — HLE boot-skip is automatic now
Releases ship [runtime] bios_hle = true, so the boot skip is on by default and no longer a per-user launcher setting (the old toggle also described the retired snapshot mechanism's "first boot still loads" behavior, which no longer exists). Power users can still set bios_hle / fast_boot in settings.toml or game.toml by hand. Also aligns CLAUDE.md: the session-start mantra now points at the §0 amendments instead of a blanket "No HLE", and the 2026-07-02 amendment names the real config key ([runtime] bios_hle). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
582aeccdac |
bios: HLE as a first-class swappable tier (gbarecomp model) + HLE boot shell-skip
USER PIVOT 2026-07-02 (CLAUDE.md §0 amendment included): psxrecomp now carries an opt-in High-Level Emulation backend alongside LLE. LLE (the recompiled BIOS) stays the default, the reference implementation, and the correctness/timing oracle; every service HLE does not implement falls through to LLE, so HLE is never load-bearing beyond what it covers. Mechanism: full_function_emitter.cpp emits a null-by-default hook g_psx_bios_hle_hook consulted at the top of every psx_dispatch_impl iteration, on the pre-normalize physical address, BEFORE any backend (game image / dirty-RAM / static table) claims the target. A handled call resumes at $ra through the trampoline's existing return/tail contract. NULL (default) = pure LLE, dispatch-identical. Regenerating BIOS+game images is required (emitter change). v1 call-HLE (runtime/src/bios_hle.c): the B0 event family — DeliverEvent (incl. callback dispatch with the kernel-true $ra 0x1720), OpenEvent, CloseEvent, TestEvent, EnableEvent, DisableEvent — each ground-truthed instruction-by-instruction against the SCPH1001 kernel disassembly (0xBFC11644..0xBFC11A84) and operating on the REAL guest EvCB table ([0x120]/[0x124], stride 0x1C). WaitEvent/threads/pads/card/A0/C0 fall through to LLE. Cycle charges are documented approximations; LLE remains the timing oracle. No-stubs stands. Boot HLE: with the tier on (and no keep-intro opt-out) the hook one-shot intercepts the first dispatch of the BIOS shell entry (RAM 0x30000 — LoadRunShell's indirect call always routes through the dispatcher), so BIOS Main() proceeds straight to SYSTEM.CNF + game EXE load with kernel state built entirely by the real recompiled kernel init, unpaced (boot turbo) until game handoff. This REPLACES the fast_boot snapshot capture/restore; fast_boot=true now aliases the boot-skip alone. Selection: [runtime] bios_hle / bios_hle_keep_intro (+ settings.toml bios_hle mirror), PSX_BIOS_HLE / PSX_BIOS_HLE_KEEP_INTRO env overrides, startup banner bios_backend=/bios_boot=. The PSX_HLE_SCHEDULER spike is folded in as the tier's standing subsystem replacement: default from [runtime] hle_scheduler via psx_hle_scheduler_set_default, env wins. Observability: always-on 16K-entry HLE ring (route LLE-fallthrough / HLE / boot-skip per record) + hle_dump TCP command (TCP_COMMANDS.md). VALIDATED on Tomba (build-wt): LLE pass byte-identical behavior (real intro, card check, save/load OK); HLE pass boots shell-less, TestEvent/ DeliverEvent route HLE, ChangeTh/ReturnFromException/OpenTh/CloseTh and the card stack fall through to LLE, save/load OK (user-driven). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
dea4de0c3b |
docs: ground LLE-first / faithful-HLE-subsystem-replacement policy + scheduler carve-out plan
CLAUDE.md §0 AMENDMENT: the three prohibitions (no interpreter / no HLE BIOS layer / no stubs) are now the DEFAULT, not an absolute ban on all HLE. A faithful HLE *subsystem replacement* is permitted when ALL hold: (1) a genuine LLE landmine (non-determinism with no hardware analog, or profound perf loss), (2) general not per-game, (3) operates on the real guest structures + reproduces the documented mechanism, (4) continuously Beetle-validated. It is a deliberate subsystem replacement on a proven LLE baseline, NEVER the starting point; the fake-the-answer HLE shim stays forbidden. Rule -1 scoped to the foundation phase. Faithfulness is the FOUNDATION, not the destination. HLE_SCHEDULER_CARVEOUT_PLAN.md: the first carve-out — replace the non-deterministic host-fiber cooperative-thread bridge with a deterministic TCB scheduler (BIOS scheduler is pure-TCB, no stack switch). ChatGPT-conferred design "A+" + 8-step minimal plan + invariants captured. Diagnosis gate (thread1 timeline diff vs Beetle) precedes implementation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
09a5d451d1 |
docs: full accuracy burndown across all axes (ACCURACY_BURNDOWN.md)
Per-axis (semantics/cycle/IRQ/MMIO/peripherals/static-dynamic/determinism) burndown with the external comparative to cross-reference each item against (psx-spx, in-tree Beetle source, DuckStation, HW test ROMs) + validation method. 'Looks good' is not a status until cross-referenced + oracle-validated. Axis 5 (peripherals; esp SIO/controller = the Tomba hybrid-pad bug) flagged as suspected-weakest. Phasing: validate on Tomba 2, then cross-title, then merge, then post-merge burndown for the rest. Referenced from CLAUDE.md Rule -1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f9d50d7503 |
fix(tomba2): delay-slot cycle accounting -> Tomba 2 reaches the intro FMV
The multi-week Whoopee-Camp logo->FMV stall was a TIMING-FAITHFULNESS bug, not
game logic: the static recompiler charged cycles block-granular and a branch
whose delay slot is a SEPARATE block leader (branch at end_addr, delay slot
outside the block) undercharged by one cycle on every execution -- the
always-executed delay-slot clone was emitted but counted by neither the branch
block nor the (unentered) delay-slot block. ~8 such sites on the boot init path
= the measured -8 cycle drift that made native run behind the interpreter, so
the frame-1824 elapsed-Timer1 logo-delay loop exited after ~42 iterations
(native) instead of ~1557 (interp/HW) and never reached the FMV.
Fix (code_generator.cpp translate_basic_block, the faithful class fix -- every
dynamically executed instruction charged exactly once):
block_exec_cycles = instruction_count
+ (exit branch at end_addr with delay slot outside ? 1 : 0)
applied to both the block cycle charge and the slice budget. R3000 is MIPS-I so
the delay slot is unconditional; the not-taken path already falls through to
branch_pc+8 (no double-count). Result, screenshot-verified: native passes the
logo-delay loop, screen animates, CDROM+DMA stream active, the jungle intro FMV
plays.
Also in this checkpoint (all on wt/tomba2, not merged/pinned):
- PARKED precise interrupt-slicing (PRECISE_IRQ_SLICE.md): root-caused its pc=0
boot exit to a mid-function clean-text resume PC the dispatcher can't re-enter;
ChatGPT-validated fix is "every block leader = re-enterable CPS continuation"
(psx_game_is_function_entry predicate added; precise_pc_dispatchable +
irq_taken-once restructure in psx_run_precise). Default OFF (PSX_PRECISE_SLICE=1
to resume); inert on the baseline. Slice-trace diagnostics added to freeze_check.
- FAITHFUL_TIMING_PLAN.md: authoritative game plan (P1-P6) + standing directive
(build the faithful core, never hacks; ecosystem is being built, not preserved);
referenced from CLAUDE.md Rule -1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
7a12a0baac |
two-process refactor: replace embedded oracle with independent psx-runtime + psx-beetle
Switches diagnostic methodology from a single binary running both backends in lockstep (psx-beetleoracle.exe) to two independent processes: psx-runtime.exe (recomp only, port 4370) psx-beetle.exe (Beetle libretro only, port 4380) Both expose the same JSON wire protocol for the common debug commands (read_ram, press, set_input, clear_input, pad_status, screenshot_file, wtrace_*, fntrace_* on Beetle). Cross-process comparison is done by querying both ports from a tool, NOT by sharing input or memory. Why: the embedded-oracle setup required keyboard input to drive both backends in lockstep. Once their state diverged, the same keypress drove them to different screens and "compare on the same press" became unreliable. Two independent processes lets each backend be navigated to its own state and queried on its own timeline. Removed: - runtime/src/beetle_psx_bridge.cpp (cannibalised into beetle_libretro.cpp) - runtime/src/duckstation_bridge.cpp - runtime/src/psx_oracle_cmds.c - runtime/src/psx_oracle_stub.c - runtime/include/psx_oracle_backend.h - psx-beetleoracle and psx-dsoracle cmake targets - 22 dual-backend tools (emu_read_ram / find_first_divergence / etc) Added: - runtime/src/beetle_main.cpp (SDL window + libretro driver + keyboard) - runtime/src/beetle_libretro.cpp (libretro callbacks + wtrace/fntrace/sio rings) - runtime/src/beetle_debug_server.c (TCP server, port 4380, same wire protocol) - psx-beetle cmake target Also bumps tooling caps surfaced during modal investigation: - DIRTY_RAM_BLOCK_LOG_CAP: 16K -> 4M (28ms eviction -> ~7s retention) - WTRACE_MAX_RANGES: 16 -> 64 (boot defaults filled the prior cap) - DirtyRamBlockLogEntry: added a0/a1 fields for richer dispatch context CLAUDE.md section 16 rewritten for the new methodology. New memory note locks the direction so future sessions don't reach for the deleted embedded-oracle commands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5b3c7dd08d |
phase4: freeze_check diagnostic + accumulated overnight infra
Today's session work
- runtime/src/debug_server.c: freeze_check TCP cmd snapshots all liveness
counters (PC, exception entries, exception_reentry_blocks, dirty_ram
blocks/insns, fn_entry total + top-K histogram, SIO IRQ pending +
countdown, sio_stat/i_stat/i_mask, mc_max_state) for tight-loop
diagnosis when the runtime hangs
- runtime/src/debug_server.c: wtrace slot 12 covering [0x72F0..0x72F4]
(data-byte counter); measured peak=1 confirming setup_data_phase resets
the counter mid-cycle
- runtime/src/interrupts.c: exception_entries_total + exception_reentry_blocks
counters + psx_get_freeze_diag accessor
- runtime/src/sio.c: sio_get_freeze_diag accessor for IRQ pacing internals
- memory entries: phase4_card_gate_setup_writes_2026_04_28 (refutes the
prior \"missing [0x7568+slot] clearer\" framing — setup functions write
LSB=0 directly), phase4_72f0_one_byte_per_vblank_2026_04_28 (peak=1
measurement)
Overnight session work bundled in
- runtime/src/dirty_ram_interp.{c,h}: small MIPS interpreter for
install-at-runtime kernel RAM stubs (Rule 18; e.g., SIO data-byte
handler the BIOS writes to RAM 0xCF0)
- recompiler/src/full_function_emitter.{cpp,h}: 3057 jal/jalr continuation
return labels added to dispatch table (continuation fix); branch
fall-through fix for conditional-branch delay slots
- recompiler/src/strict_translator.cpp: matching translator updates
- generated/: regenerated SCPH1001 dispatch + full C output reflecting
the recompiler changes
- runtime/include/debug_server.h, src/memory.c: card_txn ring + SIO IRQ
ring + EvCB walk ring + per-PC dirty_ram counters + always-on wtrace
coverage for [0x755A], [0x7514], [0x7528], [0x7520], [0x74A4],
[0x75C0..C8], [0x74B8..C0]
- recompiler/tests/, runtime/tests/: SIO/card protocol unit tests
- tools/: 60+ Python diagnostic scripts (chain_trace analysis, SIO trace
diff, EvCB walker, wtrace dumpers, etc.)
- docs/: psx_bios_disasm reference + dynamic_handler_install rationale
- OVERNIGHT_2026_04_28.md, SUMMARY_20260412_2.md: session logs
Phase 4 status (still blocked, root cause better understood)
- BIOS card chain runs through R-handlers correctly (chain_trace shows
R1..R11 cycling 26x); shell IS retriggering _card_read
- Install handler at ROM 0xBFC15F1C increments [0x72F0] correctly per
SIO IRQ; gate at <0x80 / <0x7F is correct
- Bottleneck: SIO IRQ countdown is access-paced, fires ~1× per VBlank
vs ~128× needed; setup_data_phase (called from outer coord on VBlank)
zeroes [0x72F0] before counter reaches 128
- Both attempted fixes today caused freezes:
* VBlank deferral on [0x75C0]==1 — pending VBlank already in i_stat
delivered anyway; tighter dispatch gate also locked up
* Cycle-paced sio_tick at rates 50, 200 (and gated on [0x75C0]==1) —
runtime freezes once data phase activates, root cause unidentified
- delay=5 narrows the threshold (peak=2 vs peak=1, no freeze) but
doesn't get to 0x80
- Real fix likely requires deeper instrumentation of the freeze (call
stack / dispatch state at the moment of TCP starvation)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
b02aa963c3 |
docs: add Rule 17 — Phase 5 gate requires fixing hardware stubs first
STUBS_TO_FIX.md lists MDEC, SPU, and DMA channel stubs that must be implemented before loading any game. Rule 17 makes this a hard gate so the stubs can't be forgotten under schedule pressure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
20625d5803 |
docs: add CLAUDE.md Rule 15 — fix broken tooling, never route around it
When a tool fails, fix it. Never infer correctness from indirect evidence. Never declare "correct" without visual oracle verification. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
685687f36f |
Restructure duckstation as submodule + patch; salvage TCP docs + debug_client
Recovery + restructure after rm -rf destroyed duckstation/build/ earlier this session. Adopts the nesrecomp pattern (see F:/Projects/nesrecomp): pristine upstream as submodule, our changes as a patch file that gets auto-applied by a setup script. Submodule: - duckstation/ now pins stenzek/duckstation@ffb33c281 (release-20260328 era) - .gitmodules records the pin; .gitignore stops ignoring the submodule path but still ignores build/ and dep/prebuilt/ (the submodule's own .gitignore also handles these) Patch + setup: - tools/duckstation/psxrecomp_oracle.patch (1187 lines, 7 files) captures our TCP debug-server on port 4371 plus the unfinished pc_break family of commands (with the VirtualMemoryAddress compile fix) - tools/duckstation/setup.sh clones submodule, fetches + verifies + extracts prebuilt Windows deps, rewrites stale absolute paths baked into the prebuilt CMake metadata, applies the oracle patch. Idempotent. - tools/duckstation/build.sh configures CMake (VS 17 2022) + runs MSBuild, then provisions bin/ with portable marker, BIOS copy, and settings.ini post-fixes - tools/duckstation/README.md documents the layout, the regeneration flow, and the known headless-boot configuration issue TCP documentation (salvaged from v3): - TCP_COMMANDS.md: full command table with native (4370) / duckstation (4371) / both columns, reflecting actual v4 implementation including wtrace_* and pc_break/pc_hit_last families - tools/debug_client.py: unified CLI from v3 (ports 4370/4371 match v4) - DEBUG.md: merged v3's END-TO-END COMPLETION RULE, Stale Hypothesis Rule, TOOLING RULE, and TOOL LIFECYCLE RULE sections into v4's existing loop Phase 4 diagnostic artefacts from this session: - generated/relocation_proofs/vblank_registrar/ — corrected VBlank-stall diagnosis. Prior handoff claimed the shell VBlank handler was never installed; live TCP inspection of both runtime and DuckStation oracle proved handler IS installed at 0x800DFEE0. Real gap is one level up in the kernel IRQ chain at *(0xA000E014). - tools/duck_query*.py, duck_search.py, disasm_ram.py, scan_*.py — focused probes used to establish the above; reusable against either server CLAUDE.md §2 and new §15 document the submodule-based oracle setup and the "never edit submodule, regenerate patch instead" rule. Known issues (tracked in tools/duckstation/README.md): - Fresh settings.ini doesn't complete BIOS boot under -nogui; one-time launch with GUI is required to warm up the settings before headless mode works Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
7c40d33db3 |
Phase 1 complete: recompiler proven correct on SCPH1001.BIN
Phase 1a (boot slice): 30 instructions at 0xBFC00000, compiles clean. Phase 1b (instruction coverage): 54 opcodes implemented in strict_translator, 44,629 walker-reachable instructions covered, 0 missing. Phase 1c (function discovery): 76 functions from 2 seeds, 2,988 instructions, 199 call edges, 27 indirect jumps. All validated through StrictTranslator. Phase 1d (indirect control flow): 27 sites classified — 21 A0/B0/C0 dispatch stubs, 4 computed calls, 2 computed tail calls. Ghidra cross-referenced with 0 disagreements. Phase 1e (relocation): ROM-to-RAM copy at FUN_bfc00420 proven with both Ghidra (static) and DuckStation (runtime). 69 address aliases, 68/69 function entries match byte-for-byte in RAM. Normalization rule documented. Includes PRINCIPLES.md and DEBUG.md adapted from recomp-template. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |