[DRAFT] libretro core proof-of-concept#282
Conversation
|
This is lovely, is there any interest upstream (and by this, I mean: to refactor things so that this could be integrated without hacks)? As it would make possible to get supermodel working in various handhelds devices easily! |
|
LFG |
|
FWIW, I play Spikeout with this almost every day and haven't had to make any changes. I haven't tested any other games. I expect that gun games will be the biggest problem. |
That's probably the only game I'd play, is the core available for android too? I'd like to test. |
|
Need to look into this over the holidays! |
I also play Spikeout, I'm working on my 1cc right now. I would love to test |
@SRC267 I have not done anything to port to new platforms. I have tested on macOS and Windows and I use Windows regularly. The way I did the core is not very conducive to a mobile port because of the hidden window creation and framebuffer read. |
Okay, if you have the windows core, I can try it on my PC. I have a few PCs, I'll try it on my handheld pc. |
- Keep the libretro render path isolated from overlay/crosshair work so supersampling, widescreen, and 2x/3x/4x output quality remain unchanged. - Restore the libretro vector crosshair overlay as an optional layer that can be shown alongside the native Supermodel crosshair, with state restoration so the overlay does not contaminate viewport/scissor/blend/depth state. - Keep the overlay drawing path decoupled from renderer reinitialization so toggling the overlay no longer causes resolution or quality regressions. - Keep gun input profiles working across mouse, lightgun, and joypad modes while preserving the racer and fighter mappings already validated by the user. - Make the native crosshair path more robust in vector mode by avoiding bitmap asset dependency when not needed. - Keep the libretro core self-contained instead of depending on Supermodel.ini for the main runtime behaviors already ported into RetroArch core options. - Preserve the validated widescreen behavior: 4:3 stays stable when disabled, and widescreen uses the standalone-style geometry/path when enabled. - Preserve the validated supersampling path: 1x through 5x continue to scale the 3D output cleanly without being tied to the overlay toggle. - Preserve gun profile defaults so shooters can use mouse/joypad/lightgun inputs with fire/reload/offscreen and operator buttons without affecting racers/fighters.
Add dedicated libretro defaults and descriptors for Game::INPUT_ANALOG_JOYSTICK and Game::INPUT_SOCCER.\n\nAnalog joystick games now get explicit RetroPad bindings for the analog stick directions plus face-button actions, while preserving the existing operator buttons. Soccer games now map short pass, long pass, and shoot to usable RetroPad face buttons, with separate descriptors so RetroArch exposes the controls clearly.\n\nThis keeps the existing racer, fighter, gun, and widescreen paths unchanged and confines the new behavior to the game types that already existed in the standalone input model.
This commit collects the remaining libretro input work and the Visual Studio 2022 migration in one consistent baseline.\n\nLibretro side:\n- Add dedicated mappings for Game::INPUT_ANALOG_JOYSTICK so analog-joystick titles receive usable RetroPad face-button bindings, analog stick directions, and operator buttons without affecting racers, fighters, or gun games.\n- Add dedicated mappings for Game::INPUT_SOCCER so Virtua Striker-style titles expose short pass, long pass, and shoot on usable face buttons while keeping the existing directional input behavior intact.\n- Add a dedicated twin-joystick profile for Game::INPUT_TWIN_JOYSTICKS so Virtual On-style titles can use the two analog sticks as two virtual joysticks, with macro movement buttons, shot/turbo bindings, jump/crouch bindings, and Test/Service kept on L1/R1.\n- Restore the libretro crosshair overlay to be available across all game types again, while defaulting the toggle to off and honoring the saved RetroArch .opt value at game load time so the overlay appears immediately when the option is enabled.\n- Preserve the previously validated racer, fighter, gun, widescreen, and supersampling paths without changing their behavior.\n\nVisual Studio side:\n- Update the VS2008 solution and project files so they open cleanly in Visual Studio 2022 / MSVC v143.\n- Move the project metadata forward without changing the source layout, so the same repo can be used from the standalone build flow and the modern IDE setup.\n\nThe intent is to leave the repository on a stable, reproducible baseline for continued libretro tuning and IDE-based development.
…forward awareness Replace the temporary-file libretro savestate flow with an in-memory implementation and wire frontend fast-forward state into the runtime loop. This removes filesystem dependency from the savestate hot path and improves behavior for latency-sensitive frontend features. Previous behavior wrote a temporary .supermodel.st file via fopen/fwrite/fread/remove across retro_serialize_size/retro_serialize/retro_unserialize. That path introduced unnecessary disk I/O and made runtime behavior less robust under constrained filesystems. New savestate behavior: - retro_serialize_size() now builds a serialized block state directly in memory and returns its exact byte size. - retro_serialize() now copies from the prepared in-memory buffer into frontend-provided memory. - retro_unserialize() now loads state directly from frontend-provided memory without creating temporary files. - Removed libretro temp-file handshake state (savestate_path and serialize_size_called). CBlockFile was extended with a backend-agnostic model to support both existing file users and new memory users: - Added Backend enum: None/File/MemoryRead/MemoryWrite. - Added CreateMemory(), LoadMemory(), GetMemoryData(), GetMemorySize(). - Updated ReadBytes/WriteBytes/UpdateBlockSize/FindBlock/Create/Load/Close paths to operate correctly for both file and memory backends. Fast-forward awareness additions: - Query RETRO_ENVIRONMENT_GET_FASTFORWARDING each frame in retro_run(). - ApplyFastForwardAwareness() disables Throttle/VSync while frontend fast-forward is active and restores baseline values when leaving fast-forward. - Skip non-essential overlay and crosshair drawing while fast-forwarding to reduce per-frame overhead. - Added lifecycle reset/cleanup of fast-forward and in-memory savestate state in retro_init/retro_deinit/retro_unload_game. File-level summary: - Src/BlockFile.h: memory backend API and state declarations. - Src/BlockFile.cpp: memory backend implementation + backend-aware I/O/block traversal. - Src/OSD/SDL/LibRetro.cpp: in-memory savestate path, dead-code removal for temp savestate files, and fast-forward runtime awareness. Validation: Built libretro target on Win64 successfully with mingw32-make -f Makefiles/Makefile.Win32 LIBRETRO=1 BITS=64 SDL2_INCLUDE_DIR=C:/msys64/mingw64/include/SDL2 SDL2_LIB_DIR=C:/msys64/mingw64/lib -j2 and produced lib64/supermodel_libretro.dll.
This commit fixes the remaining interaction between the native Supermodel crosshair path and the libretro overlay path. Crosshair.cpp: - Save and restore OpenGL state inside CCrosshair::Update() so the native crosshair no longer leaves a modified viewport/scissor/program/VAO state behind after drawing. - Preserve GL depth, blend, and scissor enable states across the crosshair draw. - This prevents shooters from leaking the native crosshair viewport back into the libretro geometry path, which had been making supersampling collapse to 1x after runtime changes. LibRetro.cpp: - Reduce the libretro vector crosshair overlay scale from 0.5f to 0.4f so it stays readable without becoming oversized in 1x or higher supersampling modes. - Keep the overlay logic separate from the actual render resolution path so it only changes pointer visual size, not game output scaling. Behavior preserved: - Racer, fighter, soccer, analog joystick, twin joystick, and gun profiles remain unchanged. - Widescreen and supersampling behavior remain intact. - Libretro crosshair toggle still respects the RetroArch option state at game load. Net result: - Shooters keep their chosen supersampling value after toggling crosshair behavior. - Native and libretro crosshair paths no longer interfere with the active GL viewport. - The libretro overlay is smaller and easier to read without touching the game render pipeline.
Problem statement - The libretro core declared only controller port 0 and reported a single joystick to the input system. - As a consequence, any JOY2_* mapping parsed by the input layer became an empty source (out-of-range joystick index), so Player 2 controls were effectively unreachable in libretro sessions. - Although game/input definitions include P2 actions (Start2/Coin2/Joy2 directions/fighting actions), runtime libretro defaults and frontend port exposure were not enough to make them functional for fighters. What this commit changes 1) Frontend port declaration - Adds a second controller info entry (port 1) as RetroPad in retro_set_environment(). - Keeps port 0 capabilities intact (RetroPad/Mouse/Light Gun) and adds port 1 explicitly so RetroArch can configure a second player controller in-core. 2) Fighter-gated joystick count - CRetroInputSystem::GetNumJoysticks() now returns 2 only when fighting_profile_active is true; otherwise it remains 1. - This intentionally scopes the behavioral change to fighter titles and preserves existing behavior for non-fighting games. 3) Fighter profile P2 defaults (mirroring P1 intent) - Extends ApplyFightingInputDefaults() with missing P2 common + movement mappings: * InputStart2 = JOY2_BUTTON4 * InputCoin2 = JOY2_BUTTON3 * InputJoyUp2/Down2/Left2/Right2 = JOY2_BUTTON5/6/7/8 - Keeps existing P2 fighting buttons and aligns P2 with the same RetroPad semantics used by P1 in this core. 4) Fighter-specific P2 input descriptors - UpdateInputDescriptors() now publishes port 1 labels during fighting profile usage: * P2 Punch/Kick/Guard/Escape * P2 Up/Down/Left/Right * P2 Start/Coin - This improves discoverability and clarity in RetroArch control UI for the second player. 5) Port device setter compatibility - retro_set_controller_port_device() now accepts ports 0 and 1 (ignores >1). - Existing profile auto-detection logic remains tied to port 0 to avoid unintended side effects in non-fighter scenarios. Why this design - Requested scope: enable and prepare 2P specifically for fighters by cloning/mirroring port 0-style mapping for player 2. - Avoids broad multi-profile behavior changes and keeps risk localized. - Leaves room for future generalization (global multi-user support, per-port device policies for non-fighter profiles) without regressing current flows. Validation - Rebuilt libretro target successfully on Win64: mingw32-make -f Makefiles/Makefile.Win32 LIBRETRO=1 BITS=64 PLATFORM=win64 NET_BOARD=0 XINPUT=0 SDL2=0 - Build output linked successfully to lib64/supermodel_libretro.dll with no compilation/link errors for modified file.
… messages) with anti-spam throttling Overview - Introduces a reusable frontend integration foundation in the libretro core to improve observability, diagnostics, and user-facing runtime feedback. - Implements RETRO_ENVIRONMENT_GET_LOG_INTERFACE, RETRO_ENVIRONMENT_GET_PERF_INTERFACE, and message interface support with RETRO_ENVIRONMENT_SET_MESSAGE_EXT fallback to legacy RETRO_ENVIRONMENT_SET_MESSAGE. - Adds centralized anti-spam throttling so high-frequency state changes and recurring log sites do not flood RetroArch logs/OSD. Why this change - Prior state used a console logger in libretro mode and lacked structured frontend integration for logs/perf notifications. - Runtime feedback and profiling were difficult to consume from frontend tools. - We needed a base that can scale as we add more log points/events without creating noisy output. Detailed changes 1) Frontend interface discovery and lifecycle plumbing - Added RefreshFrontendInterfaces() and hooked it during environment setup and init. - Captures and tracks: * retro_log_callback (GET_LOG_INTERFACE) * retro_perf_callback (GET_PERF_INTERFACE) * message interface version (GET_MESSAGE_INTERFACE_VERSION) - Ensures safe fallback behavior when interfaces are unavailable. 2) Extensible frontend logger implementation - Added CLibretroFrontendLogger (CLogger implementation) and switched libretro init to use it. - All Debug/Info/Error paths now route through frontend-compatible log output. - Fallback to stderr remains available when frontend log interface is not present. - This preserves existing logging call sites while enabling frontend-native output globally. 3) Generic anti-spam throttling framework - Added keyed throttle storage and decision helpers for both log entries and runtime messages. - Added bounded table maintenance to avoid unbounded growth. - Added suppression summaries for deduped logs so dropped repeats are still observable in aggregate. - Default behavior: * log throttle window: 1000 ms * runtime message throttle window: 800 ms - Framework is key-based and reusable, making future additions low-risk and consistent. 4) Runtime message helpers (OSD/log UX) - Added PushRuntimeMessage() with message-ext preferred path: * RETRO_ENVIRONMENT_SET_MESSAGE_EXT when supported * automatic fallback to RETRO_ENVIRONMENT_SET_MESSAGE otherwise - Added throttled wrapper PushRuntimeMessageThrottled(...). - This provides a standardized way to publish user-visible status updates without flooding. 5) Performance counter foundation - Added perf counter registration and scoped RAII helpers: * supermodel.frame_total * supermodel.input_poll * supermodel.emulate_frame * supermodel.video_submit * supermodel.serialize * supermodel.unserialize - Added ScopedPerfCounter wrapper to ensure start/stop symmetry and keep instrumentation concise. - Added perf log flush on retro_deinit() when available. 6) Instrumentation points wired in - retro_run(): frame total, input poll, emulation, and video submit scopes. - Save-state paths: serialize/unserialize scopes plus buffer build path instrumentation. - This gives immediate visibility into frame-time distribution and save-state overhead. 7) Initial runtime events integrated through the new layer - Supersampling changes now emit both runtime OSD status and throttled frontend logs. - Input profile changes now emit throttled runtime status. - Fighter profile activation emits a one-shot status/log note confirming P2 path enabled. - Fast-forward state transitions emit throttled debug log entries. Compatibility and behavior notes - No regression to old frontends: if message-ext/log/perf interfaces are unavailable, behavior gracefully degrades. - Logging architecture remains compatible with existing ErrorLog/InfoLog/DebugLog call sites. - Throttling is centralized and key-based, so future event points can be added with minimal risk of log spam. Validation - Successfully rebuilt Win64 libretro target: mingw32-make -f Makefiles/Makefile.Win32 LIBRETRO=1 BITS=64 PLATFORM=win64 NET_BOARD=0 XINPUT=0 SDL2=0 - Output linked successfully to lib64/supermodel_libretro.dll. - Verified modified integration points are compiled and reachable in libretro lifecycle paths (set_environment/init/run/serialize/unserialize/deinit).
…roducible Win32 build script Summary - Implements libretro memory API wiring for persistent Model 3 memory regions. - Adds a dedicated Win32 build entry point (`build32.bat`) to mirror existing `build64.bat` workflow. - Validates 32-bit and 64-bit build scripts from repository root and confirms produced binary architectures. Context / Problem - `retro_get_memory_data()` and `retro_get_memory_size()` previously returned `NULL`/`0`, so frontend SRAM/RTC persistence could not rely on direct memory regions. - A 64-bit helper script existed (`build64.bat`) but there was no equivalent root-level helper for Win32 builds. Detailed changes 1) Expose EEPROM backing storage from device class - Added non-invasive accessors to `C93C46`: - `GetData()` / `GetData() const` - `GetSizeBytes()` - This exposes the exact EEPROM register buffer (`regs`) and size in bytes without changing emulation behavior. - Files: - Src/Model3/93C46.h - Src/Model3/93C46.cpp 2) Expose persistent memory from `CModel3` - Added accessor surface in `CModel3` for libretro memory mapping: - `GetBackupRAMData()` / const variant - `GetBackupRAMSize()` (0x20000 / 131072 bytes) - `GetEEPROMData()` / const variant - `GetEEPROMSize()` (93C46 byte size) - Files: - Src/Model3/Model3.h - Src/Model3/Model3.cpp 3) Implement libretro memory API in core frontend - `retro_get_memory_data(unsigned id)` now maps: - `RETRO_MEMORY_SAVE_RAM` -> Model 3 Backup RAM pointer - `RETRO_MEMORY_RTC` -> 93C46 EEPROM pointer - `retro_get_memory_size(unsigned id)` now reports matching byte sizes. - Includes safe guards: - requires `game_loaded` and non-null emulator - uses `CModel3` type guard before mapping pointers - File: - Src/OSD/SDL/LibRetro.cpp 4) Add Win32 build helper script - New root script: `build32.bat` - Mirrors `build64.bat` style: - sets `mingw32` toolchain paths - sets SDL2 include/lib dirs for mingw32 - calls `mingw32-make` for `LIBRETRO=1 BITS=32` - returns proper exit code - File: - build32.bat Verification performed 1) Executed both scripts from repo root: - `build64.bat` -> exit code 0 - `build32.bat` -> exit code 0 2) Verified output binary architecture explicitly: - `lib64/supermodel_libretro.dll` => `pei-x86-64` - `lib32/supermodel_libretro.dll` => `pei-i386` 3) Smoke-tested RetroArch Win32 with the new Win32 core and required system/config files: - Core loads and boots content. - Frontend runtime confirms SRAM save operations for RAM type #0 and RAM type #1. - Save artifacts produced by frontend include: - `.srm` for save RAM - `.rtc` for RTC/EEPROM region Notes - This patch intentionally keeps existing `.nv` handling logic untouched; memory API exposure is additive for frontend-native persistence paths. - Memory API mapping is focused on persistent regions suitable for frontend save management and avoids exposing transient runtime RAM.
- Add a libretro-specific GLEW path that resolves OpenGL symbols through RetroArch's get_proc_address callback instead of GLX/EGL. - Keep the Linux core portable across X11 and Wayland while preserving the existing OpenGL/OpenGL core HW render path. - Fix Linux build coverage in Rules.inc for the actual source filenames, PIC flags, and libretro defines. - Guard the Windows DPI awareness hint so standalone Linux builds do not see a Windows-only SDL hint. - Add buildlinux.bat to stage, compile, install the Linux core, emit the .info file, and copy the vf3 test ROM into the VM for validation.
RefreshOutputGeometry() was overriding the core's game geometry with GL_VIEWPORT from the current RetroArch framebuffer. That works poorly on Linux/Wayland where the hw context can expose a much larger surface, leaving the game rendered in a small corner of the output. Keep the model 3 geometry as the source of truth and let RetroArch scale the framebuffer.
This reverts commit d506845.
Keep the Windows path untouched while restoring full-screen presentation on Linux. Linux now uses the frontend output dimensions for geometry, and the final New3D composite disables the lingering scissor test so the framebuffer is not clipped to the lower-left corner.
Add three high-value core options to the libretro frontend without disturbing existing defaults: PowerPCFrequency, LegacySoundDSP, and CRTcolors.\n\nPowerPCFrequency:\n- Expose an Auto/66/100/166 MHz choice in RetroArch core options.\n- Keep Auto tied to the ROM-set stepping default so the existing XML-driven behavior remains unchanged.\n- Apply the setting live by updating runtime config; the frame timing path already consumes it per frame, so no renderer rebuild is needed.\n\nLegacySoundDSP:\n- Expose the compatibility SCSP DSP path as a runtime option.\n- Add an explicit SCSP setter so the global DSP mode can be switched in place without restarting the core.\n- Preserve the existing default of disabled, matching the current libretro behavior.\n\nCRTcolors:\n- Expose CRT color emulation as a runtime video option.\n- Plumb the selected CRT color into SuperAA instead of hardcoding None.\n- Rebuild renderers automatically when the option changes so the shader path updates immediately and safely.\n\nBehavioral notes:\n- No changes to the default user experience when all options stay at their defaults.\n- Existing video/input/runtime options continue to work as before.\n- Verified compilation for both Win64 and Win32 libretro builds.
After rebasing onto trzy, CNetBoard/CSimNetBoard read config["Network"] (NetBoard.cpp / SimNetBoard.cpp), which the standalone sets in Main.cpp but the libretro self-contained config only set "SimulateNet" for. Games with a Net Board (e.g. Spikeout Final Edition) threw `Node "Network" does not exist` from retro_load_game. Mirror Main.cpp's default.
- Pointer-overlay (crosshair) shader used #version 130, rejected under macOS's
required GL 4.1 core profile ("Pointer overlay shader compile failed"). The
shader body is already core-compatible (in/out, no fixed-function); bump both
stages to #version 410 core to match the New3D shaders.
- Add build-libretro-macos.sh capturing the two non-obvious build requirements:
Apple /usr/bin/clang (Homebrew libc++ __hash_memory skew) and SDL2/SDL2_net
frameworks symlinked next to the dylib for @loader_path resolution.
For frontend memory inspection / game analysis (RAM-diff to locate health, position, flags), expose CModel3's live 8 MB PowerPC RAM via the libretro memory API, alongside mixerjdp's existing SAVE_RAM (backup) / RTC (EEPROM) regions which are persistence-only. - CModel3::GetPPCRAMData()/GetPPCRAMSize() return `ram` / 0x800000. - retro_get_memory_data/size dispatch RETRO_MEMORY_SYSTEM_RAM. - Documented the byte-swapped storage (PPC byte A at data[A^3], halfword [A^2], word [A]) so downstream ram-diff can map offsets back to PPC addresses. Verified end-to-end: retro-trainer's read_system_ram() returns 8388608 bytes for Spikeout.
|
I just merged a big update that @mixerjdp did to the PR that makes it a lot better and removes most of my hacks. He did a killer job and I think it is so much better now. |
This PR has a basic version of a libretro core.
There are some obviously ugly things that would be a lot more beautiful with some (hopefully small) changes to Supermodel, but it performs very well on OS X and Windows with 'Spikeout: Final Edition'.
Things I wish were a little different about Supermodel
CreateGLScreenis almost identical, although I modified my copy to hide the window.Things I'm not sure how you'd prefer things to be implemented
Hacks I made that are possible to fix but I just haven't done
I'm posting this to get feedback on the above points and advertise in case anyone else is interested in working on this.