First post, by superfury
I'm currently using the following to decode access from the CPU to the VGA:
OPTINLINE void decodeCPUaddress(byte towrite, uint_32 offset, byte *planes, uint_32 *realoffset)
{
if (ActiveVGA->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER.Chain4Enable) //Chain 4 mode?
{
*realoffset = offset; //Original offset to start with!
offset &= 0x3; //Walk through the planes!
*planes = (1 << offset); //Lower bits, create bitmask!
*realoffset >>= 2; //Rest of the bits. Multiples of 4 wont get written!
return; //Done!
}
if (ActiveVGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.OddEvenMode) //Odd/Even mode?
{
//Odd/even mode used (compatiblity case)?
//Do the same as VPC!
register byte calcplanes;
register uint_32 newoffset;
newoffset = offset; //Take the default offset!
newoffset &= 0xFFFE; //Take the offset within the plane!
if (ActiveVGA->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.EnableOddEvenMode) //Chain using A0 selected? 0=0/2, 1=1/3!
{
calcplanes = offset;
calcplanes &= 1; //Take 1 bit to determine the plane (0/1)!
}
else //Normal operations?
{
calcplanes = 0; //The plane calculated is always 0!
newoffset |= (offset & 1); //Linear operations!
}
calcplanes = (0x5 << calcplanes); //Convert to used plane (0/2 or 1/3)!
*planes = calcplanes; //Load the planes to address!
*realoffset = newoffset; //Load the offset to address!
return; //Done!
}
if (towrite) //Writing access?
{
*planes = 0xF; //Write to all planes possible, map mask register does the rest!
}
else
{
*planes = 1; //Load plane 0!
*planes <<= ActiveVGA->registers->GraphicsRegisters.REGISTERS.READMAPSELECTREGISTER.ReadMapSelect; //Take this plane!
}
*realoffset = offset; //Direct offset into VRAM!
//The offset is used directly!
}
I'm using the int10_modes.cpp from Dosbox-X and the plotting and text mode fonts of Dosbox.
For some reason I'm getting wrong output with text modes. Anyone knows why?
Also, what's the effect of the byte/word/doubleword modes on this?
Does realoffset need to be multiplied by 1, 2 or 4 depending on it? I'm getting text output with empty space between the characters. So instead of "x86EMU" it displays "x 8 6 E M U" etc.
Edit: This is now fixed. But for some reason the screen keeps repeating the first graphics/text line.
VGA_MMU contains the CPU memory window and related effects. VGA_IO the CPU I/O. VGA_Sequencer contains the rendering script and VGA_Precalcs contains the calculated values using when rendering (byte/word/dw modes too).
Anyone knows why the mode 13h is going wrong (multiple screens), also for some reason the first scanline (either character line or graphics pixel) is repeated for the whole screen? All other modes (text mode and graphics modes up to 12h) are working correctly.
Edit:
It seems that there's two byte/word/doubleword settings:
- The CRTC Mode Control's byte/word mode and Underline Location's Doubleword setting combine into byte/word/doubleword mode. The combine into a shift left by 0, 1 or 2?
- The CRTC Mode Control's Divide Memory Address by 2 and Underline Location's Divide Memory Address by 4. These combine into divide by 1, 2 or 4?
Anyone knows how these two combine during CPU reads/writes and how they combine/affect rendering? These two settings, how are they applied in a real VGA? Are they both applied at the rendering, when a character clock loads information from the four memory planes? Or are they applied when the CPU reads and writes to display memory?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io