Category : Files from Magazines
Archive   : VOL7N1.ZIP
Filename : HELP.ASM

 
Output of file : HELP.ASM contained in archive : VOL7N1.ZIP
; Help.asm
; Resident help facility
; Format: HELP filespec [... filespec][/Nn][/P][/Hn] | [/U]
; defaults: pages = 4; hot key = Alt H

CODE SEGMENT ;********************************;
ASSUME CS:CODE,DS:CODE ;* *;
ORG 100H ;* Requires MASM 2.0 or later *;
;* Remember to EXE2BIN *;
START: JMP BEGINNING ;* *;
;********************************;

; DATA AREA
; ---------
COPYRIGHT DB "HELP 1.0 (c) 1987 Ziff Communications Co.",13,10
DB "Successfully installed",13,10
ALT_COMBO DB "Press Alt H to activate",10,0,26

PROGRAMMER DB "Michael J. Mefford"

OLD_KEYBOARD DD ?
CRT_COLS DW ?
STATUS_REG DW ?
SCREEN_SEG DW 0B000H
LINE_COUNT DB 25
IMMEDIATE_FLAG DB 0
BUSY DB 0

IMMEDIATE DW POP_IT
DATA_SEG DW ?
DATA_INT DB 0
INSTALLED_FLAG DB 0
POPUP_FLAG DB 0
HOT_KEY DB 35

FILENAME DW ?
ERROR_LEVEL DB 0

CURRENT_PAGE DB 1
RESERVED_PAGES DB 4
ACTIVE_PAGES DB 0
PAGE_COUNT DB 0
DELIMITERS DB 9,32,13,44,";","/"

SYNTAX LABEL BYTE
DB 10,"Usage: HELP filespec [... filespec][/Nn][/Hn][/P] | [/U]",13,10,10
DB "/Nn where n = number of reserved pages (1-14); default = 4",13,10
DB "/Hn where n = Alt hot key combo (A-Z,0-9,",34,45,34,44,34,61,34
DB "); default = H",13,10
DB "/P = immediate pop-up",13,10
DB "/U = uninstall",13,10,10
DB "Use: PgUp PgDn Home End to navigate through HELP",13,10
DB 5 DUP(32),"ESC or hot key to exit",10,0


ACTIVE_MSG DB " active page(s)",13,10,0
RESERVED_MSG DB " total page(s)",13,10,10,0
UNLOAD_MSG DB 10,"HELP can't be uninstalled.",13,10
DB "Uninstall resident programs in reverse order.",10,0
UNINSTALL_MSG DB 10,"HELP uninstalled",10,0
NO_FREE DB "Too many resident programs",0
NOT_FOUND DB 32,"not found",13,10,0
NOT_ENOUGH DB "Not enough memory",0
ALLOCATE_MSG DB "Memory allocation error",13,10,0

SCAN_CODES LABEL BYTE

DB 45,130,48,129,49,120,50,121,51,122,52,123,53,124
DB 54,125,55,126,56,127,57,128,61,131,65,30,66,48,67
DB 46,68,32,69,18,70,33,71,34,72,35,73,23,74,36,75,37
DB 76,38,77,50,78,49,79,24,80,25,81,16,82,19,83,31
DB 84,20,85,22,86,47,87,17,88,45,89,21,90,44

; SCAN CODES FOR ALT COMBO
;
; Code Key Code Key Code Key Code Key
; 16 Q 30 A 44 Z 120 1
; 17 W 31 S 45 X 121 2
; 18 E 32 D 46 C 122 3
; 19 R 33 F 47 V 123 4
; 20 T 34 G 48 B 124 5
; 21 Y 35 H 49 N 125 6
; 22 U 36 J 50 M 126 7
; 23 I 37 K 127 8
; 24 O 38 L 128 9
; 25 P 129 0
; 130 -
; Default is 35 (Alt H) 131 =


;************* KEYBOARD INTERCEPTOR *************;

NEW_KEYBOARD: STI
PUSHF ;Simulate an interrupt
CALL CS:OLD_KEYBOARD ; by pushing flags and far call.

