Back in June Peter Jones (Hi Peter, hope you’re still reading?) asked after a machine-code version of the BASIC SCREEN$ command, to help him convert a BASIC program. At the time I briefly replied that it wasn’t the best way to do things in m/c, and now I’ll explain why, and what a better alternative is.
Firstly, lets look at what the SCREEN$ command does – it tells you the character which is on the screen at a certain position. The Spectrum uses the modified version of the ASCII character set, and can print 96 different characters from it, starting with a space character (ASCII value 32), and ending with the copyright symbol (value 127). The Spectrum also allows you to print inverted versions of all those characters – doubling the possibilities to 192. And as we know, each character is stored in 8 bytes – one for each row.
What that means is that the SCREEN$ command has to find the location in screen memory which you want to check, and then work through every possible character which can be shown, trying to match it with what it finds on the screen. As you might imagine, this can take some time. It’s also not a consistent amount of time – for example, if the character on the screen is a space (i.e. empty) the command returns very quickly, as it’s the first character it tests, but if it’s the copyright symbol that’s at the end of the range it tests, and so it’s had to work through, and discount, all the other characters in the range before it matches that. In the confines of a BASIC program, you probably wouldn’t notice the time it takes, because every instruction is slow compared to machine code, but in a game that kind of exhaustive searching isn’t at all optimal, and so is avoided when possible.
Now, we could be more efficient than the BASIC version if we know which characters we are going to print, and so reduce the range of characters which we have to check for, and we might also be able to remove testing for the inverted form of the character, again, as we know what we’re going to print, but it’s still not a very good way of doing things.
So what’s the alternative? The answer is really quite simple – what if we had a version of the screen which stored which character we wrote to it, instead of the actual graphic represented by that character? If we had that, we could just read the value directly, and it would be a fast and constant-time routine. In BASIC this would be a 2D array of 32 x 24 values – one for each character position – something like DIM c(32,24) – in machine code we’d do the same, and reserve a block of memory 768 bytes in size, and use methods similar to that of writing colours to the screen to interact with it.
So that’s a solution to the problem of SCREEN$, but the concept can be used for many other things. What we’ve done is logically split what you see on the screen from a more abstract version of what describes it, and that’s how you setup levels for a game, or a big scrolling map. In a Boulder-Dash style game, you would make an array as large as the level, and use each entry to describe what it stores – a boulder, soil, gem, wall, and so on – and use that to populate the screen, and know how to react when the player, or anything else, moves on the map.