题
我见过很酷的 C64 演示,在屏幕的边框区域显示精灵。这不应该是不可能的;我认为他们设法以某种方式欺骗了图形芯片。他们到底是怎么做到的?
解决方案
是的,你需要汇编器。这是一个中断计时技巧。VIC 能够在边框中显示精灵,但框架只是隐藏它们,因此精灵可以在其后面滑动。它连接到 VIC 显示的扫描线。对于下/上边框来说非常简单:
- 编程一个中断,同步从下边界之前的某个扫描线、7 个像素或类似的位置开始。
- 设置VIC中的寄存器,使边框变小。(有一个寄存器可以做到这一点。)
- VIC现在认为边界已经开始,并且不会开始绘制它。
- -> 底部没有边框。
- 在实际边界后编程另一个中断,将其设置回原始状态。
对于左/右边框中的精灵,情况更为复杂,因为必须对每条扫描线重复该过程:
- 对中断进行编程,同步以在特定扫描线处启动。
- 然后执行一些 NOP,直到距离右边框 7 个像素。
- 设置VIC中的寄存器,使边框变小。
- -> 右侧没有边框。
- 执行一些 NOP 直到到达真实边界并将寄存器设置回原始值。
- 再次执行一些 NOP,直到步骤 2。
问题是所有这些 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不得不查询电子束的精确的垂直位置,同时将其绘制在屏幕的方法。 当一个新的行启动,你不得不等待几个周期(你可以这个时间使用NOP指令),然后您必须设置这是负责制定screenmode(和边框宽度)videochip的硬件寄存器。 通过定时完全正确,并再次做它的每一个扫描线,整个sideborder消失。
在底边框还带走了类似的伎俩。在哪里垂直边界开始的准确扫描线你也必须设置禁用它底边框该帧的:视频模式。
事实上,这件事曾在组装工作要做。否则,你永远无法得到的时机完全正确的。
作为边注,我认为sideborder特技被记入1001船员(荷兰组)。我不知道谁被拉断第一底边框的把戏。
有关的C64打开边界的主题一个很好的教程, 检查出帕斯Ojala的在Ç优良文章=黑客问题6 。
没有得到太多的技术,诀窍使用VIC的一个特征 芯片让你25/24行和文本/图形三十八分之四十零列,之间切换 涉及的确切合适的时机来糊弄VIC使这个开关 以为它已经打开了边界时,实际上它 没有。看看上面的文章为一个更透彻的解释 用代码的例子。
也就是说很久以前。
我知道有,关于显示器的频率依赖的溶液。
通过一个CRT,当前像素被即使它是正常的屏幕以外公知的。 所以,你可以操纵的射线。
在某处我junkpile必须有一些C64的书籍。
Offtopic,但图形与VIC20(C64的的前身)很有趣。有没有办法来处理每一个像素,但你可以改变现有的字符。所以,你所有的字符填充的屏幕从0到...,改变了人物设定像素到屏幕上。 ; - 。)
时序是关键。该图像是在边界通过改变过扫描(边框)颜色创建为CRT的光束移动由左到右。有以产生图像需要两个定时信号 - 垂直刷新和水平刷新。通过在水平方向和垂直刷新时就可以开始的汇编指令的序列来改变边框颜色以产生图像检测。你需要计算出每个边界像素CPU的时钟周期数,并用它来创建代码,改变在正确的点上边框的颜色。
当谈到编写游戏的CPU开销太大,那里是随时电梯处理用户输入和游戏状态它没有很好地工作。