Bare metal VGA: simplify treatment of background color codes

This commit is contained in:
tkchia 2022-09-10 06:18:43 +00:00
parent 5886678ad7
commit 26712247ad

View file

@ -261,15 +261,29 @@ static void TtySetCodepage(struct Tty *tty, char id) {
} }
} }
/**
* Map the currently active foreground & background colors & terminal
* configuration to a VGA text character attribute byte.
*
* @see VGA_USE_BLINK macro (libc/vga/vga.internal.h)
* @see drivers/tty/vt/vt.c in Linux 5.9.14 source code
*/
static uint8_t TtyGetVgaAttr(struct Tty *tty) static uint8_t TtyGetVgaAttr(struct Tty *tty)
{ {
uint8_t attr = tty->fg | tty->bg << 4; uint8_t attr = tty->fg | tty->bg << 4;
if ((tty->pr & kTtyBold) != 0)
attr |= 0x08;
#ifdef VGA_USE_BLINK #ifdef VGA_USE_BLINK
/*
* If blinking is enabled, we can only have the 8 dark background color
* codes (0 to 7). Simply map any bright background color (8 to 15) to
* its corresponding dark color, & call it a day. This is a bit more
* simplistic than what Linux does, but should be enough.
*/
attr &= ~0x80;
if ((tty->pr & kTtyBlink) != 0) if ((tty->pr & kTtyBlink) != 0)
attr |= 0x80; attr |= 0x80;
#endif #endif
if ((tty->pr & kTtyBold) != 0)
attr |= 0x08;
return attr; return attr;
} }
@ -642,37 +656,23 @@ static void TtyCsiN(struct Tty *tty) {
/** /**
* Map the given (R, G, B) triplet to one of the 16 basic foreground colors * Map the given (R, G, B) triplet to one of the 16 basic foreground colors
* or one of the 8 (or 16) background colors. * or one of the 16 background colors.
* *
* @see VGA_USE_BLINK macro (libc/vga/vga.internal.h)
* @see drivers/tty/vt/vt.c in Linux 5.9.14 source code * @see drivers/tty/vt/vt.c in Linux 5.9.14 source code
*/ */
static uint8_t TtyMapTrueColor(uint8_t r, uint8_t g, uint8_t b, bool as_fg) static uint8_t TtyMapTrueColor(uint8_t r, uint8_t g, uint8_t b)
{ {
uint8_t hue = 0; uint8_t hue = 0, max = MAX(MAX(r, g), b);
#ifdef VGA_USE_BLINK if (r > max / 2)
if (!as_fg) { hue |= 4;
if (r >= 128) if (g > max / 2)
hue |= 4; hue |= 2;
if (g >= 128) if (b > max / 2)
hue |= 2; hue |= 1;
if (b >= 128) if (hue == 7 && max <= 0x55)
hue |= 1; hue = 8;
} else else if (max > 0xaa)
#endif hue |= 8;
{
uint8_t max = MAX(MAX(r, g), b);
if (r > max / 2)
hue |= 4;
if (g > max / 2)
hue |= 2;
if (b > max / 2)
hue |= 1;
if (hue == 7 && max <= 0x55)
hue = 8;
else if (max > 0xaa)
hue |= 8;
}
return hue; return hue;
} }
@ -682,7 +682,7 @@ static uint8_t TtyMapTrueColor(uint8_t r, uint8_t g, uint8_t b, bool as_fg)
* *
* @see drivers/tty/vt/vt.c in Linux 5.9.14 source code * @see drivers/tty/vt/vt.c in Linux 5.9.14 source code
*/ */
static uint8_t TtyMapXtermColor(uint8_t color, bool as_fg) static uint8_t TtyMapXtermColor(uint8_t color)
{ {
uint8_t r, g, b; uint8_t r, g, b;
if (color < 8) { if (color < 8) {
@ -702,7 +702,7 @@ static uint8_t TtyMapXtermColor(uint8_t color, bool as_fg)
r = color * 0x55 / 2; r = color * 0x55 / 2;
} else } else
r = g = b = (unsigned)color * 10 - 2312; r = g = b = (unsigned)color * 10 - 2312;
return TtyMapTrueColor(r, g, b, as_fg); return TtyMapTrueColor(r, g, b);
} }
static void TtySelectGraphicsRendition(struct Tty *tty) { static void TtySelectGraphicsRendition(struct Tty *tty) {
@ -825,13 +825,7 @@ static void TtySelectGraphicsRendition(struct Tty *tty) {
break; break;
case 100 ... 107: case 100 ... 107:
code[0] -= 100 - 40; code[0] -= 100 - 40;
#ifndef VGA_USE_BLINK
/*
* If blinking is not enabled in VGA text mode, then we can
* use bright background colors.
*/
code[0] += 8; code[0] += 8;
#endif
/* fallthrough */ /* fallthrough */
case 40 ... 47: case 40 ... 47:
tty->bg = code[0] - 40; tty->bg = code[0] - 40;
@ -858,7 +852,7 @@ static void TtySelectGraphicsRendition(struct Tty *tty) {
if (++code[3] == 3) { if (++code[3] == 3) {
code[3] = 0; code[3] = 0;
t = kSgr; t = kSgr;
tty->fg = TtyMapTrueColor(code[0], code[1], code[2], true); tty->fg = TtyMapTrueColor(code[0], code[1], code[2]);
tty->pr |= kTtyFg; tty->pr |= kTtyFg;
tty->pr |= kTtyTrue; tty->pr |= kTtyTrue;
} }
@ -867,20 +861,20 @@ static void TtySelectGraphicsRendition(struct Tty *tty) {
if (++code[3] == 3) { if (++code[3] == 3) {
code[3] = 0; code[3] = 0;
t = kSgr; t = kSgr;
tty->bg = TtyMapTrueColor(code[0], code[1], code[2], false); tty->bg = TtyMapTrueColor(code[0], code[1], code[2]);
tty->pr |= kTtyBg; tty->pr |= kTtyBg;
tty->pr |= kTtyTrue; tty->pr |= kTtyTrue;
} }
break; break;
case kSgrFgXterm: case kSgrFgXterm:
t = kSgr; t = kSgr;
tty->fg = TtyMapXtermColor(code[0], true); tty->fg = TtyMapXtermColor(code[0]);
tty->pr |= kTtyFg; tty->pr |= kTtyFg;
tty->pr &= ~kTtyTrue; tty->pr &= ~kTtyTrue;
break; break;
case kSgrBgXterm: case kSgrBgXterm:
t = kSgr; t = kSgr;
tty->bg = TtyMapXtermColor(code[0], false); tty->bg = TtyMapXtermColor(code[0]);
tty->pr |= kTtyBg; tty->pr |= kTtyBg;
tty->pr &= ~kTtyTrue; tty->pr &= ~kTtyTrue;
break; break;