An annotated disassembly of Chaos: The Battle of Wizards (Julian Gollop, 1985) for the ZX Spectrum 48K, produced with SkoolKit 10.0.
Browse the rendered site: 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).
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) the immense amount of heavy lifting has been performed tirelessly by Claude Code. 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.
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)
- Python 3.x
- Pillow (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 - used by
tools/encode_sounds.pyto compress the synthesised beeper WAVs into Opus/OGG (~95% smaller). The build falls back to shipping uncompressed.wavif ffmpeg isn't onPATH, 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.
bash update.sh
The script runs from the project root:
sna2skoolreadssources/chaos.z80+sources/chaos.ctland writessources/chaos.skool.tools/gen_sounds.pysynthesises beeper WAVs intochaos/audio/sounds/.tools/trace_beams.pycaptures the beam-flight sounds that need the trace harness.tools/encode_sounds.pycompresses the WAVs to Opus/OGG via ffmpeg (skipped with a notice if ffmpeg is missing).tools/gen_beams.pyrenders beam-animation GIFs intochaos/images/beams/.skool2htmlrenderssources/chaos.skool+ the ref files intochaos/. SkoolKit's[Game] AudioFormatsdefault makes it auto-prefer the.oggsiblings of any#AUDIO0(...wav)macro, so no source edits are needed when the encode step runs.tools/gen_favicon.pywriteschaos/favicon.icofrom 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.
- Spells - all 65 records at
$7D60with 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).
- Edit
sources/chaos.ctlonly.sources/chaos.skoolis generated and overwritten on every build. - All addresses in
chaos.ctluse$XXXXhex (uppercase). - Stick to ASCII in
sources/*.ctlandsources/*.ref- SkoolKit decodes them as ASCII. Use HTML entities (×,✓, etc) for symbols. - See
CLAUDE.mdfor the full annotation conventions.