Skip to main content

TITAN – Tool for Interpreting and Transforming Archival Nodes. CLI and library for Ultima 8: Pagan file formats.

Project description

titan-ultima

TITAN – Tool for Interpreting and Transforming Archival Nodes.

A Python CLI and library for working with Ultima 8: Pagan file formats. TITAN reads, converts, extracts, and reconstructs the game's proprietary archive and data formats — from sprite sheets and sound effects to full isometric world maps.

Run titan --help for a full list of commands, or titan <command> --help for per-command options.


What TITAN can do

Category Capability
Archives Read, list, extract, create, and patch Flex (.flx) archives
Shapes Decode RLE-compressed sprite frames to PNG; re-import edited PNGs
Palette Export the VGA 6-bit palette as a colour swatch
Sound Decode Sonarc-compressed audio (.raw) to WAV
Music Convert XMIDI (.xmi) to standard MIDI
Maps Render full isometric or top-down world maps from FIXED.DAT + GLOBs with engine-accurate dependency-graph depth sorting; merge live NPCs and items from save files; filter by all 16 TYPEFLAG bits (fixed, solid, sea, land, occl, bag, damaging, noisy, draw, ignore, roof, transl, editor, explode, unk46, unk47)
Type data Decode TYPEFLAG.DAT shape physics/flag metadata
Gumps Dump GUMPAGE.DAT container UI layout
Credits Decrypt XOR-encoded ECREDITS.DAT / QUOTES.DAT
Saves List and extract entries from U8 save archives

Installation

pip install titan-ultima

Requires Python 3.9+, NumPy ≥ 1.24, Pillow ≥ 10.0, Typer ≥ 0.15.


Getting started

Option A — first-time wizard (recommended)

Run the interactive setup wizard once. It auto-detects your Ultima 8 installation, handles Pentagram/ScummVM save paths, writes titan.toml, and optionally extracts the shape and glob archives for you.

titan setup

The wizard will:

  1. Search common GOG, Origin, and disc install paths for FIXED.DAT
  2. Ask you to confirm (or enter) the base path and language folder
  3. Detect %APPDATA%\Pentagram\u8-save\U8SAVE.000 and offer to use it as the live-object source
  4. Write titan.toml in your current directory
  5. Optionally run flex-extract to populate shapes/ and globs/

After setup, map commands need no path arguments at all:

titan map-render -m 5               # renders map_005_iso_classic.png
titan map-render -m 0 --no-roof     # roof tiles removed
titan map-render -m 39 --no-editor --no-ignore   # player-accurate (no eggs/markers)
titan map-render-all --maps 0 5 39 --views iso_classic iso_high

Option B — manual setup (no config file)

If you prefer to supply explicit paths on every command, TITAN works without a config file too:

# One-time: extract the shape and glob archives
titan flex-extract U8SHAPES.FLX -o shapes/
titan flex-extract GLOB.FLX     -o globs/

# Render a map
titan map-render \
  --fixed FIXED.DAT --shapes shapes/ --globs globs/ \
  --palette U8PAL.PAL --typeflag TYPEFLAG.DAT \
  --map 5 -o map_005.png

# Player-accurate render (excludes editor eggs/markers and ignored shapes)
titan map-render \
  --fixed FIXED.DAT --shapes shapes/ --globs globs/ \
  --palette U8PAL.PAL --typeflag TYPEFLAG.DAT \
  --nonfixed U8SAVE.000 --no-editor --no-ignore \
  --map 39 -o map_039.png

Other useful commands (no config needed)

# Convert XMIDI music to standard MIDI
titan flex-extract MUSIC.FLX -o music_xmi/
titan music-batch music_xmi/ -o music_midi/

# Decode Sonarc sound effects to WAV
titan flex-extract SOUND.FLX -o sound_raw/
titan sound-batch sound_raw/ -o sound_wav/

# Export all shapes to PNG
titan shape-batch shapes/ -p U8PAL.PAL -o shapes_png/

Run titan <command> --help for per-command options, or see the full CLI reference.


Configuration (titan.toml)

titan.toml stores default paths so map and other commands work without repeating long paths on every invocation. CLI flags always override config values.

File location

