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 v1.2.0 ISO 9660文件系统

zenglOX v1.0.0 shell(命令行程式及各种小工具)

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

zenglOX v2.4.0 DMA(Direct Memory Access)

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

zenglOX v0.0.6 使用Heap(堆)动态分配和释放内存