Press:
p to walk right
o to walk left
Loading ZX Spectrum...
org 33000
defb %00000001 ;bit definitions (if set to 1):
;bit 0: right direction
;bit 1: jump
;bit 2: holding lantern
anim_frames EQU 8
;sprite reverse of main character into memory addresses
ld bc, 576 ; 72 x 8 frames
ld hl, sprite
ld de, sprite_reversed
sprite_reverse_loop
ld a, (hl)
call reverse_a
ld (de), a
inc hl
inc de
ld a, c
or b
dec bc
jp nz, sprite_reverse_loop
ld b, 144 ; starting y-coordinate
ld c, 3 ; starting x-coordinate
push bc
ld a, 1
out (254), a ;set border
main
ld ix, sprite
pop bc
ld iyl, anim_frames ; frame counter
push bc
call Get_Pix_address_DE
pop bc
push bc
call save_sprite_bg
pop bc
push bc
call restore_sprite_bg
pop bc
push bc
;; call apply_attributes
pop bc
push bc
call draw_sprite
;;;;;;;;;;;;;;; main loop
detect_keys
pop bc
push bc
; walk sound every 4th frame
ld a, iyl
cp 4
jp nz, no_walk_sound
ld a, (33000)
bit 7, a
jp nz, no_walk_sound
call walk_sound
no_walk_sound
ld bc, 0xDFFE
in a, (c)
and 1
jp z, key_p_pressed
ld bc, 0xDFFE
in a, (c)
and 2
jp z, key_o_pressed
jp detect_keys
key_o_pressed:
ld a, (33000)
bit 0, a
jp z, no_turning_l
turn_left:
pop bc ; get our coordinates
ld a, c ; align to x-grid
add a, 8
ld c, a
push bc
pop bc
ld iyl, 1
ld a, c
sub 6
and %11111000
add a, 6
ld c, a
push bc ; push new coordinates
call restore_sprite_bg
ld a, (33000) ; get sprite detail
res 0, a ; we have turned, set bit
ld (33000), a ; store it
jp handle_movement_l
no_turning_l:
handle_movement_l:
pop bc
halt
call clr_sprite
push bc
pop bc
push bc
call restore_sprite_bg
pop bc
dec c ; decrease x-coordinate
push bc
call save_sprite_bg
pop bc
push bc
call draw_sprite
pop bc
push bc
ld bc, 1500 ; slow down animation
call delay
jp detect_keys
key_p_pressed: ;right direction
ld a, (33000)
bit 0, a
jp nz, no_turning_r
turn_right:
pop bc
ld iyl, 1 ; load anim frame 1
ld a, c ; Load Y coordinate
add a, 7 ; Subtract base offset
and %11111000 ; Clear lower 3 bits (align to 8)
sub 7 ; Restore offset
ld c, a ; Store back
push bc
call restore_sprite_bg
ld a, (33000) ; get sprite detail
set 0, a ; we have turned, set bit
ld (33000), a ; store it
jp handle_movement_r
no_turning_r
handle_movement_r:
pop bc
halt
call clr_sprite
push bc
call restore_sprite_bg
pop bc
inc c ; increase x
push bc
call save_sprite_bg
pop bc
push bc
call draw_sprite
pop bc
push bc
ld bc, 1500 ; slow down animation
call delay
jp detect_keys
the_end
pop bc
ret ; END - return to basic
;; ---------routines below ;;
walk_sound
push hl
ld h, 1
sound
ld b, 20
ld c, 76
pulse
ld a, %00001001
out (254), a
push bc
pulse_delay
dec bc
ld a, c
cp b
jp nz, pulse_delay
pop bc
ld a, %00000001
out (254), a
djnz pulse
dec h
jp nz, sound
pop hl
ld a, (33000)
set 7, a
ld (33000), a
ret
delay:
push af
delay_loop:
dec bc
ld a, b
or c
jp nz, delay_loop
pop af
ret
restore_sprite_bg:
push bc
push ix ; preserve sprite data addr
ld ix, sprite_bg_addr
ld h, 8
call restore_sprite_bg_loop
inc d
dec e
dec e
dec e
ld h, 8
call restore_sprite_bg_loop
inc d
dec e
dec e
dec e
ld h, 8
call restore_sprite_bg_loop
push de
push hl
ld a, b
sub 16
ld b, a
call get_attr_addr ; for restoring
ld hl, 37000
ld a, (hl)
ld (de), a
inc l
inc e
ld a, (hl)
ld (de), a
inc l
inc e
ld a, (hl)
ld (de), a
dec e
dec e
inc l
ld a, e
add a, 32 ; jump to 2nd row
ld e, a
ld a, (hl) ; restore
ld (de), a
inc e
inc l
ld a, (hl)
ld (de), a
inc e
inc l
ld a, (hl)
ld (de), a
dec e
dec e
inc l
ld a, e
add a, 32 ; jump to 3rd row
ld e, a
ld a, (hl) ; restore
ld (de), a
inc e
inc l
ld a, (hl)
ld (de), a
inc e
inc l
ld a, (hl)
ld (de), a
dec e
dec e
inc l
ld a, e
add a, 32 ; jump to 4th row
ld e, a
ld a, (hl) ; restore
ld (de), a
inc e
inc l
ld a, (hl)
ld (de), a
inc e
inc l
ld a, (hl)
ld (de), a
pop hl
pop de
pop ix
pop bc
ret
restore_sprite_bg_loop
call Get_Pix_Address_DE
ld a, (ix+0)
ld (de), a
inc e
ld a, (ix+1)
ld (de), a
inc e
ld a, (ix+2)
ld (de), a
inc b
dec h
inc ix
inc ix
inc ix
jp nz, restore_sprite_bg_loop
ret
save_sprite_bg:
push bc
push ix
ld ix, sprite_bg_addr
ld h, 8
call save_sprite_bg_loop
ld h, 8
inc d
dec e
dec e
dec e
call save_sprite_bg_loop
ld h, 8
inc d
dec e
dec e
dec e
call save_sprite_bg_loop
;save_sprite background attr.
push bc
push hl
ld a, b
sub 16
ld b, a
call get_attr_addr
ld hl, 37000
ld a, (de) ;save_1st row
ld (hl), a
inc e
inc l
ld a, (de)
ld (hl), a
inc e
inc l
ld a, (de)
ld (hl), a
inc l
ld a, e
add a, 30 ;jump to_2nd row
ld e, a
ld a, (de) ;save_2nd row
ld (hl), a
inc l
inc e
ld a, (de)
ld (hl), a
inc l
inc e
ld a, (de)
ld (hl), a
inc l
ld a, e
add a, 30 ;jump to_3rd row
ld e, a
ld a, (de) ;save
ld (hl), a
inc l
inc e
ld a, (de)
ld (hl), a
inc l
inc e
ld a, (de)
ld (hl), a
inc l
ld a, e
add a, 30 ;jump to_4th row
ld e, a
ld a, (de) ;save
ld (hl), a
inc l
inc e
ld a, (de)
ld (hl), a
inc l
inc e
ld a, (de)
ld (hl), a
pop hl
pop bc
pop ix
pop bc
ret
save_sprite_bg_loop
call Get_Pix_Address_DE
ld a, (de)
ld (ix+0), a
inc e
ld a, (de)
ld (ix+1), a
inc e
ld a, (de)
ld (ix+2), a
inc b
inc ixl
inc ixl
inc ixl
dec h
jp nz, save_sprite_bg_loop
ret
clr_sprite
push bc
ld h, 8 ;set counter
call loop_clr
inc d
ld h, 8 ;set counter
call loop_clr
inc d
ld h, 8 ;set counter
call loop_clr
pop bc
ret
loop_clr
call Get_Pix_Address_DE
ld a, 0
ld (de), a
inc e
ld (de), a
inc e
ld (de), a
inc b
dec h
jp nz, loop_clr
ret
draw_sprite
ld a, (33000) ;test bit for direction
bit 0, a
jp z, moving_left
moving_right
ld h, 8 ;set counter
call loop_24x24
inc d
ld h, 8 ;set counter
call loop_24x24
inc d
ld h, 8 ;set counter
call loop_24x24
jp rows_done
moving_left
ld h, 8 ;set counter
call loop_24x24_reverse
inc d
ld h, 8 ;set counter
call loop_24x24_reverse
inc d
ld h, 8 ;set counter
call loop_24x24_reverse
jp rows_done
rows_done ;char pixel drawing done
ld iyh, 0
dec iyl ;check how many frames
call z, reset_sprite
ret
reset_sprite
pop bc
dec c
push bc
ld ix, sprite
ld iyl, anim_frames
ret
loop_24x24:
call Get_Pix_Address_DE
push hl
push bc
ex de, hl
; first column bytes
ld a, (ix+0)
sla a
cpl
and (hl)
ld (hl), a
ld a, (ix+0)
sra a
cpl
and (hl)
ld (hl), a
ld a, (ix+0)
or (hl)
ld (hl), a
inc l
; second column bytes
ld a, (ix+1)
sla a
cpl
and (hl)
ld (hl), a
ld a, (ix+1)
sra a
cpl
and (hl)
ld (hl), a
ld a, (ix+1)
or (hl)
ld (hl), a
inc l
; third column bytes
ld a, (ix+2)
sla a
cpl
and (hl)
ld (hl), a
ld a, (ix+2)
sra a
cpl
and (hl)
ld (hl), a
ld a, (ix+2)
or (hl)
ld (hl), a
inc l
; Advance IX
inc ix
inc ix
inc ix
pop bc
inc b
pop hl
dec h
jp nz, loop_24x24
call apply_attributes
ret
apply_attributes ; per row
push de
push hl
push bc
call get_attr_addr
pop bc
; load characters with attrb values
ld a, %01111100 ; sprite color
ld (de), a ; first 8x8 of row
inc e ; second 8x8 of row
ld (de), a
inc e ; third 8x8 of row
ld (de), a
pop hl ; restore HL
pop de
ret
skip_frame
inc c
ret
loop_24x24_reverse
call Get_Pix_Address_DE
push hl
push bc
ex de, hl
push hl
ld a, ixh
ld d, a
ld a, ixl
ld e, a
ld hl, 578
add hl, de
ex de, hl
pop hl
; first byte of column with flip routine
ld a, (de)
sla a
cpl
and (hl)
ld (hl), a
ld a, (de)
sra a
cpl
and (hl)
ld (hl), a
ld a, (de)
or (hl)
ld (hl), a
inc l
; second byte of column with flip routine
dec de
ld a, (de)
sla a
cpl
and (hl)
ld (hl), a
ld a, (de)
sra a
cpl
and (hl)
ld (hl), a
ld a, (de)
or (hl)
ld (hl), a
inc l
; third byte of column with flip routine
dec de
ld a, (de)
sla a
cpl
and (hl)
ld (hl), a
ld a, (de)
sra a
cpl
and (hl)
ld (hl), a
ld a, (de)
or (hl)
ld (hl), a
; Advance IX
inc ix
inc ix
inc ix
pop bc
inc b ; next scanline
pop hl
dec h
jp nz, loop_24x24_reverse
call apply_attributes
ret
get_attr_addr
; attr address = 22528 + (INT(Y / 8) × 32) + INT(X / 8)
ld h, 0 ; clear H
ld l, 0
ld a, b
sub 8 ; back to original y (B)
ld b, a
ld a, b
srl a
srl a
srl a
ld l, a
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
ld DE, 22528
add HL, DE
ex DE, HL
ld h, 0
ld l, 0
ld a, c
srl a
srl a
srl a
ld l, a
add HL, DE
ex DE, HL
ret
reverse_a:
push bc
ld b,a
rrca
rrca
xor b
and %10101010
xor b
ld b, a
rrca
rrca
rrca
rlc b
xor b
and %00110011
xor b
rlca
rlca
pop bc
ret
Get_Pix_Address_DE:
LD A, B ; Y coordinate
AND %00000111 ; Y2,Y1,Y0
OR %01000000 ; Base &4000
LD D, A ; Store in D
LD A, B ; Y7,Y6
RRA
RRA
RRA
AND %00011000
OR D ; OR with Y2,Y1,Y0
LD D, A ; Final D
LD A, B ; Y5,Y4,Y3
RLA
RLA
AND %11100000
LD E, A ; Store in E
LD A, C ; X4,X3,X2,X1,X0
RRA
RRA
RRA
AND %00011111
OR E ; OR with Y5,Y4,Y3
LD E, A ; Final E
RET ; Address in DE
sprite
;frame1-top
defb %00010000, %00000000, %00000000
defb %00011111, %10000000, %00000000
defb %00001111, %11111000, %00000000
defb %00000011, %11111110, %00000000
defb %00000001, %11111111, %00000000
defb %00000000, %11111111, %10000000
defb %00000000, %01111111, %11000000
defb %00000000, %00111111, %11000000
;frame1-middle
defb %00000000, %00011111, %11100000
defb %00000000, %00111111, %11000000
defb %00000000, %00111111, %10000000
defb %00000000, %00000111, %00000000
defb %00000000, %00000010, %00000000
defb %00000000, %00001111, %00000000
defb %00000000, %00011111, %10000000
defb %00000000, %00111111, %11000000
;frame1-bottom
defb %00000000, %01101111, %01110000
defb %00000000, %11001111, %00110000
defb %00000000, %11001111, %00000000
defb %00000000, %00000111, %10000000
defb %00000000, %00000100, %11000000
defb %00000000, %00011000, %01100000
defb %00000000, %00010010, %00101000
defb %00000000, %00011110, %00111000
;frame2-top
defb %00001100, %00000000, %00000000
defb %00001111, %11100000, %00000000
defb %00000111, %11111000, %00000000
defb %00000011, %11111111, %00000000
defb %00000000, %01111111, %11000000
defb %00000000, %01111111, %11000000
defb %00000000, %00111111, %11000000
defb %00000000, %00001111, %11100000
;frame2-middle
defb %00000000, %00001111, %11110000
defb %00000000, %00011111, %11110000
defb %00000000, %00011111, %11000000
defb %00000000, %00000011, %11000000
defb %00000000, %00000001, %00000000
defb %00000000, %00000111, %11000000
defb %00000000, %00000111, %11000000
defb %00000000, %00001111, %11000000
;frame2-bottom
defb %00000000, %00110111, %11000000
defb %00000000, %00110111, %11000000
defb %00000000, %00000110, %00000000
defb %00000000, %00000110, %00000000
defb %00000000, %00000110, %00000000
defb %00000000, %00000110, %00000000
defb %00000000, %00000111, %01000000
defb %00000000, %00000111, %11000000
;frame3-top
defb %00000001, %10000000, %00000000
defb %00000000, %11111100, %00000000
defb %00000000, %01111110, %00000000
defb %00000000, %01111111, %11000000
defb %00000000, %00111111, %11100000
defb %00000000, %00011111, %11110000
defb %00000000, %00011111, %11111000
defb %00000000, %00000111, %11111100
;frame3-middle
defb %00000000, %00000111, %11111000
defb %00000000, %00001111, %11110000
defb %00000000, %00001111, %11110000
defb %00000000, %00000000, %01000000
defb %00000000, %00000000, %11110000
defb %00000000, %00000001, %11110000
defb %00000000, %00000001, %11110110
defb %00000000, %00000001, %11111110
;frame3-bottom
defb %00000000, %00000011, %11100000
defb %00000000, %00001111, %11100000
defb %00000000, %00001101, %11000000
defb %00000000, %00000001, %00110100
defb %00000000, %00000001, %00111100
defb %00000000, %00000111, %00000000
defb %00000000, %00001110, %00000000
defb %00000000, %00001111, %00000000
;frame4-top
defb %00000001, %10000000, %00000000
defb %00000001, %11111100, %00000000
defb %00000001, %11111110, %00000000
defb %00000000, %00111111, %11100000
defb %00000000, %00001111, %11111000
defb %00000000, %00001111, %11111100
defb %00000000, %00000111, %11111110
defb %00000000, %00000011, %11111111
;frame4-middle
defb %00000000, %00000001, %11111100
defb %00000000, %00000111, %11111100
defb %00000000, %00000111, %11111000
defb %00000000, %00000000, %11111000
defb %00000000, %00000000, %00100000
defb %00000000, %00000000, %01111000
defb %00000000, %00000000, %11111000
defb %00000000, %00000000, %11111000
;frame4-bottom
defb %00000000, %00000001, %11111100
defb %00000000, %00000011, %11111111
defb %00000000, %00000110, %00100011
defb %00000000, %00000000, %11111000
defb %00000000, %00000000, %11111010
defb %00000000, %00000111, %00011110
defb %00000000, %00000110, %00000110
defb %00000000, %00000111, %00000000
;frame5-top
defb %00000000, %00110000, %00000000
defb %00000000, %00011110, %00000000
defb %00000000, %00011111, %10000000
defb %00000000, %00000111, %11110000
defb %00000000, %00000111, %11111000
defb %00000000, %00000011, %11111100
defb %00000000, %00000001, %11111100
defb %00000000, %00000000, %11111110
;frame5-middle
defb %00000000, %00000000, %11111111
defb %00000000, %00000001, %11111110
defb %00000000, %00000001, %11111100
defb %00000000, %00000000, %00111000
defb %00000000, %00000000, %00011000
defb %00000000, %00000000, %00111100
defb %00000000, %00000000, %00111100
defb %00000000, %00000000, %00111100
;frame5-bottom
defb %00000000, %00000000, %11111111
defb %00000000, %00000000, %11111111
defb %00000000, %00000000, %11011011
defb %00000000, %00000000, %00011000
defb %00000000, %00000000, %00011000
defb %00000000, %00000000, %11100100
defb %00000000, %00000000, %00000111
defb %00000000, %00000000, %00000011
;frame6-top
defb %00011000, %00000000, %00000000
defb %00001111, %10000000, %00000000
defb %00000111, %10000000, %00000000
defb %00000011, %11110000, %00000000
defb %00000011, %11111000, %00000000
defb %00000001, %11111110, %00000000
defb %00000001, %11111111, %00000000
defb %00000001, %11111111, %10000000
;frame6-middle
defb %00000000, %11111110, %00000000
defb %00000000, %11111110, %00000000
defb %00000001, %11111110, %00000000
defb %00000001, %10111100, %00000000
defb %00000000, %00001000, %00000000
defb %00000000, %00111100, %00000000
defb %00000000, %00111110, %00000000
defb %00000000, %00111110, %00000000
;frame6-bottom
defb %00000000, %00111111, %00000000
defb %00000000, %00101100, %00000000
defb %00000000, %00011110, %00000000
defb %00000000, %00101010, %00000000
defb %00000000, %00111011, %00000000
defb %00000001, %11100011, %00000000
defb %00000001, %10000011, %01000000
defb %00000001, %11000011, %10000000
;frame7-top
defb %01100000, %00000000, %00000000
defb %00011110, %00000000, %00000000
defb %00011110, %00000000, %00000000
defb %00001111, %11110000, %00000000
defb %00000011, %11111110, %00000000
defb %00000011, %11111110, %00000000
defb %00000001, %11111111, %00000000
defb %00000000, %01111111, %00000000
;frame7-middle
defb %00000000, %01111111, %00000000
defb %00000000, %11111110, %00000000
defb %00000000, %11111110, %00000000
defb %00000000, %00111110, %00000000
defb %00000000, %00001000, %00000000
defb %00000000, %00011100, %00000000
defb %00000000, %00111100, %00000000
defb %00000000, %01111110, %00000000
;frame7-bottom
defb %00000000, %01111110, %00000000
defb %00000000, %01111110, %00000000
defb %00000000, %00111110, %00000000
defb %00000000, %00111000, %00000000
defb %00000000, %00111000, %00000000
defb %00000000, %01001100, %00000000
defb %00000000, %01100101, %00000000
defb %00000000, %01110111, %00000000
;frame8-top
defb %00111000, %00000000, %00000000
defb %00011111, %10000000, %00000000
defb %00000111, %11110000, %00000000
defb %00000011, %11111000, %00000000
defb %00000001, %11111110, %00000000
defb %00000000, %11111110, %00000000
defb %00000000, %01111111, %10000000
defb %00000000, %01111111, %11000000
;frame8-middle
defb %00000000, %00111111, %00000000
defb %00000000, %01111111, %00000000
defb %00000000, %00111111, %00000000
defb %00000000, %00001110, %00000000
defb %00000000, %00000100, %00000000
defb %00000000, %00011110, %00000000
defb %00000000, %00011110, %00000000
defb %00000000, %00011111, %10000000
;frame8-bottom
defb %00000000, %01101110, %11000000
defb %00000000, %01101110, %11000000
defb %00000000, %00001110, %00000000
defb %00000000, %00001110, %00000000
defb %00000000, %00001110, %10000000
defb %00000000, %01110000, %11000000
defb %00000000, %01000100, %01010000
defb %00000000, %01100000, %01110000
sprite_reversed ;pre flipped bytes go here
turn_sprites
;frame1-top
defb %11000011, %11000111
defb %10010001, %10010001
defb %10110000, %00101000
defb %10010000, %00001000
defb %00010000, %00110000
defb %00111000, %00111100
defb %10000001, %10000001
defb %11000011, %11000011
;frame1-bottom
defb %11000011, %11000011
defb %10011001, %10011001
defb %10101000, %00101000
defb %10011000, %01111000
defb %00001000, %00001000
defb %00111000, %00011100
defb %10000001, %10000001
defb %11000011, %11000011
org 35000
defb %00000000 ;speed
org 36000
sprite_bg_addr
defb 0 ;save bg