Amiga Flashback


In this article I am going to talk about what it was like to program software and control hardware when developing Amiga games. Others may have done it differently. This was our very direct approach.

In 1993 André Schneider and I finished our first Amiga 500/2000 game called Timelock, a puzzle game with optional two player timeout mode. Programming was done purely using MC68000 assembler. After loading the disk’s boot block we took over control using direct hardware access and memory management for maximum performance. Efficient programming was absolutely important and we had a big table of MC68000 instruction timing (cycles) right above our monitors. Everything was programmed for maximum performance, not just core routines and we used the Amiga’s coprocessors wherever possible to unburden the CPU and parallelize data processing. OS function calls were not used at all. Hardware and software interrupts (callbacks) were all re-directed to custom functions. In fact almost everything was custom made. The only commercial software we used on the Amiga were Deluxe Paint and Debabelizer for 2D graphic design and image processing.

André did most of the game logic, graphic functions and input control handling. I programmed a custom sound player inclusive editor called "Noise System" and wrote the disk IO functions.

Sound

Amiga sound was usually based on waveform samples of original instruments that were played at different rate on 4 output channels. I had tested various hardware solutions to sample sound directly with an Amiga digitizer module, but antialiasing due to downsampling resulted in background noise that was way beyond the quality I had in mind. In the end I sampled all instruments using an AKAI S1000 studio sampler and did the downsampling on an Atari ST with proper filtering. The Atari was also used to do the notation for the soundtrack. The Amiga has a build in high frequency filter to reduce noise, but as a side effect you loose a lot of waveform spectrum and everything sounds dull. Newer Amiga models could turn off the filter using a software switch. I had to modify the hardware of my Amiga 2000 to be able to toggle high band filtering.

There were several sound players available for the Amiga like the famous Soundtracker. Instead of doing linear sequencing and sample playback I wanted to take sound design a step further by making both sample playback and note pattern programmable using a simple programming language. In the final version of the Noise System a sample program could choose the sample to play including an offset and do various things within programmable loops. I could i.e. program a simple ADSR loop to modify volume or let the pitch oszillate after some time to simulate a vibrato. The waveform playback range could be set very short (i.e. just 16 bytes) to choose a specific wavefrom segment from a sample, which may have been i.e. a sine or more complex form. By shifting the offset over time I was able to simulate synthetic sounds or make speech samples sound robotic. I had no name for this technique at that time, but this method was later known as wave-sequencing and could be found in studio samplers. Using wave-sequencing saved a lot of valuable RAM, because I was able to generate a host of sound variations from a small number of base samples.


Programmable note pattern showing an excerpt of commands available

Our game engine triggered an interrupt 50 times per second (screen refresh rate, differs depending on power supply in your country) that executed a new game engine cycle. Thus, a Noise System player’s sample program could apply changes to sample playback at a maximum of 50 hertz.



Disk IO

Doing disk IO was a little tricky, because we could not use OS functions. This meant, we had to come up with a custom disk format, control the motor that spins the disk, the stepper motor that positions the read/write head, transmit data and handle multiple drives.


Loading screen. Read/write head is synced with disk drive.

Since I had to do this all from scratch I also wanted to integrate a copy protection right from the beginning. I will come back to this later on. Writing a robust and secure IO function was my major concern, especially when writing highscore data to disk. I must admit this escalated a little bit in the end, but was fun to program. Most games simply crashed when removing the disk while loading and expected it to be in the first drive. Our disk access function first checked each disk drive attached to the Amiga for the game disk. Once found it started loading or writing data. If the disk was removed, the function started searching drives again until it found the disk anywhere else and continued disk IO.

The disk format was fairly simple, just a small data header that included the track number, checksum and some specifications about the data, followed by the actual data block. By storing the track number within the track header we were able to make sure the read/write head is at the correct track when writing data to disk. We had experienced other games that corrupted disks by writing data to the wrong track and I wanted to make sure this will not happen with our games. Amiga disks store data MFM encoded. That means the actual amount of data is doubled to apply a specific pattern required by the hardware to read data reliably. The MFM rule says there may be at most three successive "0" bits and only one "1". If four successive zero bits are used, the disk drive may miss a bit resulting in invalid data. The beginning of each track is marked by a unique 16 bit sync value.

While writing the MFM data encoder I recognized this could be combined with a simple nibble cruncher. Though we did not need to compress data it was interesting to see that all data could at least be compressed by 20% no matter if the data had already been pre-compressed.

To apply a copy protection we used long tracks. Long tracks store more data to a single track than it can usually contain. Since space on a track is physically limited we need to store bits a little denser which can only be done to a certain degree. We cannot change the speed at which the motor rotates the disk, but we can force the disk drive controller to write data a little faster. This can be achieved by overclocking the Amiga slightly. Usually, an Amiga 500/2000 runs at 7.5MHz. By clocking it to 8.0MHz you can write at least 200 bytes more per track to a disk. I built a custom hardware solution (see photo below) to switch between 7.5 and 8.0MHz. The circuit board contains a 30 and 32MHz quartz. Using the parallel port you can clock the Amiga externally. The circuit board contains a manual switch to toggle the clock rate. We also had to be able to switch the clock rate using our long track copy software, because the very first track must be written at normal speed. Luckily, you can apply voltage to a pin on the joystick connector via a software switch. Thus, we were able to control clock rate switching remotely.

To enhance the copy protection even further, we used different sync markers per track. Unfortunately, one of these markers had four successive zero bits and thus was illegal. The disk drives were tolerant enough to handle this, but the digital processing laboratory was not able to copy the data. As a result of this little mistake the publisher sent us 4000 disks and we had to create the copies of the game manually! I extended our long track software to write to four disk drives simultaneously and perform a verify pass. Using two Amigas and eight disk drives we were able to create all copies within two weeks.