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 ; ---