v1.6.0版本里新增的VGA驱动程式,是参考的 .....modes.c 对应的C源代码,这是一个运行于DOS系统下的C程式,你可以在DOSBOX模拟器中,配合DJGPP工具来编译运行和调试该程式。这个C程式通过直接读写VGA寄存器来切换不同的图形模式与文本模式...

    v1.6.0版本的项目地址:

    github.com地址:https://github.com/zenglong/zenglOX (只包含git提交上来的源代码)

    Dropbox地址:点此进入Dropbox网盘  这两个版本位于zenglOX_v1.6.0的文件夹中,文件夹里的zip压缩包为源代码,readme.txt为版本的简单说明。

    Google Drive地址:点此进入Google Drive云端硬盘 对应也是zenglOX_v1.6.0的文件夹。

    sourceforge地址:https://sourceforge.net/projects/zenglox/files  对应也是zenglOX_v1.6.0的文件夹。

    Dropbox与Google Drive如果正常途径访问不了,则需要使用代理访问。

    和zenglOX编译调试相关的内容,请参考v0.0.1版本对应的文章。

    v1.6.0版本里新增的VGA驱动程式,是参考的 http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c 该链接对应的C源代码,这是一个运行于DOS系统下的C程式,你可以在DOSBOX模拟器中,配合DJGPP工具来编译运行和调试该程式。这个C程式通过直接读写VGA寄存器来切换不同的图形模式与文本模式,由于需要设置61个VGA寄存器才能完成不同模式的切换,因此,这61个寄存器的具体需要设置的值应该是,先利用BIOS中断切换到对应的图形模式,再通过modes.c文件里的read_regs与dump_regs函数将不同模式下的寄存器值反向读取和显示出来,最后就可以直接利用这些反向读取出来的值来直接对VGA寄存器进行设置,就可以达到与BIOS中断相同的效果。

    当然,modes.c文件里还对某些反向读取出来的值做了些简单的修改,已达到某些特殊的效果,例如,320x200x4的图形模式对应的g_320x200x4数组里,就对GC即图形控制器里的索引值为6的混合寄存器进行修改,从而将该模式的显存起始地址修改为0xA0000,从而避免了和文本模式的B8000相冲突(BIOS的05h模式下默认是B8000的起始地址),同时还将显存的寻址模式改为了线性寻址(BIOS的05h模式是CGA的非线性映射),有关混合寄存器的详情可以参考下面要提到的 EGA_VGA_Program_Manual.pdf 电子文档的第78页(该页数是PDF电子档分页输入框中的页数),有关CGA非线性映射的内容可以参考该PDF文档的第32页,下面内容中提到的PDF电子档都指的是该PDF文档。

    zenglOX对modes.c源代码进行了简单的修改,并移植到当前版本的zlox_vga.c文件里,从而作为保护模式下,VGA图形模式的驱动程式(保护模式下,无法再调用BIOS中断,所以只能通过I/O端口读写VGA寄存器,来完成模式的切换以及其他的和VGA相关的各种操作)。

    在之前"zenglOX v0.0.2 VGA输出显示字符串"的文章中,对VGA相关的寄存器做过一个简单的介绍,但是当时只是对CRT控制器里的光标位置寄存器进行设置,以控制文本模式下光标的位置,在v0.0.2版本对应的网盘中,有一个 EGA_VGA_Program_Manual.pdf 的电子文档,这是VGA的编程手册,要理解zlox_vga.c文件里涉及到的各寄存器的含义,就必须先阅读该电子文档,好在该文档是中文的,简单的通读一遍,问题应该不大。

    下面就对zlox_vga.c文件里的比较重要的代码做个介绍。

    以320x200x256的图形模式为例来进行说明。该图形模式的配置字节数组为vga_320x200x256 :

// 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
};

.................................................


    上面代码里,棕色的注释是这里额外添加的,在源文件中暂时没有。

    前面提到过,该数组里的配置数据是在DOS系统下,调用BIOS中断后,反向读取出来的,如果你想了解每个寄存器的作用,以及寄存器里各二进制位的含义,可以在PDF电子档里查看到(上面注释中已经给出了具体的页数)。

    在有了配置数组后,只需将这些数据依次写入到各个寄存器中即可,zlox_vga.c文件是通过zlox_vga_write_regs函数来完成数据的写入操作的:

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);
}


    从上面的代码中可以看到,对各寄存器进行写入操作,都是先向索引寄存器写入数值,以选中需要操作的寄存器,再向数据寄存器中写入具体的数值来完成的。

    上面函数的代码在对CRTC(CRT控制器)的寄存器进行写入操作之前,需要先对CRT控制器里的某些寄存器进行些必要的设置,例如,CRT控制器的索引值为0x3的寄存器,该寄存器是水平消隐信号结尾寄存器(可以参考PDF电子档的第52页),当对VGA进行设置时,该寄存器的最高位必须是1,因此,上面函数的如下代码:

