VGA VRAM manipulation for graphics modes?

I'm trying to find the errors in my emulation of VGA VRAM concerning graphics modes.
Anybody knows what goes wrong? (I'm testing it by doing plotting of all colors from x=0 to x=xsize-1 (where the color is relative, so 0=0 and xsize-1=maxcolor (in the case of 16 colors it's 15, etc.)))

VRAM Graphics management:
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include "headers/types.h" //Basic type support!
#include "headers/hardware/ports.h" //Basic PORT compatibility!

#include "headers/hardware/vga.h" //VGA data!
#include "headers/mmu/mmu.h" //For CPU passtrough!

#include "headers/hardware/vga_screen/vga_displaygeneration_crtcontroller.h" //For virtual width in bytes within VRAM!

#include "headers/hardware/vga_rest/textmodedata.h" //Text mode data for loading!

#include "headers/hardware/vga_rest/colorconversion.h" //Color conversion support!

extern VGA_type VGA; //VGA chipset!

//COLOR MODES:
//VGA: 2, 3 (B/W/Bold), 4, 4 shades, 16, 256
//SVGA: 32k, 64k, True Colors

//We handle all input for writing to VRAM (CPU interrupts) and reading from VRAM (hardware) here!

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!
}

/*

2 colors!

*/

inline byte MEMGRAPHICS_get2colors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 offset;
	byte bit; //The bit!
	bit = 7-(x%8); //The bit number we need to adjust in the VRAM plane!
	offset = ((y*getrowsize()))+((x/8)*getVRAMMemAddrSize()); //Column index in VRAM planes!
	return getBitPlaneBit(startaddr,0,offset,bit); //Give the color!
}

inline void MEMGRAPHICS_put2colors(uint_32 startaddr, int x, int y, int xres, int yres, byte color)
{
	uint_32 offset;
	byte bit; //The bit!
	bit = 7-(x%8); //The bit number we need to adjust in the VRAM plane!
	offset = ((y*getrowsize()))+((x/8)*getVRAMMemAddrSize()); //Column index in VRAM planes!
	setBitPlaneBit(startaddr,0,offset,bit,(color%2)); //Set the color!
}

/*

4 colors!
4 pixels per byte!

*/


inline byte MEMGRAPHICS_get4colors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 offset;
	byte bit; //The bit!
	bit = 7-((x%4)*2); //The bit number we need to adjust in the VRAM plane! (Lower bit)
	offset = ((y*getrowsize()))+((x/4)*getVRAMMemAddrSize()); //Column index in VRAM planes!
//Info: first plane has bit 0, second plane has bit 1, planes 2&3 are unused!
	return getBitPlaneBit(startaddr,0,offset,bit+1)|(getBitPlaneBit(startaddr,1,offset,bit)<<1); //Give the result!
}

inline void MEMGRAPHICS_put4colors(uint_32 startaddr, int x, int y, int xres, int yres, byte color)
{
	uint_32 offset;
	byte bit; //The bit!
	bit = 7-((x%4)*2); //The bit number we need to adjust in the VRAM plane!
	offset = ((y*getrowsize()))+((x/4)*getVRAMMemAddrSize()); //Column index in VRAM planes!
	//Info: first plane has bit 0, second bit 1 etc. so: PLANE|=BIT.
	setBitPlaneBit(startaddr,0,offset,bit+1,color&1); //Low!
	setBitPlaneBit(startaddr,1,offset,bit,(color&2)>>1); //High!
}

/*

4 colors (SHADES)!

*/


inline byte MEMGRAPHICS_get4colorsSHADE(uint_32 startaddr, int x, int y, int xres, int yres)
{
	return MEMGRAPHICS_get4colors(startaddr, x,y,xres,yres); //Passtrough: same!
}

inline void MEMGRAPHICS_put4colorsSHADE(uint_32 startaddr, int x, int y, int xres, int yres, byte color)
{
	MEMGRAPHICS_put4colors(startaddr, x,y,xres,yres,color); //Passtrough: same!
}

/*

16 colors!

*/

