* AcessOS 1\r
* Video BIOS Extensions (Vesa) Driver\r
*/\r
-#define DEBUG 0\r
+#define DEBUG 1\r
#define VERSION 0x100\r
\r
#include <acess.h>\r
void Vesa_int_HideCursor(void);\r
void Vesa_int_ShowCursor(void);\r
void Vesa_FlipCursor(void *Arg);\r
+Uint16 VBE_int_GetWord(const tVT_Char *Char);\r
+void VBE_int_Text_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);\r
+void VBE_int_Text_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);\r
\r
// === GLOBALS ===\r
MODULE_DEFINE(0, VERSION, Vesa, Vesa_Install, NULL, "PCI", "VM8086", NULL);\r
int giVesaDriverId = -1;\r
// --- Video Modes ---\r
int giVesaCurrentMode = 0;\r
+tVesa_Mode gVesa_BootMode = {0x03, 80*8, 25*16, 80*8*2, 12, FLAG_POPULATED, 80*25*2, 0xB8000};\r
tVesa_Mode *gVesa_Modes;\r
tVesa_Mode *gpVesaCurMode;\r
int giVesaModeCount = 0;\r
int gbVesa_CursorVisible = 0;\r
// --- 2D Video Stream Handlers ---\r
tDrvUtil_Video_BufInfo gVesa_BufInfo;\r
+tDrvUtil_Video_2DHandlers gVBE_Text2DFunctions = {\r
+ NULL,\r
+ VBE_int_Text_2D_Fill,\r
+ VBE_int_Text_2D_Blit\r
+};\r
// --- Settings ---\r
+bool gbVesa_DisableBIOSCalls; // Disables calls to the BIOS\r
// int gbVesa_DisableFBCache; // Disables the main-memory framebuffer cache\r
\r
// === CODE ===\r
{\r
int rv;\r
\r
-// for( int i = 0; Arguments[i]; i ++ )\r
-// {\r
-// if( strcmp(Aguments[i], "nocache") == 0 )\r
-// gbVesa_DisableFBCache = 1;\r
-// }\r
- \r
- gpVesa_BiosState = VM8086_Init();\r
- \r
- if( (rv = VBE_int_GetModeList()) )\r
- return rv;\r
+ for( int i = 0; Arguments && Arguments[i]; i ++ )\r
+ {\r
+ if( strcmp(Arguments[i], "nobios") == 0 )\r
+ gbVesa_DisableBIOSCalls = 1;\r
+ //else if( strcmp(Arguments[i], "nocache") == 0 )\r
+ // gbVesa_DisableFBCache = 1;\r
+ else {\r
+ Log_Notice("VBE", "Unknown argument '%s'", Arguments[i]);\r
+ }\r
+ }\r
+\r
+ if( !gbVesa_DisableBIOSCalls )\r
+ {\r
+ gpVesa_BiosState = VM8086_Init();\r
+ \r
+ if( (rv = VBE_int_GetModeList()) )\r
+ return rv;\r
+ }\r
\r
#if BLINKING_CURSOR\r
// Create blink timer\r
tVesa_CallInfo *info;\r
tFarPtr infoPtr;\r
Uint16 *modes;\r
- int i;\r
\r
// Allocate Info Block\r
info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs);\r
// Call Interrupt\r
VM8086_Int(gpVesa_BiosState, 0x10);\r
if(gpVesa_BiosState->AX != 0x004F) {\r
- Log_Warning("VESA", "Vesa_Install - VESA/VBE Unsupported (AX = 0x%x)", gpVesa_BiosState->AX);\r
+ Log_Warning("VBE", "Vesa_Install - VESA/VBE Unsupported (AX = 0x%x)", gpVesa_BiosState->AX);\r
return MODULE_ERR_NOTNEEDED;\r
}\r
\r
// VM8086_Deallocate( gpVesa_BiosState, info );\r
\r
// Count Modes\r
- for( giVesaModeCount = 0; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ );\r
- giVesaModeCount ++; // First text mode\r
+ for( giVesaModeCount = 0; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ )\r
+ ;\r
gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) );\r
\r
Log_Debug("VBE", "%i Modes", giVesaModeCount);\r
\r
// Insert Text Mode\r
- gVesa_Modes[0].width = 80;\r
- gVesa_Modes[0].height = 25;\r
- gVesa_Modes[0].bpp = 12;\r
- gVesa_Modes[0].code = 0x3;\r
- gVesa_Modes[0].flags = 1;\r
- gVesa_Modes[0].fbSize = 80*25*2;\r
- gVesa_Modes[0].framebuffer = 0xB8000;\r
- \r
- for( i = 1; i < giVesaModeCount; i++ )\r
+ \r
+ for( int i = 0; i < giVesaModeCount; i++ )\r
{\r
- gVesa_Modes[i].code = modes[i-1];\r
+ gVesa_Modes[i].code = modes[i];\r
}\r
\r
return 0;\r
}\r
\r
-void VBE_int_FillMode_Int(int Index, tVesa_CallModeInfo *vbeinfo, tFarPtr *BufPtr)\r
+int VBE_int_GetModeInfo(Uint16 Code, tFarPtr *BufPtr)\r
{\r
- tVesa_Mode *mode = &gVesa_Modes[Index];\r
-\r
// Get Mode info\r
gpVesa_BiosState->AX = 0x4F01;\r
- gpVesa_BiosState->CX = mode->code;\r
+ gpVesa_BiosState->CX = Code;\r
gpVesa_BiosState->ES = BufPtr->seg;\r
gpVesa_BiosState->DI = BufPtr->ofs;\r
VM8086_Int(gpVesa_BiosState, 0x10);\r
\r
if( gpVesa_BiosState->AX != 0x004F ) {\r
- Log_Error("VESA", "Getting info on mode 0x%x failed (AX=0x%x)",\r
- mode->code, gpVesa_BiosState->AX);\r
- return ;\r
+ Log_Error("VBE", "Getting info on mode 0x%x failed (AX=0x%x)",\r
+ Code, gpVesa_BiosState->AX);\r
+ return 1;\r
}\r
+ return 0;\r
+}\r
\r
- #if 0\r
+\r
+void VBE_int_FillMode_Int(tVesa_Mode *Mode, const tVesa_CallModeInfo *vbeinfo)\r
+{\r
+ #if 1\r
#define S_LOG(s, fld, fmt) LOG(" ."#fld" = "fmt, (s).fld)\r
- LOG("vbeinfo[0x%x] = {", mode->code);\r
+ LOG("vbeinfo[0x%x] = {", Mode->code);\r
S_LOG(*vbeinfo, attributes, "0x%02x");\r
S_LOG(*vbeinfo, winA, "0x%02x");\r
S_LOG(*vbeinfo, winB, "0x%02x");\r
LOG("}");\r
#endif\r
\r
- mode->flags = FLAG_POPULATED;\r
- if( !(vbeinfo->attributes & 1) ) {\r
+ Mode->flags = FLAG_POPULATED;\r
+ if( !(vbeinfo->attributes & 1) )\r
+ {\r
#if DEBUG\r
- Log_Log("VESA", "0x%x - not supported", mode->code);\r
+ Log_Log("VBE", "0x%x - not supported", Mode->code);\r
#endif\r
- mode->width = 0;\r
- mode->height = 0;\r
- mode->bpp = 0;\r
+ Mode->width = 0;\r
+ Mode->height = 0;\r
+ Mode->bpp = 0;\r
return ;\r
}\r
\r
// Parse Info\r
- mode->flags |= FLAG_VALID;\r
- if ( (vbeinfo->attributes & 0x90) == 0x90 )\r
+ Mode->flags |= FLAG_VALID;\r
+ switch( vbeinfo->attributes & 0x90 ) // LFB, Graphics\r
{\r
- mode->flags |= FLAG_LFB;\r
- mode->framebuffer = vbeinfo->physbase;\r
- mode->fbSize = vbeinfo->Yres*vbeinfo->pitch;\r
- } else {\r
- mode->framebuffer = 0;\r
- mode->fbSize = 0;\r
+ case 0x00: // Banked, Text\r
+ case 0x10: // Banked, Graphics\r
+ case 0x80: // Linear, Text (?)\r
+ Mode->width = 0;\r
+ Mode->height = 0;\r
+ Mode->bpp = 0;\r
+ return ;\r
+ case 0x90:\r
+ Mode->flags |= FLAG_LFB;\r
+ Mode->framebuffer = vbeinfo->physbase;\r
+ Mode->fbSize = vbeinfo->Yres*vbeinfo->pitch;\r
+ break;\r
}\r
\r
- mode->pitch = vbeinfo->pitch;\r
- mode->width = vbeinfo->Xres;\r
- mode->height = vbeinfo->Yres;\r
- mode->bpp = vbeinfo->bpp;\r
+ Mode->pitch = vbeinfo->pitch;\r
+ Mode->width = vbeinfo->Xres;\r
+ Mode->height = vbeinfo->Yres;\r
+ Mode->bpp = vbeinfo->bpp;\r
\r
#if DEBUG\r
- Log_Log("VESA", "#%i 0x%x - %ix%ix%i (%x)",\r
- Index, mode->code, mode->width, mode->height, mode->bpp, mode->flags);\r
+ Log_Log("VBE", "0x%x - %ix%ix%i (%x)",\r
+ Mode->code, Mode->width, Mode->height, Mode->bpp, Mode->flags);\r
#endif\r
\r
} \r
\r
+void VBE_int_SetBootMode(Uint16 ModeID, const void *ModeInfo)\r
+{\r
+ gVesa_BootMode.code = ModeID;\r
+ VBE_int_FillMode_Int(&gVesa_BootMode, ModeInfo);\r
+}\r
+\r
void Vesa_int_FillModeList(void)\r
{\r
- if( !gbVesaModesChecked )\r
+ if( !gbVesaModesChecked && !gbVesa_DisableBIOSCalls )\r
{\r
- int i;\r
tVesa_CallModeInfo *modeinfo;\r
tFarPtr modeinfoPtr;\r
\r
modeinfo = VM8086_Allocate(gpVesa_BiosState, 256, &modeinfoPtr.seg, &modeinfoPtr.ofs);\r
- for( i = 1; i < giVesaModeCount; i ++ )\r
+ for( int i = 0; i < giVesaModeCount; i ++ )\r
{\r
- VBE_int_FillMode_Int(i, modeinfo, &modeinfoPtr);\r
+ if( VBE_int_GetModeInfo(gVesa_Modes[i].code, &modeinfoPtr) == 0 )\r
+ {\r
+ VBE_int_FillMode_Int( &gVesa_Modes[i], modeinfo );\r
+ }\r
} \r
// VM8086_Deallocate( gpVesa_BiosState, modeinfo );\r
\r
*/\r
size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)\r
{\r
- if( gVesa_Modes[giVesaCurrentMode].framebuffer == 0 ) {\r
- Log_Warning("VESA", "Vesa_Write - Non-LFB Modes not yet supported.");\r
+ // Framebuffer modes - just pass on\r
+ if( gpVesaCurMode->flags & FLAG_LFB )\r
+ return DrvUtil_Video_WriteLFB(&gVesa_BufInfo, Offset, Length, Buffer);\r
+ \r
+ // EGA text mode translation\r
+ switch( gVesa_BufInfo.BufferFormat )\r
+ {\r
+ case VIDEO_BUFFMT_TEXT: {\r
+ int num = Length / sizeof(tVT_Char);\r
+ int ofs = Offset / sizeof(tVT_Char);\r
+ int i = 0;\r
+ const tVT_Char *chars = Buffer;\r
+ Uint16 word;\r
+ \r
+ for( ; num--; i ++, ofs ++)\r
+ {\r
+ word = VBE_int_GetWord( &chars[i] );\r
+ ((Uint16*)gVesa_BufInfo.Framebuffer)[ ofs ] = word;\r
+ }\r
+ \r
+ return Length; }\r
+ case VIDEO_BUFFMT_2DSTREAM:\r
+ return DrvUtil_Video_2DStream(NULL, Buffer, Length,\r
+ &gVBE_Text2DFunctions, sizeof(gVBE_Text2DFunctions));\r
+ default:\r
+ Log_Warning("VBE", "TODO: Alternate modes in EGA text mode");\r
return 0;\r
}\r
\r
- return DrvUtil_Video_WriteLFB(&gVesa_BufInfo, Offset, Length, Buffer);\r
}\r
\r
const char *csaVESA_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};\r
int ret;\r
switch(ID)\r
{\r
- BASE_IOCTLS(DRV_TYPE_VIDEO, "VESA", VERSION, csaVESA_IOCtls);\r
+ BASE_IOCTLS(DRV_TYPE_VIDEO, "VBE", VERSION, csaVESA_IOCtls);\r
\r
case VIDEO_IOCTL_GETSETMODE:\r
if( !Data ) return giVesaCurrentMode;\r
* \brief Updates the video mode\r
*/\r
int Vesa_Int_SetMode(int mode)\r
-{ \r
- // Sanity Check values\r
- if(mode < 0 || mode > giVesaModeCount) return -1;\r
-\r
+{\r
+ tVesa_Mode *modeptr;\r
// Check for fast return\r
if(mode == giVesaCurrentMode) return 1;\r
\r
+ // Special case: Boot mode\r
+ if( mode == -1 )\r
+ modeptr = &gVesa_BootMode;\r
+ else if( 0 <= mode && mode < giVesaModeCount )\r
+ modeptr = &gVesa_Modes[mode];\r
+ else\r
+ return -1;\r
+ \r
Vesa_int_FillModeList();\r
\r
#if BLINKING_CURSOR\r
\r
Mutex_Acquire( &glVesa_Lock );\r
\r
- gpVesa_BiosState->AX = 0x4F02;\r
- gpVesa_BiosState->BX = gVesa_Modes[mode].code;\r
- if(gVesa_Modes[mode].flags & FLAG_LFB) {\r
- gpVesa_BiosState->BX |= 1 << 14; // Use LFB\r
+ if( gbVesa_DisableBIOSCalls )\r
+ {\r
+ ASSERT(mode == -1);\r
}\r
- LOG("In : AX=%04x/BX=%04x",\r
- gpVesa_BiosState->AX, gpVesa_BiosState->BX);\r
- \r
- // Set Mode\r
- VM8086_Int(gpVesa_BiosState, 0x10);\r
+ else\r
+ {\r
+ gpVesa_BiosState->AX = 0x4F02;\r
+ gpVesa_BiosState->BX = modeptr->code;\r
+ if(modeptr->flags & FLAG_LFB) {\r
+ gpVesa_BiosState->BX |= 1 << 14; // Use LFB\r
+ }\r
+ LOG("In : AX=%04x/BX=%04x", gpVesa_BiosState->AX, gpVesa_BiosState->BX);\r
+ \r
+ // Set Mode\r
+ VM8086_Int(gpVesa_BiosState, 0x10);\r
\r
- LOG("Out: AX = %04x", gpVesa_BiosState->AX);\r
+ LOG("Out: AX = %04x", gpVesa_BiosState->AX);\r
+ }\r
\r
// Map Framebuffer\r
- if( (tVAddr)gpVesa_Framebuffer != VESA_DEFAULT_FRAMEBUFFER )\r
- MM_UnmapHWPages((tVAddr)gpVesa_Framebuffer, giVesaPageCount);\r
- giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12;\r
- gpVesa_Framebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount);\r
- \r
- Log_Log("VESA", "Setting mode to %i 0x%x (%ix%i %ibpp) %p[0x%x] maps %P",\r
- mode, gVesa_Modes[mode].code,\r
- gVesa_Modes[mode].width, gVesa_Modes[mode].height,\r
- gVesa_Modes[mode].bpp,\r
- gpVesa_Framebuffer, giVesaPageCount << 12, gVesa_Modes[mode].framebuffer\r
+ if( gpVesaCurMode )\r
+ {\r
+ if( gpVesaCurMode->framebuffer < 1024*1024 )\r
+ ;\r
+ else\r
+ MM_UnmapHWPages((tVAddr)gpVesa_Framebuffer, giVesaPageCount);\r
+ }\r
+ giVesaPageCount = (modeptr->fbSize + 0xFFF) >> 12;\r
+ if( modeptr->framebuffer < 1024*1024 )\r
+ gpVesa_Framebuffer = (void*)(KERNEL_BASE|modeptr->framebuffer);\r
+ else\r
+ gpVesa_Framebuffer = (void*)MM_MapHWPages(modeptr->framebuffer, giVesaPageCount);\r
+ \r
+ Log_Log("VBE", "Setting mode to %i 0x%x (%ix%i %ibpp) %p[0x%x] maps %P",\r
+ mode, modeptr->code,\r
+ modeptr->width, modeptr->height,\r
+ modeptr->bpp,\r
+ gpVesa_Framebuffer, giVesaPageCount << 12, modeptr->framebuffer\r
);\r
\r
// Record Mode Set\r
giVesaCurrentMode = mode;\r
- gpVesaCurMode = &gVesa_Modes[giVesaCurrentMode];\r
+ gpVesaCurMode = modeptr;\r
\r
Mutex_Release( &glVesa_Lock );\r
\r
+ // TODO: Disableable backbuffer\r
gVesa_BufInfo.BackBuffer = realloc(gVesa_BufInfo.BackBuffer,\r
- gVesa_Modes[mode].height * gVesa_Modes[mode].pitch);\r
+ modeptr->height * modeptr->pitch);\r
gVesa_BufInfo.Framebuffer = gpVesa_Framebuffer;\r
- gVesa_BufInfo.Pitch = gVesa_Modes[mode].pitch;\r
- gVesa_BufInfo.Width = gVesa_Modes[mode].width;\r
- gVesa_BufInfo.Height = gVesa_Modes[mode].height;\r
- gVesa_BufInfo.Depth = gVesa_Modes[mode].bpp; \r
+ gVesa_BufInfo.Pitch = modeptr->pitch;\r
+ gVesa_BufInfo.Width = modeptr->width;\r
+ gVesa_BufInfo.Height = modeptr->height;\r
+ gVesa_BufInfo.Depth = modeptr->bpp; \r
\r
return 1;\r
}\r
\r
-int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data)\r
+int VBE_int_MatchModes(tVideo_IOCtl_Mode *ReqMode, tVesa_Mode *ThisMode)\r
{\r
- int i;\r
- int best = -1, tmp;\r
- unsigned int factor, bestFactor = -1;\r
- \r
- ENTER("idata->width idata->height idata->bpp", data->width, data->height, data->bpp);\r
-\r
- Vesa_int_FillModeList();\r
- \r
- for(i = 0; i < giVesaModeCount; i ++)\r
+ LOG("Matching %ix%i %ibpp", ThisMode->width, ThisMode->height, ThisMode->bpp);\r
+ if(ThisMode->width == ReqMode->width && ThisMode->height == ReqMode->height)\r
{\r
- LOG("Mode %i (%ix%ix%i)", i, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
- \r
- if(gVesa_Modes[i].width == data->width && gVesa_Modes[i].height == data->height)\r
+ //if( (data->bpp == 32 || data->bpp == 24)\r
+ // && (gVesa_Modes[i].bpp == 32 || gVesa_Modes[i].bpp == 24) )\r
+ if( ReqMode->bpp == ThisMode->bpp )\r
{\r
- //if( (data->bpp == 32 || data->bpp == 24)\r
- // && (gVesa_Modes[i].bpp == 32 || gVesa_Modes[i].bpp == 24) )\r
- if( data->bpp == gVesa_Modes[i].bpp )\r
- {\r
- LOG("Perfect!");\r
- best = i;\r
- break;\r
- }\r
+ LOG("Perfect!");\r
+ return -1;\r
}\r
+ }\r
+ \r
+ int tmp = ThisMode->width * ThisMode->height - ReqMode->width * ReqMode->height;\r
+ tmp = tmp < 0 ? -tmp : tmp;\r
+ unsigned int factor = (Uint64)tmp * 1000 / (ReqMode->width * ReqMode->height);\r
+ if( ThisMode->bpp > ReqMode->bpp )\r
+ factor += ThisMode->bpp - ReqMode->bpp;\r
+ else\r
+ factor += ReqMode->bpp - ThisMode->bpp;\r
+\r
+ if( ReqMode->bpp == ThisMode->bpp )\r
+ factor /= 2;\r
+ else\r
+ {\r
+ if( ReqMode->bpp == 8 && ThisMode->bpp != 8 ) factor *= 4;\r
+ if( ReqMode->bpp == 16 && ThisMode->bpp != 16 ) factor *= 4;\r
\r
- tmp = gVesa_Modes[i].width * gVesa_Modes[i].height;\r
- tmp -= data->width * data->height;\r
- tmp = tmp < 0 ? -tmp : tmp;\r
- factor = (Uint64)tmp * 1000 / (data->width * data->height);\r
- \r
- if( data->bpp == 8 && gVesa_Modes[i].bpp != 8 ) continue;\r
- if( data->bpp == 16 && gVesa_Modes[i].bpp != 16 ) continue;\r
- \r
- if( (data->bpp == 32 || data->bpp == 24)\r
- && (gVesa_Modes[i].bpp == 32 || gVesa_Modes[i].bpp == 24) )\r
+ if( (ReqMode->bpp == 32 || ReqMode->bpp == 24)\r
+ && (ThisMode->bpp == 32 || ThisMode->bpp == 24) )\r
{\r
- if( data->bpp == gVesa_Modes[i].bpp )\r
- factor /= 2;\r
+ // NC\r
}\r
else {\r
- if( data->bpp != gVesa_Modes[i].bpp )\r
- continue ;\r
+ if( ReqMode->bpp < ThisMode->bpp )\r
+ factor *= ThisMode->bpp / ReqMode->bpp + 1;\r
+ else\r
+ factor *= ReqMode->bpp / ThisMode->bpp + 1;\r
}\r
+ }\r
+ \r
+ return factor;\r
+}\r
+\r
+int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data)\r
+{\r
+ int best = -1;\r
+ \r
+ ENTER("idata->width idata->height idata->bpp", data->width, data->height, data->bpp);\r
+\r
+ Vesa_int_FillModeList();\r
+\r
+ int bestFactor = VBE_int_MatchModes(data, &gVesa_BootMode); \r
+ tVesa_Mode *bestPtr = &gVesa_BootMode;\r
+\r
+ for(int i = 0; bestFactor > 0 && i < giVesaModeCount; i ++)\r
+ {\r
+ LOG("Mode %i (%ix%ix%i)", i, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
+ \r
+ int factor = VBE_int_MatchModes(data, &gVesa_Modes[i]);\r
\r
- LOG("factor = %i", factor);\r
+ LOG("factor = %i, bestFactor = %i", factor, bestFactor);\r
\r
if(factor < bestFactor)\r
{\r
bestFactor = factor;\r
best = i;\r
+ bestPtr = &gVesa_Modes[i];\r
}\r
}\r
data->id = best;\r
- data->width = gVesa_Modes[best].width;\r
- data->height = gVesa_Modes[best].height;\r
- data->bpp = gVesa_Modes[best].bpp;\r
+ data->width = bestPtr->width;\r
+ data->height = bestPtr->height;\r
+ data->bpp = bestPtr->bpp;\r
LEAVE('i', best);\r
return best;\r
}\r
\r
int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data)\r
{\r
- if(data->id < 0 || data->id > giVesaModeCount) return -1;\r
+ tVesa_Mode *modeptr;\r
+ if( data->id == -1 )\r
+ modeptr = &gVesa_BootMode;\r
+ else if( 0 <= data->id && data->id < giVesaModeCount)\r
+ modeptr = &gVesa_Modes[data->id];\r
+ else\r
+ return 0;\r
\r
Vesa_int_FillModeList();\r
\r
- data->width = gVesa_Modes[data->id].width;\r
- data->height = gVesa_Modes[data->id].height;\r
- data->bpp = gVesa_Modes[data->id].bpp;\r
+ data->width = modeptr->width;\r
+ data->height = modeptr->height;\r
+ data->bpp = modeptr->bpp;\r
return 1;\r
}\r
\r
void Vesa_int_HideCursor(void)\r
{\r
- DrvUtil_Video_RemoveCursor( &gVesa_BufInfo );\r
- #if BLINKING_CURSOR\r
- if(gpVesaCursorTimer) {\r
- Time_RemoveTimer(gpVesaCursorTimer);\r
+ if( gpVesaCurMode->flags & FLAG_LFB )\r
+ {\r
+ DrvUtil_Video_RemoveCursor( &gVesa_BufInfo );\r
+ #if BLINKING_CURSOR\r
+ if(gpVesaCursorTimer) {\r
+ Time_RemoveTimer(gpVesaCursorTimer);\r
+ }\r
+ #endif\r
}\r
- #endif\r
}\r
\r
void Vesa_int_ShowCursor(void)\r
{\r
- gbVesa_CursorVisible = (giVesaCursorX >= 0);\r
- if(gVesa_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+ if( gpVesaCurMode->flags & FLAG_LFB )\r
{\r
- DrvUtil_Video_DrawCursor(\r
- &gVesa_BufInfo,\r
- giVesaCursorX*giVT_CharWidth,\r
- giVesaCursorY*giVT_CharHeight\r
- );\r
- #if BLINKING_CURSOR\r
- Time_ScheduleTimer( gpVesaCursorTimer, VESA_CURSOR_PERIOD );\r
- #endif\r
+ gbVesa_CursorVisible = (giVesaCursorX >= 0);\r
+ if(gVesa_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+ {\r
+ DrvUtil_Video_DrawCursor(\r
+ &gVesa_BufInfo,\r
+ giVesaCursorX*giVT_CharWidth,\r
+ giVesaCursorY*giVT_CharHeight\r
+ );\r
+ #if BLINKING_CURSOR\r
+ Time_ScheduleTimer( gpVesaCursorTimer, VESA_CURSOR_PERIOD );\r
+ #endif\r
+ }\r
+ else\r
+ DrvUtil_Video_DrawCursor(\r
+ &gVesa_BufInfo,\r
+ giVesaCursorX,\r
+ giVesaCursorY\r
+ );\r
}\r
- else\r
- DrvUtil_Video_DrawCursor(\r
- &gVesa_BufInfo,\r
- giVesaCursorX,\r
- giVesaCursorY\r
- );\r
}\r
\r
/**\r
if( gVesa_BufInfo.BufferFormat != VIDEO_BUFFMT_TEXT )\r
return ;\r
\r
- if( gbVesa_CursorVisible )\r
- DrvUtil_Video_RemoveCursor(&gVesa_BufInfo);\r
+ 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
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
+ dst += H*tw;\r
+ src += H*tw;\r
+ while( H -- ) {\r
+ dst -= tw-W;\r
+ src -= tw-W;\r
+ for( int i = W; i --; ) *--dst = *--src;\r
+ }\r
+ }\r
}\r
\r