This is an assembly version of the Cat Animation. It uses direct screen plotting from RLE compressed frames of data.
;
; Fast Cat Animation in Assembly
; Steven Reid
; v1 02/08/2023 - turning basic into a fast cat animation.
; v2 02/12/2023 - code cleanup and moved delay to frame counter
; +++
;
; Header and startup
;
; start up stuff
org 16514 ; stored in REM at top (ZX81)
jr start ; needed for z80asm
; title and copyright (will show when listed)
copy:
db _as,_as,_f_,_a_,_s_,_t_,_sp,_c_,_a_,_t_,
db _as,_s_,_l_,_r_,_sl,_2_,_0_,_2_,_3_,_as
db _as,$76,$76
; variables
frame_end: db 0 ; holds ending frame value
frame_loc: dw 0 ; pointer to frame location
start:
call slow ; SLOW is required.
call cls ; clear screen / exapnd screen
; end header and startup
;
; ---
; +++
;
; Main Program
;
; print floor
ld hl,(d_file)
ld de,14*33+1
add hl,de
ld b,32
ld a,$0a
floor_loop:
ld (hl),a
inc hl
djnz floor_loop
main_loop:
; load initial frame
ld hl,cat_frames
ld (frame_loc),hl
frame_loop:
; grab frame counter
ld hl,frames ; make hl point to the timecounter
ld a,(hl) ; get the timecounter in A
push af ; save current frame values
push hl ; save location (faster than reloading later)
; move to start of screen
ld de,(d_file)
inc de
ld hl,(frame_loc) ; grab frame location
line_loop:
; RLE encoded frame
ld b,(hl) ; loop size
inc hl
ld a,(hl) ; what to print
inc hl
cp $fe ; done with frame?
jp nc,frame_done
; print RLE
rle_loop:
ld (de),a
inc de
djnz rle_loop
jp line_loop
frame_done:
ld (frame_loc),hl ; save frame location
ld (frame_end),a ; save ending frame value
; now delay
pop hl ; restore frame location
pop af ; restore previous frame value
sub 5 ; number of frames to delay
wfr: cp (hl) ; test if frames match
jr nz,wfr ; nope, loop until they do
call check_break ; check if we are done?
ld a,(frame_end) ; restore frame value
cp $fe ; are there more frames?
jp z,frame_loop ; is $fe, then print next frame
jp main_loop ; is $ff, start over!
cat_frames:
; frame 1
db 32,$00,1,$76
db 32,$00,1,$76
db 32,$00,1,$76
db 22,$00,7,$80,1,$00,1,$80,1,$0,1,$76
db 11,$00,11,$80,7,$00,2,$80,1,$00,1,$76
db 8,$00,3,$80,20,$00,1,$80,1,$76
db 7,$00,1,$80,15,$00,1,$80,2,$00,3,$80,2,$00,1,$80,1,$76
db 5,$00,2,$80,16,$00,1,$80,2,$00,1,$80,2,$00,2,$80,1,$00,1,$76
db 1,$00,5,$80,8,$00,11,$80,1,$00,2,$80,4,$00,1,$76
db 1,$80,3,$00,1,$80,4,$00,5,$80,11,$00,5,$80,2,$00,1,$76
db 4,$00,5,$80,19,$00,1,$80,1,$00,1,$80,1,$00,1,$76
db 3,$00,2,$80,24,$00,1,$80,1,$00,1,$80,1,$76
db 2,$00,1,$80,1,$00,1,$80,27,$00,1,$76
db 4,$00,2,$80,26,$00,1,$fe
; frame 2
db 32,$00,1,$76
db 32,$00,1,$76
db 32,$00,1,$76
db 32,$00,1,$76
db 10,$00,7,$80,4,$00,5,$80,3,$00,1,$80,2,$00,1,$76
db 8,$00,2,$80,7,$00,4,$80,5,$00,4,$80,2,$00,1,$76
db 7,$00,1,$80,22,$00,1,$80,1,$00,1,$76
db 5,$00,2,$80,16,$00,1,$80,1,$00,3,$80,3,$00,1,$80,1,$76
db 5,$80,1,$00,1,$80,6,$00,13,$80,2,$00,3,$80,1,$00,1,$76
db 5,$00,2,$80,3,$00,3,$80,9,$00,2,$80,1,$00,3,$80,4,$00,1,$76
db 3,$00,3,$80,1,$00,3,$80,13,$00,1,$80,3,$00,3,$80,2,$00,1,$76
db 4,$00,1,$80,18,$00,1,$80,6,$00,2,$80,1,$76
db 2,$00,2,$80,19,$00,2,$80,7,$00,1,$76
db 24,$00,2,$80,6,$00,1,$fe
; frame 3
db 32,$00,1,$76
db 32,$00,1,$76
db 13,$00,5,$80,14,$00,1,$76
db 11,$00,2,$80,5,$00,2,$80,8,$00,1,$80,3,$00,1,$76
db 9,$00,2,$80,9,$00,5,$80,1,$00,4,$80,2,$00,1,$76
db 8,$00,2,$80,15,$00,1,$80,4,$00,1,$80,1,$00,1,$76
db 7,$00,1,$80,2,$00,1,$80,5,$00,1,$80,10,$00,1,$80,3,$00,1,$80,1,$76
db 6,$00,1,$80,3,$00,1,$80,4,$00,1,$80,1,$00,2,$80,7,$00,1,$80,1,$00,3,$80,1,$00,1,$76
db 1,$00,5,$80,3,$00,1,$80,4,$00,1,$80,4,$00,5,$80,1,$00,1,$80,6,$00,1,$76
db 9,$00,1,$80,1,$00,3,$80,7,$00,1,$80,1,$00,1,$80,1,$00,1,$80,6,$00,1,$76
db 10,$00,1,$80,8,$00,2,$80,3,$00,3,$80,5,$00,1,$76
db 11,$00,1,$80,7,$00,1,$80,6,$00,2,$80,4,$00,1,$76
db 10,$00,1,$80,8,$00,1,$80,8,$00,1,$80,3,$00,1,$76
db 20,$00,1,$80,8,$00,1,$80,2,$00,1,$fe
; frame 4
db 32,$00,1,$76
db 32,$00,1,$76
db 14,$00,4,$80,14,$00,1,$76
db 12,$00,2,$80,4,$00,2,$80,12,$00,1,$76
db 6,$00,6,$80,8,$00,2,$80,6,$00,1,$80,3,$00,1,$76
db 5,$00,1,$80,5,$00,1,$80,10,$00,1,$80,4,$00,2,$80,3,$00,1,$76
db 3,$00,2,$80,6,$00,1,$80,2,$00,1,$80,8,$00,4,$80,2,$00,1,$80,2,$00,1,$76
db 3,$80,9,$00,1,$80,2,$00,1,$80,3,$00,1,$80,10,$00,1,$80,1,$00,1,$76
db 13,$00,1,$80,1,$00,2,$80,1,$00,1,$80,7,$00,4,$80,2,$00,1,$76
db 14,$00,2,$80,1,$00,2,$80,1,$00,6,$80,6,$00,1,$76
db 14,$00,2,$80,1,$00,1,$80,1,$00,2,$80,11,$00,1,$76
db 15,$00,3,$80,1,$00,2,$80,11,$00,1,$76
db 16,$00,1,$80,3,$00,1,$80,11,$00,1,$76
db 20,$00,2,$80,10,$00,1,$fe
; frame 5
db 32,$00,1,$76
db 32,$00,1,$76
db 32,$00,1,$76
db 2,$00,6,$80,4,$00,5,$80,15,$00,1,$76
db 1,$00,1,$80,6,$00,4,$80,5,$00,2,$80,7,$00,1,$80,5,$00,1,$76
db 1,$00,1,$80,9,$00,1,$80,7,$00,2,$80,3,$00,3,$80,5,$00,1,$76
db 10,$00,1,$80,10,$00,3,$80,3,$00,1,$80,4,$00,1,$76
db 10,$00,1,$80,17,$00,1,$80,3,$00,1,$76
db 10,$00,1,$80,7,$00,1,$80,5,$00,4,$80,4,$00,1,$76
db 11,$00,1,$80,1,$00,8,$80,1,$00,2,$80,8,$00,1,$76
db 11,$00,2,$80,6,$00,1,$80,1,$00,1,$80,10,$00,1,$76
db 11,$00,1,$80,1,$00,1,$80,4,$00,1,$80,1,$00,1,$80,11,$00,1,$76
db 10,$00,2,$80,1,$00,1,$80,3,$00,1,$80,14,$00,1,$76
db 11,$00,2,$80,1,$00,2,$80,16,$00,1,$fe
; frame 6
db 32,$00,1,$76
db 1,$00,3,$80,28,$00,1,$76
db 4,$00,4,$80,24,$00,1,$76
db 8,$00,3,$80,3,$00,4,$80,11,$00,1,$80,2,$00,1,$76
db 11,$00,3,$80,4,$00,2,$80,7,$00,4,$80,1,$00,1,$76
db 10,$00,1,$80,9,$00,3,$80,1,$00,3,$80,4,$00,1,$80,1,$76
db 9,$00,1,$80,13,$00,1,$80,7,$00,1,$80,1,$76
db 9,$00,1,$80,17,$00,4,$80,1,$00,1,$76
db 9,$00,1,$80,4,$00,3,$80,9,$00,1,$80,5,$00,1,$76
db 8,$00,1,$80,4,$00,1,$80,3,$00,9,$80,1,$00,1,$80,4,$00,1,$76
db 7,$00,1,$80,2,$00,3,$80,12,$00,3,$80,4,$00,1,$76
db 7,$00,1,$80,1,$00,1,$80,22,$00,1,$76
db 8,$00,1,$80,1,$00,1,$80,21,$00,1,$76
db 9,$00,4,$80,19,$00,1,$ff
; End of loop!
;
; +++
; Break
;
; preserves state, but will exit if SPACE is pushed
check_break:
exx ; save register states
; did the player press break key (space)?
call $0f46 ; was break pressed? (break-1 ROM routine)
jr nc,break ; no, exit as normal
exx ; restore registers
ret ; and return
; yes, exit the program as normal
break:
rst $0008 ; call ERROR-1 reset
db $ff ; with error code 0 (normal exit)
; end break
; ---
; +++
;
; Data and Defines
;
; ZX81 system vars
d_file: equ $400c
df_cc: equ 16398
last_k: equ 16421
margin: equ 16424
s_posn: equ 16441
frames: equ 16436
; ZX81 ROM functions
kscan: equ $02bb
findchar: equ $07bd
stop: equ $0cdc
slow: equ $0f2b
fast: equ $02e7
save: equ $02f9
printat: equ $08f5
pause: equ $0f35
cls: equ $0a2a
; ZX81 Characters (not ASCII)
_sp: equ $00
_qu: equ $0b
_lb: equ $0c
_dl: equ $0d
_cl: equ $0e
_lp: equ $10
_rp: equ $11
_gt: equ $12
_lt: equ $13
_eq: equ $14
_pl: equ $15
_mi: equ $16
_as: equ $17
_sl: equ $18
_sc: equ $19
_cm: equ $1a
_pr: equ $1b
_0_: equ $1c
_1_: equ $1d
_2_: equ $1e
_3_: equ $1f
_4_: equ $20
_5_: equ $21
_6_: equ $22
_7_: equ $23
_8_: equ $24
_9_: equ $25
_a_: equ $26
_b_: equ $27
_c_: equ $28
_d_: equ $29
_e_: equ $2a
_f_: equ $2b
_g_: equ $2c
_h_: equ $2d
_i_: equ $2e
_j_: equ $2f
_k_: equ $30
_l_: equ $31
_m_: equ $32
_n_: equ $33
_o_: equ $34
_p_: equ $35
_q_: equ $36
_r_: equ $37
_s_: equ $38
_t_: equ $39
_u_: equ $3a
_v_: equ $3b
_w_: equ $3c
_x_: equ $3d
_y_: equ $3e
_z_: equ $3f
; end defines
; ---