Skip to content

[WIP] Libretro core implementation#1770

Merged
midwan merged 46 commits intoBlitterStudio:libretro-corefrom
rtissera:libretro-core-rtissera
Feb 10, 2026
Merged

[WIP] Libretro core implementation#1770
midwan merged 46 commits intoBlitterStudio:libretro-corefrom
rtissera:libretro-core-rtissera

Conversation

@rtissera
Copy link
Contributor

@rtissera rtissera commented Jan 28, 2026

Fixes #1759 .

Changes proposed in this pull request:

  • Libretro core for linux/amd64 and linux/aarch64
  • WHDLoad support
  • Libretro core options
  • No JIT, no MIDI, no IPF at the moment

@midwan

rtissera and others added 30 commits January 21, 2026 18:17
@rtissera rtissera changed the title Libretro core rtissera [WIP] Libretro core implementation Jan 29, 2026
@rtissera rtissera marked this pull request as ready for review February 5, 2026 21:34
@rtissera rtissera requested a review from midwan as a code owner February 5, 2026 21:34
@midwan
Copy link
Collaborator

midwan commented Feb 6, 2026

This was so big, I enlisted the help of LLMs to go through it...

What's Good

  1. Platform abstraction is well-designed -- The header indirection pattern via CMake defines keeps the libretro code cleanly separated from the host build. This is much better than littering #ifdef blocks everywhere.

  2. Code quality fixes that benefit all builds:

  • src/archivers/chd/chdcd.cpp: Adds return-value checking to all fread()/fgets() calls
  • src/archivers/chd/corestr.cpp: Fixes signed/unsigned conversion issues
  • src/archivers/lha/header.cpp: Fixes readlink() buffer overflow vulnerability and UB in _sntprintf
  • src/osdep/bsdsocket_host.cpp: Suppresses unused return value warnings
  • src/jit/compemu_prefs.cpp: Adds missing includes
  1. dr_flac alternative -- A complete FLAC decoder alternative using the single-header dr_flac library, avoiding the libFLAC dependency for libretro builds while preserving the original code path.

  2. Cooperative threading via libco -- Using coroutines to bridge the libretro run-loop model with Amiberry's main loop is the standard approach for libretro cores.

  3. CI workflow changes are solid -- proper cross-compilation support with fallback zlib building.

Concerns & Issues

High Priority

  1. src/include/sysdeps.h changes are risky (+65 -26)
    This is a foundational header included everywhere. The changes restructure POSIX/stdio emulation, change function signatures (posixemu_close return type from void to int, parameter types from TCHAR* to void*), and add extern "C" blocks. Any regression here will be felt across the entire codebase. Needs very careful testing of the host build.

  2. src/osdep/amiberry_filesys.cpp has massive #ifdef LIBRETRO blocks (+345 lines)
    Despite the nice abstraction elsewhere, this file adds 345 lines of #ifdef LIBRETRO alternative implementations for nearly every filesystem function. This goes against the PR's own abstraction pattern. Consider moving these to a separate amiberry_filesys_libretro.cpp file or using the same header-indirection pattern.

  3. src/osdep/amiberry.cpp still has #ifdef LIBRETRO blocks
    The controller mapping save/load functions use #ifdef LIBRETRO to switch between C++ fstream and C FILE* I/O. This should follow the platform abstraction pattern too.

  4. src/fpp_native.cpp change is questionable
    Changing defined(GNUC) && 0 (intentionally disabled dead code) to defined(GNUC) && defined(LIBRETRO) re-enables x87 FPU control word manipulation for libretro builds. Why was this disabled in the first place? What x87 behavior does this fix? This needs a comment explaining the rationale.

  5. src/custom.cpp removes #ifdef SERIAL_PORT guard
    Removing the guard around #include "serial.h" makes it unconditional. Is this safe for all build configurations? What if serial port support is intentionally disabled?

Medium Priority
6. Vendored dependencies are huge
libretro-common and libco add ~130K+ lines. Consider using git submodules instead of vendoring the full libraries in-tree. This would keep the repo size manageable and make updates easier.

  1. Commit history is messy
    39 commits with messages like "WIP", "More pruning", "Fixup", duplicate merge commits. Consider squashing into logical units before merge:
  • Platform abstraction layer
  • dr_flac FLAC alternative
  • Code quality fixes (chdcd, corestr, lha, bsdsocket)
  • Libretro core implementation
  • CI changes
  1. src/osdep/amiberry_whdbooter.cpp mixes concerns (+366 -50)
    This file adds both libretro filesystem helpers AND new WHDLoad features (archive slave detection, kickstart copying, environment variable support). These should be separate changes. The environment variable paths (AMIBERRY_WHDBOOT_PATH, AMIBERRY_WHDBOOT_SAVE_DATA) might also be useful for non-libretro builds.

