Commit Graph

1616 Commits

Author SHA1 Message Date
Alex Vanderveen f74ffcae33 runtime: give ten more cross-language globals C linkage in main.cpp
Second report on #244: main.cpp references C-defined globals that MSVC
cannot resolve. MSVC mangles namespace-scope variables; the Itanium ABI
does not, so a C++ reference to a C global links on GCC/Clang and fails
under MSVC with an unresolved external.

main.cpp already has the fix pattern -- the file-scope extern "C" block
added by the earlier MSVC pass, with a comment saying exactly this. Ten
globals added since then never made it into the block:

  memory.c            i_stat, i_mask, g_guest_store_count,
                      g_vblank_ack_count
  interrupts.c        g_vblank_raise_count, g_vblank_deliver_count
  dirty_ram_interp.c  g_dirty_ram_blocks_run, g_dirty_pump_count
  overlay_loader.c    g_call_unit_depth
  psx_bios_backend.c  g_psx_dispatch_depth

Each is referenced only through a block-scope `extern` inside a function.
With no namespace-scope declaration in view, that block-scope declaration
gives the entity C++ linkage, which is the failure. Declaring them in the
file-scope extern "C" block fixes it without touching the use sites: the
block-scope redeclarations now inherit C linkage, as the block's comment
already describes for the symbols that were there.

Which ten was measured, not eyeballed. Every block-scope extern in
main.cpp (31 distinct symbols) was probed by appending
`extern "C++" { extern T sym; }` to a copy of the file compiled with the
target's real command line: a conflicting-linkage diagnostic means the
symbol already has C linkage from an extern "C" header, silence means it
does not. 21 came back already-C (declared in psx_cycles.h, cpu_state.h,
debug_server.h and friends, or already in this block); these 10 came back
C++. After the change all 31 probe as C linkage.

Audited beyond main.cpp: it is the only C++ TU in the runtime with this
pattern. beetle_libretro.cpp's `extern PS_GPU GPU` / `extern PS_CDC *PSX_CDC`
are genuine C++ symbols from the Beetle core, correctly left with C++
linkage, and psx-beetle is not built under MSVC in any case.

No behaviour change on the existing toolchains: main.cpp.o is byte-identical
to its origin/master build. Full runtime suite on a clean build dir is 47/48,
the single failure being gte_register_access_test, which fails identically at
origin/master (43/44 there) -- it links gte.cpp + pgxp.cpp but references
gpu_ws_precise_nclip_enabled, defined in gpu.c, which is not in that target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YD7rrVK63Kncki6prB65S
2026-08-27 16:30:26 -04:00
Alex Vanderveen a9a732aae8 runtime: build under MSVC (drop two GNU-only constructs)
The README and docs/BUILDING.md both advertise MSVC as a supported
Windows toolchain, and the build system means it: runtime.cmake carries
/GS- /guard:cf-, /STACK, /SUBSYSTEM:WINDOWS with /ENTRY:mainCRTStartup,
an /experimental:c11atomics scoped to audio_trace.c, an SDL2 MSVC
dev-package lookup, and psx-oracle / psx-beetle are skipped under MSVC
because they are MinGW-only. psx_cycles.c already picks _BitScanReverse
over __builtin_clz, and the recompiler already emits a .CRT$XCU static
initializer instead of __attribute__((constructor)).

