Over the last couple of weeks I've taken a break from the book writing process and have been poking about with some scraps of code that have their roots way back in the late '80s.
The bits of particular interest are a fast sprite blitter, an interrupt driven sound FX generater prototyped in Skyway, and the beginnings of an isometric game engine.
I have had the occasional fiddle with the isometric game engine and sprite blitter over the years, but nothing more than a handful of hours really. This time I've been rather more productive.
As soon as I saw Knightlore, and later Head Over Heels, I wanted to write my own isometric game. Cybex was isometric in projection but didn't have the masking techniques or object interaction of Knightlore. Being fifteen years old I didn't have the experience necessary to write code that ran fast enough to do all the calculations and screen drawing necessary.
The question was, did I have the skills and experience now, twenty or so years later?
The Sprite Engine
The sprite engine was, I thought, quite neat in design. It used the stack to pull the sprite data to be rendered, with the display byte and its mask being stored as pairs so that a single POP gets both.
The code was written with an unrolled sprite row blitting loop which could handle sprites up to four columns wide. For narrower sprites the code jumped forward, reducing the number of columns rendered. Nothing new really.
Sprites were written to a workscreen and not directly to the display. This of course was slower, but necessary if static sprites such as object could sometimes appear in front of a moving sprite, and sometimes behind. The idea being that sprites would be written to the workscreen in order of depth, and then the area covered by the sprite that had moved would be blitted to the display.
The Isometric Engine
The isometric engine had been sketched out, but nothing actually coded. The basic principle was to compare dynamic sprites (those that have animated or moved) against static sprites. Where there was an overlap, the static sprites were marked for redraw. Both the dynamic sprites and the static sprites marked for redraw are then drawn to the wokscreen in reverse-depth order, calculated in the XYZ coordinate space. The rectangles occupied by the dynamic sprites in the workscreen are then copied to the display.
This approach minimises the number of sprite draws necessary to give the impression of depth with sprites being able to move around each other, at the expense of repeated sprite overlap calculation. And by performing most of the work in a workscreen held in uncontended memory, the number of writes to the contended display RAM is also minimised.
I set to work writing this, and came up with the following demo (this animated gif has a low frame rate as I could only produce a gif with 1 frame every 100ms, not 20ms as I wanted. Gimp being annoying I guess :-| )
GNU Binutil Tool-Chain
I had been doing this work using the zmac assembler, using a number of utilities I had written to perform simple linking and to generate .sna snapshot files. As I was at a stage where a serious project was likely, I ported everything over to the GNU binutils tool chain, something I was familiar with from my Linux work and ARM cross-assembly projects, and in the process discovered a few bugs with the gnu assembler and linker. I fixed the assembler and submitted a patch, and Arnold Metselaar fixed the linking issue.
Now everthing is building under binutils, I can create reusable code through relocatable libraries, and use linkmaps to define the memory layout of the build target.
All I need now is a good game idea, and I'm off!