VGA 4&16 color mode errors need fixing.

I have made some code based on the freeVGA documentation, but (with exception of the 256-color mode and text mode), all other color modes fail. Anyone can tell me what's going wrong (16 color mode used to work)?

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
#include "headers/types.h" //Basic types!
#include "headers/emu/gpu/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" //Graphics mode!
#include "headers/hardware/vga_screen/vga_displaygeneration_crtcontroller.h" //For scanline start!
#include "headers/hardware/vga_screen/vga_vram.h" //Our VRAM support!
#include "headers/cpu/interrupts.h" //For get/putpixel variant!
#include "headers/support/log.h" //Logging support!
#include "headers/mmu/mmu.h" //For BIOS data!
#include "headers/header_dosbox.h" //For comp.

//To debug all colors using getcolorrel?
#define DEBUG_COLORS 0
#define IGNOREATTRPLANES 1

byte LOG_RENDER_BYTES = 0; //Log all rendering of scanline #0!

byte getcolorrel(int x,int maxcolor,int xsize)
{
	return (byte)SAFEMOD(((int)convertrel(x,xsize,maxcolor)),maxcolor);
}

//This should be OK, according to: http://www.nondot.org/sabre/Mirrored/GraphicsProgrammingBlackBook/gpbb31.pdf
void calculate256colorplaneoffset(VGA_Type *VGA, int x, int y, byte *plane, uint_32 *fulloffset, uint_32 vramstart) //Calculates 256-color plane&offset, not counting start register!
{
	uint_32 scanlineoffset = getVRAMScanlineStart(VGA,y)*2; //Scanline offset!
	*fulloffset = (vramstart*4)+scanlineoffset+x; //The offset within all four planes!
	*fulloffset = addresswrap(VGA,patch_map1314(VGA,*fulloffset,y,scanlineoffset)); //The full offset of the plane!
	*plane = (*fulloffset%4); //The used plane!
}

typedef uint_64 (*agetcolorplanes)(VGA_Type *VGA, int x, int y, word vramstart); //For our jumptable for getcolorplanes!
typedef byte (*agetpixel)(VGA_Type *VGA, int x, int y, word vramstart); //For our jumptable for getpixel!
typedef void (*graphicsmode_processor)(VGA_AttributeInfo *Sequencer_attributeinfo); //Graphics mode pixel processor!

/*

256 COLOR MODE

*/

uint_64 getcolorplanes256colorshiftmode(VGA_Type *VGA, int x, int y, word vramstart) //256colorshiftmode getcolorplanes!
{
	//dolog("VGA","getcolorplanes256colorshiftmode...");
	uint_32 offset;
	uint_64 result = 0;
	byte currentbit;
	if (DEBUG_COLORS) return 0xE0E0E0E0E0E0E0E0LL; //All allowed!
	byte plane;
	calculate256colorplaneoffset(VGA,x,y,&plane,&offset,vramstart); //Calculate the offset!
	if (plane) //Gotten used a plane?
	{
		for (currentbit=0;currentbit<8;currentbit++) //Process all bits!
		{
			result |= ((1<<plane)<<(currentbit*8)); //Set the plane to this!
		}
	}
	//dolog("VGA","getcolorplanes256colorshiftmode>RET...");
	return result; //Give the result!
}

byte getpixel256colorshiftmode(VGA_Type *VGA, int x, int y, word vramstart) //256colorshiftmode getcolorplanes!
{
	//dolog("VGA","getpixel256colorshiftmode...");
	uint_32 offset;
	if (DEBUG_COLORS) return getcolorrel(x,0x100,getxres(VGA));
	byte plane;
	calculate256colorplaneoffset(VGA,x,y,&plane,&offset,vramstart); //Calculate the offset in real VRAM!
	
	uint_32 fulloffset = offset+plane; //The full offset in real VRAM!
	//dolog("VGA","getpixel256colorshiftmode>RET...");
	return readVRAMdirect(VGA,0,fulloffset); //The full offset of the plane!
}

void VGA_Sequencer_GraphicsMode_256colorshiftmode(VGA_AttributeInfo *Sequencer_attributeinfo)
{
	//dolog("VGA","VGA_Sequencer_GraphicsMode_256colorshiftmode...");
	Sequencer_attributeinfo->attribute_graphics = 2; //Disable attribute controller!
	//dolog("VGA","VGA_Sequencer_GraphicsMode_256colorshiftmode>RET...");
}