POP_IT: PUSHF ;On return save all registers
PUSH DS ; that will be used.
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH BP

PUSH CS ;Point to our data.
POP DS
CLD ;Moves in forward direction.
MOV AX,40H ;Point to ROM BIOS data area
MOV ES,AX
MOV AX,ES:[4AH] ;Get number of columns on screen
MOV CRT_COLS,AX ; and store.
MOV AX,ES:[63H] ;Get base address of video card.
ADD AX,6 ;Convert to status register
MOV STATUS_REG,AX ; and store.
CMP AX,3BAH ;Is it mono card?
JZ MONO ;If yes, use b800h.
MOV SCREEN_SEG,0B800H ; else point to color card.
MONO: MOV AL,ES:[49H] ;Retrieve video mode.
CMP AL,3 ;Is it text mode?
JBE GOOD_MODE ;If yes, OK.
CMP AL,7
JNZ DONE_HERE ;Exit if graphics

GOOD_MODE: CMP IMMEDIATE_FLAG,1 ;Is there a pop-up request?
JZ NOW ;If yes, pop-up right now.
CMP BUSY,1 ;If the window is already popped
JZ DONE_HERE ; exit Int 9 back to window.
MOV AH,1 ;Is an ASCII character ready?
INT 16H
JZ DONE_HERE ;If it's just a key release, exit.
CMP AL,0 ;Is it extended code?
JNZ DONE_HERE ;If no, exit.
CMP AH,HOT_KEY ;Else, see if our Alt key combo.
JZ OPEN_WINDOW ;If yes, open window
DONE_HERE: JMP SHORT EXIT_KEYBOARD ; else exit.

;------------------------------------;
; Save screen so we can pop up HELP. ;
;------------------------------------;

OPEN_WINDOW: MOV AH,0 ;Retrieve and discard hot key
INT 16H ; character from keyboard buffer.
NOW: MOV BUSY,1 ;Flag that window is open.
MOV IMMEDIATE_FLAG,0 ;Restore immediate flag.
CALL STORE_SCREEN ;Store screen.

;-----------------------------------------;
; Loop here looking for valid keystrokes. ;
;-----------------------------------------;

READ_KEY: MOV CL,CURRENT_PAGE ;Get current page.
DEC CL ;Adjust for starting offset.
CALL PAGE_SIZE ;Get offset.
MOV SI,DX
CALL WRITE_SCREEN ;Update the screen.
MOV AH,0 ;Wait for a character.
INT 16H
CMP AH,1 ;Is it Esc?
JZ EXIT_WINDOW ;If yes, exit window.
CMP AH,BYTE PTR HOT_KEY ;Is it our key combo?
JZ EXIT_WINDOW ;If yes, exit window.

MOV CL,CURRENT_PAGE ;Get current page.
CMP AH,49H ;Is it PgUp?
JNZ CK_PGDN
CMP CL,1 ;If yes, is it already page one?
JZ END_KEY
DEC CL ;If no, decrement page.

CK_PGDN: CMP AH,51H ;Is it PgDn?
JNZ CK_HOME
CMP CL,ACTIVE_PAGES ;If yes, are we already last page?
JZ END_KEY
INC CL ;If no, increment page.

CK_HOME: CMP AH,47H ;Is it Home?
JNZ CK_END
MOV CL,1 ;If yes, move to page one.

CK_END: CMP AH,4FH ;Is it End?
JNZ END_KEY
MOV CL,ACTIVE_PAGES ;If yes, move to last page.

END_KEY: MOV CURRENT_PAGE,CL ;Store new current page.
JMP SHORT READ_KEY

;----------------------------------;
; This is the window exit routine. ;
;----------------------------------;

EXIT_WINDOW: MOV SI,OFFSET SCREEN_BUFFER ;Point to the stored screen
CALL WRITE_SCREEN ; and restore the screen.
MOV IMMEDIATE_FLAG,0 ;Reset the pop-up flag.
MOV BUSY,0 ;Flag done with window.

