                name    window
                page    ,132

                title   BIOS Window Extension V1.1

comment         \

                Copyright 1984 John J. Seal

                The Graphic Software Company
                348 East Pratt Street
                Franklin, IN 46131

                This program may be used for any non-commercial purpose
                provided that this copyright notice is included.
                Commercial use is forbidden without the express written
                consent of The Graphic Software Company.

                This program allows a window to be defined on the display.
                All programs which use the BIOS Write TTY call for output
                will work within the window. Other BIOS calls may still be
                used for I/O to arbitrary screen positions.

                The window is defined by a pair of coordinates specified on
                the command line. The only absolute format requirements are
                that each coordinate pair start with a left parenthesis and
                be separated with a comma. Everything else is optional. The
                suggested command format is:

                window (ur,lc) to (lr,rc)

                ur = upper row
                lc = left column
                lr = lower row
                rc = right column

                The new functions serviced by the video interrupt (int 10)
                and their corresponding function codes are:

                ah = 14 Write TTY
                ah = 16 Set window coordinates
                ah = 17 Get window coordinates
                ah = 18 Get blanking attribute

                \

code            segment
                org     100h                            ;For COM conversion

                assume  cs:code

DOS_entry       label   far                             ;DOS entry point
                jmp     install

upper_left      label   word                            ;Window coordinates
left            db      0
upper           db      0
lower_right     label   word
right           db      79
lower           db      24

old_int         dd      ?                               ;Old interrupt vector

comment         \

                The new interrupt procedure first filters out the new
                services from the old, and passes all old service calls
                back to the BIOS.

                \

interrupt       proc    far
                sti
                cmp     ah,14                           ;Write TTY
                je      write_tty
                cmp     ah,16                           ;Set window
                je      set_window
                cmp     ah,17                           ;Get window
                je      get_window
                cmp     ah,18                           ;Get blanking
                je      get_blanking
bios:           jmp     old_int

comment         \

                Set window coordinates.

                This function call sets the coordinates of a window in the
                display area. The window is defined by specifying the upper
                left and lower right corners in terms of screen coordinates.
                The upper left corner of the screen is position (0,0). The
                specified corners are included in the window area.

                If the specified coordinates are legal then the window is
                cleared, the cursor is homed to the upper left corner, and
                al = 0. Otherwise, no action is taken and al = 1.

                Entry:  ah = 16 (function code)
                        cx = upper left corner
                        dx = lower right corner
                Exit:   al = fail flag (see above)

                All registers preserved except ax.

                \

set_window:     push    bx                              ;Save registers
                push    cx
                push    dx
                mov     al,1
                cmp     ch,dh                           ;Check coordinates
                ja      exit
                cmp     cl,dl
                ja      exit
                mov     upper_left,cx                   ;Update coordinates
                mov     lower_right,dx
                mov     ah,18                           ;Read blank attribute
                int     10h
                mov     ax,600h                         ;Blank entire window
                int     10h
                mov     ah,15                           ;Read current page
                int     10h
                mov     dx,cx                           ;Home cursor
                mov     ah,2
                int     10h
                mov     al,0
exit:           pop     dx                              ;Restore registers
                pop     cx
                pop     bx
                iret

comment         \

                Get window coordinates.

                This function call returns the coordinates of the upper left
                and lower right corners of the current display window.

                Entry:  ah = 17 (function code)
                Exit:   cx = upper left corner
                        dx = lower right corner

                All registers preserved except cx and dx.

                \

get_window:     mov     cx,upper_left                   ;Read coordinates
                mov     dx,lower_right
                iret

comment         \

                Get blanking attribute.

                This function call returns the attribute of the character
                at the current cursor position, if in alpha mode, or the
                background color (0) if in graphics mode. The resulting
                attribute is meant to be used when scrolling the screen.

                Entry:  ah = 18 (function code)
                Exit:   bh = blanking attribute

                All registers preserved except bx.

                \

get_blanking:   push    ax                              ;Save registers
                mov     ah,15                           ;Read current page
                int     10h
                xor     ah,ah                           ;Background color
                cmp     al,3                            ;Check for alpha modes
                jbe     alpha
                cmp     al,6                            ;Check for graphics
                jbe     graphics
alpha:          mov     ah,8                            ;Read attribute
                int     10h
graphics:       mov     bh,ah                           ;Return attribute
                pop     ax
                iret

comment         \

                Write TTY.

                This function call replaces the old call of the same name.
                It performs the same functions but allows the current window
                to be user defined instead of the whole screen.

                Entry:  ah = 14 (function code)
                        al = character to write
                        bh = page number to write on
                        bl = foreground color (in graphics modes)

                All registers preserved.

                \

