9

我正在编写一个 DOS 游戏框架,以更好地学习 C 语言,并且对在旧硬件上编程(尤其是在我长大的系统上)产生普遍兴趣。

我正在尝试实现双缓冲系统,但在将远指针分配给 320*200 数组时遇到问题。

起初我尝试使用 malloc,但发现它只能分配 64kb 以下。我读到您需要使用farmalloc(malloc返回NULL)并且它分配正确。但是,当 _fmemset 或 _fmemcpy 运行时....整个系统冻结。

backBuffer = (unsigned char far*) farmalloc(64000);

什么时候交换我使用的缓冲区

_fmemcpy(VGA, backBuffer, 64000);

程序正在使用小内存模型。

4

1 回答 1

8

很有趣的帖子,我也很喜欢旧硬件。

  • 您是否尝试过在中型或大型模型中编译以检查代码是否正确运行?

  • 您确定指向 VGA 显存的指针已正确初始化吗?

我记得在那些日子里,使用内存副本来交换屏幕缓冲区非常缓慢,更不用说您必须等待垂直回溯期才能开始复制内存。(我有一个基本的 VGA 卡,所以也许你的硬件更好,延迟是可以接受的)。

如果您有兴趣,我强烈建议您阅读 Michael Abrash 的Mode-X专栏。

Mode-X 及其衍生物是由 Michael Abrash 首次记录的替代图形模式。基本上,它们是对 256 色 13H 模式的破解,您可以通过调整 VGA 卡中的一些寄存器来激活该模式。

一旦激活,有两个很大的优势:

  1. 四页显存
  2. 方形像素(在 320x240 的原始 ModeX 中),(绘制的圆圈看起来像一个圆圈,而不是椭圆)

实现双甚至三缓冲区是轻而易举的事,因为您可以直接写入非活动缓冲区并激活它,只需更改 vga 卡中的寄存器,根本不需要 memcopy!(还是需要等待垂直回扫,否则会出现难看的闪烁)

缺点是这种模式更难编程,基本上,模式-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

轮换编程模式

[Edit1:添加了必须将指针移动到下一列顶部的缺失步骤]

[Edit2:更正,我添加 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 专栏的链接中都有详细说明。这是古老的东西,但我打赌你会发现它很迷人!

干杯!

于 2012-09-14T17:36:38.433 回答