Could've been in contention...


Ah, the joys of hardware revisions...

Without a doubt, if there wasn't a 128K version of the Spectrum then I would no longer be writing this game.  I had great hopes when I started on this dream conversion many (4!) years ago that it could run on a 48K machine just like the other great Ultimate isometric games, but as the art became more beautiful and detailed, and the room count grew, it proved impossible to fit it all in that memory.

So, over it moved to the 128K machine.  It took a while to get it to work, and it still requires a lot of juggling of exactly where each bit of code & data is stored, but it runs, and is wonderful.  However, the 128K Spectrum has a few 'quirks'...

I think I outlined this in a post a while ago, but the 128K splits it's memory between eight 16K memory pages, as the Z80 processor can only access 64K at a time.  Half of those pages are slightly limited by something called memory contention - which means they are accessed at a slightly slower and inconsistent speed whilst the screen is being drawn.  When I converted the code over for the 128K machine, I consulted the documentation, and found that it was the last four pages (4-7) which were contended, and so placed all the time-critical stuff (graphics, game code, music etc) in the first four pages (0-3) so they didn't suffer from contention.  And all seemed good.

This week however, whilst doing a bit of surfing, I read that the official documentation was actually wrong, and the 128K & +2A machine had a bug which changed the pages which suffered from contention to the odd-numbered pages - 1, 3, 5 & 7 - and so the game would actually be running slightly slower than it could be.  So I've moved everything around again to match this new layout - the speed increase isn't really noticeable, but it all helps.

Ironically, when Amstrad took to making their +2B & +3 versions of the Spectrum they also used the original documentation, and not the bugged implementation (which they didn't know about), and returned the contention to the last four pages, which means that running the game on those machines will not work well.  I'm still not sure what I'm going to do about that.  I want to be inclusive and have it running at its best on each type of the machine, so I might end up with two separate versions of the game - one for the earlier machines, and one for later ones.  The game would play the same on both, but internally the memory usage would be different.  I was also checking to see if it's possible to detect the machine being used and alter the memory usage on-the-fly, but that could prove difficult, use more memory, and potentially be un-reliable anyway, so have ditched that idea for now.

TL:DR - the game runs quicker!!

Comments

Log in with itch.io to leave a comment.

One possibility is to use a lookup table. Suppose we have 8 values (#50, #51, #52, #53, #54, #55, #56, #57) at address #6400 (our lookup table). Then you can use this "macro" whenever you need to change the page:

; A = page number we want to set

ld ($ + 4),a         ; modify the lookup address in the next opcode
ld a,(#6400)       ; pick value
out (253),a         ; set page

For Amstrad the lookup table would be different with flipped 1-3 and 4-6 entries but your code can still index pages using the same logical number taken from Sinclair.

As for detection, you could simply ask the user before loading. Alternatively you could set a page that you know is different (such as 1) and count how many loops the CPU does between two successive interrupts.

Also note that there's no contention in the "border area" so if you execute something before or after the paper is drawn, any page will do.

I’ve been considering exactly those solutions, but each comes with a downside. I’ll likely simply produce two different builds, which keeps everything fast and straightforward