$PAGINATE
$title(Arnold 5 test)
$subtitle(Test of Split Screen feature)
$copyright(Copyright (c) 1989, 1990, Amstrad plc.)
$pagewidth=131

        PUBLIC  SplitScreenTest         ;called indirectly from TESTPACK
                                        ; out of MainMenuTable

        EXTERN  UnlockArn5              ;SUPPORT
        EXTERN  RelockArn5              ;SUPPORT
        EXTERN  SetCursorPos            ;SUPPORT
        EXTERN  ScreenPrintChar         ;SUPPORT
        EXTERN  KeyboardReadNoDelay     ;SUPPORT

        EXTERN  ?SplitScreenLine        ;TESTVARS
        EXTERN  ?SplitSecondAddr        ;TESTVARS
        EXTERN  ?SplitIncrement         ;TESTVARS

        DEFSEG  TestCode, CLASS=CODE

        SEG     TestCode

;===============
SplitScreenTest:
;===============
;
; This test will just do the following:
;
; Fill the whole 80x25 screen at C000h with the letter B, block move all this
; to 4000h. Fill the whole 80x25 at C000h with the letter A.
;
; Then we unlock the Arnold 5 features which will make the IO register page
; appear at location 4000h..7FFFh.
;
; We set the pointer to the second screen to 4000h and then enter a loop syncd
; with frame flyback which on each F/F increments (and later decrements) the
; split sreen line.
;
        ld      c,'0'
        call    _SplitFillScreenC       ;fill with BBBBs

        ld      hl,0C000h
        ld      de,04000h
        ld      bc,04000h
;        ldir                            ;copy screen low
_SplitInvertAndCopy:
        ld      a,(hl)
        xor     0ffh
        ld      (de),a
        inc     hl
        inc     de
        dec     bc
        ld      a,b
        or      c
        jr      nz,_SplitInvertAndCopy

        ld      c,'A'
        call    _SplitFillScreenC       ;fill with AAAAs

        call    UnlockArn5              ;make IO page appear at 4000h..

        ld      bc,0BC05h
        out     (c),c                   ;make 6845 ready for vertical total adjust

        ld      hl,0010h                ;4000 wrong way round cos 6802 is
        ld      (?SplitSecondAddr),hl   ;keep a copy
        ld      (6802h),hl              ;tell ULA where second screen is

        ld      a,0
        ld      (?SplitScreenLine),a    ;reset variable that gos 0..199..0
        ld      a,1
        ld      (?SplitIncrement),a     ;we'll count up (+1) and later dn (-1)

        ld      bc,0F500h               ;8255 port B (bit 0 is f/f)
_SplitWaitFFLow:
        in      a,(c)
        bit     0,a
        jr      nz,_SplitWaitFFLow      ;need to see it low

_SplitWaitFFHigh:
        in      a,(c)
        bit     0,a
        jr      z,_SplitWaitFFHigh      ;then wait for the low to high edge

_SplitDisplayMainLoop:
        ld      bc,0F500h
_SplitMainWaitFFHigh:
        in      a,(c)                   ;first time thru we have just seen FF
        bit     0,a                     ;so this will fall thru. On subsequent
        jr      z,_SplitMainWaitFFHigh  ;loops it'll wait till FF leading edge

        ld      a,(?SplitScreenLine)
        cp      37h                     ;that "magical" value !
        jr      nz,_SplitNoFixProblem
        ld      bc,0BD01h
        out     (c),c                   ;set vert. total adjust up 1
        jr      _SplitProblemFixed
_SplitNoFixProblem:
        ld      bc,0BD00h
        out     (c),c                   ;set vert total adjust to normal
_SplitProblemFixed:
        ld      (06801h),a              ;set current split
        ld      b,a
        ld      a,(?SplitIncrement)
        add     b                       ;so A has new line value
        ld      (?SplitScreenLine),a
        push    af
        and     7
        cp      0
        jr      nz,_SplitNoAdjustOffsetDown
        ld      a,(?SplitIncrement)
        cp      1
        jr      nz,_SplitNoAdjustOffset
        push    de
        ld      hl,(?SplitSecondAddr)
        ld      a,h
        ld      h,l
        ld      l,a                     ;switch hl cos its not Z80 order
        ld      de,40
        add     hl,de
        ld      a,h
        ld      h,l
        ld      l,a                     ;switch hl back again
        ld      (6802h),hl
        ld      (?SplitSecondAddr),hl
        pop     de
_SplitNoAdjustOffsetDown:
        cp      5                       ;well we might be going 7..0
        jr      nz,_SplitNoAdjustOffset
        ld      a,(?SplitIncrement)
        cp      -1
        jr      nz,_SplitNoAdjustOffset
        push    de
        ld      hl,(?SplitSecondAddr)
        ld      a,h
        ld      h,l
        ld      l,a                     ;switch hl cos its not Z80 order
        ld      de,40
        xor     a                       ;clear carry
        sbc     hl,de
        ld      a,h
        ld      h,l
        ld      l,a                     ;switch hl back again
        ld      (6802h),hl
        ld      (?SplitSecondAddr),hl
        pop     de

_SplitNoAdjustOffset:
        pop     af
        cp      200                     ;have we reached limit yet ?
        jr      z,_SplitChangeDirection
        cp      0
        jr      z,_SplitChangeDirection
        jr      _SplitNotAtMax

_SplitChangeDirection:
        ld      a,(?SplitIncrement)
        neg                             ;if it's 1 make -1 and vv
        ld      (?SplitIncrement),a
        cp      1
        jr      z,_SplitEndTest

_SplitNotAtMax:
        call    KeyboardReadNoDelay
        cp      0FFh
        jr      nz,_SplitEndTest
        ld      bc,01000h
_SplitWaitABit:
        dec     bc
        ld      a,b
        or      c
        jr      nz,_SplitWaitABit
        jp      _SplitDisplayMainLoop


_SplitEndTest:
        xor     a
        ld      (6801h),a               ;switch split off

        call    RelockArn5

        xor     a                       ;carry clear cos there is no error
        ret

;=================
_SplitFillScreenC:
;=================
;
; This next bit just draws 80 by 25 characters to fill the current screen mode.
;
        ld      d,0                     ;character row 0
_SplitPrintCharRowLoop:
        ld      e,0                     ;column 0
_SplitPrintCharColLoop:
        push    de
        push    bc
        call    SetCursorPos            ;start at (0,0) gonna fill #

        pop     bc
        push    bc
        ld      a,c
        ld      b,2
        call    ScreenPrintChar
        pop     bc
        pop     de
        inc     e                       ;step onto next column
        ld      a,40
        cp      e                       ;hit edge yet ?
        jr      nz,_SplitPrintCharColLoop
        inc     c                       ;step char on one for each line
        inc     d                       ;step down a row
        ld      a,d
        cp      25
        jr      nz,_SplitPrintCharRowLoop
        ret



        END
