;;--------------------------------------------- ;; ;; 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