;; This example demonstrates a method to plot sprites using the firmware
;; and the character set.
;;
;; - The sprites are defined using the character set matrices.
;;
;; - Each sprite is therefore composed of multiple 8x8 character matrices.
;;
;; - The display mode is set to mode 2 (640x200) which uses 1 bit per pixel
;;   Each line of the character matrix is represented by 1 byte.
;;
;; - When the character is displayed in mode 2, each line of the character
;;   matrix is written direct to the screen memory without conversion.
;;   This is an important fact for this example.
;;   (Normally, the character matrix data is converted into mode 1 or mode 2
;;   pixel data)
;;
;; - The display mode is changed, without informing the firmware functions.
;;   The characters will be plotting using the mode 2 method, regardless
;;   of the forced video mode. This is an important fact for this example.
;;
;;   If the character matrix data is setup so that each byte represents
;;   a byte of mode 1 or mode 0 screen pixel data, then multi-coloured
;;   sprites can be plotted, by the firmware, using the standard character
;;   plot routines. The only problem, is that each character matrix 
;;   represents 4x8 pixels in mode 1, and 2x8 pixels in mode 0. So many
;;   matrices may be required to hold the pixel data for each sprite.
;;
;; - graphics coordinates, if used, must be defined so that the sprite
;;   is plotted on a byte boundary. e.g. x must be a integer multiple of 8.
;;
;; This method may be useful for plotting sprites for games in a
;; 1K games competition.

.scr_set_mode equ &bc0e
.mc_set_mode equ &bd1c
.km_read_char equ &bb09
.mc_wait_flyback equ &bd19
.txt_output equ &bb5a
.txt_set_matrix equ &bba8
.gra_move_absolute equ &bbc0
.gra_move_relative equ &bbc3
.gra_wr_char equ &bbfc
.scr_access equ &bc59

org &4000
nolist

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

;; set display mode 2
ld a,2
call scr_set_mode

;; force display mode 1
;; - the firmware will plot characters using the method for mode 2.

ld a,1
call mc_set_mode

;;-----------------------------------------------------------------------
;; set screen write mode to XOR
;;
;; - plot sprite using XOR to display, plot sprite using XOR in same position
;; to erase.
;; - if sprite moves over any other graphics, some pixels will change colour.

ld a,1
call scr_access

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

;; initialise sprite data

ld hl,pixel_data          ;; location of character matrix data
ld a,248                  ;; id of first character matrix
ld b,8                    ;; number of characters to define matrix for
.sch
push af
push bc
push hl
call txt_set_matrix       ;; set character matrix
pop hl

ld bc,8                   ;; number of bytes per character matrix
add hl,bc

pop bc
pop af
inc a
djnz sch



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

;; plot sprite
ld a,248
ld de,(sprite_x)
ld hl,(sprite_y)
call draw_sprite

.loop
call mc_wait_flyback

;; erase sprite
ld a,248
ld de,(sprite_x)
ld hl,(sprite_y)
call draw_sprite

call controls

;; plot sprite (in new position
;; if sprite's coordinates have changed)
ld a,248
ld de,(sprite_x)
ld hl,(sprite_y)
call draw_sprite

jp loop

.controls
call km_read_char
ret nc
and &df
cp "Q"
jp z,moveup
cp "A"
jp z,movedown
cp "O"
jr z,moveleft
cp "P"
jr z,moveright
ret

;; adjust y coordinate of sprite
;; to move it up the screen.
;; - Each scan-line is 2 graphics y coordinates.
;; - origin of graphics coordinates is bottom-left
.moveup
ld hl,(sprite_y)
inc hl
inc hl
ld (sprite_y),hl
ret

;; adjust y coordinate of sprite
;; to move it down the screen.
.movedown
ld hl,(sprite_y)
dec hl
dec hl
ld (sprite_y),hl
ret

;; adjust x coordinate of sprite
;; to move it left accross the screen.
;; - each byte is 8 graphics x coordinates
.moveleft
ld hl,(sprite_x)
ld bc,8
or a
sbc hl,bc
ld (sprite_x),hl
ret

;; adjust x coordinate of sprite
;; to move it right accross screen
.moveright
ld hl,(sprite_x)
ld bc,8
add hl,bc
ld (sprite_x),hl
ret

;;-------------------------------------------------------------
;; A = id of first character used by sprite data
;; DE = x graphics coordinate
;; HL = y graphics coordinate

.draw_sprite
;; move to initial position
push af
call gra_move_absolute
pop af

ld b,2          ;; number of character matrices occupied by sprite in
                ;; y dimension
.ps1
push bc
push af

ld c,4          ;; number of character matrices occupied by sprite in
                ;; x dimension

.ps2
push bc
push af

;; plot character at graphics coordinate position
;; and update graphics coordinate position for next
;; character
call gra_wr_char

pop af
pop bc
add 2           ;; increment character id
                ;; (see character matrix usage below)
dec c
jr nz,ps2

;; adjust graphics character position for next row
;; of characters

ld de,-8*4
ld hl,-16
call gra_move_relative

pop af

;; increment character id
;; (see character matrix usage below)
inc a
          
pop bc
djnz ps1
ret

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

;; graphics coordinates for sprites position
.sprite_x defw 320
.sprite_y defw 100

;; sprite is:
;; - 16 mode 1 pixels wide = 4 bytes wide = 4 mode 2 characters wide
;; - 16 mode 1 pixels tall = 2 mode 2 characters tall
;; 
;; sprite data is stored as:
;;
;; char 248   char 250  char 252  char 254
;; char 249   char 251  char 253  char 255

.pixel_data
defb &00                  ;; char 248
defb &00
defb &10
defb &20
defb &40
defb &40
defb &80
defb &80

defb &80                  ;; char 249
defb &80
defb &40
defb &51
defb &31
defb &10
defb &00
defb &00

defb &30                  ;; char 250
defb &C0
defb &00
defb &00
defb &06
defb &0C
defb &0C
defb &04

defb &00                  ;; char 251
defb &00
defb &AA
defb &55
defb &FF
defb &FD
defb &F2
defb &30

defb &C0                  ;; char 252
defb &30
defb &00
defb &00
defb &00
defb &00
defb &00
defb &11

defb &22                  ;; char 253
defb &55
defb &BA
defb &75
defb &FA
defb &F5
defb &F8
defb &C0

defb &00                  ;; char 254
defb &00
defb &80
defb &40
defb &20
defb &20
defb &32
defb &76

defb &FA                  ;; char 255
defb &F4
defb &E8
defb &E4
defb &C8
defb &80
defb &00
defb &00