home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1989
/
06
/
mono.asm
< prev
next >
Wrap
Assembly Source File
|
1989-01-03
|
18KB
|
376 lines
;------------------------------------------------------------------------;
; MONO - TSR designed to make color applications readable on monochrome ;
; labtop computers by converting color attributes to monochrome. ;
; Syntax: MONO [U] ;
; PC Magazine - Michael J. Mefford ;
;------------------------------------------------------------------------;
BIOS_DATA SEGMENT AT 40H
ORG 17H
KBD_FLAG DB ?
ORG 49H
CRT_MODE DB ?
CRT_COLS DW ?
ORG 4EH
CRT_START DW ?
ORG 63H
ADDR_6845 DW ?
ORG 84H
CRT_ROWS DB ?
BIOS_DATA ENDS
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
ORG 100H
START: JMP INITIALIZE
; DATA AREA
SIGNATURE DB CR,SPACE,SPACE,SPACE,CR,LF
COPYRIGHT DB "MONO 1.0 (c) 1989 Ziff Communications Co.",CR,LF
PROGRAMMER DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
DB CTRL_Z
CR EQU 13
LF EQU 10
CTRL_Z EQU 26
SPACE EQU 32
BELL EQU 7
BOX EQU 254
ALT_SHIFT EQU 08H
PORT_A EQU 60H
PORT_B EQU 61H
COMMAND_PORT EQU 20H
EOI EQU 20H
M_SCAN_CODE EQU 32H
OLD_INT_8 DW ?,?
OLD_INT_9 DW ?,?
COUNTER DB 0
BUSY_FLAG DB 0
MODE_BYTE DB 1
; CODE AREA
;************* INTERRUPT HANDLERS *************;
MONO_INT_8 PROC FAR
PUSHF
ADD CS:COUNTER,64 ;Change attributes every 256/64
JNB INT_8_END ; timer ticks
PUSH DS ; (approx. every 1/5 second.)
PUSH CS
POP DS ;Point to our data segment.
CMP BUSY_FLAG,1 ;Are we already adjusting colors?
JZ RESTORE_SEG ;If yes, exit.
STI ;Else, interrupts on.
CALL ATTRIBUTES ;Set the attributes.
RESTORE_SEG: POP DS ;Restore data segment.
INT_8_END: POPF
JMP DWORD PTR CS:OLD_INT_8 ;Service old INT 8 interrupt.
MONO_INT_8 ENDP
;------------------------------------------------;
MONO_INT_9 PROC FAR
PUSH AX ;Save some registers.
PUSHF
PUSH DS
MOV AX,40H ;Is the Alt key depressed?
MOV DS,AX
ASSUME DS:BIOS_DATA
TEST KBD_FLAG,ALT_SHIFT
JZ INT_9_END ;If no, exit.
IN AL,PORT_A ;Else, is the "M" key pressed?
CMP AL,M_SCAN_CODE
JNZ INT_9_END ;If no, exit.
XOR CS:MODE_BYTE,1 ;Else, toggle active state.
IN AL,PORT_B ;Retrieve Port B.
OR AL,80H ;Turn bit 7 on to reset.
JMP $ + 2 ;I/O delay.
OUT PORT_B,AL ;Reset KBD.
AND AL,NOT 80H ;Turn bit 7 back off.
JMP $ + 2 ;I/O delay.
OUT PORT_B,AL ;Restore port.
POP DS ;Restore data segment.
POPF
CLI ;Interrupts off.
MOV AL,EOI ;Send End Of Interrupt
OUT COMMAND_PORT,AL ; to 8259A PIC.
POP AX ;Restore AX.
IRET ;Interrupt return.
INT_9_END: POP DS ;No-hot-key exit.
POPF
POP AX
JMP DWORD PTR CS:OLD_INT_9 ;Go to old INT 9 interrupt.
MONO_INT_9 ENDP
;-----------------------------------------;
INACTIVE: RET ;Quick exit.
ASSUME DS:_TEXT
ATTRIBUTES: CLD ;Strings operations forward.
CMP MODE_BYTE,0 ;Is attribute mode active?
JZ INACTIVE ;If no, done here; exit.
MOV BUSY_FLAG,1 ;Else, flag so non-reentrant.
PUSH AX ;Save some registers.
PUSH DS
MOV AX,40H ;Point to BIOS data segment.
MOV DS,AX
ASSUME DS:BIOS_DATA
MOV AL,CRT_MODE ;Retrieve video mode.
CMP AL,3 ;Is it color text mode?
JBE SAVE_REG ;If yes, continue.
CMP AL,7 ;Is it mono text mode?
JNZ QUICK_EXIT ;If no, graphics; exit.
SAVE_REG: PUSH BX
PUSH CX ;Else, save some more registers.
PUSH DX
PUSH DI
PUSH ES
MOV AX,CRT_COLS ;Retrieve CRT columns.
MOV CL,CRT_ROWS ;Retrieve CRT rows - 1.
OR CL,CL ;Is in non-zero?
JNZ DO_CRT_LENGTH ;If yes, good value.
MOV CL,24 ;Otherwise, use 25 - 1 row value.
DO_CRT_LENGTH: INC CL ;Adjust row.
MUL CL ;CRT length = rows * columns.
MOV CX,AX ;Store in counter.
MOV DX,ADDR_6845 ;Retrieve 6845 address.
ADD DX,6 ;Convert to Status register.
MOV DI,CRT_START ;Retrieve start of CRT buffer.
INC DI ;Point to first attribute.
MOV AX,0B000H ;Assume mono card segment.
CMP DX,3BAH ;Is it?
JZ VIDEO_SEG ;If yes, continue.
ADD AX,800H ;Else, color card segment.
VIDEO_SEG: MOV DS,AX ;Set segment registers.
MOV ES,AX
MOV BX,7007H ;Inverse video and normal attrib.
; Jmp Short SNOW_CHECK ;Add this instruction for CGA.
NOP ;NOP bytes to add jump to
NOP ; snow check routine via Debug.
NEXT_ATTRIB: MOV AL,[DI] ;Retrieve an attribute.
MOV AH,BH ;Assume inverse video.
TEST AL,AH ;Is background non-zero?
JNZ ADD_ATTRIB ;If yes, use 70h attribute.
MOV AH,BL ;Else, use 07h attribute.
ADD_ATTRIB: AND AL,NOT 77H ;Mask off all but intensity and
OR AL,AH ; blinking; add attribute.
STOSB ;Store the attribute.
INC DI ;Bump pointer past character.
LOOP NEXT_ATTRIB ;Do all attributes.
JMP SHORT RESTORE_REG
;---------------------------------------;
; Snow checking routine for CGA cards. ;
;---------------------------------------;
SNOW_CHECK: MOV AH,[DI] ;Retrieve an attribute.
MOV AL,BH ;Assume inverse video.
TEST AH,AL ;Is background non-zero?
JNZ ADD_ATTRIB2 ;If yes, use 70h attribute.
MOV AL,BL ;Else, use 07h attribute.
ADD_ATTRIB2: AND AH,NOT 77H ;Mask off all but intensity and
OR AH,AL ; blinking; add attribute.
HORZ_RET: IN AL,DX ;Get status.
TEST AL,1 ;Is it low?
JNZ HORZ_RET ;If not, wait until it is.
CLI ;No more interrupts.
HWAIT: IN AL,DX ;Get status.
TEST AL,1 ;Is it high?
JZ HWAIT ;If no, wait until it is.
XCHG AL,AH ;Retrieve character; now it's OK
STOSB ; to write to screen buffer.
STI ;Interrupts back on.
INC DI ;Bump pointer past character.
LOOP SNOW_CHECK ;Do all attributes.
RESTORE_REG: POP ES ;Restore registers.
POP DI
POP DX
POP CX
POP BX
ASSUME DS:_TEXT
QUICK_EXIT: POP DS
POP AX
MOV BUSY_FLAG,0 ;No longer busy.
RET
; DISPOSABLE DATA
; ---------------
SYNTAX LABEL BYTE
DB "Syntax: MONO [U]",CR,LF
DB "U = uninstall",CR,LF
DB "Hot key = Alt M"
DB CR,LF,LF,"$"
NOT_INSTALLED DB "MONO not installed",CR,LF,"$"
UNLOAD_MSG DB "MONO can't uninstall",CR,LF,"$"
NOT_ENOUGH DB "Not enough memory",CR,LF,"$"
ALLOCATE_MSG DB "Memory allocation error",CR,LF,BELL,"$"
INSTALL_MSG DB "Installed",CR,LF,"$"
UNINSTALL_MSG DB "Uninstalled",CR,LF,"$"
;--------------------------------------------------------------------;
; Search memory for a copy of our code, to see if already installed. ;
;--------------------------------------------------------------------;
INITIALIZE PROC NEAR
CLD ;All string operations forward.
MOV BX,OFFSET START ;Point to start of code.
NOT BYTE PTR [BX] ;Change a byte so no false match.
XOR DX,DX ;Start at segment zero.
MOV AX,CS ;Store our segment in AX.
NEXT_PARAG: INC DX ;Next paragraph.
MOV ES,DX
CMP DX,AX ;Is it our segment?
JZ ANNOUNCE ;If yes, search is done.
MOV SI,BX ;Else, point to our signature.
MOV DI,BX ; and offset of possible match.
MOV CX,16 ;Check 16 bytes for match.
REP CMPSB
JNZ NEXT_PARAG ;If no match, keep looking.
;------------------------------------------------;
ANNOUNCE: MOV DX,OFFSET SIGNATURE ;Display our signature.
CALL PRINT_STRING
MOV DX,OFFSET SYNTAX ;And syntax.
CALL PRINT_STRING
;------------------------------------------------;
PARSE: MOV SI,81H ;Point to command line again.
NEXT_PARSE: LODSB ;Get a byte.
CMP AL,CR ;Is it CR?
JZ INSTALL ;If yes, done here.
AND AL,5FH
CMP AL,"U" ;Is it "U" ?
JNZ NEXT_PARSE ;If no, next byte.
CALL CK_INSTALLED ;Else, see if installed.
MOV DX,OFFSET NOT_INSTALLED ;If no, exit with error message.
JZ MSG_EXIT
JMP SHORT UNINSTALL ;Else, uninstall.
;------------------------------------------------;
INSTALL: CALL CK_INSTALLED ;Check if already installed.
JZ CK_AVAILABLE ;If no, see if enough memory.
XOR AL,AL ;Else, done.
JMP SHORT EXIT ;Exit with ERRORLEVEL = 0.
;--------------------------------;
; This is the install procedure. ;
;--------------------------------;
CK_AVAILABLE: MOV BP,OFFSET SYNTAX ;End of resident portion.
ADD BP,15 ;Round up.
CMP BP,DS:[6] ;TSR > PSP bytes in segment?
MOV DX,OFFSET NOT_ENOUGH ;If yes, exit without installing
JA MSG_EXIT ; with message.
MOV AX,3508H ;Else, get INT 8 vector.
INT 21H
MOV OLD_INT_8[0],BX ;Save old interrupt.
MOV OLD_INT_8[2],ES
MOV DX,OFFSET MONO_INT_8 ;Install new interrupt.
MOV AX,2508H
INT 21H
MOV AX,3509H ;Get INT 9 vector.
INT 21H
MOV OLD_INT_9[0],BX ;Save old interrupt.
MOV OLD_INT_9[2],ES
MOV DX,OFFSET MONO_INT_9 ;Install new interrupt.
MOV AX,2509H
INT 21H
MOV AX,DS:[2CH] ;Get environment segment.
MOV ES,AX
MOV AH,49H ;Free up environment.
INT 21H
MOV DX,OFFSET INSTALL_MSG ;Display install message.
CALL PRINT_STRING
MOV DX,BP ;Retrieve resident request.
MOV CL,4
SHR DX,CL ;Convert to paragraphs.
MOV AX,3100H ;Return error code of zero.
INT 21H ;Terminate but stay resident.
;-------------------------------------------------------------------;
; Exit. Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
;-------------------------------------------------------------------;
MSG_EXIT: CALL PRINT_STRING
ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1.
EXIT: MOV AH,4CH ;Terminate.
INT 21H
;---------------------------------------------------;
; This subroutine uninstalls the resident MONO.COM. ;
;---------------------------------------------------;
UNINSTALL: MOV CX,ES ;Save segment in CX.
MOV AX,3508H ;Get interrupt 8.
INT 21H
CMP BX,OFFSET MONO_INT_8 ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JNZ UNINSTALL_ERR ;If no, exit with error message.
MOV AX,3509H ;Get interrupt 9.
INT 21H
CMP BX,OFFSET MONO_INT_9 ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JNZ UNINSTALL_ERR ;If no, exit with error message.
MOV AH,49H ;Return memory to system pool.
INT 21H
MOV DX,OFFSET ALLOCATE_MSG
JC MSG_EXIT ;Display message if problem.
MOV DX,ES:OLD_INT_8[0] ;Restore old INT 8.
MOV DS,ES:OLD_INT_8[2]
MOV AX,2508H
INT 21H
MOV DX,ES:OLD_INT_9[0] ;Restore old INT 9.
MOV DS,ES:OLD_INT_9[2]
MOV AX,2509H
INT 21H
PUSH CS
POP DS ;Point to our data.
MOV DX,OFFSET UNINSTALL_MSG ;Display uninstall message.
CALL PRINT_STRING
OR AL,AL ;Exit with ERRORLEVEL = 0.
JMP EXIT
UNINSTALL_ERR: MOV ES,CX ;If error, exit
MOV DX,OFFSET UNLOAD_MSG ; with error message.
JMP MSG_EXIT
INITIALIZE ENDP
;-------------------------------------------------------;
; OUTPUT: ZR = 1 if not installed; ZR = 0 if installed. ;
;-------------------------------------------------------;
CK_INSTALLED: MOV AX,ES
MOV BX,CS
CMP AX,BX ;Compare segments.
RET
;------------------------------------------------;
PRINT_STRING: MOV AH,9
DOS_INT: INT 21H ;Print string via DOS.
RET
_TEXT ENDS
END START