59

我有 25 年的好奇心,我很想了解其中的诀窍。

在 Commodore 64 中,6569 VIC 无法寻址边界。您所能做的就是在光标移动的中心区域绘制像素。边界总是统一的,虽然你可以用戳 53280 改变它的颜色,如果我没记错的话。

尽管如此,我清楚地记得游戏介绍中的边框带有图形,就像它是完全可寻址的一样。我试图了解它是如何工作的,但从未达到目的。传说这是对精灵的巧妙使用,在某些情况下,可以在边界上绘制,但我不知道这是否是都市传说。

编辑:只需从提供的链接之一中阅读此内容

精灵在垂直光栅线上多路复用(超过 8 个精灵,有时多达 120 个精灵)。直到 2007 年 5 月 Group Crest 发布 Krestage 3 之前,人们普遍认为在一条光栅线上不能出现超过 8 个精灵,但分配新的 Y 坐标使其重新出现在屏幕下方。

这是邪恶的......你击败了光栅并在精灵到达那里之前重新定位......

4

9 回答 9

44

首先,只有精灵可以显示在边界区域或从视频库的最后一个字节读取的重复的 8 位模式(8 像素宽),通常是 $3fff。请注意,当您欺骗 VIC 芯片“不显示”边框时,您只能看到这些精灵或 8 位模式。见下文。

边框比精灵具有更高的优先级,因此通常当精灵在边框区域中绘制时,边框会覆盖精灵。使用一点 VIC 芯片技巧,您可以关闭边框。

您可以很容易地关闭顶部和底部边框(我将在下面解释),并且在非常关键的时机关闭侧边框。

首先是关于 VIC 芯片如何在 c64 上工作的一些信息。

VIC芯片从左上到右上画屏,然后下一行,再从左到右,直到画完整个屏。它每秒执行 50 次重绘(对于 PAL 单位)或每秒执行 60 次(对于 NTSC 单位)。

有一个 8 位 VIC 寄存器,其中包含任何给定时间光栅的垂直位置。$d012。实际上有超过 255 个可能的位置,因此第 9 位存储在第 7 位(最高位)或寄存器 $d011 中。因此,您可以随时读取这些寄存器并找出光栅的垂直位置。没有可用的寄存器来读取光栅的 x 位置。

VIC 芯片的另一个很酷的功能用于解决使用硬件滚动时出现的问题。基本的垂直滚动是通过使用硬件寄存器将屏幕垂直移动 0-7 个像素来实现的。一旦达到限制(0 或 7,取决于滚动方向),您将垂直移动每个字符块(8x8 像素)一个块并绘制新数据以显示在顶部(或底部取决于方向)。这很好用,除了每滚动 8 个像素你会看到数据“弹出”到屏幕上。为了解决这个问题,您可以通过清除寄存器 $d011 中的位 3 使边界区域垂直增长 8 个像素。这称为 24 行模式。默认情况下,屏幕设置为 25 行 8x8 像素字符。在 24 行模式下,您仍然可以将字符绘制到底行,它们只是被边框隐藏。

所以关闭顶部和底部边框的技巧是:

1) 将屏幕设置为 25 行模式

2) 等待光栅到达 $f2 和 $fa 之间的垂直位置(在 24 行模式和 25 行模式下边界开始位置之间的 8 个像素)。

3) 将屏幕设置为 24 行模式...将边框的垂直起点移到当前光栅位置上方

4)等到垂直光栅位置($fa)之后

5) 重复每一帧

步骤 3) 欺骗 VIC 芯片认为它已经开始绘制边界,因此它永远不会开始绘制它。瞧,顶部和底部边界是开放的。

关于边边界,您可以使用不同的寄存器做同样的事情,但是由于光栅的水平移动比垂直移动快很多,所以时间需要更紧。还有另一个问题需要考虑,称为抖动。<-我不会在这里解释。在 Web 上搜索“Stable Raster C64”以获得对该问题的深入解释。

于 2009-11-19T03:56:20.027 回答
9

请注意,Krestage 3 所做的(如问题中所述)是不同的。

技巧的一个层面是在“纸”(工作区矩形,边框内的东西)的底部刚刚被绘制时弄乱边框。这使您可以在上下边框中拥有精灵。

更高的级别是在纸张的右侧边缘,在每条光栅线中弄乱它,所有这些都在上面 JohnD 的回答中解释。这使您可以在左右边框中拥有精灵。

这些都不能让你在一行中有超过 8 个精灵。那只是克雷斯特的魔法。

到目前为止,VIC 芯片的最佳资源(我知道)是Christian Bauer的“MOS 6567/6569 视频控制器 (VIC-II) 及其在 Commodore 64 中的应用”,一个有用的附录是“The memory accesses of the MOS 6569 VIC-II 和 MOS 8566 VIC-IIe 视频接口控制器”,作者 Marko Mäkelä。
警告讲师:这些都是技术性的,在您自己编写了一些 VIC 效果器后,您可能会发现它们更容易理解。