EXIT_KEYBOARD: POP BP ;Restore all registers.
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
POPF
IRET ;Return from interrupt.


;************* FILE LOADING AND INSTALL PROCEDURE *************;

BEGINNING: CLD
PUSH CS
POP DATA_SEG ;Store our segment.
CMP SP,65533 ;Do we have 64K?
JA CK_PARA
MOV SI,OFFSET NOT_ENOUGH ;If no, exit with message.
JMP ERROR_EXIT

CK_PARA: CMP BYTE PTR DS:[80H],0 ;Any parameters?
JNZ CK_FREE
OPTIONS: MOV SI,OFFSET SYNTAX ;If no, exit with syntax message.
JMP ERROR_EXIT

;----------------------------------------------------------------------;
; Check user vectors to see if we are installed or if one is available ;
;----------------------------------------------------------------------;

CK_FREE: MOV AL,60H - 1 ;Available vectors are 60H - 67H.
FREE_USER_INT: INC AL
MOV AH,35H ;Get vector address.
INT 21H
CMP BX,0 ;Is offset being used?
JNZ CK_SIGNATURE ;If yes, see if it's us.
MOV DX,ES
CMP DX,0 ;Is segment being used?
JNZ CK_SIGNATURE ;If yes, see if it's us.
MOV DATA_INT,AL ;If available, save INT number.

NEXT_USER: CMP AL,67H ;Have we checked all 7?
JNZ FREE_USER_INT ;If no, next one.
JMP SHORT CK_SWITCHES

CK_SIGNATURE: MOV DI,BX ;See if INT has our signature.
MOV SI,100H
MOV CX,30/2
REPZ CMPSW
JNZ NEXT_USER ;If yes, already installed.
MOV DATA_SEG,ES ;Save segment.
MOV INSTALLED_FLAG,1

;--------------------------------------------;
; Check the command line for switch options. ;
;--------------------------------------------;

CK_SWITCHES: PUSH DATA_SEG ;First point to installed segment.
POP ES
MOV SI,81H ;First parameter.

NEXT_SWITCH: LODSB ;Get a byte.
CMP AL,13 ;Is it carriage return?
JZ CK_FILENAMES ;If yes, done here.
CMP AL,"/" ;Is it switch character?
JNZ NEXT_SWITCH ;If no, get next byte
LODSB ; else get switch.
CMP AL,13 ;Is it carriage return?
JZ CK_FILENAMES ;If yes, done here
CALL CAPITALIZE ; else capitalize.

CMP AL,"U" ;Is it "U"?
JNZ CK_N
CMP INSTALLED_FLAG,1 ;If yes, are we installed?
JNZ NEXT_SWITCH
JMP UNINSTALL ;If yes, uninstall.

CK_N: CMP AL,"N" ;Is it "N"?
JNZ CK_P
CMP INSTALLED_FLAG,1 ;If yes, are we installed?
JZ NEXT_SWITCH ;If yes, can't change reserved.
CALL DEC_TO_HEX ;Else, convert decimal to hex.
CMP BL,14 ;Request greater than 14 pages
JA NEXT_SWITCH ; or equal to zero?
CMP BL,0
JZ NEXT_SWITCH ;If yes, ignore.
MOV RESERVED_PAGES,BL ;Else, store reserved pages.
JMP SHORT NEXT_SWITCH

CK_P: CMP AL,"P" ;Is it "P"?
JNZ CK_H
MOV POPUP_FLAG,1 ;If yes, flag to pop-up immediate.

CK_H: CMP AL,"H" ;Is it "H"?
JNZ NEXT_SWITCH
LODSB
DEC SI ;Adjust in case it's just CR.
CALL CAPITALIZE
MOV DI,OFFSET SCAN_CODES
MOV CX,38 ;38 possible Alt key combos.

NEXT_ALT: SCASB ;Do we have a match?
JZ GOT_ALT
INC DI ;If no, bump pointer to next byte.
LOOP NEXT_ALT
JMP SHORT NEXT_SWITCH

