mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Bare metal VGA: minor improvements (#608)
This commit is contained in:
parent
155b378a39
commit
bae7367774
3 changed files with 79 additions and 101 deletions
159
libc/vga/tty.c
159
libc/vga/tty.c
|
@ -93,7 +93,7 @@ static wchar_t *Wcs(struct Tty *tty)
|
||||||
|
|
||||||
void _StartTty(struct Tty *tty, unsigned short yn, unsigned short xn,
|
void _StartTty(struct Tty *tty, unsigned short yn, unsigned short xn,
|
||||||
unsigned short starty, unsigned short startx,
|
unsigned short starty, unsigned short startx,
|
||||||
void *vccs, wchar_t *wcs) {
|
unsigned char chr_ht, void *vccs, wchar_t *wcs) {
|
||||||
struct VgaTextCharCell *ccs = vccs;
|
struct VgaTextCharCell *ccs = vccs;
|
||||||
memset(tty, 0, sizeof(struct Tty));
|
memset(tty, 0, sizeof(struct Tty));
|
||||||
SetYn(tty, yn);
|
SetYn(tty, yn);
|
||||||
|
@ -103,8 +103,11 @@ void _StartTty(struct Tty *tty, unsigned short yn, unsigned short xn,
|
||||||
starty = yn - 1;
|
starty = yn - 1;
|
||||||
if (startx >= xn)
|
if (startx >= xn)
|
||||||
startx = xn - 1;
|
startx = xn - 1;
|
||||||
|
if (chr_ht > 32)
|
||||||
|
chr_ht = 32;
|
||||||
tty->y = starty;
|
tty->y = starty;
|
||||||
tty->x = startx;
|
tty->x = startx;
|
||||||
|
tty->chr_ht = chr_ht;
|
||||||
if (SetWcs(tty, wcs)) {
|
if (SetWcs(tty, wcs)) {
|
||||||
size_t n = (size_t)yn * xn, i;
|
size_t n = (size_t)yn * xn, i;
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
|
@ -143,66 +146,27 @@ static wchar_t *GetXlatLineDrawing(void) {
|
||||||
return xlat;
|
return xlat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void XlatAlphabet(wchar_t xlat[128], int a, int b) {
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < 128; ++i) {
|
|
||||||
if ('a' <= i && i <= 'z') {
|
|
||||||
xlat[i] = i - 'a' + a;
|
|
||||||
} else if ('A' <= i && i <= 'Z') {
|
|
||||||
xlat[i] = i - 'A' + b;
|
|
||||||
} else {
|
|
||||||
xlat[i] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static wchar_t *GetXlatItalic(void) {
|
static wchar_t *GetXlatItalic(void) {
|
||||||
static bool once;
|
/* Unimplemented. Simply output normal non-italicized characters for now. */
|
||||||
static wchar_t xlat[128];
|
return GetXlatAscii();
|
||||||
if (!once) {
|
|
||||||
XlatAlphabet(xlat, L'𝑎', L'𝐴');
|
|
||||||
once = true;
|
|
||||||
}
|
|
||||||
return xlat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static wchar_t *GetXlatBoldItalic(void) {
|
static wchar_t *GetXlatBoldItalic(void) {
|
||||||
static bool once;
|
/*
|
||||||
static wchar_t xlat[128];
|
* Unimplemented. Simply output high-intensity non-italicized characters
|
||||||
if (!once) {
|
* for now.
|
||||||
XlatAlphabet(xlat, L'𝒂', L'𝑨');
|
*/
|
||||||
once = true;
|
return GetXlatAscii();
|
||||||
}
|
|
||||||
return xlat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static wchar_t *GetXlatBoldFraktur(void) {
|
static wchar_t *GetXlatBoldFraktur(void) {
|
||||||
static bool once;
|
/* Unimplemented. */
|
||||||
static wchar_t xlat[128];
|
return GetXlatAscii();
|
||||||
if (!once) {
|
|
||||||
XlatAlphabet(xlat, L'𝖆', L'𝕬');
|
|
||||||
once = true;
|
|
||||||
}
|
|
||||||
return xlat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static wchar_t *GetXlatFraktur(void) {
|
static wchar_t *GetXlatFraktur(void) {
|
||||||
unsigned i;
|
/* Unimplemented. */
|
||||||
static bool once;
|
return GetXlatAscii();
|
||||||
static wchar_t xlat[128];
|
|
||||||
if (!once) {
|
|
||||||
for (i = 0; i < ARRAYLEN(xlat); ++i) {
|
|
||||||
if ('A' <= i && i <= 'Z') {
|
|
||||||
xlat[i] = L"𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ"[i - 'A'];
|
|
||||||
} else if ('a' <= i && i <= 'z') {
|
|
||||||
xlat[i] = i - 'a' + L'𝔞';
|
|
||||||
} else {
|
|
||||||
xlat[i] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
once = true;
|
|
||||||
}
|
|
||||||
return xlat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static wchar_t *GetXlatDoubleWidth(void) {
|
static wchar_t *GetXlatDoubleWidth(void) {
|
||||||
|
@ -258,15 +222,33 @@ 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;
|
||||||
if ((tty->pr & kTtyBold) != 0)
|
if ((tty->pr & kTtyFlip) == 0)
|
||||||
attr |= 0x08;
|
attr = tty->fg | tty->bg << 4;
|
||||||
|
else
|
||||||
|
attr = tty->bg | tty->fg << 4;
|
||||||
#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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,37 +621,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,7 +647,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) {
|
||||||
|
@ -699,7 +667,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) {
|
||||||
|
@ -822,13 +790,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;
|
||||||
|
@ -855,7 +817,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;
|
||||||
}
|
}
|
||||||
|
@ -864,20 +826,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;
|
||||||
|
@ -1081,10 +1043,17 @@ static void TtyEscAppend(struct Tty *tty, char c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TtyUpdateHwCursor(struct Tty *tty) {
|
static void TtyUpdateHwCursor(struct Tty *tty) {
|
||||||
|
unsigned char start = tty->chr_ht - 2, end = tty->chr_ht - 1;
|
||||||
unsigned short pos = tty->y * Xn(tty) + tty->x;
|
unsigned short pos = tty->y * Xn(tty) + tty->x;
|
||||||
outb(CRTPORT, 0x0e);
|
if ((tty->conf & kTtyNocursor))
|
||||||
|
start |= 1 << 5;
|
||||||
|
outb(CRTPORT, 0x0A);
|
||||||
|
outb(CRTPORT + 1, start);
|
||||||
|
outb(CRTPORT, 0x0B);
|
||||||
|
outb(CRTPORT + 1, end);
|
||||||
|
outb(CRTPORT, 0x0E);
|
||||||
outb(CRTPORT + 1, (unsigned char)(pos >> 8));
|
outb(CRTPORT + 1, (unsigned char)(pos >> 8));
|
||||||
outb(CRTPORT, 0x0f);
|
outb(CRTPORT, 0x0F);
|
||||||
outb(CRTPORT + 1, (unsigned char)pos);
|
outb(CRTPORT + 1, (unsigned char)pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ struct Tty {
|
||||||
uint32_t u8;
|
uint32_t u8;
|
||||||
uint32_t n8;
|
uint32_t n8;
|
||||||
uint32_t pr;
|
uint32_t pr;
|
||||||
uint8_t fg, bg;
|
uint8_t fg, bg, chr_ht;
|
||||||
uint32_t conf;
|
uint32_t conf;
|
||||||
unsigned short savey, savex;
|
unsigned short savey, savex;
|
||||||
struct VgaTextCharCell *ccs;
|
struct VgaTextCharCell *ccs;
|
||||||
|
@ -134,7 +134,8 @@ struct Tty {
|
||||||
};
|
};
|
||||||
|
|
||||||
void _StartTty(struct Tty *, unsigned short, unsigned short,
|
void _StartTty(struct Tty *, unsigned short, unsigned short,
|
||||||
unsigned short, unsigned short, void *, wchar_t *);
|
unsigned short, unsigned short, unsigned char,
|
||||||
|
void *, wchar_t *);
|
||||||
ssize_t _TtyRead(struct Tty *, void *, size_t);
|
ssize_t _TtyRead(struct Tty *, void *, size_t);
|
||||||
ssize_t _TtyWrite(struct Tty *, const void *, size_t);
|
ssize_t _TtyWrite(struct Tty *, const void *, size_t);
|
||||||
ssize_t _TtyWriteInput(struct Tty *, const void *, size_t);
|
ssize_t _TtyWriteInput(struct Tty *, const void *, size_t);
|
||||||
|
|
|
@ -58,15 +58,23 @@ ssize_t sys_writev_vga(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||||
|
|
||||||
__attribute__((__constructor__)) static textstartup void _vga_init(void) {
|
__attribute__((__constructor__)) static textstartup void _vga_init(void) {
|
||||||
void * const vid_buf = (void *)(BANE + 0xb8000ull);
|
void * const vid_buf = (void *)(BANE + 0xb8000ull);
|
||||||
/* Get the initial cursor position from the BIOS data area. */
|
/*
|
||||||
|
* Get the initial cursor position from the BIOS data area. Also get
|
||||||
|
* the height (in scan lines) of each character; this is used to set the
|
||||||
|
* cursor shape.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char col, row;
|
unsigned char col, row;
|
||||||
} bios_curs_pos_t;
|
} bios_curs_pos_t;
|
||||||
bios_curs_pos_t pos = *(bios_curs_pos_t *)(BANE + 0x0450ull);
|
bios_curs_pos_t pos = *(bios_curs_pos_t *)(BANE + 0x0450ull);
|
||||||
|
uint8_t chr_ht = *(uint8_t *)(BANE + 0x0485ull),
|
||||||
|
chr_ht_hi = *(uint8_t *)(BANE + 0x0486ull);
|
||||||
|
if (chr_ht_hi != 0 || chr_ht > 32)
|
||||||
|
chr_ht = 32;
|
||||||
/*
|
/*
|
||||||
* Initialize our tty structure from the current screen contents & current
|
* Initialize our tty structure from the current screen contents, current
|
||||||
* cursor position.
|
* cursor position, & character height.
|
||||||
*/
|
*/
|
||||||
_StartTty(&vga_tty, VGA_TTY_HEIGHT, VGA_TTY_WIDTH, pos.row, pos.col,
|
_StartTty(&vga_tty, VGA_TTY_HEIGHT, VGA_TTY_WIDTH, pos.row, pos.col,
|
||||||
vid_buf, vga_wcs);
|
chr_ht, vid_buf, vga_wcs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue