From: John Hodge Date: Sat, 14 Sep 2013 01:47:19 +0000 (+0800) Subject: Kernel/VTerm - Switched to using userland VT100 code X-Git-Tag: rel0.15~218 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=45ea05112879353e05848dde97fff36615721d6b;p=tpg%2Facess2.git Kernel/VTerm - Switched to using userland VT100 code --- diff --git a/KernelLand/Kernel/drv/vterm.h b/KernelLand/Kernel/drv/vterm.h index 5acb4640..85264263 100644 --- a/KernelLand/Kernel/drv/vterm.h +++ b/KernelLand/Kernel/drv/vterm.h @@ -119,6 +119,7 @@ extern void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int arg extern int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes); // --- Terminal Buffer --- extern void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count); +extern void VT_int_PutRawString(tVTerm *Term, const Uint8 *String, size_t Bytes); extern void VT_int_PutChar(tVTerm *Term, Uint32 Ch); extern void VT_int_ScrollText(tVTerm *Term, int Count); extern void VT_int_ClearLine(tVTerm *Term, int Num); diff --git a/KernelLand/Kernel/drv/vterm_font.c b/KernelLand/Kernel/drv/vterm_font.c index f084c5b3..cb2702d9 100644 --- a/KernelLand/Kernel/drv/vterm_font.c +++ b/KernelLand/Kernel/drv/vterm_font.c @@ -132,6 +132,18 @@ void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Depth, int Pitch, Uint32 } } +Uint16 VT_Colour24to12(Uint32 Col24) +{ + Uint16 ret = 0; + + for( int i = 0; i < 3; i ++ ) + { + Uint32 comp = (Col24 >> (i*8)) & 0xFF; + ret |= ((comp * 15) / 255) << (i*4); + } + return ret; +} + /** * \fn Uint32 VT_Colour12to24(Uint16 Col12) * \brief Converts a 12-bit colour into 24 bits diff --git a/KernelLand/Kernel/drv/vterm_termbuf.c b/KernelLand/Kernel/drv/vterm_termbuf.c index ee543858..e3ddff1f 100644 --- a/KernelLand/Kernel/drv/vterm_termbuf.c +++ b/KernelLand/Kernel/drv/vterm_termbuf.c @@ -5,8 +5,11 @@ * drv/vterm_termbuf.c * - Virtual Terminal - Terminal buffer manipulation */ +#define DEBUG 1 #include "vterm.h" +extern int Term_HandleVT100(tVTerm *Term, int Len, const char *Buf); + // === CODE === /** @@ -15,30 +18,32 @@ */ void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count) { - int i; - // Iterate - for( i = 0; i < Count; i++ ) + for( int ofs = 0; ofs < Count; ) { - // Handle escape sequences - int ret = VT_int_ParseEscape(Term, (const char*)&Buffer[i], Count-i); - if( ret > 0 ) - { - i += ret-1; - continue; + int esc_len = Term_HandleVT100(Term, Count - ofs, (const void*)(Buffer + ofs)); + if( esc_len < 0 ) { + esc_len = -esc_len; + VT_int_PutRawString(Term, Buffer + ofs, esc_len); + //Debug("Raw string '%.*s'", esc_len, Buffer+ofs); } - - // Fast check for non UTF-8 - if( Buffer[i] < 128 ) // Plain ASCII - VT_int_PutChar(Term, Buffer[i]); - else { // UTF-8 - Uint32 val; - i += ReadUTF8(&Buffer[i], &val) - 1; - VT_int_PutChar(Term, val); + else { + //Debug("Escape code '%.*s'", esc_len, Buffer+ofs); } + ASSERTCR(esc_len, >, 0, ); + ofs += esc_len; } // Update Screen - VT_int_UpdateScreen( Term, 0 ); + VT_int_UpdateScreen( Term, 1 ); +} + +void VT_int_PutRawString(tVTerm *Term, const Uint8 *String, size_t Bytes) +{ + for( int i = 0; i < Bytes; ) { + Uint32 val; + i += ReadUTF8(String+i, &val); + VT_int_PutChar(Term, val); + } } /** @@ -50,14 +55,17 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) int i; tVT_Char *buffer; int write_pos; + int limit; if(Term->Flags & VT_FLAG_ALTBUF) { buffer = Term->AltBuf; write_pos = Term->AltWritePos; + limit = Term->TextHeight * Term->TextWidth; } else { buffer = Term->Text; write_pos = Term->WritePos; + limit = Term->TextHeight*(giVT_Scrollback+1) * Term->TextWidth; } switch(Ch) @@ -104,6 +112,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) break; default: + ASSERTC(write_pos,<,limit); buffer[ write_pos ].Ch = Ch; buffer[ write_pos ].Colour = Term->CurColour; // Update the line before wrapping @@ -117,19 +126,18 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) { Term->AltWritePos = write_pos; - if(Term->AltWritePos >= Term->TextWidth*Term->TextHeight) + if(Term->AltWritePos >= limit) { Term->AltWritePos -= Term->TextWidth; VT_int_ScrollText(Term, 1); } - } else { Term->WritePos = write_pos; // Move Screen // - Check if we need to scroll the entire scrollback buffer - if(Term->WritePos >= Term->TextWidth*Term->TextHeight*(giVT_Scrollback+1)) + if(Term->WritePos >= limit) { int base; @@ -266,15 +274,13 @@ void VT_int_ScrollText(tVTerm *Term, int Count) */ void VT_int_ClearLine(tVTerm *Term, int Num) { - int i; - tVT_Char *cell; - - if( Num < 0 || Num >= Term->TextHeight * (giVT_Scrollback + 1) ) return ; + int limit = Term->TextHeight * (Term->Flags & VT_FLAG_ALTBUF ? 1 : giVT_Scrollback + 1); + tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text); + if( Num < 0 || Num >= limit ) return ; - cell = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltBuf : Term->Text; - cell = &cell[ Num*Term->TextWidth ]; + tVT_Char *cell = &buffer[ Num*Term->TextWidth ]; - for( i = Term->TextWidth; i--; ) + for( int i = 0; i < Term->TextWidth; i ++ ) { cell[ i ].Ch = 0; cell[ i ].Colour = Term->CurColour; diff --git a/KernelLand/Kernel/drv/vterm_vt100.c b/KernelLand/Kernel/drv/vterm_vt100.c index 1a51a583..bab78022 100644 --- a/KernelLand/Kernel/drv/vterm_vt100.c +++ b/KernelLand/Kernel/drv/vterm_vt100.c @@ -5,377 +5,203 @@ * drv/vterm_vt100.c * - Virtual Terminal - VT100 (Kinda) Emulation */ +#define DEBUG 0 #include "vterm.h" -// === CONSTANTS === -const Uint16 caVT100Colours[] = { - // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray - // Same again, but bright - VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0xAAA, - VT_COL_GREY, 0xF00, 0x0F0, 0xFF0, 0x00F, 0xF0F, 0x0FF, VT_COL_WHITE - }; +#define sTerminal sVTerm +#include "../../../Usermode/Applications/gui_terminal_src/vt100.c" -// === CODE === -/** - * \brief Handle a standard large escape code - * - * Handles any escape code of the form \x1B[n,...A where n is an integer - * and A is any letter. - */ -void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int *args) +void Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text) +{ + VT_int_PutRawString(Term, (const void*)UTF8Text, Length); +} +void Display_Newline(tTerminal *Term, bool bCarriageReturn) +{ + LOG(""); + VT_int_PutChar(Term, '\n'); +} +void Display_SetScrollArea(tTerminal *Term, int Start, int Count) { - int tmp = 1; - switch(CmdChar) + LOG("(%i,+%i)", Start, Count); + Term->ScrollTop = Start; + Term->ScrollHeight = Count; +} +void Display_ScrollDown(tTerminal *Term, int CountDown) +{ + LOG("(%i)", CountDown); + VT_int_UpdateScreen(Term, 0); + if( Term->Flags & VT_FLAG_ALTBUF ) + VT_int_ScrollText(Term, CountDown); + else { - // Left - case 'D': - tmp = -1; - // Right - case 'C': - if(argc == 1) tmp *= args[0]; - if( Term->Flags & VT_FLAG_ALTBUF ) + if(Term->ViewPos/Term->TextWidth + CountDown < 0) + return ; + if(Term->ViewPos/Term->TextWidth + CountDown > Term->TextHeight * (giVT_Scrollback + 1)) + return ; + + Term->ViewPos += Term->TextWidth * CountDown; + } +} +void Display_SetCursor(tTerminal *Term, int Row, int Col) +{ + LOG("(R%i,C%i)", Row, Col); + VT_int_UpdateScreen(Term, 0); + int maxrows = ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight; + ASSERTCR( Row, >=, 0, ); + ASSERTCR( Row, <, maxrows, ); + ASSERTCR( Col, >=, 0, ); + ASSERTCR( Col, <, Term->TextWidth, ); + *(Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos) = Row*Term->TextWidth + Col; +} +void Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol) +{ + LOG("(R+%i,C+%i)", RelRow, RelCol); + int *wrpos = (Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos); + + if( RelCol != 0 ) + { + // + if( RelCol < 0 ) { - if( (Term->AltWritePos + tmp) % Term->TextWidth == 0 ) { - Term->AltWritePos -= Term->AltWritePos % Term->TextWidth; - Term->AltWritePos += Term->TextWidth - 1; - } - else - Term->AltWritePos += tmp; + size_t avail = *wrpos % Term->TextWidth; + if( RelCol < -avail ) + RelCol = -avail; } else { - if( (Term->WritePos + tmp) % Term->TextWidth == 0 ) { - Term->WritePos -= Term->WritePos % Term->TextWidth; - Term->WritePos += Term->TextWidth - 1; - } - else - Term->WritePos += tmp; + size_t avail = Term->TextWidth - (*wrpos % Term->TextWidth); + if(RelCol > avail) + RelCol = avail; } - break; - - // Erase - case 'J': - switch(args[0]) - { - case 0: // Erase below - break; - case 1: // Erase above - break; - case 2: // Erase all - if( Term->Flags & VT_FLAG_ALTBUF ) - { - int i = Term->TextHeight; - while( i-- ) VT_int_ClearLine(Term, i); - Term->AltWritePos = 0; - VT_int_UpdateScreen(Term, 1); - } - else - { - int i = Term->TextHeight * (giVT_Scrollback + 1); - while( i-- ) VT_int_ClearLine(Term, i); - Term->WritePos = 0; - Term->ViewPos = 0; - VT_int_UpdateScreen(Term, 1); - } - break; - } - break; - - // Erase in line - case 'K': - switch(args[0]) + *wrpos += RelCol; + } + if( RelRow != 0 ) + { + int currow = *wrpos / Term->TextWidth; + int maxrows = ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight; + if( RelRow < 0 ) { - case 0: // Erase to right - if( Term->Flags & VT_FLAG_ALTBUF ) - { - int i, max; - max = Term->Width - Term->AltWritePos % Term->Width; - for( i = 0; i < max; i ++ ) - Term->AltBuf[Term->AltWritePos+i].Ch = 0; - } - else - { - int i, max; - max = Term->Width - Term->WritePos % Term->Width; - for( i = 0; i < max; i ++ ) - Term->Text[Term->WritePos+i].Ch = 0; - } - VT_int_UpdateScreen(Term, 0); - break; - case 1: // Erase to left - if( Term->Flags & VT_FLAG_ALTBUF ) - { - int i = Term->AltWritePos % Term->Width; - while( i -- ) - Term->AltBuf[Term->AltWritePos++].Ch = 0; - } - else - { - int i = Term->WritePos % Term->Width; - while( i -- ) - Term->Text[Term->WritePos++].Ch = 0; - } - VT_int_UpdateScreen(Term, 0); - break; - case 2: // Erase all - if( Term->Flags & VT_FLAG_ALTBUF ) - { - VT_int_ClearLine(Term, Term->AltWritePos / Term->Width); - } - else - { - VT_int_ClearLine(Term, Term->WritePos / Term->Width); - } - VT_int_UpdateScreen(Term, 0); - break; + if( currow + RelRow < 0 ) + RelRow = currow; } - break; - - // Set cursor position - case 'H': - if( Term->Flags & VT_FLAG_ALTBUF ) - Term->AltWritePos = args[1] + args[0]*Term->TextWidth; else - Term->WritePos = args[1] + args[0]*Term->TextWidth; - //Log_Debug("VTerm", "args = {%i, %i}", args[0], args[1]); - break; - // Scroll up `n` lines - case 'S': - tmp = -1; - // Scroll down `n` lines - case 'T': - if(argc == 1) tmp *= args[0]; - if( Term->Flags & VT_FLAG_ALTBUF ) - VT_int_ScrollText(Term, tmp); - else - { - if(Term->ViewPos/Term->TextWidth + tmp < 0) - break; - if(Term->ViewPos/Term->TextWidth + tmp > Term->TextHeight * (giVT_Scrollback + 1)) - break; - - Term->ViewPos += Term->TextWidth*tmp; - } - break; - // Set Mode (?) - case 'h': - if( argc >= 1 ) - { - switch(args[0]) - { - case 2: // Keyboard action mode - case 4: // Insert mode - case 12: // Send/receive - case 20: // Automatic newline - break; - default: // ? - break; - } - } - break; - - // Set Font flags - case 'm': - for( ; argc--; ) { - int colour_idx; - // Flags - if( 0 <= args[argc] && args[argc] <= 8) - { - switch(args[argc]) - { - case 0: Term->CurColour = DEFAULT_COLOUR; break; // Reset - case 1: Term->CurColour |= 0x80000000; break; // Bright - case 2: Term->CurColour &= ~0x80000000; break; // Dim - } - } - // Foreground Colour - else if(30 <= args[argc] && args[argc] <= 37) { - // Get colour index, accounting for bright bit - colour_idx = args[argc]-30 + ((Term->CurColour>>28) & 8); - Term->CurColour &= 0x8000FFFF; - Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ] << 16; - } - // Background Colour - else if(40 <= args[argc] && args[argc] <= 47) { - // Get colour index, accounting for bright bit - colour_idx = args[argc]-40 + ((Term->CurColour>>12) & 8); - Term->CurColour &= 0xFFFF8000; - Term->CurColour |= caVT100Colours[ colour_idx ]; - } - // Foreground Colour - bright - else if(90 <= args[argc] && args[argc] <= 97 ) { - colour_idx = args[argc]-90 + 8; - Term->CurColour &= 0x8000FFFF; - Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ] << 16; - } - // Background Colour - bright - else if(100 <= args[argc] && args[argc] <= 107 ) { - colour_idx = args[argc]-100 + 8; - Term->CurColour &= 0xFFFF8000; - Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ]; - } - else { - Log_Warning("VTerm", "Unknown font flag %i", args[argc]); - } + if( currow + RelRow > maxrows-1 ) + RelRow = maxrows-1 - currow; } - break; - - // Set scrolling region - case 'r': - if( argc != 2 ) break; - Term->ScrollTop = args[0]; - Term->ScrollHeight = args[1] - args[0]; - break; - - // Save cursor position - case 's': - if( argc != 0 ) break; - Term->SavedWritePos = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltWritePos : Term->WritePos; - break; - - // Restore saved cursor position - case 'u': - if( argc != 0 ) break; - *((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos) = Term->SavedWritePos; - break; - - default: - Log_Warning("VTerm", "Unknown control sequence '\\x1B[%c'", CmdChar); - break; + *wrpos += RelRow*Term->TextWidth; } } - -/** - * \fn int VT_int_ParseEscape(tVTerm *Term, const char *Buffer) - * \brief Parses a VT100 Escape code - */ -int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes) +void Display_SaveCursor(tTerminal *Term) +{ + Term->SavedWritePos = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltWritePos : Term->WritePos; + LOG("Saved = %i", Term->SavedWritePos); +} +void Display_RestoreCursor(tTerminal *Term) { - char c; - int argc = 0, j = 0; - int args[6] = {0,0,0,0}; - int bQuestionMark = 0; - const int ofs = Term->EscapeCodeLen; - const int sparespace = sizeof(Term->EscapeCodeCache)-Term->EscapeCodeLen; - const int copysize = MIN(Bytes, sparespace); + int max = ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight * Term->TextWidth; + int *wrpos = ((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos); + if( Term->SavedWritePos >= max ) + *wrpos = max-1; + else + *wrpos = Term->SavedWritePos; + LOG("Restored %i", *wrpos); +} +// 0: All, 1: Forward, -1: Reverse +void Display_ClearLine(tTerminal *Term, int Dir) +{ + int *wrpos = (Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos); + tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text); - memcpy( Term->EscapeCodeCache + Term->EscapeCodeLen, Buffer, copysize ); - Term->EscapeCodeLen += copysize; - - Bytes = Term->EscapeCodeLen; - Buffer = Term->EscapeCodeCache; + LOG("(Dir=%i)", Dir); - if( Bytes == j ) return j-ofs; - c = Buffer[j++]; - if(c != '\x1b') { - Term->EscapeCodeLen = 0; - return 0; + // Erase all + if( Dir == 0 ) { + VT_int_ClearLine(Term, *wrpos / Term->Width); + VT_int_UpdateScreen(Term, 0); } - - if( Bytes == j ) return j-ofs; - c = Buffer[j++]; - - switch(c) - { - //Large Code - case '[': - // Get Arguments - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - if(c == '?') { - bQuestionMark = 1; - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - } - if( '0' <= c && c <= '9' ) - { - do { - if(c == ';') { - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - } - while('0' <= c && c <= '9') { - args[argc] *= 10; - args[argc] += c-'0'; - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - } - argc ++; - } while(c == ';'); - } - - // Get Command - if( !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') ) - { - // Error - eat ESC only? - // > j : Entire code skipped - Term->EscapeCodeLen = 0; - return j-ofs; - } + // Erase to right + else if( Dir == 1 ) { + int max = Term->Width - *wrpos % Term->Width; + for( int i = 0; i < max; i ++ ) + buffer[*wrpos+i].Ch = 0; + VT_int_UpdateScreen(Term, 0); + } + // Erase to left + else if( Dir == -1 ) { + int start = *wrpos - *wrpos % Term->Width; + for( int i = start; i < *wrpos; i ++ ) + buffer[i].Ch = 0; + VT_int_UpdateScreen(Term, 0); + } + else { + // ERROR! + ASSERTC(Dir, >=, -1); + ASSERTC(Dir, <=, 1); + } +} +void Display_ClearLines(tTerminal *Term, int Dir) +{ + LOG("(Dir=%i)", Dir); + int *wrpos = (Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos); + tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text); + + // All + if( Dir == 0 ) { + int count; - if( bQuestionMark ) - { - switch(c) - { - // DEC Private Mode Set - case 'h': - if(argc != 1) break; - switch(args[0]) - { - case 25: - Term->Flags &= ~VT_FLAG_HIDECSR; - break; - case 1047: - VT_int_ToggleAltBuffer(Term, 1); - break; - } - break; - case 'l': - if(argc != 1) break; - switch(args[0]) - { - case 25: - Term->Flags |= VT_FLAG_HIDECSR; - break; - case 1047: - VT_int_ToggleAltBuffer(Term, 0); - break; - } - break; - default: - Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c); - break; - } + if( Term->Flags & VT_FLAG_ALTBUF ) { + count = Term->TextHeight; } - else - { - VT_int_ParseEscape_StandardLarge(Term, c, argc, args); + else { + count = Term->TextHeight * (giVT_Scrollback + 1); + Term->ViewPos = 0; } - break; - case '\0': - // Ignore \0 - break; - // Reset all attributes - case 'c': - Term->CurColour = DEFAULT_COLOUR; - Term->Flags = 0; - Term->ScrollHeight = 0; - break; - default: - //Log_Notice("VTerm", "TODO: Handle short escape codes"); - { - static volatile int tmp = 0; - if(tmp == 0) { - tmp = 1; - Debug("VTerm: Unknown short 0x%x", c); - tmp = 0; - } - } - break; + while( count -- ) + VT_int_ClearLine(Term, count); + *wrpos = 0; + VT_int_UpdateScreen(Term, 1); + } + // Downwards + else if( Dir == 1 ) { + Log_Warning("VTerm", "TODO: ClearLines Down"); } + // Upwards + else if( Dir == -1 ) { + Log_Warning("VTerm", "TODO: ClearLines Up"); + } + else { + // ERROR! + ASSERTC(Dir, >=, -1); + ASSERTC(Dir, <=, 1); + } +} +void Display_ResetAttributes(tTerminal *Term) +{ + LOG(""); + Term->CurColour = DEFAULT_COLOUR; +} +void Display_SetForeground(tTerminal *Term, uint32_t RGB) +{ + LOG("(%06x)", RGB); + Term->CurColour &= 0x8000FFFF; + Term->CurColour |= (Uint32)VT_Colour24to12(RGB) << 16; - //Log_Debug("VTerm", "j = %i, Buffer = '%s'", j, Buffer); - Term->EscapeCodeLen = 0; - return j-ofs; } +void Display_SetBackground(tTerminal *Term, uint32_t RGB) +{ + LOG("(%06x)", RGB); + Term->CurColour &= 0xFFFF8000; + Term->CurColour |= (Uint32)VT_Colour24to12(RGB) <<06; +} +void Display_Flush(tTerminal *Term) +{ + LOG(""); + VT_int_UpdateScreen(Term, 0); +} +void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled) +{ + LOG("(%B)", AltBufEnabled); + VT_int_ToggleAltBuffer(Term, AltBufEnabled); +} + diff --git a/KernelLand/Kernel/include/api_drv_video.h b/KernelLand/Kernel/include/api_drv_video.h index 0d681fee..4607b855 100644 --- a/KernelLand/Kernel/include/api_drv_video.h +++ b/KernelLand/Kernel/include/api_drv_video.h @@ -273,6 +273,10 @@ extern int giVT_CharHeight; * easing the driver development and reducing code duplication. */ extern void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Depth, int Pitch, Uint32 BGC, Uint32 FGC); +/** + * \brief Convert a colour from 24bpp 8:8:8 to 12bpp 4:4:4 + */ +extern Uint16 VT_Colour24to12(Uint32 Col24); /** * \fn Uint32 VT_Colour12to24(Uint16 Col12) * \brief Converts a colour from 12bpp to 24bpp