;;------------------------------------------------------------------------
;; RLE compressed hardware sprites
;;
;; This example will only run on the CPC+.
;; 
;; In this example:
;;
;; - An animation sequence is defined by a sequence of images (frames)
;; - The first frame is stored completely, subsequent frames are stored in a compressed
;;   format, where the data represents the differences between the new frame and the
;;   previous frame. (Each frame is a "delta" of the previous frame)
;; - The sequence must be played from the beginning to the end for the
;;   result to be correct; otherwise there will be errors.


;; this code must not be in the range &4000-&7fff, because it must 
;; run when the CPC+ hardware registers are active in this range.
org &8000
nolist


;;----------------------------------------------------------------------
;; unlock asic to gain access to asic registers
di
ld b,&bc
ld hl,sequence
ld e,17
.seq 
ld a,(hl)
out (c),a
inc hl
dec e
jr nz,seq


;;----------------------------------------------------------------------

;; set initial sprite frame
xor a
ld (sprite_frame),a

call update_sprite

ld a,(sprite_frame)
inc a
ld (sprite_frame),a



;;----------------------------------------------------------------------
;; update sprite ram with image data
;; 
;; DE = points to CPC+ hardware sprite RAM
;; A = index of sprite frame

.update_sprite
;; page in ASIC hardware registers
ld bc,&7fb8
out (c),c

ld a,(sprite_frame)				;; sprite frame
ld l,a
add hl,hl						;; x2 to get offset in table
ld bc,sprite_frames				;; base of table
add hl,bc						;; address of entry in table
ld a,(hl)						;; get entry from table (address of sprite frame)
inc hl
ld h,(hl)
ld l,a

call rle_decode_sprite

;; page out ASIC hardware registers
ld bc,&7fa0
out (c),c
ret

;;----------------------------------------------------------------------
;; decode compressed sprite pixel data into the CPC+ hardware sprite RAM
;;
;; HL = points to compressed sprite data pixel data
;; DE = points to CPC+ hardware sprite RAM
;; HL,DE,BC corrupt
;;
;; compressed sprite pixel data format:
;; 
;; The data is a list of one or more "packets".
;; Each packet has a code byte with parameters dependant on the value of the code byte.
;;
;; code byte:
;; 0 = end of compressed data, no parameters 
;; -ve = no parameters.  negate code byte to get number of bytes to add onto current DE
;; +ve = number of bytes to copy to hardware sprite RAM, followed by the actual bytes

.rle_decode_sprite
.rle_next
ld a,(hl)		;; get code

inc hl
or a			
ret z			;; quit if end of compressed data code
jp m,rle_move	


;; +ve code. Code is the number of bytes to copy to hardware sprite RAM
;; the bytes to copy follow the code.

ld b,a	
ld c,0			;; BC = count
ldir			;; transfer
jr next

.rle_move
neg
add a,e
ld e,a
jr next

;;----------------------------------------------------------------------



.sprite_frame
defb 0				;; index of current frame

;; pointer to data for each sprite frame
.sprite_frames
defw frame0
defw frame1
defw frame2
defw frame3


;;----------------------------------------------------------------------
;; this is the sequence to unlock the ASIC extra features
.sequence
defb &ff,&00,&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd,&ee