First post, by superfury
According to Tseng's VDIAG, there's a problem with the Write Mode 3 emulation? It gives me an Error 7 about it.
This is the current code of applying the write modes:
OPTINLINE uint_32 LogicalOperation(uint_32 input)
{
switch (GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.DATAROTATEREGISTER,3,3))
{
case 0x00: /* None */
return input; //Unmodified
case 0x01: /* AND */
return input & LE32(getActiveVGA()->registers->ExternalRegisters.DATALATCH.latch);
case 0x02: /* OR */
return input | LE32(getActiveVGA()->registers->ExternalRegisters.DATALATCH.latch);
case 0x03: /* XOR */
return input ^ LE32(getActiveVGA()->registers->ExternalRegisters.DATALATCH.latch);
default:
break;
};
return input; //Unknown, just give the input!
}
OPTINLINE uint_32 BitmaskOperation(uint_32 input, byte bitmaskregister)
{
INLINEREGISTER uint_32 result = 0; //The result built!
INLINEREGISTER uint_32 mask,inputdata; //Latch and extended mask!
//Load the mask to use, extend to all four planes!
mask = getActiveVGA()->ExpandTable[bitmaskregister]; //Load the current mask(one plane) expanded!
//Convert the value&latch to result using the mask!
inputdata = input; //Load the input to process!
inputdata &= mask; //Apply the mask to get the bits to turn on!
result |= inputdata; //Apply the bits to turn on to the result!
mask ^= 0xFFFFFFFF; //Flip the mask bits to get the bits to retrieve from the latch!
inputdata = LE32(getActiveVGA()->registers->ExternalRegisters.DATALATCH.latch); //Load the latch!
inputdata &= mask; //Apply the mask to get the bits to turn on!
result |= inputdata; //Apply the bits to turn on to the result!
return result; //Give the resulting value!
}
/*
Core read/write operations!
*/
typedef uint_32 (*VGA_WriteMode)(uint_32 data);
uint_32 VGA_WriteModeLinear(uint_32 data) //Passthrough operation!
{
data = getActiveVGA()->ExpandTable[data]; //Make sure the data is on the all planes!
return data; //Give the resulting data!
}
uint_32 VGA_WriteMode0(uint_32 data) //Read-Modify-Write operation!
{
INLINEREGISTER byte curplane;
data = (byte)ror((byte)data, GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.DATAROTATEREGISTER,0,7)); //Rotate it! Keep 8-bit data!
data = getActiveVGA()->ExpandTable[data]; //Make sure the data is on the all planes!
curplane = 1; //Process all 4 plane bits!
do
{
if (GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.ENABLESETRESETREGISTER,0,0xF)&curplane) //Enable set/reset? (Mode 3 ignores this flag)
{
data = (data&(~getActiveVGA()->FillTable[curplane])) | getActiveVGA()->FillTable[GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.SETRESETREGISTER,0,0xF)&curplane]; //Turn all those bits off, and the set/reset plane ON=0xFF for the plane and OFF=0x00!
}
curplane <<= 1; //Next plane!
} while (curplane!=0x10); //Only the 4 planes are used!
data = LogicalOperation(data); //Execute the logical operation!
data = BitmaskOperation(data, getActiveVGA()->registers->GraphicsRegisters.REGISTERS.BITMASKREGISTER); //Execute the bitmask operation!
return data; //Give the resulting data!
}
uint_32 VGA_WriteMode1(uint_32 data) //Video-to-video transfer
{
return LE32(getActiveVGA()->registers->ExternalRegisters.DATALATCH.latch); //Use the latch!
}
uint_32 VGA_WriteMode2(uint_32 data) //Write color to all pixels in the source address byte of VRAM. Use Bit Mask Register.
{
data = getActiveVGA()->FillTable[data&0xF]; //Replicate across all 4 planes to 8 bits set or cleared of their respective planes. The upper 4 bits of the CPU input are unused.
data = LogicalOperation(data); //Execute the logical operation!
data = BitmaskOperation(data, getActiveVGA()->registers->GraphicsRegisters.REGISTERS.BITMASKREGISTER); //Execute the bitmask operation fully!
return data;
}
uint_32 VGA_WriteMode3(uint_32 data) //Ignore enable set reset register!
{
data = ror(data, GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.DATAROTATEREGISTER,0,7)); //Rotate it! Keep 8-bit data!
data &= getActiveVGA()->registers->GraphicsRegisters.REGISTERS.BITMASKREGISTER; //AND with the Bit Mask field.
data = BitmaskOperation(LogicalOperation(getActiveVGA()->FillTable[GETBITS(getActiveVGA()->registers->GraphicsRegisters.REGISTERS.SETRESETREGISTER,0,0xF)]), data); //Use the generated data on the Set/Reset register
return data;
}
It's a simple 8-bits input, 32-bits output for the four planes.
Can anyone see what's going wrong?
I'm looking at Dosbox-X's peculiar way of handling said modes (https://github.com/joncampbell123/dosbox-x/bl … /vga_memory.cpp), but it's kind of difficult to see where the exact error lies?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io