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