ZX81 Assembly Listing for fastcat.asm


ZX81 assembly listing for **CAT ASM**SLR/2023**

**CAT ASM**SLR/2023** (fastcat.asm)

This is an assembly version of the Cat Animation. It uses direct screen plotting from RLE compressed frames of data.


ASSEMBLY PROGRAM LISTING

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