#include <kernel/kernel.h> #include <kernel/driver.h> #include <kernel/proc.h> #include <kernel/thread.h> #include <kernel/sys.h> #include <string.h> #include <stdio.h> #include "surface.h" class VgaGraphics : public Surface { private: bool fLocked; int m_palette_size; colour_t m_palette[256]; public: VgaGraphics(int nMode); virtual ~VgaGraphics(); IMPLEMENT_IUNKNOWN(VgaGraphics); STDMETHOD(SetPalette)(int nIndex, int red, int green, int blue); STDMETHOD(Lock)(surface_t* pDesc); STDMETHOD(Unlock)(); STDMETHOD(GetSurfaceDesc)(surface_t* pDesc); STDMETHOD_(pixel_t, ColourMatch)(colour_t clr); STDMETHOD(SetPixel)(int x, int y, pixel_t pix); STDMETHOD_(pixel_t, GetPixel)(int x, int y); STDMETHOD(Blt)(ISurface* pSrc, int x, int y, int nWidth, int nHeight, int nSrcX, int nSrcY, pixel_t pixTrans); STDMETHOD(FillRect)(const rectangle_t* rect, pixel_t pix); STDMETHOD(AttachProcess)(); }; ISurface* CreateGraphics(int nMode) { return new VgaGraphics(nMode); } byte* vmem = (byte*) 0xa0000; #define CRT_C 24 /* 24 CRT Controller Registers */ #define ATT_C 21 /* 21 Attribute Controller Registers */ #define GRA_C 9 /* 9 Graphics Controller Registers */ #define SEQ_C 5 /* 5 Sequencer Registers */ #define MIS_C 1 /* 1 Misc Output Register */ #define CRT_I 0x3D4 /* CRT Controller Index (mono: 0x3B4) */ #define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ #define GRA_I 0x3CE /* Graphics Controller Index */ #define SEQ_I 0x3C4 /* Sequencer Index */ #define PEL_IW 0x3C8 /* PEL Write Index */ #define CRT_D 0x3D5 /* CRT Controller Data Register (mono: 0x3B5) */ #define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ #define GRA_D 0x3CF /* Graphics Controller Data Register */ #define SEQ_D 0x3C5 /* Sequencer Data Register */ #define MIS_R 0x3CC /* Misc Output Read Register */ #define MIS_W 0x3C2 /* Misc Output Write Register */ #define IS1_R 0x3DA /* Input Status Register 1 (mono: 0x3BA) */ #define PEL_D 0x3C9 /* PEL Data Register */ #define PaletteMask 0x3C6 // bit mask register #define PaletteRegisterRead 0x3C7 // read index #define PaletteRegisterWrite 0x3C8 // write index #define PaletteData 0x3C9 // send/receive data here struct vgaregs_t { byte crt[CRT_C]; byte att[ATT_C]; byte gra[GRA_C]; byte seq[SEQ_C]; byte mis[MIS_C]; }; static const vgaregs_t mode12 = { { 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00, 0x00,0x00,0x00,0x59,0xEA,0x8C,0xDF,0x28,0x0F,0xE7,0x04,0xC3 }, // CRTC { 0x00,0x08,0x3F,0x3F,0x18,0x18,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 0x3F,0x3F,0x3F,0x3F,0x01,0x00,0x0F,0x00,0x00 }, // ATTC { 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,0xFF }, // Graphics { 0x03,0x01,0x0F,0x00,0x06 }, // Sequencer { 0xE3 } // Misc }; // BIOS mode 13 - 320x200x8 static const vgaregs_t mode13 = { { 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x41,0x00,0x00, 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x28,0x40,0x96,0xB9,0xA3 }, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F,0x41,0x00,0x0F,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF }, { 0x03,0x01,0x0F,0x00,0x0E }, { 0x63 } }; // VESA mode 100 static const vgaregs_t mode100 = { { 0x63,0x4F,0x50,0x82,0x53,0xCC,0xC0,0x1F,0x00,0x40,0x00,0x00, 0x00,0x00,0x00,0x00,0x9C,0x82,0x8F,0x50,0x00,0xE7,0x04,0xE3 }, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF }, { 0x03,0x01,0x0F,0x00,0x0A }, { 0x6B } }; #include "palette.h" // Saved text mode registers static vgaregs_t text; void WriteMode(const vgaregs_t* pMode) { int i; for (i = 0; i < CRT_C; i++) { out(CRT_I, i); out(CRT_D, pMode->crt[i]); } in(IS1_R); for (i = 0; i < ATT_C; i++) { in(ATT_IW); out(ATT_IW, i); out(ATT_IW, pMode->att[i]); } out(ATT_IW, 0x20); for (i = 0; i < GRA_C; i++) { out(GRA_I, i); out(GRA_D, pMode->gra[i]); } for (i = 0; i < SEQ_C; i++) { out(SEQ_I, i); out(SEQ_D, pMode->seq[i]); } out(MIS_W, pMode->mis[0]); } void ReadMode(vgaregs_t* pMode) { int i; for (i = 0; i < CRT_C; i++) { out(CRT_I, i); pMode->crt[i] = in(CRT_D); } for (i = 0; i < ATT_C; i++) { in(IS1_R); out(ATT_IW, i); pMode->att[i] = in(ATT_R); } for (i = 0; i < GRA_C; i++) { out(GRA_I, i); pMode->gra[i] = in(GRA_D); } for (i = 0; i < SEQ_C; i++) { out(SEQ_I, i); pMode->seq[i] = in(SEQ_D); } pMode->mis[0] = in(MIS_R); } //extern "C" void s3triofb_init_of(struct device_node *dp); //extern "C" void trio_init(); #if 0 void thrWaitHandle(dword hnd) { __asm { mov eax, 101h mov ebx, hnd int 30h } } void thrYield() { __asm { mov eax, 2 int 30h } } #pragma warning(disable:4035) dword thrCreate86(const byte* code, size_t code_size) { __asm { xor eax, eax mov ebx, code mov ecx, code_size int 30h } } #pragma warning(default:4035) #endif byte code86[] = { 0x8C, 0xC8, // MOV AX,CS 0x8E, 0xD8, // MOV DS,AX 0x8E, 0xC0, // MOV ES,AX 0x8E, 0xD0, // MOV SS,AX 0xB8, 0x13, 0x00, // MOV AX,13h 0xCD, 0x10, // INT 10 // 0xEB, 0xFE, // JMP $ 0xB8, 0x06, 0x01, // MOV AX,0106h 0xCD, 0x30, // INT 30 }; /*byte code86[] = { 0xeb, 0xfe };*/ // // VgaGraphics::VgaGraphics // // Initializes the VGA card to the given mode (only 0x12 & 0x13 supported atm). // VgaGraphics::VgaGraphics(int nMode) { int i; thread_t* thr; code86[9] = nMode; thr = thrCreate86(procCurrent(), code86, sizeof(code86), sysV86Fault); thrWaitHandle(thrCurrent(), thr); fWidth = 320; fHeight = 200; fBpp = 8; m_palette_size = 256; for (i = 0; i < m_palette_size; i++) SetPalette(i, palette[i * 3], palette[i * 3 + 1], palette[i * 3 + 2]); m_refs = 0; fLocked = false; fDrawMode = modeCopy; //s3triofb_init_of(NULL); //trio_init(); } VgaGraphics::~VgaGraphics() { WriteMode(&text); } HRESULT VgaGraphics::AttachProcess() { return S_OK; } // // SetPalette // // Sets the palette index color to the colour (red, green, blue). // red, green & blue are 8-bit integers. // HRESULT VgaGraphics::SetPalette(int color, int red, int green, int blue) { out(PaletteMask, 0xff); out(PaletteRegisterWrite, color); out(PaletteData, red / 4); out(PaletteData, green / 4); out(PaletteData, blue / 4); m_palette[color] = RGB(red, green, blue); return S_OK; } HRESULT VgaGraphics::Lock(surface_t* pDesc) { //HRESULT hr; if (fLocked) return E_FAIL; //if (FAILED(hr = VerifyArea(pDesc, sizeof(SurfaceDesc), PRIV_USER | PRIV_WR))) //return hr; GetSurfaceDesc(pDesc); pDesc->pMemory = vmem; return S_OK; } HRESULT VgaGraphics::Unlock() { fLocked = false; return S_OK; } HRESULT VgaGraphics::GetSurfaceDesc(surface_t* pDesc) { pDesc->nWidth = fWidth; pDesc->nHeight = fHeight; pDesc->nBpp = fBpp; pDesc->nPitch = fWidth; pDesc->pMemory = NULL; return S_OK; } pixel_t VgaGraphics::ColourMatch(colour_t clr) { int i; for (i = 0; i < m_palette_size; i++) if (m_palette[i] == clr) return (byte) i; return 255; } HRESULT VgaGraphics::SetPixel(int x, int y, pixel_t pix) { if (x < fWidth && y < fHeight) { switch (fDrawMode) { case modeCopy: vmem[x + y * fWidth] = (byte) pix; break; case modeXor: vmem[x + y * fWidth] ^= (byte) pix; break; case modeNot: vmem[x + y * fWidth] = ~vmem[x + y * fWidth]; break; } } return S_OK; } pixel_t VgaGraphics::GetPixel(int x, int y) { if (x < fWidth && y < fHeight) return vmem[x + y * fWidth]; else return 0; } HRESULT VgaGraphics::Blt(ISurface* pSrc, int x, int y, int nWidth, int nHeight, int nSrcX, int nSrcY, pixel_t pixTrans) { surface_t srcDesc; HRESULT hr; int i, j; pixel_t b; pSrc->GetSurfaceDesc(&srcDesc); if (srcDesc.nBpp == fBpp) { if (x < 0) x = 0; if (y < 0) y = 0; if (x + nWidth >= fWidth) nWidth = fWidth - x; if (y + nHeight >= fHeight) nHeight = fHeight - y; /*if (nSrcX < 0) nSrcX = 0; if (nSrcY < 0) nSrcY = 0; if (nSrcX + nWidth >= srcDesc.nWidth) nWidth = srcDesc.nWidth - nSrcX; if (nSrcY + nHeight >= srcDesc.nHeight) nHeight = srcDesc.nHeight - y;*/ if (FAILED(hr = pSrc->Lock(&srcDesc))) return hr; if (pixTrans == (pixel_t) -1) for (i = 0; i < nHeight; i++) memcpy(vmem + x + (y + i) * fWidth, (byte*) srcDesc.pMemory + nSrcX + (nSrcY + i) * srcDesc.nWidth, nWidth); else { for (i = 0; i < nHeight; i++) for (j = 0; j < nWidth; j++) { b = ((byte*) srcDesc.pMemory)[nSrcX + j + (nSrcY + i) * srcDesc.nWidth]; if (b != pixTrans) vmem[x + j + (y + i) * fWidth] = b; } } pSrc->Unlock(); return S_OK; } else return Surface::Blt(pSrc, x, y, nWidth, nHeight, nSrcX, nSrcY, pixTrans); } HRESULT VgaGraphics::FillRect(const rectangle_t* rect, pixel_t pix) { int x, y; surface_t desc; if (FAILED(Lock(&desc))) return E_FAIL; /*__asm { mov eax, rect mov ebx, [eax+4] mov ecx, [eax+8] mov edx, [eax+12] mov eax, [eax] mov esi, desc.pMemory cli hlt }*/ for (y = rect->top; y < rect->bottom; y++) i386_lmemset((addr_t) desc.pMemory + y * desc.nPitch + rect->left, pix, min(rect->Width(), fWidth - rect->left)); /*for (y = rect->top; y < rect->bottom; y++) for (x = rect->left; y < rect->right; x++) ((byte*) desc.pMemory) [x + y * fWidth] = pix;*/ Unlock(); return S_OK; }