Deconstructing an Illusion: fixing the classic ZX Spectrum demo

Subliminal Extacy #05

Deconstructing an Illusion

By lordcoxis

As some of our readers will surely remember, "Illusion" by X-Trade got 1st place at Enlight 1996, leaving "Vibrations" by DMS (which I actually preferred) trailing behind. I remember vividly (sort of) trying to run it on my classic Speccy, only to find out that it (basically) ran like a turd. At this time I wasn't fully versed in the ways of the Pentagon (or any ex-USSR clones for that matter) so I couldn't really fully understand what was going on. How could a demo full of slowdowns and glitches have won the compo? It was clear that something was afoot. A couple of months later, through contacts (mostly) with Raver/PHT I finally understood what the Pentagon and Scorpion could do and things became clearer. The contended (slow) RAM in the classic speccy was slowing most of the code down and that caused the slowdowns and glitches. There was even a part that specifically said that it would only run on Pentagon (so not even on other clones without slow ram).

Fast forward 25 years... For some reason that I can't recall, I decided to have a look at the code under the hood of this bad boy. Now that I think about it, it might have been to check if I could make it run on classic Speccies that have a Z80DMA interface. So I started dissecting the little bastard piece by piece (as if I didn't have anything better to do), until I finally made it run 99% identical to the Pentagon, but on the classic 128/+2/+3. At the time of the release introspec asked me about the process on Pouet, and it triggered me to write this article - but since more than 2 years have passed already, details might be a little sketchy. So bear with me while I try my best to remember most of it...

General Optimizations

  • Critical code & vars were moved to fast RAM wherever possible;
  • IM2 vectors were also relocated to avoid "snowing";
  • AY ABC/ACB stereo switch was added;
  • Automatic 128/+2 and +2A/+3 model detection;
  • Repacked everything using Mr.Spiv's ZXPac.

The Chicken and Egg Situation

It's when you reach the egg jumping on the dot field effect that you start getting the impression that you may have a shitty speccy model. The music slows down and both the egg and the dot field flicker like mad. Luckily the sync in this section is done using a simple counting loop, so it was enough to apply the "General Optimizations" and configuring new values for the loop according to each speccy model.

I've got Big Ballz

The next effect is a Big Ball (oo-er) jumping on top of a dot field scroller, and what you get is basically the same as on the previous effect - a cumbersome mix of slowdown and flickering that will (almost) make you go out and get a C64 instead. Again, the sync is done using a loop/delay and was an easy fix.

You've got Small Ballz

The effect with the whirlpool and small balls bouncing around (oh, and a crappy "Illusion" logo above, shame) almost runs well, but it slow downs in some bits. Once again, the general optimizations together with a change to the sync-loop counter was enough to fix it.

Sonic Rotozoomer

This part was not so easy to fix. A lot of code had to be juggled around from slow to fast ram, and even then I could not find a safe spot for the IM2 vector. I ended up having to place it inside the Sonic bitmap, in a place where it mostly blended in with the existing graphics, hoping it wouldn't be too noticeable (did I succeed?).

Dead or Alive, You're Coming With Me

This is the part that has the following on the scroller text: "SORRY, BUT THIS EFFECT AVAILABLE ONLY ON PENTAGON 128.". It features a textured ball with a part of the "RoboCop" game title screen, jumping on top of a full-width bouncing scroller near the bottom. Now this was the part that took me longer to fix, because even with all the usual optimizations, it still wouldn't run in one frame. I tried to shorten the width of the scroller, tried to shave 1 raster at the top and bottom of the ball, but no dice. I spent a few days analysing the code and trying to think outside the box, but it really looked like a dead-end. I was about to shelve the project when it dawned on me - the code is clearing the whole area of the ball, but it actually doesn't have to. I can just clear the necessary lines at the top when it's going down, and the reverse when it's going up. This freed up enough tacts to allow the effect to run unchanged on any classic 128 speccy.

This is the end

The final effect is a big-ass zooming scroller that also slows down when it's at the biggest zoom factors. Despite all the optimizations, it still slowed down in some parts (depending on which part of the music it was playing), so I had to reduce the maximum zoom factor just a little bit. In the end (pun intended) I think it turned out OK.

Now do it all over again

The first iteration of the fix would crash shortly after it looped - this is because I did not know that the demo would loop after the end (I had never waited long enough, shame on me). It crashed because I had moved stuff around between memory pages during the first run, not expecting them to be required again.

So after all the effects were fixed, I kinda had to redo some bits and pieces so that everything would still be in it's rightful place after the demo looped.

And that's it! Hoped you liked this article, and if you didn't feel free to blame introspec ;) You can get the Illusion fix at:

http://deadcoderssociety.net/scx/illusion.zip

Share your thoughts about the article