Prev: E2FA Up: Map Next: E3CC
E336: Handle creature/graphic animation
Used by the routines at C837 and E929.
For animated creatures and items, e.g. servant spell cursor, animated sabre.
Some will need left/right facing direction determined (e.g. goblin warrior), others won't (e.g. demon)
This routine advances the animation frame to the next one, or resets it to frame 1, as long as the creature/item isn't affected by an active FREEZE spell.
E336 LD A,($EAAA) Incrementing timer byte
E339 AND $01 Check bit 1
E33B JP Z,$E3CB Skip animation routine (straight to RET) every other frame, so that animation rate isn't too fast
E33E LD A,($EB43)
E341 CP $03 Is it a creature?
E343 JR NZ,$E353 If not, animation shouldn't be affected by FREEZE spell so can skip the check for this
It's a creature, so it'll need animating. Check if creature is affected by FREEZE spell:
E345 LD A,($EB4E) Creature properties byte
E348 AND $E0 If any of the top 3 bits are set, it means the creature is disintegrating/materialising - this animation isn't be affected by the FREEZE spell (the animation should continue)
E34A JR NZ,$E353 If any of the 3 bits are set, skip the following FREEZE spell check
If the FREEZE spell is active, creatures do not move:
E34C LD A,($EC9C) Get FREEZE spell timer counter
E34F CP $00
E351 JR NZ,$E3CB If it's > 0 the FREEZE spell is active, so skip this routine and go straight to RET
Check if the creature has a left/right facing version of the graphic that needs calculating:
E353 LD A,($EB4F) Get pre-graphics data byte (Graphic properties)
E356 LD B,A Temp store in B register
E357 AND $40 Bit 6 (64), if set, indicates that this creature has left/right facing graphics (e.g. goblins, guardian of chaos, and wraith)
E359 JR Z,$E394 Jump if NOT set (i.e. not any of the above) - creature isn't left/right facing, e.g. the demon)
Figure out whether we need a left or right facing graphic for this item/creature.
Bit 3 (8) of the byte at EB50 indicates whether the creature is facing right (1 - set) or left (0 - not set)
E35B LD A,($EB50) Get graphic address frame number offset
E35E LD D,A Temp store in D
E35F AND $08 Get bit 3
E361 LD C,A C now contains either 8 (right) or 0 (left) depending on whether bit 3 was set
E362 LD A,($EB4C) Movement speed/direction
E365 CP $00 Stationary?
E367 JR Z,$E394 If so, don't need to calculate anything - skip to the end
E369 CP $80 Negative value = move left.
E36B JR NC,$E37E
Creature needs to move right - check if it is already moving/facing in this direction
E36D LD A,C Retrieve byte from C register - if bit 3 (8) of EB50 was set, C will contain 8, otherwise 0.
E36E CP $08 If the byte is 8 it means the creature is already moving right
E370 JR Z,$E394 If so, no need to change which way the creature is facing
Creature is moving left but needs to switch to right. Calculate the graphics pointer offset to the opposite facing graphics frame.
E372 LD A,B Retrieve pre-graphics data byte
E373 AND $07 Lowest 3 bits = number of frames
E375 ADD A,A Multiply by 2 as we're dealing with 2 byte graphic address pointers
E376 LD E,A Store offset in E register
E377 LD A,D Get graphic address frame number offset
E378 OR $08 Set bit 4 to indicate the creature is now moving right - for storing at EB50 at E38F
E37A LD D,$00 Set high byte (D register) to 0. The offset, now in DE, will be added to the graphics address pointer later.
E37C JR $E38F
Creature needs to move left - check if it is already moving/facing in this direction
E37E LD A,C Retrieve byte from C register - if bit 3 (8) of EB50 was set, C will contain 8, otherwise 0.
E37F CP $00 If the byte is 0 it means the creature is already moving left
E381 JR Z,$E394 If so, no need to change which way the creature is facing
Creature is moving right but needs to switch to left. Calculate the graphics pointer offset to the opposite facing graphics frame. This needs to be negative as the address pointer needs to move back up the table at 97C3.
E383 LD A,B Retrieve pre-graphics data byte
E384 AND $07 Lowest 3 bits = number of frames
E386 ADD A,A Multiply by 2 as we're dealing with 2 byte graphic address pointers
E387 NEG Make negative so when added later, the offset will effectively be subtracted to get to an earlier address pointer
E389 LD E,A Store offset in E register
E38A LD A,D Get graphic address frame number offset
E38B AND $F7 Reset bit 4 to indicate the creature is now moving left - for storing at EB50 at E38F
E38D LD D,$FF Set high byte (D register) to 255. The negative offset, now in DE, will be added to the graphics address pointer later.
Creature direction and graphic address calculated
E38F LD ($EB50),A Re-store the graphic address frame number offset, with bit 3 set/unset to indicate right/left facing respectively
E392 JR $E3BC As we've just switched direction, we're already changing the graphic frame, so there's no need to change the animation frame again till next time round - so skip the next few sections.
ANIMATE THE CREATURE/GRAPHIC
Advance the animation frame to the next one, or if it's reached the total number of animation frames, reset it to frame 1:
E394 LD A,B Retrieve pre-graphics data byte
E395 AND $80 Bit 7 indicates the graphic has animation frames
E397 JR Z,$E3CB If NOT set (not animated), jump to straight to RET
Calculate graphics animation frame:
E399 LD A,B Retrieve pre-graphics data byte
E39A AND $07 Get number of frames for this sprite
E39C LD B,A ...and store in B register
E39D LD A,($EB50) Get graphic frame number offset for this graphic
E3A0 LD C,A Temp store in C register
E3A1 AND $07 Keep bits 0-2 to get the sprite's current frame number
E3A3 LD H,A Temp store in H register
E3A4 LD DE,$0000 DE will be the calculated offset value to re-calculate the graphics frame address pointer shortly
E3A7 CP B Is the graphic's current frame number <= the total frames for this sprite?
E3A8 JR C,$E3B5 If so, skip next few instructions, OK to advance to the next frame so jump out here
Frame number has passed total frames for this graphic so we need to reset its frame number:
E3AA LD A,C Retrieve current frame number
E3AB AND $F8 Reset frame number to 0 (stored in bits 0,1,2 so set these to zero)
E3AD LD C,A ...And store in C register
Next, return the sprite graphics address pointer to the address for the first frame.
This is done by getting the total number of frames for the graphic, multiplying by 2, and subtracting it from the current frame address.
E3AE LD A,H Retrieve the earlier (final) frame number
E3AF ADD A,A Double it (as address pointers are 2 bytes)
E3B0 NEG This value will be added later, so NEG here will mean it gets subtracted
E3B2 LD E,A Store in E, and set D to 255 to effectively create a 2 byte negative offset
E3B3 LD D,$FF
Recalculate new sprite graphics address pointer for the next frame:
E3B5 LD A,C Retrieve the sprite's frame number...
E3B6 INC A ...Increment...
E3B7 LD ($EB50),A ...and re-store.
E3BA INC DE Increment the offset by 2 (to move to the next graphics frame address)
E3BB INC DE
Recalculate and re-store sprite frame graphic pointer:
E3BC LD HL,($EB51) Get the sprite frame graphic pointer
E3BF ADD HL,DE Add the offset - either adding two bytes to get to the next frame, or adding the negative offset to return to the first frame
E3C0 LD ($EB51),HL ...and re-store
E3C3 LD A,($EB4E) Item (creature) properties byte
E3C6 OR $04 Ensure bit 2 (4) is set - indicates graphic (i.e. the old frame) will need erasing before the new one is drawn
E3C8 LD ($EB4E),A ...and re-store
E3CB RET
Prev: E2FA Up: Map Next: E3CC