inline byte MEMGRAPHICS_get16colors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 offset;
	byte bit; //The bit!
	bit = 7-(x%8); //The bit number we need to adjust in the VRAM plane!
	offset = (y*getrowsize())+((x/8)*getVRAMMemAddrSize()); //Column index in VRAM planes!
	//Info: first plane has bit 0, second bit 1 etc. so: PLANE|=BIT.

	byte result; //The result!
	result = 0; //Init result!
	result |= getBitPlaneBit(startaddr,0,offset,bit); //Bit0!
	result |= (getBitPlaneBit(startaddr,1,offset,bit)<<1); //Bit1!
	result |= (getBitPlaneBit(startaddr,2,offset,bit)<<2); //Bit2!
	result |= (getBitPlaneBit(startaddr,3,offset,bit)<<3); //Bit3!

	return result; //Give the result!
}

inline void MEMGRAPHICS_put16colors(uint_32 startaddr, int x, int y, int xres, int yres, byte color)
{
	uint_32 offset;
	byte bit; //The bit!
	bit = 7-(x%8); //The bit number we need to adjust in the VRAM plane!
	offset = (y*getrowsize())+((x/8)*getVRAMMemAddrSize()); //Column index in VRAM planes!
	//Info: first plane has bit 0, second bit 1 etc. so: PLANE|=BIT.
	setBitPlaneBit(startaddr,0,offset,bit,(color&1)); //Lowest bit!
	setBitPlaneBit(startaddr,1,offset,bit,((color&2)>>1)); //Bit1!
	setBitPlaneBit(startaddr,2,offset,bit,((color&4)>>2)); //Bit1!
	setBitPlaneBit(startaddr,3,offset,bit,((color&8)>>3)); //Bit1!
}

/*

256 COLORS

*/

inline byte MEMGRAPHICS_get256colors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+(y*getrowsize())+(x*getVRAMMemAddrSize());
	return VRAM_readdirect(pixelnumber); //Give the pixel from memory!
}

inline void MEMGRAPHICS_put256colors(uint_32 startaddr, int x, int y, int xres, int yres, byte color)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+(y*getrowsize())+(x*getVRAMMemAddrSize());
	VRAM_writedirect(pixelnumber,color); //Write byte to VRAM!
}

//END OF VGA COLOR SUPPORT! 
Last edited on
Continued:
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
109
110
//SVGA color support

union
{
	struct
	{
		union
		{
			struct
			{
				byte datalow;
				byte datahigh;
			};
			word data;
		};
	};
	struct
	{
		byte b : 5;
		byte g : 5;
		byte r : 5;
		byte u : 1;
	};
} decoder32k; //32K decoder!

/*
32k colors: 1:5:5:5
*/

inline uint_32 MEMGRAPHICS_get32kcolors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+((y*xres)*2)+(x*2); //Starting pixel!
	decoder32k.datahigh = VRAM_readdirect(pixelnumber+1);
	decoder32k.datalow = VRAM_readdirect(pixelnumber);
	return getcolX(decoder32k.r,decoder32k.g,decoder32k.b,0x1F); //Give RGB!
}

inline void MEMGRAPHICS_put32kcolors(uint_32 startaddr, int x, int y, int xres, int yres, word color)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+((y*xres)*2)+(x*2); //Starting pixel!
	VRAM_writedirect(pixelnumber,(color&0xFF)); //Low
	VRAM_writedirect(pixelnumber+1,((color>>8)&0xFF)); //High!
}

union
{
	struct
	{
		union
		{
			struct
			{
				byte datalow;
				byte datahigh;
			};
			word data;
		};
	};
	struct
	{
		byte b : 5;
		byte g : 6;
		byte r : 5;
	};
} decoder64k; //64K decoder!


/*
64k colors: 5:6:5
*/

inline uint_32 MEMGRAPHICS_get64kcolors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+((y*xres)*2)+(x*2); //Starting pixel!
	decoder64k.datahigh = VRAM_readdirect(pixelnumber+1);
	decoder64k.datalow = VRAM_readdirect(pixelnumber);
	return getcol64k(decoder32k.r,decoder32k.g,decoder32k.b); //Give RGB!
}

inline void MEMGRAPHICS_put64kcolors(uint_32 startaddr, int x, int y, int xres, int yres, word color)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+((y*xres)*2)+(x*2); //Starting pixel!
	VRAM_writedirect(pixelnumber,(color&0xFF)); //Low
	VRAM_writedirect(pixelnumber+1,((color>>8)&0xFF)); //High!
}


/*
24 bits true color 8:8:8
*/

