https://github.com/lewster32/chaos-disassembly
Annotated dissasembly of Chaos: The Battle of Wizards (1985)
https://github.com/lewster32/chaos-disassembly
gamedev sinclair-zx-spectrum z80-assembly
Last synced: about 2 months ago
JSON representation
Annotated dissasembly of Chaos: The Battle of Wizards (1985)
- Host: GitHub
- URL: https://github.com/lewster32/chaos-disassembly
- Owner: lewster32
- License: mit
- Created: 2026-04-12T21:58:34.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2026-05-01T21:47:37.000Z (about 2 months ago)
- Last Synced: 2026-05-01T23:27:05.448Z (about 2 months ago)
- Topics: gamedev, sinclair-zx-spectrum, z80-assembly
- Language: Assembly
- Homepage: https://www.archaos.co.uk/chaos-disassembly/
- Size: 3.27 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Chaos Disassembly
An annotated disassembly of [Chaos: The Battle of Wizards](https://en.wikipedia.org/wiki/Chaos_(1985_video_game)) (Julian Gollop, 1985) for the ZX Spectrum 48K, produced with [SkoolKit 10.0](https://skoolkit.ca/).
**Browse the rendered site:** [archaos.co.uk/chaos-disassembly](https://www.archaos.co.uk/chaos-disassembly/)
The output is a browsable HTML site with labelled routines, annotated data tables, creature sprites, sound-effect previews, and cross-referenced spell and creature stats. Custom memory-map pages group the engine into thematic chunks (Spell selection and casting, Movement and combat, Computer AI).
## AI disclaimer
_The following paragraph has been written by a real person; everything else is probably AI-generated._
While this project has been supervised by a knowledgeable human (me, [Lewis Lane](https://www.rotates.org)) the immense amount of heavy lifting has been performed tirelessly by [Claude Code](https://claude.ai/). Its accuracy can therefore not be guaranteed; I don't know Z80 assembly, nor have I spoken to Julian Gollop at any length about the original game's development. Everything presented here is a mixture of research and reference materials from others who have almost certainly done things the old fashioned way, my own knowledge of the game, and a lot of LLM magic.
## Layout
```
sources/ everything the build consumes
chaos.ctl primary annotation file (this is what you edit)
chaos.ref SkoolKit config (paths, custom pages, page index)
pages.ref [Page:*] definitions for the custom HTML pages
bugs.ref [Bug:*] entries
glossary.ref [Glossary:*] entries
chaos.py ChaosHtmlWriter subclass that renders the live tables
chaos.css site stylesheet (overlays skoolkit.css + dark theme)
chaos.js sortable tables and the custom audio player
chaos.woff/.woff2 Chaos web font
chaos.z80 game snapshot (input to sna2skool)
chaos.rzx game recording (input to the trace harnesses)
chaossounds.json beeper-effect parameter table
tools/ build, generation and research scripts
gen_sounds.py beeper WAV synthesiser, run by update.sh
trace_beams.py capture beam-flight sounds via the trace harness
encode_sounds.py WAV -> Opus/OGG converter (needs ffmpeg, falls back to WAV)
gen_beams.py beam GIFs, run by update.sh
gen_favicon.py favicon.ico from the Blob sprite, run by update.sh
trace_magic_wood.py Magic Wood placement trace (research)
serve.py local dev server with browser auto-reload
*.py archived one-shot research / patch scripts
reference/ read-only reference material
chaos-manual.md, chaos-rules.md, creatures.md
chaos-mapped-utf8.ctl, chaos-guesser.ctl, chaos-guesser.skool
zxs48rom.asm, ZXS48.ROM
alignment.ts TS reference for the spell-alignment math
chaos/ generated HTML site (gitignored)
```
## Prerequisites
- Python 3.x
- [Pillow](https://pillow.readthedocs.io/) (for the favicon and beam GIFs)
- SkoolKit 10.0 - either checked out into `skoolkit-src/` or installed via pip:
```
pip install -r requirements.txt
```
- [ffmpeg](https://ffmpeg.org/) - used by `tools/encode_sounds.py` to compress the synthesised beeper WAVs into Opus/OGG (~95% smaller). The build falls back to shipping uncompressed `.wav` if ffmpeg isn't on `PATH`, so this is technically optional, but the rendered site is much lighter with it. Windows install:
```
winget install --id=Gyan.FFmpeg -e
```
(or `choco install ffmpeg` / `scoop install ffmpeg`). On macOS use `brew install ffmpeg`; on Debian/Ubuntu `sudo apt install ffmpeg`.
## Building
```
bash update.sh
```
The script runs from the project root:
1. `sna2skool` reads `sources/chaos.z80` + `sources/chaos.ctl` and writes `sources/chaos.skool`.
2. `tools/gen_sounds.py` synthesises beeper WAVs into `chaos/audio/sounds/`.
3. `tools/trace_beams.py` captures the beam-flight sounds that need the trace harness.
4. `tools/encode_sounds.py` compresses the WAVs to Opus/OGG via ffmpeg (skipped with a notice if ffmpeg is missing).
5. `tools/gen_beams.py` renders beam-animation GIFs into `chaos/images/beams/`.
6. `skool2html` renders `sources/chaos.skool` + the ref files into `chaos/`. SkoolKit's `[Game] AudioFormats` default makes it auto-prefer the `.ogg` siblings of any `#AUDIO0(...wav)` macro, so no source edits are needed when the encode step runs.
7. `tools/gen_favicon.py` writes `chaos/favicon.ico` from the Blob sprite.
Open `chaos/index.html` to browse the result, or use the dev server:
```
python tools/serve.py # http://localhost:8080
python tools/serve.py 9000 # custom port
```
The dev server auto-reloads any open browser tabs after each `update.sh` run.
## What's annotated
- **Spells** - all 65 records at `$7D60` with casting chance, range, alignment bias, sort key, and dispatch routine.
- **Creature stats** - 38-byte records for every creature and structure, with sprite UDGs and live casting-chance lookup from the spell table.
- **Sound effects** - 10-byte beeper records with embedded WAV preview and a custom audio player.
- **Beams** - the six beam types rendered by the Bresenham line routine at `$B626`, each with a per-beam GIF preview.
- **Sprites** - creature, wizard, font, and effects/UI blocks rendered as UDG arrays.
- **Custom memory maps** - `Spell selection and casting` (`$9168-$97CD`), `Movement and combat` (`$AC36-$B60A`), `Computer AI` (`$C63D-$CDD2` + `$D3F0`).
## Editing tips
- Edit `sources/chaos.ctl` only. `sources/chaos.skool` is generated and overwritten on every build.
- All addresses in `chaos.ctl` use `$XXXX` hex (uppercase).
- Stick to ASCII in `sources/*.ctl` and `sources/*.ref` - SkoolKit decodes them as ASCII. Use HTML entities (`×`, `✓`, etc) for symbols.
- See `CLAUDE.md` for the full annotation conventions.