Files
llamamod/docs/tools.md
T

122 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tools
Everything in this repository that you can run, what it is for and where its code and notes are.
None of the tools contain game data; they all work on your own copy of the game.
## LlamaMod (Java app)
The main product: a mod manager with a launcher and a 3D level editor, for Windows and Linux.
Java 25 + Swing, sources in [`src/main/java/com/eliasmueller/llamamod/`](../src/main/java/com/eliasmueller/llamamod/).
![The LlamaMod launcher](img/launcher.jpg)
| Part | What it does | Docs |
|---|---|---|
| launcher | first-start wizard (copies the game from CD/ISO), mod list with options, save-game editor, starts the game (Wine on Linux) | [manual: Installing](manual/02-installing.md), [manual: Mods](manual/18-mods.md), [notes/llamamod-app.md](../notes/llamamod-app.md) |
| level editor | 3D editor for new and original levels: brushes, tiles, meshes, textures, objects, waypoints, cameras, zones, lights, visibility, strat scripts, play-test, glTF export | [editor manual](manual/index.md) |
| mods | Test World, Alligator Arena, level projects, Boot to level, Intro skip, Mirror mode, Practice tools, Randomizer, Draw distance, Built-in cheats, Debug wireframe, Free camera | [manual: LlamaMod mods](manual/18-mods.md), `notes/mod-*.md` |
### Command line
```text
llamamod start the GUI
llamamod --version show the version and build id
llamamod --install <iso|folder> set up the game data
llamamod --mods list available mods and their options
llamamod --apply [id,id,...] [--opt id.key=value ...]
apply mods (none = original); options are saved
llamamod --launch [--wait] start the game
llamamod --registry show the registry values
llamamod --saves show save games
llamamod --unlock <slot 1-3> <world> <chapter> [--cursor]
llamamod --editor [project.llamalevel | t1l1m001] level editor
llamamod --editor-build <project.llamalevel> <out.wad> [--cd <dir>]
llamamod --editor-import <level.wad|t1l1m001> <project.llamalevel> [--cd <dir>]
llamamod --editor-new <project.llamalevel> [base level] [--name <name>] [--cd <dir>]
llamamod --import-level <project.llamalevel> (into the level folder, shown as a mod)
llamamod --remove-level <id|file> move a level mod's file to backups/levels/
```
Data folder: `-Dllamamod.data=<folder>` or `LLAMAMOD_DATA` (default `~/.local/share/LlamaMod`,
Windows `%LOCALAPPDATA%\LlamaMod`). Source: [`Main.java`](../src/main/java/com/eliasmueller/llamamod/Main.java).
### Debug view
The *Debug wireframe* mod
([`mods/debug/`](../src/main/java/com/eliasmueller/llamamod/mods/debug/)) adds visible geometry to
every level: collision as coloured frames (invisible walls filled red, the exit floor violet, death
planes magenta) and markers for invisible objects (start, exit, checkpoints, cameras, triggers,
zones). Gameplay is unchanged. Its Python ancestor is `tools/debugviz.py`; colour legend and
details: [notes/debugviz.md](../notes/debugviz.md).
![Debug view in Village 3](img/debug-view.jpg)
## Python kit (`tools/`)
The reverse-engineering toolkit the project started with. Python 3.8+ with `numpy` and `Pillow`
(`capstone` for `disx86.py`). All parsers rebuild the original files byte for byte.
| Tool | Purpose |
|---|---|
| [`wadtool.py`](../tools/wadtool.py) | list, extract and replace WAD chunks |
| [`geomlib.py`](../tools/geomlib.py) | library: WAD, TRAK, STPC models, MAP tile part, TEXT, collision |
| [`geom_export.py`](../tools/geom_export.py) | level → OBJ/MTL with textures and vertex colours, `--collision` (collision.obj by material), `--objects`, preview renders |
| [`geom_import.py`](../tools/geom_import.py) | OBJ → new world geometry in a copy of a level |
| [`geom_demo.py`](../tools/geom_demo.py) | example geometry for `geom_import.py` |
| [`mapchunk.py`](../tools/mapchunk.py) | MAP parser/writer |
| [`map_dump.py`](../tools/map_dump.py) | print a level's tiles, strats, lights |
| [`strats.py`](../tools/strats.py) | object types of a level: names, instance counts, code offsets, type fields |
| [`strat_table.py`](../tools/strat_table.py) | type × level table → [notes/strat_types_table.md](../notes/strat_types_table.md) |
| [`stpcwalk.py`](../tools/stpcwalk.py) | rough walk through STPC (models, animations, code) |
| [`textchunk.py`](../tools/textchunk.py), [`text_export.py`](../tools/text_export.py) | TEXT chunk; export pages to PNG and import them back |
| [`texsheet.py`](../tools/texsheet.py) | contact sheet of a level's textures with indices |
| [`levelbuild.py`](../tools/levelbuild.py) | level builder from a Python script ([guide](guide/levels-in-code.md)) |
| [`make_testlevel.py`](../tools/make_testlevel.py) | early experiment: one object per type on a floor plate |
| [`debugviz.py`](../tools/debugviz.py), [`debugviz_check.py`](../tools/debugviz_check.py) | debug-view WADs for all levels and an offline check |
| [`cor2png.py`](../tools/cor2png.py), [`png2cor.py`](../tools/png2cor.py) | loading pictures (COR) ↔ PNG |
| [`asf2wav.py`](../tools/asf2wav.py) | music (ASF) → WAV, exact decoder |
| [`disx86.py`](../tools/disx86.py) | disassemble `groove.exe` at a virtual address |
| [`vorschau/`](../tools/vorschau/) | Blender (Eevee) preview renders of a level with labels |
| [`lama-mod`](../tools/lama-mod) | shell script: CD overlay of symlinks for mods in a hand-made Wine setup (pre-LlamaMod) |
Level scripts in [`levels/`](../levels/): `testwelt.py` (the original test world),
`sprunglabor.py` (jump lab used to measure the llama), `testwelt_parkour.seq` (scripted run).
Several scripts have **hard-coded paths** to the original author's Wine setup at the top (see
[Levels from scripts](guide/levels-in-code.md#a-python-level)).
## Testing in the game
| Tool | What it does | Notes |
|---|---|---|
| [`tools/apptest.py`](../tools/apptest.py) | runs the game **through LlamaMod** in an isolated session: own data folder, Wine prefix, invisible X display (Xvfb), muted private PulseAudio; applies mods, unlocks a level, navigates the menus, presses keys, takes screenshots, detects crashes | [notes/llamamod-app.md](../notes/llamamod-app.md#testing-mods-in-game-toolsapptestpy) |
| [`tools/lamatest.py`](../tools/lamatest.py) | the older harness for a hand-made Wine setup: loads a WAD as TestLevel and runs a key sequence | [notes/testharness.md](../notes/testharness.md) |
Linux only; needs Wine, Xvfb, xdotool, ImageMagick, tesseract (German data, for reading menu
texts) and PulseAudio. `apptest.py` defaults to a session root inside the author's job folder –
set `APPTEST_ROOT`.
```bash
./gradlew fatJar
tools/apptest.py run demo --display 7 --mods arena --level 9 49 \
--seq "Up:1.5 shot:walk z shot:kick" --out /tmp/demo
```
## Reverse engineering
* `re/ghidra_scripts/DumpAll.java` – headless Ghidra script that decompiles every function of
`groove.exe` into one C file. The exe, the decompile and (currently) the script itself are
excluded from the repository (`.gitignore`). Run
`analyzeHeadless <projdir> groove -import groove.exe -scriptPath re/ghidra_scripts -postScript DumpAll.java groove_decomp.c`
(Ghidra 12.x needs JDK 25).
* Key functions: MAP loader `0x42ac50`, TRAK `0x42aac0`, STPC `0x42ab50`, strat VM `0x54d180`,
chunk dispatcher `0x558960`.
## Other folders
| Folder | Content |
|---|---|
| [`examples/`](../examples/) | `testwelt.llamalevel`: the original test world as an editor project |
| [`packaging/`](../packaging/) | icons, Windows (launch4j) and Linux packaging files |
| [`deb-build/`](../deb-build/) | older script (German) that builds a Debian package of the game itself from your ISO, with the soundtrack converted to MP3 |