Code: Select all
#include "vga.h"
#include "../kernel/port.h"
//This code was adapted from a tutorial by Create Your Own Operating System on YouTube (https://www.youtube.com/watch?v=N68cYNWZgy8&ab_channel=WriteyourownOperatingSystem)
uint16_t miscPort;
uint16_t crtcIndexPort;
uint16_t crtcDataPort;
uint16_t sequencerIndexPort;
uint16_t sequencerDataPort;
uint16_t graphicsControllerIndexPort;
uint16_t graphicsControllerDataPort;
uint16_t attributeControllerIndexPort;
uint16_t attributeControllerReadPort;
uint16_t attributeControllerWritePort;
uint16_t attributeControllerResetPort;
bool vgad_supports_mode(uint32_t width, uint32_t height, uint32_t colordepth){
//Just implment 320 x 200 x 8 for now
return width == 320 && height == 200 && colordepth == 8;
}
//TODO make this more advanced
bool vgad_set_mode(uint32_t width, uint32_t height, uint32_t colordepth){
if (!vgad_supports_mode(width, height, colordepth)){
return false;
}
uint8_t g_320x200x256[] =
{
/* MISC */
0x63,
/* SEQ */
0x03, 0x01, 0x0F, 0x00, 0x0E,
/* CRTC */
0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
0xFF,
/* GC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
0xFF,
/* AC */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x41, 0x00, 0x0F, 0x00, 0x00
};
vgad_write_registers(g_320x200x256);
return true;
}
void vgad_write_registers(uint8_t *registers){
p_write8(miscPort, *(registers++));
for (uint8_t i = 0; i < 5; i++){
p_write8(sequencerIndexPort, i);
p_write8(sequencerDataPort, *(registers++));
}
//Problems here
p_write8(crtcIndexPort, 0x03);
p_write8(crtcDataPort, p_read8(crtcDataPort) | 0x80);
p_write8(crtcIndexPort, 0x11);
p_write8(crtcDataPort, p_read8(crtcDataPort) & ~0x80);
registers[0x03] = registers[0x03] | 0x80;
registers[0x11] = registers[0x11] & ~0x80;
for (uint8_t i = 0; i < 25; i++){
p_write8(crtcIndexPort, i);
p_write8(crtcDataPort, *(registers++));
}
for (uint8_t i = 0; i < 9; i++){
p_write8(graphicsControllerIndexPort, i);
p_write8(graphicsControllerDataPort, *(registers++));
}
for (uint8_t i = 0; i < 21; i++){
p_read8(attributeControllerResetPort);
p_write8(attributeControllerIndexPort, i);
p_write8(attributeControllerWritePort, *(registers++));
}
p_read8(attributeControllerResetPort);
p_write8(attributeControllerIndexPort, 0x20);
}
uint8_t* vgad_get_framebuffer_segment(){
p_write8(graphicsControllerIndexPort, 0x06);
uint8_t segmentNumber = ((p_read8(graphicsControllerDataPort) >> 2) & 0x03);
switch (segmentNumber)
{
default:
case 0:
return (uint8_t*)0x0000;
case 1:
return (uint8_t*)0xA000;
case 2:
return (uint8_t*)0xB000;
case 3:
return (uint8_t*)0xB800;
}
}
void vgad_put_pixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b){
vgad_put_pixel_index(x, y, vgad_get_color_index(r, g, b));
}
void vgad_put_pixel_index(uint32_t x, uint32_t y, uint8_t colorIndex){
uint8_t *pixelAddress = vgad_get_framebuffer_segment() + 320 * y + x;
*pixelAddress = colorIndex;
}
uint8_t vgad_get_color_index(uint8_t r, uint8_t g, uint8_t b){
//This is stupid, don't do this
if (r == 0x00 && g == 0x00 && b == 0xA8){
return 0x01;
}
return 0x0;
}
void vgad_init(){
miscPort = 0x3C2;
crtcIndexPort = 0x3D4;
crtcDataPort = 0x3D5;
sequencerIndexPort = 0x3C4;
sequencerDataPort = 0x3C5;
graphicsControllerIndexPort = 0x3CE;
graphicsControllerDataPort = 0x3CF;
attributeControllerIndexPort = 0x3C0;
attributeControllerReadPort = 0x3C1;
attributeControllerWritePort = 0x3C0;
attributeControllerResetPort = 0x3DA;
}