/*

SHIFT REGISTER INTERLEAVE MODE

*/

uint_64 getcolorplanesshiftregisterinterleavemode(VGA_Type *VGA, int x, int y, word vramstart) //256colorshiftmode getcolorplanes!
{
	//dolog("VGA","getcolorplanesshiftregisterinterleavemode...");
	uint_64 result = 0;
	if (DEBUG_COLORS) return 0xF0F0F0F0E0E0E0E0LL; //All 4 bits allowed!
	byte planebase = (x/4)%2; //Base plane (0/1)! OK!
	byte planebaselow = planebase; //Base plane (0/1)! OK!
	byte planebasehigh = planebase+2; //High plane (2/3)! OK!
	//dolog("VGA","getcolorplanesshiftregisterinterleavemode>Planes:Low:%i,High:%i",planebaselow,planebasehigh); //Plane bases!
	
	if (VGA->precalcs.VRAMmemaddrsize==2) //Word mode?
	{
		if (!VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.AW) //Appear as if only 64k memory is present?
		{
			planebaselow = 0; //Force plane #0 (65k mem)
			planebasehigh = 0; //Force plane #0 (65k mem)
		}
	}
	byte currentbit;
	for (currentbit=0;currentbit<8;currentbit++) //Process all bits!
	{
		if (currentbit<2) //Low plane?
		{
			result |= ((1<<planebaselow)<<(currentbit*8));
		}
		else if (currentbit<4) //High plane?
		{
			result |= ((1<<planebasehigh)<<(currentbit*8));
		}
	}
	result |= 0xF0F0F0F000000000LL; //The high bits are unused!
	//dolog("VGA","getcolorplanesshiftregisterinterleavemode>RET:%016X...",result);
	return result; //Give the result!
}

byte getpixelshiftregisterinterleavemode(VGA_Type *VGA, int x, int y, word vramstart) //256colorshiftmode getcolorplanes!
{
	//dolog("VGA","getpixelshiftregisterinterleavemode...");
	if (DEBUG_COLORS) return getcolorrel(x,0x16,getxres(VGA)); //We assume we're mode 4/5!
	//TODO!
	uint_32 scanlineoffset = getVRAMScanlineStart(VGA,y); //Scanline offset!
	uint_32 planeindex = (x/8)*getVRAMMemAddrSize(VGA); //The full offset, within the plane with our pixel!
	byte planebase = (x/4)%2; //Base plane (0/1)! OK!
	byte planelow = readVRAMdirect(VGA,0,addresswrap(VGA,patch_map1314(VGA,((vramstart+scanlineoffset)*4)+planebase+(planeindex*4),y,scanlineoffset))); //Lower plane: OK!
	byte planehigh = readVRAMdirect(VGA,0,addresswrap(VGA,patch_map1314(VGA,addresswrap(VGA,((vramstart+scanlineoffset)*4)+planebase+2+(planeindex*4)),y,scanlineoffset))); //Higher plane: OK!
	byte shift = 6-((x%4)*2); //OK!
	byte bitmask = 3<<shift; //The bitmask for the lower&higher planes: OK!
	byte result = ( //This should be OK!
		((planelow&bitmask)>>shift)|
		(((planehigh&bitmask)>>shift)<<2)
		); //Give the VRAM value of the specified pixel!
	//dolog("VGA","getpixelshiftregisterinterleavemode>RET:%02X...",result);
	return result; //Give the result!
}

/*

SINGLE SHIFT MODE

*/