TITAN looks for the config in this order:

  1. ./titan.toml — current working directory (recommended)
  2. ~/.config/titan/config.toml — Linux / macOS
  3. %APPDATA%\titan\config.toml — Windows

Use titan --config /other/path.toml <command> to override.

Format

[game]
base     = "C:/ultima8"   # root of your Ultima 8 install
language = "ENGLISH"      # ENGLISH, FRENCH, GERMAN, etc.
                          # leave "" for flat mode (files directly in base/)

[paths]
# Relative paths are auto-expanded to <base>/<language>/STATIC/<name>
fixed     = "FIXED.DAT"
palette   = "U8PAL.PAL"
typeflag  = "TYPEFLAG.DAT"

# Pre-extracted directories (relative to your working directory)
shapes    = "shapes/"
globs     = "globs/"

# Live objects — relative expands to <base>/<language>/SAVEGAME/<name>
# Absolute paths (e.g. Pentagram/ScummVM) are used unchanged
nonfixed  = "U8SAVE.000"

A fully annotated template is available in titan.toml.example.

Rules:

  • language = "" enables flat mode — all files expected directly in base/; useful when you copy game files to your working directory.
  • nonfixed with an absolute path (e.g. a Pentagram save) is used as-is.
  • shapes and globs are always relative to the working directory, not the game install.

Inspecting the active config

titan config           # show all resolved paths with OK / NOT FOUND status
titan config --edit    # open titan.toml in your system editor

Library quick start

TITAN is also a Python library. Every CLI command has a corresponding module.

# Flex archives
from titan.flex import FlexArchive

archive = FlexArchive.from_file("U8SHAPES.FLX")
archive.extract_all("shapes/")

# Shapes + palette
from titan.shape import U8Shape
from titan.palette import U8Palette

pal    = U8Palette.from_file("U8PAL.PAL")
shape  = U8Shape.from_file("shapes/0001.shp")
frames = shape.to_pngs(pal)
frames[0].save("frame0.png")

# Map rendering
from titan.map import U8MapRenderer

renderer = U8MapRenderer(
    fixed_path    = "FIXED.DAT",
    shapes_dir    = "shapes/",
    globs_dir     = "globs/",
    palette_path  = "U8PAL.PAL",
    typeflag_path = "TYPEFLAG.DAT",
)
img = renderer.render_map(map_num=5, view="iso_classic")
img.save("map_005.png")

# Save archives
from titan.save import U8SaveArchive

save = U8SaveArchive.from_file("U8SAVE.000")
for name, size in save.list_entries():
    print(f"{name}  {size:,} bytes")
nonfixed_bytes = save.get_data("NONFIXED.DAT")

Supported formats

Format Module Game file(s)
Flex archive titan.flex *.FLX
Shape sprites titan.shape U8SHAPES.FLX.shp
VGA palette titan.palette U8PAL.PAL
Sonarc audio titan.sound SOUND.FLX.raw
XMIDI music titan.music MUSIC.FLX.xmi
World map (static) titan.map FIXED.DAT, GLOB.FLX
World map (dynamic) titan.map NONFIXED.DAT / U8SAVE.000
Type flags titan.typeflag TYPEFLAG.DAT
Gump layout (cli only) GUMPAGE.DAT
XOR credits titan.credits ECREDITS.DAT, QUOTES.DAT
Colour transforms titan.xformpal XFORMPAL.DAT
Save archives titan.save U8SAVE.000.005

Game files

TITAN requires the original Ultima 8: Pagan game files. If you own the game through GOG, the default install locations are:

Platform Method Default path
Windows GOG Galaxy C:\Program Files (x86)\GOG Galaxy\Games\Ultima 8
Windows GOG Offline Installer C:\GOG Games\Ultima 8
Linux GOG Galaxy / Offline ~/GOG Games/Ultima 8

titan setup auto-detects these paths and others (legacy EA/Origin disc installs, common manual redirects such as C:\ULTIMA8).

Typical GOG directory layout

