Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要帮助在Borland C++;3_C_Memory_Pointers_Dos - Fatal编程技术网

需要帮助在Borland C++;3

需要帮助在Borland C++;3,c,memory,pointers,dos,C,Memory,Pointers,Dos,我正在写一个DOS游戏框架,以更好地学习C语言,并对在旧硬件上编程(尤其是在我成长的系统上)有着广泛的兴趣 我试图实现一个双缓冲区系统,但在分配一个指向320*200数组的远指针时遇到了问题 起初我试图使用malloc,但发现它只能分配64kb以下的内存。我了解到您需要使用farmalloc(malloc返回NULL),并且它分配正确。但是,当运行_fmemset或_fmemcpy时。。。。整个系统冻结 backBuffer = (unsigned char far*) farmalloc(64

我正在写一个DOS游戏框架,以更好地学习C语言,并对在旧硬件上编程(尤其是在我成长的系统上)有着广泛的兴趣

我试图实现一个双缓冲区系统,但在分配一个指向320*200数组的远指针时遇到了问题

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

backBuffer = (unsigned char far*) farmalloc(64000);
当需要交换缓冲区时,我使用

_fmemcpy(VGA, backBuffer, 64000);

程序使用的是小内存模式。

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

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

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

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

如果你感兴趣,我强烈建议你阅读迈克尔·艾布拉什的专栏

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

一旦激活,有两大优势:

  • 四页显示存储器
  • 方形像素(在320x240的原始ModeX中),(绘制的圆看起来像圆,而不是椭圆)
  • 实现双缓冲区甚至三缓冲区是轻而易举的事,因为您可以直接写入非活动缓冲区并激活它,只需更改vga卡中的寄存器,而无需memcopy(您仍然需要等待垂直回程,否则会出现难看的闪烁)

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

    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专栏链接中详细介绍了所有涉及的步骤和注册地址。这是古老的东西,但我打赌你会发现它很迷人


    干杯

    什么是
    VGA
    ,它的值,
    backbuffer
    \u fmemcpy()
    ?VGA是指向地址0xA000000L(VGA内存地址)的无符号字符远指针。Backbuffer也是一个无符号的char远指针,是用上面的函数分配的。我不理解0xA000000L。它必须是:段=0xA000&偏移量=0(对应于物理地址=段*0x10+偏移量=0xA0000=640K)。它真的有段=0xA000和偏移=0吗?或者是段=0xA00&offset=0还是其他什么?制作这样一个指针的正确方法是通过
    MK_FP(0xA000,0)
    @loncannon,也许这是你的评论中的一个错误,但是你缺少了一个零,它应该是0xA0000000L。似乎有人关闭了我的问题:(。无论如何,这似乎是“未锁定模式”我阅读了关于是的?来回答你的问题:尝试了中等模式,当它退出内联汇编块时会表现出奇怪的行为。VGA显示内存被初始化,因为我在处理后缓冲区之前有程序绘图。是的!它们指的是相同的模式。它显然是“发现的”同时由几个开发人员开发,正如VGA技术文档中暗示的那样,该模式的存在,但没有详细说明。我没有BC++3.0,你能检查一下是否有一个紧凑的模型可用并尝试一下吗?它应该是64KB代码(就像小模式一样),但数据量为64+KB(可能程序集块假设只有一段64KB的代码?)-如果你能得到Watcom的C编译器的副本,那么你就可以在一个更简单的平面内存模型中编程(没有段)并使用保护模式对所有可用内存进行寻址。奇怪的是,将其设置为压缩内存模式会导致fread冻结。根据我选择的型号,程序中的随机点似乎会冻结。太令人沮丧了。嗨@loncannon,很抱歉听到这个消息,我出去旅行了。从你描述的内容来看,你可能会有一些内存腐败问题(可能是系统其他部分的缓冲区溢出)。Numega的BoundsChecker之类的工具非常有助于找到这些缺陷点。如果您在现代系统下进行调试,另一种可能是计时问题。我记得一些库通过测量计算机的速度来同步事情,并调整