VOGONS


First post, by Battler

User metadata
Rank Member
Rank
Member

Does anyone here any idea on how this actually works?

Based on the documentation, I get this:
Sequencer register 04h, bit 2:

O/E Dis. -- Odd/Even Host Memory Write Adressing Disable
"When this bit is set to 0, even system addresses access maps 0 and 2, while odd system addresses access maps 1 and 3. When this bit is set to 1, system addresses sequentially access data within a bit map, and the maps are accessed according to the value in the Map Mask register (index 0x02)."

Graphics register 05h, bit 4:

Host O/E -- Host Odd/Even Memory Read Addressing Enable
"When set to 1, this bit selects the odd/even addressing mode used by the IBM Color/Graphics Monitor Adapter. Normally, the value here follows the value of Memory Mode register bit 2 in the sequencer."

Graphics register 06h, bit 1:

Chain O/E -- Chain Odd/Even Enable
"When set to 1, this bit directs the system address bit, A0, to be replaced by a higher-order bit. The odd map is then selected when A0 is 1, and the even map when A0 is 0."

Miscellaneous output register, bit 5:

O/E Page -- Odd/Even Page Select "Selects the upper/lower 64K page of memory when the system is in an eve/odd mode (modes 0,1,2, […]
Show full quote

O/E Page -- Odd/Even Page Select
"Selects the upper/lower 64K page of memory when the system is in an eve/odd mode (modes 0,1,2,3,7).
= 0 selects the low page
= 1 selects the high page"

But how does this actually work? I suppose it is like this:
- Sequencer register 04h, bit 2, when set to 0, enables Chain-2 / Odd/Even mode on writes from CPU to VRAM;
- Graphics register 05h, bit 4, when set to 1, enables Chain-2 / Odd/Even on reads from CPU to VRAM;
- Graphics register 06h, bit 1, when set to 1, enables Chain-2 / Odd/Even on reads from VRAM to DAC;
- Miscellaneous output register, bit 5 controls whether the high or low page is used - as in, 0/2 when clear, and 1/3 when set.

Am I interpreting this right?

Reply 1 of 2, by superfury

User metadata
Rank l33t++
Rank
l33t++

As far as I know(and implemented in UniPCemu):
Sequencer memory mode register bit 3 set write and read memory to use chain-4 mode(different mapping on Tseng SVGA vs all other VGA's).
Otherwise, it uses either planar or odd/even mode:
Sequencer Memory mode register bit 2, when cleared, sets odd/even memory mode on writes to memory, planar memory mode otherwise.
Graphics mode register bit 4, when set, sets odd/even memory mode on reads from memory, planar memory mode otherwise.
The misc graphics register(index 06h) bit 1, when set, affects bit 0 of the generated VRAM address only, replacing it with bit 16, during CPU memory accesses('Replace A0 with high order bit').
The high/low page of the Misc output register selects the high page or low page(plane 2/3 instead of 0/1) when addressing the second 64K half of the 128K window only.

UniPCemu's decoding code of the odd/even mode for all memory accesses:

void VGA_OddEven_decode(byte towrite, uint_32 offset, byte *planes, uint_32 *realoffset)
{
INLINEREGISTER uint_32 realoffsettmp;
INLINEREGISTER byte calcplanes;
calcplanes = realoffsettmp = offset; //Take the default offset!
calcplanes &= 1; //Take 1 bit to determine the odd/even plane (odd/even)!
if (GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER,1,1)) //Replace A0 with high order bit?
{
realoffsettmp &= 0xFFFE; //Clear bit 0 for our result!
realoffsettmp |= (offset>>16)&1; //Replace bit 0 with high order bit!
}
if (GETBITS(getActiveVGA()->registers->ExternalRegisters.MISCOUTPUTREGISTER,5,1) && (offset & 0x10000)) //High page on High RAM?
{
realoffsettmp |= 2; //Apply high page!
rwbank <<= 2; //ET4000: Read/write bank supplies bits 18-19 instead.
}
else
{
rwbank <<= 1; //ET4000: Read/write bank supplies bits 17-18 instead.
}

realoffsettmp &= 0xFFFF; //Wrap the offset low!
*realoffset = realoffsettmp; //Give the calculated offset!
*planes = (0x5 << calcplanes); //Convert to used plane (0&2 or 1&3)!
#ifdef ENABLE_SPECIALDEBUGGER
if (specialdebugger||verboseVGA) //Debugging special?
#else
if (verboseVGA) //Debugging special?
#endif
{
dolog("VGA", "%s using Odd/Even: Memory aperture offset %08X=Planes: %04X, Offset: %08X, VRAM offset: %08X, Bank: %08X", towritetext[towrite ? 1 : 0], offset, *planes, *realoffset, (*realoffset<<2), rwbank);
}
}