<install root>\
├── ENGLISH\                ← language folder (FRENCH / GERMAN for other editions)
│   ├── STATIC\             ← core game data
│   │   ├── FIXED.DAT           world map static objects
│   │   ├── GLOB.FLX            reusable object groups  (extract → globs/)
│   │   ├── U8SHAPES.FLX        all sprites             (extract → shapes/)
│   │   ├── U8PAL.PAL           VGA colour palette
│   │   ├── TYPEFLAG.DAT        shape physics / flag metadata
│   │   ├── GUMPAGE.DAT         container gump UI layout
│   │   ├── XFORMPAL.DAT        colour-transform palette
│   │   ├── ECREDITS.DAT        encrypted credits text
│   │   ├── QUOTES.DAT          encrypted quote text
│   │   ├── U8FONTS.FLX         font shapes
│   │   ├── U8GUMPS.FLX         UI gump shapes
│   │   └── EINTRO.SKF / ENDGAME.SKF
│   ├── SOUND\              ← audio
│   │   ├── SOUND.FLX           sound effects  (extract → sound_raw/)
│   │   ├── MUSIC.FLX           music tracks   (extract → music_xmi/)
│   │   └── E*.FLX              language-specific voice/effects
│   └── USECODE\            ← game bytecode
│       └── EUSECODE.FLX
│
└── cloud_saves\            ← all GOG saves live here (not in the language folder)
    └── SAVEGAME\
        ├── SGHEADER.DAT        save slot names
        └── U8SAVE.000–005      save archives

Note: GOG does not write saves into ENGLISH\SAVEGAME\; all save files go to cloud_saves\SAVEGAME\. titan setup configures the nonfixed path accordingly.

Pentagram save locations

Platform Settings folder Save file
Windows %APPDATA%\Pentagram\ %APPDATA%\Pentagram\u8-save\U8SAVE.000
macOS ~/Library/Application Support/Pentagram/ ~/Library/Application Support/Pentagram/u8-save/U8SAVE.000

titan setup detects Pentagram saves on both Windows and macOS automatically.

Module → file reference

TITAN module Files needed Location
titan.flex Any .flx archive STATIC/ or SOUND/
titan.shape .shp files (extracted) Output of flex-extract U8SHAPES.FLX
titan.palette U8PAL.PAL STATIC/
titan.sound .raw files (extracted) Output of flex-extract SOUND.FLX
titan.music .xmi files (extracted) Output of flex-extract MUSIC.FLX
titan.map FIXED.DAT, TYPEFLAG.DAT, extracted shapes/ + globs/; U8SAVE.000 (optional) STATIC/, SAVEGAME/
titan.typeflag TYPEFLAG.DAT STATIC/
titan.credits ECREDITS.DAT, QUOTES.DAT STATIC/
titan.save U8SAVE.000.005 SAVEGAME/ or cloud_saves/SAVEGAME/

Requirements

  • Python 3.9+
  • NumPy ≥ 1.24
  • Pillow ≥ 10.0
  • Typer ≥ 0.15
  • tomli ≥ 2.0 (Python < 3.11 only — for titan.toml support)

License

MIT

Important note

Ultima (Copyright 1981–1999, Electronic Arts)

To use this fan-made tool you must own a legitimate copy of Ultima 8: Pagan. This project is not affiliated with Electronic Arts. All rights to Ultima remain with Electronic Arts.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

titan_ultima-0.4.0.tar.gz (68.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

titan_ultima-0.4.0-py3-none-any.whl (59.9 kB view details)

Uploaded Python 3

File details

Details for the file titan_ultima-0.4.0.tar.gz.

File metadata

  • Download URL: titan_ultima-0.4.0.tar.gz
  • Upload date:
  • Size: 68.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for titan_ultima-0.4.0.tar.gz
Algorithm Hash digest
SHA256 ba75dc4dea2f97f8b6faef0a84d02c1987a25f89c8a91b4945f7f96d81971365
MD5 da792673e2dcd4dafc88317c1aaab63e
BLAKE2b-256 f1ef2d4d7e4080c58af7ca727bec93e8485aa13ed8bd805058698380cb7461d1

See more details on using hashes here.

File details

Details for the file titan_ultima-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: titan_ultima-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 59.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for titan_ultima-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bb398cb6e0b23ddde5048b691d5459ad0013ff8555511d6d6839262ee25f3c97
MD5 d29c290eb71ef3078874ace9c8210445
BLAKE2b-256 d55818d5fbed21269599b38d9f3790090280c3f7cfa776e270f3691089038912

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page