
; NOTE : This template is for .COM files only do not use for .EXE files!!


;
;
;
;       Copyright 1986 by Dana Nowell - All rights reserved
;
; HISTORY:
;     Version     Date         Name            Description
;       1.0     11/10/86        dn      first cut
;       1.01    11/11/86        dn      masked all foreground colors
;                                       either on or off
;       1.02    11/14/86        dn      masked all background colors
;                                       either on or off
;       1.03    11/22/86        dn      added check for already resident
;       1.04    11/23/86        dn      fixed bug with black on black displays
;       1.05    11/30/86        dn      set color suppressed mode at install
;                                       incase program checks.
;                                       moved copyright message to after
;                                       equipment check call so monochrome
;                                       can be properly determined
;       1.06    12/27/86        dn      trapped for pixel and tty writes
;                                       moved color remap to a subroutine
;                                       added mode variable to trap for
;                                       graphics mode differences
;       1.07    03/12/87        dn      trapped for dark grey on black
;

title   SUPPRESS.ASM



        NULL            equ     00h
        BELL            equ     07h             ; bell character
        BACKSPACE       equ     08h             ; backspace character
        TAB             equ     09h             ; tab character
        LF              equ     0ah             ; line feed
        F_FEED          equ     0ch             ; form feed
        CR              equ     0dh             ; carriage return
        EOF             equ     1ah             ; ctrl z ( end of file )
        SPACE           equ     ' '             ; ascii space character
        QUOTE           equ     '"'

SIGNATURE1              equ     6144h           ; used for already
SIGNATURE2              equ     616eh           ; resident check

DOS_INT                 equ     21h      ; DOS function interrupt
DISP_CHAR               equ     02h
GET_KEY                 equ     08h
DOS_SCR_MSG             equ     09h
DOS_SET_INT             equ     25h
DOS_RESIDENT            equ     31h
DOS_GET_INT             equ     35h
DOS_TERMINATE           equ     4ch
DOS_STRING_TERM         equ     '$'
BIOS_ACTIVE_PAGE        equ      5
BIOS_SET_VIDEO_MODE     equ      0
BIOS_SET_CURSOR_SIZE    equ      1

; Interrupt vectors used

HOOK_INT        equ    10h      ; interrupt to be hooked
PAGE_NUMBER     equ     0       ; active page to be set if color moniter
VIDEO_MODE      equ     2       ; color 80 x 25 with 4 grey colors
CURSOR_SIZE     equ  0607h      ; color monitor cursor 6x7

;------------------------------------------------------------------------------
;
;       MACRO   SECTION
;
;------------------------------------------------------------------------------

Version_msg     macro
                jmp     short copyright_end

copyright_msg   db      CR, LF
                db      'SUPPRESS - Version 1.07', CR, LF
                db      'Copyright 1986, Dana Nowell  ', CR, LF, CR, LF
                db      'May be distributed without license', CR, LF, '$'
copyright_end:
                Msg     copyright_msg
                endm


Msg     macro   ptr

        push    dx
        push    ax

        lea     dx, ptr
        mov     ah, 09h
        int     21h

        pop     ax
        pop     dx

        endm





com     segment para public 'code'
        assume cs:com, ds:com, es:com


        org     100h    ; required for COM file ( skips PSP )


start:
        jmp     install                 ; install the demon

;-------------------------------------------------------------------
;
;               resident data structures go here
;
;-------------------------------------------------------------------

        old_int         dd      0       ; original value of hooked interrupt
        resident1       dw      SIGNATURE1
        resident2       dw      SIGNATURE2
        mode            dw      0       ; 0 = text  -  1 = graphics


;-------------------------------------------------------------------
;
;               new interrupt starts here
;
;-------------------------------------------------------------------


new_int:
        pushf

        cmp     ah, 0eh
        je      write_tty

        cmp     ah, 9
        je      write_character

        cmp     ah, 0ah
        je      write_attribute

        cmp     ah, 6
        je      scroll

        cmp     ah, 7
        je      scroll

        cmp     ah, 0ch
        je      write_pixel

        cmp     ah, 13h
        je      write_string

        cmp     ah, 0
        je      set_mode

        jmp     do_int

write_pixel:

        push    bx              ; save bx
        mov     bl, al          ; pixel color is in al so move in to bl
        call    remap_color     ; remap the pixel color
        mov     al, bl          ; put color back into al
        pop     bx              ; restore original bx

        jmp     do_int

write_tty:

        call    remap_color     ; attribute in bl
        jmp     do_int


write_character:

        call    remap_color     ; not mixed - attribute in bl
        jmp     do_int



write_string:

        cmp     al, 1
        jg      mixed_attributes ; attribute bytes and chars mixed in a string

        call    remap_color     ; not mixed - attribute in bl
        jmp     do_int

mixed_attributes:               ; stub for now
        jmp     do_int




scroll:
        and     bh, 8fh         ; set blank lines to black
        jmp     do_int




set_mode:
        mov     cs:mode, 0         ; mark as text mode
        cmp     al, 4
        jl      text

        mov     cs:mode, 1         ; really graphics mode
        cmp     al, 5
        jle     mgraphics
        jmp     do_int

text:
        cmp     al, 1
        jg      htext

ltext:
        mov     al, 0
        jmp     do_int

htext:
        mov     al, 2
        jmp     do_int

mgraphics:
        mov     al, 5
        jmp     do_int





write_attribute:

        call    remap_color


