需要帮助的用Borland C分配远指针++ 3.0 [英] Need help allocating a far pointer on Borland C++ 3.0

查看:238
本文介绍了需要帮助的用Borland C分配远指针++ 3.0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写一个DOS游戏框架,以更好地学习C并在旧硬件编程一般利益(尤其是在系统上我长大了)。

我想实现双缓冲系统,但我有麻烦远指针分配给一个320 * 200的数组。

起初我试图使用malloc,但是发现它只能在64KB分配。我读了你需要使用farmalloc(的malloc返回NULL),它正确分配。然而,运行_fmemset或_fmemcpy时....整个系统死机。

  =后备缓冲(无符号字符FAR *)farmalloc(64000);

当它的时间来交换缓冲

我用

  _fmemcpy(VGA,后备缓冲,64000);

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


解决方案

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


  • 您是否尝试过在中型或大型模型编译来检查code正常运行?


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


我记得,在那些日子里,用内存拷贝交换缓冲区的屏幕是非常慢,更何况,你必须等待垂直回扫期间开始复制内存。 (我有一个光秃秃的骨头显卡,所以也许你的硬件更好,延迟超过可接受)。

如果您有兴趣,我强烈建议你阅读迈克尔·亚伯拉什的的模式-X 列。

模式-X和其衍生物是替代图形模式最早由迈克尔·亚伯拉什记录。基本上,他们是黑客的256色13H模式,你可以通过在显卡调整一些寄存器激活。

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


  1. 4页显示内存

  2. 方形像素(原来在这ModeX为320x240),(标绘的圆圈看起来像一个圆,而不是椭圆形)

实施双重甚至三重缓冲是一件轻而易举的,因为你可以直接写为无效缓冲区并激活它只是参与了显卡更改寄存器,没有存储器复制了!(您仍需要等待垂直回扫,否则是一个丑陋的闪烁)

的缺点是,这种模式是更难程序,基本上与模式-X现在单个存储器地址被映射到连续的四个像素,因此,一个单一的象素写入实际上将在一次改变四个像素。 (这是多边形填充例程伟大加速!)。

如果你想改变一个像素,那么你必须设置一个像素面具(又一个VGA卡寄存器)指定哪四个象素的将内存写入的影响,您绘制像素之前。

如果做天真,因为绘制每个像素需要建立一个面具这是缓慢的。通常我们直观地倾向于借鉴的东西从左到右,从上到下(因为这是precisely如何显存映射在VGA模式13H),但美国模式-X程序员学会了它的速度要快得多为旋转模式 ,也就是我们画的东西上到下,左到右。

为什么呢?因为这允许我们修改像素面具只有一次,每列拉!
下面是一些伪code:

朴素,直观的编程

  pixelptr =屏幕内存的开始
连续的foreach
   列的foreach
      调整像素面具
      写像素值
      pixelptr + = 1 //提前指针下一像素向左
   下一个
下一个

编程的旋转模式

 为每列
   屏幕内存+当前列索引pixelptr =启动
   调整像素掩码//相同的掩模应用到每个像素在相同列!
   对于每一行
      写像素值
      pixelptr + =(320/4)//提前指针下一个像素,在底部
   下一个
下一个

所有涉及的步骤和注册地址在链接我提供的迈克尔·亚伯拉什列的详细。这是一个古老的东西,但我敢打赌,你会发现它令人着迷!

干杯!

I am writing a DOS game framework to learn C better and a general interest in programming on old hardware (especially on the system I grew up with).

I am trying to implement a double buffer system but I am having trouble allocating a far pointer to a 320*200 array.

At first I was trying to use malloc but found out it can only allocate under 64kb. I read that you need to use farmalloc (malloc returns NULL) and it allocated correctly. However, when _fmemset or _fmemcpy is run.... the whole system freezes.

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

when it is time to swap buffers I use

_fmemcpy(VGA, backBuffer, 64000);

Program is using the small memory model.

解决方案

Very interesting post, I'm also very fond of old hardware.

  • Have you tried compiling in medium or large models to check if the code runs correctly?

  • Are you sure the pointer to the VGA display memory is correctly initialized?

I remember that in those days, using a memory copy to swap screen buffers was painfully slow, not to mention that you had to wait for the vertical retrace period to begin copying memory. (I had a bare bones VGA card, so perhaps your hardware is better and the delay is more than acceptable).

If your are interested, I'd strongly advice you to read Michael Abrash's Mode-X columns.

Mode-X and its derivatives are alternative graphic modes first documented by Michael Abrash. Basically they were hacks to the 256 color 13H mode that you could activate by tweaking some registers in the VGA card.

Once activated, there were two great advantages:

  1. Four pages of display memory
  2. Square Pixels (In original ModeX that is 320x240), (a plotted circle will look like a circle, not an ellipse)

Implementing a double or even triple buffer was a breeze, as you could directly write to the inactive buffer and activating it simply involved changing a register in the vga card, no memcopy at all! (you still need to wait for vertical retrace, otherwise there's an ugly flicker)

The disadvantage is that this mode is harder to program, basically, with mode-X now a single memory address is mapped to four consecutive pixels, so, a single pixel write will actually alter four pixels at once. (this is great acceleration for polygon filler routines!).

If you want to alter a single pixel, then you have to setup a "pixel mask" (also a VGA card register) specifying which of the four pixels will be affected by the memory write, just before you plot the pixel.

This is slow if done naively, as every pixel plotted requires setting up a mask. Usually we intuitively tend to draw things left to right, top to bottom (because that's precisely how video memory is mapped on the VGA mode 13H), but us Mode-X programmers learned it is much faster to "rotate the paradigm", that is, we drew things top-to-bottom, left-to-right.

Why? because this allows us to modify the pixel mask just once for every column drawn! Here's some pseudocode:

Naive, intuitive programming

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

Rotated mode of programming

[Edit1: added the missing step where pointer must be moved to top of next column]

[Edit2: correction, I was adding 320 to advance to the next row when in fact this should be divided by 4 since a consecutive increment of the video memory address will map to the group of next four pixels to the right of the previous, four-pixel group]

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

All the involved steps and register addresses are detailed in the link to the Michael Abrash columns I provided. This is ancient stuff, but I bet you'll find it fascinating!

Cheers!

这篇关于需要帮助的用Borland C分配远指针++ 3.0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