在Commodore 64上使用6510组件,我试图创建一个稳定的光栅效果。使用双IRQ原理,我在屏幕上画了一些光栅线。I垫与NOP匹配63个周期为每个正常的扫描线,和23个周期为每个坏线。我意识到我需要设置一个特定的起始行,以便将我的第8次迭代与badline相匹配,但无论我将第一行放在哪一行,或者我使用的NOP的组合如何,我都无法获得正确的时间。我想要完整的线条,而不是“破碎”。有人能看出我做错了什么吗?代码采用Kick Assembler格式。下面是一个截图:
.pc = $0801 "Basic upstart"
:BasicUpstart($8000)
.pc = $8000 "Program"
jsr $ff81
sei
lda #$35
sta $01
jsr setupInterrupts
cli
jmp *
setupInterrupts:
lda #<int1
ldy #>int1
sta $fffe
sty $ffff
lda #$01
sta $d01a
lda #$7f
sta $dc0d
sta $dd0d
lda $dc0d
lda $dd0d
lda #$1b
sta $d011
lda #$01
sta $d019
lda start
sta $d012
rts
start:
.byte 56
int1:
pha txa pha tya pha
:STABILIZE()
.for (var i=0; i<7; i++) {
inc $d020 // 6 cycles
inc $d021 // 6 cycles
nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop // 24*2=48 cycles
bit $ea // 3 cycles
// = 63 cycles
}
inc $d020 // 6 cycles
inc $d021 // 6 cycles
nop nop nop nop // 4*2=8 cycles
bit $ea // 3 cycles
// = 23 cycles (badline)
lda #$00
sta $d020
sta $d021
lda start
sta $d012
lda #<int1
ldy #>int1
sta $fffe
sty $ffff
lda #$01
sta $d019
pla tay pla tax pla
rti
.macro STABILIZE() {
lda #<nextRasterLineIRQ
sta $fffe
lda #>nextRasterLineIRQ
sta $ffff
inc $d012
lda #$01
sta $d019
tsx
cli
nop nop nop nop nop nop nop nop
nextRasterLineIRQ:
txs
ldx #$08
dex
bne *-1
bit $00
lda $d012
cmp $d012
beq *+2
}
4条答案
按热度按时间bprjcwpo1#
据我所知,您的问题不是光栅条 Flink (即您的光栅中断是稳定的),但是您在屏幕上绘制的光栅条的第二行不是完全红色的。
你的问题是线路不好。(参见[1])
在你稳定了你的光栅中断之后,用你发布的代码,你的“实际代码”将在光栅线$3A的周期4开始运行。
光栅条的第二行,您希望背景色和边框颜色为红色,是一条坏线。(这是30亿美元的光栅线。由于$D011 = $1B,这是一条坏线,因为$D011和$D012的低3位是相同的)
在这条坏线上,第一个INC(INC $D020)设法运行,因此边框颜色变为红色。然后,第二个INC(INC $D021)开始运行,但维克在它完成之前接管,因此,您的INC $D021直到VIC归还总线之后才完成。(这是43个周期后的结果-即将背景色设置为红色被延迟43个周期)。
你几乎已经得到了它,但是badline在一个与你的代码预期不同的光栅行上,你需要“推几个周期”,这样两个INC在被维克中断之前都会在badline上执行。(如果您希望在维克接管之前执行这两个INC,那么在坏行的周期4开始执行这两个INC有点太晚了)
更新示例:
尝试替换代码的这一部分:
用这个:
(警告:这段代码非常浪费内存--同样的效果可以很容易地用一个普通的循环来实现)(如果你不打算显示字符图形,你可以通过修改$D011来替换坏行,而不是改变延迟)
尝试检查HOXS 64仿真器中的机器码监视器。它非常适合调试与时序相关的问题。它显示您在任何给定时间处于哪个光栅线的哪个周期(+它可以在中断时中断)。
希望这有帮助:)
如果有人阅读这篇文章不知道什么是badlines:
酷引用:
**[1]:**阅读更多关于“坏线”在vic文章(或“vic圣经”,因为它值得被称为):http://csdb.dk/release/?id=44685(PDF)或http://vice-emu.sourceforge.net/plain/VIC-Article.txt(TXT)。另见附录:http://vice-emu.sourceforge.net/plain/VIC-Addendum.txt
基本上,当VIC-chip开始绘制文本行的第一个光栅行时,它会从CPU中窃取40-43个周期(见下文为什么不总是43)。这些光栅线被称为“坏线”。在坏线路上,因此只有20-23个周期可用,而不是63个。
(To更准确地说,当$D011的3个最低位等于$D012的3个最低位时,就会出现坏行(并且我们不在边框中,屏幕也没有被$D011的位4“关闭”)
VIC-chip使用这43个周期中的最后40个周期来读取要显示在文本行上的40个字符。CPU在这40个周期内不能执行任何指令。
然而,在这43个周期的前3个周期中,CPU实际上可以执行其指令的“写入周期”-但仅是写入周期,而不是读取周期。(参见[2])因此,如果您正确计算操作码的时间,您可以在这3个周期中执行指令的某些周期。(注意:唯一有3个写周期的指令是“brk”,它通常是无用的,所以在实践中,你最多只能使用这3个周期中的2个来做一些有用的事情)。
请注意,除了窃取坏线上的周期外,维克还将从具有子画面的光栅线上的CPU窃取周期。
**[2]:**参见“64 doc”,了解C64不同指令的哪些周期是写周期:http://vice-emu.sourceforge.net/plain/64doc.txt
(在表中,写入周期标记为“W”,读取周期标记为“R”)
[X]:... http://codebase64.org上有很多好文章
ssgvzors2#
为了使光栅线不 Flink ,需要一些额外的技巧来稳定时序。原因是,您永远无法确定光栅例程是在一行的最开始执行的,但取决于CPU“离开”主程序代码的位置,执行最后一个操作会浪费未知数量的周期。有不同的方法可以达到这个目标,你应该查看Codebase64上的this页面来了解更多关于这个主题的信息,并获得一些示例代码。然而,一旦你建立了一个稳定的光栅定时,你的方法看起来很好。
mpgws1up3#
你可能想检查一下这个:https://github.com/Zibri/C64_Stable_Raster
HSYNC程序的核心是:
0ve6wy6x4#
如果我没记错的话(20多年前)。
由于轻微的中断抖动,不太可能获得光栅效果的完全稳定的时序;所以不管你在软件中做什么,你都会在扫描线的开始处有一个“ Flink ”的点。
要解决这个问题,请使用精灵来隐藏 Flink 点。