iain's development activities. May contain z80, Cocoa, or whatever.
2 January 2023
Completed the non-clipping part of the even offset code mentioned yesterday, and starting on the odd offset version, although I think it’s going to be much more complex because when I was thinking about it yesterday I forgot I don’t just have to mix the left nibble with the background colour but with whatever data is already on the screen. I could just use the conventional method for the odd offset, but that would mean every other frame was considerably slower which might cause weirdness with other logic.
Was thinking about memory vs speed tradeoffs as well: currently the zero offset code and the even offset code are pretty much identical copies but with a few values and addresses different. I could save memory by using self modifying tricks to only have one copy of the code in memory and change the various values and addresses at run time, which would make it slightly slower to run - but I’ve got 512k to play with (sort of) so I’m not sure I’m going to be too memory constrained at this point.
Which makes me wonder if I should put the map drawing code on the same page as the graphics, as it would save on a lot of page switching. Currently the screen is in memory banks A&B with all the graphics drawing code in the second 8k of bank B. The map drawing code is on page 0 and is loaded into memory bank C&D, but the graphics are on page 5, so the map drawing code executes, calls bank B to draw a tile. Bank B switches C&D to page 5 (and 6) to find the graphics and draws the tile, then brings page 0 back in to work out the next tile. So each tile drawn on screen causes 2 memory bank switches. If I was to place the map drawing code at the end of page 5 (or 6) then the jump routine in B would only need to swap the page once for the whole frame.
I can’t see me using more than 32k for graphics and graphics drawing code at this point, so it probably makes sense. And even if I did, there’s other pages to put the extra graphics on (and copy the drawing code to as well), but this is all thoughts for a later time once I get the map drawing code sorted.
1 January 2023
Back coding after a few days off for Christmas and faffing around trying to set up this dev diary (using Jekyll and a bare minimum of html/css that it needs to look “ok”). Before the break I had ported the map code to use the stack to copy the map data directly to the screen, which halved the time required to draw the screen - 75kt down from about 150kt, but it only works for the no-scroll offset case, which is one out of every eight frames. So now I need to do the other 7 frames.
There’s two cases here: the even and the odd offset. The main difference between the 0 offset case and the even offset case is that there are 33 tiles drawn per row rather than 32: the first and last tiles are clipped as they scroll on and off screen, but the rest of the 31 tiles can be drawn using the same code as the 0 case.
The complication comes in the odd offset case. Because the tile graphics get shifted 1 nibble right for the odd offsets the sprite drawing code and each byte contains two pixels, it means the drawing code needs to draw 10 pixels even though the tile graphic is only 8 pixels wide. The first and last pixel are transparent and need or’d with the background colour. Means that while we can still use the stack trick to speed up drawing, the first and last bytes will need to be special cased.
Even with the special casing though it will be much faster than the original naive implementation at the expense of only allowing a single background colour - which is ok at this stage.
Still thinking of other ways to speed things up: I should be able to detect runs of the same tile and then blast them onto the screen in long sequences of push
- 64 for an entire pixel row, then drop down to the next row and another 64 push
commands and so on. Saves having the reload the registers for every tile and move the stack pointer back to the start of the next tile.