需要帮助在Borland C++ 3.0上分配远指针

Ion*_*non 9 c memory pointers dos

我正在编写一个DOS游戏框架来更好地学习C,并对旧硬件上的编程感兴趣(特别是在我长大的系统上).

我正在尝试实现一个双缓冲系统,但我无法分配一个指向320*200阵列的远指针.

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

backBuffer = (unsigned char far*) farmalloc(64000);
Run Code Online (Sandbox Code Playgroud)

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

_fmemcpy(VGA, backBuffer, 64000);
Run Code Online (Sandbox Code Playgroud)

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

小智 8

非常有趣的帖子,我也非常喜欢旧硬件.

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

  • 你确定正确初始化了VGA显示内存的指针吗?

我记得在那些日子里,使用内存副本来交换屏幕缓冲区非常缓慢,更不用说你必须等待垂直回扫期开始复制内存.(我有一块裸机的VGA卡,所以也许你的硬件更好,延迟超过可接受的程度).

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

模式-X及其衍生物是Michael Abrash首先记录的替代图形模式.基本上他们是256色13H模式的黑客,你可以通过调整VGA卡中的一些寄存器来激活.

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

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

实现双倍甚至三倍缓冲区是轻而易举的,因为您可以直接写入非活动缓冲区并激活它只需更改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
Run Code Online (Sandbox Code Playgroud)

旋转编程模式

[Edit1:添加了缺少的步骤,其中指针必须移动到下一列的顶部]

[编辑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
Run Code Online (Sandbox Code Playgroud)

所有涉及的步骤和寄存器地址都在我提供的Michael Abrash列的链接中详细说明.这是古老的东西,但我打赌你会发现它很有趣!

干杯!