write_tty:      cmp     al,7                            ;Let BIOS ring the bell
                je      bios
                push    ax                              ;Save registers
                push    bx
                push    cx
                push    dx
                push    ax                              ;Save character
                mov     ah,3                            ;Read cursor position
                int     10h
                pop     ax                              ;Recover character

;               Check for unprintable control characters

                cmp     al,8                            ;Backspace
                je      bs
                cmp     al,10                           ;Line feed
                je      lf
                cmp     al,13                           ;Carriage return
                je      cr

;               Character is printable

                mov     cx,1                            ;Print character
                mov     ah,10
                int     10h
                inc     dl                              ;Advance cursor
                cmp     dl,right
                jbe     set_cursor

;               Right edge of window exceeded - wrap to next line

                mov     dl,left
lf:             inc     dh
                cmp     dh,lower
                jbe     set_cursor

;               Lower edge of window exceeded - scroll window up

                push    bx                              ;Save page
                mov     ah,18                           ;Read blank attribute
                int     10h
                mov     cx,upper_left                   ;Scroll window up
                mov     dx,lower_right
                mov     ax,601h
                int     10h
                pop     bx                              ;Restore page

;               Return cursor to left-hand edge

cr:             mov     dl,left                         ;Carriage return

;               Set cursor to new position

set_cursor:     mov     ah,2                            ;Set cursor
                int     10h
                pop     dx                              ;Restore registers
                pop     cx
                pop     bx
                pop     ax
                iret

;               Backspace does not wrap past left edge of window

bs:             dec     dl                              ;Back up
                cmp     dl,left                         ;Past left edge?
                jb      cr                              ;Yes, reset cursor
                jmp     set_cursor                      ;No, leave it alone

interrupt       endp

greeting        db      13,10
                db      218,30 dup (196),191,13,10
                db      179,' The Graphic Software Company ',179,13,10
                db      179,'  BIOS Window Extension V1.1  ',179,13,10
                db      192,30 dup (196),217,13,10,'$'

error_msg       db      13,10,'Invalid window coordinates',13,10,'$'

comment         \

                The install procedure is invoked through the DOS entry point
                when the program is first run. It installs the new interrupt
                and prints a message on the console. When done, it returns to
                DOS and allows the space it occupies itself to be reclaimed.

                The program first tests whether the BIOS extensions are already
                installed. If they are not, this can be detected by the fact
                that a call to an illegal function will return without altering
                any registers.

                \

                assume  ds:code

install         proc    near
                mov     ah,17                           ;Read coordinates
                int     10h
                inc     cl                              ;Alter their value
                mov     al,cl
                int     10h                             ;Read them again
                cmp     al,cl                           ;Test for difference
                pushf
                jne     installed

;               Install BIOS extensions

                mov     dx,offset greeting              ;Report installation
                mov     ah,9
                int     21h
                mov     ax,3510h                        ;Read old interrupt
                int     21h
        mov word ptr [old_int],bx   ;Save old interrupt
        mov word ptr [old_int+2],es
                mov     dx,offset interrupt             ;Install new interrupt
                mov     ax,2510h
                int     21h

;               BIOS extensions are installed now

installed:      push    cs                              ;Point to command tail
                pop     es
                mov     di,81h
                mov     cx,7fh                          ;Read coordinates
                mov     al,'('
                repne   scasb                           ;Find first pair
                call    num_pair
                push    dx
                repne   scasb                           ;Find second pair
                call    num_pair
                pop     cx
                mov     ah,16                           ;Set coordinates
                int     10h
                or      al,al                           ;Test legality
                jz      legal

;               Window coordinates are illegal

                mov     dx,offset error_msg             ;Print error message
                mov     ah,9
                int     21h

;               Terminate program in appropriate manner

legal:          popf                                    ;Check residency
                jne     resident
                mov     dx,offset greeting              ;Make resident
                int     27h

resident:       int     20h                             ;Already resident

num_pair        proc    near
                push    bx
                call    number                          ;Read first number
                mov     bh,dl
                call    number                          ;Read second number
                mov     dh,bh
                pop     bx
                ret                                     ;Row/Col pair in dx
num_pair        endp

number          proc    near
                push    ax
                push    bx
                mov     al,' '                          ;Skip leading blanks
                repe    scasb
                dec     di
                mov     bl,10                           ;Decimal multiplier
                xor     ax,ax
                xor     dx,dx
digit:          xchg    ax,dx                           ;Multiply by 10
                mul     bl
                add     ax,dx                           ;Add new digit
                xchg    ax,dx
                mov     al,es:[di]                      ;Read next character
                inc     di
                sub     al,'0'                          ;Normalize it
                cmp     al,'9'                          ;Check for digits
                jbe     digit
                pop     bx
                pop     ax
                ret                                     ;Number in dx
number          endp

install         endp

code            ends
                end     DOS_entry                       ;Must be far label
