📄 vga.c
字号:
#include <support.h>
#include <video/graphic.h>
#include <video/modes.h>
#include <video/fonts.h>
#include <video/palette.h>
#include <drivers/mem/mem.h>
#include <drivers/timer.h>
static unsigned char * font_buf = g_8x8_font;
static unsigned int vga_card = GR_VGA;
static unsigned int cursor_position = 0;
static unsigned int current_mode = 0x03; // text mode
#define pokeb(A,V) ( *(char*) ( A ) = ( V ) )
#define pokew(A,V) ( *(short*) ( A ) = ( V ) )
static struct Screen
{
unsigned int x, y;
unsigned color_fg, color_bg;
} screen = { 1, 1, CL_WHITE, CL_BLACK };
static unsigned get_fb_seg(void)
{
unsigned seg;
outportb(GRA_I, 6);
seg = inportb(GRA_D);
seg >>= 2;
seg &= 3;
switch(seg)
{
case 0:
case 1: seg = 0xA0000; break;
case 2: seg = 0xB0000; break;
case 3: seg = 0xB8000; break;
}
return seg;
}
#define _vmemwr(A,S,N) _dosmemputb(S, N, A)
static void vmemwr(unsigned dst_off, unsigned char *src, unsigned count)
{
_vmemwr(get_fb_seg() + dst_off, src, count);
}
static void vga_putpixel(unsigned int x, unsigned int y, unsigned color);
static void vga_gotoxy ( unsigned int x, unsigned int y );
static unsigned int vga_wherex ( void );
static unsigned int vga_wherey ( void );
static void vga_scroll(long lines);
static unsigned int getcuraddr ( void )
{
byte b1, b2 ;
outportb ( CRT_I, 14 ) ;
b1 = inportb ( CRT_D ) ;
outportb ( CRT_I, 15 ) ;
b2 = inportb ( CRT_D ) ;
return ( ((unsigned int)b1 << 8) | ((unsigned int)b2) ) ;
}
static void setcuraddr ( unsigned int addr )
{
outportb ( CRT_I, 14 ) ;
outportb ( CRT_D, (addr & 0x0FF00) >> 8 ) ;
outportb ( CRT_I, 15 ) ;
outportb ( CRT_D, addr & 0x0FF ) ;
cursor_position = addr * 2;
}
static void text_show_cursor(void)
{
outportb(CRT_I, 0x0A);
outportb(CRT_D, inportb(CRT_D) | 0x20);
}
static void text_hide_cursor(void)
{
outportb(CRT_I, 0x0A);
outportb(CRT_D, inportb(CRT_D) & ~0x20);
}
static void vga_putch(unsigned int xx, unsigned int yy, unsigned char data)
{
unsigned int x, y, i, j;
unsigned char ch;
vga_gotoxy(xx, yy);
x = vga_wherex();
y = vga_wherey();
if (bios_modes[current_mode].graphic)
{
if (data == '\r')
{
vga_gotoxy (1, y);
return;
}
if (data == '\n')
{
x = 1;
y++;
if (y > bios_modes[current_mode].max_y / bios_modes[current_mode].font_height)
{
vga_scroll(1);
y = bios_modes[current_mode].max_y / bios_modes[current_mode].font_height;
}
vga_gotoxy(x, y);
}
else
{
for (i=0; i < bios_modes[current_mode].font_height; i++)
{
ch = font_buf[data * bios_modes[current_mode].font_height + i];
for (j=0; j < bios_modes[current_mode].font_width; j++)
{
if (ch & 0x80)
vga_putpixel(screen.x + j, screen.y + i, screen.color_fg);
else
vga_putpixel(screen.x + j, screen.y + i, screen.color_bg);
ch <<= 1;
}
}
x++;
if (x > bios_modes[current_mode].max_x / bios_modes[current_mode].font_width)
{
x = 1;
y++;
if (y > bios_modes[current_mode].max_y / bios_modes[current_mode].font_height)
{
//vga_scroll(1);
y = bios_modes[current_mode].max_y / bios_modes[current_mode].font_height;
}
}
vga_gotoxy(x, y);
}
}
else
{
if (data == '\r')
{
vga_gotoxy (1, y);
return;
}
if (data == '\n')
{
x = 1; y++;
if (y > bios_modes[current_mode].max_y)
{
vga_scroll(1);
y = bios_modes[current_mode].max_y;
}
vga_gotoxy(x, y);
}
else
{
bios_modes[current_mode].video_ptr[cursor_position] = data;
bios_modes[current_mode].video_ptr[cursor_position + 1] = screen.color_fg;
x++;
if (x > bios_modes[current_mode].max_x)
{
x = 1; y++;
if (y > bios_modes[current_mode].max_y)
{
vga_scroll(1);
y = bios_modes[current_mode].max_y;
}
}
vga_gotoxy(x, y);
}
}
}
static unsigned int vga_wherex ( void )
{
if (bios_modes[current_mode].graphic)
{
return (screen.x / bios_modes[current_mode].font_width) + 1;
}
return ( getcuraddr() % bios_modes[current_mode].max_x ) + 1;
}
static unsigned int vga_wherey ( void )
{
if (bios_modes[current_mode].graphic)
{
return (screen.y / bios_modes[current_mode].font_height) + 1;
}
return ( getcuraddr() / bios_modes[current_mode].max_x ) + 1;
}
static unsigned int vga_max_x(void)
{
return bios_modes[current_mode].max_x;
}
static unsigned int vga_max_y(void)
{
return bios_modes[current_mode].max_y;
}
static unsigned long vga_max_col(void)
{
return bios_modes[current_mode].max_cols;
}
static void vga_gotoxy ( unsigned int x, unsigned int y )
{
if (x > 0 && x <= bios_modes[current_mode].max_x && y > 0 && y <= bios_modes[current_mode].max_y)
{
x--; y--;
if (!bios_modes[current_mode].graphic)
{
screen.x = x;
screen.y = y;
setcuraddr ((y * bios_modes[current_mode].max_x) + x);
}
else
{
screen.x = x * bios_modes[current_mode].font_width;
screen.y = y * bios_modes[current_mode].font_height;
}
}
}
// fixed: scroll didn't draw more blank lines if lines > 1
static void vga_scroll(long lines)
{
unsigned tmp1, tmp2, div;
if (lines > 0)
{
if (bios_modes[current_mode].graphic)
{
switch(current_mode)
{
case 0x04:
case 0x05:
case 0x13: div = 4; break;
case 0x06:
case 0x0D:
case 0x0E:
case 0x0F:
case 0x10:
case 0x11:
case 0x12: div = 8; break;
default: div = 8;
}
tmp1 = lines * bios_modes[current_mode].max_x * (bios_modes[current_mode].font_height);
tmp1 /= div;
tmp2 = (bios_modes[current_mode].max_x * bios_modes[current_mode].max_y) - tmp1;
tmp2 /= div;
// Move all the text on the screen up, discard top line(s)
memmove((char *)bios_modes[current_mode].video_ptr,
(char *)bios_modes[current_mode].video_ptr + tmp1, tmp2);
tmp2 = (bios_modes[current_mode].max_x * bios_modes[current_mode].max_y) -
((bios_modes[current_mode].font_height) * lines);
tmp2 /= div;
// Draw a line of spaces at the bottom
memset((char *)bios_modes[current_mode].video_ptr + tmp2, screen.color_bg, tmp1);
vga_gotoxy(1, bios_modes[current_mode].max_y - bios_modes[current_mode].font_height - 1);
}
else
{
tmp1 = lines * bios_modes[current_mode].max_x * 2;
tmp2 = (bios_modes[current_mode].max_x * bios_modes[current_mode].max_y * 2) - tmp1;
// Move all the text on the screen up, discard top line(s)
memmove((char *)bios_modes[current_mode].video_ptr,
(char *)bios_modes[current_mode].video_ptr + tmp1, tmp2);
tmp1 = bios_modes[current_mode].max_x * (bios_modes[current_mode].max_y-1) * 2;
// Draw a line of spaces at the bottom
memsetw((char *)bios_modes[current_mode].video_ptr + tmp1,
(((screen.color_bg << 4) | screen.color_fg) << 8) | ' ', lines * bios_modes[current_mode].max_x);
vga_gotoxy(1, bios_modes[current_mode].max_y);
}
}
}
static void vga_clrscr(void)
{
if (!bios_modes[current_mode].graphic)
{
memsetw((char *)bios_modes[current_mode].video_ptr, MAKEWORD(' ', screen.color_bg),
(bios_modes[current_mode].max_x * bios_modes[current_mode].max_y));
setcuraddr(0);
}
else
// switch(current_mode)
{
// case 0x13:
// {
outportb(SEQ_I, 2); // index map register
outportb(SEQ_D, 0x0F); // allow write access on all levels
memset((char *)bios_modes[current_mode].video_ptr, CL_BLACK, 65535);
screen.x = 1;
screen.y = 1;
// } break;
}
}
// only for vga
// mm = 0 EGA a0000 -bffff
// mm = 1 EGA a0000 -affff
// mm = 2 MDA b0000 -b7fff
// mm = 3 CGA b8000 -b8fff
void vga_mmap(int mm)
{
mm &= 3;
outportb(GRA_I, 6);
if (vga_card == GR_EGA)
outportb(GRA_D, (0x0E & 3) | (mm << 3)); // GRA_D not readable
else
outportb(GRA_D, (inportb(GRA_D) & 3) | (mm << 2)); // bits 2, 3
}
static void vga_putpixel(unsigned int x, unsigned int y, unsigned color)
{
unsigned int offset, mask, col_mask[4] = {0x00, 0x55, 0xAA, 0xFF};
unsigned char tmp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -