; HOWARD SWINEHART
; INT9.ASM - Demonstrates videogame INT 9h handler.
;            Use arrows to draw on screen.  Press ESC to quit.

code    segment para public 'code'
        assume cs:code, ds:code, es:code, ss:code
        org 100h
main:
    jmp start
ESCKEY  equ     1               ; Escape key scancode
LEFT    equ     4bh             ; Left arrow
RIGHT   equ     4dh             ; Right arrow
UP      equ     48h             ; Up arrow
DOWN    equ     50h             ; Down arrow

oldint9     dw  0,0             ; Original int 9h pointer
keytable    db  128 dup(0)      ; Key state table

start:
    mov     al,09h              ; Get INT 09h address
    mov     ah,35h
    int     21h
    mov     [oldint9],bx        ; Save it for later
    mov     [oldint9+2],es

    mov     al,09h              ; Set new INT 09h
    mov     dx,offset newint9   ; DS:DX = new interrupt
    mov     ah,25h
    int     21h
;----- MAIN PROGRAM BEGINS HERE -----
    mov     ax,0a000h           ; Point to VGA segment
    mov     es,ax
    mov     ax,13h              ; Set graphics mode
    int     10h

    mov     di,32160            ; Place dot at center of screen
keyloop:
    test    [keytable+ESCKEY],1 ; Is ESC held down?
    jnz     exit                ; Yes, exit
k1:
    test    [keytable+LEFT],1   ; Is left arrow down?
    jz      k2                  ; No, continue
    dec     di                  ; Yes, move line left
k2:
    test    [keytable+RIGHT],1  ; Is right arrow down?
    jz      k3                  ; No, continue
    inc     di                  ; Yes, move line right
k3:
    test    [keytable+DOWN],1   ; Is down arrow down?
    jz      k4                  ; No, continue
    add     di,320              ; Yes, move line down
k4:
    test    [keytable+UP],1     ; Is up arrow down?
    jz      k99                 ; No, continue
    sub     di,320              ; Yes, move line up
k99:
    inc     al                  ; Increment color
    and     al,31               ; Stay within range 0 - 31
    add     al,32               ; Point to interesting colors
    mov     es:[di],al          ; Draw dot

    mov     cx,1000h           ; Delay.  Remove this for higher speed.
delay:
    loop    delay
    jmp     keyloop             ; Loop back and do it all again
;----- PROGRAM EXITS HERE -----
exit:
    mov     al,09h              ; Restore original INT 09h
    mov     dx,[oldint9]
    mov     ds,[oldint9+2]      ; Move old INT 09H pointer to DS:DX
    mov     ah,25h
    int     21h

    mov     ax,03h              ; Restore text mode
    int     10h
    mov     ax,4c00h            ; Return to DOS
    int     21h
;
;        NEW INT 09H HANDLER
newint9:
    push    ax                  ; Save regs
    push    bx

    in      al,60h              ; Get scan code
    mov     bl,al               ; bl = scan code
    and     bx,127              ; BX = scan code - high bit
    and     [bx+keytable],0feh  ; Zero key's flag
    test    al,128              ; Is it a key release?
    jnz     exit9               ;   Yes, exit
    or      [bx+keytable],1     ;   No, set key's flag
exit9:
    mov     al,20h              ; Signal end of interrupt
    out     20h,al

    pop     bx
    pop     ax                  ; Restore regs
    iret
code    ends
end     main
