saga20101119 - simondotm/stardot-wiki GitHub Wiki

19/11/2010: More Compression

Three days and I'm back to where I was on the 16th. Well, not quite, I've updated the compression routines which required quite a bit of a rewrite. There's also been a bit of tuning for handling messages.

First off, the compression. The ScottFree format of rooms is:

byte northexit

byte southexit

byte eastexit

byte westexit

byte upexit

byte downexit

string description

Which is generally wasteful as very few locations have all six cardinal directions open. The easiest way to compress this is a have an exit count, followed by only those exits that are open. Of course we need a way of the direction of each exit. It'd be great if we had enough spare bits to munge this into a single exit byte; but there are 6 directions (so 3 bits required) and the SAGA engine allows up to 150 rooms (8 bits), so this won't work. What we can have is an exit status byte (similar to that used by the Robico engine), which uses a bit for each direction, e.g. bit 0 = north, bit 1 = south etc. This gives us a count and the order of exits in one byte.

It does mean that we have to be a tad more complex on using the exits. Fortunately, RichTW came to my aid with the difficult bit of how to map a given exit (e.g. North) to its location.

The other compression step was on conditions, I fixed a bug in my compression code, which may have lost some conditions. Whilst doing this I notice a potential for another saving: the most common condition is 0 (push), which pushes a parameter onto a stack for the actions to use later. The parameters could be a counter (up to 8), a flag (up to 16) or a room or object (up to 150) and there are up to 20 conditions. As we only have 20 conditions, we have 3 spare bits that we can use. If we make a special condition where if the condition is 0 and the parameter is less that 127, we store this in a byte with bit 8 set. Most condition 0's I've seen are less than 127, so it will save us quite a few bytes.

One side effect of this is that it will be better to change the count of conditions/actions to be a count of bytes representing conditions/actions, so any find functions don't have to try to parse them. We also have 2 spare bits that we could use to compress other conditions similarly!

On to the big change: until now I'd been using zero terminated strings (I'm too used to C programming). The problem with this technique is that if you need to search for a message you have to touch every byte from the string start to the string end. If we change this slightly so each string is preceded by a count to the next bit of information, we have a net byte difference of 0, but our loops to locate a string are quicker and require less code! The only disadvantage to this is I had to roll back a change to the objects, which used the terminator byte to store information to make some minor shrinkages in object data. Below is the same code as used above, now simplified:

.objectloop    lda objectlocs,x

                   cmp astore

                   beq printobject

.nextobject   inx

                   cpx nitems

                   bne objectloop

                   jmp leave

.printobject   stx xstore

                   txa

                   jsr findobject

.prtobj          jsr copymessage

                   ldx #workbuffer MOD 256

                   ldy #workbuffer DIV 256

                   jsr printbuf

                   ldx xstore

                   jmp nextobject

Finally, I've moved the system messages to a table at the end of the code. As the messages change for different games, this makes it easier to allow template loads. To save code I made a second entry point in my currently existing findmessage routine, so it could just use that!

Comments

⚠️ **GitHub.com Fallback** ⚠️