GOT_ALT: MOV ALT_COMBO + 10,AL ;Store Alt key.
MOV AL,[DI] ;Get scan code
MOV ES:HOT_KEY,AL ; and store.
JMP SHORT NEXT_SWITCH

;-----------------------------------------------------;
; This routine parses the command line for filenames. ;
;-----------------------------------------------------;

CK_FILENAMES: MOV SI,81H ;Point to first parameter.
NEXT_FILENAME: CALL CK_DELIMITER ;Is it a delimiter?
JC CK_CR ;If yes, see if end.
MOV FILENAME,SI ;Else, store filename start.
FIND_END: CALL CK_DELIMITER ;Look for delimiter to mark end.
JNC FIND_END
PUSH SI ;Save pointer and delimiter.
PUSH AX
CALL READ_FILE ;Read the file in.
POP AX
POP SI ;Restore pointers.

CK_CR: CMP AL,13 ;Is it carriage return?
JZ END_FILENAMES ;If yes, done here.
CMP AL,"/" ;Is it switch character?
JNZ NEXT_FILENAME ;If no, get next filename.
FIND_SWITCH: CALL CK_DELIMITER ;Else, look for delimiter.
JNC FIND_SWITCH
JMP SHORT CK_CR ;And check if carriage return.

END_FILENAMES: MOV AL,PAGE_COUNT ;Retrieve page count.
CMP INSTALLED_FLAG,1 ;Are we installed?
JZ STORE_ACTIVE ;If yes, check pages read.
CMP AL,RESERVED_PAGES ;Pages read greater than reserved?
JBE STORE_ACTIVE
MOV RESERVED_PAGES,AL ;If yes, store as reserved.

STORE_ACTIVE: CMP AL,0 ;Did we read any pages?
JZ CK_INSTALLED1 ;If no, check if installed.
MOV ES:ACTIVE_PAGES,AL ;Else, store active pages.
MOV ES:CURRENT_PAGE,1 ;Reset the current page to one.
JMP SHORT CK_POPUP ;Check popup request.

CK_INSTALLED1: CMP INSTALLED_FLAG,1 ;Are we installed?
JNZ CK_INSTALLED2 ;If no, exit.

;----------------------------------------;
; This routine does an immediate pop-up. ;
;----------------------------------------;

CK_POPUP: CMP POPUP_FLAG,1 ;Is there a popup request?
JNZ CK_INSTALLED2 ;If no, check pages read.
MOV ES:IMMEDIATE_FLAG,1 ;Else, flag keyboard routine.
PUSHF ;Simulate an interrupt.
CALL DWORD PTR IMMEDIATE
MOV BL,0 ;Error level of zero.
CMP AL,0 ;Any pages read?
JZ EXIT ;If no, done here.

;--------------------------------------------------;
; This routine checks to see if we are to install. ;
;--------------------------------------------------;

CK_INSTALLED2: CMP AL,0 ;Did we fail to open a file?
MOV SI,OFFSET SYNTAX ;If yes, exit with syntax message.
JZ ERROR_EXIT
PUSH AX
MOV CL,AL ;Save active pages.
MOV DL,10
CALL WRITE_IT ;Display linefeed.
CALL WRITE_NUMBER ;Display active pages.
MOV SI,OFFSET ACTIVE_MSG
CALL DISPLAY_TEXT
POP AX

CMP INSTALLED_FLAG,1 ;Are we already installed?
MOV BL,ERROR_LEVEL
JZ EXIT ;If yes, done here
CK_INT: CMP DATA_INT,0 ;Did we find a free user interrupt?
JNZ INSTALL ;If yes, install
MOV SI,OFFSET NO_FREE ;Else, exit with message.

;-------------------;
; This is the exit. ;
;-------------------;

ERROR_EXIT: MOV BL,1 ;Error code of one.
MSG_EXIT: CALL DISPLAY_TEXT
EXIT: MOV AL,BL
MOV AH,4CH ;Return with error code.
INT 21H ;Terminate.