Low Priority
9. src/osdep/dpi_handler.hpp -- Changing "SDL.h" to <SDL.h> changes include search order. Verify this doesn't break any existing build configurations.

  1. src/include/options.h -- Changing from guisan/color.hpp to gui_color_platform.h affects all builds, not just libretro. The host header must be a perfect drop-in replacement.

  2. dr_mp3.h is included but unclear if it's used -- verify the MP3 decoder is actually wired up, or remove it to avoid dead code.

Recommendations

  1. Split the code quality fixes (chdcd, corestr, lha, bsdsocket) into a separate PR that can be merged to master immediately -- they benefit all builds and have nothing to do with libretro.

  2. Move filesystem #ifdef LIBRETRO blocks in amiberry_filesys.cpp to the platform abstraction pattern or a separate compilation unit.

  3. Test the host build thoroughly after the sysdeps.h changes, especially the POSIX emulation signature changes.

  4. Squash commits into logical groups before merge.

  5. Add comments explaining non-obvious decisions (fpp_native x87 change, JIT disabled on x86_64, serial.h guard removal).

  6. Consider submodules for libretro-common and libco instead of vendoring.

Summary

This is an impressive amount of work for a libretro core implementation. The platform abstraction pattern is well-designed and the right approach. The main risks are in the sysdeps.h changes (affects all builds), inconsistent use of the abstraction pattern (filesystem still uses #ifdef), and the sheer size making review difficult. Splitting out the independent code quality fixes and squashing the commit history would make this much easier to review and merge safely.

@rtissera
Copy link
Contributor Author

rtissera commented Feb 6, 2026

Yeah, this is quite invasive.
Let me go through the valid points leveraged by LLM analysis and address them.
I will do asap first round (high priority risks) @midwan

@rtissera
Copy link
Contributor Author

rtissera commented Feb 8, 2026

@midwan can you reasset the PR before I move to proper rebase / squash commit re-organization ?

@midwan midwan requested a review from Copilot February 8, 2026 17:32
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Libretro core implementation (Linux amd64/aarch64) with Libretro-specific platform abstractions for audio/video/input/logging and filesystem access, plus updates to WHDLoad boot flow and CHD/FLAC handling to better suit Libretro environments.

Changes:

  • Introduces platform-indirection headers (gfx/input/sound/gui/color/amiberry platform) to support both host and Libretro builds.
  • Adds Libretro VFS-backed stdio/POSIX emulation and adapts filesystem usage to route through it.
  • Updates WHDLoad booting (including archive slave fallback) and hardens several file/network parsing paths.

Reviewed changes

Copilot reviewed 80 out of 82 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/threaddep/thread.h Drops SDL_thread include for Libretro shim compatibility
src/specialmonitors.cpp Disables PNG/genlock loading under Libretro
src/sounddep/sound_platform_internal_libretro.h Libretro audio backend hooks (batch/callback)
src/sounddep/sound_platform_internal_host.h Host stub for sound platform indirection
src/sounddep/sound_platform_internal.h Includes selected sound platform header
src/sounddep/sound.cpp Routes audio open/output/enumeration through platform hooks
src/slirp/tcp_subr.cpp Fixes unsafe snprintf sizing and bounds handling
src/slirp/misc.cpp Silences unused syscall return warnings
src/qemuvga/qemuuaeglue.h Adds missing stddef include
src/ppc/ppcd.cpp Hardens operand formatting with bounded append helper
src/osdep/writelog.cpp Preps host logging to coexist with Libretro logging
src/osdep/sysconfig.h Adds Libretro JIT gating + portability tweaks
src/osdep/retroarch.cpp Adds FILE*-based parsing for Libretro builds
src/osdep/registry.cpp Routes filesystem checks through amiberry_fs abstraction
src/osdep/main.cpp Adds standalone main() wrapper calling amiberry_main
src/osdep/libretro/writelog.cpp Libretro logging implementation using log_cb/SDL_Log
src/osdep/libretro/stdioemu_vfs.cpp Implements stdio emulation via Libretro VFS (cookie-based)
src/osdep/libretro/posixemu_vfs.cpp Implements POSIX emulation via Libretro VFS
src/osdep/libretro/mp3decoder.cpp Adds Libretro MP3 decoder (dr_mp3 + zfile)
src/osdep/libretro/libretro_vfs.h Declares accessors for Libretro VFS interface availability
src/osdep/libretro/input_platform_internal.h Libretro joystick enumeration/mapping defaults
src/osdep/libretro/input_platform.cpp Libretro keyboard init stub
src/osdep/libretro/gui_handling_platform.h Libretro GUI handling shim includes stub
src/osdep/libretro/gfx_platform_internal.h Libretro gfx platform hooks (present/output/format/display)
src/osdep/libretro/amiberry_platform_internal.h Libretro platform behavior hooks (SDL/event pump/etc)
src/osdep/libretro/amiberry_fs.h Filesystem abstraction using VFS-backed posixemu calls
src/osdep/keyboard.cpp Includes SDL.h for required key APIs
src/osdep/input_platform_internal_host.h Host joystick init/mapping via SDL controller DB
src/osdep/input_platform_internal.h Includes selected input platform header
src/osdep/input_platform.h Declares osdep_init_keyboard()
src/osdep/input_platform.cpp Host keyboard init (RetroArch config + german layout detect)
src/osdep/gui_handling_platform_host.h Host GUI handling include passthrough
src/osdep/gui_handling_platform.h Includes selected GUI handling header
src/osdep/gfx_platform_internal_host.h Host gfx platform hooks (png/screenshots/window icon)
src/osdep/gfx_platform_internal.h Includes selected gfx platform header
src/osdep/dpi_handler.hpp Switches to <SDL.h>/<SDL_ttf.h> includes
src/osdep/bsdsocket_host.cpp Silences unused read/write return values
src/osdep/amiberry_whdbooter.cpp VFS-aware kickstart handling + slave fallback in archives
src/osdep/amiberry_platform_internal_host.h Host platform hooks for SDL/UI/clipboard and event pump
src/osdep/amiberry_platform_internal.h Includes selected amiberry platform header
src/osdep/amiberry_input.h Includes SDL.h for controller symbols/types
src/osdep/amiberry_input.cpp Refactors keyboard/joystick init through platform hooks
src/osdep/amiberry_gfx.cpp Refactors gfx through platform hooks; Libretro frame output
src/osdep/amiberry_filesys.cpp Routes filesystem operations through amiberry_fs/VFS when needed
src/osdep/amiberry.cpp Moves platform-dependent behavior behind platform hooks; amiberry_main
src/jit/compemu_prefs.cpp Adds missing includes (likely to fix build break)
src/include/uae/string.h Adds standard C/C++ includes needed by string utilities
src/include/sysdeps.h Adds STAT typedef + Libretro DONT_HAVE_POSIX/STDIO wiring
src/include/options.h Swaps GUI color include to platform-selected header
src/include/gui_color_platform_host.h Host GUI color include passthrough
src/include/gui_color_platform.h Includes selected GUI color header
src/fpp_native.cpp Libretro-safe x87 control word setting using inline asm
src/blkdev_cdimage.cpp Makes FLAC backend selectable (dr_flac vs libFLAC)
src/archivers/lha/header.cpp Fixes readlink bounds handling for LHA headers
src/archivers/chd/osdlib_unix.cpp Uses <SDL.h> include path
src/archivers/chd/flac_platform_internal_libretro.h Libretro FLAC platform settings/types (dr_flac)
src/archivers/chd/flac_platform_internal_host.h Host FLAC platform settings (libFLAC)
src/archivers/chd/flac_platform_internal.h Includes selected CHD FLAC platform header
src/archivers/chd/flac.h Adds platform switch for FLAC encoder/decoder APIs
src/archivers/chd/flac.cpp Adds dr_flac-based decoder + Libretro encoder stub
src/archivers/chd/corestr.cpp Fixes size_t/long overflow hazards in string distance
src/archivers/chd/chdcd.cpp Hardens parsing against short reads / bad fgets loops
libretro/libretro_stubs.cpp Adds Libretro stubs for GUI/MIDI/ethernet/other host deps
libretro/libretro_shared.h Exposes log_cb to core code
libretro/libretro_gui_stubs.cpp Adds GUI/TTF/VKBD stub functions for Libretro
libretro/libretro-common Adds libretro-common as submodule pointer
libretro/libco Adds libco as submodule pointer
libretro/gui_handling_stub.h Defines minimal GUI handling symbols for Libretro
libretro/gui_color_platform_libretro.h Provides minimal gcn::Color for Libretro builds
libretro/SDL_ttf.h Libretro SDL_ttf shim header
libretro/SDL_thread.h Libretro SDL_thread shim header
libretro/SDL_mutex.h Libretro SDL_mutex shim header
libretro/SDL.h Libretro SDL shim header
libretro/Makefile Builds Libretro core + wires platform headers/VFS/zlib/submodules
cmake/SourceFiles.cmake Adds host platform header defines + new source files
.gitmodules Registers libretro-common & libco submodules
.github/workflows/c-cpp.yml Uses submodules; adds zlib support for aarch64 cross build
Comments suppressed due to low confidence (4)

src/osdep/libretro/writelog.cpp:1

  • SDL_GetTicks() is time-since-start, not Unix epoch time. Converting it to time_t and passing it to localtime() will produce incorrect timestamps (typically near 1970). Use time(nullptr) (or std::chrono::system_clock) for the wall-clock portion and keep SDL_GetTicks() only for relative/elapsed timing if needed.
    src/osdep/libretro/writelog.cpp:1
  • vsnprintf can return a negative value on encoding errors, or a value >= the provided buffer size when output is truncated. Using buffer[count] can write out of bounds. Clamp the index (e.g., treat negative as 0; treat >= (WRITE_LOG_BUF_SIZE - 1) as (WRITE_LOG_BUF_SIZE - 1)) before writing the terminator.
    src/osdep/libretro/stdioemu_vfs.cpp:1
  • In Libretro builds, falling back to ::fopen bypasses the Libretro VFS and may fail in sandboxed/front-end environments (and defeats the purpose of DONT_HAVE_STDIO). Consider returning nullptr when VFS isn't available/usable, or provide an alternate non-cookie implementation for non-glibc platforms instead of using the host filesystem as a fallback.
    src/osdep/libretro/posixemu_vfs.cpp:1
  • posixemu_access ignores the requested access mode (R_OK/W_OK/X_OK), so callers will treat “exists” as “permitted”, which is not equivalent to POSIX access(2). If you can't reliably emulate permissions with Libretro VFS, a safer approximation is to attempt an open in the requested mode (read/write) and return 0 only if it succeeds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Use sizeof(int16_t) for FLAC filesize/frame calculations since
drflac_read_pcm_frames_s16 always outputs 16-bit samples, regardless
of source bit depth (e.g. 24-bit FLAC would overallocate).

Widen posixemu_seek and io_lseek from int to off_t so that seek offsets
on large disk images (>2GB HDF/CHD) are not truncated to 32 bits.
Prevents tar from receiving an HTML error page on transient
network failures, giving a clear error instead.
@rtissera rtissera requested a review from midwan February 9, 2026 20:04
@rtissera
Copy link
Contributor Author

rtissera commented Feb 9, 2026

@midwan let me know if current failures are expected or not

@midwan
Copy link
Collaborator

midwan commented Feb 9, 2026

The build failures on the opengl targets is because that branch is behind the imgui one that is actively worked on. I've removed glew from there, and also from the docker images used to build, since it was not needed/used. But the libretro branch didn't get that change. I could merge the latest of imgui to the libretro branch, and then you can update your branch from there accordingly, and that should fix these errors.

@rtissera
Copy link
Contributor Author

@midwan okay I will work on conflict resolution now

@midwan midwan merged commit b0cef1f into BlitterStudio:libretro-core Feb 10, 2026
20 of 25 checks passed
@cscd98
Copy link

cscd98 commented Feb 14, 2026

Thanks for the libretro port! I'm getting a compile error with this:

In file included from ../src/a2065.cpp:10:
../src/osdep/sysconfig.h:60:9: warning: "AMIBERRY" redefined
   60 | #define AMIBERRY
      |         ^~~~~~~~
<command-line>: note: this is the location of the previous definition
../src/osdep/sysconfig.h:61:2: error: #endif without #if
   61 | #endif
      |  ^~~~~
../src/osdep/sysconfig.h:745: error: unterminated #ifndef
  745 | #ifndef __MINGW32__
make: *** [Makefile:536: ../src/a2065.o] Error 1

Can the JIT include armv7a also?

@midwan
Copy link
Collaborator

midwan commented Feb 14, 2026

This is still pretty much WIP, but the automated builds don't fail - so something must be wrong where you compiled it. Please open a new issue with more details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants