;; This example shows how to double buffer a standard 16K screen 
;; using the hardware. The example is minimal and just shows how
;; you set the screen base to do the double buffer it doesn't show
;; how to draw on double buffered screens.
;;
;; One screen will be at &4000-&7fff.
;; Second screen will be at &c000-&ffff.
;;
;; This example assumes we are executing at exactly 50hz because
;; the double buffer flip always happens every 50th of a second.
;;
;; location for our code, not inside visible screen area (this allows
;; us to scroll the screen if we need)
org &8000

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

start:

di
im 1
ld a,&c3
ld hl,int_handler
ld (&0038),a
ld (int_handler),hl
ei

;; we display the visible screen
ld a,&c0
ld (base_visible),a
;; we draw to the hidden screen, this is it's initial state
ld a,&40
ld (base_hidden),a

loop:
jp loop

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

int_handler:
;; store registers we will change
push af
push bc
push hl

;; in VSYNC?
ld b,&f5
in a,(c)
rra
jr nc,int_handler2 ;; no, skip double buffer

;; in VSYNC
;;
;; here we update our double buffer

;; set screen address using CRTC
;; 
;; we set R12/R13.
ld a,(base_visible)
;; make the value correct for crtc
srl a
srl a

ld bc,&bc0c		;; CRTC R12
out (c),c
;; B = &BD
inc b
out (c),a
dec b
inc c
;; BC=&BC0D
out (c),c			;; CRTC R13
inc b
;; B = &BD
xor a
out (c),a

;;
;; &c0-&40 AND &40-&c0
ld a,(base_visible)
xor &80
ld (base_visible),a

;; code should now use this to work out how to draw

;; &40-&c0 AND &c0-&40
ld a,(base_hidden)
xor &80
ld (base_hidden),a

int_handler2:
pop hl
pop bc
ei
reti

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

;; this is the visible screen
base_visible:
defb &c0

;; this is the hidden screen we draw to
base_hidden:
defb &40

end