UniPCemu's memory read and write memory mode updating:

		if (GETBITS(VGA->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER,3,1)) //Chain 4 mode?
{
VGA_WriteMemoryMode = VGA_ReadMemoryMode = VGA->precalcs.WriteMemoryMode = VGA->precalcs.ReadMemoryMode = 1; //Chain-4 mode on both writes and reads!
}
else //Other memory modes, which can be mixed?
{
//Determine write memory mode!
if (GETBITS(VGA->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER,2,1)==0) //Write using odd/even addressing?
{
VGA_WriteMemoryMode = VGA->precalcs.WriteMemoryMode = 2; //Odd/Even mode!
}
else //Planar mode?
{
VGA_WriteMemoryMode = VGA->precalcs.WriteMemoryMode = 0; //Planar mode!
}

//Determine read memory mode!
if (GETBITS(VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER,4,1)) //Read using odd/even addressing?
{
VGA_ReadMemoryMode = VGA->precalcs.ReadMemoryMode = 2; //Odd/Even mode!
}
else //Planar mode?
{
VGA_ReadMemoryMode = VGA->precalcs.ReadMemoryMode = 0; //Planar mode!
}
}

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 2 of 2, by superfury

User metadata
Rank l33t++
Rank
l33t++

The main purpose of replacing bit 0 with bit 16 seems to be:
When disabled:
A0000 maps to plane 0, byte 0
A0001 maps to plane 1, byte 0
A0002 maps to plane 0, byte 2
A0003 maps to plane 0, byte 2
The A16 line has no effect, so it's a duplicate of the above(at B0000-BFFFF).
etc.

But when the A0 mapping is enabled:
B0000 maps to plane 0, byte 1
B0001 maps to plane 1, byte 1
B0002 maps to plane 0, byte 3
B0003 maps to plane 1, byte 3
etc.

Thus, it's some kind of even/odd address(instead of plane) mapping across the 128K window, to access VRAM in some kind of even/odd way:
To access plane 0 sequentially like this:
A0000, B0000, A0002, B0002 etc.

Or(in C syntax):
Address = A0000|(plane&1)|((address&1)<<16)|(address>>1)

Maybe useful for fades and those kind of effects(in 256-color mode)?

The misc output register bit 5 is probably used to set bit 1 on the plane(thus using plane 2/3 instead of 0/1), but for some reason I've implemented it to set bit 2 (the A1 line) instead. Can't remember the reason, though.

The docs say this:

Selects the upper/lower 64K page of memory when the system is in an eve/odd mode (modes
|0,1,2,3,7).

Anyone can clarify what is meant by this?
Edit: Dosbox doesn't handle it. PCem-X seems to make it set bit 16 of the physical memory access(bit 14 of the planar address). That doesn't make sense, since it's provided by the VRAM window address bit?
Edit: Reading https://archive.org/stream/bitsavers_chipsAnd … ge/n25/mode/1up , it seems that the misc output register bit 5 actually selects between using planes 0&1(low page) and 2&3(high page).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io