Two translation units regressed past that work and stop cl.exe cold.
Both files are in the runtime source list (runtime.cmake:261,267), so
this hit the framework runtime and every generated game project alike.

  runtime/src/sio.c  -- five GNU [0 ... PSX_MAX_PLAYERS - 1] range
    designators, which MSVC has no equivalent for. Replaced with a
    PSX_PAD_INIT() element-repeat macro in sio.h, next to the
    PSX_MAX_PLAYERS 1..8 bound that makes the ladder finite. Each
    PSX_PAD_REP_n is flat rather than recursive so no nested macro call
    is involved and the expansion is the same under the conforming and
    the traditional MSVC preprocessor; variadic so a braced element
    survives argument splitting. Element count cannot drift from the
    array extent because both are spelled PSX_MAX_PLAYERS.

  runtime/src/mdec.c -- __attribute__((aligned(16))) on the two SSE2
    scratch locals. The alignment is load-bearing: idct_sse2_dot8 stores
    with _mm_store_si128, which faults on an under-aligned destination.
    The irony is that mdec.c:9-10 gates the SSE2 path on _M_X64 || _M_AMD64
    specifically so MSVC x64 takes it, and then that path used a
    GCC-only attribute. Replaced with PSX_ALIGN(n) from the new
    runtime/include/psx_align.h, which maps to __declspec(align(n)) on
    MSVC -- prefix position being the one placement both spellings share.
    Written in the style of the neighbouring psx_bss.h.

No behaviour change on the existing toolchains, and that is checked
rather than asserted: sio.o and mdec.o are byte-identical to their
pre-patch builds under both gcc and clang, and for sio.o at every
supported PSX_MAX_PLAYERS from 1 through 8. A -Wpedantic sweep over
runtime/src, which reported the five range designators before, now
reports none. psx-runtime and psx-oracle link, and the runtime ctest
suite is 43/43.

Unfixed and pre-existing, unrelated to this change: gte_register_access_test
fails to link (gte.cpp references gpu_ws_precise_nclip_enabled, defined in
gpu.c, which is not in that target's source list).

Not attempted here: nothing in CI compiles runtime/src with cl.exe, which
is why these two landed unnoticed. A windows-latest MSVC configure+build
job is the durable fix and should be its own change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YD7rrVK63Kncki6prB65S
2026-08-27 14:39:54 -04:00
Matthew Stanley fa4d77069c mods: expose the scanned-out display size to trusted plugins
A plugin that draws its own overlay primitives needs to know where the
right-hand edge of the screen is, and it cannot work that out for itself.
GPUSTAT carries the horizontal-resolution bits, so a plugin can recover
the coarse mode width, but the visible width also depends on the GP1(06h)
X1/X2 range -- and that register is write-only and mirrored nowhere a
plugin can read.

Ape Escape is the worked example. It scans out 384 (368-mode, dot clock 7,
horizontal range 539..3227) while its mode width is 368, and the usual
assumption of 320 is wrong by 64. A HUD row right-aligned to 316 lands 68
pixels short of the edge, which is exactly what the Quick Gadget Select
mod does today.

psx_mod_display_width()/psx_mod_display_height() return what the presenter
uses, straight from gpu_get_display_info(). Zero means the geometry is not
established yet, and the header tells callers to skip drawing rather than
substitute a guess -- an overlay in the wrong place is worse than an
overlay that waits a frame.

mod_runtime_test covers the passthrough with a stubbed GPU, including the
384-vs-368 case that motivates it and the zero case.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 19:32:17 -07:00
Matt Stanley 06b9522afd Merge pull request #241 from mstan/pr/dispatch-mirrors
recompiler: fold PSX main-RAM dispatch mirrors
2026-08-26 19:00:32 -07:00
Matt Stanley e5b31de3e8 Merge pull request #240 from mstan/pr/sio-card-fixes
sio: keep SPU I_STAT pending across a card ACK; preserve the memory-card new-card flag until the first write
2026-08-26 18:53:35 -07:00
Matt Stanley 590b6e7c75 Merge pull request #238 from mstan/pr/cd-status-003-007
cdrom: READ status after seek complete; cancel stale INT2 on new command (PSX-CD-003/007)
2026-08-26 18:53:07 -07:00
Alexandros Mandravillis 2c52b467c6 recompiler: fold PSX main RAM dispatch mirrors
(cherry picked from commit d0f3e950a9c0ddc080db7c8b74d7b24fba73435d)
2026-08-26 21:43:29 +03:00
Pegasus 7e3d2f9421 fix(sio): preserve memory card new-card flag until write
(cherry picked from commit 97f95f47963ce05f970c448bcae598a9acd090ef)
2026-08-26 21:43:29 +03:00
Alexandros Mandravillis 3592a19e40 fix(sio): keep SPU I_STAT pending across card ACK
The memory-card ACK path cleared I_STAT bit 9 (SPU) before raising the
SIO0 interrupt. That is cross-device interrupt ownership: an SIO event
consumed a pending SPU source, so SPU-IRQ-driven audio (Konami intro,
MGS dialogue streaming) lost its interrupt during card scans. The clear
originated as a netplay digest-parity experiment (probe ACKs landing on
i_stat_before 0x200 vs 0x000) and was never a hardware behavior.

Remove the clear. A card ACK now only raises bit 7; a pending SPU
interrupt stays pending until the guest performs the SPU/INTC
acknowledgement sequence.

Regression: sio_spu_istat_ownership_test drives the card READ preamble
with SPU pending and asserts bit 9 survives every ACK delivery (fails
before this change, passes after). The pre-existing DISABLED
sio_card_protocol_test baseline is unchanged at 147/309 failures.

(cherry picked from commit f14bd43dcb7f97acfe60e22870d9f0c6c201afb5)
2026-08-26 21:43:29 +03:00
Alexandros Mandravillis 2d67bb9a79 cdrom: cancel stale INT2 on new command (PSX-CD-007)
Cancel the previous command's outstanding second-response interrupt when
a new CD command is accepted (psx-spx command flow; DuckStation
BeginCommand semantics). Without this, a Pause(0x09) INT2 survives into
the guest's next Setmode/Setloc/ReadN sequence and fires mid-read as a
stale COMPLETE — LIBDS drivers treat it as a read failure, corrupting
the streamed resource chain.

Cross-validated: C-12 Final Resistance mission 1 PC=0 null-callback
termination disappeared after absorbing this fix (DEVLOG 2026-08-05).
MOHU Mission 1 freeze in a DsRead FATAL/retry loop on single-sector
marker reads.

Also guard beetle SIGSTOP trap behind #ifndef _WIN32 (Windows has no
SIGSTOP).

