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