$PAGINATE
$title(Arnold 5 test)
$subtitle(Test of screen line raster interrupt mechanism)
$copyright(Copyright (c) 1989, 1990, Amstrad plc.)
$pagewidth=131

        PUBLIC  RasterInterruptTest     ;called indirectly from TESTPACK
                                        ; out of MainMenuTable


        EXTERN  ScreenResetPalette      ;SUPPORT
        EXTERN  SetCursorPos            ;SUPPORT
        EXTERN  PrintAHex               ;SUPPORT
        EXTERN  KeyboardReadNoDelay     ;SUPPORT
        EXTERN  UnlockArn5              ;SUPPORT
        EXTERN  RelockArn5              ;SUPPORT

        EXTERN  .RasterRainbow          ;MESSAGES

        EXTERN  ?IntVectorTable         ;TESTVARS
        EXTERN  ?RasterIntLine          ;TESTVARS
        EXTERN  ?RasterIncrement        ;TESTVARS
        EXTERN  ?RasterIntHappened      ;TESTVARS

        DEFSEG  TestCode, CLASS=CODE

        SEG     TestCode

;===================
RasterInterruptTest:
;===================
;
; The video circuitry in the ASIC can be programmed to generate an interrupt
; on any video scan line. By using the Z80 vectored interrupt mode 2 we can
; have transfer controlled to a fixed routine when a particluar scan line
; is reached.
;
; This test aims to test that feature as follows. The screen will be drawn in
; MODE 1 with the whole screen set to PEN 0 (background color). A sync with FF
; will be made at which point all the palette registers are filled with the
; same color (white say). Interrupts are then enabled and at a programmed
; moment in the scan an interrupt will go off to direct control to my
; _RasterInterruptHandler. This will switch the PEN 0 entry in the palette to
; an exciting new color and count on the ole fingers for a while to give a
; chance to see the colored strip. At the end of this period the palette will
; be switched back to the original background color.
;
; On sucessive flame frybacks the interrupting scan line will be incremented
; so the the stripe will be seen to slowly travel from the top to the bottom
; of the screen.
;
; The address of the routine to be run when a interrupt occurs in IM2 is as
; follows:
;
;       (Z80 I register) << 8 + (6805h) & 0F8h + 6 {if raster int}
;
; I want to set it up to be "_IM2VectorTable" so set:
;
;       I = (_IM2VectorTable & FF00) >> 8 [ld hl,VectTab; ld a,h; ld i,a]
;       (6805) = _IM2VectorTable & 0F8h
;
; The interrupt vector table then holds:
;
;       dw      dummy   (DMA chan 0 interrupt)
;       dw      dummy   (DMA chan 1 interrupt)
;       dw      dummy   (DMA chan 2 interrupt)
;       dw      _RasterInterruptHanlder
;
; On entry the screen is in MODE 2 and is filled with PEN 0.
;

        call    UnlockArn5


        ld      hl,_IM2VectorTable
        ld      de,?IntVectorTable
        ld      bc,8
        ldir                            ;copy out to RAM at 8000h so that we
                                        ;can be sure that bottom 3 bits of table
                                        ;address are 0 when programming 6805.

        ld      hl,?IntVectorTable      ;I know this is 8000h
        ld      a,h
        ld      i,a                     ;set I reg to top half of table address

        ld      a,l                     ;get low half
        and     0F8h                    ;clear bottom 3 bits
        or      1
        ld      (6805h),a               ;set ASIC vector register

        im      2                       ;use vectored interrupt mode

        ld      a,1                     ;start at scan line 1
        ld      (?RasterIntLine),a
        ld      (6800h),a               ;set intial scan line for interrupt

        ld      a,1
        ld      (?RasterIncrement),a

_RastDisplayMainLoop:

        ld      hl,?RasterIntHappened
        ld      a,0
        ld      (hl),a                  ;clear flag

_RastWaitInterrupt:
        ei                              ;let the interrupt occur

        call    KeyboardReadNoDelay
        cp      0ffh
        jp      nz,_RasterEndTest
        jr      _RastNoKey

;        cp      66                      ;ESC
;        jp      z,_RasterEndTest
;        cp      76                      ;Joy 0 fire
;        jp      z,_RasterEndTest
;        cp      0                       ;cursor up
;        jr      z,_RasterUp
;        cp      72                      ;joy 0 up
;        jr      z,_RasterUp
;        cp      2                       ;cursor down
;        jr      z,_RasterDown
;        cp      73                      ;joy 0 down
;        jr      z,_RasterDown
;        jr      _RastWaitInterrupt

;_RasterUp:
;        ld      a,(?RasterIntLine)
;        dec     a
;        jr      z,_RastWaitInterrupt    ;can't go above line 1
;        ld      (?RasterIntLine),a
;        ld      (6800h),a
;        jr      _RastWaitInterrupt

;_RasterDown:
;        ld      a,(?RasterIntLine)
;        inc     a
;        cp      200
;        jr      z,_RastWaitInterrupt    ;can't go below line 200
;        ld      (?RasterIntLine),a
;        ld      (6800h),a
;        jr      _RastWaitInterrupt


_RastNoKey:
        ld      hl,?RasterIntHappened
        xor     a
        cp      (hl)
        jr      z,_RastWaitInterrupt    ;loops here until Int has done its bit

        di
        ld      a,(?RasterIntLine)
        ld      b,a
        ld      a,(?RasterIncrement)
        add     b
        ld      (?RasterIntLine),a
        ld      (6800h),a
        cp      200                     ;reached scan line 200 yet ?
        jr      z,_RasterChangeDirection
        cp      1
        jr      z,_RasterChangeDirection
        jr      _RastDisplayMainLoop

_RasterChangeDirection:
        ld      a,(?RasterIncrement)
        neg
        ld      (?RasterIncrement),a
        cp      1
        jr      z,_RasterEndTest
        jr      _RastDisplayMainLoop

_RasterEndTest:
        di
        im      1                       ;back to normal interrupt mode

        ld      a,0
        ld      (6800h),a               ;set raster int to off again

        call    RelockArn5

        call    ScreenResetPalette

        ret


_RasterInterruptHandler:
;
; this code is entered when the raster interrupt goes off.
;
        nop
        nop
        nop
        nop

        nop
        nop
        nop
        nop

        nop
        nop
        nop
        nop

        nop
        nop
        nop
        nop
        push    af
        push    bc
        push    de
        push    hl

        ld      hl,.RasterRainbow
        ld      e,8                     ;colors in a rainbow

_RastIntDrawRainbow:
        ld      bc,07F00h
        out     (c),c                   ;point at PEN 0 palette entry
        ld      a,(hl)                  ;get color for stripe
        inc     hl                      ;point at next color in stripes
        or      a,40h                   ;bit for setting palette entry
        out     (c),a                   ;set PEN 0 to bright white

        ld      bc,45h                  ;long enuff for stripe to be seen.
_RastIntDelay:
        dec     bc
        ld      a,b
        or      c
        jr      nz,_RastIntDelay
        nop
        nop
        nop
        nop
        nop
        nop

        dec     e
        jr      nz,_RastIntDrawRainbow

        ld      a,0FFh
        ld      (?RasterIntHappened),a  ;flag that we have done our party piece

        pop     hl
        pop     de
        pop     bc
        pop     af
        ret

_IM2VectorTable:
        dw      _RasterInterruptHandler
        dw      _RasterInterruptHandler
        dw      _RasterInterruptHandler
        dw      _RasterInterruptHandler

        END
