;; This example shows another way to handle the interrupts by hitting the hardware
;; directly.
;;
;; There are 6 interrupts per screen, one of which is triggered 2 HSYNCs after the start
;; of the VSYNC signal. We can use this to syncronise our interrupts.
;;
;; We first need to synchronise with the VSYNC, we can then enable our interrupts.
;; We now know exactly the order the interrupts will come and we can have 1 function for
;; each.

org &4000

start:
di				;; disable interrupts
im 1			;; Z80 interrupt mode (z80 calls to &0038 for each interrupt)

ld a,&c3	;; Z80 JP instruction
ld hl,int_fn	;; we always call this function for interrupt
ld (&0038),a	;; write JP instruction
ld (&0039),hl	;; write address
ei

;; delay
loop:
jp loop


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

;; this is synchronised to happen 2 HSYNCs after VSYNC
int_fn:
push af
push hl
push bc
;; in vsync?
ld b,&f5
in a,(c)
rra
jr nc,int_fn_not_vsync
;; in vsync.
;; reset counter
xor a
jp int_fn_handle

int_fn_not_vsync:
ld a,(counter)
inc a

int_fn_handle:
;; counter is the number of the interrupt function
;; to execute
;;
;; multiply this by 3 to find JP in table to use
;;
;; then execute the function

ld (counter),a
ld l,a
add a,a					;; x2
add a,l					;; x3
add a,int_functions AND 255
ld l,a
ld a,int_functions/256
adc a,0
ld h,a
call call_hl

pop bc
pop hl
pop af
ei
reti

call_hl:
jp (hl)

counter:
defb 0


int_functions:
jp int1
jp int2
jp int3
jp int4
jp int5
jp int6


int1:
ret

int2:
ret

int3:
ret

int4:
ret

int5:
ret

int6:
ret


end start
