【问题标题】:Stop screen refreshing - INT 0x10 (Video Services) - In Assembly停止屏幕刷新 - INT 0x10(视频服务) - 组装中
【发布时间】:2016-09-17 23:28:26
【问题描述】:

我的编程环境是一个 MS-DOS 仿真器,我正在使用 16 位汇编编程。

我使用的是常规文本模式,可以打印字符和使用属性。

在屏幕的一部分上,我每秒钟都在绘制很多字符,数以千计的字符,这会创建一个漂亮的动画。

问题是,为了创建动画,首先我必须删除旧的,我基本上是打印 1000 次左右的空格字符。 (!) 现在,因为我正在这样做,所以每次我重绘动画时都会出现轻微的闪烁问题,这很明显并且非常烦人。

我正在使用视频服务来完成所有的输出和动画操作。所以我的第一个想法是想办法阻止屏幕刷新,重绘它,让屏幕自己继续刷新。

因为此过程每秒发生多次,而且必须多次发生,所以我发现任何其他清洁方法都不是很有帮助。

【问题讨论】:

  • 准备缓冲区中的下一个数据。使用int 10h 函数02h 将光标位置设置在左上角。打印缓冲区。顺便说一句,int 10h 可以访问 BIOS 功能,而不是 MS-DOS 功能。

标签: video assembly x86 refresh dos


【解决方案1】:

基本问题是,如果只是一瞬间,您会向用户展示一些他们不应该看到的东西,一个充满空格的空白屏幕。这就是导致闪烁的原因。您可以通过使用单个 BIOS 调用(例如 INT 10h AX=0600h)更快地擦除屏幕来改善这一点,但更好的解决方案是只向用户显示他们应该看到的内容。

从上到下覆盖所有内容

这样做的一种方法是更改​​您的代码,以便在绘制新框架时完全覆盖旧框架。这样就无需擦除屏幕。因此,例如,不要在屏幕上的不同位置跳来跳去绘制文本,而是从左上角开始,从左到右,从上到下绘制文本。打印空格以将光标从一个位置移动到另一个位置。假设您只有两个可以使用的功能,一个将光标移动到屏幕的左上角,一个打印一个字符并推进光标。

在用户看不到的地方画出来

如果这太难了,您可以使用屏幕外缓冲区来完成您现在正在做的事情。擦除屏幕外缓冲区,在其上绘制文本,然后显示它。这样用户就永远不会看到他们本来不想看到的已擦除屏幕。您可以在内存中创建一个离屏缓冲区,然后将其复制到屏幕上,也可以在显存中的页面之间翻转。

绘制到内存中的离屏缓冲区

在内存中使用缓冲区意味着您不能使用 BIOS 函数来绘制它,但根据具体情况,这会更方便。您将使用普通的内存写入来擦除缓冲区并绘制文本,然后将整个缓冲区复制到屏幕上。本质上,这是一种完全覆盖我上面描述的从上到下的所有内容的方式。

绘制到非活动视频页面

在视频页面之间翻转可能让您使用与现在相同的 BIOS 功能来绘制文本。也就是说,假设他们在 BH 中接受一个参数来指定使用哪个页面。并不是所有的 BIOS 函数都有这个,特别是我前面提到的 BIOS 函数 INT 10h, AH=06h 没有。您将使用两个视频页面,0 和 1,并且您需要跟踪哪个页面当前处于活动状态并向用户显示。然后,您将在非活动页面上擦除并绘制文本,完成后您将翻页,使非活动页面成为活动页面。为此,您需要使用 INT 10h AX=05XX,其中 XX 是要激活的页码。

直接写入显存

更高级的技术是直接写入视频内存。回到 MS-DOS 流行的时候,PC 非常慢,以至于使用 BIOS 绘制文本对于任何类型的实际动画来说通常都太慢了。相反,大多数执行此类操作的应用程序直接写入视频内存,绕过缓慢的 BIOS 例程。您可以结合使用上述任何技术。例如,您可以绘制到普通内存中的屏幕外缓冲区,然后使用 REP MOVS 指令将其复制(“blit”)到视频内存。

绕过 BIOS 的不利之处在于它使您的代码的可移植性降低了一些。例如,最初的 IBM PC 单色显示适配器 (MDA) 和彩色图形适配器 (CGA) 的视频内存位于不同的位置(分别为 B000:0000 和 B800:0000)。其他不是 100% 兼容 PC 的第三方计算机就更奇怪了。有些不支持文本模式,BIOS 将使用位图图形模式绘制文本。

【讨论】:

  • 等待新的垂直回溯的旧技巧在这里适用吗?
  • @MargaretBloom 它可能只在直接写入视频内存时才有效。否则,BIOS 例程太慢,无法在垂直消隐间隔内做很多事情。似乎也没有任何等待回溯的 BIOS 功能,这意味着直接访问视频卡的 I/O 端口,因此超出了我想通过这个答案获得的内容。否则,是的,等待垂直回撤将是防止撕裂的好主意。至少在真正的硬件上,我不知道模拟器能模拟到什么程度。
【解决方案2】:

直接写入显存:

  • 找出视频模式如下:

    1. 将 AH 设置为 0x0F
    2. 调用中断 0x10(视频服务)
    3. 在 AL 中查找视频模式
  • 如果视频模式为 7,屏幕内存从 B000:0000 开始

  • 否则,屏幕内存从 B800:0000 开始

内存在一个字节用于字符和一个字节用于“属性”(粗体、下划线、反转、闪烁)之间交替进行

如果您使用的是物理硬件,最好在写入物理屏幕内存之前等待垂直回扫,以避免“下雪”。这可以通过在写入之前等待端口 0x3DA 变为奇数来完成。

请参阅此old Usenet thread,了解有关此技术的局限性和可能改进的讨论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-08
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多