v1.6.0版本里新增的VGA驱动程式,是参考的 .....modes.c 对应的C源代码,这是一个运行于DOS系统下的C程式,你可以在DOSBOX模拟器中,配合DJGPP工具来编译运行和调试该程式。这个C程式通过直接读写VGA寄存器来切换不同的图形模式与文本模式...
// zlox_vga.c -- something relate to vga #include "zlox_kheap.h" #include "zlox_vga.h" ................................................. ZLOX_UINT8 vga_320x200x256[] = { /* MISC */ /*********** 混合输出寄存器(I/O地址为3C2) 请参考上面提到的PDF电子档的第46页 ************/ 0x63, /* SEQ */ /*********** 时序发生器,包含5个输出寄存器 这5个寄存器复用到两个I/O地址(3C4和3C5) 3C4用于索引寄存器,3C5用于对选中的寄存器 进行读写操作,请参考PDF电子档的第63页 ************/ 0x03, 0x01, 0x0F, 0x00, 0x0E, /* CRTC */ /*********** CRT控制器,一共包含25个寄存器 复用到两个I/O地址:单色模式下为 3B4用于索引,3B5用于读写数据。 彩色模式下为3D4用于索引,3D5用于 读写数据。请参考PDF电子档的第50页 ************/ 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, 0xFF, /* GC */ /*********** 图形控制器,一共包含9个寄存器 复用到两个I/O地址:3CE用于索引, 3CF用于读写数据。 请参考PDF电子档的第68页 ************/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, /* AC */ /*********** 属性控制器,一共包含21个寄存器 只复用到一个I/O地址:3C0 有一个内部触发器,当对3BA(单色模式)或 3DA(彩色模式)进行一次读操作后,该内部触发器 就会被初始化,初始化后,对3C0的第一次写入操作会被 用于索引寄存器,第二次写入操作时,会被 用于对索引选中的寄存器进行数据读写操作。 这样使用3C0这一个I/O地址就可以对 属性控制器里的21个寄存器进行读写操作了 请参考PDF电子档的第80页 ************/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00 }; ................................................. |
ZLOX_VOID zlox_vga_write_regs(ZLOX_UINT8 *regs) { ZLOX_UINT32 i; /* write MISCELLANEOUS reg */ zlox_outb(ZLOX_VGA_MISC_WRITE, *regs); regs++; /* write SEQUENCER regs */ for(i = 0; i < ZLOX_VGA_NUM_SEQ_REGS; i++) { zlox_outb(ZLOX_VGA_SEQ_INDEX, i); zlox_outb(ZLOX_VGA_SEQ_DATA, *regs); regs++; } /* unlock CRTC registers */ zlox_outb(ZLOX_VGA_CRTC_INDEX, 0x03); zlox_outb(ZLOX_VGA_CRTC_DATA, zlox_inb(ZLOX_VGA_CRTC_DATA) | 0x80); zlox_outb(ZLOX_VGA_CRTC_INDEX, 0x11); zlox_outb(ZLOX_VGA_CRTC_DATA, zlox_inb(ZLOX_VGA_CRTC_DATA) & ~0x80); /* make sure they remain unlocked */ regs[0x03] |= 0x80; regs[0x11] &= ~0x80; /* write CRTC regs */ for(i = 0; i < ZLOX_VGA_NUM_CRTC_REGS; i++) { zlox_outb(ZLOX_VGA_CRTC_INDEX, i); zlox_outb(ZLOX_VGA_CRTC_DATA, *regs); regs++; } /* write GRAPHICS CONTROLLER regs */ for(i = 0; i < ZLOX_VGA_NUM_GC_REGS; i++) { zlox_outb(ZLOX_VGA_GC_INDEX, i); zlox_outb(ZLOX_VGA_GC_DATA, *regs); regs++; } /* write ATTRIBUTE CONTROLLER regs */ for(i = 0; i < ZLOX_VGA_NUM_AC_REGS; i++) { (ZLOX_VOID)zlox_inb(ZLOX_VGA_INSTAT_READ); zlox_outb(ZLOX_VGA_AC_INDEX, i); zlox_outb(ZLOX_VGA_AC_WRITE, *regs); regs++; } /* lock 16-color palette and unblank display */ (ZLOX_VOID)zlox_inb(ZLOX_VGA_INSTAT_READ); zlox_outb(ZLOX_VGA_AC_INDEX, 0x20); } |
zlox_outb(ZLOX_VGA_CRTC_INDEX, 0x03); zlox_outb(ZLOX_VGA_CRTC_DATA, zlox_inb(ZLOX_VGA_CRTC_DATA) | 0x80); |
zlox_outb(ZLOX_VGA_CRTC_INDEX, 0x11); zlox_outb(ZLOX_VGA_CRTC_DATA, zlox_inb(ZLOX_VGA_CRTC_DATA) & ~0x80); |
/* lock 16-color palette and unblank display */
(ZLOX_VOID)zlox_inb(ZLOX_VGA_INSTAT_READ);
zlox_outb(ZLOX_VGA_AC_INDEX, 0x20);
|
ZLOX_SINT32 zlox_vga_set_mode(ZLOX_UINT32 mode) { ZLOX_UINT8 * video_memory; switch(mode) { ........................................................... case ZLOX_VGA_MODE_320X200X256: ........................................................... zlox_vga_write_regs(vga_320x200x256); vga_current_mode = ZLOX_VGA_MODE_320X200X256; return 0; break; case ZLOX_VGA_MODE_640X480X16: ........................................................... zlox_vga_write_regs(vga_640x480x16); vga_current_mode = ZLOX_VGA_MODE_640X480X16; return 0; break; default: break; } return -1; } |
/***************************************************************************** *****************************************************************************/ static ZLOX_VOID zlox_vga_set_plane(ZLOX_UINT32 p) { ZLOX_UINT8 pmask; p &= 3; pmask = 1 << p; /* set read plane */ zlox_outb(ZLOX_VGA_GC_INDEX, 4); zlox_outb(ZLOX_VGA_GC_DATA, p); /* set write plane */ zlox_outb(ZLOX_VGA_SEQ_INDEX, 2); zlox_outb(ZLOX_VGA_SEQ_DATA, pmask); } /***************************************************************************** VGA framebuffer is at A000:0000, B000:0000, or B800:0000 depending on bits in GC 6 *****************************************************************************/ static ZLOX_UINT32 zlox_vga_get_fb_seg() { ZLOX_UINT32 seg; zlox_outb(ZLOX_VGA_GC_INDEX, 6); seg = zlox_inb(ZLOX_VGA_GC_DATA); 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; } /***************************************************************************** write font to plane P4 (assuming planes are named P1, P2, P4, P8) *****************************************************************************/ static ZLOX_VOID zlox_vga_write_font(ZLOX_UINT8 *buf, ZLOX_UINT32 font_height) { ZLOX_UINT8 seq2, seq4, gc4, gc5, gc6; ZLOX_UINT32 i; ..................................................... /* write font to plane P4 */ zlox_vga_set_plane(2); /* write font 0 */ ZLOX_UINT8 * dest = (ZLOX_UINT8 *)zlox_vga_get_fb_seg(); for(i = 0; i < 256; i++) { zlox_memcpy(dest + i * 32, buf, font_height); buf += font_height; } ..................................................... } |
/***************************************************************************** SET TEXT MODES *****************************************************************************/ ZLOX_VOID zlox_vga_set_text_mode() { ZLOX_UINT8 * video_memory; zlox_vga_write_regs(vga_80x25_text); /* set font */ zlox_vga_write_font(vga_8x16_font, 16); if(vga_text_content_backup != ZLOX_NULL) { video_memory = (ZLOX_UINT8 *)zlox_vga_get_fb_seg(); zlox_memcpy(video_memory, vga_text_content_backup, 80 * 25 * 2); zlox_kfree(vga_text_content_backup); vga_text_content_backup = ZLOX_NULL; } } |
int plot_pixel(UINT8 * buffer ,int x, int y, UINT8 c) { int wd_in_bytes; int off; if(vga_mode == VGA_MODE_320X200X256) { wd_in_bytes = 320; off = wd_in_bytes * y + x; buffer[off] = c; } ................................................. } |
int plot_pixel(UINT8 * buffer ,int x, int y, UINT8 c) { int wd_in_bytes; int off; ..................................................... else if(vga_mode == VGA_MODE_640X480X16) { int pmask, p, plane_size = (640 * 480) / 8; UINT8 mask; wd_in_bytes = 640 / 8; off = wd_in_bytes * y + x / 8; x = (x & 7) * 1; mask = 0x80; asm volatile ("shrb %%cl, %%al" :"=a"(mask):"c"(x),"0"(mask)); //mask = 0x80 >> x; pmask = 1; for(p = 0; p < 4; p++) { if(pmask & c) buffer[off] |= mask; else buffer[off] &= ~mask; pmask <<= 1; buffer += plane_size; } } return 0; } |
ZLOX_SINT32 zlox_vga_update_screen(ZLOX_UINT8 * buffer, ZLOX_UINT32 buffer_size) { ZLOX_UINT8 * video_memory; switch(vga_current_mode) { ........................................................ case ZLOX_VGA_MODE_640X480X16: video_memory = (ZLOX_UINT8 *)zlox_vga_get_fb_seg(); ZLOX_UINT32 tmp_size = buffer_size, plane_size = (640 * 480) / 8, i; for(i=0; i < 4 ;i++) { zlox_vga_set_plane(i); if(tmp_size <= plane_size) { zlox_memcpy(video_memory, buffer, tmp_size); break; } else { zlox_memcpy(video_memory, buffer, plane_size); tmp_size -= plane_size; buffer += plane_size; } } return 0; break; default: break; } return -1; } |
// vga.c -- 测试vga图形界面 #include "common.h" #include "syscall.h" #include "vga.h" #include "task.h" //Byte array of bitmap of 64 x 64 px: UINT8 mono_img [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC7, 0xFF, 0xFC, 0x00, 0x1D, 0xC0, 0x1F, 0xFF, 0xC7, 0xFF, 0xFC, 0x1F, 0x1D, 0xD8, 0x1C, 0x01, 0xC0, 0x00, 0x7C, 0x1F, 0x1D, 0xD8, 0x1D, 0xFD, 0xC1, 0xDD, 0xFF, 0x7F, 0xDD, 0xF8, 0x1D, 0xFD, 0xC1, 0xDD, 0xF7, 0x71, 0xDC, 0x70, 0x1D, 0xFD, 0xC7, 0xFD, 0xF7, 0xFF, 0xFF, 0xF0, 0x1D, 0xFD, 0xC7, 0x71, 0xF1, 0xFF, 0x77, 0xF0, 0x1D, 0xFD, 0xC7, 0xF1, 0xF1, 0xFF, 0xFF, 0xF0, 0x1D, 0xFD, 0xC7, 0xF0, 0x01, 0xFF, 0xFC, 0x70, .................................................. }; |
int draw_mono_img(UINT8 * buffer, UINT8 * img, int color, int x, int y, int w, int h) { int c,d,i,j,z, wc = w / 8; for(c = (h - 1),d=0;c >= 0;c--,d++) { UINT8 * tmp_img = img + wc * c; for(i=0;i < wc;i++) for(j = 7,z = 0;j >= 0;j--,z++) if(tmp_img[i] & (1 << j)) plot_pixel(buffer, x + z + i * 8, y + d, (UINT8)color); } return 0; } |