;--------------------------------;
; This is the install procedure. ;
;--------------------------------;

INSTALL: MOV AX,DS:[2CH] ;Get environment segment.
MOV ES,AX
MOV AH,49H ;Free up environment.
INT 21H
MOV SI,OFFSET ALLOCATE_MSG
JC ERROR_EXIT ;If error, exit with message.

MOV DX,100H ;Install user interrupt as
MOV AL,DATA_INT ; pointer to residency.
MOV AH,25H
INT 21H

MOV AX,3509H ;Get keyboard interrupt.
INT 21H
MOV WORD PTR OLD_KEYBOARD,BX ;Save old interrupt.
MOV WORD PTR OLD_KEYBOARD[2],ES

MOV DX,OFFSET NEW_KEYBOARD ;Install new interrupt.
MOV AX,2509H
INT 21H

MOV CL,RESERVED_PAGES ;Display reserved pages.
CALL WRITE_NUMBER
MOV SI,OFFSET RESERVED_MSG
CALL DISPLAY_TEXT

MOV SI,OFFSET COPYRIGHT ;Display install message.
CALL DISPLAY_TEXT

CALL PAGE_SIZE ;Convert reserved pages to offset.
MOV CL,4
SHR DX,CL ;Convert to paragraphs.
INC DX ;Round up one.
MOV AX,3100H ;Return error code of zero.
INT 21H ;Terminate but stay resident.

;*************;
; SUBROUTINES ;
;*************;

;-----------------------------------------------;
; This subroutine uninstalls the resident help. ;
;-----------------------------------------------;

UNINSTALL: MOV AX,3509H ;Get keyboard interrupt.
INT 21H
CMP BX,OFFSET NEW_KEYBOARD ;Is the offset vector same?
MOV SI,OFFSET UNLOAD_MSG ;Error message if INT 9h changed.
MOV BL,1 ;Error code of one if fails.
JNZ MSG_EXIT
MOV AX,ES ;Is segment vector same?
CMP AX,DATA_SEG
JNZ MSG_EXIT ;If no, exit with error.

MOV ES,DATA_SEG ;Point to resident segment.
MOV AH,49H ;And return memory to system pool.
INT 21H
MOV SI,OFFSET ALLOCATE_MSG
JNC DEALLOCATED ;Display message if problem.
CALL DISPLAY_TEXT

DEALLOCATED: MOV DX,ES:WORD PTR OLD_KEYBOARD ;Restore old INT 9.
MOV DS,ES:WORD PTR OLD_KEYBOARD[2]
MOV AX,2509H
INT 21H

MOV AL,ES:DATA_INT ;Retrieve user interrupt.
XOR DX,DX
MOV DS,DX ;Return vector to nulls.
MOV AH,25H
INT 21H

PUSH CS
POP DS
MOV SI,OFFSET UNINSTALL_MSG ;Display uninstall message.
MOV BL,0 ;Error code of zero.
JMP MSG_EXIT ;And exit.

;-----------------------------------------;
; These subroutines display the messages. ;
;-----------------------------------------;

WRITE_NUMBER: MOV BL,CL ;Retrieve number.
CMP BL,10 ;Is it greater than ten?
JB ONES
MOV DL,"1" ;If yes, display a one.
CALL WRITE_IT
SUB BL,10
ONES: MOV DL,BL
ADD DL,"0" ;Convert to decimal.
CALL WRITE_IT ;Display one's digit.
RET

;----------------------------------------;

WRITE_IT: MOV AH,2 ;Display byte via DOS.
INT 21H
RET

;----------------------------------------;

DISPLAY_IT: CALL WRITE_IT
DISPLAY_TEXT: LODSB ;Get a byte
MOV DL,AL
CMP DL,0 ;Zero marks end of string.
JNZ DISPLAY_IT
RET

;-------------------------------------------------------------;
; This subroutine opens files if there is room to store them. ;
;-------------------------------------------------------------;

