home *** CD-ROM | disk | FTP | other *** search
- page 60,132
- ; HELP.COM by Bob Montgomery, 2/23/87
- ; This program is a generic help screen template for use with the MASM
- ; assembler. The desired help message is written as db's at Hlpst in
- ; place of the test message that is there now. The only restrictions
- ; on the help message are:
- ; 1. The message must not exceed 80 characters wide.
- ; 2. The message must not exceed 25 lines long.
- ; 3. Each help line must be the same length.
- ; The program will auto center the message on the display screen. The hot
- ; key combo to bring up the help screen is defined as Hotkey below (set
- ; for Cntl-Leftshift right now) and can be changed to another combination
- ; by changing the equate for Hotkey.
-
- Code segment
- assume cs:Code,ds:Code
- org 100h
-
- Begin: jmp Init ;Initialize program
-
- Esc equ 1Bh
- Vidmem equ 0B800h ;Location of screen 0
- Monomem equ 0B000h ;Location of mono screen
- BWattr equ 70h ;Grey background, black foreground
-
- ; Bits in shift status
- Rtsh equ 1
- Lftsh equ 2
- Cntl equ 4
- Alt equ 8
- Scrl equ 10h
- Numl equ 20h
- Capl equ 40h
-
- Mode db ? ;Current video mode
- Vpage db ? ;Current video page
- Vidseg dw ? ;Current page segment
- Hlpflg db 0 ;1 => Help on
- Attr db ? ;Attribute to use
- Cursor dw ? ;Current cursor type
-
- ; ==================================================================
- ; This is the test help message to be displayed on the video screen.
- ; Change this area for your own help message, color, and hot key combo.
-
- Colattr equ 4Eh ;Red background, yellow foreground
- Hotkey equ Cntl+Lftsh ;Define the hot key combo to bring up screen
-
- Hlpst: db 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
- Linchr equ $-Hlpst ;Chars on each help line
- db 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
- db 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'
- db 'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'
- db 'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'
- DB 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
- db 'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG'
- db 'HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH'
- db 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'
- db 'JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ'
- db 'KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK'
- DB 'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL'
- DB 'MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM'
- DB 'NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN'
- DB 'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO'
- DB 'PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP'
- DB 'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ'
- DB 'RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR'
- DB 'SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS'
- DB 'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT'
- DB 'UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU'
- DB 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
- DB 'WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW'
- ; ===================================================================
-
- Msglen equ $-Hlpst ;# chars in help buffer
- Lines equ Msglen/Linchr ;# lines of help
- Buflen equ 2*Msglen ;Screen data buffer length
- Stlin equ (25-Lines)/2 ;Start line
- Stchr equ (80-Linchr)/2 ;Start byte on line
- Stscr equ 160*Stlin + 2*Stchr ;Start of mem to put help
-
- Scrbuf: db Buflen dup (?) ;Buffer for screen data
-
- ; New Int 9 routine - check for Cntrl-LShift; ignore others.
- ; Since Int 9 is called every time a key is pressed or released, and
- ; reads the keyboard thru some mysterious means in BIOS, we must call
- ; the old Int 9 as a subroutine each time an Int 9 is generated. But,
- ; an interrupt routine has a IRET instead of a RET as the return
- ; instruction, which pops the return address like a RET does, and then
- ; pops the flags. So to call Int 9 like a subroutine, we have to push
- ; the flags first; then when the the IRET is executed, control returns
- ; to our program with the stack pointer at the right place.
-
- Start: push ax ;Save all for calling program
- push bx
- push cx
- push dx
- push ds
- push es
- push di
- push si
- pushf ;Put flags on stack since Int pops flags
- ;Call old Int 9 to get key-will pop flags
- db 9Ah ;Opcode for far call
- Oldint dw ?,? ;Save old Int 9 vector here
- mov ah,2 ;Get shift status
- Int 16h ;in al
- and al,Hotkey ;Only keep Hot keys
- cmp al,Hotkey ;Were both pressed?
- jne Exit ;No
- push cs
- pop ds ;Yes, set ds=cs
- cmp Hlpflg,1 ;Is help already up?
- jne Go ;No, put it up
- ; If help is already up, ignore the Hotkey.
- Exit: pop si ;Restore all for calling program
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- iret ;Pop return address and flags
-
- ; Come here if should put up help.
- Go: mov al,Colattr ;Assume color
- mov Attr,al
- mov ah,15 ;Get video mode in al
- int 10h ;and page in bh
- mov Mode,al ;Save Mode
- mov Vpage,bh ;and page
- cmp al,2 ;Mode=2?
- je Color ;Yes
- cmp al,3 ;Mode=3?
- je Color ;Yes
- cmp al,7 ;Mode=7? (mono)
- jne Exit ;No, must be graphics so exit
- mov al,BWattr ;Set B&W attribute
- mov Attr,al
- mov bx,Monomem ;and start of mono video memory
- jmp short A0
- Color: mov bl,0 ;Bx=256*display page
- add bx,Vidmem ;Get display mem segment
- A0: mov ds,bx ;in ds
-
- ; Put up help screen.
- ; First save current screen to buffer.
- call Hidecur ;Hide cursor
- call Vidoff ;Disable video (avoids snow on CGA)
- mov dl,Lines ;Get # lines of help
- push cs ;es=cs
- pop es
- mov si,Stscr ;ds:si points to help screen area in disp mem
- mov di,offset Scrbuf ;es:di points to buffer for screen data
- push si ;Save them
- push es
- push ds
- mov ch,0 ;ch=0
- mov cl,Linchr ;cx=chars/help line
- A1: push si ;Save position in scrn mem & chars/line
- push cx
- cld ;Set to inc si & di
- rep movsw ;Move screen to buffer
- pop cx ;Get start of line & chars/line
- pop si
- add si,160 ;Next line, same column
- dec dl ;Done all lines?
- jne A1 ;No
-
- ; Now put up help.
- pop es ;Now ds=cs, es:di=help scrn area in screen mem
- pop ds
- pop di
- push di ;Put back in orig order
- push ds
- push es
- mov si,offset Hlpst ;Point si to help data
- mov dl,Lines ;Get chars/help line
- mov ah,Attr ;Get char attribute (color)
- B1: push di ;Save disp mem pos & chars/help line
- push cx
- B2: lodsb ;Get a help char in al
- stosw ;Save char & attribute in screen mem
- loop B2 ;Do whole line
- pop cx ;Get start of disp line & chars/line
- pop di
- add di,160 ;Next line, same column
- dec dl ;Done all lines?
- jne B1 ;No
- mov Hlpflg,1 ;Yes, indicate help up
- call Vidon ;and enable video
-
- ; Now, wait for the escape key; come here after each keypress (Int 9).
- Wait1: mov ah,0 ;Wait for a key
- int 16h
- cmp al,Esc ;Was it Escape?
- jne Wait1 ;No
-
- ; If Esc was pressed, put the old screen back
- pop es ;ds=cs; es:di=start of help area in disp mem
- pop ds
- pop di
- mov si,offset Scrbuf ;Point to old screen data buffer
- call Vidoff ;Disable video (avoid snow on CGA)
- mov dl,Lines ;Chars/help line
- C1: push di ;Save scrn mem pointer & chars/line
- push cx
- rep movsw ;Move a line to scrn mem
- pop cx ;Get start of line & chars/line
- pop di
- add di,160 ;Next line, same column
- dec dl ;Done all lines?
- jne C1 ;No
- mov Hlpflg,0 ;Yes, clear flag
- call Vidon ;Enable video
- call Showcur ;Turn cursor back on
- jmp Exit ;and return
-
- ; Sub to turn cursor off; come with ds=video.
- Hidecur: push cx
- push ds
- push cs ;ds=cs
- pop ds
- mov ah,3 ;Get current cursor data
- mov bh,Vpage ;for current page
- int 10h
- mov Cursor,cx ;Save cursor type
- mov ch,20h ;Set cursor off
- mov ah,1
- int 10h
- pop ds
- pop cx
- ret
-
- ; Sub to turn cursor on; come with ds=cs.
- Showcur: mov cx,Cursor ;Set original cursor Type
- mov bh,Vpage
- mov ah,1
- int 10h
- ret
-
- ; Turn video off
- Vidoff: cmp cs:Mode,7 ;Mono?
- je D0 ;Yes, skip wait for vert retrace
- push ds
- push dx
- push ax
- call Getmode ;Get current video mode byte
- and al,0F7h ;Clear video enable bit
- out dx,al ;Send to mode control port
- pop ax
- pop dx
- pop ds
- D0: ret
-
- ; Turn video on
- Vidon: cmp cs:Mode,7 ;Mono?
- je E0 ;Yes, skip wait for vert retrace
- push ds
- push dx
- push ax
- call Getmode ;Get current video mode byte
- or al,8 ;Set video enable bit
- out dx,al ;Send to mode control port
- pop ax
- pop dx
- pop ds
- E0: ret
-
- ; Sub to wait for vertical retrace to avoid snow on CGA screen.
- Vert: mov dx,3DAh ;CRT status port
- F1: in al,dx ;Read status
- test al,8 ;Vert retrace?
- je F1 ;No
- mov dx,3D8h ;Point to video mode port
- ret ;Yes, return
-
- Getmode: call Vert ;Wait for vert retrace
- mov ax,40h ;Get video mode
- mov ds,ax ;at 465h
- mov al,ds:[65h]
- ret ;and return
-
- ; Come here to install the program as the new Int 9 routine.
- Init: mov ax,3509h ;Get current Int 9 vector
- int 21h ;in es:bx
- push cs
- pop ds
- mov Oldint,bx ;Save it
- mov Oldint+2,es
- mov ax,2509h ;Set new Int 9 routine
- mov dx,offset Start
- int 21h
- mov dx,offset Init ;Terminate and
- int 27h ;stay resident
-
- Code ends
- end Begin