+ if( gpVesaCurMode->flags & FLAG_LFB )\r
+ {\r
+ if( gbVesa_CursorVisible )\r
+ DrvUtil_Video_RemoveCursor(&gVesa_BufInfo);\r
+ else\r
+ DrvUtil_Video_DrawCursor(&gVesa_BufInfo,\r
+ giVesaCursorX*giVT_CharWidth,\r
+ giVesaCursorY*giVT_CharHeight\r
+ );\r
+ gbVesa_CursorVisible = !gbVesa_CursorVisible;\r
+ \r
+ #if BLINKING_CURSOR\r
+ Time_ScheduleTimer( gpVesaCursorTimer, VESA_CURSOR_PERIOD );\r
+ #endif\r
+ }\r
+}\r
+\r
+// ---\r
+// Helpers for text mode\r
+// ---\r
+\r
+/**\r
+ * \fn Uint8 VGA_int_GetColourNibble(Uint16 col)\r
+ * \brief Converts a 12-bit colour into a VGA 4-bit colour\r
+ */\r
+Uint8 VBE_int_GetColourNibble(Uint16 col)\r
+{\r
+ Uint8 ret = 0;\r
+ int bright = 0;\r
+ \r
+ col = col & 0xCCC;\r
+ col = ((col>>2)&3) | ((col>>4)&0xC) | ((col>>6)&0x30);\r
+ bright = ( (col & 2 ? 1 : 0) + (col & 8 ? 1 : 0) + (col & 32 ? 1 : 0) ) / 2;\r
+ \r
+ switch(col)\r
+ {\r
+ // Black\r
+ case 0x00: ret = 0x0; break;\r
+ // Dark Grey\r
+ case 0x15: ret = 0x8; break;\r
+ // Blues\r
+ case 0x01:\r
+ case 0x02: ret = 0x1; break;\r
+ case 0x03: ret = 0x9; break;\r
+ // Green\r
+ case 0x04:\r
+ case 0x08: ret = 0x2; break;\r
+ case 0x0C: ret = 0xA; break;\r
+ // Reds\r
+ case 0x10:\r
+ case 0x20: ret = 0x4; break;\r
+ case 0x30: ret = 0xC; break;\r
+ // Light Grey\r
+ case 0x2A: ret = 0x7; break;\r
+ // White\r
+ case 0x3F: ret = 0xF; break;\r
+ \r
+ default:\r
+ ret |= (col & 0x03 ? 1 : 0);\r
+ ret |= (col & 0x0C ? 2 : 0);\r
+ ret |= (col & 0x30 ? 4 : 0);\r
+ ret |= (bright ? 8 : 0);\r
+ break;\r
+ }\r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \brief Convers a character structure to a VGA character word\r
+ */\r
+Uint16 VBE_int_GetWord(const tVT_Char *Char)\r
+{\r
+ Uint16 ret;\r
+ Uint16 col;\r
+ \r
+ // Get Character\r
+ if(Char->Ch < 128)\r
+ ret = Char->Ch;\r
+ else {\r
+ switch(Char->Ch)\r
+ {\r
+ default: ret = 0; break;\r
+ }\r
+ }\r
+ \r
+ col = VBE_int_GetColourNibble(Char->BGCol);\r
+ ret |= col << 12;\r
+ \r
+ col = VBE_int_GetColourNibble(Char->FGCol);\r
+ ret |= col << 8;\r
+ \r
+ return ret;\r
+}\r
+\r
+void VBE_int_Text_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)\r
+{\r
+ const int charw = 8;\r
+ const int charh = 16;\r
+ const int tw = gpVesaCurMode->width / charw;\r
+ const int th = gpVesaCurMode->height / charh;\r
+\r
+ X /= charw;\r
+ W /= charw;\r
+ Y /= charh;\r
+ H /= charh;\r
+\r
+ tVT_Char ch;\r
+ ch.Ch = 0x20;\r
+ ch.BGCol = (Colour & 0x0F0000) >> (16-8);\r
+ ch.BGCol |= (Colour & 0x000F00) >> (8-4);\r
+ ch.BGCol |= (Colour & 0x00000F);\r
+ ch.FGCol = 0;\r
+ Uint16 word = VBE_int_GetWord(&ch);\r
+\r
+ Log("Fill (%i,%i) %ix%i with 0x%x", X, Y, W, H, word);\r
+\r
+ if( X >= tw || Y >= th ) return ;\r
+ if( X + W > tw ) W = tw - X;\r
+ if( Y + H > th ) H = th - Y;\r
+\r
+ Uint16 *buf = (Uint16*)gpVesa_Framebuffer + Y*tw + X;\r
+\r
+ \r
+ while( H -- ) {\r
+ for( int i = 0; i < W; i ++ )\r
+ *buf++ = word;\r
+ buf += tw - W;\r
+ }\r
+}\r
+\r
+void VBE_int_Text_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)\r
+{\r
+ const int charw = 8;\r
+ const int charh = 16;\r
+ const int tw = gpVesaCurMode->width / charw;\r
+ const int th = gpVesaCurMode->height / charh;\r
+\r
+ DstX /= charw;\r
+ SrcX /= charw;\r
+ W /= charw;\r
+\r
+ DstY /= charh;\r
+ SrcY /= charh;\r
+ H /= charh;\r
+\r
+// Log("(%i,%i) from (%i,%i) %ix%i", DstX, DstY, SrcX, SrcY, W, H);\r
+\r
+ if( SrcX >= tw || SrcY >= th ) return ;\r
+ if( SrcX + W > tw ) W = tw - SrcX;\r
+ if( SrcY + H > th ) H = th - SrcY;\r
+ if( DstX >= tw || DstY >= th ) return ;\r
+ if( DstX + W > tw ) W = tw - DstX;\r
+ if( DstY + H > th ) H = th - DstY;\r
+\r
+\r
+ Uint16 *src = (Uint16*)gpVesa_Framebuffer + SrcY*tw + SrcX;\r
+ Uint16 *dst = (Uint16*)gpVesa_Framebuffer + DstY*tw + DstX;\r
+\r
+ if( src > dst )\r
+ {\r
+ // Simple copy\r
+ while( H-- ) {\r
+ memcpy(dst, src, W*2);\r
+ dst += tw;\r
+ src += tw;\r
+ }\r
+ }\r