(cherry picked from commit 2c43fc69c66242a86183156a6f1e60b2f81b1e47)
(cherry picked from commit c03fe5ba3d49241dfaedb344db6ad9c977070722)
2026-08-26 21:43:27 +03:00
Alexandros Mandravillis 2795b5a01a runtime: set READ status after seek complete (PSX-CD-003)
(cherry picked from commit 3e94eccc089550b44abb30dc522cbda7c46713fe)
(cherry picked from commit f9c938c36075bf145af26ba9891d5e239c16d4e0)
2026-08-26 21:43:27 +03:00
Matt Stanley 01c647e8a2 Merge pull request #237 from mstan/codex/savestate-safe-dirty-boundaries
savestate: reject dirty-pump snapshot contexts
2026-08-25 23:50:23 -07:00
Matthew Stanley cd68169cb8 savestate: reject dirty-pump snapshot contexts 2026-08-25 23:49:59 -07:00
Matt Stanley bfae39d2bb Merge pull request #236 from mstan/codex/package-empty-runtime-dirs
packaging: tolerate empty runtime dir lists
2026-08-25 21:02:19 -07:00
Matthew Stanley b9fd356e6d packaging: tolerate empty runtime dir lists 2026-08-25 21:01:59 -07:00
Matt Stanley 62a49214de Merge pull request #235 from mstan/codex/controller-presentation-policy
input: add plugin controller presentation policies
2026-08-25 20:38:21 -07:00
Matthew Stanley 432a44f64a input: add plugin controller presentation policies
Supersedes the global HYBRID controller-mode shape from PR #233 with a trusted plugin callback that can choose analog or digital presentation per input sample.

