A Libretro frontend implementation using Raylib for macOS.
Created by mikedx
This project is licensed under the MIT License.
This project uses the following third-party libraries:
-
libretro API: The official
libretro.hheader file is included from RetroArch's libretro-common repository. Copyright (C) 2010-2024 The RetroArch team. The libretro API is available under the MIT License (as stated in the header file). See https://www.libretro.com/ for details. Note: Thelibretro.hfile in this repository is an unmodified copy and should not be edited. -
raylib: Used under the zlib/libpng license. See https://github.com/raysan5/raylib for details.
- macOS with Xcode Command Line Tools
- raylib installed in
../raylib/src - A libretro core (
.dylibfile) for your target platform
You can use the included script to download cores:
./download_cores.shThis will:
- Fetch the list of available cores from the libretro buildbot
- Display them in a menu
- Allow you to download individual cores or all cores
- Save them to the
cores/directory
makeThis will create the libretro_raylib executable.
./libretro_raylib <path_to_core.dylib> [rom_file]# Load a core with a ROM file (using downloaded core)
./libretro_raylib cores/mgba_libretro.dylib mike_test.gba
# Load a core without a ROM (for cores that support no-game mode)
./libretro_raylib cores/mgba_libretro.dylib
# Atari 2600 (Stella core)
./libretro_raylib cores/stella_libretro.dylib pitfall.bin
# SNES (bsnes core)
./libretro_raylib cores/bsnes_libretro.dylib mario_kart.sfc
# SNES (snes9x core)
./libretro_raylib cores/snes9x_libretro.dylib super_mario_world.sfc
# Or use a core from any location
./libretro_raylib /path/to/core.dylib /path/to/rom.gba- Arrow Keys / WASD - D-Pad
- X - A button
- Z - B button
- C - X button
- V - Y button
- Q - L button
- E - R button
- TAB - Select
- ENTER - Start
- ESC - Exit
- Dynamic loading of libretro cores
- Video rendering with pixel format conversion and proper frame/display dimension handling
- Audio playback with ring buffer management and underrun/overflow protection
- Keyboard input mapping
- Aspect ratio preservation
- Modular architecture for maintainability and extensibility
- Support for multiple pixel formats (XRGB8888, RGB565, 0RGB1555, RGB555)
The frontend is organized into modular components:
-
libretro.h- Official libretro API header (unmodified copy from RetroArch)- All libretro constants, enums, structures, and type definitions
- Callback type definitions
- This file is maintained by the RetroArch/libretro team and should not be modified
-
libretro_core_types.h- Custom core function pointer wrapperretro_core_tstructure for holding dynamically loaded core function pointers- Core symbol name definitions (
SYM_RETRO_*) - This is our own structure, not part of the official libretro API
-
libretro_frontend.h/c- Main public API- Coordinates all modules
- Public API functions for core management
- Frontend state management
-
libretro_environment.h/c- Environment callback implementation- Handles core requests for system information
- Pixel format configuration
- Directory paths and system settings
- Log interface support
-
libretro_video.h/c- Video refresh callback- Receives rendered frames from cores
- Pixel format conversion (RGB565, XRGB8888, 0RGB1555)
- Framebuffer management
- Auto-detection of pixel formats
-
libretro_audio.h/c- Audio callbacks- Single-sample and batch audio callbacks
- Ring buffer management for audio streaming
- Audio format conversion (int16_t to float)
- Handles cores that use single-sample callbacks (e.g., xrick)
-
libretro_input.h/c- Input handling- Input poll callback
- Input state queries (joypad and keyboard)
- Keyboard keycode mapping
libretro_core.h/c- Core loading and management- Dynamic library loading (dlopen)
- Core symbol resolution
- Core initialization
- ROM loading (supports both fullpath and memory-based loading)
- Audio/video info updates
- Core cleanup and resource management
main.c- Main entry point and raylib integration- Window management
- Input handling (keyboard to libretro mapping)
- Audio stream management
- Frame rendering loop
The modular design provides:
- Separation of concerns: Each module handles a specific aspect of the libretro API
- Maintainability: Easier to locate and modify specific functionality
- Testability: Modules can be tested independently
- Readability: Smaller, focused files are easier to understand
- The frontend supports pixel formats:
- XRGB8888 (format 1): 32-bit format, 8 bits per channel
- RGB565 (format 2): 16-bit format, 5-6-5 bits (R-G-B), used by mGBA
- 0RGB1555 (format 0): 16-bit format, 5-5-5 bits (R-G-B), used by bsnes
- RGB555 (format 12): 16-bit format, 5-5-5 bits (R-G-B), used by snes9x
- Audio is converted from int16_t samples to float for raylib
- Video frames are converted to RGBA8888 format for rendering
- Audio uses a ring buffer to handle timing variations between core and playback
- Single-sample audio callbacks are supported for cores like xrick
The following cores have been tested and are working:
- mGBA - Game Boy Advance emulation
- bsnes - SNES emulation (including Super Mario Kart)
- snes9x - SNES emulation (tested with Super Mario World and Super Mario Kart)
- Stella - Atari 2600 emulation
None at this time. If you encounter issues with specific cores or games, please report them.