Page 1 of 1
VGA colors in 80x25 text mode?
Posted: Sun Jun 19, 2011 11:10 am
by mariuszp
Hi, I was writing an extension for my kernel which would change the 16 VGA colors (for 80x25 text mode). I tried following Brackeen's tutorial on 256-color 0x13 mode, because in my old kernel (which I abandoned), I was able to set colors in 80x25 text mode in the exact same way. Now, the thing that goes wrong is that color 0 changes OK, but color 15 doesn't. I haven't tried other colors, but does anyone know how I should implement this correctly? Here's my extension:
Code: Select all
/*
vgacol.h
Custom VGA colors kernel extension
This extension is "always enable". When it is
"disabled" (default ;)), it is only used to make
sure all colors are displayed appropriately on all
VGA screens (BIOS-independent).
Bibliography:
http://www.brackeen.com/vga/basics.html
http://www.brackeen.com/vga/bitmaps.html
*/
#ifndef _VGACOL_H
#define _VGACOL_H
#include <atom/kernel.h>
typedef struct color_struct
{
u8int red;
u8int green;
u8int blue;
} __attribute__ ((packed)) color_t;
color_t colors[16] = {
{1, 1, 1}, /* black */
{1, 1, 32}, /* blue */
{1, 32, 1}, /* green */
{1, 32, 32}, /* cyan */
{32, 1, 1}, /* red */
{32, 1, 32}, /* magenta */
{16, 16, 1}, /* brown */
{32, 32, 32}, /* light gray */
{16, 16, 16}, /* dark gray */
{1, 1, 63}, /* light blue */
{1, 63, 1}, /* light green */
{1, 63, 63}, /* light cyan */
{63, 1, 1}, /* light red */
{63, 1, 63}, /* light magenta */
{63, 63, 1}, /* yellow */
{63, 63, 63} /* white */
};
void vgacol()
{
/* write VGA colors */
while ((inb(0x03DA) & 0x08));
while (!(inb(0x03DA) & 0x08));
int i=0;
for (i=0; i<16; i++)
{
//outb(0x03C8, i);
printdec(colors[i].red); printk(" ");
printdec(colors[i].green); printk(" ");
printdec(colors[i].blue); printk("\n");
outb(0x03C9, colors[i].red);
outb(0x03C9, colors[i].green);
outb(0x03C9, colors[i].blue);
};
while (1);
};
#endif
When I change white and black, only black changes (to magenta) on the screen. The prindec()s print out the palette correctly.
And yes, I know that the palette I put there is exactly the same as VGA's original one, but when I change color 15 I don't see the effect, and that's why I'm asking. Is there something I'm doing wrong?
P.S. changing light red doesn't seem to work either... only color 0 is changing...
Re: VGA colors in 80x25 text mode?
Posted: Sun Jun 19, 2011 12:16 pm
by Owen
Is there a reason why the write to - what is I assume, anyway (my VGA memory is hazy) - the palette index port is commented out?
Re: VGA colors in 80x25 text mode?
Posted: Sun Jun 19, 2011 2:25 pm
by Combuster
Not writing the DAC address is one bug (though it might just happen to work because the bios loads the entire DAC after which the address ends up being 0 again). It should however increment automatically after each three DAC data writes, so you only need to write it once, before the loop.
The bigger problem is the EGA palette. Since you are in 16-colour mode, the 4 colour bits are mapped through the EGA palette to 6 bits, selecting colours from a grand choice of 64. Worse, the default setting makes sure that colours 0..15 do not map to DAC entries 0..15, but rather go all over that choice of 64.
Re: VGA colors in 80x25 text mode?
Posted: Mon Jun 20, 2011 12:35 am
by Brendan
Hi,
Combuster wrote:The bigger problem is the EGA palette. Since you are in 16-colour mode, the 4 colour bits are mapped through the EGA palette to 6 bits, selecting colours from a grand choice of 64. Worse, the default setting makes sure that colours 0..15 do not map to DAC entries 0..15, but rather go all over that choice of 64.
My book ("Programmer's Guide to the EGA, VGA and Super VGA Cards") explains it like this..
For EGA cards, the 4-bit colour is used as an index into a 16-entry palette to select one of 64 possible colours (where the 64 possible colours are "2-bit red, 2-bit green and 2-bit blue").
For VGA cards, the 4-bit colour is used as an index into a 16-entry EGA palette to select a 6-bit value, and then this 6-bit value is used as an index in the VGA palette to select one of 262144 possible colours (where the 262144 possible colours are "6-bit red, 6-bit green and 6-bit blue").
For VGA cards, the EGA palette is meant to be like this (as default):
Code: Select all
EGA VGA
0x0 0x00 Black
0x1 0x01 Blue
0x2 0x02 Green
0x3 0x03 Cyan
0x4 0x04 Red
0x5 0x05 Magenta
0x6 0x14 Brown
0x7 0x07 Light Gray
0x8 0x38 Gray
0x9 0x39 Light Blue
0xA 0x3A Light Green
0xB 0x3B Light Cyan
0xC 0x3C Light Red
0xD 0x3D Light Magenta
0xE 0x3E Light Yellow
0xF 0x3F White
Where "EGA" is the 4-bit original data value, and "VGA" is the 6-bit value used in the VGA palette to find the final colour. Notice how they're not sequential (and that brown is strange).
A while ago I did some experiments with the palette for 16-colour graphics modes (using BIOS functions to set the palette/s). I wanted to setup 16-colour graphics modes as "1-bit red, 2-bit green and 1-bit blue" to make my dithering code (which converts "8-bit blue, 8-bit red, 8-bit green" source data) simpler and faster. I found that:
- some modern (Super VGA) video cards do it right (as described above) and some don't
- there's no combination (of EGA and VGA palette values) that works correctly on all modern video cards
- there's no way to determine if the video card does it right or not (at least not without a huge blacklist/whitelist with an entry for each video card)
In the end I couldn't get it to work reliably on all video cards (only about 75% of them) and gave up. I'd assume that the way palettes are used for 16-colour text modes is the same as 16-colour graphics modes, and that you'll have the same problem.
Cheers,
Brendan
Re: VGA colors in 80x25 text mode?
Posted: Mon Jun 20, 2011 5:15 am
by egos
Sorry, I think it will be correctly to write that the second column contains EGA colors/VGA indexes in DAC.
Now I don't have compatibility with EGA therefore I initialize "Attribute Controller" with 0-15 and load only first 16 DAC triplexes when update palette. Default palette (0) is compatible with EGA by colors but not by values stored in "Attribute Controller".
Re: VGA colors in 80x25 text mode?
Posted: Mon Jun 20, 2011 12:55 pm
by mariuszp
Thanks, it works now. In my code I added a map of "EGA -> VGA" palette indexes as posted by Brendan, and it's working
I just look up the table and insert the right value into the palette index port, and so on. And everything is fine!
Re: VGA colors in 80x25 text mode?
Posted: Mon Jun 20, 2011 8:05 pm
by IanSeyler
Thanks Brendan!
I had no idea why color 0x6 was not being set properly when I updated the palette. Now I find out that it is really 0x14 that needs to be set thus fixing the bug.
http://code.google.com/p/baremetal/sour ... nit_64.asm
Re: VGA colors in 80x25 text mode?
Posted: Wed Jun 22, 2011 2:02 am
by egos
The values 0-15 are correct for palette registers of "Attribute Controller" in VGA compatible cards and more simple. They are just indexes in DAC (4 or 6 low-significant bits of indexes). Total initialization of VGA register set gives good result with this values. Here is my default palette that compatible with EGA colors 0...5, 0x14, 7, 0x38... (see attach). And here is the code to initialize DAC with this palette.
Code: Select all
mov dl,VIDEO_DACMR and 0xFF
mov al,0x0F ; mask to use only first 16 triplexes
out dx,al
mov dl,VIDEO_DACAWMR and 0xFF
mov al,0 ; base index
out dx,al
mov dl,VIDEO_DACDR and 0xFF
mov ecx,16*3 ; count of bytes to write
rep outsb
Re: VGA colors in 80x25 text mode?
Posted: Wed Jun 22, 2011 11:02 am
by IanSeyler
What is VIDEO_DACMR and why are you only setting DL?
This is my old code (That did not set color 6 or the high colors properly)
Code: Select all
xor eax, eax
mov dx, 0x03C8 ; DAC Address Write Mode Register
out dx, al
mov dx, 0x03C9 ; DAC Data Register
mov rcx, 16 ; 16 colors
mov rsi, palette
nexttritone:
lodsb
out dx, al
lodsb
out dx, al
lodsb
out dx, al
dec rcx
cmp rcx, 0
jne nexttritone
Re: VGA colors in 80x25 text mode?
Posted: Wed Jun 22, 2011 12:16 pm
by egos
Code: Select all
VIDEO_DACMR equ 0x3C6 ; I think it's DAC Mask Register
...
VIDEO_ISR1 equ 0x3DA
...
mov edx,VIDEO_ISR1 ; set address for first i/o operation (dh=3)
...
mov dl,VIDEO_DACMR and 0xFF
...
Re: VGA colors in 80x25 text mode?
Posted: Wed Jun 22, 2011 3:33 pm
by Combuster
in other words, its a poorly documented trick to optimize
o16 mov dx, register; out dx, al;
to
mov dh, 0x03 ; all vga registers take the form of 3xx; add three bytes here
(...)
mov dl, register; out dx, al; save two bytes for each of these
Using just the DAC mask however breaks the brown colour since PAL[6] & 0x0f = 4 and PAL[4] & 0x0f = 4, which means that brown becomes aliased to red. That said, brendan's table of DAC aliases correspond with the default values in the EGA palette, and on a true VGA they can be modified to a linear palette:
Code: Select all
mov dx, 0x3da
in al, dx ; reset AC flipflop to "address"
mov dx, 0x3c0 ; AC register
mov al, 16
.loop:
dec al
out dx, al ; index
out dx, al ; data: pal[x] = x
jnz .loop
mov al, 0x20
out dx, al ; enable screen again
What concerns me more is that Brendan mentioned poor implementations of PAL/DAC in 16-colour modes with the added conclusion that neither rewriting the PAL nor rewriting the DAC or any combination of the two gives guaranteed success. I already realized that I need two VGA drivers anyway: one for all the implementations that can do the standard stuff, i.e. either text, planar-16 w/o DAC, chain4-256 or Mode X with DAC and none of the fun stuff, and one that actually exposes all VGA features including but not limited to GRs, latches, EGA palette, splitscreens, linear 16-colour modes, 512-character text and freeform resolutions. The first driver would then be primarily for emulated hardware (which sucks in general) and possibly bad vga clones, while the second would be for actual VGAs and 100% compatibles.
Re: VGA colors in 80x25 text mode?
Posted: Fri Jun 24, 2011 9:11 am
by egos
Your code like mine:
Code: Select all
mov edx,VIDEO_ISR1
cli
in al,dx
mov dl,VIDEO_AOR and 0xFF
mov al,VIDEO_MAXATTR
@@:
out dx,al
outsb
dec al
cmp al,0x10
jae @b
@@:
out dx,al
out dx,al
sub al,1
jnc @b
mov al,0x20
out dx,al
I have the second variant only (with advanced VGA features such as 512 different characters at once - normal and bold characters as alternative for 256 different characters with normal and bright colors, 16 background colors as alternative for 8 colors and blinking, fixed base address of video memory for all modes - 0xA0000, fixed "EGA palette" for all color palettes - 0-15, resolution 80x30 (720x 480) as alternative for resolution 80x25 (720x400) and so on). I use only first 16 DAC triplexes because it's simple and some emulators have no support for DAC palette splitting 16x16 and 4x64. The driver works fine on all hardware where I test it.
Re: VGA colors in 80x25 text mode?
Posted: Fri Jun 24, 2011 5:20 pm
by Combuster
You do know that that code snippet lacks any form of documentation and does not, as your wording suggests, do what my snippet does?
Re: VGA colors in 80x25 text mode?
Posted: Sat Jun 25, 2011 2:40 am
by egos
Hmm, it does more than just initialize "EGA palette". And what kind of documentation do you want to see? Is it such comment as "reset flip-flop to write index" or "reset PAS bit for normal operation of the attribute controller"? Or anybody don't understand what is means VIDEO_AOR or VIDEO_MAXATTR?
Re: VGA colors in 80x25 text mode?
Posted: Mon Jul 22, 2019 8:20 pm
by quadrant
Brendan wrote:
For VGA cards, the EGA palette is meant to be like this (as default):
Code: Select all
EGA VGA
0x0 0x00 Black
0x1 0x01 Blue
0x2 0x02 Green
0x3 0x03 Cyan
0x4 0x04 Red
0x5 0x05 Magenta
0x6 0x14 Brown
0x7 0x07 Light Gray
0x8 0x38 Gray
0x9 0x39 Light Blue
0xA 0x3A Light Green
0xB 0x3B Light Cyan
0xC 0x3C Light Red
0xD 0x3D Light Magenta
0xE 0x3E Light Yellow
0xF 0x3F White
Thank you for this table! Was wondering why the colors no longer matched when switching from text mode to graphics mode then back to text mode. Why brown (0x6) now appeared as a shade of grey! The shade of grey is exactly the color at index 0x14, and so on... Maybe the reason this isn't so well documented is because once people leave text mode, they never look back.