我正在编写一个DOS游戏框架,以便更好地学习C和对旧硬件编程的一般兴趣(特别是在我长大的系统上)。
我正在尝试实现一个双缓冲系统但是我在分配一个指向320 * 200数组的远指针时遇到了麻烦。
起初我试图使用malloc,但发现它只能分配到64kb以下。我读过你需要使用farmalloc(malloc返回NULL)并正确分配。但是,当运行_fmemset或_fmemcpy时......整个系统会冻结。
backBuffer = (unsigned char far*) farmalloc(64000);
什么时候交换缓冲区我用
_fmemcpy(VGA, backBuffer, 64000);
程序正在使用小内存模型。
答案 0 :(得分:8)
非常有趣的帖子,我也非常喜欢旧硬件。
您是否尝试过编译中型或大型模型以检查代码是否正常运行?
您确定指向VGA显示内存的指针已正确初始化吗?
我记得在那些日子里,使用内存副本交换屏幕缓冲区非常缓慢,更不用说你必须等待垂直回扫期开始复制内存。 (我有一块裸机的VGA卡,所以也许你的硬件更好,而且延迟超出了可接受范围。)
如果您有兴趣,我强烈建议您阅读Michael Abrash的Mode-X专栏。
模式-X及其衍生物是Michael Abrash首先记录的替代图形模式。基本上他们是256色13H模式的黑客,你可以通过调整VGA卡中的一些寄存器来激活。
一旦激活,有两大优势:
实现双倍甚至三倍缓冲是一件轻而易举的事,因为你可以直接写入非活动缓冲区并激活它只需更改vga卡中的寄存器,根本不需要记忆!(你仍然需要等待垂直回扫,否则会有一个丑陋的闪烁)
缺点是这种模式更难编程,基本上,使用mode-X现在单个存储器地址被映射到四个连续像素,因此,单个像素写入实际上会一次改变四个像素。 (这是多边形填充程序的很好的加速度!)。
如果要更改单个像素,则必须设置“像素掩码”(也称为VGA卡寄存器),指定在绘制像素之前,内存写入会影响四个像素中的哪一个。
如果天真地完成,这很慢,因为绘制的每个像素都需要设置掩码。通常我们直观地倾向于从左到右,从上到下绘制事物(因为这正是视频内存在VGA模式13H上的映射方式),但是我们Mode-X程序员学会了“旋转范例”要快得多,那就是,我们从上到下,从左到右画出东西。
为什么呢?因为这允许我们为每个绘制的列只修改一次像素掩码! 这是一些伪代码:
天真,直观的编程
pixelptr = start of screen memory
foreach row
foreach column
adjust pixel mask
write pixel value
pixelptr+= 1 // advance pointer to next pixel to the left
next
next
旋转编程模式
[编辑1:添加了缺少的步骤,其中指针必须移动到下一列的顶部]
[编辑2:修正,我正在添加320以前进到下一行,实际上这应该除以4,因为视频内存地址的连续增量将映射到右边的下四个像素的组之前的,四像素组]
for each column
pixelptr = start of screen memory + current column index
adjust pixel mask // same mask applies to every pixel in the same column!
for each row
write pixel value
pixelptr += (320 / 4) // advance pointer to next pixel, to the bottom
next
next
所有涉及的步骤和注册地址都在我提供的Michael Abrash专栏的链接中详细说明。这是古老的东西,但我打赌你会发现它很有趣!
干杯!