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