MindBomb Demo - The 3D Megaballs Screen


This demo was written by The Lost Boys for their MindBomb Demo on the Atari ST. It is amazing because the sprites move very quickly and scale very smoothly. There is a cool starfield, 32 pixel high scroller and the music is a conversion of the Hybris Theme Tune by Chrispy Noodle. The sprites follow a precalculated path and there are sprite masks for shadows. Not bad for a computer running at 8MHz with 512k RAM.

The Lost Boys (Manikin) licensed the source code to some MindBomb demo screens to Budgie UK. You could buy them for £10 each and I bought the source code for The Main Menu and The Digi-Synth Demo, but they didn't release the source code to this one! I felt a bit cheated. I was unable to try to fix the flickering rasters or learn how to do the smooth zooming 3D sprites.

DirectX Conversion

I have wanted to rewrite this demo using DirectX in Windows for years, but there are a few problems:

1. The waveforms are unknown because the source code was never released,
2. The waveforms are precalculated before each wave is displayed, but the rasters flicker,
3. The code is written in 100% assembly so the code, trigonometry, 3D projection routines and sprite scaling are really, really complicated.

We assumed back in the day that the precalc routine uses lots of MULS and DIVS instructions and possibly move multiple (movem.w/movem.l) instructions which take over 100 clock cycles each at least. Interrupts cannot occur mid-instruction only at instruction boundaries, so the raster interrupt misses the start of the scanline causing flicker.

Codef Conversion

Fortuntely NewCore has made a conversion to the Codef Framework, which is excellent. I have examined the code and wrote some C# code to analyse the waveforms, unfortunately this is before 3D transformation. We don't get the transformed coordinates or an easy way to map the real Z coordinate to a scaled sprite value. I raised this as an issue in GitHub.

Photonstorm said: "Codef3d is just a super tiny wrapper around an ancient version of three.js (version 49 I believe). So you need to consult the three.js docs to figure this all out, although good luck, because they are famously incomplete."

I then thought I could extract the precalculated data from the ST Version and use that. That may be the approach I will take in a DirectX conversion, but nobody to my knowledge has disassembled the demo. I'd have to do that.

Getting the code

Preview version

A preview version was released without the starfield and a different font. This demo has been released on many compilation demos, but never unpacked or repacked for easy disassembly using MonST or Easy Rider. A first place to start would be to unpack this demo so it can be examined in more detail.

Multi depackers on the ST cannot depack it so I assume it was a custom packer by Manikin. I have depacked it using MonST and saved it uncompressed.

Depacking the code

1. What actually happens here is the SUPEXEC function is used to execute the depack routine in Supervisor mode.

2. Run the code and place a breakpoint after the SUPEXEC call.

3. The depack code would then relocate the code in the same way GEMDOS does it, and then JMP to start the demo. We want to save the code before it is relocated.

Before it relocates you will see a standard executable header at the address value in register A0. Save a memory block starting at that address to disk. Save that. Examine it in your favourite editor and trim it to length. The demo is just under 64kB.

Conclusion: This is actually not a good place to start as the routines might have been optimised in the MindBomb Demo version. I have kept the unpacked version incase anyone wants to disassemble it with Easy Rider or for MindBomb version comparison.

MindBomb version

This code could be examined using Steem Debug but that's rather difficult to handle. Luckily The Eagles extracted the demo using a loader tool for their Compact Disk #31 so I have used that to disassemble the demo using Easy Rider. Manikin has a nasty message in the code for hackers, but after nearly 30 years I'm doing this out of admiration for the demo!

The disassembled code is 570k long. Assembling the music into a single binary (tune.dat) and including that using incbin saves 46k of source code reducing the size to 524k which is easier to handle on a 1Mb machine (or 1Mb Steem Configuration).

Raster Flicker Fix

Leonard/Oxygene gave me the idea that executing a STOP instruction before each MULS/DIVS might be able to fix the flickery rasters, at the expensive of taking more time to precalculate each waveform. This trick is actually attributed to Ziggy Stardust and is a simple, brilliant idea.

The STOP instruction in 68000 requires a status register immediate value. The execution of instructions resumes when a trace, an interrupt, or a reset exception occurs. In this case the HBL interrupt service routine for the rasters occurs, once that completes after the RTE then the code can resume.

Using Steem Debug I could see that during wave precalculation the SR value is #$2300 so this is the value I have to use in my STOP.

There are 14 MULS and 9 DIVS instructions in the waveform calculation routines that have to be preceeded by a STOP. This increases the time to precalcuate each waveform from 2 to 3 to 8 to 10 seconds but that's OK for academic purposes. I tried exiting the demo during wave calculation to see if the main code exits and causes the wave code to freeze on a STOP but it doesn't. Phew.

Saving The Precalcuated Data

Although this could be done quite easily using Steem debugger there are problems with this approach. It simply does not store the x,y and sprite number for the sprites in a heap in memory. It doesn't even store the screen offset and exact word position for each sprite like the dots in A Globe Called Alice by Wheee The Fibble, and that data was about 170k I think. There are horrible $ffffffff magic numbers everywhere. I haven't worked it out yet, but I think that would be the easiest approach.

Code Pack

I will make the source files available for download. I include the original code as well as my flicker fixed version.

DirectX Conversion

Work In Progress...

Back to index.