uint_64 getcolorplanessingleshiftmode(VGA_Type *VGA, int x, int y, word vramstart)
{
	//Optimized!
	uint_64 result = 0xF0F0F0F008040201LL; //We are from planes 0-3 = Bit 0-3, all other is invalid!
	if (VGA->precalcs.VRAMmemaddrsize==2) //Word mode?
	{
		if (!VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.AW) //Appear as if only 64k memory is present?
		{
			result = 0xF0F0F0F000000000LL; //Force plane #0 (65k mem)
		}
	}
	//dolog("VGA","getcolorplanessingleshiftmode...");
	//dolog("VGA","getcolorplanessingleshiftmode>RET...");
	return result; //Give the result!
}
Last edited on
Part 2:
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
byte getpixelsingleshiftmode(VGA_Type *VGA, int x, int y, word vramstart)
{
	//dolog("VGA","getpixelsingleshiftmode...");
	/*if (!x) //Got a start of a line to test?
	{
		dolog("VGA","singleshiftmode: Row: %i; CalcCPU: %i; Our value: %i",y,MMU_rw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8*y,getVRAMScanlineStart(VGA,y)*8); //Debug exchange! Seems to be OK!
	}*/
	//Should be OK?
	//uint_32 offset = (getVRAMScanlineStart(VGA,y)*8); //The start offset in real VRAM!
	uint_32 offset = getVRAMScanlineStart(VGA,y); //No offset, don't process scanline start!
	offset += (x>>3); //The x coordinate, 8 pixels per byte!
	byte bit = 7-(x&7); //The bit in the byte!
	//dolog("VGA","%04X:x,y=%i,%i=Offset:%08X,bit=%02X,FullOffset=%05X",vramstart,x,y,offset,bit,vramstart+offset); //Log it!
	//getVRAMScanlineStart(VGA,y)
	//16-color mode!
	byte result = (
		(getBitPlaneBit(VGA,vramstart,0,offset,bit))
		|(getBitPlaneBit(VGA,vramstart,1,offset,bit)<<1)
		|(getBitPlaneBit(VGA,vramstart,2,offset,bit)<<2)
		|(getBitPlaneBit(VGA,vramstart,3,offset,bit)<<3)
		);
	//if (DEBUG_COLORS) return getcolorrel(x,0x10,getxres(VGA));
	if (!y) //First row only?
	{
		if (LOG_RENDER_BYTES) //To log rendering bytes?
		{
			dolog("VGA","getpixelsingleshiftmode>RET(%i):%X...",x,result);
		}
	}
	return result; //Give the result!
}

/*

BOTH SHIFT REGISTER INTERLEAVE AND SINGLE SHIFT MODE

*/

void VGA_Sequencer_GraphicsMode_SingleShiftAndInterleavedShift(VGA_AttributeInfo *Sequencer_attributeinfo)
{
	//Black/white?
	//16 colors?
	//Interleaved shift?
	//Normal processing!
	//dolog("VGA","Sequencer_GraphicsMode_SingleShiftAndInterleavedShift...");
}

uint_64 getColorPlanesAlphaNumeric(VGA_Type *VGA, int x, int y, word vramstart) //When !VGA->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.AlphaNumericModeDisable
{
	return 0x0707070707070707LL; //All our colour bits are from plane 0,1&2 (attribute), all others are unknown!
}

uint_64 getColorPlanesIgnoreAttrPlanes(VGA_Type *VGA, int x, int y, word vramstart) //When to ignore attribute planes!
{
	return 0xE0E0E0E0E0E0E0E0LL; //Ignore attribute controller planes!
}

/*

ALL JMPTBLs.

*/

//Shiftregister: 2=ShiftRegisterInterleave, 1=Color256ShiftMode. Priority list: 1, 2, 0; So 1&3=256colorshiftmode, 2=ShiftRegisterInterleave, 0=SingleShift.
//When index0(VGA->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.AlphaNumericModeDisable)=1, getColorPlanesAlphaNumeric
//When index1(IGNOREATTRPLANES)=1, getColorPlanesIgnoreAttrPlanes 
agetcolorplanes getcolorplanes_jmptbl[2][2][4] = {
							{ //Index0=0=AlphaNumericModeDisable=0=Alphanumeric mode!
								{ //IgnoreAttrPlanes=0: don't ignore attribute planes!
									getColorPlanesAlphaNumeric,
									getColorPlanesAlphaNumeric,
									getColorPlanesAlphaNumeric,
									getColorPlanesAlphaNumeric
								},
								{ //IgnoreAttrPlanes=1: Ignore attribute planes!
									getColorPlanesIgnoreAttrPlanes,
									getColorPlanesIgnoreAttrPlanes,
									getColorPlanesIgnoreAttrPlanes,
									getColorPlanesIgnoreAttrPlanes
								}
							},							
							{ //Index0=1=AlphaNumericModeDisable=1=Graphics mode!
								{ //IgnoreAttrPlanes=0: don't ignore attribute planes!
									getcolorplanessingleshiftmode,
									getcolorplanesshiftregisterinterleavemode,
									getcolorplanes256colorshiftmode,
									getcolorplanes256colorshiftmode
								},
								{ //IgnoreAttrPlanes=1: ignore attribute planes!
									getColorPlanesIgnoreAttrPlanes,
									getColorPlanesIgnoreAttrPlanes,
									getColorPlanesIgnoreAttrPlanes,
									getColorPlanesIgnoreAttrPlanes
								},
							}
						}; //Execution flow!

