Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/HarbourMasters/Starship/llms.txt

Use this file to discover all available pages before exploring further.

The Starship asset pipeline transforms a raw Star Fox 64 ROM into the two .o2r archives the engine loads at runtime. Understanding this pipeline is essential for contributors who need to add new asset definitions, and for modders who want to know how asset paths are structured inside the archives.

Supported ROMs

Starship only accepts US 1.0 and US 1.1 ROMs for base asset extraction. Both versions are compressed with MIO0 and must first be decompressed before extraction begins.
VersionCompressed SHA-1Decompressed SHA-1
US 1.0d8b1088520f7c5f81433292a9258c1184afa145763b69f0ef36306257481afc250f9bc304c7162b2
US 1.109f0d105f476b00efa5303a3ebc42e60a7753b7af7475fb11e7e6830f82883412638e8390791ab87
You can verify your ROM’s SHA-1 hash using the ROM Hashing Tool before attempting extraction.
JP and EU ROMs are supported only for voice audio replacement (producing sf64jp.o2r / sf64eu.o2r in mods/). They cannot be used as the base ROM for general asset extraction.

Pipeline steps

1

Provide a US ROM (.z64)

Place your verified US 1.0 or US 1.1 ROM in the project root (the same directory as CMakeLists.txt), naming it baserom.z64. The file must be in big-endian .z64 format; convert from .n64 with a byte-swapper if needed.
2

Run the ExtractAssets CMake target

The ExtractAssets target builds the Torch extractor tool and then runs it against the ROM:
cmake --build build --target ExtractAssets
Internally, CMake executes:
torch o2r baserom.z64
Torch reads config.yml to locate the asset YAML definitions, decompresses the ROM with the MIO0 method, validates the SHA-1 checksum, and then walks each YAML definition to parse and serialize every asset.
3

Asset YAML definitions are read from yamls/

YAML files under yamls/us/rev0/ (US 1.0) or yamls/us/rev1/ (US 1.1) describe every asset segment: its name, type, and byte offset inside the ROM. The top-level files (assets.yaml, main.yaml, overlays.yaml, header.yaml) compose the full asset map.Example entry pattern:
- name: ast_andross
  type: AnimData
  start: 0x1A4000
4

Torch produces sf64.o2r in the project root

After processing all YAML definitions, Torch writes sf64.o2r to the project root. The archive contains every serialized asset keyed by its internal path (e.g. sf64/assets/ast_andross). CMake then copies the file into the build directory.
5

Run the GeneratePortO2R CMake target

Port-specific assets (UI widgets, enhancement textures, etc.) live under port/ in the source tree. The GeneratePortO2R target packs them:
cmake --build build --target GeneratePortO2R
CMake runs:
torch pack port starship.o2r o2r
This produces starship.o2r in the project root and copies it to the build directory.
6

Both archives are loaded at runtime

When starship launches, GameEngine constructs a list of archive paths and hands them to libultraship’s resource manager in load order: sf64.o2r first, then starship.o2r, then every file found recursively in mods/.

config.yml structure

config.yml maps ROM SHA-1 hashes to extraction configuration. The extractor reads this file to know which YAML path to use, which microcode variant (F3DEX) to target, and where to write output files.
# US 1.1 — compressed ROM entry
09f0d105f476b00efa5303a3ebc42e60a7753b7a:
  name: Star Fox 64 (U) (V1.1) (Compressed)
  preprocess:
    decompress_mio0:
      method: mio0-comptool
      type: decompress
      target: f7475fb11e7e6830f82883412638e8390791ab87
      restart: true

# US 1.1 — decompressed ROM entry (target of the above)
f7475fb11e7e6830f82883412638e8390791ab87:
  name: Star Fox 64 (U) (V1.1)
  path: assets/yaml/us/rev1
  config:
    gbi: F3DEX
    sort: OFFSET
    logging: INFO
    output:
      binary: sf64.o2r
      code: src/assets
      headers: include/assets
      modding: src/assets
Each compressed entry has a preprocess block that decompresses the ROM and restarts the hash lookup against the decompressed target. The decompressed entry carries the real extraction config.
FieldDescription
pathDirectory containing YAML asset definitions
gbiGraphics Binary Interface variant (F3DEX)
sortAsset sort strategy (OFFSET = ROM byte order)
output.binaryOutput archive filename (sf64.o2r)
output.codeDirectory for generated C source stubs
output.headersDirectory for generated C header files

Runtime asset loading macros

The engine exposes two C macros for fetching asset data by path:
// LOAD_ASSET: falls back to the raw pointer if the path is not an archive path
#define LOAD_ASSET(path) \
    (path == NULL ? NULL : \
        (GameEngine_OTRSigCheck((const char*) path) \
            ? ResourceGetDataByName((const char*) path) \
            : path))

// LOAD_ASSET_RAW: always retrieves from the resource manager (no fallback)
#define LOAD_ASSET_RAW(path) ResourceGetDataByName((const char*) path)
GameEngine_OTRSigCheck inspects the first seven bytes of the string for the sentinel __OTR__. Archive paths injected by the resource system carry this prefix; raw file-system paths do not. This allows the same game code to work with both archived and non-archived asset sources.
When writing new game code that references assets, prefer LOAD_ASSET over direct pointer dereference. It keeps the code compatible with both archived and raw asset modes without branching logic in the caller.

Build docs developers (and LLMs) love