VGA Graphics emulation?

Jul 20, 2013 at 11:33am
I'm currently working on VGA Graphics emulation (the rendering part. Text emulation already works). For some reason I keep getting blue pixels everywhere, when trying to use 256 or 16 color modes?

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
byte logpixels = 0;

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!
	//vramstart += getVRAMScanlineStart(VGA,y)*getVRAMScanlineMultiplier(VGA); //Start of the graphics row!
	
	uint_32 offset; //The offset!
	byte bit; //The bit we need!

	if (VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.Color256ShiftMode) //256-color mode?
	{
		/*uint_32 planeoffset = getVRAMScanlineStart(VGA,y)+x; //The full offset!
		byte result = readVRAMplane(VGA,vramstart,planeoffset%4,planeoffset/4); //Get the 8-bit pixel!
		*/
		offset = getVRAMScanlineStart(VGA,y)+x; //The offset!

		if (logpixels)
		{
			dolog("VGA_VRAM","Scanline size: %i",getVRAMScanlineStart(VGA,1));
			dolog("VGA_VRAM","VRAM Start: %i",vramstart);
			logpixels = 0; //No logging anymore!
		}
		/*if (logpixels && y<5) //First 5 rows only?
		{
			dolog("VRAM","%03i,%03i=%05X",x,y,offset); //Log the result!
			if (x==getxres(VGA) && y==5) //Last X?
			{
				++logpixels; //Next pixel level!
			}
			if (logpixels>2) //More than 2 screens?
			{
				logpixels = 0; //Not logpixels anymore!
			}
		} //Should be OK!
		*/
		return readVRAMdirect(VGA,vramstart,offset); //Seems to work...
	}
	else if (VGA->registers->GraphicsRegisters.REGISTERS.GRAPHICSMODEREGISTER.ShiftRegisterInterleaveMode) //Shift Register Interleave mode?
	{
		uint_32 planeindex = /*getVRAMScanlineStart(VGA,y)+ */ (x/8); //Plane index, should be OK for row 0!
		byte planelow = readVRAMplane(VGA,vramstart,(x%8)/4,planeindex); //Lower plane: OK!
		byte planehigh = readVRAMplane(VGA,vramstart,((x%8)/4)+2,planeindex); //Higher plane: OK!
		byte shift = 6-((x%8)%4)*2; //OK!
		byte bitmask = 3<<shift; //The bitmask for the lower&higher planes: OK!
		return ( //This should be OK!
			((planelow&bitmask)>>shift)|
			(((planehigh&bitmask)>>shift)<<2)
			); //Give the VRAM value of the specified pixel!
	}
	else if (!VGA->registers->ExternalRegisters.MISCOUTPUTREGISTER.IO_AS) //Monochrome mode?
	{
		offset = (getVRAMScanlineStart(VGA,y)+((x/8)*getVRAMMemAddrSize(VGA))); //Offset!
		bit = 7-(x%8); //The bit in the byte!
		return getBitPlaneBit(VGA,vramstart,0,offset,bit); //Give the bit from VRAM plane 0!
	}
	else //16-color mode = Single shift?
	{
		//TODO!
		return 0xF; //White out!
		bit = 7-((x%4)*2); //The bit number!
		offset = (getVRAMScanlineStart(VGA,y)+((x/8)*getVRAMMemAddrSize(VGA)));
		return (getBitPlaneBit(VGA,vramstart,0,offset,bit)| //Bit0
			(getBitPlaneBit(VGA,vramstart,1,offset,bit)<<1)| //Bit1
			(getBitPlaneBit(VGA,vramstart,2,offset,bit)<<2)| //Bit2
			(getBitPlaneBit(VGA,vramstart,3,offset,bit)<<3)); //Bit3
	}
}


Btw, getBitPlaneBit(VGA instance(Which holds the full VRAM and all other VGA related settings, registers etc.), VRAM start address(0-VRAMsize), Plane number(0-3), Byte number within Plane(Normally 0-65535), Bit(0=9)) gives a bit from VRAM.
readVRAMplane is the same, but without the bit option (thus returning a whole byte of VRAM).
getVRAMScanLineStart(VGA,Scanline) returns the start address of a scanline in VRAM, from the beginning of VRAM (Using a precalculated value:

1
2
3
4
uint_32 getVRAMScanlineStart(VGA_Type *VGA,word Scanline) //Start of a scanline!
{
	return VGA->precalcs.scanlinesize*Scanline; //Give the start of the row!
}


Calculation of precalcs scanlinesize:
1
2
3
4
5
6
7
8
9
10
11

VGA->precalcs.rowsize = (VGA->registers->CRTControllerRegisters.REGISTERS.OFFSETREGISTER<<1);

...

VGA->precalcs.VRAMmemaddrsize = VGA->registers->CRTControllerRegisters.REGISTERS.UNDERLINELOCATIONREGISTER.DW?4:
							(VGA->registers->CRTControllerRegisters.REGISTERS.CRTCMODECONTROLREGISTER.UseByteMode?1:2); //Memory address size!

...

VGA->precalcs.scanlinesize = VGA->precalcs.rowsize*VGA->precalcs.VRAMmemaddrsize; //Scanline size! 

)
Last edited on Jul 20, 2013 at 6:26pm
Jul 20, 2013 at 6:28pm
Got it working so far on the 256 color shift mode and the Monochrome mode. Anyone knows what's going wrong with the Shift Register Interleave mode and the 16-color mode?
Topic archived. No new replies allowed.