;;---------------------------------------------
;;
;; screen is split into 2 sections
;; 
;;
;; screen is 39 char lines tall, 25 for main area, rest for "border".
;; we need 1 char line effectively for the scroll, (and we take this away from the border area).
;; this is split into 2 areas, one added at the end of the "border" region, and one added at the end
;; of the main region, setup so they always both add to 8 scanlines so that the vsync in the bottom 
;; section is always at the same position.
;; these 2 areas are defined using CRTC register R5.
;; 

;; top and bottom are the same section wrapped around.
;; bottom section wraps to the top, and has a vsync triggered in the middle of it.

;; 8 lines per char
;; 
;; top section is: 6 char lines tall (6*8 = 48 scan lines)
;; R5!=0 here
;;
;; - interrupt occurs at 2nd line within this block. 
;; Next one happens 52 lines later at scanline 54. Potential that 7 additional lines are added.

;; main section is 25 char lines tall (25 * 8 = 200 scanlines)
;; R5!=0 here

;; bottom section is: 7 char lines tall (7*8 = 56 scan lines)
;; R5 = 0 here

org &2000
nolist

scr_set_mode equ &bc0e
txt_output equ &bb5a
scr_next_line equ &bc26

start:

;; generate initial screen
ld a,2
call scr_set_mode

ld bc,24*80
ld d,' '
l2:
inc d
ld a,d
cp &7f
jr nz,no_char_reset
ld d,' '
no_char_reset:
ld a,d
call txt_output
dec bc
ld a,b
or c
jr nz,l2

;; now copy byte shifted to another screen
ld hl,&c000
ld b,200
shiftedl:
push bc
push hl
ld e,l
ld d,h
ld a,d
and &3f
or &40
ld d,a
inc hl
ld bc,&80-1
ldir
pop hl
call scr_next_line
pop bc
djnz shiftedl


di
im 1
ld a,&c3
ld hl,int_handler1
ld (&0038),a
ld (&0039),hl
ld bc,&bc07
out (c),c
ld bc,&bd00+7
out (c),c
call vsync_sync
ld bc,&bc04
out (c),c
ld bc,&bd00+14-1-1
out (c),c
ei

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

loop1:
ld b,&f5
l1:
in a,(c)
rra
jr nc,l1
ld c,1
call scroll_up
call scroll_right

ld hl,(scrl2)
ld a,(scroll_adjustment)
or a
ld c,&30
jr z,loop2a
ld c,&18
loop2a:
ld a,h
and &3
or c
ld h,a
ld (scrl2),hl

;;xor 1
;;add a,&f5
;;ld (hsync2),a

ld a,1
ld (fetch_values),a

loop5:
loop2:
halt
halt
halt
jp loop1

scroll_adjustment:
defb 0

scroll_right:
ld a,(scroll_adjustment)
xor 1					
ld (scroll_adjustment),a
cp 1
ret z

ld hl,(scrl2)
inc hl
ld a,h
and &3
ld h,a
ld (scrl2),hl
ret


scroll_left:
ld a,(scroll_adjustment)
xor 1					
ld (scroll_adjustment),a
or a
ret z

ld hl,(scrl2)
dec hl
ld a,h
and &3
ld h,a
ld (scrl2),hl
ret
;;---------------------------------------------

;; update these seperate of display
scroll_up:
ld a,(vscrl_line2)
add a,c
cp 8
jr c,scroll_up2
and &7
ld (vscrl_line2),a

ld hl,(scrl2)
ld bc,40
add hl,bc
ld a,h
and &3
ld h,a
ld (scrl2),hl
ret
scroll_up2:
and &7
ld (vscrl_line2),a
ret


;; update these seperate of display
scroll_down:
ld a,(vscrl_line2)
dec a
and &7
ld (vscrl_line2),a
or a
jr nz,loop2
ld hl,(scrl2)
or a
ld bc,40
sbc hl,bc
ld a,h
and &3
ld h,a
ld (scrl2),hl
ret

vsync_sync:
ld b,&f5
vs1:
in a,(c)
rra
jr nc,vs1
vs2:
in a,(c)
rra
jr c,vs2
ret

;;-----------------------------------------------------------------------------
;; this is called 2 lines after the vsync starts.
;; vsync occurs on char line 7
;;
;; +2
;; +52
;; +52 -> 106

;; 7 lines until end of end of block = 56 lines
;; + 8 max. = 64

;; 106-64 = 42 lines/8 = 5 lines
;; next int is 10 lines before end
;; next after that is 

int_handler1:
push bc
push hl
push af


;; make vsync position no longer reachable
ld bc,&bc07
out (c),c
ld bc,&bdff
out (c),c

;;ld bc,&bc03
;;out (c),c
;;inc b
;;ld a,(hsync)
;;out (c),a

;; add some lines after to do vertical scroll
ld bc,&bc05
out (c),c
inc b
ld a,(vscrl_line)
neg
add a,8
out (c),a

ld hl,int_handler2
ld (&0039),hl
pop af
pop hl
pop bc
ei
ret

;; not used, still in top part
int_handler2:
push hl
ld bc,&bc0c
out (c),c
ld hl,(scrl)
inc b
out (c),h
ld bc,&bc0d
out (c),c
inc b
out (c),l
ld bc,&bc01
out (c),c
ld bc,&bd00+40
out (c),c
ld hl,int_handler3
ld (&0039),hl
pop hl
ei
ret

;; this is
int_handler3:
push bc
push hl
push af
;; set height of this area
ld bc,&bc04
out (c),c
ld bc,&bd00+25-1
out (c),c

;; set scroll after
ld bc,&bc05
out (c),c
inc b
ld a,(vscrl_line)
out (c),a

ld hl,int_handler4
ld (&0039),hl
pop af
pop hl
pop bc
ei
ret


int_handler4:
push hl
ld hl,int_handler5
ld (&0039),hl
pop hl
ei
ret


int_handler5:
push hl

ld hl,int_handler6
ld (&0039),hl
pop hl
ei
ret

int_handler6:
push bc
push hl
push af

;; turn off border for bottom bit...
ld bc,&bc01
out (c),c
ld bc,&bd00
out (c),c

;; 39-25 = 14

;; set height of this area
ld bc,&bc04
out (c),c
ld bc,&bd00+14-1-1
out (c),c

;; this can't be on first char line
ld bc,&bc07
out (c),c
ld bc,&bd00+7
out (c),c
ld hl,int_handler1
ld (&0039),hl

ld a,(fetch_values)
or a
jr z,int_handler1a
;; refresh display versions
ld a,(vscrl_line2)
ld (vscrl_line),a
ld hl,(scrl2)
ld (scrl),hl
;;ld a,(hsync2)
;;ld (hsync),a
xor a
ld (fetch_values),a

int_handler1a:

pop af
pop hl
pop bc
ei
ret

fetch_values:
defb 0

hsync:
defb 0

hsync2:
defb &85

scrl2:
defw 0

vscrl_line2:
defb 0

vscrl_line:
defb 0

scrl:
defw 0

end start