I've been slowly reverse engineering Cryo's Dune, coded by Rémi Herbulot in assembler, and the code is both brilliant and insane.
Every function (to the extent that you can call it a function in assembler) is manually tail call optimized, often to the point of just doing fallthrough by placing functions after each other.
All arguments and return values are passed in registers and flags. Sometimes I'm investigating where a pointer in the SI or DI register came from and I'll have to trace back through several function layers that just didn't touch those registers to find the place it was set. When you're looking at a function, all registers and flags are potential return values.
Everything is hardcoded, all the resource id's are fixed, extracting things from the resources files requires that you know what's where. In the file ATTACK, entries 0–52 are sprites, 53-55 are palettes, and he does math on the id's to find the previous/next one (dec/inc).
Some of the resource files are compressed, which you can tell by checksumming the 6 byte header. If the header bytes add to 0xAB and the third byte is zero, it's compressed.
In the video decoder, there are chunks for sound that start with SD, chunks for palette updates that start with PL, and chunks for frame data which are identified by them /not/ having a chunk identifer. That saves a whole 2 bytes per frame!
The globe renderer is a work of art, the room renderer constructs the game backgrounds from sprites, lines and polygons with randomly dithered coloring – although his implementation of the Bresenham line algorithm is slightly broken :). In the CD version the game has lipsync data embedded in the audio files.
I built in 8086 emulator just to help me reverse engineer this game…
madmoose•1h ago
Every function (to the extent that you can call it a function in assembler) is manually tail call optimized, often to the point of just doing fallthrough by placing functions after each other.
All arguments and return values are passed in registers and flags. Sometimes I'm investigating where a pointer in the SI or DI register came from and I'll have to trace back through several function layers that just didn't touch those registers to find the place it was set. When you're looking at a function, all registers and flags are potential return values.
Everything is hardcoded, all the resource id's are fixed, extracting things from the resources files requires that you know what's where. In the file ATTACK, entries 0–52 are sprites, 53-55 are palettes, and he does math on the id's to find the previous/next one (dec/inc).
Some of the resource files are compressed, which you can tell by checksumming the 6 byte header. If the header bytes add to 0xAB and the third byte is zero, it's compressed.
In the video decoder, there are chunks for sound that start with SD, chunks for palette updates that start with PL, and chunks for frame data which are identified by them /not/ having a chunk identifer. That saves a whole 2 bytes per frame!
The globe renderer is a work of art, the room renderer constructs the game backgrounds from sprites, lines and polygons with randomly dithered coloring – although his implementation of the Bresenham line algorithm is slightly broken :). In the CD version the game has lipsync data embedded in the audio files.
I built in 8086 emulator just to help me reverse engineer this game…