OSDev.org
https://forum.osdev.org/

VGA colors in 80x25 text mode?
https://forum.osdev.org/viewtopic.php?f=1&t=23753
Page 1 of 1

Author:  mariuszp [ Sun Jun 19, 2011 11:10 am ]
Post subject:  VGA colors in 80x25 text mode?

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:
/*

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...

Author:  Owen [ Sun Jun 19, 2011 12:16 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

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?

Author:  Combuster [ Sun Jun 19, 2011 2:25 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

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.

Author:  Brendan [ Mon Jun 20, 2011 12:35 am ]
Post subject:  Re: VGA colors in 80x25 text mode?

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:
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

Author:  egos [ Mon Jun 20, 2011 5:15 am ]
Post subject:  Re: VGA colors in 80x25 text mode?

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".

Author:  mariuszp [ Mon Jun 20, 2011 12:55 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

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!

Author:  IanSeyler [ Mon Jun 20, 2011 8:05 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

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

Author:  egos [ Wed Jun 22, 2011 2:02 am ]
Post subject:  Re: VGA colors in 80x25 text mode?

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:
  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 35 times

Author:  IanSeyler [ Wed Jun 22, 2011 11:02 am ]
Post subject:  Re: VGA colors in 80x25 text mode?

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:
   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

Author:  egos [ Wed Jun 22, 2011 12:16 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

Code:
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
  ...

Author:  Combuster [ Wed Jun 22, 2011 3:33 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

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:
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.

Author:  egos [ Fri Jun 24, 2011 9:11 am ]
Post subject:  Re: VGA colors in 80x25 text mode?

Your code like mine:
Code:
  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.

Author:  Combuster [ Fri Jun 24, 2011 5:20 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

You do know that that code snippet lacks any form of documentation and does not, as your wording suggests, do what my snippet does?

Author:  egos [ Sat Jun 25, 2011 2:40 am ]
Post subject:  Re: VGA colors in 80x25 text mode?

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

Author:  quadrant [ Mon Jul 22, 2019 8:20 pm ]
Post subject:  Re: VGA colors in 80x25 text mode?

Brendan wrote:
For VGA cards, the EGA palette is meant to be like this (as default):
Code:
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.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/