• Please review our updated Terms and Rules here

Programming > 80x25 text modes in DOS with Borland Turbo C++ 3.0

juj

Member
Joined
Jan 25, 2022
Messages
32
Hi all,

I am looking to change the usual DOS 80x25 console text mode into something like 132x44 or 132x60 so that I can use more real estate in console-like programs that print a lot of text out to stdout.

The SVGA/VESA aspect of switching to these modes is well covered, and I can set up the text modes I want.

However, I observe when I call INT 10h to set up e.g. 132x44 text mode in a program I compile with Borland Turbo C++ 3.0, then most of the text output API functions that it provides start to break down:
- gettextinfo() function returns 80x25 if I started the program in 80x25 mode but switched to 132x44 while running the program.
- gettextinfo() function returns and odd 132x25 mismatched resolution if current DOS text resolution was 132x44 already when I start the program.
- cprintf() function (for printf() with colors) behaves as if constrained by the window that gettextinfo() reports, e.g. it begins to scroll the view after 25 rows even though there would still be many lines of room on the console.
- gotoxy() does nothing if called with y coordinate > 25.

I found there is a DOS memory location 44Ah that contains the number of text columns the current mode has: https://wiki.osdev.org/Memory_Map_(x86) Observing that memory location does print out 132 columns correctly. I cannot find if there might exist a similar memory location somewhere?

The DOS interrupt for acquiring information about current video mode ( https://stanislavs.org/helppc/int_10-1b.html ), does correctly report 44 in the "22 byte number of displayed character rows" field, so I am thinking that this is maybe a Borland Turbo C++ 3.0 issue, and not a DOS/BIOS/VGA adapter issue.

So I am kind of leaning towards this just being a Borland bug, and I should roll out my own printf() functions to sidestep the issue.. but I wonder if there might be something that I might be overlooking? Maybe there could be a way to tell Borland about the nonstandard screen size? I found the window() function, but looks like that does not work to expand beyond 80x25 window. I was pondering if there might have been an easy way to disassemble what Borland does inside its gettextinfo() function to arrive to the wrong conclusion about number of rows, but my disasm skills weren't quite up to par for that..

Any tips? Thanks!
 
Well that's very curious.

I know back in the day, I did exactly what you were doing. We had some machines with some random graphics card that offered a bunch of extended character modes. I distinctly remember that the modes were unique, in that there was no guarantee that any other random card would support the same resolution. Good thing we bought 10 of them!

And I know I wrote a bunch of display routines to support the new resolution, but I'm guessing I never ran the printf code, and I supposed I was just storing into the frame buffer directly, because I never ran into your wrapping issues. But I also know I never queried anything asking resolution, I just switched the modes and "knew" what the values were.

Pretty sure this was Turbo 2, not 3, it certainly didn't have C++.
 
Borland's conio.h uses the textmode function to set the screen mode and dimensions. There was never SVGA support (even in Borland C++ 3/4/5), so 80x50 is the limit.

That said, Borland C++ (not Turbo) includes the runtime library (RTL) source. So you could potentially modify it to add support for other text modes.
 
the problem with most of those modes is, they often use either B000 or A000 for memory instead of the more common b800, and tihs messes up most anything expecting to talk to the screen..

so other programins printing to stdout, most of it goes through int 0x29, which is a front end to going out of the ANSI driver. If your ansi driver does not understand the mode you have switched into (132x60 etc, which uses 0xA0000), its going to come down to the driver know it or not. or if the bios default output char 0x0E function works correctly to line feed the entire screen up etc.
 
I am thinking that this is maybe a Borland Turbo C++ 3.0 issue, and not a DOS/BIOS/VGA adapter issue.

Correct. Borland's code only supports text modes up to 80x50. If you want VESA text mode support, you'll have to write your own text mode/printing routines (which, thankfully, are very easy to do given the nature of text mode).

Maybe there could be a way to tell Borland about the nonstandard screen size?

I think it's deeper than that, some of the code actually has clipping for cols>80 or rows>50 IIRC. You'll likely have to write your own.

the problem with most of those modes is, they often use either B000 or A000 for memory instead of the more common b800, and tihs messes up most anything expecting to talk to the screen..

That is not true. All text modes initiated with the built-in BIOS, EGA/VGA BIOS, or VESA BIOS have the base segment set to b800 for all color modes and b000 for monochrome modes. A cursory check of custom chipset modes for extended text rows/cols at https://faydoc.tripod.com/structures/00/0010.htm also shows the base for b800 for those modes.

It is possible that direct chipset commands for setting those modes might use a different segment, but I know of no software that attempted to do that; they either used application-specific drivers provided by the manufacturer (Wordperfect, Lotus 1-2-3, Microsoft Word, etc.) or they used VESA BIOS calls. Any new program written today is going to use VESA BIOS calls (ie. modes 108h through 10ch), so the OP can confidently use b800 as the segment.

Here's some example code to set a VESA BIOS text mode:

Code:
function setVESA(mode:word):word; assembler;
asm
        mov     bx,mode
        mov     mode,0                  ;reuse mode var to track state
        mov     ax,4f02h                ;set VESA BIOS mode
        int     10h
        cmp     al,4fh                  ;AL = 4Fh if function supported
        je      @FunctionSupported
        mov     mode,1                  ;function not supported
        jmp     @done

@FunctionSupported:
        cmp     ah,01h                  ;AH = status: 00h success, 01h fail
        jne     @done
        mov     mode,2
@done:
        mov     ax,mode                 ;return 1 if not supported,
                                        ;2 if supported but mode set failed,
                                        ;or 0 if successful
end;
 
Thanks, yeah, I am going down the route of rolling out my own printf, and that works out just fine. Plus now I can add printf formatting strings for color inline in the format string :D
 
Back
Top