Make your own OS in 30 days – day4: VRAM
Day 4 initialize pallet and write directly into VRAM in C.
To set pallet,
- disable interrupts (call CLI = CLear Interrupt flag to reset it)
- write pallet number int 0x03c8
- write R, G, B into 0x03c9 in the order
- 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.
Day 5 will draw characters and the mouse cursor which doesn't move, and learn segmentation and interrupt.