VGA Text mode using Word addressing mode?

I'm building an emulator which implements a VGA card. As far as I know each address is incremented by a byte, word or doubleword, depending on the Byte/Word and DoubleWord bits in the VGA registers.

What I'm finding strange, is that during text mode, it's set to word mode. So this would mean that the first letter is at plane 0, address 0, the second at plane 0, address 2, the third at plane 0, address 4. So this would mean that every even letter is skipped?

Example (using 16-bit segmented PC addressing):
0xA000:0000 A = plane 0 offset 0
0xA000:0000 0xF = plane 1 offset 0
0xA000:0002 B = plane 0 offset 1
0xA000:0000 0xF = plane 1 offset 1
0xA000:0004 C = plane 0 offset 2
0xA000:0000 0xF = plane 1 offset 2
0xA000:0006 D = plane 0 offset 3
0xA000:0000 0xF = plane 1 offset 3
0xA000:0008 E = plane 0 offset 4
0xA000:0000 0xF = plane 1 offset 4
0xA000:000A F = plane 0 offset 5
0xA000:0000 0xF = plane 1 offset 5

Display should be, according to word mode (bit 0 is essentially cleared for the first row):

ACE

But all documentation says it's supposed to be:
ABCDEF

Is this correct? Or does the text mode operation ignore the Byte/Word/Doubleword mode setting for some reason? Am I implementing the word mode wrong?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
OPTINLINE uint_32 addresswrap(VGA_Type *VGA, uint_32 memoryaddress) //Wraps memory arround 64k!
{
	register uint_32 address2; //Load the initial value for calculating!
	register uint_32 result;
	result = memoryaddress; //Default: don't change!
	if (getVRAMMemAddrSize(VGA)==2) //Word mode?
	{
		address2 = memoryaddress; //Load the address for calculating!
		if (VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.AW) //MA15 has to be on MA0
		{
			address2 >>= 15;
		}
		else //MA13 has to be on MA0?
		{
			address2 >>= 13;
		}
		address2 &= 1; //Only load 1 bit!
		result &= ~1; //Clear bit 0!
		result |= address2; //Add bit MA15 at position 0!
	}
	return result; //Adjusted address!
}
Last edited on
I seem to recall that the PC used 1 byte to store the character and one byte to store the color (4 bits for foreground, 4 bits for background). In that case. the odd numbered bytes would contain the color info and the display would be ABCDEF.

Don't know if this is useful.
But according to the odd/even mode, which is set during text mode, all even bytes go to plane 0 and all odd bytes go to plane 1.

So plane 0 contains all text:
ABCDEF

And plane 1 contains all attributes:
0xF0xF0xF0xF0xF0xF

How does the byte/word/dword addressing mode affect this? Also what's the effect when reading the planes when rendering the screen?

Edit: Fixed. The problem was in the MMU access function, which write it to memory while reversing the shift:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	else if (ActiveVGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.OddEvenMode //Odd/even mode possible?
		&& ActiveVGA->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.EnableOddEvenMode
		&& ActiveVGA->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER.EnableOE //Odd/even mode enabled?
		) //Odd/even mode?
	{
		plane = 1;
		byte plane2;
		plane2 = ActiveVGA->registers->ExternalRegisters.MISCOUTPUTREGISTER.OE_HighPage; //Load high page!
		plane2 <<= 1;
		plane2 |= (originaloffset&1); //Sub!
		plane <<= plane2; //The plane to use: odd(1) or even(0)!
		realoffset = originaloffset;
		realoffset &= ~1; //Calculate the correct offset within the VRAM! Bit 0 is cleared: we address even bytes only!
realoffset >>= 1; //Shift to the correct position?
	}


The problem is caused by the last instruction: it assumes the data supposed to write/read as addresses 0, 1, 2, 3 (every character offset). This should be even addresses only for some reason (which explains the word address mode).

So the VRAM now contains:
Plane 0 offset 0 A
Plane 1 offset 0 0xF
Plane 0 offset 2 B
Plane 1 offset 2 0xF
Plane 0 offset 4 C
Plane 1 offset 4 0xF
Plane 0 offset 6 D
Plane 1 offset 6 0xF
Plane 0 offset 8 E
Plane 1 offset 8 0xF
Plane 0 offset 10 F
Plane 1 offset 10 0xF

Which combined with word addressing mode gives the result:
Text: ABCDEF
Colors: 0xF0xF0xF0xF0xF

This is correct according to the manual.

I still wonder though: why only use even addresses when using the mode? Why not use all addresses (shift address as in this post), but use byte addressing instead of word addressing?
Last edited on
Topic archived. No new replies allowed.