VOGONS


First post, by llm

User metadata
Rank Member
Rank
Member

this code is part of a EGA/VGA 320x200x16 color DOS game reverse engineering project - i have no real knowledge about legacy video code stuff except the easy peasy Mode 13h with 256 colors per pixel-byte

does that code change the internal EGA/VGA palett?


// bytes comming from a game picture file
std::vector<uint8_t> color_data{00 05 01 03 00 3A 03 05 38 07 39 3A 3E 3C 04 3F};

// used this way
for(int index = 0; index < color_data.size(); ++i)
{
cli();

// force index state
inb(0x3DA);
outb(0x3C0, index); // activate cpu-access + color-index
outb(0x3C0, color_data[index]); // color data

// force index state
inb(0x3DA);
outb(0x3C0, 0x20); // activate video access

sti();
}

i've found the infos about behavior of port 0x3C0 and 0x3DA here https://github.com/cirosantilli/ralf-brown-in … d/PORTS.B#L4666

the index is the color-index but the data part of 0x3C0 is not fully clear to me

indexed registers in ATC (flipflop set to 'data'): (see #P0662)
Bit(s) Description (Table P0663)
7-6 reserved
5 secondary red video
4 secondary green/intensity video
3 secondary blue/mono video
2 primary red video
1 primary green video
0 primary blue video

Question 1:
what is a secondary blue/mono video bit and a green/intensity video bit?

Question 2:
aren't port 0x3c8(color-index) and 0x3c9(R,G,B) used for color palett changing?

Question 3: could have the code be written like that?

std::vector<uint8_t> color_data{00 05 01 03 00 3A 03 05 38 07 39 3A 3E 3C 04 3F};
cli();
// force index state
inb(0x3DA);
for(int index = 0; index < color_data.size(); ++i)
{
outb(0x3C0, index); // activate cpu-access + color-index
outb(0x3C0, color_data[index]); // color data
}
outb(0x3C0, 0x20); // activate video access
sti();

Reply 1 of 5, by vstrakh

User metadata
Rank Member
Rank
Member
llm wrote on 2022-12-02, 10:42:

Question 1:
what is a secondary blue/mono video bit and a green/intensity video bit?

EGA has 6-bit digital output, the secondary values is the least significant bit in each channel's 2-bit value, carrying 1/3 of channel value weight, and primary carrying 2/3 of the weight.
The monochrome display needs 1-bit "video" value (on/off), and 1-bit "intensity" value. The "secondary blue/mono video" carries either least significant bit for color monitors, or "video" signal for monochrome monitor.

llm wrote on 2022-12-02, 10:42:

Question 2:
aren't port 0x3c8(color-index) and 0x3c9(R,G,B) used for color palett changing?

Those ports address the VGA DAC. The DAC does not exist on EGA, instead you program "internal palette" which 6-bit digital value to output for each possible color. There are 16 colors, and so 16 indices addressable via 3C0h are allocated for palette.

Reply 3 of 5, by mkarcher

User metadata
Rank Oldbie
Rank
Oldbie
llm wrote on 2022-12-02, 15:32:

so the 0x3C0 port is the EGA version of port 0x3c8/0x3c9 in VGA

No, it's not "the EGA version". VGA has both the EGA-compatible attribute controller at port 3C0 and the RAMDAC at port 3C6-3C9. The EGA-compatible attribute controller translates the color number (0 till up to 15) in all modes but the 256-color mode into an 8-bit number. This 8-bit number is subsequently translated by the RAMDAC to one of the 262144 different analog colors the VGA card can produce. By default, the RAMDAC is set up in a way that the first 64 colors match the EGA colors. A program defining colors "the EGA way" using port 3C0 is supposed to work on a VGA card equally well. As the output of the VGA version of the attribute controller outputs 8-bit color numbers, but the EGA palette registers only contain 6 bits, there is a little-used VGA features that the two extra bits can be globally programmed, resulting in four different sets of 64 colors each. Even less used is an alternate configuration that allows 16 different sets of 16 colors each.

Reply 4 of 5, by mkarcher

User metadata
Rank Oldbie
Rank
Oldbie
llm wrote on 2022-12-02, 10:42:

what is a secondary blue/mono video bit and a green/intensity video bit?

If you connect an MDA monitor to the EGA card, the "video" signal (defines whether a pixel is black or not) is controlled by the bit that controls a "33% blue" component on EGA monitors. Also the "intensity" signal (defines whether a non-black pixel is normal intensity or high intensity) is controlled by the bit that defines "33% green" on EGA monitors and "33% of everything" on CGA-compatible monitors.

llm wrote on 2022-12-02, 10:42:

aren't port 0x3c8(color-index) and 0x3c9(R,G,B) used for color palett changing?

As I already explained in my separate port, the device at 3C0 and the device at 3c8/3c9 are both used on VGA cards, except in mode 13h. In mode 13h, the device at 3C0 is bypassed.

llm wrote on 2022-12-02, 10:42:
Question 3: could have the code be written like that? […]
Show full quote

Question 3: could have the code be written like that?

std::vector<uint8_t> color_data{00 05 01 03 00 3A 03 05 38 07 39 3A 3E 3C 04 3F};
cli();
// force index state
inb(0x3DA);
for(int index = 0; index < color_data.size(); ++i)
{
outb(0x3C0, index); // activate cpu-access + color-index
outb(0x3C0, color_data[index]); // color data
}
outb(0x3C0, 0x20); // activate video access
sti();

Yes, this would work, too, and it is more efficient.