13 KiB
levelbau – level modding kit for The Emperor's New Groove (PC, 2000)
German title: Ein Königreich für ein Lama. PC port by Argonaut, built on the Croc 2 engine.
This kit came out of an AI-assisted reverse-engineering project. It contains:
- Format documentation for the level files (
*.wad): geometry, collision, object placement, textures, waypoints, visibility zones, and what makes the level exit work. - Python tools that read, export and rebuild those files byte-exactly.
- A level builder (
tools/levelbuild.py). You describe a level as a short Python script (boxes, ramps, stairs, fences, trees, sea, objects) and it writes a complete, playable WAD. - An example level, "Testwelt" (
levels/testwelt.py). It goes into the hidden, empty TestLevel slot (world 9, chapter 1) and has its own geometry, a gallery with every object type on pedestals, an animal pen and a small parkour with a working exit. - A debug patch generator (
tools/debugviz.py). It makes collision visible in every level, including invisible walls, along with invisible trigger and camera objects. - An automated in-game tester (
tools/lamatest.py). On Linux it runs the game under Wine on a virtual display, loads the test level, takes screenshots and detects crashes.
Nothing from the game itself is included: no game files, no executable, no decompiled code, no built WADs. Every tool works on your own copy of the game.
Most notes in
notes/are written in German. Any AI assistant can read and translate them, and that is the recommended way to use this kit (see the last section).
Requirements
- Your own copy of the game. Development used the German CD version. Other language versions should use the same format, but this hasn't been tested.
- Python 3.8+ with
numpyandPillow. Optional:capstone(disassembler helper). - For the automated in-game tests only: Linux, Wine, Xvfb, xdotool, ImageMagick, tesseract
with German language data, and PulseAudio (
pactl). - Optional: Blender (preview renders), and Ghidra (to regenerate the decompile, see below).
The builder and the export tools are plain Python, so they should also work on Windows. The test harness is Linux/Wine-only.
Paths – adjust these
The tools were written for one Linux/Wine setup and some paths are hard-coded at the top of the scripts:
| Script | Variable | Meaning |
|---|---|---|
tools/levelbuild.py |
WADS |
folder with the original level WADs (the wads folder of the game CD) |
tools/levelbuild.py |
MODWAD |
where --install puts the built level (T1L9M001.wad) |
tools/debugviz.py |
CD_WADS |
same as WADS |
tools/lamatest.py |
PREFIX, LAMA_MOD |
Wine prefix and the overlay script |
The game reads its level data from the CD drive, in the wads folder of the CD. To mod it,
make a copy of the CD data (or an overlay of symlinks, see tools/lama-mod), point the CD
drive or CDPath at that copy, and put modified WADs into its wads folder.
Folder layout
README.md this file
notes/ format documentation and findings (German)
geometry.md TRAK/MAP geometry, collision polygons, coordinate spaces, zones, limits
objects.md MAP chunk layout, strat (object) entries, waypoints, player start, exit
strat_types_table.md every object type in every original level, with counts
textures.md TEXT chunk: texture pages, RLE16, texture table, animations
levelbau.md how to use levelbuild.py, measured player physics, exit logic
testharness.md the automated Wine/Xvfb tester
debugviz.md debug patch: colour legend, what is shown, limits
img/ screenshots and preview renders
tools/
geomlib.py core library: WAD, TRAK, STPC models, MAP geometry, TEXT, collision
geom_export.py WAD -> OBJ/MTL (+ textures, vertex colours, collision.obj, objects.obj)
geom_import.py OBJ -> new geometry inside a WAD copy
mapchunk.py MAP chunk parser/writer (byte-exact on all original levels)
strats.py, strat_table.py, stpcwalk.py, map_dump.py object types and strat code helpers
textchunk.py, text_export.py, texsheet.py textures: export/import PNG, contact sheets
levelbuild.py the level builder (see notes/levelbau.md)
debugviz.py debug patch generator (collision/trigger visualisation)
lamatest.py automated in-game test on a virtual display (Linux/Wine)
lama-mod shell script: builds a CD overlay with modded WADs (Wine setup)
vorschau/ Blender preview render scripts
disx86.py small disassembler helper for groove.exe (needs capstone)
wadtool.py minimal WAD chunk lister/extractor/replacer (used by several tools)
cor2png.py, png2cor.py loading/concept pictures (*.COR, LZ-compressed 640x480) <-> PNG
asf2wav.py music (*.ASF, 4-bit ADPCM) -> WAV
levels/
testwelt.py the example test world
testwelt_parkour.seq scripted run through the parkour (used with lamatest.py)
sprunglabor.py "jump lab": test lanes used to measure jump height/width
re/ghidra_scripts/
DumpAll.java Ghidra headless script: decompiles every function to one C file
Quick start
# export a level to OBJ (+ collision and object markers)
python3 tools/geom_export.py /path/to/cd/wads/t1l1m001.wad out_village --collision --objects
# -> level.obj/.mtl, texture pages, collision.obj, objects.obj, preview images
# build the example test world
python3 tools/levelbuild.py levels/testwelt.py testwelt.wad
python3 tools/levelbuild.py --types # object types you can place
python3 tools/levelbuild.py --textures tex.png # texture sheet with the names you can use
# build the debug patch for all levels
python3 tools/debugviz.py --help
Playing the test level
The game has a hidden world 9, TestLevel, with 49 chapter slots, but the retail game ships
no data for it. Put your built WAD into the CD's wads folder as T1L9M001.wad. Also add a
loading picture T191.COR, for example a copy of another T1xx.COR.
To reach world 9, edit a save file (king0.ksv…king2.ksv, 256 bytes):
+0x04/+0x05= map cursor (world, chapter)+0x3f/+0x40= current world/chapter+0x42/+0x43= highest unlocked world/chapter
Set them to world 9, chapter 1.
When you leave through the exit, the game unlocks the next chapter. levelbuild.py --install
therefore links chapters 2–49 to the same file, so that picking one on the map doesn't crash.
Debug patch: visible collision and invisible walls
python3 tools/debugviz.py --all debug_wads --src /path/to/cd/wads # all 33 level WADs
python3 tools/debugviz.py t1l1m001.wad t1l1m001_debug.wad # a single level
python3 tools/debugviz_check.py debug_wads /path/to/cd/wads # offline sanity check
Put the resulting WADs into the CD's wads folder in place of the originals, keeping the
same file names. On the Wine setup, lama-mod debug an|aus toggles them. The patch only
adds render geometry. Collision, objects, waypoints and zones stay byte-identical, so
gameplay is unchanged.
Legend (full version in notes/debugviz.md):
| Colour | Meaning |
|---|---|
| green / yellow-green wireframe | walkable floor / slope |
| blue | wall |
| orange | ceiling / overhang |
| red, semi-transparent fill | invisible collision: invisible walls and floors |
| magenta lines | death plane ("no floor") |
| violet fill | level exit floor (material 16) |
| other colours | special collision materials |
| Marker | Meaning |
|---|---|
| white arrow | player start |
| violet cube | exit |
| turquoise cube | checkpoint |
| cyan cube | camera |
| yellow cube | trigger / cutscene |
| orange cube | force or special zone |
| gold cube | secret zone |
| grey cube | other invisible helper object |
| pink wire box | ambience / music / fog zone |
Cubes sit on a stick, and a horizontal line shows the object's facing. Wire boxes show trigger areas.
Status: 19 of 33 levels were loaded in the game without problems. The rest (catacombs/roller coaster world 7, lab world 8, two others) passed the offline check only. Collision of moving objects (platforms, doors) is not shown.
LlamaMod and the level editor
Besides the Python kit, this repository contains LlamaMod (Java 25, Swing; src/), a
one-click mod manager for the game on Windows and Linux, and a full 3D level editor
built into it. Nothing from the game is included: the wizard installs the game from your own
CD/ISO into LlamaMod's data folder, and all mods are built from that copy.
- Mods – tick mods, click Apply/Play: debug wireframe, Test World, randomizer, fog,
mirror mode, intro skip, cheats, practice tools, free camera, boot to level … Mods may change
level files and
groove.exe(code caves); the original files are never touched. Developer notes:notes/llamamod-app.md, onenotes/mod-*.mdper mod. - Level editor (Level Editor button, or
LlamaMod --editor): create new levels from templates, brushes and the base level's tile models and objects, or edit the original levels; import OBJ/glTF meshes and PNG/JPG textures (texture manager, paint-on-faces, animations); waypoints, zones, fog, lights, visibility regions; Play (F5) builds the level and starts the game directly in it (Escape returns to the editor). - Sharing: a level is a small
.llamalevelfile with only your changes. Others import it in LlamaMod (Mods → Levels → Import level) and it is built from their own game copy; new levels appear in the hidden TestLevel world (chapters 1–49).
User guide (English): notes/editor-guide.md. In the editor: Help → Getting started
and Help → Shortcut sheet. Technical notes: notes/editor-design.md, editor-api.md,
editor-format.md, editor-render.md, editor-ui.md, editor-tools-*.md,
editor-playtest.md.
./gradlew build fatJar # tests + build/libs/llamamod-<ver>-all.jar
./gradlew packageLinux # build/dist/LlamaMod-<ver>-full-linux-x64.tar.gz (own Java runtime)
./gradlew packageWindows # build/dist/LlamaMod-<ver>-full-windows-x64.zip (LlamaMod.exe + runtime)
./gradlew packageAll # both systems, full and launcher (no editor) edition
java -jar build/libs/llamamod-*-all.jar # LlamaMod
java -jar build/libs/llamamod-*-all.jar --editor # the level editor alone
Key facts
- The world is made of tiles. TRAK holds about 100–650 small models: render triangles plus collision polygons. MAP places them on a W×H grid (96×96 in the village) with height and rotation. MAP also stores baked vertex colours and a 32-zone visibility table. There is no BSP and no single world mesh.
- Objects are "strats". These are compiled scripts in the STPC chunk. In MAP, an object's
type is simply its byte offset into STPC. A level can therefore only use the object
types its own STPC contains. The builder uses the village (
t1l1m001) as its base. - Coordinates and scale. y points up. Fixed point 20.12 for objects, 4096 = 360° for angles, and render space vs. game space have z mirrored. The llama is about 0.6 units tall, runs about 1.1 units/s, can step up at most about 0.35 and jumps about 1.3 units far with a run-up.
- The level exit (LevelDoor) is an invisible trigger. It fires only when the llama stands in its grid cell on floor with collision material 16. Its parameters are (tribe, world, chapter) of the next level.
- Texture pixels are PS1-style 15-bit BGR, RLE16-compressed, on 256×256 pages. The value 0x0000 means transparent.
The parsers rebuild every original WAD byte-for-byte, so they can be trusted as format specs.
Building on this with an AI assistant
This whole kit was made by an AI coding agent (Claude Code) working through the steps below. Any capable assistant that can run code should be able to continue.
- Give it the notes first. Ask it to read
notes/*.md(they are German; it can translate). They contain offsets, field meanings, confidence levels and pitfalls. - Regenerate the decompile for questions about game logic. Install Ghidra and a full
JDK (version 25 for Ghidra 12.x), then run
analyzeHeadless <projdir> groove -import groove.exe -scriptPath re/ghidra_scripts -postScript DumpAll.java groove_decomp.c. This writes all functions as C (about 2 MB) for the assistant to search with grep. Loader functions worth knowing: MAP0x42ac50, TRAK0x42aac0, STPC0x42ab50, strat interpreter0x54d180. - Always test in the game. Have the assistant load and screenshot every build. On
Linux,
tools/lamatest.py run <wad> <outdir>does this unattended in about 75 s. On Windows, test by hand or adapt the script. - Change one thing at a time and keep the original WADs untouched. The game crashes on inconsistent data: tiles outside the grid, a vertex-colour block that doesn't match the vertex counts, or missing chapters.
Ideas for what to try next
- Use object types from other levels. You would have to merge and relocate their STPC code and their textures.
Import custom textures– done in the level editor (texture manager, import, painting).Make a real visual editor– done: the LlamaMod level editor (see above).- Add custom music or sounds (SMPC/AMPC/SRPC are sound banks).
This is a non-commercial fan project, not affiliated with Disney or Argonaut. Please share only tools and your own content, not the game's files.
