;***************************************************************************
;This program intercepts Video I/O routine.Commands to scroll the screen and
;are intercepted,allothers passed through. This routine is attached to DOS.
;***************************************************************************
;***** ***** ***** ***** ***** scrlky.asm ***** ***** ***** ***** ***** *****
;-----------------------------------------------------------------------------
;INTERRUPT VECTORS FOR VIDEO AND KEYBOARD FUNCTIONS
;---------------------------------------------------------------------------
VECTORS SEGMENT AT 0
        ORG     10H*4
VIDEO_INT       LABEL   DWORD
        ORG     16H*4
KEYBOARD_INT    LABEL   DWORD
VECTORS ENDS
;
ROM_BIOS_DATA   SEGMENT AT  40H
        ORG     17H
KB_FLAG DB      ?               ;bit 4 set for scroll lock
ROM_BIOS_DATA   ENDS
;---------------------------------------------------------------------------
;Initialize vectors and attach to DOS
;---------------------------------------------------------------------------
CSEG    SEGMENT PARA
        ASSUME  CS:CSEG
        ORG     100H
BEGIN:  JMP     INIT_VECTORS    ;Initialize INT 10H and attach to DOS
;----------------------------------------------------------------------------
;These memory locations store addresses of ROM routines for Video&KB I/O
;----------------------------------------------------------------------------
ROM_VIDEO_IO    DD              ;address of ROM routines
ROM_KEYBOARD_IO DD
SCROLL_COUNT    DB      0       ;no. lines scrolled since last pause
LAST_LOCK_STATE DB      0       ;scroll by 23 lines leaving one old line
MAX_LINES       DB      23      ;at the top of the screen
LAST_LINE       DB              ;last line the cursor was one
;----------------------------------------------------------------------------
;This routine intercepts calls to Video I/O routine in ROM
;Scroll Lock
;      OFF      This routine passes control directly to ROM BIOS
;      ON       Functions other than Scroll Up orScroll down are passed
;               directly to ROM routines. Otherwise,this routine increments
;               the scroll count and checks to see if it esceeds the page
;               size of 25 lines. If so, loop until either shift key is
;               pressed.
;                       left shift - allows scroll of entire window
;                       right shift- scroll one line
;----------------------------------------------------------------------------
INTERCEPT_VIDEO PROC    FAR
        ASSUME  CS:CSEG
        STI                     ;turn on interrupts again
        PUSH    DS              ;save registers used
        PUSH    BX      
        PUSH    AX
        ASSUME  DS:ROM_BIOS_DATA
        MOV     BX,ROM_BIOS_DATA
        MOV     DS,BX
        MOV     AL,KB_FLAG      ;check state of scroll lock key
        AND     AL,10H          ;pick off scroll lock bit
        ASSUME  DS:CSEG
        MOV     BX,CS           ;Data segment for variables above
        MOV     DS,BX
        CMP     AL,LAST_LOCK_STATE
        JE      UN_CHANGED      
        MOV     BL,MAX_LINES    ;scroll lock key has changed,set to
        MOV     SCROLL_COUNT,BL ;MAX_LINES to stop scrolling
        MOV     LAST_LOCK_STATE,AL      ;Save new scroll lock state
        PUSH    CX              ;read current cursro position
        PUSH    DX      
        PUSH    AX
        MOV     AH,3
        MOV     BH,0
        PUSHF
        CALL    ROM_VIDEO_IO    ;find old cursor position
        MOV     LAST_LINE,DH
        POP     AX
        POP     DX
        POP     CX
UN_CHANGED:
        XCHG    AX,BX           ;Recover function(AH) and retain scroll lock
        POP     AX
        OR      BL,BL           ;is scroll lock on?
        JZ      TO_VIDEO_IO     ;no, jump to ROM video I/O
;----------------------------------------------------------------
;Scroll Lock On
;----------------------------------------------------------------
        CMP     AH,2    ;check for SET CURSOR POSITION function
        JNE     NOPE
        CMP     DH,LAST_LINE    ;is cursor beingmoved to next line?
        MOV     LAST_LINE,DH    ;save new cursor line
        JLE     TO_VIDEO_IO     ;no, go to ROM
        JMP     SHORT CHECK_LOCK        ;yes,see if need to lock