READ_FILE: CALL CK_SPACE ;Is there room for help?
JC END_READ
MOV DX,FILENAME ;If yes, open file.
DEC DX
MOV AX,3D00H
INT 21H
JNC GOT_FILE
MOV ERROR_LEVEL,1 ;Else, indicate had a problem.
MOV SI,DX ;Display filename and message
CALL DISPLAY_TEXT ; if file not found.
MOV SI,OFFSET NOT_FOUND
CALL DISPLAY_TEXT
RET

GOT_FILE: MOV BX,AX ;Filehandle in BX.
NEXT_READ: CALL READ_IT ;Read it.
JC CLOSE_FILE ;Done here if nothing read.
CALL CK_SPACE ;If room, read balance, if any,
JNC NEXT_READ ; into next page.

CLOSE_FILE: MOV AH,3EH ;Close file.
INT 21H
END_READ: RET

;--------------------------------------------------------------------;
; This subroutine does the actual reading of help files into storage ;
;--------------------------------------------------------------------;

READ_IT: MOV CL,PAGE_COUNT ;Retrieve page count.
CALL PAGE_SIZE ;Convert to offset.
PUSH ES
POP DS ;Point to storage segment.
MOV CX,4000 ;Read 4000 bytes.
MOV AH,3FH
INT 21H
JC READ_END
CMP AX,0 ;Did we read anything?
JZ READ_END
INC CS:PAGE_COUNT ;If yes, increment page count.
SUB CX,AX ;Was it a full page?
JZ SKIP_PAD
MOV DI,DX ;If no, pad balance with nulls.
ADD DI,AX
XOR AL,AL
REP STOSB
SKIP_PAD: CLC ;Indicate read something.
JMP SHORT RESTORE_DS

READ_END: STC ;Indicate nothing read.
RESTORE_DS: PUSH CS ;Restore data segment.
POP DS
RET

;------------------------------------------------;
; This subroutine checks for free storage space. ;
;------------------------------------------------;

CK_SPACE: CMP PAGE_COUNT,14 ;Already a full 14 pages?
JZ NO_SPACE ;If yes, no space.
CMP INSTALLED_FLAG,1 ;Are we installed.
JNZ SPACE
MOV AL,ES:RESERVED_PAGES ;If yes, are reserved pages full?
CMP AL,PAGE_COUNT
JZ NO_SPACE ;If yes, no space.
SPACE: CLC ;Else, there is space.
RET

NO_SPACE: STC
RET

;-------------------------------------------------------;
; This subroutine calculates the page offsets. ;
; Enter with CL = multiplicand; Return with DX = offset ;
;-------------------------------------------------------;

PAGE_SIZE: MOV AX,4000 ;Multiply by 4000 bytes.
XOR DX,DX
XOR CH,CH
MUL CX
MOV DX,OFFSET PAGE_BUFFER ;Add to page buffer offset.
ADD DX,AX
RET

;------------------------------------------;
; This subroutine converts decimal to hex. ;
;------------------------------------------;

DEC_TO_HEX: XOR BL,BL ;Start with zero.
NEXT_NUMBER: LODSB ;Get a byte.
CMP AL,"0" ;Is it a number?
JB END_NUMBER
CMP AL,"9"
JA END_NUMBER
SUB AL,"0" ;If yes convert to hex.
XCHG AL,BL ;Save it.
XOR AH,AH ;Multiply previous by 10.
MOV DL,10
MUL DL
XCHG AL,BL ;Retrieve current number.
ADD BL,AL ;And add to total.
JMP SHORT NEXT_NUMBER
END_NUMBER: DEC SI ;Adjust pointer.
RET

;---------------------------------------------------------;
; This subroutine checks the command line for delimiters. ;
;---------------------------------------------------------;

CK_DELIMITER: LODSB ;Get a byte.
MOV DI,OFFSET DELIMITERS ;Point to delimiters.
MOV CX,6
REPNZ SCASB ;And see if match.
JNZ NO_DELIMITER
MOV BYTE PTR [SI-1],0 ;If yes, convert to ASCIIZ.
STC
RET
NO_DELIMITER: CLC
RET

