Calculate the start of a row in VGA VRAM?

How do I calculate the start of a row (e.g. row #0, #1 etc.) in the VGA's VRAM? (On a planar level)

So if I need to get row #13 on plane #0, with an offset register of 0x20 (32 decimal) and an pixel size of WORD (so 2 bytes in the calculation), where would this row start in VRAM? (Is there a formula to do this?)

EDIT: Is this correct?

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
98
99
100
101
102
103
104
105
106
107
108
inline byte readVRAMdirect(uint_32 start, uint_32 offset)
{
	return VGA.VRAM[(start+offset)%VGA.VRAM_size]; //Read with overflow protection!
}

inline void writeVRAMdirect(uint_32 start, uint_32 offset, byte value)
{
	VGA.VRAM[(start+offset)%VGA.VRAM_size] = value; //Write with overflow protection!
}

inline byte readVRAMplane(uint_32 start, byte plane, uint_32 offset) //Read from a VRAM plane!
{
	return VGA.VRAM[((plane*0x10000)+start+offset)%VGA.VRAM_size]; //Read with overflow protection!
}

inline void writeVRAMplane(uint_32 start, byte plane, uint_32 offset, byte value) //Write to a VRAM plane!
{
	VGA.VRAM[((plane*0x10000)+start+offset)%VGA.VRAM_size] = value; //Write with overflow protection!
}

inline void *VGA_planeptr(uint_32 start, byte plane) //Pointer to VRAM plane!
{
	return &VGA.VRAM[((plane*0x10000)+start)%VGA.VRAM_size]; //Pointer to the VRAM plane!
}

inline byte getBitPlaneBit(uint_32 start, int plane, uint_32 offset, byte bit)
{
return ((readVRAMplane(start,plane,offset)&(1<<bit))>>bit); //Give the bit!
}

inline void setBitPlaneBit(uint_32 start, int plane, uint_32 offset, byte bit, byte on)
{
writeVRAMplane(start,plane,offset,((readVRAMplane(start,plane,offset)&~(1<<bit)))|(on<<bit)); //Set the bit!
}

byte VGA_getpixel(int x, int y)
{
uint_32 offset; //The offset within the plane!
int plane; //The plane!
int pixel;
switch (VGA.info.VRAMmode)
{
case 2: //Mono: take bit out of bitplane 0?
	offset = getVRAMScanlineStart(y); //The starting offset!
	offset += (x/8)*getVRAMMemAddrSize(); //Add X!
	return getBitPlaneBit(VGA.info.startMap,0,offset,(x%8)); //Give the bit representing the pixel!
	
case 4: //Shift register interleave = packed shift mode?
	offset = getVRAMScanLineStart(y); //The starting offset of the row!
	offset += (x/4)*getVRAMMemAddrSize(); //Add X!
	plane = (x/4)%2; //The plane to start, 0 or 1!
	pixel = x%4; //The pixel we need to get!
	return getBitPlaneBit(VGA.info.startMap,plane+2,offset,7-(pixel*2))*8+ //Plane highest
		   getBitPlaneBit(VGA.info.startMap,plane+2,offset,7-(pixel*2))*4+ //Plane lower!
		   getBitPlaneBit(VGA.info.startMap,plane,offset,6-(pixel*2))*2+ //Plane highest
		   getBitPlaneBit(VGA.info.startMap,plane,offset,6-(pixel*2))+ //Plane lower!
case 16: //Planar shift?
	offset = getVRAMScanLineStart(y); //The starting offset of the row!
	offset += (x/8)*getVRAMMemAddrSize(); //Add X!
	return getBitPlaneBit(VGA.info.startMap,0,offset,(x%8))+  //Bit 0!
			getBitPlaneBit(VGA.info.startMap,1,offset,(x%8))*2+ //Bit 1!
			getBitPlaneBit(VGA.info.startMap,2,offset,(x%8))*4+ //Bit 2!
			getBitPlaneBit(VGA.info.startMap,3,offset,(x%8))*8+ //Bit 3!
case 256: //256 color shift mode?
	offset = getVRAMScanlineStart(y); //The starting offset!
	offset += ((x/4)*getVRAMMemAddrSize()); //Add X!
	plane = (x%4); //The plane: we're spread over the planes!
	return readVRAMplane(VGA.info.startMap,plane,offset); //Give the bit representing the pixel!
}
}

void VGA_putpixel(int x, int y, byte color)
{
uint_32 offset; //The offset within the plane!
int plane; //The plane!
int pixel;
byte colorbuf; //Buffer!
switch (VGA.info.VRAMmode)
{
case 2: //Mono: take bit out of bitplane 0?
	offset = getVRAMScanlineStart(y); //The starting offset!
	offset += (x/8)*getVRAMMemAddrSize(); //Add X!
	setBitPlaneBit(VGA.info.startMap,0,offset,(x%8),(color%2)); //Give the bit representing the pixel!
	
case 4: //Shift register interleave = packed shift mode?
	offset = getVRAMScanLineStart(y); //The starting offset of the row!
	offset += (x/4)*getVRAMMemAddrSize(); //Add X!
	plane = (x/4)%2; //The plane to start, 0 or 1!
	pixel = x%4; //The pixel we need to get!
	colorbuf = (color&0x3); //The actual color with overflow protection!
	setBitPlaneBit(VGA.info.startMap,plane+2,offset,7-(pixel*2),((colorbuf&0x8)>>3)); //Plane highest
	setBitPlaneBit(VGA.info.startMap,plane+2,offset,7-(pixel*2),((colorbuf&0x4)>>2)); //Plane lower!
	setBitPlaneBit(VGA.info.startMap,plane,offset,6-(pixel*2),((colorbuf&0x2)>>1)); //Plane highest
	setBitPlaneBit(VGA.info.startMap,plane,offset,6-(pixel*2),(colorbuf&0x1)); //Plane lower!
case 16: //Planar shift?
	offset = getVRAMScanLineStart(y); //The starting offset of the row!
	offset += (x/8)*getVRAMMemAddrSize(); //Add X!
	setBitPlaneBit(VGA.info.startMap,0,offset,(x%8),(colorbuf&0x1));  //Bit 0!
	setBitPlaneBit(VGA.info.startMap,1,offset,(x%8),(colorbuf&0x2)>>1); //Bit 1!
	setBitPlaneBit(VGA.info.startMap,2,offset,(x%8),(colorbuf&0x4)>>2); //Bit 2!
	setBitPlaneBit(VGA.info.startMap,3,offset,(x%8),(colorbuf&0x8)>>3); //Bit 3!
case 256: //256 color shift mode?
	offset = getVRAMScanlineStart(y); //The starting offset!
	offset += ((x/4)*getVRAMMemAddrSize()); //Add X!
	plane = (x%4); //The plane: we're spread over the planes!
	writeVRAMplane(VGA.info.startMap,plane,offset); //Give the bit representing the pixel!
}
}
Last edited on
Topic archived. No new replies allowed.