VGA 4&16 color mode?

Anyone knows how to read pixels from an x,y coordinate using the VGA register values?

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
byte readVRAMdirect(VGA_Type *VGA, uint_32 start, uint_32 offset) //Used in 256 color mode!
{
	if (!VGA->VRAM_size) return 0; //No size!
	return VGA->VRAM[SAFEMOD((start*4)+offset,VGA->VRAM_size)]; //The full protected offset!
}

void writeVRAMdirect(VGA_Type *VGA, uint_32 start, uint_32 offset, byte value) //See readVRAMdirect above!
{
	if (!VGA->VRAM_size) return; //No size!
	VGA->VRAM[SAFEMOD((start*4)+offset,VGA->VRAM_size)] = value; //Write with overflow protection!
}

byte readVRAMplane(VGA_Type *VGA, uint_32 start, byte plane, uint_32 offset) //Read from a VRAM plane!
{
	uint_32 fulloffset = SAFEMOD(start+(offset*4)+(3-plane),VGA->VRAM_size); //Full offset!
	return VGA->VRAM[fulloffset];
}

void writeVRAMplane(VGA_Type *VGA, uint_32 start, byte plane, uint_32 offset, byte value) //Write to a VRAM plane!
{
	uint_32 fulloffset = SAFEMOD(start+(offset*4)+(3-plane),VGA->VRAM_size); //Full offset!
	VGA->VRAM[fulloffset] = value;
}

byte getBitPlaneBit(VGA_Type *VGA, uint_32 start, int plane, uint_32 offset, byte bit)
{
	return GETBIT(readVRAMplane(VGA,start,plane,offset),bit); //Give the bit!
}

void setBitPlaneBit(VGA_Type *VGA, uint_32 start, int plane, uint_32 offset, byte bit, byte on)
{
	writeVRAMplane(VGA,start,plane,offset,BITON(SETBIT0(readVRAMplane(VGA,start,plane,offset),bit),(on<<bit))); //Set the bit!
}


Currently the 4-color modes are read like this (interleaved shift mode):
1
2
3
4
5
6
7
8
9
10
11
12
			//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,scanlineoffset+planebase+((vramstart+planeindex)*4),y,scanlineoffset))); //Lower plane: OK!
		byte planehigh = readVRAMdirect(VGA,0,addresswrap(VGA,patch_map1314(VGA,scanlineoffset+planebase+2+((vramstart+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!
		return ( //This should be OK!
			((planelow&bitmask)>>shift)|
			(((planehigh&bitmask)>>shift)<<2)
			); //Give the VRAM value of the specified pixel! 


256 color mode (working):
1
2
3
4
5
6
		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!
		return readVRAMdirect(VGA,0,fulloffset); //The full offset of the plane! 


256 color helper function:

1
2
3
4
5
6
7
8
//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!
}


Currently 16-color planar mode (Native mode) is read like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//dolog("VGA_16Color","Row: %i; CalcCPU: %i; Our value: %i",y,MMU_rw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8*y,getVRAMScanlineStart(VGA,y)*8); //Debug exchange!
		//Should be OK?
		byte result;
		offset = (x/8); //The start offset in real VRAM!
		bit = 7-(x&7); //The bit in the byte!
		//16-color mode!
		result = (
			(getBitPlaneBit(VGA,getVRAMScanlineStart(VGA,y),0,vramstart+offset,bit))|
			(getBitPlaneBit(VGA,getVRAMScanlineStart(VGA,y),1,vramstart+offset,bit)<<1)|
			(getBitPlaneBit(VGA,getVRAMScanlineStart(VGA,y),2,vramstart+offset,bit)<<2)|
			(getBitPlaneBit(VGA,getVRAMScanlineStart(VGA,y),3,vramstart+offset,bit)<<3)
			);
		if (!VGA->registers->ExternalRegisters.MISCOUTPUTREGISTER.IO_AS) //Monochrome mode uses only plane 0?
		{
			if (DEBUG_COLORS) return getcolorrel(x,0x2,getxres(VGA));
			//result &= 0x1; //Only bit0!
		} //Isn't this handled by the attribute controller?
		if (DEBUG_COLORS) return getcolorrel(x,0x10,getxres(VGA));
		return result; //Give the result! 


getVRAMScanlineStart(VGA,y) gives the offset register multiplied by 2 (shl 1), multiplied with the current memory address size (byte, word or dword) multiplied by the scanline.

256-color mode is already working.

GETBIT gives a bit #(0-7) of a specified byte.

writeVRAMplane & readVRAMplane are used by the CPU to write data to VRAM (address 0xA000:xxxx-0xBFFF:xxxx), determined by the memory read and write modes(working) and the odd/even, planar or chain4 enable mode (working).

Anyone can tell me how to get the 16 color and interleaved shift mode working?

ZIP with screen captures: http://superfury.heliohost.org/cplusplus/GRAPHICSANDTEXTMODES_20130804_2059.zip
Last edited on
closed account (G309216C)
Hi,

I am not expert in VGA but you can intercept the interrupts from the sector 0 , Master Boot Sector, the reason being is because interrupts are privileged so you cannot access them directly so you need to create a bootloader.

Look at these: http://en.wikipedia.org/wiki/INT_10H

It has information regarding intercepting and reading pixels from screen, you need to place a hook on the following interrupts then pass it on to Kernel which should be recived by a Driver then the Driver should build a connection bridge across to the Ring3 application which would be what the end user sees then the ring3 application should process the information.

The hooking of these interrupts require highly complex methods unlike the Ring3 functions or even Ring0 functions such as KiFastSystemCall and ZwOpenProcess and NtCreateThread and such.

Next all I can say is expect a large hook callback.
@SpaceWorm: I'm building an emulator (8086/80186 atm), not a kernel to run within it. (Like an OS etc.) I just want the emulator to work with full VGA emulation. (So others than text mode and 256-color mode too.)
Topic archived. No new replies allowed.