Porting Retrodev to Other Platforms

March 19, 2026 · View on GitHub

Cross-platform library choices

Every third-party library in Retrodev was chosen for explicit cross-platform support. None of them require platform-specific code paths in the application layer:

LibraryRolePlatforms
SDL3Window, renderer, input, file I/OWindows, Linux, macOS, and more
Dear ImGui (SDL3 + SDLRenderer3 backends)UIAny platform SDL3 runs on
FreeTypeFont rasterisationAll platforms
AngelScriptScripting engineAll platforms
RASMZ80 assemblerAll platforms
GlazeJSON serialisation (header-only)All platforms
CTRECompile-time regex (header-only)All platforms
ClangCompiler used for all buildsWindows, Linux, macOS

The result is that the vast majority of the codebase compiles and runs identically on every platform with no conditional code at all.

Path convention

All source file paths and all build artifact paths use forward slashes (/) throughout the entire codebase, including the Kombine build scripts. There are no calls to Windows-specific path APIs (GetFullPathNameW, backslash concatenation, etc.) and no POSIX-specific path assumptions anywhere in the application code. Kombine and the underlying OS normalise the separator when making actual filesystem calls.

Platform filtering in Kombine scripts

Platform-specific source files are placed in subfolders named win/, lnx/, or osx/. The Kombine build scripts (retro.dev.lib.csx and retro.dev.gui.csx) build a full source list from globs and then filter it at build time using the Kombine host detection API:

// Host.IsWindows() — skip Linux and macOS sources
if (filex.Contains("/osx/") || filex.Contains("/lnx/"))
    continue;

// Host.IsLinux() — skip Windows and macOS sources
if (filex.Contains("/win/") || filex.Contains("/osx/"))
    continue;

// Host.IsMacOS() — skip Windows and Linux sources
if (filex.Contains("/win/") || filex.Contains("/lnx/"))
    continue;

Any new platform-specific implementation file placed in the correct subfolder is automatically picked up or excluded by this mechanism — no changes to the build scripts are needed beyond adding the folder filter if a new platform name is introduced.

On Windows release builds the GUI script additionally adds the .rc resource file to the source list (application icon and manifest) and passes the following linker flags, which are Windows-only:

-Wl,/subsystem:windows
-Wl,/manifest:embed
-Wl,/manifestinput:gui/os/win/retrodev.manifest

Platform-specific source files

Application entry point

src/gui/os/win/entry.cpp provides the Windows entry point. In release mode it defines WinMain, converts the LPSTR command line to a UTF-8 argv array via WideCharToMultiByte, and calls the shared retromain(). In debug mode the same file defines a standard main() so the application runs as a console program.

An equivalent entry point file does not yet exist for Linux (src/gui/os/lnx/) or macOS (src/gui/os/osx/). Because both of those platforms use a standard main() signature, each file would be trivial — a single main(int argc, char** argv) forwarding to retromain().

Emulator process launching

This is the only area where platform-specific system API calls are required. The interface is declared in src/lib/assets/source/source.emulator.native.h and implemented separately per platform:

FilePlatformAPI used
src/lib/assets/source/win/source.emulator.native.win.cppWindowsCreateProcessW, WaitForSingleObject, GetExitCodeProcess, CloseHandle
src/lib/assets/source/lnx/source.emulator.native.lnx.cppLinuxposix_spawn, posix_spawn_file_actions_t, waitpid
src/lib/assets/source/osx/source.emulator.native.osx.cppmacOSposix_spawn, posix_spawn_file_actions_t, waitpid

All three implementations are already present in the repository. The Linux and macOS files share the same posix_spawn approach, including a command-line tokeniser that correctly handles quoted paths with spaces.

Windows-only resources

src/gui/os/win/ also contains retrodev.rc, resource.h, retrodev.ico, and retrodev.manifest. These are compiled only on Windows release builds by the Kombine source filter and linker flags described above. They have no equivalent on other platforms and none is needed.

Windows SDK libraries

retro.dev.gui.csx links the following Windows SDK libraries on Windows builds only (guarded by Host.IsWindows()):

dwmapi.lib  user32.lib  kernel32.lib  gdi32.lib  winmm.lib
setupapi.lib  imm32.lib  shell32.lib  ole32.lib  advapi32.lib
version.lib  oleaut32.lib  Shcore.lib  uxtheme.lib  Ws2_32.lib

The equivalent system library list for Linux and macOS is currently a // TODO block in the script and must be filled in when those ports are completed.

Summary: what remains for a Linux or macOS port

ItemStatus
All application and library C++ sources✅ Already cross-platform
Third-party libraries (SDL3, ImGui, FreeType, etc.)✅ All support Linux and macOS
Kombine platform filtering infrastructure✅ Already handles Linux and macOS folder exclusion
Emulator spawn (posix_spawn)lnx and osx files already exist
Application entry point (main())src/gui/os/lnx/ and src/gui/os/osx/ files not yet created
System linker libraries❌ TODO blocks in retro.dev.gui.csx need filling