zlox_outb(ZLOX_VGA_CRTC_INDEX, 0x03);
zlox_outb(ZLOX_VGA_CRTC_DATA, zlox_inb(ZLOX_VGA_CRTC_DATA) | 0x80);


    就将该寄存器的最高位设置为了1 。

    另外,CRT控制器的索引值为0x11的寄存器,是垂直回扫结尾寄存器(可以参考PDF电子档的第54页),当该寄存器的最高位为1时,会对CRT控制器的索引为0至7的寄存器实行写保护,写保护下就无法对这几个寄存器进行数据写入操作,因此需要将该寄存器的最高位设置为0 ,就有了函数里的如下代码:

zlox_outb(ZLOX_VGA_CRTC_INDEX, 0x11);
zlox_outb(ZLOX_VGA_CRTC_DATA, zlox_inb(ZLOX_VGA_CRTC_DATA) & ~0x80);


    上面代码将0x11寄存器的最高位清零,从而解除对索引为0到7的寄存器的写保护,后面才能将配置数据写入到这几个寄存器中。

    在将配置数据写入到各个寄存器中后,函数的最后有如下两条代码:

/* lock 16-color palette and unblank display */
	(ZLOX_VOID)zlox_inb(ZLOX_VGA_INSTAT_READ);
	zlox_outb(ZLOX_VGA_AC_INDEX, 0x20);


    要理解上面两条代码的含义,可以参见PDF电子档的第80页,该页对属性控制器的索引寄存器的各二进制位都进行了介绍,通过将索引寄存器的位5设置为1,就可以lock锁住调色板,同时让屏幕可以显示。属性控制器的索引值为0x0到0xF的寄存器是调色板寄存器,在前面将配置数组里的数据写入到调色板寄存器后,必须将调色板锁住,屏幕才可以进行输出显示,因此上面代码就将0x20(该值的位5为1)设置到ZLOX_VGA_AC_INDEX对应的属性控制器的索引寄存器中,以锁住调色板。

    上面代码在写入索引寄存器前,有个读ZLOX_VGA_INSTAT_READ的操作,ZLOX_VGA_INSTAT_READ的宏值为0x3DA,前面介绍过,当对3DA进行读操作后,就可以初始化内部触发器,内部触发器被初始化后,对ZLOX_VGA_AC_INDEX即0x3C0的写入操作就会被导向索引寄存器。

    对于VGA的320x200x256与640x480x16的图形模式,只需通过上面的zlox_vga_write_regs函数将配置数组里的数据写入到各个寄存器中,即可切换到对应的图形模式,如zlox_vga.c文件里的zlox_vga_set_mode函数:

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;
}


    但是要从图形模式切换回文本模式,除了需要将配置数据写入到寄存器中,还需要恢复字体与原来0xB8000起始的显存里的内容数据,因为切换到图形模式时,会破坏掉原来文本模式中的字体数据与内容数据。

    文本模式下,显存里的ASCII码,前景色、背景色等属性值,以及字体的点阵位图分别存储在三个平面中,这几个平面的起始地址都是0xB8000,通过对图形控制器与时钟发生器里的相关寄存器进行写入操作,就可以对不同的面进行读写操作。文本模式的显存里的ASCII码位于平面0里,属性值则位于平面1里,如下图所示:


图1(PDF电子档的第28页)

    字体的点阵位图则位于平面2,如下面两幅图所示:
 

图2(PDF电子档的第28页)
 
 

图3(PDF电子档的第30页)

    zlox_vga.c文件的zlox_vga_write_font函数就用于对平面2里的字体点阵数据进行设置:

/*****************************************************************************
*****************************************************************************/
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;
	}
.....................................................
}


    上面的zlox_vga_write_font函数通过调用zlox_vga_set_plane(2)函数将当前的读写平面设置为平面2 ,这样后面的for循环里,就可以将字体数据写入到平面2里了。

    VGA切换到文本模式的代码位于zlox_vga.c文件的zlox_vga_set_text_mode函数中:

/*****************************************************************************
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;
	}
}


    上面的函数在调用zlox_vga_write_regs函数将文本模式的配置数组写入到寄存器后,会再调用zlox_vga_write_font函数将vga_8x16_font数组里的字体点阵数据写入到平面2,以恢复原来的字体数据,最后还会通过zlox_memcpy函数,将vga_text_content_backup即切换到图形模式时,备份的内容数据给恢复到当前的显存中。

    以上就是切换VGA图形或文本模式相关的内容。

    在切换到VGA图形模式后,就可以通过对显存进行读写操作,来进行绘图了。不过,VGA不同的图形模式下,像素在显存里的存储方式也是不同的。

    在320x200x256的模式下,显存起始地址为0xA0000,显存中的每个字节对应一个像素,其中的第一个字节对应为左上角的像素。在BIOS里,这种320x200x256的模式也被称作13h模式,详情可以参考PDF电子档的第36页(该页的"方式 13HEX ---- 256色的图形"的部分),该模式仅用于VGA卡,可在低分辨率(320个水平像素,200个垂直像素)的条件下同时支持256种颜色,显存是采用线性映射的方式,如下图所示:


图4

    上图是作者重新画的,没有使用PDF电子档第36页的图2-18,因为2-18画的是错误的,这个PDF电子档唯一不足的地方就是,文章里的插图有些画的不对。

    zenglOX里新增的vga工具,在320x200x256的模式下,就是根据上图的公式在屏幕上绘制像素的,如下所示(这段代码位于build_initrd_img目录的vga.c文件中):

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;
	}
.................................................
}


    zenglOX的VGA图形模式的驱动程式里,除了320x200x256的模式外,还有一种640x480x16的模式,该模式也就是BIOS里常用的方式12h,方式12h与方式10h除了在垂直像素上有些不同外(12h方式有480个垂直像素,10h则只有350个垂直像素),其他的,如像素在显存中的存储方式等都是一样的,可以参考PDF电子档的第35页,这种图形模式下,4个颜色平面都被用到了,每个像素在每个平面上各占一位,结果就是每个像素占4位,因此,可以同时显示16种不同的颜色,如下图所示:


图5(PDF电子档的第35页)

    根据上图里字节地址与位地址的公式,就有了build_initrd_img目录中vga.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;
}


    上面代码里,buffer是用户分配的缓冲,在640x480x16模式下,该buffer缓冲里包含了平面0到平面4里的所有数据,每个平面为plane_size大小。在将buffer里缓冲的4个平面的像素数据都写好后,就可以通过syscall_vga_update_screen系统调用,来将buffer缓冲里的数据更新到显存实际的4个平面中,该系统调用最终会调用zlox_vga.c文件的zlox_vga_update_screen函数来完成操作:

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;
}


    上面代码中,在for循环里,会先通过zlox_vga_set_plane函数设置需要写入的颜色平面,再通过zlox_memcpy函数将buffer缓冲的不同平面的数据给拷贝到显存对应的实际平面里,从而完成更新显存的操作,更新的数据会实时显示到屏幕上。

    此外,在build_initrd_img目录的vga.c文件里,还有一个名为mono_img的字节数组:

// 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, 
..................................................
};


    该数组是从isodir目录的qrcode.bmp位图文件里,提取出来的位图数据。作者是使用WinHex工具提取出位图数据的:


图6

    有了位图数据,再配合vga.c文件的draw_mono_img函数,就可以将这个二维码图片给显示出来了:

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;
}


    之所以采用提取位图数据的方式,是因为这样可以避免读取文件的操作。

    有关bmp位图文件的格式,可以参考 http://www.cnblogs.com/xiehy/archive/2011/06/07/2074405.html 该链接对应的文章(如果该链接失效,可以参考 http://en.wikipedia.org/wiki/BMP_file_format 该链接对应的文章)。

    在该版本的zenglOX命令行下,可以直接输入vga命令,来测试320x200x256的图形模式,如下图所示:


图7

    在出现二维码图片后,可以用上下左右键来移动该二维码到合适的位置,可以用手机软件扫描二维码进入www.zengl.com官网,最后可以按ESC键退出该程式,并返回到文本模式。

    如果在vga后面添加参数640,就可以进入640x480x16的图形模式,如下图所示:
 

图8

    可以看到,由于640x480x16模式的分辨率比320的高,因此,字体比较清晰,没那么多的锯齿。

    这些图形模式在bochs与virtualbox虚拟机中的运行速度明显比vmware下运行的慢,因此,vmware确实很适合做图形界面的开发。

    以上就是v1.6.0版本的相关内容。

    OK,就到这里,休息,休息一下 o(∩_∩)o~~
 
上下篇

下一篇: zenglOX v2.0.0 E1000系列网卡驱动, PCI驱动, PS/2控制器驱动, 以太网,ARP,IP,UDP,DHCP,ICMP协议, dhcp,arp,ipconf,ping,lspci命令行程式

上一篇: zenglOX v1.5.0 zenglfs文件系统, MBR主引导记录, fdisk分区工具及format磁盘格式化工具, file文件目录读写工具等

相关文章

zenglOX v2.2.0 ee(easy editor)文本编辑器 C标准库函数 uheap(单独的用户堆空间) atapi驱动BUG zenglfs文件系统BUG 分页BUG 堆算法BUG等修复

zenglOX v0.0.2 VGA输出显示字符串

zenglOX v0.0.10 Keyboard(获取键盘的输入)

zenglOX v0.0.5 分页

zenglOX v0.0.3 初始化GDT和IDT

zenglOX v3.0.2 PNG(Portable Network Graphics) and BUG Fix