📄 video.c
字号:
/*============================================================================TEXT VIDEO ROUTINESEXPORTS:void blink(void);void select_vc(unsigned which_con);void putch(unsigned char c);void init_video(void);============================================================================*/#include <string.h> /* memcpy(), memsetw() */#include <ctype.h> /* isdigit() */#include <x86.h> /* outportb(), inportb() */#include "_krnl.h" /* MAX_VC, console_t *//* IMPORTSfrom MAIN.C */void kprintf(const char *fmt, ...);#define VGA_MISC_READ 0x3CCconsole_t _vc[MAX_VC];static unsigned short _num_vcs;static console_t *_curr_vc;static unsigned short *_vga_fb_adr;static unsigned _crtc_io_adr, _vc_width, _vc_height;/**********************************************************************************************************************************************************/void blink(void){ (*(unsigned char *)_vga_fb_adr)++;}/**********************************************************************************************************************************************************/static void scroll(console_t *con){ unsigned short *fb_adr; unsigned blank, temp; blank = 0x20 | ((unsigned)con->attrib << 8); fb_adr = con->fb_adr;/* scroll up */ if(con->csr_y >= _vc_height) { temp = con->csr_y - _vc_height + 1; memcpy(fb_adr, fb_adr + temp * _vc_width, (_vc_height - temp) * _vc_width * 2);/* blank the bottom line of the screen */ memsetw(fb_adr + (_vc_height - temp) * _vc_width, blank, _vc_width); con->csr_y = _vc_height - 1; }}/**********************************************************************************************************************************************************/static void set_attrib(console_t *con, unsigned att){ static const unsigned ansi_to_vga[] = { 0, 4, 2, 6, 1, 5, 3, 7 };/**/ unsigned new_att; new_att = con->attrib; if(att == 0) new_att &= ~0x08; /* bold off */ else if(att == 1) new_att |= 0x08; /* bold on */ else if(att >= 30 && att <= 37) { att = ansi_to_vga[att - 30]; new_att = (new_att & ~0x07) | att;/* fg color */ } else if(att >= 40 && att <= 47) { att = ansi_to_vga[att - 40] << 4; new_att = (new_att & ~0x70) | att;/* bg color */ } con->attrib = new_att;}/**********************************************************************************************************************************************************/static void move_csr(void){ unsigned short temp; temp = (_curr_vc->csr_y * _vc_width + _curr_vc->csr_x) + (_curr_vc->fb_adr - _vga_fb_adr); outportb(_crtc_io_adr + 0, 14); outportb(_crtc_io_adr + 1, temp >> 8); outportb(_crtc_io_adr + 0, 15); outportb(_crtc_io_adr + 1, temp);}/**********************************************************************************************************************************************************/void select_vc(unsigned which_vc){ unsigned i; if(which_vc >= _num_vcs) return; _curr_vc = _vc + which_vc; i = _curr_vc->fb_adr - _vga_fb_adr; outportb(_crtc_io_adr + 0, 12); outportb(_crtc_io_adr + 1, i >> 8); outportb(_crtc_io_adr + 0, 13); outportb(_crtc_io_adr + 1, i);/* oops, forgot this: */ move_csr();}/**********************************************************************************************************************************************************/static void putch_help(console_t *con, unsigned c){ unsigned short *fb_adr; unsigned att; att = (unsigned)con->attrib << 8; fb_adr = con->fb_adr;/* state machine to handle the escape sequencesESC */ if(con->esc == 1) { if(c == '[') { con->esc++; con->esc1 = 0; return; } /* else fall-through: zero esc and print c */ }/* ESC[ */ else if(con->esc == 2) { if(isdigit(c)) { con->esc1 = con->esc1 * 10 + c - '0'; return; } else if(c == ';') { con->esc++; con->esc2 = 0; return; }/* ESC[2J -- clear screen */ else if(c == 'J') { if(con->esc1 == 2) { memsetw(fb_adr, ' ' | att, _vc_height * _vc_width); con->csr_x = con->csr_y = 0; } }/* ESC[num1m -- set attribute num1 */ else if(c == 'm') set_attrib(con, con->esc1); con->esc = 0; /* anything else with one numeric arg */ return; }/* ESC[num1; */ else if(con->esc == 3) { if(isdigit(c)) { con->esc2 = con->esc2 * 10 + c - '0'; return; } else if(c == ';') { con->esc++; /* ESC[num1;num2; */ con->esc3 = 0; return; }/* ESC[num1;num2H -- move cursor to num1,num2 */ else if(c == 'H') { if(con->esc2 < _vc_width) con->csr_x = con->esc2; if(con->esc1 < _vc_height) con->csr_y = con->esc1; }/* ESC[num1;num2m -- set attributes num1,num2 */ else if(c == 'm') { set_attrib(con, con->esc1); set_attrib(con, con->esc2); } con->esc = 0; return; }/* ESC[num1;num2;num3 */ else if(con->esc == 4) { if(isdigit(c)) { con->esc3 = con->esc3 * 10 + c - '0'; return; }/* ESC[num1;num2;num3m -- set attributes num1,num2,num3 */ else if(c == 'm') { set_attrib(con, con->esc1); set_attrib(con, con->esc2); set_attrib(con, con->esc3); } con->esc = 0; return; } con->esc = 0;/* escape character */ if(c == 0x1B) { con->esc = 1; return; }/* backspace */ if(c == 0x08) { if(con->csr_x != 0) con->csr_x--; }/* tab */ else if(c == 0x09) con->csr_x = (con->csr_x + 8) & ~(8 - 1);/* carriage return */ else if(c == '\r') /* 0x0D */ con->csr_x = 0;/* line feed */// else if(c == '\n') /* 0x0A */// con->csr_y++;/* CR/LF */ else if(c == '\n') /* ### - 0x0A again */ { con->csr_x = 0; con->csr_y++; }/* printable ASCII */ else if(c >= ' ') { unsigned short *where; where = fb_adr + (con->csr_y * _vc_width + con->csr_x); *where = (c | att); con->csr_x++; } if(con->csr_x >= _vc_width) { con->csr_x = 0; con->csr_y++; } scroll(con);/* move cursor only if the VC we're writing is the current VC */ if(_curr_vc == con) move_csr();}/**********************************************************************************************************************************************************/void putch(unsigned c){/* all kernel messages to VC #0 */// putch_help(_vc + 0, c);/* all kernel messages to current VC */ putch_help(_curr_vc, c);}/**********************************************************************************************************************************************************/void init_video(void){ unsigned i;/* check for monochrome or color VGA emulation */ if((inportb(VGA_MISC_READ) & 0x01) != 0) { _vga_fb_adr = (unsigned short *)0xB8000L; _crtc_io_adr = 0x3D4; } else { _vga_fb_adr = (unsigned short *)0xB0000L; _crtc_io_adr = 0x3B4; }/* read current screen size from BIOS data segment (addresses 400-4FF) */ _vc_width = *(unsigned short *)0x44A; _vc_height = *(unsigned char *)0x484 + 1;/* figure out how many VCs we can have with 32K of display memory.Use INTEGER division to round down. */ _num_vcs = 32768L / (_vc_width * _vc_height * 2); if(_num_vcs > MAX_VC) _num_vcs = MAX_VC;/* init VCs, with a different foreground color for each */ for(i = 0; i < _num_vcs; i++) { _curr_vc = _vc + i; _curr_vc->attrib = i + 1; _curr_vc->fb_adr = _vga_fb_adr + _vc_width * _vc_height * i;/* ESC[2J clears the screen */ kprintf("\x1B[2J this is VC#%u (of 0-%u)\n", i, _num_vcs - 1); } select_vc(0); kprintf("init_video: %s emulation, %u x %u, framebuffer at " "0x%lX\n", (_crtc_io_adr == 0x3D4) ? "color" : "mono", _vc_width, _vc_height, _vga_fb_adr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -