;; This code shows a firmware compatible way to do:
;; 1. swap the screen base every 50th of a second. In this way we can switch between 2 images rapidly
;; can be used to give the illusion of better resolution or more colours
;; 
;; 2. change the screen mode every 50th of a second. In this way we can switch between 2 images in 2 different modes.
;; can be used to give the illusion of better resolution or more colours

;; 3. how to set the colours for each mode (uses fact that firmware has two colour palettes it switches between)
;; done in a firmware friendly way

;; 4. how to set the rate at which the firmware changes palettes

scr_set_mode equ &bc0e
scr_set_ink equ &bc32
mc_wait_flyback equ &bd19
scr_set_flashing equ &bc3e
scr_set_base equ &bc08
mc_set_mode equ &bd1c
cas_in_open equ &bc77
cas_in_direct equ &bc83
cas_in_close equ &bc7a
scr_initialise equ &bbff
scr_reset equ &bc02
scr_set_border equ &bc38   
screencolours equ 16
km_test_key equ &bb1e

def1high equ def1/256
def2high equ def2/256
def1low equ def1 and 255
def2low equ def2 and 255

defswap_high equ def1high xor def2high
defswap_low equ def1low xor def2low

org &8000
nolist

;; We need to sync with the flyback to ensure that when we re-initialise the screen
;; the colour changes will happen when we want them to.

;; 1st screen goes to &c000
;; 2nd screen goes to &4000
;; each screen is 16k

;; will quit if flyback has started or in-progress
call mc_wait_flyback
;; wait long enough for frame flyback interrupt to pass
halt
halt

;; this waits for flyback to start
call mc_wait_flyback
;; wait for frame flyback interrupt to occur and then pass
halt
halt

;; reset flashing speeds, inks to default value and resets the flip-flop value that
;; defines which palette to display 
call scr_reset

;; set flashing rate
ld h,1
ld l,1
call scr_set_flashing

;; now we set colours for the screens
ld b,screencolours
xor a
ld ix,colours

set_colours:
push bc
push af
ld b,(ix+0)
ld c,(ix+screencolours)
inc ix
push ix
call scr_set_ink
pop ix
pop af
pop bc
inc a
djnz set_colours

;; set border
ld bc,0
call scr_set_border

ld hl,def1
ld (cur_def),hl


l1:
;; set any time before new frame starts
ld hl,(cur_def)
ld a,(hl)
inc hl
push hl
call scr_set_base

;; now we need to wait for flyback to happen again; this time first palette will be set
call mc_wait_flyback
pop hl
;; set mode after flyback
ld a,(hl)
call mc_set_mode

;; flip data for screens
ld hl,(cur_def)
ld a,h
xor defswap_high
ld h,a
ld a,l
xor defswap_low
ld l,a
ld (cur_def),hl

halt
halt

ld a,47				;; space key
call km_test_key
ret nz				;; quit if pressed back to basic

jp l1

cur_def:
defw def1

def1:
defb &40			;; base for screen 1
defb 0				;; mode for screen 1


def2:
defb &c0			;; base for screen 2
defb 0				;; mode for screen 2


colours:
;; firmware colours for screen 1
db 3,16,26,12,13,25,0,6,14,21,10,11,1,15,24,4
;; firmware colours for screen 2
db 3,16,26,12,13,25,0,6,14,21,10,11,1,15,24,4