A save-game editor for Baldur's Gate, Icewind Dale and Planescape: Torment, original and Enhanced Editions. See the Infinitier Keeper README for the supported games and platforms, how to configure and use it, and what it can edit.
A personal project, built just for fun.
The goal is to implement pure Rust readers for all file formats used by the Infinity Engine games:
- Baldur's Gate I & II (standard and Enhanced Editions)
- Planescape: Torment (standard and Enhanced Edition)
- Icewind Dale I & II (standard and Enhanced Editions)
Requirements:
-
A recent Rust toolchain. The workspace uses
edition = "2024"andresolver = "3", andas_chunks, so Rust 1.88 or newer is required. Install via rustup and keep it onstable. -
just— (optional) a simple build tool that can be used as the task runner. Runjustwith no arguments to list available recipes. -
On Ubuntu/Debian, the audio backend (
rodio/ ALSA) needs the ALSA development headers, and the Slint UI's text stack needs the fontconfig ones:sudo apt-get install -y libasound2-dev libfontconfig1-dev
-
The UI's component library, slint-themekit, is for now a path dependency: clone it next to this repository (see the keeper README).
Common recipes:
just build # build the workspace
just test # run the test suite
just check_code # rustfmt + clippyReader covers the importer / decoder; Writer covers the exporter / encoder.
| Format | Description | Reader | Writer |
|---|---|---|---|
| 2DA | Two-dimensional array (data table) | Done | Done |
| ACM | Compressed audio | Done | Done |
| ARE | Area / location data | ||
| BAM | Bitmap animation | Done | Done |
| BCS | Compiled script | Done | Done |
| BIF | Resource archive | Done | Done |
| BIK | Bink video (mve extension) |
Done | Non needed. Use the official Bink tools |
| BMP | Bitmap image | Done | Not needed |
| CHR | Character record | ||
| CHU | UI window and control definitions | ||
| CRE | Creature | Done | Done |
| DLG | Dialogue tree | ||
| EFF | Effect | ||
| FNT | Font | Done | Not needed |
| GAM | Game save state | Done | Done |
| GLSL | GLSL shader | ||
| GUI | GUI definition | ||
| IDS | Identifier / enumeration reference | Done | Done |
| INI | Configuration | Done | Done |
| ITM | Item | Done | Done |
| KEY | Resource index | Done | Done |
| LUA | Lua script | ||
| MAZE | Maze data (IWD2) | ||
| MENU | WeiDU menu | ||
| MOS | Background mosaic image | Done | Done |
| MUS | Music playlist | ||
| MVE | Interplay MVE video | Done | Done |
| PLT | Paperdoll layered bitmap | ||
| PNG | PNG image | Done | Not needed |
| PRO | Projectile | ||
| PVRZ | PVR compressed texture | Done | Done |
| SAV | Save game archive | Done | Done |
| SQL | SQLite database | ||
| SPL | Spell | Done | Done |
| SRC | Script source | ||
| STO | Store / shop | ||
| TIS | Tileset | Done | Done |
| TLK | String table | Done | Done |
| TOH | String override header (EE) | ||
| TOT | String override table (EE) | ||
| TTF | TrueType font | Done | Not needed |
| VAR | Variables (IWD2) | ||
| VEF | Visual effect | ||
| VVC | Looping visual component | ||
| WAVC | Compressed WAV audio | Done | Done |
| WAV | Audio | Done | Not needed |
| WBM | WebM video | Done | Not needed |
| WED | Area geometry and layout | Done | Done |
| WFX | Sound effects configuration | ||
| WMAP | World map |
A significant portion of the UI code was written with AI assistance because I don't like working on UI code.
These decoders were also translated from C to Rust with AI help:
- ACM decoder — translated from markokr/libacm
- ACM encoder — translated from DLTCEP
- BIK decoder — translated from FFmpeg's
libavcodec/bink.candbinkaudio.c - MVE decoder — translated from gemrb/gemrb MVEPlayer
- MVE encoder — video encoder generated by running
avi2mve.exe(tool by Abel / TeamX, 2003-04) against a matrix of synthetic AVI inputs and analysing the per-block mode histograms of its output. The audio encoder was cross-referenced against FFmpeg'slibavcodec/interplay_dpcm.c.