Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the board
Thread view  Mix view  Order
Laaca

Homepage

Czech republic,
14.11.2020, 11:00
 

How to detect the text mode? (Developers)

It was slightly mentioned in the DWED text editor thread - the cooperation with various text modes.
I like when the text mode program can cooperate with the already set text mode and does not try to change it into own mode. My beloved Volkoc commander works in this way.
But, when the graphic mode is present, it is not more possible to use the standard videomemory access scheme (segment B800h, even addresses chars, odd addresses attributes).
So the question is, how to easily distinguish between text mode and graphic mode.

I might thing that I am idiot, but I am looking for scheme working in various tweaked modes (like 90x28), SVGA text modes and special tweaked modes set by utility SVGATextMode which are basicaly graphic modes but somehow modified to be allowed the text mode videomemory access scheme.

---
DOS-u-akbar!

Japheth

Homepage

Germany (South),
14.11.2020, 16:01

@ Laaca

How to detect the text mode?

> So the question is, how to easily distinguish between text mode and graphic
> mode.

If the graphics card is VGA compatible, there are at least 2 options:

1. graphics controller, port 3CEh, index 6: if bit 0=1, graphics mode active
2. attribute controller, port 3C0h, index 10h: if bit 0=1, graphics mode.

---
MS-DOS forever!

tkchia

Homepage

15.11.2020, 08:01

@ Japheth

How to detect the text mode?

Hello Laaca, hello Japheth,

> > So the question is, how to easily distinguish between text mode and
> graphic
> > mode.

> If the graphics card is VGA compatible, there are at least 2 options:
> 1. graphics controller, port 3CEh, index 6: if bit 0=1, graphics mode
> active
> 2. attribute controller, port 3C0h, index 10h: if bit 0=1, graphics mode.

Is there anything that will also work with MDA or CGA graphics cards? :-)

I think a good way to test specifically whether one can directly peek and poke 0xb800:0 or 0xb000:0, etc., would be to query the mode number. To do this, what my libi86 project currently does is to call int 0x10, ax = 0x4f03, and if that fails, fall back on int 0x10, ah = 0x0f.

I expect that most if not all tweaked 80×__ modes will have a mode number of 0x0003, except with differing numbers of text rows.