;-------------------------------------------------;
; This subroutine capitalizes the character in AL ;
;-------------------------------------------------;

CAPITALIZE: CMP AL,"a"
JB END_CAPS
CMP AL,"z"
JA END_CAPS
AND AL,5FH
END_CAPS: RET

;------------------------------------------------------------------;
; This subroutine stores the screen so it can be restored on exit. ;
;------------------------------------------------------------------;

STORE_SCREEN: MOV LINE_COUNT,25 ;25 lines to save.
MOV DX,STATUS_REG ;Retrieve status register.
MOV AX,SCREEN_SEG ;Point to screen buffer.
MOV DS,AX
PUSH CS ;Point to storage segment.
POP ES
XOR SI,SI ;Top left corner.
MOV DI,OFFSET SCREEN_BUFFER ;Point to storage offset.

NEXT_LINE1: MOV BP,ES:CRT_COLS ;Retrieve screen columns.
MOV CX,80 ;Save maximum of 80 columns.

HORZ_RET1: IN AL,DX ;Get status.
TEST AL,1 ;Is it low?
JNZ HORZ_RET1 ;If no, wait until it is.
CLI ;No more interrupts.

WAIT1: IN AL,DX ;Get status
TEST AL,1 ;Is it high?
JZ WAIT1 ;If no, wait until it is.
LODSW ;Retrieve a word.
STI ;Interrupts back on.
STOSW ;Store the character/attribute.

DEC BP ;Decrement screen column count.
JZ SHORT_COLS1 ;Was it less than 80?
LOOP HORZ_RET1 ;If no, loop until row done.

SHL BP,1 ;Convert balance to a word.
ADD SI,BP ;Add to screen offset.
JMP SHORT CK_LINES1

SHORT_COLS1: DEC CX ;Adjust balance.
SHL CX,1 ;Convert to a word.
ADD DI,CX ;Add to storage offset.


CK_LINES1: DEC ES:LINE_COUNT ;Do all 25 lines.
JNZ NEXT_LINE1

PUSH CS ;Restore data segment.
POP DS
RET ;Return.

;---------------------------------------------;
; This subroutine writes to the screen buffer ;
;---------------------------------------------;

WRITE_SCREEN: MOV LINE_COUNT,25 ;25 lines to save.
MOV DX,STATUS_REG ;Retrieve status register.
MOV AX,SCREEN_SEG ;Point to screen buffer.
MOV ES,AX
XOR DI,DI ;Top left corner.

NEXT_LINE2: MOV BP,CRT_COLS ;Retrieve screen columns.
MOV CX,80 ;Write maximum of 80 columns.

NEXT_BYTE: LODSW ;Get a byte.
MOV BX,AX ;Store it in AX.

HORZ_RET2: IN AL,DX ;Get status.
TEST AL,1 ;Is it low?
JNZ HORZ_RET2 ;If no, wait until it is.
CLI ;No more interrupts.

WAIT2: IN AL,DX ;Get status.
TEST AL,1 ;Is it high?
JZ WAIT2 ;If no, wait until it is.
MOV AX,BX ;Retrieve the word
STOSW ; and store it.
STI ;Interrupts back on.

DEC BP ;Decrement screen column count.
JZ SHORT_COLS2 ;Was it less than 80?
LOOP NEXT_BYTE ;If no, loop until row done.

SHL BP,1 ;Convert balance to a word.
ADD DI,BP ;Add to storage offset.
JMP SHORT CK_LINES2

SHORT_COLS2: DEC CX ;Adjust balance.
SHL CX,1 ;Convert to a word.
ADD SI,CX ;Add to screen offset.

CK_LINES2: DEC LINE_COUNT ;Do all 25 lines.
JNZ NEXT_LINE2
RET


SCREEN_BUFFER LABEL BYTE
PAGE_BUFFER EQU SCREEN_BUFFER + ( 2 * 80 * 25 )

CODE ENDS
END START


  3 Responses to “Category : Files from Magazines
Archive   : VOL7N1.ZIP
Filename : HELP.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/