📄 vga.c
字号:
switch(current_mode)
{
case 0x04:
case 0x05:
{
offset = (y * bios_modes[current_mode].max_x) + (x / 4) + (8152 * (y & 1));
mask = 0xC0 >> ((x & 3) * 2);
tmp = bios_modes[current_mode].video_ptr[offset];
tmp = (tmp & (mask & 0xFF)) | (col_mask[color] & mask);
bios_modes[current_mode].video_ptr[offset] = tmp;
} break;
case 0x06:
{
offset = ((y * bios_modes[current_mode].max_x) + x) / 8 + (8152 * (y & 1));
mask = 0x80 >> (x & 7);
if (color)
bios_modes[current_mode].video_ptr[offset] |= mask;
else
bios_modes[current_mode].video_ptr[offset] &= (mask & 0xFF);
} break;
case 0x11:
{
offset = ((y * bios_modes[current_mode].max_x) + x) / 8;
mask = 0x80 >> (x & 7);
if (color)
bios_modes[current_mode].video_ptr[offset] |= mask;
else
bios_modes[current_mode].video_ptr[offset] &= (mask & 0xFF);
} break;
case 0x0D:
case 0x0E:
case 0x0F:
case 0x10:
case 0x12:
{
if (current_mode == 0x0F)
{
if (color > 1) // if bit 0, set bit 2
color += 2;
}
offset = ((y * bios_modes[current_mode].max_x) + x) / 8;
mask = 0x80 >> (x & 7);
// load S/R with color
outportb(GRA_I, 0); outportb(GRA_D, color);
// open memory for S/R
outportb(GRA_I, 1); outportb(GRA_D, 0x0F);
// load bitmask
outportb(GRA_I, 8);
outportb(GRA_D, mask);
// write color
bios_modes[current_mode].video_ptr[offset]--;
// reset
outportb(GRA_I, 1); outportb(GRA_D, 0);
outportb(GRA_I, 8); outportb(GRA_D, 0xFF);
} break;
case 0x13:
{
offset = ((y * bios_modes[current_mode].max_x) + x) / 4;
outportb(SEQ_I, 2); // index map register
outportb(SEQ_D, 1 << (x & 3)); // select memory level
bios_modes[current_mode].video_ptr[offset] = color;
} break;
}
}
static unsigned vga_getpixel(unsigned int x, unsigned int y)
{
switch(current_mode)
{
case 0x13:
{
unsigned int offset;
offset = (y * bios_modes[current_mode].max_x * 2) + (x / 4);
outportb(GRA_I, 4); // index map register select
outportb(GRA_D, x & 3); // select memory level
return bios_modes[current_mode].video_ptr[offset];
} break;
}
return 0;
}
static char vga_setmode(unsigned int mode)
{
switch(mode)
{
case 0x00: // text, 40x25, 16 cols
{
write_regs(g_mode_00);
setpalette16();
} break;
case 0x01: // text, 40x25, 16 cols
{
write_regs(g_mode_01);
setpalette16();
} break;
case 0x02: // text, 80x25, 16 cols
{
write_regs(g_mode_02);
setpalette16();
} break;
case 0x03: // text, 80x25, 16 cols
{
write_regs(g_mode_03);
setpalette16();
} break;
case 0x04: // 320x200x4
{
write_regs(g_mode_04);
setpalette4();
} break;
case 0x05: // 320x200x4
{
write_regs(g_mode_05);
/* to make CGA graphics work like other graphics modes... */
/* 1) turn off screwy CGA addressing */
outportb(CRT_I, 0x17);
outportb(CRT_D, inportb(CRT_D) | 1);
/* 2) turn off doublescan */
outportb(CRT_I, 9);
outportb(CRT_D, inportb(CRT_D) & ~0x80);
/* 3) move the framebuffer from B800:0000 to A000:0000 */
outportb(GRA_I, 6);
outportb(GRA_D, inportb(GRA_I) & ~0x0C);
/* set new address */
bios_modes[mode].video_ptr = (char *)(0xA0000);
setpalette4();
} break;
case 0x07: // text, 80x25, 16 cols
{
write_regs(g_mode_07);
} break;
case 0x0D: // 320x200x16
{
write_regs(g_mode_0D);
setpalette16();
} break;
case 0x0E: // 640x200x16
{
write_regs(g_mode_0E);
setpalette16();
} break;
case 0x0F: // 640x350xMono
{
write_regs(g_mode_0F);
} break;
case 0x10: // 640x350x16
{
write_regs(g_mode_10);
setpalette16();
} break;
case 0x11: // 640x480x2
{
write_regs(g_mode_11);
} break;
case 0x12: // 640x480x16
{
write_regs(g_mode_12);
setpalette16();
} break;
case 0x13: // 320x200x256 aka ModeX
{
write_regs(g_mode_13);
setpalette256();
// 1) turn off Chain-4 addressing
// bit 3, memory mode register = 0
outportb(SEQ_I, 0x04);
outportb(SEQ_D, inportb(SEQ_D) & ~0x08);
// 2) turn off doubleword clocking
// bit 6, underline location register = 0, double word mode off
outportb(CRT_I, 0x14);
outportb(CRT_D, inportb(CRT_D) & ~0x40);
// 3) turn off word clocking in case it's on
// bit 6, mode control register = 1, byte mode on
outportb(CRT_I, 0x17);
outportb(CRT_D, inportb(CRT_D) | 0x40);
} break;
default:
{
return -0x01;
}
}
if (bios_modes[mode].font_height >= 16)
memcpy(font_buf, g_8x16_font, 4096);
else
memcpy(font_buf, g_8x8_font, 2048);
if (bios_modes[current_mode].graphic && graphic_card > GR_EGA)
{
// restore font data in plane 2
outportb(SEQ_I, 0x02);
outportb(SEQ_D, 0x04);
// restore font data in plane 3, trident
outportb(SEQ_I, 0x02);
outportb(SEQ_D, 0x08);
}
current_mode = mode;
/* tell the BIOS what we've done, so BIOS text output works OK */
// pokew(0x40, 0x4A, bios_modes[mode].max_x); /* columns on screen */
// pokew(0x40, 0x4C, bios_modes[mode].max_x * bios_modes[mode].max_y * 2); /* framebuffer size */
// pokew(0x40, 0x50, 0); /* cursor pos'n */
// pokeb(0x40, 0x60, bios_modes[mode].font_height - 1); /* cursor shape */
// pokeb(0x40, 0x61, bios_modes[mode].font_height - 2);
// pokeb(0x40, 0x84, bios_modes[mode].max_x - 1); /* rows on screen - 1 */
// pokeb(0x40, 0x85, bios_modes[mode].font_height); /* char height */
return 0x00;
}
static unsigned int vga_getmode(void)
{
return current_mode;
}
char find6845(unsigned int addr)
{
unsigned char tmp, result;
outportb(addr, 0x0F);
tmp = inportb(addr + 1);
outportb(addr, 0x0F);
outportb(addr + 1, 0x66);
delay(100);
result = (inportb(addr + 1) == 0x66);
outportb(addr + 1, tmp);
return result;
}
char findMono(void)
{
unsigned char tmp1, tmp2;
unsigned int timeout;
if (find6845(CRT_IM))
{
tmp1 = inportb(CRT_IM + 6) & 0x80;
timeout = 100;
do {
tmp2 = inportb(CRT_IM + 6) & 0x80;
delay(1);
} while (tmp1 != tmp2 || ! timeout--);
if (tmp1 != tmp2)
return GR_HERC;
return GR_MONO;
}
return GR_UNKNOWN;
}
char findCGA(void)
{
return find6845(CRT_IC) ? GR_CGA : GR_UNKNOWN;
}
static unsigned int vga_test(void)
{
unsigned char save, back;
if (vga_card == GR_UNKNOWN)
{ // Check if a DAC is present
save = inportb(PEL_IW);
graphic_delay();
outportb(PEL_IW, ~ save);
graphic_delay();
back = inportb(PEL_IW);
graphic_delay();
outportb(PEL_IW, save);
save = ~save;
vga_card = (back == save) ? GR_VGA : GR_EGA;
}
if (vga_card == GR_EGA)
{
vga_card = findMono();
if (vga_card == GR_UNKNOWN)
vga_card = findCGA();
}
return 1; // always true
}
static unsigned int vga_memory(void)
{
return 32;
}
static char * vga_get_name(void)
{
switch(vga_card)
{
case GR_UNKNOWN: return "Unknown";
case GR_MONO: return "Mono";
case GR_HERC: return "HERC";
case GR_CGA: return "CGA";
case GR_EGA: return "EGA";
case GR_VGA: return "VGA";
}
return "Unknown";
}
GraphicDriver vga_driver =
{
vga_test,
vga_get_name,
vga_memory,
vga_setmode,
vga_getmode,
NULL,
NULL,
NULL,
NULL,
vga_putch,
vga_wherex,
vga_wherey,
vga_max_x,
vga_max_y,
vga_max_col,
vga_gotoxy,
vga_scroll,
vga_clrscr
};
char Check_VGA(GraphicDriver * driver)
{
*driver = vga_driver;
return (vga_test());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -