Make your own OS in 30 days – day4: VRAM

Day 4 initialize pallet and write directly into VRAM in C.
To set pallet,

  1. disable interrupts (call CLI = CLear Interrupt flag to reset it)
  2. write pallet number int 0x03c8
  3. write R, G, B into 0x03c9 in the order
  4. restore the interrupt flag

Since the interrupt flag is the 9th bit of the eflags, if you restore it, you don’t need to call STI.

void set_palette(int start, int end, unsigned char *rgb)
{
	int i, eflags;
	eflags = io_load_eflags();	/* save the current eflags */
	io_cli(); 			/* disable interrupts */
	io_out8(0x03c8, start);		/* send data to the device 3c8 */
	for (i = start; i <= end; i++) {
		io_out8(0x03c9, rgb[0] / 4);  /* send data to the device 3c9 */
		io_out8(0x03c9, rgb[1] / 4);
		io_out8(0x03c9, rgb[2] / 4);
		rgb += 3;
	}
	io_store_eflags(eflags);	/* reset eflags */
	return;
}

io_load_eflags, io_store, flags, _io_cli and io_out8 are written as below.

_io_cli:
		CLI
		RET

_io_out8:
		MOV		EDX,[ESP+4]		; port
		MOV		AL,[ESP+8]		; data
		OUT		DX,AL
		RET

_io_load_eflags:
		PUSHFD		; PUSH EFLAGS
		POP		EAX
		RET

_io_store_eflags:
		MOV		EAX,[ESP+4]
		PUSH	EAX
		POPFD		; POP EFLAGS
		RET

Now we are ready to write in VRAM (starts at 0xa000).

{
...
    vram = (char *) 0xa0000;
    xsize = 320;
    ysize = 200;
    boxfill8(vram, xsize, COL8_008484,  0,         0,          xsize -  1, ysize - 29);
...
}

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
    int x, y;
        for (y = y0; y <= y1; y++) {
            for (x = x0; x <= x1; x++)
                vram[y * xsize + x] = c;
    }
    return;
}

When you draw several rectangles, it'll be like this.
OS_day04_1

Day 5 will draw characters and the mouse cursor which doesn't move, and learn segmentation and interrupt.

Leave a Reply

Your email address will not be published. Required fields are marked *