uint_32 patch_map1314(VGA_Type *VGA, uint_32 rowscancounter, uint_32 rowscanaddress) //Patch full VRAM address!
{
uint_32 newrowscan = rowscanaddress; //New row scan to use!
if (!VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.MAP13) //a13=Bit 0 of the row scan counter!
{
//Row scan counter bit 1 is placed on the memory bus bit 14 during active display time.
//Bit 1, placed on memory address bit 14 has the effect of quartering the memory.
newrowscan = (newrowscan&(~(1<<13)))|((rowscancounter&1)<<13); //Exchange row scan counter bit 0 for bit 13!
}
if (!VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.MAP14) //a14<=Bit 1 of the row scan counter!
{
newrowscan = (newrowscan&(~(1<<14)))|((rowscancounter&2)<<13); //Exchange row scan counter bit 0 for bit 13!
}
return newrowscan; //Give the linear address!
}
uint_32 addresswrap(VGA_Type *VGA, uint_32 memoryaddress) //Wraps memory arround 64k!
{
if (!VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.AW) //Put address bit 13 on bit 0?
{
if (VGA->registers->CRTControllerRegisters.REGISTERS.UNDERLINELOCATIONREGISTER.DW) //Doubleword mode?
{
return ((memoryaddress<<2)&0xFFFC)|((memoryaddress>>12)&3); //SHL 2, MA12&13 to MA0&1?
}
elseif (!VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.UseByteMode) //Word mode is used in CGA emulation?
{
return ((memoryaddress<<1)&0xFFFE)|((memoryaddress>>13)&1); //SHL 1, MA13 to MA1?
}
//Byte mode runs normally!
}
return memoryaddress; //Normal operating mode!
}
When the sequencer reads data from memory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
extern uint_32 rowscanaddress; //Row scan address!
extern uint_32 rowscancounter; //Row scan counter!
//Allow wrap is used to determine the hardware rendering!
uint_32 determinewrap(VGA_Type *VGA, uint_32 addr,byte is_renderer)
{
uint_32 result = addr; //Default: take address itself!
if (is_renderer) //Hardware side?
{
result -= rowscanaddress; //Substract the row scan address to get the base!
rowscanaddress = addresswrap(VGA,rowscanaddress); //Wrap if needed!
rowscanaddress = patch_map1314(VGA,rowscancounter,rowscanaddress); //Allow patching of MAP13&14!
result += rowscanaddress; //Apply new row scan address!
}
return result; //New offset!
}
When the renderer is calling memory reads, is_renderer==1, when the CPU executes reads/writes to video memory is_renderer==0.
The VRAM offset passed to determinewrap is calculated like this:
(((start+offset)*4)+plane)%VRAM_SIZE
VRAM_SIZE is usually 256k (4*65536)
Anyone can help me fix this (or can tell me if this is correct)?
This is supposed to be left half white, right half white.