(To spot for text modes in general, for my libi86, I currently use bit 1 of 0x40:0x65 (see Ralf Brown's Interrupt List). I am not sure how reliable that is though.)

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

DosWorld

15.11.2020, 15:12

@ Laaca

How to detect the text mode?

I want join to thread, but in another direction.

Howto detect text-mode segment 0xB000 ? (instead 0xB800)
This is case for MDA and Hercules (not sure).
Is it enough - 0040:0065 bit 3 ? (2 in RBIL notation)

When i was a child - i known it, but forgot it now. :(

---
Make DOS great again!

Carthago delenda est, Ceterum censeo Carthaginem delendam esse.

Japheth

Homepage

Germany (South),
15.11.2020, 17:13

@ DosWorld

How to detect the text mode?

> Howto detect text-mode segment 0xB000 ? (instead 0xB800)
> This is case for MDA and Hercules (not sure).
> Is it enough - 0040:0065 bit 3 ? (2 in RBIL notation)

Checking BIOS variables is ok in most cases. Usually if word at 40h:63h is 3D4h, it's meant a "color" mode starting at 0B800h, and 3B4h means "monochrome" mode at 0B000h

What's more fun is to check the graphics controller, "miscellaneous" register 6, bits 2-3:


       3  2          Addressing Assignment                                                               
       0  0          A0000 for 128KB                                                                     
       0  1          A0000 for 64KB                                                                       
       1  0          B0000 for 32 KB                                                                     
       1  1          B8000 for 32 KB                                           


So you can even set your text mode buffer to A000, size 128 KB. However, I'm not sure if all VGA-compatible cards will accept this.

http://www.o3one.org/hwdocs/vga/vga_app.html

---
MS-DOS forever!

DosWorld

15.11.2020, 18:49

@ Japheth

How to detect the text mode?

Thank you!

PS: I pickup one "MDA/Hercules adapter" (unknown which one) on ebay and will play with it and check to be sure (when arrive, expecting - next year).

---
Make DOS great again!

Carthago delenda est, Ceterum censeo Carthaginem delendam esse.

jassenna

Campinas,SP,Brazil,
30.12.2020, 17:56

@ Japheth

How to detect the text mode?

> > So the question is, how to easily distinguish between text mode and
> graphic
> > mode.
>
> If the graphics card is VGA compatible, there are at least 2 options:
>
> 1. graphics controller, port 3CEh, index 6: if bit 0=1, graphics mode
> active
> 2. attribute controller, port 3C0h, index 10h: if bit 0=1, graphics mode.

There is a third that I use:
INT10 function 1Bh . This function is well documented both in RBIL
and in "PC Video Systems".
It returns a 64 byte data structure containing, among other info,
video mode, number of characters/line, number of lines/screen.

tkchia

Homepage

31.12.2020, 08:16

@ jassenna

How to detect the text mode?

Hello jassenna,

> There is a third that I use:
> INT10 function 1Bh . This function is well documented both in RBIL
> and in "PC Video Systems".
> It returns a 64 byte data structure containing, among other info,
> video mode, number of characters/line, number of lines/screen.

Thanks, interesting. But I see that, like int 0x10, ax = 0x4f03, it is not supported by all BIOSes, so one will need to fall back on one of the other detection methods (e.g. int 0x10, ah = 0x0f), in any case...

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

bretjohn

Homepage E-mail

Rio Rancho, NM,
31.12.2020, 17:52
(edited by bretjohn, 31.12.2020, 18:16)

@ Laaca

How to detect the text mode?

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

jassenna

Campinas,SP,Brazil,
01.02.2021, 00:02

@ tkchia

How to detect the text mode?

tkchia said:

> Thanks, interesting. But I see that, like int 0x10, ax = 0x4f03, it is not
> supported by all BIOSes, so one will need to fall back on one of the other
> detection methods (e.g. int 0x10, ah = 0x0f), in any case...

Do you know any (EGA ir later) video adapter that
does not support this function ? I am interested
because I have used few adapters and all did work,
but design of a fallback would depend on how often
one shall find an incompatible video BIOS.

tkchia

Homepage

01.02.2021, 14:26

@ jassenna

How to detect the text mode?

Hello jassenna,

> Do you know any (EGA ir later) video adapter that
> does not support this function [int 0x10,
> ah = 0x1b]? I am interested
> because I have used few adapters and all did work,
> but design of a fallback would depend on how often
> one shall find an incompatible video BIOS.

I am not very sure about that myself. But RBIL lists the function as "PS, VGA/MCGA", so my guess is that not all EGA cards actually support it.

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

rr

Homepage E-mail

Berlin, Germany,
01.02.2021, 17:56

@ tkchia

How to detect the text mode?

> > Do you know any (EGA ir later) video adapter that
> > does not support this function [int 0x10,
> > ah = 0x1b]? I am interested
> > because I have used few adapters and all did work,
> > but design of a fallback would depend on how often
> > one shall find an incompatible video BIOS.
>
> I am not very sure about that myself. But RBIL lists the function as "PS,
> VGA/MCGA", so my guess is that not all EGA cards actually support it.

I had a quick look to my physical copies of the books "VGA-Kompendium" (German) und "Programmer's Guide to the EGA, VGA, and Super VGA Cards". Both say nothing about function 1Bh on the EGA card. So expect, that RBIL is right with saying "PS,VGA/MCGA".

If one of the late EGA cards supports this call: fine.

---
Forum admin

Back to the board
Thread view  Mix view  Order
22049 Postings in 2034 Threads, 396 registered users, 273 users online (0 registered, 273 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum