• Please review our updated Terms and Rules here

VGA Text mode "03" but 320x240

Mills32

Experienced Member
Joined
Sep 25, 2018
Messages
149
Location
Spain
I'm trying to get cool effects by using text mode and uploading custom tiles/fonts to VGA. I already tested custom fonts on mode 3, and also changed cell size to 8x8, and disabled horizontal spacing so that 8x8 tiles fill the whole screen without vertical lines. That results in 640x400 resolution and it worked well on a real VGA, dosbox, PCem...

Now I want to set the screen resolution to 320x240 to create a 40x30 text mode with 16 colors, so that it resembles a graphic mode, and it is faster to update the screen. I found a code to set the mode to 40x25 and tweaked it to be 40x30. This worked on dosbox, PCem... but on a real vga it produed an incompatible signal for my LCD (It should generate 320x240 60 hz). I don't have a CRT to test, anyway if it is not working on LCD there is something wrong.

Emulators and even an fpga core generated this:

tinydemo_000.png


These are the values I entered to set vga registers, I used some values from 320x240 mode X, the important ones are CRTC_INDEX values, the others just set the text mode without using bios interrupts :

Code:
unsigned char g_40x30_text[] = {
   //MISC_OUTPUT (0x03c2)
    0x67,
   //SC_INDEX (0x03c4)
    0x03, 0x09, 0x03, 0x00, 0x02,
   //CRTC_INDEX (0x03d4)
    0x28, 0x28, 0x28, 0x90, 0x2B, 0xA0, 0x0D, 0x3E,
    0x00, 0x87, 0x20, 0x0E, 0x00, 0x00, 0x00, 0xA0,
    0xEA, 0xAC, 0xDF, 0x14, 0x1F, 0xe7, 0x06, 0xA3,
    0xFF,
   //GC_INDEX (0x03ce)
    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
    0xFF,
   //AC_INDEX (0x03c0)
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
    0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
    0x0C, 0x00, 0x0F, 0x08, 0x00,
};
 
VGA monitors don't really distinguish between a horizontal resolution of 640 and 320. As far as the monitor is concerned, a raster line is just a stream of analog data, and it's agnostic of how it's divided up into pixels.

Anyway: when you're changing horizontal timings, it's not just a matter of sending out the correct register values. There's a specific sequence of things... and apparently many VGA chipsets are very finicky about it.
Let's see how I had to do it in my font editor....

Start with the CRTC (0x3D4):
  • Read register 0x11, clear bit 7 (to deprotect registers 00-07), write back the value
  • Then send the horizontal timing values to registers 00-05:
    Code:
    go_40col:        db 02Dh, 027h, 028h, 090h, 02Bh, 0A0h;___________
    ;         ___________/     /     |      \__     \______           \
    ;        /            ____/      |         \           \          End
    ;    Horiz.          /        Start        End        Start      Horiz.
    ;    Total     End Horiz.     Horiz.      Horiz.      Horiz.    Retrace
    ;               Display      Blanking    Blanking    Retrace
  • Set bit 7 of register 0x11 again, to re-protect those dangerous timing registers. (Probably optional, but why not be nice to your users and their potentially garbage CRTs) ;)
Then the Sequencer port (0x3C4):
  • SET synchronous reset (send 0x1 to register 00)
  • Read the Clocking Mode (register 01), set bit 3 (=divide dot clock by 2), write back the value
  • CLEAR synchronous reset (send 0x3 to register 00)
I *think* that's it - at least for the part of switching from 80 to 40 columns. About going from 200 lines/70Hz to 240/60Hz, I don't have code for that, but you can probably take those vertical timings from mode X and set them just after you do registers 00-05.
 
Last edited:
VGA monitors don't really distinguish between a horizontal resolution of 640 and 320. As far as the monitor is concerned, a raster line is just a stream of analog data, and it's agnostic of how it's divided up into pixels.

Anyway: when you're changing horizontal timings, it's not just a matter of sending out the correct register values. There's a specific sequence of things... and apparently many VGA chipsets are very finicky about it.
Let's see how I had to do it in my font editor....

Start with the CRTC (0x3D4):
  • Read register 0x11, clear bit 7 (to deprotect registers 00-07), write back the value
  • Then send the horizontal timing values to registers 00-05:
    Code:
    go_40col:        db 02Dh, 027h, 028h, 090h, 02Bh, 0A0h;___________
    ;         ___________/     /     |      \__     \______           \
    ;        /            ____/      |         \           \          End
    ;    Horiz.          /        Start        End        Start      Horiz.
    ;    Total     End Horiz.     Horiz.      Horiz.      Horiz.    Retrace
    ;               Display      Blanking    Blanking    Retrace
  • Set bit 7 of register 0x11 again, to re-protect those dangerous timing registers. (Probably optional, but why not be nice to your users and their potentially garbage CRTs) ;)
Then the Sequencer port (0x3C4):
  • SET synchronous reset (send 0x1 to register 00)
  • Read the Clocking Mode (register 01), set bit 3 (=divide dot clock by 2), write back the value
  • CLEAR synchronous reset (send 0x3 to register 00)
I *think* that's it - at least for the part of switching from 80 to 40 columns. About going from 200 lines/70Hz to 240/60Hz, I don't have code for that, but you can probably take those vertical timings from mode X and set them just after you do registers 00-05.
It worked!. I also used a software called "tweak" to test modes and I got the 40x30 mode working.

Now I need some kind of map editor to draw things in that mode. I found "the draw" but it uses regular fonts and colors.

Does anybody know any map tile editor which could be configured to use vga text mode limitations (2 color per tile)?

EDIT: I found a lot of cool editors for "ascii" art which can use custom characters for c64, ega vga etc... The best one for me is playscii, because it exports a very simple format that can be edited with notepad to arrange the elements like this: "bg color (0-15), character (0-256), fg color (0-15)".
 
Last edited:
Hi, Mills32! Does this has something to do with this demo of yours (by the way, it looks very promising):

Yes, that worked using regular text mode (720x400) converted to 640x400. I wanted to make tiles bigger so that it looks more like a graphics mode.
 
Back
Top