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