From eb5f08c76b17ac6e15d6b763a7f45816cb85c570 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Tue, 10 Nov 2009 21:26:03 +0100 Subject: Started working on some 2D gra --- Source/Kernel/Devices/Display/Display.proto.h | 8 +- .../Devices/Display/GraphicDisplay.proto.cpp | 64 +++++++++++ .../Kernel/Devices/Display/GraphicDisplay.proto.h | 24 ++++ .../Kernel/Devices/Display/VESADisplay.class.cpp | 127 +++++++++++++++++++++ Source/Kernel/Devices/Display/VESADisplay.class.h | 65 +++++++++++ .../Kernel/Devices/Display/VGATextOutput.class.cpp | 16 ++- .../Kernel/Devices/Display/VGATextOutput.class.h | 6 +- Source/Kernel/Devices/Display/vga-vesa.wtf.asm | 11 ++ 8 files changed, 312 insertions(+), 9 deletions(-) create mode 100644 Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp create mode 100644 Source/Kernel/Devices/Display/GraphicDisplay.proto.h create mode 100644 Source/Kernel/Devices/Display/VESADisplay.class.cpp create mode 100644 Source/Kernel/Devices/Display/VESADisplay.class.h (limited to 'Source/Kernel/Devices') diff --git a/Source/Kernel/Devices/Display/Display.proto.h b/Source/Kernel/Devices/Display/Display.proto.h index e1775bd..8401e0b 100644 --- a/Source/Kernel/Devices/Display/Display.proto.h +++ b/Source/Kernel/Devices/Display/Display.proto.h @@ -19,7 +19,13 @@ class Display : public Device { virtual void putChar(u16int line, u16int col, WChar c, u8int color) = 0; //Color : virtual void moveCursor(u16int line, u16int col) = 0; - //Graphic functions + //Graphic functions, can stay unimplemented for textual displays + virtual void putPix(u16int x, u16int y, u32int color) {} + virtual u32int getPix(u16int x, u16int y) { return 0; } + //Advanced graphic functions. These have a simple implementation in GraphicDisplay, + //and should have an optimized version in each individual driver. This is also the + //case of the graphical putChar and moveCursor. + //drawLine, drawCircle, ... }; #endif diff --git a/Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp b/Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp new file mode 100644 index 0000000..636a64c --- /dev/null +++ b/Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp @@ -0,0 +1,64 @@ +#include "GraphicDisplay.proto.h" + +#include + +u32int consoleColor[16] = { + 0x00000000, // 0 == black + 0x00000077, // 1 == dark blue + 0x00007700, // 2 == dark green + 0x00007777, // 3 == dark cyan + 0x00770000, // 4 == dark red + 0x00770077, // 5 == dark magenta + 0x00777700, // 6 == dark orange + 0x00777777, // 7 == light grey + 0x00444444, // 8 == dark grey + 0x000000FF, // 9 == bright blue + 0x0000FF00, // A == bright green + 0x0000FFFF, // B == bright cyan + 0x00FF0000, // C == bright red + 0x00FF00FF, // D == bright yellow + 0x00FFFF00, // E == bright orange + 0x00FFFFFF, // F == white +}; + +void GraphicDisplay::putChar(u16int line, u16int col, WChar c, u8int color) { + u8int ch = c.toAscii(); + if (ch == 0) return; + + u16int sx = col * C_FONT_WIDTH, sy = line * C_FONT_HEIGHT; + u32int fgcolor = consoleColor[color & 0xF], bgcolor = consoleColor[(color >> 4) & 0xF]; + + for (int y = 0; y < C_FONT_HEIGHT; y++) { + u8int pixs = consoleFont[ch][y]; + for (int x = C_FONT_WIDTH - 1; x >= 0; x--) { + putPix(sx + x, sy + y, ((pixs & 1) != 0 ? fgcolor : bgcolor)); + pixs = pixs >> 1; + } + } +} + +void GraphicDisplay::moveCursor(u16int line, u16int col) { + //If the current cursor position is correct, write there what is supposed to be there + if (m_csrbuff.x >= 0 and m_csrbuff.y >= 0) { + for (int x = 0; x < C_FONT_WIDTH; x++) { + for (int y = 0; y < C_FONT_HEIGHT; y++) { + putPix(m_csrbuff.x + x, m_csrbuff.y + y, m_csrbuff.buff[x][y]); + } + } + } + + //Save the current stuff to the buffer + m_csrbuff.x = col * C_FONT_WIDTH; + m_csrbuff.y = line * C_FONT_HEIGHT; + for (int x = 0; x < C_FONT_WIDTH; x++) { + for (int y = 0; y < C_FONT_HEIGHT; y++) { + m_csrbuff.buff[x][y] = getPix(m_csrbuff.x + x, m_csrbuff.y + y); + } + } + + //draw some cursor + for (int x = 0; x < C_FONT_WIDTH; x++) { + putPix(m_csrbuff.x + x, m_csrbuff.y + 14, 0x00FFFFFF); + putPix(m_csrbuff.x + x, m_csrbuff.y + 15, 0x00777777); + } +} diff --git a/Source/Kernel/Devices/Display/GraphicDisplay.proto.h b/Source/Kernel/Devices/Display/GraphicDisplay.proto.h new file mode 100644 index 0000000..2f4be98 --- /dev/null +++ b/Source/Kernel/Devices/Display/GraphicDisplay.proto.h @@ -0,0 +1,24 @@ +#ifndef DEF_GRAPHICDISPLAY_PROTO_H +#define DEF_GRAPHICDISPLAY_PROTO_H + +#include + +extern char consoleFont[256][16]; +extern u32int consoleColor[16]; + +#define C_FONT_WIDTH 9 //This is width of one character ON SCREEN, real width is 8px (1px padding) +#define C_FONT_HEIGHT 16 + +class GraphicDisplay : public Display { + struct { + int x, y; + u32int buff[C_FONT_WIDTH][C_FONT_HEIGHT]; + } m_csrbuff; + + public: + GraphicDisplay() { m_csrbuff.x = -1; m_csrbuff.y = -1; } + virtual void putChar(u16int line, u16int col, WChar c, u8int color); + virtual void moveCursor(u16int line, u16int col); +}; + +#endif diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.cpp b/Source/Kernel/Devices/Display/VESADisplay.class.cpp new file mode 100644 index 0000000..a1dc7c1 --- /dev/null +++ b/Source/Kernel/Devices/Display/VESADisplay.class.cpp @@ -0,0 +1,127 @@ +#include "VESADisplay.class.h" +#include + +extern v86_function_t vesa_int; //in vga-vesa.wtf.asm + +using namespace Disp; + +String VESADisplay::getClass() { + return "display.vesa"; +} + +String VESADisplay::getName() { + return "Standard VESA display"; +} + +vbe_controller_info_t VESADisplay::getCtrlrInfo() { + vbe_controller_info_t *info = (vbe_controller_info_t*)V86::alloc(sizeof(vbe_controller_info_t)); + info->signature[0] = 'V'; info->signature[1] = 'B'; info->signature[2] = 'E'; info->signature[3] = '2'; + info->videomodes = 0; + registers_t regs; + regs.eax = 0x00004F00; + regs.esi = LIN_SEG(info); + regs.edi = LIN_OFF(info); + V86::run(vesa_int, regs, 0); + if (regs.eax != 0x004F) PANIC("Something went wrong in detecting VBE modes."); + if (info->signature[3] != 'A') PANIC("No vesa sinature"); + return *info; +} + +vbe_mode_info_t VESADisplay::getModeInfo(u16int id) { + vbe_mode_info_t *mode = (vbe_mode_info_t*)V86::alloc(sizeof(vbe_mode_info_t)); + CMem::memset((u8int*)mode, 0, sizeof(vbe_mode_info_t)); + registers_t regs; + regs.eax = 0x00004F01; + regs.ecx = id; + regs.esi = LIN_SEG(mode); + regs.edi = LIN_OFF(mode); + V86::run(vesa_int, regs, 0); + return *mode; +} + +void VESADisplay::getModes(Vector &to) { + vbe_controller_info_t info = getCtrlrInfo(); + + u16int *modes = (u16int*)(((info.videomodes & 0xFFFF0000) >> 12) | ((info.videomodes) & 0x0000FFFF)); + for (int i = 0; i < 64; i++) { + if (modes[i] == 0xFFFF) break; + vbe_mode_info_t mode = getModeInfo(modes[i]); + + if ((mode.attributes & 0x19) != 0x19) continue; + if (mode.planes != 1) continue; + mode_t m; m.device = this; + m.textCols = mode.Xres / C_FONT_WIDTH; m.textRows = mode.Yres / C_FONT_HEIGHT; + m.identifier = modes[i]; + m.graphWidth = mode.Xres; m.graphHeight = mode.Yres; m.graphDepth = mode.bpp; + to.push(m); + } +} + +bool VESADisplay::setMode(mode_t &mode) { + if (mode.device != this) return false; + m_currMode = getModeInfo(mode.identifier); + registers_t regs; + regs.eax = 0x00004F02; + regs.ebx = mode.identifier; + V86::run(vesa_int, regs, 0); + return true; +} + +u8int* VESADisplay::memPos(u16int x, u16int y) { + u32int addr = y * m_currMode.pitch + x * (m_currMode.bpp / 8); + + u8int *base = (u8int*)(((m_currMode.physbase & 0xFFFF0000) >> 12) | (m_currMode.physbase & 0x0000FFFF)); + + return base + addr; +} + +void VESADisplay::clear() { + for (u16int y = 0; y < m_currMode.Yres; y++) { + for (u16int x = 0; x < m_currMode.Xres; x++) { + putPix(x, y, 0x77777777); + } + } +} + +void VESADisplay::putPix(u16int x, u16int y, u32int c) { + u32int addr = y * m_currMode.pitch + x * (m_currMode.bpp / 8); + int banksize = m_currMode.granularity*1024; + int banknumber = addr / banksize; + int bankoffset = addr % banksize; + + if (banknumber != b) { + registers_t r; + r.eax = 0x4F05; + r.ebx = 0; + r.edx = banknumber; + V86::run(vesa_int, r, 0); + b = banknumber; + } + + u8int* a = (u8int*)(0xA0000 + bankoffset); + a[2] = (c >> 16) & 0xFF; + a[1] = (c >> 8) & 0xFF; + a[0] = c & 0xFF; +} + +u32int VESADisplay::getPix(u16int x, u16int y) { + u32int addr = y * m_currMode.pitch + x * (m_currMode.bpp / 8); + int banksize = m_currMode.granularity*1024; + int banknumber = addr / banksize; + int bankoffset = addr % banksize; + + if (banknumber != b) { + registers_t r; + r.eax = 0x4F05; + r.ebx = 0; + r.edx = banknumber; + V86::run(vesa_int, r, 0); + b = banknumber; + } + + u32int ret; + + u8int* a = (u8int*)(0xA0000 + bankoffset); + ret = (a[2] << 16) | (a[1] << 8) | a[0]; + return ret; +} diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.h b/Source/Kernel/Devices/Display/VESADisplay.class.h new file mode 100644 index 0000000..9daf1b9 --- /dev/null +++ b/Source/Kernel/Devices/Display/VESADisplay.class.h @@ -0,0 +1,65 @@ +#ifndef DEF_VESADISPLAY_CLASS_H +#define DEF_VESADISPLAY_CLASS_H + +#include +#include + +struct vbe_controller_info_t { + char signature[4]; // == "VESA" + s16int version; // == 0x0300 for VBE 3.0 + //s16int oemString[2]; // isa vbeFarPtr + FARPTR oemString; + u8int capabilities[4]; + FARPTR videomodes; + s16int totalMemory; // as # of 64KB blocks +} __attribute__((packed)); + +struct vbe_mode_info_t { + u16int attributes; + u8int winA, winB; + u16int granularity; + u16int winsize; + u16int segmentA, segmentB; + FARPTR realFctPtr; + u16int pitch; // bytes per scanline + + u16int Xres, Yres; + u8int Wchar, Ychar, planes, bpp, banks; + u8int memory_model, bank_size, image_pages; + u8int reserved0; + + u8int red_mask, red_position; + u8int green_mask, green_position; + u8int blue_mask, blue_position; + u8int rsv_mask, rsv_position; + u8int directcolor_attributes; + + u32int physbase; // your LFB address ;) + u32int reserved1; + u16int reserved2; +} __attribute__ ((packed)); + +class VESADisplay : public GraphicDisplay { + private: + vbe_controller_info_t getCtrlrInfo(); + vbe_mode_info_t getModeInfo(u16int mode); + + u8int* memPos(u16int x, u16int y); + + vbe_mode_info_t m_currMode; + + int b; + + public: + String getClass(); + String getName(); + + void getModes(Vector &to); + bool setMode(Disp::mode_t& mode); + + void clear(); + void putPix(u16int x, u16int y, u32int color); + u32int getPix(u16int x, u16int y); +}; + +#endif diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp index 3265a7d..d307f60 100644 --- a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp +++ b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp @@ -21,19 +21,23 @@ String VGATextOutput::getName() { void VGATextOutput::getModes(Vector &to) { mode_t m; - m.textCols = 80; + m.textCols = 40; m.textRows = 25; - m.identifier = 3; + m.identifier = 1; m.graphWidth = 0; m.graphHeight = 0; m.device = this; to.push(m); + m.textCols = 80; + m.identifier = 3; //3 = text 80x25 16color, just what we want + to.push(m); } bool VGATextOutput::setMode(mode_t& mode) { - if (mode.device == this && mode.identifier == 3) { + if (mode.device == this && (mode.identifier == 3 or mode.identifier == 1)) { registers_t r; - r.eax = 3; //3 = text 80x25 16color, just what we want + r.eax = mode.identifier; + m_cols = mode.textCols; V86::run(setvgamode, r, 0); clear(); return true; @@ -43,11 +47,11 @@ bool VGATextOutput::setMode(mode_t& mode) { void VGATextOutput::putChar(u16int line, u16int col, WChar c, u8int color) { u16int* where = (u16int*)RAM_ADDR; - where[(80 * line) + col] = (color << 8) | c.toAscii(); + where[(m_cols * line) + col] = (color << 8) | c.toAscii(); } void VGATextOutput::moveCursor(u16int line, u16int col) { - u16int csrLoc = (line * 80) + col; + u16int csrLoc = (line * m_cols) + col; outb(0x3D4, 14); outb(0x3D5, csrLoc >> 8); outb(0x3D4, 15); diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.h b/Source/Kernel/Devices/Display/VGATextOutput.class.h index 1ced227..2c72d40 100644 --- a/Source/Kernel/Devices/Display/VGATextOutput.class.h +++ b/Source/Kernel/Devices/Display/VGATextOutput.class.h @@ -4,15 +4,17 @@ #include class VGATextOutput : public Display { + int m_cols; + public: + VGATextOutput() : m_cols(80) {} + String getClass(); String getName(); void getModes(Vector &to); bool setMode(Disp::mode_t& mode); - u16int textCols(); - u16int textRows(); void putChar(u16int line, u16int col, WChar c, u8int color); void moveCursor(u16int line, u16int col); void clear(); diff --git a/Source/Kernel/Devices/Display/vga-vesa.wtf.asm b/Source/Kernel/Devices/Display/vga-vesa.wtf.asm index c7b6bb5..4a6a1d6 100644 --- a/Source/Kernel/Devices/Display/vga-vesa.wtf.asm +++ b/Source/Kernel/Devices/Display/vga-vesa.wtf.asm @@ -9,3 +9,14 @@ setvgamode_start: int 3 setvgamode_end: db 0 + +[GLOBAL vesa_int] +vesa_int: + dw vesa_int_end - vesa_int_start +vesa_int_start: + int 60 + mov es, si + int 10h + int 3 +vesa_int_end: + db 0 -- cgit v1.2.3