NOPE:   CMP     AH,6            ;scroll up?
        JNE     TO_VIDEO_IO     ;no, ok to scroll
                                ;yes,can't until shit key hit
CHECK_LOCK:
        INC     SCROLL_COUNT    ;take care of scroll lock
        MOV     BH,MAX_LINES
        CMP     SCROLL_COUNT,BH ;have we scrolled more than MAX_LINES
        JL      TO_VIDEO_IO     ;no,its OK to scroll
                                ;yes,can't scroll till shift key hit
        MOV     BL,BH           ;set scroll count to MAX_LINES-1
        DEC     BL              ;so can print onemore line
        MOV     SCROLL_COUNT,BL
        ASSUME  DS:ROM_BIOS_DATA
        MOV     BX,ROM_BIOS_DATA
        MOV     DS,BX
LOOP:   MOV     BL,KB_FLAG      ;wait until right orleft shift key hit
        TEST    BL,10H          ;is scroll lock still on?
        JZ      TO_VIDEO_IO
        AND     BL,3            ;pick off shift key info
        JZ      LOOP            ;stay in loop until shift key pushed
        CMP     BL,1            ;RIGHT SHIFT KEY HIT?
        JE      SCROLL_LINE     ;yes, scroll one line
                                ;no,must be right shift key,reset scroll ct.
        XOR     BX,BX
        MOV     SCROLL_COUNT,BL
SCROLL_LINE:
;
TO_VIDEO_IO:
        POP     BX
        PUSHF
        CALL    ROM_VIDEO_IO
        POP     DS
        IRET
INTERCEPT_VIDEO ENDP
;
;----------------------------------------------------------------------------
;If the KB function calls for a read (AH=0),then reset scroll count
;---------------------------------------------------------------------------
INTERCEPT_KEYBOARD      PROC    FAR
        ASSUME  CS:CSEG,DS:CSEG
        STI
        PUSH    DS                ;save registers used this routine
        PUSH    BX
        MOV     BX,CS
        MOV     DS,BX
        OR      AH,AH             ;check to see if AH=0-read character
        JNZ     KB1               ;no,brancj off to KB I/O
        XOR     BX,BX             ;yes,set scroll count to 0
        MOV     SCROLL_COUNT,BL
KB1:    POP     BX
        ASSUME  DS:NOTHING
        POP     DS
        JMP     ROM_KEYBOARD_IO
INTERCEPT_KEYBOARD      ENDP
;-----------------------------------------------------------------------
;This section saves old interrupt vectors for KB and Video I/O.These vectors
;are replaced by addresses of INTERCEPT_VIDEO & INTERCEPT_KEYBPARD
;----------------------------------------------------------------------
INIT_VECTORS    PROC    NEAR
        ASSUME  CS:CSEG,DS:CSEG
        MOV     AH,3            ;set LAST_LINE to cursor line number
        XOR     BH,BH
        INT     10H
        MOV     LAST_LINE,DH
;
        ASSUME  CS:CSEG,DS:VECTORS
        MOV     AX,VECTORS
        MOV     DS,AX
;
        MOV     AX,VIDEO_INT    ;save address of ROM routines
        MOV     ROM_VIDEO_IO,AX
        MOV     AX,VIDEO_INT[2]
        MOV     ROM_VIDEO_IO[2],AX
        MOV     AX,OFFSET INTERCEPT_VIDEO       ;set video INT 10H to point
        MOV     VIDEO_INT,AX                    ;to INTERCEPT_VIDEO above
        MOV     VIDEO_INT[2],CS
;
        MOV     AX,KEYBOARD_INT         ;save address of the ROM routines
        MOV     ROM_KEYBOARD_IO,AX
        MOV     AX,KEYBOARD_INT[2]
        MOV     ROM_KEYBOARD_IO[2],AX
        MOV     AX,OFFSET INTERCEPT_KEYBOARD    ;set KB INT 16H to point to
        MOV     KEYBOARD_INT,AX                 ;INTERCEPT_KEYBOARD above
        MOV     KEYBOARD_INT[2],CS
;
        MOV     DX,OFFSET INIT_VECTORS          ;end of resident portion
        INT     27H                             ;terminate but stay resident
INIT_VECTORS    ENDP
;
CSEG    ENDS
        END     BEGIN

        