Keeps analog mode hardware-faithful by no longer folding physical D-pad input onto the left stick, while leaving debug injection able to steer stick-only paths.

Includes the pad/cursor probe tooling from #233 for diagnosing input doubling.
2026-08-25 20:37:49 -07:00
Matt Stanley 20ae6db9b4 Merge pull request #232 from mstan/split/pr193-keyboard-pad-chord-test
tests: cover keyboard Select+Start pad chord
2026-08-25 14:23:53 -07:00
Matt Stanley d5b5315ea4 Merge pull request #231 from mstan/split/pr193-sdl3-audio-stream-spec
audio: report SDL3 stream input spec to runtime
2026-08-25 14:23:49 -07:00
Matt Stanley 707f839570 Merge pull request #230 from mstan/split/pr193-savestate-no-pc0
savestate: defer saves until a safe resume PC exists
2026-08-25 14:23:46 -07:00
Matt Stanley 042699ca70 Merge pull request #229 from mstan/split/pr193-bootstate-skip-unknown-sections
boot_state: skip unknown savestate sections
2026-08-25 14:23:42 -07:00
Matthew Stanley 19e5de4c28 boot_state: document unknown-section skip 2026-08-25 13:45:11 -07:00
Matthew Stanley ea0530eef0 tests: cover keyboard Select+Start pad chord
Split from parked PR #193. Adds the standalone keyboard_pad_chord_test target and verifies that default keyboard bindings emit Select, Start, and Select+Start without one key masking the other.
2026-08-25 13:10:52 -07:00
Matthew Stanley 151588d62e audio: report SDL3 stream input spec to runtime
Split from parked PR #193 commit 42109c58. SDL3 audio streams convert from the requested stream format to the device format internally, so psx_sdl_audio_open must report the requested stream input spec back to the runtime. Reporting the device format made the runtime generate at the wrong rate before SDL resampled again.
2026-08-25 13:07:40 -07:00
tetrisgm b0424b0b4e savestate: defer saves until a safe resume PC exists
Split from parked PR #193 commit 1469550c. The mod-state preservation half is already covered on master by the framework mod staging cleanup, so this extraction keeps only the independent save-state fix: when the resume hint is 0, wait for a published block-leader PC instead of writing a state that would later resume at pc=0.
2026-08-25 13:05:23 -07:00
tetrisgm 1d32acf74f boot_state: skip unknown sections instead of failing the whole load
`default: return 0` made every savestate written by a build with one extra
section a poison pill for every build without it. Worse than unloadable: by the
time the apply loop hit the unknown tag it had already restored RAM, VRAM and
CPU state, so the refusal left a HALF-RESTORED machine that wedged or died at
PC=0 -- which presented as "loading a save crashed the whole thing", with the
restored-but-untracked VRAM showing low-res in the wreckage.

A sectioned state format exists precisely so readers can step over what they do
not know. Known-but-malformed sections still fail as before; only genuinely
unknown tags are skipped.

