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

标签 c memory pointers dos

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

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

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

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

何时需要交换我使用的缓冲区

_fmemcpy(VGA, backBuffer, 64000);

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

最佳答案

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

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

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

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

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

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

激活后,有两大优势:

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

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

缺点是这种模式更难编程,基本上,模式-X 现在单个内存地址映射到四个连续像素,因此,单个像素写入实际上会同时改变四个像素。 (这对于多边形填充程序来说是一个很好的加速!)。

如果你想改变单个像素,那么你必须设置一个“像素掩码”(也是一个 VGA 卡寄存器),指定四个像素中的哪一个会受到内存写入的影响,就在你绘制像素之前。

如果幼稚地完成,这会很慢,因为绘制的每个像素都需要设置 mask 。通常我们直观地倾向于从左到右,从上到下(因为这正是视频内存在 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 专栏的链接中都有详细说明。这是古老的东西,但我打赌你会发现它很迷人!

干杯!

关于c - 需要帮助在 Borland C++ 3.0 上分配远指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12428345/

相关文章:

c - "error: request for member ‘clientfd’ 在不是结构或 union 的东西中”

c - 将两个字符数组的值相加

c - threadpools - 老板/ worker 与同行(工作人员)模型

c - 在C中打印双向链表的下一个和上一个值

c++ - 读取访问冲突 0xCDCDCDCD

linux - shmget() 返回带有 IPC_CREAT 的 ENOENT

ios - NSData的内容是单独引用计数的吗?

delphi - 读取任意内存位置?可能的?

C++ Visual Studio 2010,实现动态堆栈时编译错误 C3867

c - 指向指针的指针的语法是什么?