Below is some code I use in my TSR programs that "write" to the screen (CLOCK, SERIAL, and some others I'm working on). It may help with what you're trying to do, or somebody may be able to tell me what I'm doing wrong.
This is the code I call to detect what type of monitor there is (VGA, EGA, CGA, or MDA) and whether it is color or monochrome:
;------------------------------------------------------------------------------
;FIND OUT THE TYPE OF DISPLAY ADAPTER INSTALLED
;Inputs: DS = ES = Local and TSR Data Area
; (This is done before TSR is installed)
; [ProgFlags],InMemory
;Outputs: [VideoType] = MDA, CGA, EGA, or VGA
; [VideoSegment] = B000h (if mono) or B800h (if color)
;Changes:
;------------------------------------------------------------------------------
GetVideoType:
PUSH AX,BX,CX,DI,SI,ES ;Save used registers
TEST [ProgFlags],InMemory ;Are we already installed in memory?
JNZ >V90 ;If so, we've already done this
MOV AX,40h ;ES =
MOV ES,AX ; BIOS data area
MOV DI,OFFSET VideoType ;Point [DI] at VideoType
MOV SI,OFFSET VideoSegment ;Point [SI] at VideoSegment
MOV B [DI],VGA ;Assume
MOV W [SI],VSegColor ; VGA
V10: ;Test for VGA
MOV AX,1C00h ;Function 1Ch (get VGA save state size)
MOV CX,1 ;SubFunction 1 (Get Size of BIOS Data Area)
MOV BX,-1 ;Preset unrealistic return value (BX)
INT 10h ;Do it
CMP AL,1Ch ;Is the function supported?
JNE >V20 ;If not, it can't be VGA
CMP BX,-1 ;Is the return value valid?
JNE >V30 ;If so, it's VGA
V20: ;Test for EGA
MOV B [DI],EGA ;Assume EGA
MOV AH,12h ;Function 12h (EGA Alternate Select)
MOV BX,0FF10h ;Subfunction (BL) 10h (Return EGA information)
;Preset unrealistic return value (BH)
INT 10h ;Do it
CMP BL,10h ;Is the function supported?
JE >V40 ;If not, it can't be EGA
CMP BH,-1 ;Is the return value valid?
JE >V40 ;If not, it can't be EGA
V30: ;Test if EGA/VGA Active, and for Mono Display
MOV AL,ES:[87h] ;Get the EGA/VGA Information byte
TEST AL,08h ;Is the EGA/VGA Active?
JNZ >V40 ;If not, find the Active Display
CMP B ES:[49h],7 ;Is it Video Mode 7 (Mono Text Mode)?
JNE >V35 ;If not, continue
MOV W [SI],VSegMono ;If so, the EGA/VGA is emulating MDA
V35: ;Mono emulation handled
TEST AL,02h ;Is it a Monochrome Monitor?
JZ >V90 ;If not, we're done
OR [EMSFlags2],MonoMonitor ;If so, mark it as Monochrome
JMP >V90 ;Done
V40: ;Test for CGA
MOV B [DI],CGA ;Assume CGA
CMP W ES:[63h],03B4h ;Is the CRT Controller Base I/O Address MDA?
JNE >V90 ;If not, we're done
V50: ;MDA
MOV B [DI],MDA ;Mark as MDA
MOV W [SI],VSegMono ; and set mono video segment
V90: ;Done
POP ES,SI,DI,CX,BX,AX ;Restore used registers
RET
This is the part of the program that detects whether the program is currently in text or graphics mode. In the part of the program that calls this code, I set ES to the BIOS data area (0040h) and put the current Video Mode (at ES:[49h]) in AL and then call this (this is A86 source code -- you'll need to tweak it a little if you're not using A86):
;------------------------------------------------------------------------------
;TEST AND SEE IF THE CUIRRENT VIDEO MODE IS TEXT OR GRAPHICS
;Inputs: DS = EMS/DPMS Segment/Selector
; ES = BDA Segment/Selector (0040h or Equivalent Selector)
; AL = Current Video Mode
;Outputs: [EMSFlags].GraphicsMode
;Changes:
;NOTES: Determining whether or not the screen is currently in a graphics mode
; or a text mode can be very tricky. There have been so many
; proprietary video modes over the years, particularly in the early
; days of PC's (before VESA), that it is just about impossible
; to handle all of the different possibilities. It would be hard
; enough just to be able to correctly recognize all of the different
; video cards, much less keep track of all the different modes they
; can operate in.
; Modern PC's can be a little bit easier to handle, particularly if
; they follow the VESA standards. However, not even all modern
; video cards are 100% compatible with VESA (if they were, Windows
; would only need one video Driver which could handle every
; modern video card, no matter who made it).
; The methodology we use to determine whether the current mode
; is text or graphics is not 100% foolproof, but works pretty well.
; First of all, we just check the VideoMode byte in the BIOS. If it's
; one of the common, standard ones (less than 14h), we know what it is.
; If it's more than 13h, it's not "standard", we do some further
; testing.
; The "complicated" test we perform is to try and read some text
; from the screen using INT 10h, Function 8. This function
; will read "text" from the screen, even if the screen is in
; graphics mode. That is, it will compare the pixels on the screen
; at the current cursor position and compare them to the bitmaps
; it has of what each ASCII character is supposed to look like.
; If there is a match, the function will return the ASCII code
; associated with the character. If there is no match,
; it returns ASCII 0. We check a total of 12 "characters" on the
; screen, and if any of them return a 0, we assume the screen is
; in a graphics mode. While this methodology can return both
; false positives and false negatives, it seems to be pretty
; reliable. Most of the time, the video mode is one of the
; "standard" ones anyway, especially with DOS programs.
;------------------------------------------------------------------------------
TestGraphicsMode:
PUSH AX,BX,CX,DX ;Save used registers
AND [EMSFlags],(NOT GraphicsMode) ;Assume Text mode
CMP AL,4 ;Is it mode 0-3?
JB >G90 ;If so, it's Text
CMP AL,7 ;Is it mode 7?
JE >G90 ;If so, it's Text
CMP AL,13h ;If not, is it mode 4-6 or 8-13h?
JBE >G70 ;If so, it's Graphics
CMP W ES:[4Ch],8000h ;Is a page more than 32,768 bytes long?
JA >G70 ;If so, it's Graphics
G10: ;Need to do "special" graphics test
MOV BH,ES:[62h] ;Put video page number in BH
CALL GetCursor ;Get cursor position (DX)
PUSH DX ;Save cursor position
MOV CX,12 ;Test 12 characters
XOR DX,DX ;Put cursor in upper left-hand corner
G20: ;Loop to here to test each character
CALL PutCursor ;Set cursor position (DX)
ADD DX,0101 ;Move the cursor down and to the right
MOV AH,8 ;Function 8 (Read character and attribute)
INT 10h ;Do it
OR AL,AL ;Is it a legitimate character?
LOOPNZ G20 ;If legitimate, keep testing
POP DX ;Get the original cursor position back again
CALL PutCursor ;Restore original cursor position
JCXZ >G90 ;If we got 12 legitimate characters, assume Text
G70: ;Is Graphics mode
OR [EMSFlags],GraphicsMode ;Mark as Graphics
G90: ;Done
POP DX,CX,BX,AX ;Restore used registers
RET
;------------------------------------------------------------------------------
;READ OR SET CURSOR POSITION
;Inputs: DH = Cursor Row (if setting position)
; DL = Cursor Column (if setting position)
;Outputs: DH = Cursor Row
; DL = Cursor Column
;Changes:
;------------------------------------------------------------------------------
GetCursor:
PUSH AX ;Save used register
XOR AH,AH ;Flag for Get Cursor
JMP >C00 ;Do it
PutCursor:
PUSH AX ;Save used register
MOV AH,-1 ;Flag for PutCursor
; JMP >C00 ;Do it
C00:
PUSH BX,CX,DS ;Save used registers
PUSHF ;Save flags
CLI ;Disable interrupts
CALL GetBDASegDS ;DS = BIOS Data Area
MOV BX,50h ;Offset of the cursor locations
XOR CX,CX ;Compensate
MOV CL,[62h] ; for the
ADD BX,CX ; video
ADD BX,CX ; page
OR AH,AH ;Are we getting the cursor?
JNZ >C90 ;If not, just store it
MOV DX,[BX] ;Get the cursor location
C90: ;DX = New cursor location
MOV [BX],DX ;Store the cursor location
POPF ;Restore flags
POP DS,CX,BX ;Restore used registers
POP AX ;Restore used register
RET |