;; This example demonstrates double buffering using the firmware
;; functions: MC SCREEN OFFSET and SCR SET POSITION
;;
;; MC SCREEN OFFSET tells the hardware of the screen's location
;; without telling the firmware. Ideal for setting the visible screen.
;;
;; SCR SET POSITION tells the firmware of the screen's location
;; without telling the hardware. Ideal for setting the hidden (draw) screen.
;;
;;
;; All drawing operations go to the screen that the firmware knows about.
;;
;; The code waits for the 50Hz interrupt and then changes which screen
;; is visible and which is hidden, it does this using firmware functions
;; which access the CRTC hardware, so this effect is hardware double buffering.
;;
;; In order to show there are 2 screens, I draw a 'A' on one, and a 'B'
;; on the other. The flickering comes from the difference between the 
;; two screens. 
;;
;; But this demonstrates the functions to do double buffering.
;; NOTE: That you must use the firmware functions, or your own,
;; to draw and update the screens so that flicker free movement is possible.
;; This example just demonstrates how to view one screen while you draw 
;; to another, which is the basis of double buffering.

mc_screen_offset equ &bd1f
scr_set_position equ &bd55
txt_set_cursor equ &bb75
txt_output equ &bb5a
scr_set_mode equ &bc0e
scr_clear equ &bc14
mc_wait_flyback equ &bd19

;; one screen is at &4000-&7fff
;; other screen is at &c000-&ffff

org &8000

;; set initial mode
ld a,1
call scr_set_mode

;; initial state, &c000 is visible, &4000 is hidden
ld a,&c0
ld (scr_visible),a
ld a,&40
ld (scr_hidden),a

;; firmware writes to hidden,
;; we see visible
call set_double_buffer

;; clears hidden screen (screen firmware uses)
;; initially this is @ &4000
call scr_clear
ld h,1
ld l,1
call txt_set_cursor
ld a,'A'
call txt_output

;; swap buffers, firmware
call update_double_buffer
call set_double_buffer


;; clears hidden screen (screen firmware uses)
;; now this is @ &c000
call scr_clear
ld h,1
ld l,1
call txt_set_cursor
ld a,'B'
call txt_output

main_loop:
call mc_wait_flyback

call update_double_buffer

call set_double_buffer



jp main_loop

set_double_buffer:
ld a,(scr_visible)
ld hl,&0000
call mc_screen_offset

ld a,(scr_hidden)
ld hl,&0000
call scr_set_position
ret

update_double_buffer:
ld a,(scr_visible)
call toggle_base
ld (scr_visible),a

ld a,(scr_hidden)
call toggle_base
ld (scr_hidden),a
ret

scr_hidden:
defb &40

scr_visible:
defb &c0


toggle_base:
;; &c0-&40
;; &40-&c0
cp &c0
ld a,&40
ret z
ld a,&c0
ret