Category : Assembly Language Source Code
Archive   : ASM4.ZIP
Filename : STATLINE.ASM
Output of file : STATLINE.ASM contained in archive : ASM4.ZIP
; STATLINE, by John Socha, Copyright 1986 Ziff-Davis Publishing Co. ;
; ;
; Here are the two interrupt vectors that we take over. The first ;
; interrupt, INT 9, is the hardware interrupt for the keyboard, and ;
; it's called every time you push or release a key. ;
; ;
; The other interrupt, INT 10h, points to the ROM BIOS routines that ;
; handle all of the screen I/O. We intercept it so that we can watch ;
; for commands to change the display mode. Since STATLINE only works ;
; in 80x25 text modes, STATLINE turns itself off as long as the screen ;
; is in a different mode. ;
;-----------------------------------------------------------------------;
VECTORS SEGMENT AT 0h
ORG 9h*4
KEYBOARD_INT_VECTOR LABEL DWORD ;Keyboard interrupt
ORG 10h*4
VIDEO_IO_VECTOR LABEL DWORD ;ROM BIOS Video I/O function calls
VECTORS ENDS
;-----------------------------------------------------------------------;
; STATLINE uses the following flags from the ROM BIOS's data area to ;
; control the screen. ;
;-----------------------------------------------------------------------;
ROM_BIOS_DATA SEGMENT AT 40h
ORG 10h
EQUIP_FLAG DB ? ;Equipment installed
ORG 17h
KBD_FLAG DB ? ;Used to determine display type
ORG 4Eh
CRT_START DW ? ;Starting address in buffer
ORG 63h
ADDR_6845 DW ? ;3x8 register, where x is B or D
ROM_BIOS_DATA ENDS
;-----------------------------------------------------------------------;
; This section of the ROM in a COMPAQ contains the 6 bytes 'COMPAQ' ;
; which we can use to identify a COMPAQ computer. COMPAQ computers ;
; have a display adapter that uses the monochrome display, but with ;
; registers and memory the same as a color graphics adapter. ;
;-----------------------------------------------------------------------;
COMPAQ_CO EQU 4F43h ;ASCII code of 'CO'
COMPAQ_SEG SEGMENT AT 0F000h
ORG 0FFEAh
COMPAQ_ID DW ? ;We should find 'CO' (4F43h) here
COMPAQ_SEG ENDS
;-----------------------------------------------------------------------;
; Here is the STATLINE's entry point. It jumps to the initialization ;
; routine which is at the very end so that we can throw it out of ;
; memory after we've used it. ;
;-----------------------------------------------------------------------;
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG, DS:CODE_SEG
ORG 100h ;Reserve for DOS Program Segment Prefix
BEGIN: JMP INIT_VECTORS
AUTHOR_STRING DB "Installed Statline, by John Socha"
DB 0Dh, 0Ah, '$'
OLD_KBD_FLAG DB 0 ;Most recent upper nibble of status
VIDEO_MODE DB ? ;Current video mode
STATUS_LINE_ENABLED DB 1 ;0 when we're in graphics modes
;-----------------------------------------------------------------------;
; The following table contains the character/attribute pairs for the ;
; states of the Scroll Lock, Num Lock, and Caps Lock keys. ;
; ;
; The first word contains the address for the character, and the second ;
; word contains the character/attribute pair. ;
;-----------------------------------------------------------------------;
ENTRY STRUC
OFFSET_FROM_TOP DW ? ;Offset from start of display memory
ATTRIBUTE_CHARACTER DB ? ;Attribute and character code
ENTRY ENDS
FLAG_CHARACTER_TABLE LABEL WORD
ENTRY <4084,' '> ;Scroll Lock, ' '
ENTRY <4084,12h> ;Scroll Lock, double-ended arrow
ENTRY <4080,' '> ;Num Lock, ' '
ENTRY <4080,23h> ;Num lock, '#'
ENTRY <4076,' '> ;Caps Lock, ' '
ENTRY <4076,18h> ;Caps Lock, up arrow
ROM_KEYBOARD_INT DD ?
ROM_VIDEO_IO_INT DD ?
;-----------------------------------------------------------------------;
; This procedure sends control off to the ROM BIOS routine, then checks ;
; the shift-lock flags on return and writes the new flag characters to ;
; the screen. ;
;-----------------------------------------------------------------------;
INTERCEPT_KEYBOARD_INT PROC FAR
ASSUME CS:CODE_SEG, DS:NOTHING
PUSHF ;Simulate INT with PUSHF and CALL
CALL ROM_KEYBOARD_INT ;Let ROM do the work
CMP STATUS_LINE_ENABLED,1 ;See if Status line enabled.
JNE NO_STATUS_LINE ;Not enabled.
CALL CHECK_STATUS_FLAGS ;Check flags and update status line
NO_STATUS_LINE:
IRET
INTERCEPT_KEYBOARD_INT ENDP
;-----------------------------------------------------------------------;
; This procedure checks the current setting of KBD_FLAGS against the ;
; last setting, and if the flags have changed, it updates the status ;
; line display. Check_status_flags also updates Old_kbd_flag. ;
;-----------------------------------------------------------------------;
CHECK_STATUS_FLAGS PROC NEAR
PUSH AX ;Save all the registers we use
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
ASSUME CS:CODE_SEG, DS:ROM_BIOS_DATA
MOV AX,ROM_BIOS_DATA ;Set DS so it points to BIOS data area
MOV DS,AX
MOV DX,ADDR_6845 ;Get the base address for the 6845
MOV AX,0B800h ;Segment address of graphics adapter
CMP DX,3D0h ;Is this the color graphics adapter?
JAE IS_COLOR_BOARD ;It's a color board, so don't change AX
MOV AX,0B000h ;Segment address for monochrome adapter
IS_COLOR_BOARD:
MOV ES,AX ;Use extra segment for display memory
ADD DX,03DAh-03D4h ;Point to status register
MOV BL,KBD_FLAG ;Get flag information
MOV CL,4 ;Put shift lock flags into lower nibble
SHR BL,CL
ASSUME CS:CODE_SEG, DS:CODE_SEG
MOV AX,CS ;Set DS to the local data (in CS)
MOV DS,AX
CMP BL,OLD_KBD_FLAG ;Have any of the status flags changed?
JE FLAGS_HAVENT_CHANGED ;No, then do nothing
MOV OLD_KBD_FLAG,BL ;Flags have changed, update status line
MOV SI,Offset FLAG_CHARACTER_TABLE
MOV CX,3 ;Repeat for three shift lock keys
SHIFT_LOCK_LOOP:
PUSH SI
SHR BL,1 ;Get next flag in carry
JNC READ_OFFSET ;Flag was 0, SI Ok
ADD SI,3 ;Skip over information
READ_OFFSET:
MOV DI,[SI] ;Get Offset
MOV AL,[SI+2] ;Get character for this flag
PUSH CX ;Save the CX register
MOV CL,AL ;Save the character in CL
WAIT_FOR_NON_RETRACE:
IN AL,DX ;Read status
TEST AL,8 ;In vertical retrace?
JNZ WAIT_FOR_NON_RETRACE ;Wait for vertical retrace to finish
WAIT_FOR_RETRACE:
IN AL,DX ;Read status
TEST AL,8 ;In vertical retrace?
JZ WAIT_FOR_RETRACE ;No, then wait for vertical retrace
MOV AL,CL ;Get the character we want to write
STOSB ;Write character to the screen
POP CX ;Recover the old value of CX
POP SI
ADD SI,6 ;Skip to next pair of entries
LOOP SHIFT_LOCK_LOOP
FLAGS_HAVENT_CHANGED:
POP ES
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
CHECK_STATUS_FLAGS ENDP
;-----------------------------------------------------------------------;
; This procedure reprograms the 6845 whenever a program switches modes ;
; into an 80x25 text mode. ;
;-----------------------------------------------------------------------;
INTERCEPT_VIDEO_IO PROC FAR
ASSUME CS:CODE_SEG, DS:NOTHING
OR AH,AH ;Check if called for SET MODE
JZ SET_MODE ;It's a SET MODE call
JMP ROM_VIDEO_IO_INT ;Not a SET MODE, call ROM BIOS
SET_MODE:
MOV VIDEO_MODE,AL ;Save new video mode
MOV STATUS_LINE_ENABLED,AH ;Disable STATLINE during mode change
PUSHF ;Simulate INT with PUSHF, CALL
CALL ROM_VIDEO_IO_INT ;Let ROM BIOS change video mode
CALL REPROGRAM_6845 ;Create 26th line again
MOV OLD_KBD_FLAG,0 ;Flags will be clear in new mode
CALL CHECK_STATUS_FLAGS ;Make sure we show current flags
IRET
INTERCEPT_VIDEO_IO ENDP
;-----------------------------------------------------------------------;
; The following tables describe how to reprogram the 6845 registers. ;
; Each pair describes how to change one register. The first number is ;
; the register that we want to reprogram, while the second number is ;
; the new value for that register. Reprogram_6845 stops when it sees ;
; a 0 for the register number. ;
;-----------------------------------------------------------------------;
MONOCHROME_TABLE LABEL BYTE
DB 4,26 ;Vertical total, 26 lines
DB 5,3 ;Vertical total adjust, scan lines
DB 6,26 ;Vertical displayed, 26 lines
DB 7,26 ;Vertical sync position, lines
DB 0 ;End of Monochrome table
COLOR_GRAPHICS_TABLE:
DB 6,26 ;Vertical displayed
DB 0 ;End of color graphics adapter table
;-----------------------------------------------------------------------;
; This procedure reprograms the 6845 so that it will show 26 rather ;
; than 25 lines. It uses the values from one of the tables above. ;
; ;
; This procedure also handles the COMPAQ, which is a special case. The ;
; COMPAQ uses a monochrome-type display, so it needs to be reprogrammed ;
; like a monochrome display, yet writes should be to 3Dxh registers ;
; rather than the 3Bxh registers used for an IBM monochrome display. ;
; ;
; F000:FFEA holds the word 'COMPAQ' on COMPAQ computers, so we can tell ;
; when we're running on a COMPAQ. ;
;-----------------------------------------------------------------------;
REPROGRAM_6845 PROC NEAR
ASSUME CS:CODE_SEG, DS:CODE_SEG
PUSH AX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
MOV AX,CS
MOV DS,AX ;Set up Data Seg
MOV STATUS_LINE_ENABLED,0 ;Initially disable status line
MOV AL,VIDEO_MODE ;Check video mode
CMP AL,1 ;In graphics mode?
JLE GRAPHICS_MODE ;Yes, don't reprogram 6845
CMP AL,3 ;Is display in a text mode?
JLE TEXT_MODE ;Yes, then we can reprogram 6845
CMP AL,7 ;Is it in the monochrome mode?
JNE GRAPHICS_MODE ;No, then don't reprogram 6845
TEXT_MODE: ;Yes, reprogram 6845
MOV STATUS_LINE_ENABLED,1 ;Enable status line in text modes
MOV SI,Offset MONOCHROME_TABLE
MOV DX,3B4h ;6845 registers for monochrome display
PUSH DS
MOV AX,ROM_BIOS_DATA ;Read equipment flag from low memory
MOV DS,AX
ASSUME CS:CODE_SEG, DS:ROM_BIOS_DATA
MOV AL,EQUIP_FLAG
AND AL,30h ;Isolate CRT switches
CMP AL,30h ;Is it the monochrome display?
POP DS
JE SET_REGISTERS ;Yes, the registers are correct
MOV DX,3D4h ;No, set registers for graphics adapter
PUSH DS
MOV AX,COMPAQ_SEG ;Now check to see if this is a COMPAQ
MOV DS,AX
ASSUME CS:CODE_SEG, DS:COMPAQ_SEG
CMP COMPAQ_ID, COMPAQ_CO ;Is this the 'CO' from COMPAQ?
POP DS ;Restore old DS
ASSUME CS:CODE_SEG, DS:CODE_SEG
JE SET_REGISTERS ;Is a COMPAQ, use monochrome data
MOV SI,Offset COLOR_GRAPHICS_TABLE ;No, use color graphics data
SET_REGISTERS:
CLD ;Clear direction flag for increment
ADAPTER_LOOP:
LODSB ;Get register number
OR AL,AL ;Are we at the end of the table?
JZ END_OF_ADAPTER_TABLE ;Yes, we're almost done
OUT DX,AL ;No, select this register
INC DX ;Point to data register
LODSB ;Get new register value
OUT DX,AL ;Set the register to its new value
DEC DX ;Point back to address register
JMP ADAPTER_LOOP ;Get the next register/value pair
END_OF_ADAPTER_TABLE:
GRAPHICS_MODE:
POP DS
POP SI
POP DX
POP CX
POP AX
RET
REPROGRAM_6845 ENDP
;-----------------------------------------------------------------------;
; This procedure initializes the interrupt vectors and the 6845 ;
; registers. It initializes both the Monochrome and color graphics ;
; adapter address so it will work on the COMPAQ as well as IBM PCs ;
;-----------------------------------------------------------------------;
INIT_VECTORS PROC NEAR
ASSUME CS:CODE_SEG, DS:CODE_SEG
LEA DX,AUTHOR_STRING ;Print out the author notice
MOV AH,9 ;Display this string
INT 21h
MOV AH,15 ;Check current video mode
INT 10h ;Call VIDEO_IO ROM BIOS routine
MOV VIDEO_MODE,AL
CALL REPROGRAM_6845
CALL CHECK_STATUS_FLAGS ;Display any flags now on
ASSUME CS:CODE_SEG, DS:VECTORS
MOV AX,VECTORS ;Set up the data segment for vectors
MOV DS,AX
CLI ;Don't allow interrupts
MOV AX,Word Ptr KEYBOARD_INT_VECTOR
MOV Word Ptr ROM_KEYBOARD_INT,AX
MOV AX,Word Ptr KEYBOARD_INT_VECTOR[2]
MOV Word Ptr ROM_KEYBOARD_INT[2],AX
MOV Word Ptr KEYBOARD_INT_VECTOR, Offset INTERCEPT_KEYBOARD_INT
MOV Word Ptr KEYBOARD_INT_VECTOR[2],CS
MOV AX,Word Ptr VIDEO_IO_VECTOR
MOV Word Ptr ROM_VIDEO_IO_INT,AX
MOV AX,Word Ptr VIDEO_IO_VECTOR[2]
MOV Word Ptr ROM_VIDEO_IO_INT[2],AX
MOV Word Ptr VIDEO_IO_VECTOR, Offset INTERCEPT_VIDEO_IO
MOV Word Ptr VIDEO_IO_VECTOR[2],CS
STI ;Allow interrupts again
MOV DX,Offset INIT_VECTORS ;End of resident portion
INT 27h ;Terminate but stay resident
INIT_VECTORS ENDP
CODE_SEG ENDS
END BEGIN
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
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/