* docs: update PORTING.md and Fast3D README with accurate codebase info Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/5ed461fd-5205-4e07-86d7-3fc017141c9d Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com> * docs: fix minor grammar in PORTING.md Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/5ed461fd-5205-4e07-86d7-3fc017141c9d Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com> * docs: improve README, CONTRIBUTING, and include/fast/README Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/71d3affa-8cb3-43ba-a652-3c727c342e7f Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com> * Update docs/PORTING.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * docs: fix Windows vcpkg and Android build type in README Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/024701b5-63bc-40c3-97b0-a54357640efa Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com> Co-authored-by: Kenix3 <kenixwhisperwind@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
6.7 KiB
Libultraship (LUS) Porting Guide
Libultraship (LUS) is a library designed to facilitate PC ports of Nintendo 64 games. It is not a recompilation tool; rather, it allows developers to build a game's original source code (derived from decompilation) on modern hardware by providing a header-compatible wrapper around modern reimplementations of N64 SDK functions.
In essence, LUS acts as "compile-time WINE" for the N64.
Supported Platforms
LUS supports the following platforms and rendering backends:
| Platform | Rendering Backends |
|---|---|
| Windows | OpenGL, Direct3D 11 |
| macOS | OpenGL, Metal |
| Linux | OpenGL |
| iOS | OpenGL, Metal |
| Android | OpenGL ES |
| OpenBSD | OpenGL |
Prerequisites
- A Game Decompilation: You must have the source code of the game (e.g., Star Fox 64, Banjo-Kazooie) ready to build.
- Template Project: Use Ghostship as your reference. This is the standard example project used by existing ports to handle CMake configurations and asset management. Ghostship is a separate repository and is not included in this one.
The Porting Process
Phase 1: The "Stub" Build
The initial goal is not a playable game, but simply a functional executable that links against LUS.
-
Setup:
- Copy the CMake files from the Ghostship template into your decompilation directory.
- Ensure
libultrashipis added as a submodule.
-
Header Replacement:
- Replace N64 SDK includes (e.g.,
#include <ultra64.h>) in the source code with LUS includes:#include <libultraship/libultraship.h> - Use the public include path shown above unless you have explicitly configured your project's include directories to support a different form.
- Replace N64 SDK includes (e.g.,
-
Compile & Fix:
- Attempt to build. You will encounter thousands of errors.
- Stubbing: Comment out or stub functions that LUS handles automatically (e.g.,
osCreateThreadfor rumble, as LUS manages threads differently than the N64 CPU). - Disable Systems: Temporarily disable complex systems like Audio to simplify the build.
- 64-bit Fixes: Address pointer size differences and other architecture-specific issues.
- Iterate: Rinse and repeat until you successfully generate an executable (
.exeor binary).
Phase 2: Runtime & Logic
Once the executable exists, the game will likely crash immediately or behave erratically.
- Debugging: Use breakpoints to trace the logic and fix crashes as they arise.
- Microcode (UCode): Verify the game's graphics microcode.
- LUS supports the following GBI microcode variants via the
GBI_UCODECMake option:F3DEX_GBI_2(default),F3DEX_GBI, andF3DLP_GBI. Set this to match your game's microcode. - Custom UCodes (e.g., specific Rareware implementations) may need manual implementation or adjustments in the renderer.
- LUS supports the following GBI microcode variants via the
Phase 3: Assets (The Fork in the Road)
You have two options for handling game assets (textures, models, etc.):
Option A: OTR/O2R (The "Torch" Method) Recommended
- Description: Convert assets to the archive format used by LUS.
- Archive Formats:
- O2R (
.o2r): ZIP-based archive format, the modern default. No additional CMake options needed. - OTR (
.otr): MPQ-based archive format (legacy). Requires enablingINCLUDE_MPQ_SUPPORTin CMake. - Folder Archive: For development, assets can be loaded directly from a folder without packaging.
- O2R (
- Tools: Use Torch, an external tool designed to swap C files to path references and regenerate headers automatically. Torch is not included in this repository.
- Pros: Significantly faster workflow (e.g., enabled a Star Fox 64 mini-build in one day).
- Process: Write exporters for Torch and importers for LUS to handle the specific game's asset types.
Option B: The Simple Method
- Description: Use the raw assets without OTR/O2R conversion.
- Requirements: You must manually "massage" the assets to handle endianness (byte order) and bit-width differences between N64 and PC.
- Note: It is a myth that OTR/O2R is required immediately. You can start testing a port without it, though it may be "illegal" or messy depending on the context.
Phase 4: Audio
Audio is generally the last step. It requires significant effort to hook into LUS's audio system once the rest of the game is stable.
LUS only exposes PC audio drivers — it does not interface with N64 audio. The available audio backends are:
- SDL — cross-platform (Linux, Windows, macOS, etc.)
- CoreAudio — macOS / iOS
- WASAPI — Windows
- Null — silent backend for testing
Your port is responsible for implementing the game's audio pipeline and routing its output through one of these drivers.
Build Configuration Options
Key CMake options that porters should be aware of:
| Option | Default | Description |
|---|---|---|
GBI_UCODE |
F3DEX_GBI_2 |
Graphics microcode variant (F3DEX_GBI_2, F3DEX_GBI, F3DLP_GBI) |
INCLUDE_MPQ_SUPPORT |
OFF |
Enable OTR/MPQ archive support (via StormLib) |
NON_PORTABLE |
OFF |
Build a non-portable version |
DISABLE_DLL_LOADER |
OFF |
Disable dynamic library/script loading |
LUS_BUILD_TESTS |
OFF |
Build unit tests |
LUS Architecture
Bridge Pattern
LUS uses a "bridge" pattern to connect N64 SDK function calls to modern implementations. Bridge modules exist for audio, graphics, controllers, resources, events, scripting, console variables, crash handling, and window management. When porting, you interact with these bridges through the standard N64 SDK API — LUS routes calls to the appropriate modern backend automatically.
The bridge implementations live in src/libultraship/bridge/.
Directory Structure
Understanding the LUS codebase is helpful for debugging and contribution:
| Directory | Description |
|---|---|
src/libultraship/ |
Contains N64-specific code including the libultra reimplementation (libultra/), bridge layers to modern backends (bridge/), controller support, window management, and logging. |
src/ship/ |
Platform-agnostic code: resource/archive management, audio backends (SDL, CoreAudio, WASAPI), controller abstractions, configuration, scripting/DLL loading, security/keystore, and utility functions. |
src/fast/ |
The Fast3D Renderer. Interprets N64 display lists as commands for modern GPUs. Supports OpenGL, Direct3D 11, and Metal backends. |
include/ |
Public headers mirroring the src/ structure. The main entry point is libultraship/libultraship.h. |