inline uint_32 MEMGRAPHICS_getTruecolors(uint_32 startaddr, int x, int y, int xres, int yres)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+((y*xres)*3)+(x*3); //Starting pixel!
	return RGB(VRAM_readdirect(pixelnumber),VRAM_readdirect(pixelnumber+1),VRAM_readdirect(pixelnumber+2));
}

inline void MEMGRAPHICS_putTruecolors(uint_32 startaddr, int x, int y, int xres, int yres, uint_32 color)
{
	uint_32 pixelnumber;
	pixelnumber = startaddr+((y*xres)*3)+(x*3); //Starting pixel!
	VRAM_writedirect(pixelnumber,(color&0xFF)); //R
	VRAM_writedirect(pixelnumber+1,((color>>8)&0xFF)); //G
	VRAM_writedirect(pixelnumber+2,((color>>16)&0xFF)); //B
}


Video controller graphics line-based rendering (one scanline at a time) and passing it to the attribute controller:
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
#include "headers/emu/gpu.h" //GPU!
#include "headers/hardware/vga.h" //VGA!
#include "headers/hardware/vga_screen/vga_attributecontroller.h" //Attribute controller!
#include "headers/hardware/vga_screen/vga_sequencer_graphicsmode.h" //Text mode!
#include "headers/hardware/vga_screen/vga_sequencer_textmode.h" //Text mode!
#include "headers/hardware/vga_screen/vga_sequencer_textmode_cursor.h" //Text mode cursor!
#include "headers/hardware/vga_screen/vga_displaygeneration_crtcontroller.h" //CRT Controller for finishing up!
#include "headers/cpu/interrupts.h" //For get/putpixel variant!

extern uint_32 CurrentScanLine[1024]; //Current scan line!
extern VGA_type VGA; //VGA!

inline void VGA_Sequencer_GraphicsMode(word Scanline, word x, word tempx, word tempy, VGAInfo *info, byte bytepanning)
{
	VGA_AttributeInfo tempattribute; //For holding the attribute in the case of 
	switch (info->VRAMmode) //What color depth?
	{
	case 1: //Black/white?
		tempattribute.attribute = MEMGRAPHICS_get2colors(info->startMap+bytepanning,tempx,tempy,getxres(),getyres()); //Plot 2 bits!
		tempattribute.attribute_graphics = 1; //Take the attribute raw!
		tempattribute.attribute = tempattribute.attribute?0xF:0x0; //Black or white translation!
		CurrentScanLine[x] = 1; //The pixel pixel is always foreground color!
		VGA_AttributeController(Scanline, x, &tempattribute); //Process attribute to DAC index!		
		break;
	case 4: //4 colors?
		switch (MEMGRAPHICS_get4colors(info->startMap+bytepanning,tempx,tempy,getxres(),getyres())) //What color to attribute?
		{
		default:
		case 0:
			tempattribute.attribute = 0; //Attribute!
			break;
		case 1:
			tempattribute.attribute = 1; //Attribute!
			break;
		case 2:
			tempattribute.attribute = 4; //Attribute!
			break;
		case 3:
			tempattribute.attribute = 5; //Attribute!
			break;
		}
		tempattribute.attribute_graphics = 1; //Take the attribute raw: we're getting the font(always font) color from the lookup!
		CurrentScanLine[x] = 1; //The pixel pixel is always foreground color!

		VGA_AttributeController(Scanline, x, &tempattribute); //Process attribute to DAC index!
		break;
	case 16: //16 colors?
		tempattribute.attribute = MEMGRAPHICS_get16colors(info->startMap+bytepanning,tempx,tempy,getxres(),getyres()); //Plot 16 colors!
		tempattribute.attribute_graphics = 1; //Take the attribute raw!
		CurrentScanLine[x] = 1; //The scanline pixel is always on!

		VGA_AttributeController(Scanline, x, &tempattribute); //Process attribute to DAC index!
		break;
	case 256: //256 colors?
		CurrentScanLine[x] = MEMGRAPHICS_get256colors(info->startMap+bytepanning,tempx,tempy,getxres(),getyres()); //Plot 256 colors: already DAC compatible!
		break;
	default: //Unknown?
		CurrentScanLine[x] = 0; //None!
	}
}

Line 42 gives a description about the attribute_graphics flag.
Last edited on
Topic archived. No new replies allowed.