Commit Graph

2089 Commits

Author SHA1 Message Date
Shokunin 8915131ced psx-beetle: say 4382 in the port comments
beetle_main.cpp has defaulted to port 4382 since 4380 began colliding
with other oracles, but its header and the psx-beetle block in
runtime/CMakeLists.txt still said 4380. beetle_debug_server.c now says
4380 is only its fallback for a port <= 0. Comments only.

A correction to 9ef516a7 ("psx-beetle: build on macOS and send large
replies whole"): its message says none of its changes affect MinGW or
Linux. The send_raw change does. On EWOULDBLOCK every platform now waits
for the socket (up to 15 s) instead of dropping the client mid-reply.
That only turns a truncated reply into a complete one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:26:45 -07:00
Shokunin 7118734d04 docs: correct the ruler #2 icache_miss value on the 15-loop ROM
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>
2026-09-29 12:26:45 -07:00
Shokunin 216eb31ef2 cyc_watch: arm boot anchors from power-on on both backends
Boot anchors (reset, the kernel copy, the first A0/B0/C0 calls, the shell)
pass within the first frames, before a TCP cyc_watch arm can land, so a
native-vs-Beetle boot comparison could not be run from the tree.

psx-runtime (debug_server.c) and psx-beetle (beetle_main.cpp) now read
PSX_CYC_WATCH ("<pc>" or "<pc>-<end>" for region mode) and PSX_CYC_WATCH_N
(default 16) at start-up and arm the watch before the first guest
instruction. The native arm shares the TCP handler's code path
(cyc_watch_arm); psx-beetle calls beetle_cyc_watch_arm. With neither
variable set nothing changes. tools/cycle_compare.py --no-arm then reads
both rings.

PSX_BEETLE_UNPACED=1 skips psx-beetle's 59.94 Hz wall-clock pacing for
headless oracle runs. Guest timing is unaffected.

docs/beetle-macos.md step 7 documents the variables and the anchor-key
difference for BIOS copy windows declared dispatch_key = "rom": the shell
is keyed natively at its ROM address (OpenBIOS 0xBFC0A500, SCPH-1001
0xBFC18000) while Beetle sees 0x80030000. Checked on macOS: the documented
example records the OpenBIOS shell entry at 5,015,670 in Beetle, the value
of the #429 land gate, and the native watch arms from boot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:26:16 -07:00
Shokunin 055c33aaa1 docs: complete the Beetle oracle patch set; add a macOS recipe
beetle-linux.md told builders to re-land several Beetle hooks by hand
because they were never exported to docs/: the rtrace and IRQ callbacks,
the guest-cycle clock, PS_CDC::PSXRecomp_GetDecodeVolume and the CDC/DMA
IRQ peeks that beetle_libretro.cpp links against, plus the SPU event
calls and the per-instruction hook the real cyc_watch now needs. Ship
them, one patch per hook, all against the 5759277b base:

- beetle_rtrace_irq_hook.patch
- beetle_guest_cycles_hook.patch
- beetle_cdc_dma_peek_hook.patch
- beetle_spu_event_hook.patch

beetle_cdcmd_trace_hook.patch was generated from a tree that already had
the wtrace block, so applying it after the wtrace patch redefined the
wtrace globals and typedefs and needed a manual fix. It is now a diff on
top of the wtrace and SIO patches; the resulting tree is unchanged.

beetle-macos.md is the macOS recipe, verified from a fresh official
clone on Apple Silicon: `git apply` of all seven patches, the osx static
build, the psx-beetle configure on current master, OpenBIOS under the
retail file names (Beetle otherwise boots its own, different OpenBIOS),
headless runs through SDL's dummy driver, and ruler #2 as the check
before trusting a build. beetle-linux.md now uses the full patch set,
notes the current configure requirements and the headless option, and
gives psx-beetle's actual default port (4382).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:06:14 -07:00
Shokunin bfc4056fdc cycle_testrom: build ruler #2 on current master and without mkpsxiso
Ruler #2 no longer built from master:
- game.toml's text_size 0x800 is now rejected by the EXE parser ("a
  truncated text_size must be 4 KiB page-aligned"). Use 0x2000, the
  page-rounded size of the 0x1800-byte text. The icache_miss victim block
  at +0x1000 is now inside the analysed range and compiled too.
- psxrecomp-game writes the text as shards (<exe>_full_NN.c), but
  CMakeLists.txt still named a single <exe>_full.c. Glob the shards and
  fail with the regeneration hint when there are none.

Add mkdisc.py, a pure-Python stand-in for mkpsxiso (Windows-only here):
it writes the ISO9660 boot disc as MODE2/2352 sectors with a correct
EDC/ECC and copies the license area from a disc the developer owns. The
built image stays gitignored.

README: the macOS/Linux flow (headless on both backends), and why
icache_miss reads +16 on the current ROM but +14 in the 2026-06-27 log:
the mmio loops moved the loop top from word 1 to word 0 of its cache
line, so each of its two misses refills one more word. Records the
Beetle values re-measured on macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:59:31 -07:00
Shokunin d6fddd0676 psx-beetle: record cyc_watch hits instead of stubbing them
beetle_cyc_watch_* were link stubs that always answered hits=0: the
Beetle-side sampler lived in a local beetle-psx tree that never reached
docs/. tools/cycle_compare.py and tools/cycle_testrom/measure.py (ruler
#2) therefore had no oracle to compare against.

Implement the comparator here, driven by the new per-instruction PC hook
in docs/beetle_guest_cycles_hook.patch. Semantics match the native
cyc_watch in debug_server.c: an entry is taken before the anchor
instruction is fetched and carries the absolute guest cycle count of
everything before it; with an end anchor each entry is one A->B pass;
n is clamped to the native ring size (1024). The hook is installed only
while a watch is armed, so an idle oracle pays one untaken branch per
instruction.

This makes psx-beetle require the patched Beetle tree; the stubs hid
that, but the other oracle hooks (rtrace/irq/guest cycles/CDC peeks)
already needed hand-landed Beetle changes. exc_ring stays a stub: no
tool reads it and its hook was never published.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:58:25 -07:00
Shokunin 9ef516a7f1 psx-beetle: build on macOS and send large replies whole
Three portability fixes for the psx-beetle oracle target, none of which
changes behaviour on MinGW or Linux:

- beetle_cdc_decode_volume redeclared PSX_CDC at block scope inside an
  extern "C" function. GCC accepts that; clang gives the declaration C
  linkage and rejects it against psx.h's C++ declaration. psx.h already
  declares PSX_CDC, so drop the redeclaration.
- The debug server's client socket is non-blocking, and send_raw dropped
  the connection on the first EWOULDBLOCK. macOS starts a TCP send buffer
  at 128 KB, so a large reply (read_ram of the BIOS ROM or all of RAM)
  reached the client as a truncated JSON line. Wait for the socket to
  drain (select, 15 s budget, as debug_server.c's send_all_blocking does)
  and only drop the client on a real error.
- .gitignore had "beetle-psx/", which matches a directory but not the
  symlink docs recommend when the Beetle checkout lives outside the tree.
  "beetle-psx" matches both.

Also note the non-Windows make platforms in the target's comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:58:14 -07:00
Matt Stanley 44a45d3c3d Merge pull request #416 from RetroPortingToolKit/fix/disc-picker-ascii-20260928
runtime: remove redundant missing-disc modal on Windows
2026-09-28 17:33:24 -07:00
Matt Stanley 6ef8877324 Merge pull request #412 from shaneomac1337/fix/vulkan-opaque-present
vulkan: present through an opaque shader pass (fixes AMD see-through window, #411)
2026-09-28 17:01:12 -07:00
Matthew Stanley 3382f86c59 runtime: keep disc-picker dialog text ASCII-safe 2026-09-28 16:54:33 -07:00
Matt Stanley 16382d22db Merge pull request #413 from shaneomac1337/fix/project-studio-windows
project studio: make migrate_project.py work from a Windows console
2026-09-28 15:34:52 -07:00
Matt Stanley f9d8830721 Merge pull request #410 from shaneomac1337/fix/debug-server-socket-noinherit
debug_server: make the listen socket non-inheritable on Windows
2026-09-28 15:34:48 -07:00
Matt Stanley 13aa8dbf12 Merge pull request #409 from shaneomac1337/fix/vulkan-validation-ds-staging
vulkan: fix depth/stencil aspect + usage and staging-buffer usage (validation errors)
2026-09-28 15:34:44 -07:00
Martin Penkava 3a4e166545 project studio: make migrate_project.py work from a Windows console
Two failures hit while migrating a title on Windows 11:

- `audit` crashed with UnicodeEncodeError on the "->" mark (U+2192) when the
  console code page can't encode it (cp1250 here). main() now reconfigures
  stdout/stderr with errors="replace", so reports degrade those characters
  instead of aborting.
- record_framework_pins failed. subprocess.run(["bash", ...]) lets
  CreateProcess search System32 first, which starts WSL's bash; it can't see
  D:/ paths, and a CRLF checkout of record_pins.sh breaks any bash anyway.
  It now resolves bash via shutil.which, passes POSIX-style paths, and falls
  back to the existing git rev-parse snapshot when the script can't run.

Most of this was done by Claude Opus 5.5; I reviewed and tested it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 14:11:39 +02:00
Martin Penkava 7ad8519128 vulkan: present through an opaque shader pass instead of a blit
The plain present path copied the VRAM image into the swapchain with
vkCmdBlitImage, alpha included. VRAM alpha is the PSX mask/STP bit, 0 on
most pixels, and AMD's compositor honours it even with an OPAQUE
compositeAlpha: parts of the window went see-through (8x8 black/white
blocks of whatever sat behind it). Reported in #411.

vk_renderer_present_vram/_wide now draw the displayed rect with a
fullscreen triangle whose fragment shader writes alpha = 1 (new
present.vert/.frag). The pass is self-contained and created lazily; if
any of it fails to build, presents fall back to the old blit. Its render
pass ends in TRANSFER_DST_OPTIMAL so finish_present (OSD + present
barrier) is unchanged. Wide surfaces gain SAMPLED usage for it.

Checked on an RX 7900 XT: intro/logo screens render correctly, no new
validation-layer messages.

Most of this was written by Claude Opus 5.5; I reviewed and tested it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:41:03 +02:00
Martin Penkava c619fe2b75 debug_server: make the listen socket non-inheritable on Windows
Winsock sockets are inheritable by default. Any child process the runtime
spawns (e.g. the overlay autocompile's `cmd.exe /C python compile_overlays.py`)
inherits the debug server's listening socket; if the game exits while the
child is still running, the child keeps 127.0.0.1:<debug_port> bound and the
next launch cannot bind it (clients get connection refused / talk to a dead
listener).

Observed: after closing the game mid-autocompile, `netstat -ano` showed :4370
LISTENING under the exited game's PID, held by the surviving python child;
killing the compile freed it. Fix: SetHandleInformation(HANDLE_FLAG_INHERIT, 0)
right after socket(). No behavior change on non-Windows.

This change was made with AI assistance (Claude Opus 5.5, Anthropic) and
reviewed/tested by the submitter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:11:23 +02:00
Martin Penkava a8f91653d1 vulkan: fix depth/stencil aspect + usage and staging-buffer usage (validation errors)
Found with the Khronos validation layer on AMD RX 7900 XT (Windows, mingw),
where D24S8 is unavailable and choose_ds_format() picks the combined
D32_SFLOAT_S8_UINT:

- VUID-VkImageMemoryBarrier-image-03320: every view/barrier/clear on the
  canonical and wide depth-stencil images named only the STENCIL aspect.
  Without separateDepthStencilLayouts, a combined depth/stencil format must
  be transitioned with both aspects. Added DS_ASPECT and used it for the
  image views, barriers and vkCmdClearDepthStencilImage ranges.
  (vkCmdClearAttachments keeps the stencil-only mask - that is legal.)
- VUID-vkCmdClearDepthStencilImage-pRanges-02659: the canonical DS image is
  cleared with vkCmdClearDepthStencilImage but lacked
  VK_IMAGE_USAGE_TRANSFER_DST_BIT (the wide DS images already had it).
- VUID-vkCmdCopyImageToBuffer-dstBuffer-00191: staging buffers are used for
  readbacks (vkCmdCopyImageToBuffer) but were created with TRANSFER_SRC only.

Validation messages over the same 20 s boot (SmackDown 2, Vulkan):
53 -> 3 (the remaining VUID-vkQueueSubmit-pSignalSemaphores-00067 swapchain
semaphore reuse is untouched). The fix also cleared the downstream
VkImageMemoryBarrier-oldLayout-01213 and vkCmdDraw-None-09600 reports.

This change was made with AI assistance (Claude Opus 5.5, Anthropic) and
reviewed/tested by the submitter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:11:02 +02:00
Alex Vanderveen 5c1839675d Merge pull request #407 from RetroPortingToolKit/feat/recomp-json-scaffold
scaffold: setup_project writes a starter .recomp.json (recomp.fyi spec)
2026-09-27 00:13:09 -04:00
Alex Vanderveen 833c591720 scaffold: setup_project writes a starter .recomp.json (recomp.fyi spec)
New projects describe themselves to community lists (recomp.board et al.)
via .recomp.json at the repo root: game, system PS1, type recomp,
toolchain psxrecomp, status exploring, and original region + serial.

write_recomp_json.py takes the serial from disc_probe.json and derives
region from the Sony serial prefix, falling back to --region (which
defaults to USA and would mislabel PAL discs). It only fills missing
fields, so re-running it never clobbers a maintainer's edits.

Both gitignore templates ignored /*.json at the root, which would have
silently dropped the file from the initial commit; un-ignore it.

Closes #406

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 00:07:26 -04:00
Alex Vanderveen 5002187c17 bump 2026-09-27 00:00:46 -04:00
Alex Vanderveen 94552532a2 bump 2026-09-26 23:57:20 -04:00
Matt Stanley 4bb7bd429d Merge pull request #405 from RetroPortingToolKit/fix/aot-feature-presentation-keys
aot: presentation keys and exclude_writes; mods: hide_hidden_mod_features
2026-09-26 16:53:56 -07:00
Matthew Stanley 78534deff4 mods: [runtime] hide_hidden_mod_features opts the launcher into never showing hidden features
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 16:41:47 -07:00
Matthew Stanley 4b4c4b8453 aot: transfer_entries.exclude_writes keeps package-written data out of the transfer inventory
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 16:41:46 -07:00
Matthew Stanley ed07541f13 aot: accept feature presentation keys (hidden, author, channel) in mod package views
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 16:04:43 -07:00
Matt Stanley 68d77ed6a9 Merge pull request #404 from RetroPortingToolKit/fix/vblank-follows-video-mode
runtime: VBlank rate follows the GPU video mode, not the disc region
2026-09-26 16:03:47 -07:00
Matt Stanley 6dd0d2ff5a Merge pull request #401 from RetroPortingToolKit/feat/exclude-builtin-mods
Let titles exclude framework builtin mods
2026-09-26 16:03:43 -07:00
Matthew Stanley 7caef77459 debug_server: report the live video standard and frame timing in vblank_rate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 15:39:51 -07:00
Matthew Stanley f51617bb7d runtime: VBlank rate follows the GPU video mode (GP1(08h) bit 3), not the disc region
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 15:38:21 -07:00
Matthew Stanley c547f3b967 mods: implicit cross-package feature requirements ([[requirement]], format 7)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:58:16 -07:00
Matthew Stanley 7f1c81f1f4 aot: apply disc overlays to the boot EXE in mod package views
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 12:11:40 -07:00
Matthew Stanley 141eb39002 mods: let titles exclude framework builtins with EXCLUDE_BUILTIN_MODS
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 12:11:39 -07:00
Matt Stanley 71336b44d2 Merge pull request #400 from RetroPortingToolKit/feat/cli-generate-aot-static
Generate builds the static overlay shard an AOT profile declares
2026-09-26 10:45:04 -07:00
Matthew Stanley 0995f1bd19 tests: overlay_static_sources_cmake also runs under pytest
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 10:37:18 -07:00
Matthew Stanley bc5ec35998 cli: generate builds the static overlay shard an AOT profile declares
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 10:28:14 -07:00
Matt Stanley 321776b836 Merge pull request #399 from RetroPortingToolKit/feat/aot-nfe-lzss
AOT: indexed_lzss_members method for bit-stream LZSS packs
2026-09-26 10:04:42 -07:00
Matt Stanley 0487e0cb81 Merge pull request #398 from RetroPortingToolKit/feat/8mb-ram-opt-in
Opt-in 8 MB main RAM
2026-09-26 10:04:39 -07:00
Matt Stanley be0d0e7a05 Merge pull request #397 from RetroPortingToolKit/feat/aot-mod-package-images
AOT: images from mod packages; resolve function-entry mod plugins
2026-09-26 10:04:35 -07:00
Matthew Stanley b6a80e5d9e debug_server: dirty_ram_stats per_pc range filter, paging and completeness counts
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:17:34 -07:00
Matthew Stanley b43a7c9ea8 aot: indexed_lzss_members verifies identical pack copies, e.g. one linked into the boot EXE
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:17:34 -07:00
Matthew Stanley 12d13deff4 aot: indexed_lzss_members method for offset-indexed bit-stream LZSS packs
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:17:34 -07:00
Matthew Stanley c67327e42f aot: per-entry static overlay dispatch counters, queried by overlay_static_entries
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:17:28 -07:00
Matthew Stanley ec4c91cd94 runtime: GP0 source key and overlay_region_floor follow the 8 MiB window
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:03:58 -07:00
Matthew Stanley 1721739a73 debug_server: PSX_WTRACE_BOOT_RANGES gets reserved slots and is refused whole, with the reason in wtrace stats
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:03:58 -07:00
Matthew Stanley 0238117450 runtime: keep RAM-mirror PCs architectural; fold only bytes, through one live mask
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:03:57 -07:00
Matthew Stanley 18e3030440 savestate: validate every section before applying any; header records the live RAM size
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 08:03:39 -07:00
Matthew Stanley 15ed505656 recompiler: normalize KUSEG header addresses anywhere in the 8 MiB RAM window
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 07:53:18 -07:00
Matthew Stanley ab5d63e1f1 tests: register every offline-tool unit test and make the registration guard scan tools/ and tests/
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 07:36:33 -07:00
Matthew Stanley 199cfe01bc mods: flat function-entry hook table built at activation; interpreter skips it when empty
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 07:34:20 -07:00
Matthew Stanley b0aa7e108d aot: reject images crossing a retail RAM mirror unless the profile declares 8 MiB
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 07:30:03 -07:00