Files
psxrecomp/runtime/include/psx_fiber.h
T
Matthew Stanley b9716154f0 Add native macOS/Linux support (ucontext thread scheduler, fullscreen, build fixes)
The recompiler and runtime now build and run natively on macOS (Apple
Silicon & Intel) and Linux, alongside Windows. The recompiled BIOS boots to
the PlayStation logo, and Tomba boots into gameplay with working memory-card
save/load — the previously Windows-only path.

Core change — the BIOS thread scheduler:
- runtime/src/psx_fiber.{h,c} (new): one cooperative-fiber API, backed by
  Win32 Fibers on Windows and ucontext (makecontext/swapcontext) on POSIX,
  with a GetCurrentFiber analog (psx_fiber_current).
- traps.c: the BIOS thread switcher now uses psx_fiber_* on every platform.
  The old non-Windows setjmp/longjmp fallback is removed — it ran target
  threads nested on the caller's C stack and so couldn't resume an arbitrary
  suspended thread, which hung the BIOS CD-boot WaitEvent handoff. Real
  per-thread stacks (fibers/ucontext) fix it.
- interrupts.c: the exception-deferral path (g_exception_owner_fiber,
  deferred_exception_longjmp) is now fiber-based on all platforms via the
  same abstraction, instead of #ifdef _WIN32.

Cross-platform build fixes:
- recompiler/CMakeLists.txt: vendored fmt 9.1.0 force-enables consteval on
  Apple clang (the __cpp_consteval clause overrides its own Apple exclusion),
  which clang 21 then rejects; force FMT_CONSTEVAL empty on non-MSVC.
- runtime.cmake: add psx_fiber.c; add pkg-config's SDL2_LIBRARY_DIRS so
  -lSDL2 resolves outside default paths (Homebrew /opt/homebrew/lib).
- crash_trace.c: include <stdarg.h> (not pulled in transitively off Windows).
- main.cpp: the forced "opengl" render-driver hint (a Windows-GDI-freeze
  workaround) is now Windows-only so macOS uses Metal; create the renderer
  with PRESENTVSYNC; SDL_RenderSetLogicalSize(640,480) so fullscreen
  letterboxes; add an F11 / Alt+Enter / Cmd+F fullscreen toggle.

Verified: SCPH1001 BIOS boots to the Sony logo on Apple Silicon, and Tomba!
(SCUS-94236) boots into gameplay with memory-card saves persisting across
relaunches. Gamepad (SDL_GameController) was already cross-platform.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 18:53:22 -07:00

56 lines
2.0 KiB
C

/*
* psx_fiber.h — cross-platform cooperative fibers for the BIOS thread
* scheduler (traps.c) and exception-deferral (interrupts.c).
*
* The PS1 BIOS manages its own threads (TCBs) and switches between them
* cooperatively; the runtime mirrors each BIOS thread with a host fiber so
* the recompiled C for a suspended thread keeps its own native call stack
* across a ChangeThread. The CD-boot handoff in particular depends on this:
* a thread issues a CD command, WaitEvent-blocks, and the scheduler must be
* able to resume a *different* thread's previously-suspended stack — which
* requires real separate stacks, not nested dispatch.
*
* Backends:
* - Windows: the Win32 Fiber API (ConvertThreadToFiber / CreateFiber /
* SwitchToFiber / DeleteFiber). Behavior is identical to the original.
* - POSIX (macOS/Linux): ucontext (makecontext / swapcontext).
*
* Cooperative, single-threaded: exactly one fiber runs at a time and all
* switches are explicit. psx_fiber_current() is the GetCurrentFiber analog.
*/
#ifndef PSX_FIBER_H
#define PSX_FIBER_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void* psx_fiber_t;
typedef void (*psx_fiber_entry)(void* arg);
/* Make the current thread a fiber so it can switch to others. Idempotent;
* returns the handle for the current thread's fiber. Call before the first
* psx_fiber_switch on this thread. */
psx_fiber_t psx_fiber_convert_thread(void);
/* The currently-executing fiber (GetCurrentFiber analog). */
psx_fiber_t psx_fiber_current(void);
/* Create a fiber with its own stack. It does not run until switched to. */
psx_fiber_t psx_fiber_create(size_t stack_size, psx_fiber_entry entry, void* arg);
/* Switch execution to target; the caller is suspended until switched back. */
void psx_fiber_switch(psx_fiber_t target);
/* Destroy a fiber created by psx_fiber_create and free its stack. Must not
* be the currently-running fiber. */
void psx_fiber_destroy(psx_fiber_t fiber);
#ifdef __cplusplus
}
#endif
#endif /* PSX_FIBER_H */