VGA CPU write address (plane&offset) combined with VGA write plane mask?

Anyone knows how to get this done?

When CPU writes happen, the function below gets passed a plane number (always 0 when odd/even disable) and a memory address (calculated using odd/even, chain 4 or normal mode, see 2nd code block). The actions described here (http://www.osdever.net/FreeVGA/vga/vgamem.htm#write) are executed on the data. Next is going to be the writing to the display plane(s):

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
uint_32 LogicalOperation(uint_32 input)
{
	switch (ActiveVGA->registers->GraphicsRegisters.REGISTERS.DATAROTATEREGISTER.LogicalOperation)
	{
	case 0x00:	/* None */
		return input; //Unmodified
	case 0x01:	/* AND */
		return input & ActiveVGA->registers->ExternalRegisters.DATALATCH.latch;
	case 0x02:	/* OR */
		return input | ActiveVGA->registers->ExternalRegisters.DATALATCH.latch;
	case 0x03:	/* XOR */
		return input ^ ActiveVGA->registers->ExternalRegisters.DATALATCH.latch;
	};
	return input; //Unknown, just give the input!
}

uint_32 BitmaskOperation(uint_32 input, byte bitmaskregister)
{
	uint_32 result = 0; //Default: the result!4
	byte bit;
	//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","BitmaskOperation on %08X, Bitmask: %02X, Startbit: %i, Width: %i",input,bitmaskregister,startbit,width); //Log it!
	for (bit=0;bit<32;bit++) //Process all available bits!
	{
		if (bitmaskregister&(1<<(bit&7))) //Use bit from input?
		{
			//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","Bitmask: take bit from input: %i(%i)",bit,((input&(1<<bit))>>bit)); //Take this bit from the input!
			result |= input&(1<<bit); //Use the bit from input!
		}
		else //Use bit from latch?
		{
			//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","Bitmask: take bit from latch: %i(%i)",bit,((ActiveVGA->registers->ExternalRegisters.DATALATCH.latch&(1<<bit))>>bit)); //Take this bit from the input!
			result |= ActiveVGA->registers->ExternalRegisters.DATALATCH.latch&(1<<bit); //Use the bit from the latch!
		}
	}
	return result; //Give the result!
}

void VGA_WriteModeOperation(byte planes, uint_32 offset, byte val)
{
	if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA","Write %02X to plane %i...",val,plane);
	uint_32 data = val; //Default to the value given!

	byte curplane; //For plane loops!
	switch (ActiveVGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.WriteMode) //What write mode?
	{
	case 0: //Read-Modify-Write operation!
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","VRAM write: Plane: %i, Offset: %05X, Value: %02X",plane,offset,val); //Log our write operation!
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","ROR on %02X",data);
		data = (byte)ror((byte)val,ActiveVGA->registers->GraphicsRegisters.REGISTERS.DATAROTATEREGISTER.RotateCount); //Rotate it! Keep 8-bit data!
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","ROR'ED value: %02X",data);
		data = ActiveVGA->ExpandTable[data]; //Make sure the data is on the all planes!
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","All planes value: %08X",data);
		for (curplane=0;curplane<3;curplane++)
		{
			if (ActiveVGA->registers->GraphicsRegisters.REGISTERS.ENABLESETRESETREGISTER.EnableSetReset&(1<<curplane)) //Enable set/reset? (Mode 3 ignores this flag)
			{
				//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","SetReset (%i) on %08X MASK=%08X",curplane,data,ActiveVGA->FillTable[1<<curplane]);
				data = (data&(~ActiveVGA->FillTable[(1<<curplane)])) | ActiveVGA->FillTable[ActiveVGA->registers->GraphicsRegisters.REGISTERS.SETRESETREGISTER.SetReset&(1<<curplane)]; //Turn all those bits off, and the set/reset plane ON=0xFF for the plane and OFF=0x00!
				//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","AfterSetReset (%i): %08X, Set: %i",curplane,data,ActiveVGA->registers->GraphicsRegisters.REGISTERS.SETRESETREGISTER.SetReset&(1<<curplane));
			}
		}
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","AfterSetReset: %08X",data);
		data = LogicalOperation(data); //Execute the logical operation!
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","AfterLogicalOperation: %08X",data);
		data = BitmaskOperation(data,ActiveVGA->registers->GraphicsRegisters.REGISTERS.BITMASKREGISTER); //Execute the bitmask operation!
		//if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","AfterBitmaskOperation: %08X",data);
		break;
	case 1: //Video-to-video transfer
		data = ActiveVGA->registers->ExternalRegisters.DATALATCH.latch; //Use the latch!
		break;
	case 2: //Write color to all pixels in the source address byte of VRAM. Use Bit Mask Register.
		data = ActiveVGA->FillTable[data]; //Replicate across all 8 bits of their respective planes.
		data = LogicalOperation(data); //Execute the logical operation!
		data = BitmaskOperation(data,ActiveVGA->registers->GraphicsRegisters.REGISTERS.BITMASKREGISTER); //Execute the bitmask operation fully!
		break;
	case 3: //Ignore enable set reset register!
		data = ror(val,ActiveVGA->registers->GraphicsRegisters.REGISTERS.DATAROTATEREGISTER.RotateCount); //Rotate it! Keep 8-bit data!
		data &= ActiveVGA->registers->GraphicsRegisters.REGISTERS.BITMASKREGISTER; //AND with the Bit Mask field.
		data = BitmaskOperation(ActiveVGA->ExpandTable[ActiveVGA->registers->GraphicsRegisters.REGISTERS.SETRESETREGISTER.SetReset],data); //Use the generated data on the Set/Reset register
		break;
	}

	byte planeenable = ActiveVGA->registers->SequencerRegisters.REGISTERS.MAPMASKREGISTER.MemoryPlaneWriteEnable; //Enabled planes from the register!
	planeenable &= planes; //The actual planes to write to!
	for (curplane=0;curplane<4;curplane++) //Process all planes!
	{
		if (planeenable&(1<<curplane)) //Modification of the plane?
		{
			if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA","Writes to plane %i enabled!",curplane); //Enabled!
			writeVRAMplane(ActiveVGA,0,curplane,offset,((data>>(curplane<<3))&0xFF)); //Write the plane from the data!
		}
		else if (LOG_VRAM_WRITES && !is_loadchartable) //Log it?
		{
			dolog("VGA","Writes to plane %i disabled!",curplane); //Disabled!
		}
	}
}


Anyone knows how to make this code above work with the plane variable calculated below?
Last edited on
Part 2:
Host address to display address/plane code:
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
36
37
38
39
void VRAM_writecpu(uint_32 offset, byte value)
{
	if (!is_A000VRAM(offset)) //not VRAM (out of range)?
	{
		//dolog("vga_vram","Warning: Write from CPU %08X when not VRAM or disabled!",offset);
		return; //Disable!
	}
//Set now!

	uint_32 originaloffset = getVRAMOffset(offset); //Our VRAM offset starting from the 32-bit offset (A0000 etc.)!
	uint_32 realoffset = originaloffset; //Default to original offset!

	byte plane = 0; //The determined plane we use, default: none to write!
	if (ActiveVGA->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER.Chain4Enable) //Chain 4 mode?
	{
		plane = (1<<(originaloffset&0x3)); //Lower bits, create bitmask!
		realoffset = (originaloffset&0xfffb); //Rest of the bits. Multiples of 4 wont get written!
		if (ENABLE_VRAM_LOG) dolog("VGA_Chain4","Address %05X translates to plane %i, offset %05X",originaloffset,plane,realoffset);
	}
	//Src for below: http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Video/Sequential%20Systems%20Second%20Sight/Datasheets/VGA%20Registers.pdf
	else if (ActiveVGA->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER.OddEvenHostMemoryWriteAddressingDisable) //Odd/even addressing mode? According to DOSBox it's set, documents say 0, patched for documents!?
	{
		plane = 0xF; //Write to all planes possible, map mask register does the rest!
		//The offset is used directly!
		if (ENABLE_VRAM_LOG) dolog("VGA_SinglePlane","Address %05X translates to plane %i, offset %05X",originaloffset,plane,realoffset);
	}
	else //Determined by plane mask register (unchained mode)! OE_MODE!
	{
		//Add the base plane, 0(0) or 2(1)!
		plane = (ActiveVGA->registers->ExternalRegisters.MISCOUTPUTREGISTER.OE_HighPage<<1)|(originaloffset&1); //The plane to use: odd(1) or even(0)!
		plane = (1<<plane); //Create plane mask!
		realoffset = ((originaloffset&(~1))>>1); //Calculate the correct offset within the VRAM!		
		if (ENABLE_VRAM_LOG) dolog("VGA_OddEven","Address %05X translates to plane %i, offset %05X",originaloffset,plane,realoffset);
	}
	
	if (LOG_VRAM_WRITES && !is_loadchartable) dolog("VGA_VRAM","Write to address for latch: %05X",realoffset);
	loadlatch(realoffset); //Simulate latch again (to be compatible with software which doesn't use latches (plain VRAM access etc. like DOSBox does (no reads before writes!)))!
	VGA_WriteModeOperation(plane,realoffset,value); //Apply the operation on write mode!
}


Also I'm not quite sure about the Odd/even Addressing disable bit. What plane has to be chosen? Or just set to plane 0?

src: http://wiki.osdev.org/VGA_Hardware#The_Graphics_Controller
src: http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Video/Sequential%20Systems%20Second%20Sight/Datasheets/VGA%20Registers.pdf
Topic archived. No new replies allowed.