Can anyone help fix my CGA on VGA emulation?

I'm trying to get VGA's CGA mode (BIOS Video mode 06h) working.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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?
		}
		else if (!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.
Last edited on
Topic archived. No new replies allowed.