Resource centre for ZX Spectrum games
using Manic Miner and Jet Set Willy game engines
Archive of the
Manic Miner & Jet Set Willy Yahoo! Group
messages
|
|
||
|
|
Message: 7210
Author: ian.rushforth
Date: 08/11/2018
Subject: Re: two other random points
I didn't quite recall the workings of the JSW64 Trigger code correctly in my earlier post:
> A while back I was studying John Elliott's code that implements Triggers in JSW64. It occupies a tight space > in the game engine, so in order to fit in the necessary commands, John used an optimisation which made > use of a couple of commands that involve the Stack Pointer. If I recall correctly, it involved temporarily > swapping the address held by the Stack Pointer with the value stored in the IX register pair > [via the EX (SP), IX command], then after a succession of PUSH and POP commands (to edit the definition > bytes of the guardian which is the target of the Trigger), swapping the contents of IX and the Stack Pointer > back again.
I was right that it does involve messing about with the Stack Pointer (SP), but what it does is copy the current value of SP to a pair of reserved addresses (#ECD8-#ECD9), then load the value of IX up to SP. Next it uses a series of POP commands (putting unwanted pairs of bytes repeatedly into DE, and the values which it needs to update the next guardian's definition go to BC and HL). These have the effect of moving the Stack Pointer down through the Trigger's definition in the buffer, and into the buffer definition of the next guardian in the list (the one which is to be edited by the activation of the Trigger). Then when SP has reached the appropriate address in the guardian buffer, a couple of PUSH commands prints the contents of HL and BC onto the last four bytes of the target guardian's definition. Finally, the previous value of SP (i.e. what it was just prior to execution of the Trigger code) is picked back up from addresses #ECD8-#ECD9, and normal service is resumed.
(The Trigger code also updates Byte 0 of the target guardian, and the Trigger ultimately switches itself off, but those aspects probably aren't germane here.)
I still wonder if something is going wrong with that process to cause the corruption of the guardians higher up in the guardian buffer, but exactly what remains a mystery!
For reference - Disassembly of the JSW64 'Move a Trigger' code:
org #ECDA [bank 0]: LD E, (IX+$01) LD D, (IX+$02) LD A, (DE) Pick up the Trigger's flag (such as a definition byte of another guardian e.g. a switch) OR A Has the Trigger's flag reached a value of zero?
JP NZ #91B6 If not, then proceed to move the next guardian (i.e. don't activate the Trigger yet) Otherwise it's time to activate the Trigger: LD A, (IX+$03) LD (IX+$08), A Change the 'guardian type' Byte 0 of the next guardian after the Trigger LD (#ECD8), SP Load the current value of the Stack Pointer to #ECD8-9 LD SP, IX Copy the value of the IX index to SP (note this command is undocumented in some Z80 opcode listings!) POP DE This and the subsequent updates to the DE register-pair are redundant (i.e. the values picked up by DE aren't used), but they have the effect of pointing SP at the right place (further down the buffer) POP DE
POP BC POP HL The Trigger's definition bytes 4-5 and 6-7 are now held by BC and HL respectively POP DE POP DE
POP DE JP #8DC5 John must have run out of space in-situ, so the code jumps elsewhere to finish things off. (Incidentally, this has the effect of changing the value of the Program Counter (PC) - that should be independent of SP, but I wonder if it has anything to do with the reported corruption?)
org #8DC5: POP DE The Stack Pointer now points at the start of the guardian that sits two places after the Trigger in the guardian list PUSH HL SP is now being shunted back up the guardian buffer PUSH BC The guardian immediately after the Trigger has now had its Bytes 6-7 and 4-5 updated with the values in HL and BC respectively (Bytes 4-7 therefore match Bytes 4-7 of the Trigger) LD SP, (#ECD8) Restore the previous value of Stack Pointer from the temporary storage location (#ECD8-9) LD (IX+$00), #00 Switch the Trigger off (by turning it into a Blank guardian), so its effect only occurs once JP #91B6 Proceed to move the next guardian in the list
