在Commodore 64中绘制屏幕边框

时间:2009-11-17 16:51:37

标签: retro-computing c64 commodore

确定。我希望它不会被关闭,因为我有25年的好奇心,我很想理解这个伎俩。

在商品64中,6569 VIC无法查询边界。您所能做的就是在中心区域绘制像素,即光标移动的像素。边框总是均匀的,虽然你可以用捅53280改变它的颜色,如果我没记错的颜色。

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

编辑:只需从其中一个提供的链接

中阅读
  

Sprites被多路复用   垂直光栅线(超过8个精灵,   有时多达120个精灵)。直到   Group Crest发布了Krestage 3   2007年5月有共同点   认为不超过8个精灵   可以出现在一条栅格线上,但是   分配新的Y坐标   再次出现在屏幕上。

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

9 个答案:

答案 0 :(得分:42)

首先,只能在边框区域显示精灵,或者从视频库的最后一个字节读取重复的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芯片认为它已经开始绘制边框,因此它永远不会开始绘制它。 Voila,顶部和底部边界是开放的。

关于侧边框,您可以使用不同的寄存器执行相同的操作,但由于光栅的水平移动要快得多,因此垂直移动时间需要更加紧凑。还有另一个需要考虑的问题叫做抖动。 < - 我不会在这里解释。在网上搜索“Stable Raster C64”,深入解释该问题。

答案 1 :(得分:9)

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

诀窍的一个层面是当“纸张”的底部(工作区矩形,边框内的东西)刚刚被绘制时弄乱边框。这使你可以在上边界和下边界有精灵。

更高的等级是在纸张的右边缘,在每个光栅线中弄乱它,所有这些都在JohnD上面的答案中解释。这使你可以在左右边界有精灵。

这一切都不允许你在一行中拥有超过8个精灵。那只是克雷斯特的魔法。

到目前为止,VIC芯片的最佳资源(我知道)是Christian Bauer的"The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64",而MarkoMäkelä的有用附录是"The memory accesses of the MOS 6569 VIC-II and MOS 8566 VIC-IIe Video Interface Controller"。 注意事项:这些技术有点技术性,你自己编写了一些VIC效果后可能会发现它们更容易理解。

如果链接已经死亡,只需按标题搜索文章,就会无休止地复制。

答案 2 :(得分:6)

您可以使用简单的BASIC程序打开上下边框:

    1 poke56334,0:poke53266,212:poke53265,27:poke16383,0
    2 h=53265:i=53273:h1=19:h2=27:i1=1
    3 pokei,i1:waiti,i1:pokeh,h1:pokeh,h2:goto3

答案 3 :(得分:4)

我要在黑暗中捅一下(我自己也没做过)。我在维基百科上发现了这个。

c64demo section解释说:

  

认为不可能的效果   在演示中实现,主要是由于   无证的副作用   到MOS Technology VIC-II chip。   VIC-trickery的一些例子:

上面提到的一个黑客是:

  

精灵滚动器被放置在   边界。通过欺骗硬件而不是   在屏幕周围绘制边框,   精灵可以搬进这个区域   并显示。

当然,问题的有趣部分是它是如何完成的。我建议查看一些demo database,其中包含源代码,以搜索使用黑客攻击的演示。

答案 4 :(得分:3)

打印“它是53280,DUDE。”

答案 5 :(得分:2)

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

允许精灵在边界区域,并且边界被绘制在上方。通过一些技巧,可以删除边框。

答案 6 :(得分:1)

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

答案 7 :(得分:1)

你也可以在基本的BASIC Sprites in Border

中获得精灵

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

答案 8 :(得分:1)

Microsoft飞行模拟器在边界上划过。首先,我们可以通过在适当的时间更改边框颜色来实现边框绘制效果。例如,LOGO具有用于Turtle图形的分屏模式,该屏幕在上面的HiRes图形和下面的几行文本之间切换。框架的颜色也不同。因此,很容易进行地平线效果,下面的绿色牧场和上面的蓝天(如在《飞行模拟器》中一样),这种效果延伸到框架。

运行wild frame flicker程序时,例如

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

然后,颜色每10-20像素左右变化一次。我认为这是最快的变化。因此,您可以在边框上画一条水平线。 fastest change of border color

您可以通过在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 

具有以下出色的结果: split screen with two line segments drawn on the horizon