如果链接死了,只需按标题搜索文章,它们就会被无休止地复制。

于 2009-11-21T00:03:07.553 回答
5

你可以用一个简单的 BASIC 程序打开上下边框:

    1戳56334,0:戳53266,212:戳53265,27:戳16383,0
    2 h=53265:i=53273:h1=19:h2=27:i1=1
    3 pokei,i1:waiti,i1:pokeh,h1:pokeh,h2:goto3
于 2011-09-11T13:39:21.747 回答
4

我要在这里在黑暗中刺伤(我自己没有这样做)。我在维基百科上找到了这个。

c64demo部分解释说:

在演示中实现了认为不可能的效果,主要是由于与MOS Technology VIC-II 芯片有关的未记录的副作用。VIC诡计的一些例子:

提到的黑客之一是:

Sprite 滚动条放置在边框中。通过欺骗硬件不在屏幕周围绘制边框,精灵可以移动到该区域并显示。

当然,问题的有趣部分是它是如何完成的。我建议查看一些包含源代码的演示数据库,以寻找使用 hack 的演示。

于 2009-11-17T17:06:54.140 回答
3

微软飞行模拟器画在边界上。一方面,我们可以通过适时改变边框颜色来实现边框绘制效果。例如,LOGO 为 Turtle 图形提供了分屏模式,屏幕在上面的 HiRes 图形和下面的几行文本之间切换。框架的颜色也不同。所以很容易做一个地平线效果,下面的绿色牧场和上面的蓝天(就像在飞行模拟器中一样),效果延伸到框架。

当您运行狂野的帧闪烁程序时,例如

   C000 LDX #00
        STX D020
        INX
        STX D020
        DEX
        BEQ C002

然后你可以让颜色每 10-20 像素左右改变一次。我认为这是你能得到的最快的改变。所以你可以在边框上画一条水平线。边框颜色的最快变化

您可以通过使用 VIC 中 $D012 和 $D011 的第 7 位的相同垂直行寄存器来计时,您可以从该寄存器读取当前扫描行。但是如果你写入它,并且你启用寄存器 $D01A 中的低位,那么当扫描到达该行时,VIC 将发出信号并发出 IRQ。这样就实现了分屏效果。

这是一个例子。首先,我设置了我的中断例程:

   C000 SEI        ; disable interrupt
        LDA #1F    ; set interrupt routine to C01F
        STA 0314   ; set low byte
        LDA #C0    ; high byte
        STA 0315   ; set
        LDA #C0    ; raster position for horizon
        STA D012   ; set to raster position interrupt
        LDA D011   ; and for the high bit of the raster position
        AND #7F    ; clear the high bit
        STA D011   ; and set the cleared high bit
        LDA #F1    ; enable the raster interrupt
        STA D01A   ; in the appropriate register
        CLI        ; allow interrupt
        RTS        ; return from subroutine

这是我现在的实际中断程序:

   C01F LDA D019   ; load VIC interrupt register
        STA D019   ; and clear it
        BMI C02E   ; if highest bit is set, go to our routine
        LDA DC0D   ; else disable CIA interrupt
        CLI        ; enable interrupt
        JMP EA31   ; continue with normal system interrupt routine

   C02E LDA D012   ; load current vertical scan line
        CMP #01    ; is it just about the first line?
        BCS C042   ; if not jump to bottom part
        LDA #03    ; cyan
        STA D020   ; set border color (sky)
        LDA #C0    ; horizon level 
        STA D012   ; set vertical scan interrupt to occur at horizon
        JMP EA81   ; continue with normal interrupt minus cursor blink

   C042 LDA #00    ; black to draw a piece of horizontal line on the horizon
        STA D020   ; set border color
        LDX #08    ; a short busy loop
   C049 DEX
        BNE C049
        LDA #01    ; white to draw on the right side horizon
        STA D020   ; set border color
        LDX #02    ; very short busy loop
   C053 DEX
        BNE C053
        LDA #05    ; finally green as the grass
        STA D020   ; set border color
        LDA #00    ; next scan line interrupt at top of screen
        STA DO12   ; set scan line interrupt
        JMP EA81   ; continue normal interrupt sans cursor blink 

有了以下辉煌的结果: 在水平线上绘制两条线段的分屏

于 2019-09-23T02:54:32.190 回答
2

打印“它是 53280,伙计。”

于 2009-11-17T16:59:04.037 回答
2

据我了解,这仅适用于精灵。

精灵被允许在边界区域,并且边界被绘制在上面。通过一些诡计,可以删除边界。

于 2009-11-17T17:00:36.337 回答
1

边框中的图形:精灵或使用 $3FFF 效果(实际上根本不是精灵)。详细介绍需要比我在这里可用的更多的空间和时间。

于 2010-12-27T04:11:27.590 回答
1

您还可以在基本中获取精灵边界:BASIC Sprites in Border

iirc,还有一些方法可以混淆视频芯片,它会绘制第 26 行文本。

于 2014-05-23T22:26:12.257 回答