EdwardianDuck wrote: ↑
Sun May 02, 2021 1:20 pm
I'm currently porting my own work in progress game Duck! Me?
BigEd wrote: ↑
Sun May 02, 2021 1:32 pm
I'll be interested to hear the results!
Me too! If you run into any more problems with Acorn Ozmoo on the way please do let me know.
Opportunistic and unrelated technical details
The rest of this post is just some technical wafflings I drafted ages ago (back when Ozmoo 5.x was the latest and greatest version) which I never got round to posting, so I thought I'd post them now. They're still valid - Ozmoo 6.x is like Ozmoo 5.x in this regard - and might be of geeky interest. As always, you don't need to read or understand any of this if you want to make and play games with Acorn Ozmoo.
A while back I posted about the Ozmoo virtual memory code
. Johan and Fredrik have made a small but nifty tweak to how this works in Ozmoo 5.x which I thought it would be nice to write about. I'll talk about version 3 games here, but the same idea applies to all versions.
A version 3 game can be up to 128K, so the Z-machine addresses are 17-bit values. The virtual memory code always works with 512-byte blocks which are aligned to a 512-byte boundary, so we know the low 9 bits of a virtual memory block address will always be 0:
(Click on the image to enlarge if necessary.)
As described in the earlier post, for every 512-byte block of virtual memory cache Ozmoo has a 16-bit word in the vmap array containing two pieces of information about that block:
- The Z-machine address of the data; we need this so when we want to access a particular address, we can find the corresponding cache block.
- A timestamp indicating when that block was last accessed; we use this to decide which block to discard when we need to read a new block in from disc.
There's been a small tweak to the format of each 16-bit vmap entry in Ozmoo 5.x:
In Ozmoo 4.x, the least significant bit of each vmap entry was always 0. It's natural to do this, because it's the result of shifting the Z-machine address 8 bits to the right, which is a simple byte-oriented operation.
In Ozmoo 5.x, the block address is shifted right an extra bit, giving us an extra bit of timestamp resolution (i.e. doubling the number of available timestamps).
(This, incidentally, is why PREOPT files - which are more-or-less raw dumps of the vmap array - aren't compatible between Ozmoo 4.x and Ozmoo 5.x.)
The above applies to all Z-machine versions, but there's an additional advantage for version 3 games. When we're trying to access address a, we need to do something like:
Code: Select all
high_bits_of_a = a >> 8 # or >> 9 in 5.x
for i = 0 to vmap_size-1
if (vmap[i] & address_mask) == high_bits_of_a:
return i # we found a block containing address a
That comparison in the 'if' line is a 16-bit comparison in general, but in Ozmoo 5.x with a version 3 game, the address part of each vmap entry exactly fills the low byte, with the high byte being completely filled by the timestamp. (See the dotted red line on the above diagram.) This means we don't need to perform any explicit masking in the above loop - we just look at the low byte and ignore the high byte, slightly speeding things up and saving a little bit of code.
(The diagrams used here are in my repo
. vm-address.dot creates the basic diagram and then - lacking the graphviz skills to do things the way I wanted - I manually hacked the output about in gimp to create the two diagrams themselves.)