;-------------------------------------------------------------------
;
;               be well behaved and pass control to original int
;
;-------------------------------------------------------------------

do_int:
        popf
        pushf
        call   dword ptr cs:old_int     ; do old interrupt

        iret                            ; bye bye



remap_color     proc    near

        push    dx
        push    bx

;       test   bl, 08h
;       jz     not_grey
;
;       push   bx
;       and    bl, 77h
;       pop    bx
;       jnz    not_grey

        cmp     bl, 88h
        je      grey

        cmp     bl, 08h
        jne     not_grey

grey:
        pop     bx
        or      bl, 01h
        push    bx

not_grey:
        mov     dl, 00h         ; assume black background, black characters

        and     bl, 77h         ; AND color and background in character
        jz      black           ; no color or background - so use default

        mov     dl, 70h         ; assume color background, black characters

        and     bl, 07h         ; and color in character
        jz      black           ; no color - so use color background

        mov     dl, 07h         ; assume black background, color characters

        pop     bx              ; restore original bx
        and     bl, 8fh         ; set background off leave colors on and
                                ; attributes as before ( blink & intensity )
        push    bx              ; set-up for next pop

black:
        pop     bx
        or      bl, dl          ; mask it for readability
        pop     dx

        cmp     cs:mode, 0         ; if text ret
        je      remap_bye

        and     bl, 07fh        ; if graphics remove xor bit

remap_bye:
        ret

remap_color     endp

;------------------------------------------------------------------------------
;
;       INSTALLATION DATA STRUCTURES AND CODE GO HERE
;
; WARNING WARNING WARNING - this area does not exist after installation
;
;------------------------------------------------------------------------------

last_resident_byte      db      0       ; last resident byte
resident_flag           dw      0       ; am I already resident ? ( 0 = NO )

install_msg             db      CR, LF
                        db      'SUPPRESS - Installation Complete'
                        db      CR, LF, '$'

already_installed_msg   db      CR, LF
                        db      'SUPPRESS Already Installed'
                        db      ' - Installation Aborted'
                        db      CR, LF, '$'

mono                    db      CR, LF
                        db      'NO NEED TO SET COLOR SUPPRESSION '
                        db      'ON A MONOCHROME MONITER', CR, LF, '$'

install proc    near



;
;       determine monitor type
;

        int     11h                     ; determine monitor type FIRST !
        and     ax, 30h

        cmp     ax, 30
        jne     color_mon               ; assumes a monochrome monitor

;
;               MONOCHROME MONITER
;
        call    disp_version            ; display version message
        Msg     mono                    ; if mono display print no need msg
        mov     ah, DOS_TERMINATE       ; and do not install
        mov     al, 1                   ; set error exit value
        int     21h                     ; bye bye

;
;               COLOR MONITER
;

color_mon:
        call    color_setup           ; set video page and cursor etc.

        call    disp_version          ; display version message

         mov   al, HOOK_INT           ; int to hook
         mov   ah, DOS_GET_INT        ; get int(AL) vector ==> ES+BX
         int   DOS_INT                ; do the int
         lea   si, old_int            ; where to put old timer interrupt vector
         mov   [si], bx               ; save the offset and segment
         mov   2[si], es              ; ( es also used in check resident )

         call   check_resident        ; am I already resident ?

         cmp    resident_flag, 0
         je     not_resident

         Msg    already_installed_msg

         mov     ah, DOS_TERMINATE    ; terminate & stay resident
         mov     al, 1                ; return value is 1 (already installed)
         int     DOS_INT              ; bye-bye

not_resident:


;
;       setup new BIOS video interrupt routine
;


         mov   dx, offset new_int     ; offset of new timer interrupt
         mov   al, HOOK_INT           ; timer tick
         mov   ah, DOS_SET_INT        ; set int(AL) vector from DS+DX
         int   DOS_INT                ; do the int

; program terminate and stay resident

         Msg     install_msg          ; Display the installation message

         mov     dx, offset last_resident_byte

         mov     cl, 4                ; convert to paragraphs required to
         shr     dx, cl               ; remain resident ( divide by 16 )
         inc     dx                   ; allow for any remainder of division

         mov     ah, DOS_RESIDENT     ; terminate & stay resident
         mov     al, 0                ; return value is 0 (good return)
         int     DOS_INT              ; bye-bye

install endp


;
;       Check resident procedure
;               requires es register to contain the segment address of
;               the current location for the interrupt being hooked.
;               use the DOS function 35h to obtain this information.
;

check_resident  proc    near

         cmp    es:resident1, SIGNATURE1
         jne    not_res
         cmp    es:resident2, SIGNATURE2
         jne    not_res

         mov    resident_flag, 1

not_res:
        ret

check_resident  endp

color_setup     proc    near


;
;       set COLOR MONITOR to use page 0
;

        mov     ah, BIOS_ACTIVE_PAGE    ; set active page function
        mov     al, PAGE_NUMBER         ; page number to make active
        int     10h                     ; do it


;
;               set video mode
;

        mov     ah, BIOS_SET_VIDEO_MODE
        mov     al, VIDEO_MODE
        int     10h

;
;       set cursor size
;
        mov     ah, BIOS_SET_CURSOR_SIZE
        mov     cx, CURSOR_SIZE
        int     10h

        ret

color_setup     endp

disp_version    proc    near

        Version_msg
        ret
disp_version    endp


com     ends
        end     start
