Introduction
This handler is very simple, it’s a handler for “counting” between states for disappearing floors (trapdoors maybe?) The game flips between showing and hiding the floor graphic, this feature only appears in a few rooms, but they’re a lovely simple addition to the game and the code is relatively easy to follow.
Table: Room “Disappearing Floor” Data
Here’s an example of some “Disappearing Floors” room data (see Room #17 for the full list).
; Data: Room #17
; Disappearing floors:
; Instance #01.
$C04A DEFB $1A,$12 ; Coordinates: 1A/ 12.
$C04C DEFB $82 ; Width: 02 (DISAPPEARED).
$C04D DEFB $8C ; Limit for "VISIBLE" timer.
$C04E DEFB $46 ; Limit for "DISAPPEARED" timer.
$C04F DEFB $00 ; Floor change timer.
; Instance #02.
$C050 DEFB $1A,$0D ; Coordinates: 1A/ 0D.
$C052 DEFB $02 ; Width: 02 (VISIBLE).
$C053 DEFB $8C ; Limit for "VISIBLE" timer.
$C054 DEFB $46 ; Limit for "DISAPPEARED" timer.
$C055 DEFB $46 ; Floor change timer.
; Instance #03.
$C056 DEFB $1A,$08 ; Coordinates: 1A/ 08.
$C058 DEFB $02 ; Width: 02 (VISIBLE).
$C059 DEFB $8C ; Limit for "VISIBLE" timer.
$C05A DEFB $46 ; Limit for "DISAPPEARED" timer.
$C05B DEFB $00 ; Floor change timer.
; All room data is terminated using $FF.
$C05C DEFB $FF ; Terminator.
In the routine, the data is accessed using the IX register which means all the values will be accessed using offsets:
Offset | Containing |
---|---|
+$00 | Horizontal Position |
+$01 | Vertical Position |
+$02 | Width/ State* |
+$03 | Visible Max. Count |
+$04 | Disappeared Max. Count |
+$05 | Change Timer |
NOTE; *IX+$02 holds both the floor width and current “state”. It does this by utilising bit 7 for holding the current “state”:
- When bit 7 is set then the floor doesn’t show.
- When it isn’t set, the floor is present.
And bits 0-6, as they’re never higher than $80, hold the floor section length.
Routine: Disappearing Floors
The room data is of varying lengths and on room load, each section of data has its starting address stored in a number of reference pointer addresses.
; Handler: Disappearing Floors
@label=Handler_DisappearingFloors
; Fetch the address contained at $5BE6 (the data isn't stored at $5BE6 itself).
c$E581 LD IX,($5BE6) ; IX=*ReferenceDisappearingFloors.
; The body of the loop; check each instance of disappearing floor data.
@label=Handler_DisappearingFloors_Loop
; If a termination character is returned then this indicates we're finished
; checking all available disappearing floor data so then return.
*$E585 LD A,(IX+$00) ; {Return if the terminator character has been received
$E588 CP $FF ; instead of a co-ordinate ($FF).
$E58A RET Z ; }
; Bit 7 of *IX+$02 holds the floor "state".
; Is the floor currently visible?
$E58B LD A,(IX+$02) ; A=Sprite width+state (*IX+$02).
$E58E AND %10000000 ; Keep only the current "state".
$E590 JP Z,$E5C5 ; Jump to DisplayFloor if the floor should be visible.
; We didn't jump, so the floor is currently NOT visible.
; The game uses a bunch of $00 bytes at Graphics_MaskSprite to "print empty
; space" - this is how we remove sprites.
$E593 LD HL,$9F6C ; Write $9F6C (Graphics_MaskSprite) to *CHARS.
$E599 INC (IX+$05) ; Increment the floor change timer by one.
; Check the current floor change timer against the max. count for how long the
; floor should stay disappeared for.
$E59C LD A,(IX+$04) ; {Jump to PrintDisappearedFloor if the current floor
$E59F CP (IX+$05) ; change timer has not yet reached the maximum
$E5A2 JR NZ,$E5B0 ; value set in the disappeared timer count.}
; The timer for how long the floor should be "disappeared" has elapsed.
$E5A4 LD A,(IX+$02) ; A=Sprite width+state (*IX+$02).
$E5A7 AND %01111111 ; Strip off bit 7 (which is the current "state") as we
; need to unset it so the floor will display next cycle.
$E5A9 LD (IX+$02),A ; Write this value back to sprite width+state (*IX+$02).
$E5AC LD (IX+$05),$00 ; Reset the floor change timer back to $00.
; Whilst this routine could also print the floor as well, the game needs to
; update other buffers when it changes, so this version is a lot simpler.
@label=PrintDisappearedFloor
*$E5B0 LD C,(IX+$00) ; C=Horizontal position.
$E5B3 LD B,(IX+$01) ; B=Vertical position.
; Bits 0-6 of *IX+$02 hold the floor width.
$E5B6 LD A,(IX+$02) ; A=Sprite width+state (*IX+$02).
$E5B9 AND %01111111 ; Strip off bit 7 (which is the current "state") as we need the
; actual width to render the empty space where the floor should be.
$E5BB LD E,A ; E=Sprite width (A).
$E5BC LD D,$01 ; D=Sprite height (always $01).
$E5BE LD A,$20 ; A=base sprite ID ($20).
$E5C0 CALL $EA93 ; Call PrintSprite.
$E5C3 JR $E5ED ; Jump to DisappearingFloors_Next.
; The floor is currently visible so handle checking the current floor change
; timer against the max. count for how long the floor should stay visible for.
@label=DisplayFloor
*$E5C5 LD A,(IX+$03) ; Fetch the maximum visible count value.
$E5C8 INC (IX+$05) ; Increment the floor change timer by one.
$E5CB CP (IX+$05) ; {Jump to PrintVisibleFloor if the current floor change
$E5CE JR NZ,$E5DC ; timer has not yet reached the maximum value set in the
; visible timer count.}
; The timer for how long the floor should be "visible" has elapsed.
$E5D0 LD A,(IX+$02) ; A=Sprite width+state (*IX+$02).
$E5D3 OR %10000000 ; Set bit 7 (which is the current "state") so the floor
; will disappear next cycle.
$E5D5 LD (IX+$02),A ; Write this value back to sprite width+state (*IX+$02).
$E5D8 LD (IX+$05),$00 ; Reset the floor change timer back to $00.
; Display the visible floor. Note the similarity to PrintDisappearedFloor.
@label=PrintVisibleFloor
*$E5DC LD C,(IX+$00) ; C=Horizontal position.
$E5DF LD B,(IX+$01) ; B=Vertical position.
; Bits 0-6 of *IX+$02 hold the floor width.
$E5E2 LD A,(IX+$02) ; A=Sprite width+state byte.
$E5E5 AND %01111111 ; Strip off bit 7 (which is the current "state") as we
; need the actual width.
$E5E7 LD E,A ; E=Set the sprite width from above.
$E5E8 LD D,$01 ; D=Sprite height (always $01).
$E5EA CALL $E787 ; Call PrintSpriteUpdateBuffer.
; Move onto the next disappearing floor data.
@label=DisappearingFloors_Next
*$E5ED LD DE,$0006 ; {IX+=$0006.
$E5F0 ADD IX,DE ; }
$E5F2 JR $E585 ; Jump to #R$E585.