Petri Häkkinen Profile picture
Designer & programmer of Legend of Grimrock and Druidstone. Currently working on The Fall of the Black Mage (VIC-20) and Alan Wake 2.

May 9, 42 tweets

Trying to reverse my own game, Bloodfest for the Amiga. The game was released 29(!) years ago. I've lost source code and assets a long time ago... A thread!

First things first. I downloaded the game from Aminet. Files were archived with LHA which was a very common packer on the Amiga. List of files after unarchiving:

The game was written using AMOS Professional. AMOS was a full blown IDE for making games for the Amiga, similar to Pico8 today. But instead of Lua, AMOS used a custom dialect of BASIC which could be compiled to 68k machine code using AMOS Compiler (a seperate product).

The *.abk files are AMOS Bank files. Luckily somebody has already made a tool for dumping them. But there are several unknown/nonstandard file formats used, *.im, *.lev, *.pac, *.aga and *.pal.

For context, here's a playthrough video

The game comes with a README file with this interesting piece of information. This is really useful for the task at hand!

So those *.im files must be compressed using a tool called "File Imploder 4.0". I have absolutely no recollection of ever using this tool. A google search turns up with this beauty. 90s aesthetics at its finest!

Turns out somebody has already made a tool called "ancient" for uncompressing several old formats, including Turbo Imploder. Sweet!

But there's a problem. After uncompressing the im files, the uncompressed data is not what I'm expecting. They are missing Abk file header. Focusing on samples/ which I think is the laugh sfx of the end boss confirms my suspicion...

I try to play the sound using Audacity. 8-bit raw is the sound format used by Amiga. It does not sound right at all. Hmm, let's try that on a "real" Amiga. Well, NVM, let's just use the WinUAE Amiga emulator. So I install Workbench, Bloodfest and AMOS Pro.

Rereading the README and suddenly I remember it. Bloodfest used AMCAF extension which adds the capability of loading Turbo Imploder compressed files to AMOS. Let's install it and load, unpack and play the laugh sound. Nope, still doesn't sound right!

Oh dear. That sounds a lot like some simple encryption. Like scrambling the bits with XOR. Gee, likely all data files are scrambled similarly. This explains why the uncompressed files look wrong (headers missing etc.).

I try to xor the data with different bit patterns in AMOS (bringing back memories). Some values make the laugh more garbled, some slightly clearer. Then I find 0xdf10. That's clearly better. There's still some hiss to it so most likely the decoding key is not exactly right.

I try 0xdf10 with some other data files. The other sound effects sound completely broken with it. So maybe different files used different encoding keys. Uhh... this is not going anywhere fast.

Plan B: instead of trying to reverse the data files, which seems like a lot of work, let's inspect the memory of the running game inside WinUAE. If I can find the assets from memory they must already be decypted.

Let’s search for clues from the AMOS Pro manual. It’s a hefty book with probably 500 pages (but no page numbers!).

Whoah! Inside the book I find this letter from Germany. Thank you Mr. Richard Dötterl! ❤️

The internal structure of the AMOS memory banks are explained in the book. Very nice of you Mr. (and Mrs.?) book authors Mel Croucher & Stephen Hill!

So AMOS graphics banks have "Sprites" or "Icons" string at the beginning. Let's search for those strings in Amiga's memory. Yep! That looks like a valid AMOS graphics memory bank header indeed.

Next step: dump the entire memory map to file and write an utility in Lua (my fav scripting language) for analyzing it.

Amiga has two kinds of memory. Chip Mem which the video circuitry can read and Fast Mem which is only CPU accessible. The banks I found are in Fast so there must be pointers to the actual Chip Mem gfx data somewhere in the memory bank header. And sure enough there they are.

(Addresses below 0x200000 are in Chip Mem so it's easy to notice them in mem dumps. Chip Mem addresses have the format 000x xxxx.)

After some Lua coding, decoding AMOS banks and trying to remember how the bitplanes graphics mode worked on the Amiga, I get this. First "icon" from bank 0x2831d8 and converted from bitplanes to regular pixel format used on modern devices. Palette still missing but yay! 💪

Side note: bitplanes are an interesting way to save on memory bandwidth. Every pixel on the screen is on N bitplanes (where N is between 1 and 5 usually on Amiga). The first bitplane contains the lowest bit of every pixel on the screen. The second bitplane the second bit etc.

So to draw a single pixel on the Amiga required setting a single bit in N memory locations. With N = 5 you got 2^5 = 32 unique colors on screen. Cumbersome but the advantage was that a single pixel only consumed 5 bits of memory which was a huge deal in those days.

Back to Bloodfest. The palette can be found in the Fast Mem section of the graphics bank. Meaning the same palette is shared for all images in the bank. Every palette entry is RGB with 4 bits per component, so each color in the 32 entry palette could be chosen from 4096 colors.

Here are some other interesting finds from the graphics bank at 0x2831d8. The bank contains only the HUD graphics. The health meter was clearly inspired by id Software games :)

Let's try our luck with another graphics bank at 0x283db0. The bank contains 142 images so it must be the main graphics bank. Oh dear, the palette is completely broken. I have no clue why...

In the game the crew of a spaceship were in "hypersleep" when some terrible accident happened and a gate to another dimension opened (sounds familiar?). That's why some enemies are crew members gone mad and wearing long johns.

I guess the palette is not stored for some reason with the graphics bank 😟. But we can cheat a bit and dump the contents of Amiga video registers which contains the palette among other things.

LOL. Loving the graphics. I have always been blessed with working with truly talented artists. Credits for the graphics go to Tomas Björnfot and Jari Jokivuori.

I think this pretty much covers it for graphics. But it would be cool to get the sfxs too... Let's try the same trick of searching the sample bank using the string "Samples"... 2 possible sample banks found.

On closer inspection though they are not AMOS sample banks. 🤔Probably just some strings written to memory by Amiga OS when I was tinkering with the CLI. Major bummer!

This is going to be more involved. Sample banks cannot be found just by searching a string (maybe they could if I knew the right name?). But banks are stored in a linked list. Every bank has a pointer to the next bank. So maybe I can follow the links from gfx banks I found?

But that works only if the sample bank comes after a graphics bank in the linked list. 50-50% chances... Another thought: AMOS Pro manual says that "Work" and "Data" are possible bank names. Curiously there are five "Work" banks in Chip Mem (used for gfx and also *sfx*).

Three of the "Work" banks are for fonts. That leaves banks 62c18 and ed198.

The bank at ed198 has at least a convenient size of 118720 bytes. Let's dump it to disk and load it as 8-bit PCM to Audacity... 💪

This was a fun challenge and brought back so many memories. Amiga was a really fun machine to work with (with all its warts!) and with it I learned how to code and and make games. What's next? Bloodfest Remastered in 2025 to celebrate its 30th birthday!? 🤣

If you got this far... Thanks for following and have a great summer!

@Raxor1Robin Also, I just remembered I was working on Bloodfest 2 for the Amiga which had a raycast engine similar to Wolfenstein. But I never got farther than a tech demo.

@CDumancic Amos had the advantage that it could interpret the code while developing. Only at the final stage you compiled it down to machine code. So compilation step didn’t slow you down when programming.

@olli_pelz Were you in the army or out of town in 95?

Share this Scrolly Tale with your friends.

A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.

Keep scrolling