VGA colors in 80x25 text mode?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

VGA colors in 80x25 text mode?

Post 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...
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: VGA colors in 80x25 text mode?

Post 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?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Freenode IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VGA colors in 80x25 text mode?

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: VGA colors in 80x25 text mode?

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: VGA colors in 80x25 text mode?

Post 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".
If you have seen bad English in my words, tell me what's wrong, please.
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Re: VGA colors in 80x25 text mode?

Post 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!
User avatar
IanSeyler
Member
Member
Posts: 325
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Re: VGA colors in 80x25 text mode?

Post 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
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: VGA colors in 80x25 text mode?

Post 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
Attachments
cgapal.zip
(148 Bytes) Downloaded 160 times
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
IanSeyler
Member
Member
Posts: 325
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Re: VGA colors in 80x25 text mode?

Post 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
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: VGA colors in 80x25 text mode?

Post 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
  ...
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Freenode IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VGA colors in 80x25 text mode?

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: VGA colors in 80x25 text mode?

Post 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.
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Freenode IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VGA colors in 80x25 text mode?

Post 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?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: VGA colors in 80x25 text mode?

Post 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? :D
If you have seen bad English in my words, tell me what's wrong, please.
quadrant
Member
Member
Posts: 74
Joined: Tue Apr 24, 2018 9:46 pm

Re: VGA colors in 80x25 text mode?

Post 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
=D> 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.
Post Reply