This also makes the states saved during the short-lived BS_SEC_TEXPACK window
load cleanly again (the extra section is now ignored), and it is the
forward-compatibility prerequisite for ever adding that section back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:03:17 -07:00
Matt Stanley fcbda45ab0 Merge pull request #211 from mstan/split/pr169-overlay-high-bank-tools
tools: support high-bank overlay captures
2026-08-25 12:49:38 -07:00
Matt Stanley 8943695aab Merge pull request #217 from mstan/codex/hd-texture-pack-core
runtime: add external HD texture pack core
2026-08-25 12:46:36 -07:00
Matt Stanley f294f7397a Merge pull request #226 from mstan/hotfix/linux-selfcompile
Self-compile hotfixes: offline dependency vendoring, GLVND GL, Windows/MinGW C++17, and a green ctest
2026-08-25 11:59:06 -07:00
Matthew Stanley c50f3f32a6 tools: keep vendor deps help to documented usage 2026-08-25 11:58:22 -07:00
Matt Stanley c3d7fc5f71 Merge pull request #216 from mstan/codex/game-window-width
config: honor title window width
2026-08-25 11:51:40 -07:00
Matt Stanley 33be1ac338 Merge pull request #225 from mstan/fix/overlay-region-high-loading-exe
Treat RAM below a high-loading boot EXE as overlay region
2026-08-25 11:46:16 -07:00
Matthew Stanley d66b8e75fd tests: cover high-load overlay region predicate 2026-08-25 11:36:34 -07:00
Alex Vanderveen cb4762c53f bump 2026-08-25 14:33:07 -04:00
Alex Vanderveen 01d3ab2854 bump 2026-08-25 14:32:47 -04:00
Matt Stanley 6c65801caa Merge pull request #222 from mstan/codex/text-xlate-fix-only-tables
text: load fix-only translation tables
2026-08-25 11:31:40 -07:00
Matt Stanley 3612b91066 Merge pull request #215 from mstan/codex/keymap-event-scancode
input: match host hotkeys by event scancode
2026-08-25 11:31:11 -07:00
Matt Stanley cd011641ba Merge pull request #227 from mstan/fix/selfbuild-toolchain-sysroot
Self-build: pack sysroot into CMake and require toolchain 1.0.14
2026-08-25 10:34:15 -07:00
Matthew Stanley 1bc46e171d host: use portable case-insensitive compare for toolchain floor 2026-08-25 10:32:24 -07:00
Alex Vanderveen 05522e9c6a fix: default toolchain min-version floor 1.0.14 — stale pre-sysroot packs get replaced
The cache was accepted forever once any cmake ran: default min version was
empty, so a Deck (or any host) that cached a pre-sysroot pack (<=1.0.13)
never re-downloaded and kept compiling against host headers — absent on
stock SteamOS — with objects that mis-link after a pack upgrade
(__isoc23_strtoul).

Both resolvers now default the floor to 1.0.14, the first pack with the
Linux build sysroot. This is a framework floor, not a per-title pin:
RETCOMM_TOOLCHAIN_MIN_VERSION still overrides in either direction, and
"0" / "off" / "none" disables it (pre-floor behavior).

- tools/toolchain_pack.py: DEFAULT_MIN_VERSION in default_min_version();
  the ensure_toolchain stale-probe passes min_version="0" so its log line
  still sees below-floor packs.
- host: toolchain_min_version() mirrors the same default and disable
  tokens; below-floor caches now fail host_portable_cmake_ready and the
  wizard downloads /releases/latest.

