我曾经看过一些很酷的C64演示,展示了在屏幕边框区域中显示精灵。这似乎是不可能的;我认为他们以某种方式成功地欺骗了图形芯片。他们是如何做到的呢?
我见过一些很酷的C64演示,在屏幕边框区域中展示了精灵。这本应该是不可能的,我认为他们以某种方式成功地欺骗了图形芯片。他们究竟是如何实现的?我曾经看过一些很酷的C64演示,展示了在屏幕边框区域中显示精灵。这似乎是不可能的;我认为他们以某种方式成功地欺骗了图形芯片。他们是如何做到的呢?
我见过一些很酷的C64演示,在屏幕边框区域中展示了精灵。这本应该是不可能的,我认为他们以某种方式成功地欺骗了图形芯片。他们究竟是如何实现的?是的,你需要使用汇编语言。这是一个中断定时技巧。VIC能够在边框中显示精灵,但帧只是将它们隐藏起来,所以精灵可以滑动到其后面。它与VIC显示的扫描线相连。对于下/上边框来说,它非常简单:
对于左/右边框中的精灵,情况更加复杂,因为必须为每个扫描线重复这个过程:
问题在于所有这些NOP操作都是忙碌等待,会占用你用于其他事情的周期。
我找到了一些代码,可以从下边框中的精灵滚动器中获得。这是代码。(它被从某个演示中剥离出来的。)
C198 78 SEI
C199 20 2E C1 JSR C12E # clear sprite area
C19C 20 48 C1 JSR C148 # init VIC
C19F A9 BF LDA #BF # set up IRQ in C1BF
C1A1 A2 C1 LDX #C1
C1A3 8D 14 03 STA 0314
C1A6 8E 15 03 STX 0315
C1A9 A9 1B LDA #1B
C1AB 8D 11 D0 STA D011
C1AE A9 F7 LDA #F7
C1B0 8D 12 D0 STA D012
C1B3 A9 01 LDA #01
C1B5 8D 1A D0 STA D01A
C1B8 A9 7F LDA #7F
C1BA 8D 0D DC STA DC0D
C1BD 58 CLI
C1BE 60 RTS
----------------------------------
# init VIC
C148 A2 00 LDX #00
C14A BD 88 C1 LDA C188,X
C14D 9D 00 D0 STA D000,X # set first 16 values from table
C150 E8 INX
C151 E0 10 CPX #10
C153 D0 F5 BNE C14A
C155 A9 FF LDA #FF
C157 8D 15 D0 STA D015
C15A A9 00 LDA #00
C15C 8D 1C D0 STA D01C
C15F A9 FF LDA #FF
C161 8D 17 D0 STA D017
C164 8D 1D D0 STA D01D
C167 A9 C0 LDA #C0
C169 8D 10 D0 STA D010
C16C A9 F8 LDA #F8
C16E A2 00 LDX #00
C170 9D F8 07 STA 07F8,X
C173 18 CLC
C174 69 01 ADC #01
C176 E8 INX
C177 E0 08 CPX #08
C179 D0 F5 BNE C170
C17B A9 0E LDA #0E
C17D A2 00 LDX #00
C17F 9D 27 D0 STA D027,X
C182 E8 INX
C183 E0 08 CPX #08
C185 D0 F8 BNE C17F
C187 60 RTS
----------------------------------
# data set into VIC registers
C188 00 F7 30 F7 60 F7 90 F7
C190 C0 F7 F0 F7 20 F7 50 F7
----------------------------------
# main IRQ routine
C1BF A2 08 LDX #08
C1C1 CA DEX
C1C2 D0 FD BNE C1C1
C1C4 A2 28 LDX #28 # 40 or so lines
C1C6 EA NOP # "timing"
C1C7 EA NOP
C1C8 EA NOP
C1C9 EA NOP
C1CA CE 16 D0 DEC D016 # fiddle register
C1CD EE 16 D0 INC D016
C1D0 AC 12 D0 LDY D012
C1D3 88 DEY
C1D4 EA NOP
C1D5 98 TYA
C1D6 29 07 AND #07
C1D8 09 18 ORA #18
C1DA 8D 11 D0 STA D011
C1DD 24 EA BIT EA
C1DF EA NOP
C1E0 EA NOP
C1E1 CA DEX
C1E2 10 E4 BPL C1C8 # repeat next line
C1E4 A9 1B LDA #1B
C1E6 8D 11 D0 STA D011
C1E9 A9 01 LDA #01
C1EB 8D 19 D0 STA D019
C1EE 20 00 C0 JSR C000 # call main code
C1F1 4C 31 EA JMP EA31 # finish IRQ
如果您想学习有关在C64上打开边框的技巧,可以查看Pasi Ojala在C=Hacking Issue 6中撰写的优秀文章。
不过,不需要过于技术化。该技巧利用了VIC芯片的一个特性,使您可以在文本/图形的25/24行和40/38列之间切换,并涉及在恰当时刻进行此切换,以欺骗VIC芯片认为已经打开了边框,而实际上并没有打开。请参阅上述文章,了解更详细的解释及代码示例。
那是很久以前的事了。
我知道有一种解决方案依赖于监视器的频率。
在CRT中,即使当前像素位于正常屏幕之外,也可以确定其位置。因此,您可以操纵射线。
我的废品堆里肯定有一些C64图书。
离题了,但是用VIC20(C64的前身)制作图形很有趣。没有办法操纵每个像素,但您可以更改现有字符。因此,您可以使用从0到...的所有字符填充屏幕,并更改字符以将像素设置到屏幕上。;-)。
时间是关键。通过改变超扫描(边框)颜色,随着CRT的光束从左到右移动,在边框中创建图像。生成图像需要两个定时信号 - 垂直刷新和水平刷新。通过检测水平和垂直刷新发生的时间,您可以开始一系列汇编指令来更改边框颜色以生成图像。您需要计算每个边框像素的CPU时钟周期数,并使用它来创建在正确时间更改边框颜色的代码。
当涉及编写游戏时,它的效果并不好,因为CPU开销太大,没有足够的时间处理用户输入和游戏状态。