# 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 `numpy` and `Pillow`. 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 ```bash # 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 ```bash 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`, one `notes/mod-*.md` per 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 `.llamalevel` file 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`. ```bash ./gradlew build fatJar # tests + build/libs/llamamod--all.jar ./gradlew packageLinux # build/dist/LlamaMod--full-linux-x64.tar.gz (own Java runtime) ./gradlew packageWindows # build/dist/LlamaMod--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 ``` ![The level editor](notes/img/editor/ui_select_move.jpg) --- ## 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. 1. **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. 2. **Regenerate the decompile** for questions about game logic. Install Ghidra and a full JDK (version 25 for Ghidra 12.x), then run `analyzeHeadless 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: MAP `0x42ac50`, TRAK `0x42aac0`, STPC `0x42ab50`, strat interpreter `0x54d180`. 3. **Always test in the game.** Have the assistant load and screenshot every build. On Linux, `tools/lamatest.py run ` does this unattended in about 75 s. On Windows, test by hand or adapt the script. 4. **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.