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