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

        PUBLIC  SoftScrollTest          ;called indirectly from TESTPACK
                                        ; out of MainMenuTable

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

        DEFSEG  TestCode, CLASS=CODE

        SEG     TestCode

;==============
SoftScrollTest:
;==============
;
; I think I understand how this works !- just !
;
; There are actually two  separate mechanisms to be tested here. Horizontal
; pixel scroll (soft scroll is a bad name cos its actually done in h/w) and
; vertical pixel scroll.
;
; I will test the two separately. Horiz. first, then vert.
;
; For horiz. what the hardware will do for us is reduce the number of displayed
; bytes (char columns in MODE 2) to 78. Leaving C000h,C0001h, C800h,C801h, etc
; not displayed.
;
; As the 4 bit counter is increased the screen moves slowly to the right. The
; bits dropping off the right border actually wrap round into the first column
; that is hidden behind the border. The new data appearing at the left comes
; out of the bytes that make up the second column.
;
; Once 8 moves have been made, the whole of the first column contains discarded
; data and can be re-drawn.
;
; Once 16 moves have been made we have exposed the 2 columns of hidden
; characters. We now need to set te counter back to 0 (cos its only 4 bits) but
; if we did just that then the screen would just jump back to how it was
; originally so at the same time we also need to move the 6845 offset on to
; jump the screen 2 columns to the right.
;
; This scheme sounds totally plausible but the nigger in the wood pile is that
; my print character routines are firmly C000h based. What I'll do, therefore
; is just poke the data direct, making full character columns (byte wide) of
; a random byte each time. This will make the effect look like various
; patterned stripes moving across the screen from left to right.
;
; The address of the top right corner will go thru the following sequence on
; each of the 8 bit shifts:
;
;       C000h,
;
        ld      a,2
        call    ScreenSetMode           ;in MODE 2 we see most movement !

        call    UnLockArn5

;
; next bit stolen from MODES
;
        ld      a,32                    ;start at "@" character on 1st line
        ld      b,25                    ;number of lines to print
        ld      c,0
_Mode2CharlineLoop:
        push    bc                      ;and line counter
        push    af                      ;save start char

        ld      d,c
        ld      e,0
        call    SetCursorPos

        pop     af
        push    af

        ld      b,80                    ;number of chars on a line
_Mode2DoALine:
        push    bc                      ;store character count
        push    af                      ;save current character
        call    ScreenPrintChar         ;(SUPPORT) print it
        pop     af                      ;retrieve current character
        inc     a                       ;step char up as we do a line
        pop     bc                      ;retrieve char count
        djnz    _Mode2DoALine

        pop     af                      ;and starting character
        pop     bc                      ;get line counter
        inc     a                       ;next line starts with next char
        inc     c                       ;step row counter on
        djnz    _Mode2CharLineLoop

        ld      a,1
        call    DelayASeconds

        ld      a,80h                   ;bring border in by 2
        ld      (6804h),a

        ld      bc,0BC06h
        out     (c),c                   ;point at 6845 vertical displayed reg

        ld      bc,0BD18h               ;normally its 19h (25), make it 24
        out     (c),c                   ;brings bottom border up

        ld      b,4
_SSMainLoop:
        push    bc

        ld      d,80h                   ;Starting value for SSCR value
        ld      e,1                     ;the amount to add
        ld      h,90h                   ;value to stop before doing
        call    _SSMoveMainLoop

        ld      d,8Fh                   ;where we'd got to
        ld      e,10h                   ;offset to add
        ld      h,0Fh                   ;up to but not including this
        call    _SSMoveMainLoop

        ld      d,0FFh                  ;border in, X and Y at limit
        ld      e,-1                    ;going back across to right
        ld      h,0EFh
        call    _SSMoveMainLoop

        ld      d,0F0h
        ld      e,-10h                  ;back up
        ld      h,70h
        call    _SSMoveMainLoop

        call    KeyboardReadNoDelay
        cp      0ffh
        jr      z,_SSNoKeyPressed
        pop     bc                      ;clear stack
        jp      _SSEndTest

_SSNoKeyPressed:
        pop     bc
        djnz    _SSMainLoop

        jp      _SSEndTest



_SSMoveMainLoop:
        ld      bc,0F500h
_SSWaitFFHigh:
        in      a,(c)                   ;first time thru we have just seen F/F
        bit     0,a                     ;so this will fall thru. On subsequent
        jr      z,_SSWaitFFHigh         ;loops it'll wait till FF leading edge
;
; At this moment we are syncd with the start of frame flyback. It lasts for 8
; scan lines (=2000 T-States)
;
        ld      a,d
        ld      (6804h),a
        add     a,e                     ;e=10
        ld      d,a
        cp      h
        ret     z

        ld      bc,2000h
_SSBigDelay:
        dec     bc
        ld      a,b
        or      c
        jr      nz,_SSBigDelay
        jr      _SSMoveMainLoop


_SSEndTest:
        ld      a,0
        ld      (6804h),a               ;make sure we're back to normal

        ld      bc,0BC06h
        out     (c),c

        ld      bc,0BD19h
        out     (c),c                   ;make vertical displayed = 25 again

        ld      a,1
        call    DelayASeconds

        call    ReLockArn5
        ret


        END