Verified: Python — floor/override/disable semantics, real v1.0.10 pack
rejected and v1.0.14 accepted, an isolated cache holding only v1.0.10 no
longer resolves (visible again with floor disabled), full cache resolves
to v1.0.14. C — same matrix via a unit harness incl. manifest-less dirs;
both platform branches syntax-checked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vc7zPEnfUFMhMtJzUEruyb
(cherry picked from commit 00f0a9a9bb)
2026-08-25 10:31:16 -07:00
Alex Vanderveen eefa4a9efd fix: SteamOS self-build — wire pack sysroot into CMake, surface CLI failure lines
Stock SteamOS (Steam Deck) has no /usr/include and no GL dev symlinks, so
the wizard rebuild died at recomp-ui's find_package(OpenGL REQUIRED) with
"Could NOT find OpenGL (missing: OPENGL_INCLUDE_DIR)" — reported to the
user only as "psxrecomp rebuild failed (exit 1)" (recomp-ui issue #34).
The cmake-clang-v1 >=1.0.14 pack already bundles a jammy sysroot with GL
headers and a legacy libGL.so stub, but only clang.cfg used it; CMake's
find_* still searched the host.

- psxrecomp_cli: when the active pack carries sysroot/usr/include (Linux),
  pass -DCMAKE_SYSROOT=<pack>/sysroot -DOpenGL_GL_PREFERENCE=LEGACY to both
  the game and the emitters configure. LEGACY is required: the sysroot has
  legacy libGL.so + GL/gl.h but no GLVND dev files (glx.h/libOpenGL.so/
  libGLX.so), so the GLVND path cannot complete and OpenGL::GL would never
  be created. Skipped when the caller already sets CMAKE_SYSROOT.
- codegen host: run_cli_posix/run_cli_win now route the child's stderr
  into the progress pipe and keep a last-lines capture (CliTail); on
  failure err_msg carries the most recent error-looking line — JSON
  progress rows contribute their message, raw rows (compiler output,
  Python tracebacks) contribute as-is. Exit-3 disc-verify text unchanged.

Verified against a stock-SteamOS simulation (bwrap: tmpfs over
/usr/include, GL dev symlinks removed) using the shipped v1.0.14 pack:
configure previously failed exactly as on the Deck; with the sysroot args
FindOpenGL resolves from the pack, the build links, and the binary runs.
CliTail paths exercised with real compact-JSON rows and raw stderr.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vc7zPEnfUFMhMtJzUEruyb
(cherry picked from commit 0bb45442f8)
2026-08-25 10:31:16 -07:00
Matt Stanley 50c6e7bb41 Merge pull request #228 from mstan/split/pr169-project-analyze-cli
cli: add project analyze command
2026-08-25 10:25:57 -07:00
Matt Stanley 682627af1e Merge pull request #212 from mstan/split/pr169-analyzer-only
recompiler: add standalone static analyzer
2026-08-25 10:25:02 -07:00
Matt Stanley d972d66de8 Merge pull request #210 from mstan/split/pr169-setup-host-runtime-dirs
tools: stage runtime dirs in setup-host packages
2026-08-25 10:24:37 -07:00
Matt Stanley 3c976fdb85 Merge pull request #221 from mstan/codex/overlay-slti-lower-shim
autocompile: define lower-cull helper in overlay shim
2026-08-25 10:19:42 -07:00
Matt Stanley 45ceb81174 Merge pull request #214 from mstan/codex/screenshot-hires-byte-stride
runtime: fix high-resolution screenshot byte stride
2026-08-25 10:19:17 -07:00
Matt Stanley 946f2d0420 Merge pull request #220 from mstan/codex/test-compiler-path-precedence
tests: prefer PATH compiler for overlay shim
2026-08-25 10:01:49 -07:00
Matt Stanley d41cf53c6d Merge pull request #219 from mstan/codex/main-ram-geometry
memory: define retail and expanded RAM geometry
2026-08-25 10:01:41 -07:00
Matt Stanley 0a611e1706 Merge pull request #218 from mstan/codex/rational-vblank-clock
timing: add rational VBlank period generator
2026-08-25 10:01:34 -07:00
Alex Vanderveen 7efc712dd3 Windows/MinGW self-build: pin cxx_std_17 and stop capturing a structured binding
Two defects that only bite a MinGW C++17 build, both still live on master.

runtime.cmake declared only `c_std_11` on the runtime target, leaving the C++
dialect to whatever the parent project happened to set. A game CMakeLists that
omits CMAKE_CXX_STANDARD therefore compiled mod_packages.cpp as a pre-17
dialect. State the runtime's real requirement instead of inheriting it.

mod_packages.cpp captured a structured binding (`for (const auto& [id, ...])`
with `id` used inside a lambda). That is a C++20 extension; clang accepts it
silently, MinGW/GCC at C++17 rejects it. Bind the map entry to ordinary locals
before the lambda.

Cherry-picked from ae9432a3 on feat/rbengine-bak, minus that commit's unrelated
lib/recomp-net submodule bump. Verified by building psx-runtime on Linux.
2026-08-25 12:24:05 -04:00