agetpixel getpixel_jmptbl[4] = {
				getpixelsingleshiftmode,
				getpixelshiftregisterinterleavemode,
				getpixel256colorshiftmode,
				getpixel256colorshiftmode
				};

graphicsmode_processor VGA_Sequencer_GraphicsMode_jmptbl[4] = {
				VGA_Sequencer_GraphicsMode_SingleShiftAndInterleavedShift,
				VGA_Sequencer_GraphicsMode_SingleShiftAndInterleavedShift,
				VGA_Sequencer_GraphicsMode_256colorshiftmode,
				VGA_Sequencer_GraphicsMode_256colorshiftmode
				};


//int gmreg = -1; //Graphics mode register selector!

/*

Core functions!

*/

uint_64 getcolorplanes(VGA_Type *VGA, int x, int y) //For the attribute controller: Gives which bits are from which plane! Each nibble contains 1 plane, from nibble #0(0-3)=plane for bit 0 to nibble #8(0xF<<8)=plane for bit 7. Plane can be 0-3 for the plane and 0xF for no plane at all (always ignore these bits).
{
	word vramstart = ((VGA->registers->CRTControllerRegisters.REGISTERS.STARTADDRESSHIGHREGISTER<<8)|VGA->registers->CRTControllerRegisters.REGISTERS.STARTADDRESSLOWREGISTER); //Start address of VRAM display!

	//We're a graphics mode!
	return getcolorplanes_jmptbl[VGA->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.AlphaNumericModeDisable][IGNOREATTRPLANES][VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.ShiftRegister](VGA,x,y,vramstart);
}

byte VGA_getpixel(VGA_Type *VGA, int x, int y)
{
	word vramstart = ((VGA->registers->CRTControllerRegisters.REGISTERS.STARTADDRESSHIGHREGISTER<<8)|VGA->registers->CRTControllerRegisters.REGISTERS.STARTADDRESSLOWREGISTER); //Start address of VRAM display!
	
	//http://www.openwatcom.org/index.php/VGA_Fundamentals:
	//Packed Pixel: Color 256 Shift Mode.
	//Parallel Planes: Else case!
	//Interleaved: Shift Register Interleave!

	if (x>=getxres(VGA) || y>=getyres(VGA)) //Over x/y resolution?
	{
		return 0; //Nothing here!
	}

	/*if ((int)VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.ShiftRegister!=gmreg)
	{
		gmreg = VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.ShiftRegister; //Save for reference!
		dolog("VGA","Video shift mode: %i",gmreg); //Log it!
	}*/

	return getpixel_jmptbl[VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.ShiftRegister](VGA,x,y,vramstart);
}

void VGA_Sequencer_GraphicsMode(VGA_Type *Sequencer_VGA, VGA_AttributeInfo *Sequencer_attributeinfo, word Sequencer_tempx, word Sequencer_tempy, word Sequencer_x) //Used to be: VGA_Type *VGA, word Scanline, word x, word tempx, word tempy, byte bytepanning
{
	//dolog("VGA","VGA_Sequencer_GraphicsMode...");
	Sequencer_VGA->CurrentScanLine[0][Sequencer_x] = 1; //Plot font 256 colors: already DAC compatible!
	Sequencer_attributeinfo->attribute_graphics = 1; //Graphics attribute!
	Sequencer_attributeinfo->attribute = VGA_getpixel(Sequencer_VGA,Sequencer_tempx,Sequencer_tempy); //Read the pixel from VRAM!
	VGA_Sequencer_GraphicsMode_jmptbl[Sequencer_VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.ShiftRegister](Sequencer_attributeinfo); //Extra actions by color depth?

	//As the rest of the rows are simply a copy of ours, don't process them!
	//dolog("VGA","VGA_Sequencer_GraphicsMode>RET...");
}
Topic archived. No new replies allowed.