VGA Artefacts & understanding planes

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
snijj
Posts: 17
Joined: Sat Apr 04, 2015 9:35 am
Location: Scarborough, UK

VGA Artefacts & understanding planes

Post by snijj »

Hey,

Recently I've been trying to get VGA drawing working (640x480 16-colours) and have been drawing from the VGA Hardware page on the wiki, Chris Giese's example code and osdever.net for help learning and understanding everything. My first attempts were at drawing single pixels to the screen using the method shown in Chris Giese's demo, but obviously that was hilariously slow and more of a demo of how the memory is addressed. So I began taking what I had learnt there and from other places and began putting together something. It mostly works, but there is an issue:

Image

There are artefacts showing in the image. I've tried inspecting the appropriate memory locations in BOCHS and everything appears to be what I expected, but this is where I'm not sure my understanding of the planes is quite correct.

Plane 0 (0xA0000 - 0xAFFFF) is where bit 4 of the colour goes (brightness)
Plane 1 (also 0xA0000 - 0xAFFFF) is where bit 3 of the colour goes (red)
Plane 2 (also 0xB0000 - 0xB7FFF) is where bit 2 of the colour goes (green)
Plane 3 (also 0xB8000 - 0xBFFFF) is where bit 1 of the colour goes (blue)

The problem is I can quite understand what is going on with Plane 0 and Plane 1? Surely plane 1 should be at 0xa8000. However that just makes the situation worse. I also clear all of VGA memory before re-enabling the display, so I'm pretty certain its my code generating this noise.

What I'm doing is working in an offscreen buffer, where each pixel is 1 byte (wasteful I know, but more interested in getting it functional for now). Currently I'm trying to blit the entire thing to VGA memory at once (operating on runs of 8 pixels at a time.) The code is below:

Code: Select all

static inline vga_set_plane(uint8_t p)
{
	p &= 3;
	uint8_t pmask = 1 << p;
	outb(VGA_GC_INDEX, 4);
	outb(VGA_GC_DATA, p);
	outb(VGA_SEQ_INDEX, 2);
	outb(VGA_SEQ_DATA, pmask);
}

static inline vga_blit_buffer_full(struct display *display)
{
	static uint32_t plane_offsets[] = {0xa0000, 0xa8000, 0xb0000, 0xb8000};
	static uint8_t c_mask[] = {0x1, 0x2, 0x4, 0x8};
	static uint8_t c_shift[] = {0, 1, 2, 3};

	uint32_t width_in_bytes = display->width / 8;
	uint32_t buffer_offset = (uint32_t)display->buffer;
	for (uint32_t y = 0; y < display->height; ++y) {
		for (uint32_t x = 0; x < display->width; x += 8) {

			uint8_t *pixel = (uint8_t *)buffer_offset;
			uint32_t vga_offset = (width_in_bytes) * y + x / 8;

			for (uint8_t p = 0; p < 4; ++p) {
				vga_set_plane(p);
				uint8_t chunk = 0;
				uint8_t mask = 0x80;
				for (uint32_t i = 0; i < 8; ++i) {
					uint8_t c = ((*(pixel + i) & c_mask[p]) >> c_shift[p]);
					if (c) {
						chunk |= mask;
					}
					mask >>= 1;
				}
				*((uint8_t *)(plane_offsets[p] + vga_offset)) = chunk & 0xFF;
			}

			buffer_offset++;
		}
	}
}
The display struct is just a structure in which I keep some properties about the current state of the display, dimensions, off screen buffer and such. I'm pretty certain it's probably my understanding of VGA planes that is causing the issue. If anyone could point me in the right direction that would be appreciated.

Edit
I've just tried setting the screen to be red and this is the result that I get

Image
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: VGA Artefacts & understanding planes

Post by Agola »

I can be wrong as I didn't use VGA for years, but maybe it worth trying.

I remember write addresses doesn't change by changing planes, it is always 0xA0000. VGA addresses are memory-mapped, so changing plane will make new plane point at 0xA0000.

Again, I can be wrong, as I forgot VGA.
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
snijj
Posts: 17
Joined: Sat Apr 04, 2015 9:35 am
Location: Scarborough, UK

Re: VGA Artefacts & understanding planes

Post by snijj »

Agola wrote:I can be wrong as I didn't use VGA for years, but maybe it worth trying.

I remember write addresses doesn't change by changing planes, it is always 0xA0000. VGA addresses are memory-mapped, so changing plane will make new plane point at 0xA0000.

Again, I can be wrong, as I forgot VGA.
However in this case you are very correct! That seems to have fixed the issue. I knew there had to be something I was missing with regards to those planes.

Thanks a lot!
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: VGA Artefacts & understanding planes

Post by Brendan »

Hi,
snijj wrote:Plane 0 (0xA0000 - 0xAFFFF) is where bit 4 of the colour goes (brightness)
Plane 1 (also 0xA0000 - 0xAFFFF) is where bit 3 of the colour goes (red)
Plane 2 (also 0xB0000 - 0xB7FFF) is where bit 2 of the colour goes (green)
Plane 3 (also 0xB8000 - 0xBFFFF) is where bit 1 of the colour goes (blue)
No; there's a "plane select register" that controls which plane you're writing to, and it's actually like this:
  • Plane 0 (0xA0000 - 0xA7FFF) is where bit 3 of the colour goes (brightness)
    Plane 1 (also 0xA0000 - 0xA7FFF) is where bit 2 of the colour goes (red)
    Plane 2 (also 0xA0000 - 0xA7FFF) is where bit 1 of the colour goes (green)
    Plane 3 (also 0xA0000 - 0xA7FFF) is where bit 0 of the colour goes (blue)
However it's not that simple because there's also different "write modes", and it could be completely different, and there's other registers (masks, etc) that can confuse everything more.

My advice is to set the mask to "mask nothing" and make sure the write mode is sane immediately after setting the video mode and never touch any of them ever again. Then build the frame in RAM organised as "all bits for plane0, then all bits for plane1, etc"; then select plane0 and write bit0 for all pixels at once, then select plane1 and write bit1 for all pixels at once, etc.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply