Kabuto: In order to pull off the demo’s range of effects, we first had to learn about the inner workings of the Mega Drive. Whenever we would come up with a new idea, we had to approach it bearing the console’s capabilities in mind.
Neoman: In the first phase of the demo’s development, we tried to realise many effects using the console’s available capabilities. We noticed that not everything that we expected was possible in real-time. To give you a bit of perspective, the Amiga has a blitter chip, which runs in parallel to the CPU. This chip allows for the easy transfer of graphical data. Although the Mega Drive has no such chip, it has other unique abilities such as a huge ROM capacity – 4MB to be precise. This allowed us to pre-calculate and store data in ROM, which would not be possible to generate in real-time. Although we weren’t always successful with what we tried to achieve, we did realise some tricks – the rotating cube effect, as seen in the final demo, for example.
Fizzer: To my knowledge previous Mega Drive games and demos that contained a 3D cube effect used an algorithm that plots each pixel into a virtual frame-buffer (using the CPU to generate tile data on the fly). While this approach can be implemented in a similar way on many systems, it’s not ideal on the Mega Drive because it’s comparatively slow. So, we discovered another way that takes advantage of the Mega Drive’s special abilities and achieved full framerate rendering.
Kabuto: To achieve the cube effect, you have to imagine a plane with zero opaque pixels in row zero, one opaque pixel in row one, two in row two and so on. By vertically hardware scrolling this plane on every new raster-line – a method to display the desired row – we can display a row of the correct number of pixels as required for each line of one side of the cube. Through the addition of horizontal hardware scrolling, you can position that row wherever you want on a horizontal axis. The next step is to implement another plane utilising the same methodology and you can achieve two rows drawn per line – two sides of the cube. Add a neat trick to create a third row in-between the initial two – since the Mega Drive has only two planes – and you have all that you need to draw every line of a cube at 60 fps, since only three faces of the cube are visible per raster-line.
Fizzer: Another of the scenes that I worked on was the long side-scrolling animated image sequence that appears towards the end of the demo, which we called ‘MegaScroll’. To construct this scene, I wrote a tool with the ability to convert an animated GIF image into a set of tiles and a ‘script’. In this way, I was able to instruct the Overdrive program on what tiles, palettes, and tile indices to load and where to put them in VRAM. I utilised the Mega Drive’s tile mirroring function as a simple in-memory compression scheme along with an LRU cache.
The multi-twister effect, seen halfway through the final demo – and to a certain extent in the beta – while it isn’t a true 3D object, makes use of a number of hardware tricks, in the vein of the rotating cube effect. Kabuto goes on to describe:
Kabuto: Much like the cube, each plane in this effect contains one pre-rendered twister image (with a single twist). Vertical hardware scrolling is used to pick arbitrary twist rotations for each raster-line, independently for each twister. This is what makes the twister ‘twist’.
By using the Mega Drive’s graphics hardware ‘priority’ feature, each 8×8 pixel block is given a priority relative to the other planes. In this way, the outer twister is made to appear both in front of and behind the inner twister as it rotates. As the twisters themselves have curved edges and don’t align to an 8×8 block grid, the pre-rendered twist images are warped so that they left-align.
Then there’s the multi-twister shadows. Each part of the twister (the outer front, inner and outer back) can shadow every other part (inner, outer back and background). The further the ‘shadowee’ is away from the ‘shadower’, the wider the shadow tone becomes. To achieve a believable shadow-look, I used a pixel checkerboard pattern – black pixel, translucent pixel, black pixel. Even though the whole twister system sounds incredibly complicated, it was all possible thanks to the aforementioned 8×8-pixel-block priority feature.
Sik: Overdrive uses a modified version of Echo, which is a sound engine originally made for my Mega Drive game Project MD. The version of Echo used in Overdrive has a lot of optimisations, especially in the PCM (sampled audio) playback area, which is why it has a higher sample rate than the original engine. We even worked on optimizations to work around DMA-heavy code sections. Although DMA usage affects PCM playback quality on the Mega Drive, it’s something that, as far as I know, has never been put into practice by any Mega Drive sound engine before. DMA is recognisable as that ‘garbling’ sound or distortion often heard in game speech samples
Oerg866: I’m one of the original Echo programmers. During the development of Overdrive, I worked to a technical capacity with the Mega Drive’s Motorola 68000 and Zilog Z80 processors, which was both fun and frustrating at the same time. The Z80 sends FM and PSG data, along with PCM samples to the Mega Drive’s sound chips. To enable this processor to access the complete 68K address space – and more specifically, the ROM, where that data is stored – bank switching is required. Unfortunately, bank switching is slow because you have to write every bit of the destination address individually. Since a lot of data needs to be accessed from varying locations, across different banks, this address writing can create a very large overhead, stealing CPU time from the playback routines.
Aside from the instrument definitions, the Echo engine reads two streams from the ROM – the samples and the note data. I did think about reducing the rate of bank switching, which Sik tried to achieve for PCM samples through the implementation of a 16-byte buffer. However, this wasn’t ideal as the data rate is so high that it has to bank switch and refill the sample buffer a few times before needing to read more note data. As such, it actually created CPU overhead instead of removing it.
I found that the most effective method was to implement a 256-byte buffer for the song data, which had a much smaller data rate and meant that a few seconds of music could be played before the buffer had to be filled again. After intense bug-fixing during this process, I’m really glad that the music playback actually worked!
Neoman: Overdrive streams PCM data, at the same time as FM and PSG playback. There’s parts in the demo that perform long DMA transfers to get data to the video processor – the problem being that when DMA is running, the Z80 processor gets blocked when it tries to access the 68K bus and can no longer read PCM data. Thanks to time compensation code made by Oerg866, we were able to get the PCM data to sync with the demo again when the Z80 resumed. The only problem with this code was that it made the music distorted, since it would skip the play position forwards and cause a crackling sound.
My task was to find a way to reduce this distortion as much as possible. It drove me crazy! I can remember a sleepless week of testing the demo on a bunch of emulators and hardware. However, when it came to testing Overdrive on the Mega Drive hardware it was much more difficult to find a balance between audio syncing and PCM quality. In the end, we found a solution by using a combination of Oerg866′s compensation code and by splitting the DMA transfers into smaller chunks. This helped enormously and significantly improved the audio quality.
Alien^PDX: Just to add to everything already mentioned here – the loader at the start of the demo, with the weightlifting robot – it has no function whatsoever. We just thought it would be cool. Oh yes, and we also discovered that the Mega Drive’s video processor was capable of recreating a pseudo Mode 7 effect, as seen in a part of the demo that we named Botty Having a Bath. Weightlifting robots and Mode 7 on the Mega Drive – you definitely can’t beat that!