What Does It Do?
; Transition Effect
;
; Creates a transition effect where a rectangular frame grows outwards
; from the center of the screen, the colour varies depending on the current
; phase. Once the frame fills the whole screen, it then "erases" from the
; center outwards again.
;
; This animation is also present in Phoenix, the arcade game this game is based
; on.Subroutine: Print Asterisk
First off though, this simple subroutine handles printing a normal Spectrum font asterisk.
; Print Asterisk
@label=Print_Asterisk
; Stash all the registers so nothing is overwritten.
c$68A1 PUSH AF ; {Stash AF, BC, DE and HL on the stack.
$68A2 PUSH BC ;
$68A3 PUSH DE ;
$68A4 PUSH HL ; }
; The passed frame location is in the attribute buffer, so for printing the
; asterisk - we need to convert this to a screen buffer location.
$68A5 CALL $6704 ; Call ConvertAttributeToScreenBufferAddress.
; Point to an asterisk in the ZX Spectrum font UDG data.
$68A8 LD DE,$3D50 ; DE=CHARSET+$50.
; Copy the $08 lines of the asterisk to the screen buffer.
$68AB LD B,$08 ; Set a line counter in B ($08 lines in a UDG).
@label=Print_Asterisk_Loop
*$68AD LD A,(DE) ; {Copy the UDG data to the screen buffer.
$68AE LD (HL),A ; }
$68AF INC H ; Move down one pixel line in the screen buffer.
$68B0 INC DE ; Move to the next UDG graphic data byte.
$68B1 DJNZ $68AD ; Decrease the line counter by one and loop back to Print_Asterisk_Loop
; until all $08 lines of the UDG character have been drawn.
; Restore all the registers from the entry and return.
$68B3 POP HL ; {Restore HL, DE, BC and AF from the
$68B4 POP DE ; stack.
$68B5 POP BC ;
$68B6 POP AF ; }
$68B7 RET ; Return.Subroutine: Transition Effect
First of all, set up two animation loops - the idea is that the first loop will handle drawing the frame in colour, and the second loop draws over it in BLACK to erase it.
@label=TransitionEffect
c$68B8 LD B,$02 ; Set an iteration counter in B for $02 animations.Next, the loop body itself which initially sets up which attribute colour value to use - based on the current phase.
@label=TransitionEffect_Loop
*$68BA PUSH BC ; Stash the iteration counter on the stack.
$68BB LD DE,$0109 ; Set DE to initial frame dimensions (width=$09, height=$01).
$68BE LD HL,$596B ; HL=$596B (the starting attribute buffer location).
; Determine the attribute color for this iteration.
$68C1 LD A,B ; {Check if this is iteration $01?
$68C2 CP $01 ; }
; The second time this loops around, the rectangular frame "erases"
; itself (which is just achieved by doing the same thing again but in BLACK).
$68C4 LD A,$00 ; Set the iteration colour to: BLACK.
$68C6 JR Z,$68D3 ; Jump to TransitionEffect_DrawFrame if this is iteration $01.
; Else, this is the first loop - so set the INK based on the current
; phase.
$68C8 LD A,($66F1) ; {Set the iteration colour to: *Phase+$03.
$68CB ADD A,$03 ; }
$68CD CP $07 ; {Jump to TransitionEffect_DrawFrame unless the colour is WHITE (for phase $04).
$68CF JR NZ,$68D3 ; }
; Phase $04 uses INK:MAGENTA, PAPER:BLACK (BRIGHT) instead of WHITE.
$68D1 LD A,$43 ; Set the iteration colour to: INK:MAGENTA, PAPER:BLACK (BRIGHT).Now we know what colour the frame will be, begin to draw it.
; There are $0C frames to fill the whole screen.
@label=TransitionEffect_DrawFrame
*$68D3 LD B,$0C ; Set a counter in B for $0C frames.
@label=TransitionEffect_FrameLoop
*$68D5 PUSH BC ; Stash the frame counter on the stack.Starting with the top edge of the frame.
$68D6 LD B,E ; Set the horizontal counter from E (frame width).
; Draw the top edge of the frame (left to right).
@label=TransitionEffect_TopEdge
*$68D7 LD (HL),A ; Write the attribute byte to the attribute buffer.
$68D8 CALL $68A1 ; Call Print_Asterisk.
$68DB INC HL ; Move the attribute address pointer right one block.
$68DC DJNZ $68D7 ; Decrease the horizontal counter by one and loop back to TransitionEffect_TopEdge
; until the top edge of the frame has been drawn.And the right edge of the frame.
$68DE LD B,D ; Set the vertical counter from D (frame height).
; Draw the right edge of the frame (top to bottom).
@label=TransitionEffect_RightEdge
*$68DF PUSH BC ; Stash the vertical counter on the stack.
$68E0 LD (HL),A ; Write the attribute byte to the attribute buffer.
$68E1 CALL $68A1 ; Call Print_Asterisk.
$68E4 LD BC,$0020 ; {Move down one row (add $0020 to the
$68E7 ADD HL,BC ; attribute address).}
$68E8 POP BC ; Restore the vertical counter from the stack.
$68E9 DJNZ $68DF ; Decrease the vertical counter by one and loop back to TransitionEffect_RightEdge until
; the right edge of the frame has been drawn.Now the bottom edge of the frame.
$68EB LD B,E ; Set the horizontal counter from E (frame width).
; Draw the bottom edge of the frame (right to left).
@label=TransitionEffect_BottomEdge
*$68EC LD (HL),A ; Write the attribute byte to the attribute buffer.
$68ED CALL $68A1 ; Call Print_Asterisk.
$68F0 DEC HL ; Move the attribute address pointer left one block.
$68F1 DJNZ $68EC ; Decrease the horizontal counter by one and loop back to TransitionEffect_BottomEdge
; until the bottom edge of the frame has been drawn.And finally, the left edge of the frame.
$68F3 LD B,D ; Set the vertical counter from D (frame height).
; Draw the left edge of the frame (bottom to top).
@label=TransitionEffect_LeftEdge
*$68F4 PUSH BC ; Stash the vertical counter on the stack.
$68F5 LD (HL),A ; Write the attribute byte to the attribute buffer.
$68F6 CALL $68A1 ; Call Print_Asterisk.
$68F9 LD BC,$0020 ; {Move up one row (subtract $0020 from the attribute
$68FC AND A ; address).
$68FD SBC HL,BC ; }
$68FF POP BC ; Restore the vertical counter from the stack.
$6900 DJNZ $68F4 ; Decrease the vertical counter by one and loop back to TransitionEffect_LeftEdge until
; the left edge of the frame has been drawn.The first frame has now been drawn on the screen! The next frames use the same code as above (we’ll loop round), but are one asterisk bigger all round the frame (so increasing by two on the width and two on the height).
; Move outward to the next frame.
$6902 LD C,$21 ; {Move up one row and left one block (subtract $0021 from
$6904 SBC HL,BC ; the attribute address).}
; Increase the frame dimensions.
$6906 INC E ; {Increment frame width by two.
$6907 INC E ; }
$6908 INC D ; {Increment the frame height by two.
$6909 INC D ; }Add a small delay, so the player can actually observe the animation.
; Action a delay between the frames.
$690A PUSH AF ; Stash the attribute byte on the stack.
$690B LD BC,$000A ; Set a frame delay counter in BC to $0100*$0A
; loops.
@label=TransitionEffect_FrameDelay
*$690E DJNZ $690E ; Decrease the inner loop counter by one and loop back to
; TransitionEffect_FrameDelay until the inner loop counter is zero.
$6910 DEC C ; Decrease the outer loop counter by one.
$6911 JR NZ,$690E ; Jump back to TransitionEffect_FrameDelay until the outer
; loop counter is zero.Loop back to draw the next frame moving outwards.
; Process the next frame loop (or pass through when it's completed).
$6913 POP AF ; {Restore the attribute byte and frame counter from the
$6914 POP BC ; stack.}
$6915 DJNZ $68D5 ; Decrease the frame counter by one and loop back to
; TransitionEffect_FrameLoop until the counter is zero.Add another small delay so the visual effect doesn’t disappear too quickly.
; Action a delay between the iterations.
$6917 LD BC,$0032 ; Set an iteration delay counter in BC to $0100*$32
; loops.
@label=TransitionEffect_DelayLoop
*$691A DJNZ $691A ; Decrease the inner loop counter by one and loop back to
; TransitionEffect_DelayLoop until the inner loop counter is zero.
$691C DEC C ; Decrease the outer loop counter by one.
$691D JR NZ,$691A ; Jump back to TransitionEffect_DelayLoop until the outer
; loop counter is zero.At this point, the entire screen is filled with asterisks, so loop back to begin the next iteration to erase it.
; Process the next iteration animation (or pass through and end).
$691F POP BC ; Restore the iteration counter from the stack.
$6920 DJNZ $68BA ; Decrease the iteration counter by one and loop back to
; TransitionEffect_Loop until the animation is complete.All done! One last thing to do; clear the screen and return to the calling function.
; All done, clear the screen and return.
$6922 CALL $6720 ; Call ClearScreen.
$6925 RET ; Return.The Effect In Action!
