📄 vga_support.c
字号:
unsigned long *pix;
if ((x < 0) || (x >= VISIBLE_SCREEN_WIDTH) ||
(y < 0) || (y >= screen_height)) return;
for (l = 0; l < FONT_HEIGHT; l++) {
bits = font_table[c-FIRST_CHAR][l];
yoff = y*FONT_HEIGHT + l;
xoff = x*FONT_WIDTH;
#if 0 // Render font characters one bit at a time
for (p = 0; p < FONT_WIDTH; p++) {
#ifdef FONT_LEFT_TO_RIGHT
set_pixel(yoff, xoff + p, (bits & 0x80) ? fg : bg);
bits <<= 1;
#else
set_pixel(yoff, xoff + p, (bits & 0x01) ? fg : bg);
bits >>= 1;
#endif
}
#else // Render characters 4 bits at a time
pix = (unsigned long *)vga_fb(yoff, xoff);
#ifdef FONT_LEFT_TO_RIGHT
*pix++ = _bitmap[(bits & 0xF0) >> 4];
*pix++ = _bitmap[(bits & 0x0F)];
#else
*pix++ = _bitmap[(bits & 0x0F)];
*pix++ = _bitmap[(bits & 0xF0) >> 4];
#endif
#endif
}
}
static void
vga_refresh(void)
{
int row, col;
for (row = screen_start; row < screen_height; row++) {
for (col = 0; col < VISIBLE_SCREEN_WIDTH; col++) {
if ((col+screen_pan) < screen_width) {
vga_drawc(screen[row][col+screen_pan], col, row);
} else {
vga_drawc(' ', col, row);
}
}
}
if (cursor_enable) {
vga_drawc(CURSOR_ON, curX-screen_pan, curY);
}
}
static void
vga_scroll(void)
{
int col;
cyg_uint8 *c1;
cyg_uint32 *lc0, *lc1, *lcn;
cyg_uint32 *fb_row0, *fb_row1, *fb_rown;
// First scroll up the virtual screen
#if ((SCREEN_WIDTH%4) != 0)
#error Scroll code optimized for screen with multiple of 4 columns
#endif
lc0 = (cyg_uint32 *)&screen[0][0];
lc1 = (cyg_uint32 *)&screen[1][0];
lcn = (cyg_uint32 *)&screen[screen_height][0];
while (lc1 != lcn) {
*lc0++ = *lc1++;
}
c1 = &screen[screen_height-1][0];
for (col = 0; col < screen_width; col++) {
*c1++ = 0x20;
}
#if 0 // Scrolling like this is *relly* slow
fb_row0 = (cyg_uint32 *)vga_fb(screen_start*FONT_HEIGHT, 0);
fb_row1 = (cyg_uint32 *)vga_fb((screen_start+1)*FONT_HEIGHT, 0);
fb_rown = (cyg_uint32 *)vga_fb(screen_end*FONT_HEIGHT, 0);
#if 0
while (fb_row1 != fb_rown) {
*fb_row0++ = *fb_row1++;
}
#else
// Optimized ARM assembly "move" code
asm __volatile(
"mov r0,%0;"
"mov r1,%1;"
"mov r2,%2;"
"10: ldmia r1!,{r3-r6};"
"stmia r0!,{r3-r6};"
"ldmia r1!,{r3-r6};"
"stmia r0!,{r3-r6};"
"cmp r1,r2;"
"bne 10b"
:
: "r"(fb_row0), "r"(fb_row1), "r"(fb_rown)
: "r0","r1","r2","r3","r4","r5","r6"
);
#endif
// Erase bottom line
for (col = 0; col < screen_width; col++) {
vga_drawc(' ', col, screen_end-1);
}
#else // Clear & redraw is faster!
vga_refresh();
#endif
}
// Draw one character at the current position
void
vga_putc(cyg_uint8 c)
{
if (cursor_enable) {
vga_drawc(screen[curY][curX], curX-screen_pan, curY);
}
switch (c) {
case '\r':
curX = 0;
break;
case '\n':
curY++;
break;
case '\b':
curX--;
if (curX < 0) {
curY--;
if (curY < 0) curY = 0;
curX = screen_width-1;
}
break;
default:
if (((int)c < FIRST_CHAR) || ((int)c > LAST_CHAR)) c = '.';
screen[curY][curX] = c;
vga_drawc(c, curX-screen_pan, curY);
curX++;
if (curX == screen_width) {
curY++;
curX = 0;
}
}
if (curY >= screen_height) {
vga_scroll();
curY = (screen_height-1);
}
if (cursor_enable) {
vga_drawc(CURSOR_ON, curX-screen_pan, curY);
}
}
// Basic VGA 'printf()' support
#include <stdarg.h>
#define is_digit(c) ((c >= '0') && (c <= '9'))
static int
_cvt(unsigned long val, char *buf, long radix, char *digits)
{
char temp[80];
char *cp = temp;
int length = 0;
if (val == 0) {
/* Special case */
*cp++ = '0';
} else {
while (val) {
*cp++ = digits[val % radix];
val /= radix;
}
}
while (cp != temp) {
*buf++ = *--cp;
length++;
}
*buf = '\0';
return (length);
}
static int
vga_vprintf(void (*putc)(cyg_uint8), const char *fmt0, va_list ap)
{
char c, sign, *cp;
int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
char buf[32];
long val;
while ((c = *fmt0++)) {
cp = buf;
length = 0;
if (c == '%') {
c = *fmt0++;
left_prec = right_prec = pad_on_right = 0;
if (c == '-') {
c = *fmt0++;
pad_on_right++;
}
if (c == '0') {
zero_fill = TRUE;
c = *fmt0++;
} else {
zero_fill = FALSE;
}
while (is_digit(c)) {
left_prec = (left_prec * 10) + (c - '0');
c = *fmt0++;
}
if (c == '.') {
c = *fmt0++;
zero_fill++;
while (is_digit(c)) {
right_prec = (right_prec * 10) + (c - '0');
c = *fmt0++;
}
} else {
right_prec = left_prec;
}
sign = '\0';
switch (c) {
case 'd':
case 'x':
case 'X':
val = va_arg(ap, long);
switch (c) {
case 'd':
if (val < 0) {
sign = '-';
val = -val;
}
length = _cvt(val, buf, 10, "0123456789");
break;
case 'x':
length = _cvt(val, buf, 16, "0123456789abcdef");
break;
case 'X':
length = _cvt(val, buf, 16, "0123456789ABCDEF");
break;
}
break;
case 's':
cp = va_arg(ap, char *);
length = strlen(cp);
break;
case 'c':
c = va_arg(ap, long /*char*/);
(*putc)(c);
continue;
default:
(*putc)('?');
}
pad = left_prec - length;
if (sign != '\0') {
pad--;
}
if (zero_fill) {
c = '0';
if (sign != '\0') {
(*putc)(sign);
sign = '\0';
}
} else {
c = ' ';
}
if (!pad_on_right) {
while (pad-- > 0) {
(*putc)(c);
}
}
if (sign != '\0') {
(*putc)(sign);
}
while (length-- > 0) {
(*putc)(c = *cp++);
if (c == '\n') {
(*putc)('\r');
}
}
if (pad_on_right) {
while (pad-- > 0) {
(*putc)(' ');
}
}
} else {
(*putc)(c);
if (c == '\n') {
(*putc)('\r');
}
}
}
// FIXME
return 0;
}
int
_vga_printf(char const *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vga_vprintf(vga_putc, fmt, ap);
va_end(ap);
return (ret);
}
//
// Support VGA/keyboard (PS2) as a virtual I/O channel
// Adapted from i386/pcmb_screen.c
//
//-----------------------------------------------------------------------------
// Keyboard definitions
#define KBDATAPORT 0x0060 // data I/O port
#define KBCMDPORT 0x0064 // command port (write)
#define KBSTATPORT 0x0064 // status port (read)
#define KBINRDY 0x01
#define KBOUTRDY 0x02
#define KBTXTO 0x40 // Transmit timeout - nothing there
#define KBTEST 0xAB
// Scan codes
#define LSHIFT 0x2a
#define RSHIFT 0x36
#define CTRL 0x1d
#define ALT 0x38
#define CAPS 0x3a
#define NUMS 0x45
#define BREAK 0x80
// Bits for KBFlags
#define KBNormal 0x0000
#define KBShift 0x0001
#define KBCtrl 0x0002
#define KBAlt 0x0004
#define KBIndex 0x0007 // mask for the above
#define KBExtend 0x0010
#define KBAck 0x0020
#define KBResend 0x0040
#define KBShiftL (0x0080 | KBShift)
#define KBShiftR (0x0100 | KBShift)
#define KBCtrlL (0x0200 | KBCtrl)
#define KBCtrlR (0x0400 | KBCtrl)
#define KBAltL (0x0800 | KBAlt)
#define KBAltR (0x1000 | KBAlt)
#define KBCapsLock 0x2000
#define KBNumLock 0x4000
#define KBArrowUp 0x48
#define KBArrowRight 0x4D
#define KBArrowLeft 0x4B
#define KBArrowDown 0x50
//-----------------------------------------------------------------------------
// Keyboard Variables
static int KBFlags = 0;
static CYG_BYTE KBPending = 0xFF;
static CYG_BYTE KBScanTable[128][4] = {
// Normal Shift Control Alt
// 0x00
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0x1b, 0x1b, 0x1b, 0xFF, },
{ '1', '!', 0xFF, 0xFF, },
{ '2', '"', 0xFF, 0xFF, },
{ '3', '#', 0xFF, 0xFF, },
{ '4', '$', 0xFF, 0xFF, },
{ '5', '%', 0xFF, 0xFF, },
{ '6', '^', 0xFF, 0xFF, },
{ '7', '&', 0xFF, 0xFF, },
{ '8', '*', 0xFF, 0xFF, },
{ '9', '(', 0xFF, 0xFF, },
{ '0', ')', 0xFF, 0xFF, },
{ '-', '_', 0xFF, 0xFF, },
{ '=', '+', 0xFF, 0xFF, },
{ '\b', '\b', 0xFF, 0xFF, },
{ '\t', '\t', 0xFF, 0xFF, },
// 0x10
{ 'q', 'Q', 0x11, 0xFF, },
{ 'w', 'W', 0x17, 0xFF, },
{ 'e', 'E', 0x05, 0xFF, },
{ 'r', 'R', 0x12, 0xFF, },
{ 't', 'T', 0x14, 0xFF, },
{ 'y', 'Y', 0x19, 0xFF, },
{ 'u', 'U', 0x15, 0xFF, },
{ 'i', 'I', 0x09, 0xFF, },
{ 'o', 'O', 0x0F, 0xFF, },
{ 'p', 'P', 0x10, 0xFF, },
{ '[', '{', 0x1b, 0xFF, },
{ ']', '}', 0x1d, 0xFF, },
{ '\r', '\r', '\n', 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 'a', 'A', 0x01, 0xFF, },
{ 's', 'S', 0x13, 0xFF, },
// 0x20
{ 'd', 'D', 0x04, 0xFF, },
{ 'f', 'F', 0x06, 0xFF, },
{ 'g', 'G', 0x07, 0xFF, },
{ 'h', 'H', 0x08, 0xFF, },
{ 'j', 'J', 0x0a, 0xFF, },
{ 'k', 'K', 0x0b, 0xFF, },
{ 'l', 'L', 0x0c, 0xFF, },
{ ';', ':', 0xFF, 0xFF, },
{ 0x27, '@', 0xFF, 0xFF, },
{ '#', '~', 0xFF, 0xFF, },
{ '`', '~', 0xFF, 0xFF, },
{ '\\', '|', 0x1C, 0xFF, },
{ 'z', 'Z', 0x1A, 0xFF, },
{ 'x', 'X', 0x18, 0xFF, },
{ 'c', 'C', 0x03, 0xFF, },
{ 'v', 'V', 0x16, 0xFF, },
// 0x30
{ 'b', 'B', 0x02, 0xFF, },
{ 'n', 'N', 0x0E, 0xFF, },
{ 'm', 'M', 0x0D, 0xFF, },
{ ',', '<', 0xFF, 0xFF, },
{ '.', '>', 0xFF, 0xFF, },
{ '/', '?', 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ ' ', ' ', ' ', ' ', },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xF1, 0xE1, 0xFF, 0xFF, },
{ 0xF2, 0xE2, 0xFF, 0xFF, },
{ 0xF3, 0xE3, 0xFF, 0xFF, },
{ 0xF4, 0xE4, 0xFF, 0xFF, },
{ 0xF5, 0xE5, 0xFF, 0xFF, },
// 0x40
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0x15, 0x15, 0x15, 0x15, },
{ 0x10, 0x10, 0x10, 0x10, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
// 0x50
{ 0x04, 0x04, 0x04, 0x04, },
{ 0x0e, 0x0e, 0x0e, 0x0e, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
// 0x60
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -