Assembly C64上的稳定光栅
使用Commodore64上的6510 assembly,我试图创建一个稳定的光栅效果。使用双IRQ原理,我在屏幕上绘制了一些光栅线。我用NOP进行pad,使每个正常扫描线匹配63个周期,每个不良扫描线匹配23个周期。我意识到我需要设定一个特定的开始线,以便将我的第八次迭代与一个坏线相匹配,但无论我把第一行放在哪一行,或者我使用的是哪种NOP组合,我都无法获得正确的时机。我想要完整的线,而不是“断”。有人能看出我做错了什么吗?代码采用Kick汇编程序格式。下面是一个屏幕截图:Assembly C64上的稳定光栅,assembly,6510,Assembly,6510,使用Commodore64上的6510 assembly,我试图创建一个稳定的光栅效果。使用双IRQ原理,我在屏幕上绘制了一些光栅线。我用NOP进行pad,使每个正常扫描线匹配63个周期,每个不良扫描线匹配23个周期。我意识到我需要设定一个特定的开始线,以便将我的第八次迭代与一个坏线相匹配,但无论我把第一行放在哪一行,或者我使用的是哪种NOP组合,我都无法获得正确的时机。我想要完整的线,而不是“断”。有人能看出我做错了什么吗?代码采用Kick汇编程序格式。下面是一个屏幕截图: .pc = $08
.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
}
.pc=$0801“基本暴发户”
:开始(8 000美元)
.pc=$8000“程序”
jsr$ff81
软件工程研究所
lda#35美元
sta$01
jsr设置中断
cli
jmp*
设置中断:
lda#int1
sta$fffe
sty$ffff
lda#01美元
sta$d01a
lda#7f美元
sta$dc0d
sta$dd0d
lda$dc0d
lda$dd0d
10亿美元
sta$d011
lda#01美元
sta$d019
lda启动
sta$d012
即时战略
开始:
.字节56
int1:
pha txa pha tya pha
:稳定
.对于(var i=0;i如果我记得正确(20多年前)
由于较小的中断抖动,不太可能获得完全稳定的光栅效果计时;因此,无论您在软件中做什么,在扫描线的开始处都会有一个“闪烁”点
要解决此问题,请使用精灵隐藏闪烁点。为了使光栅线不闪烁,需要一些额外的技巧来稳定计时。原因是,您永远无法确定光栅例程是否在行首执行,而是取决于CPU“离开”的位置主程序代码在执行上一个操作时浪费了未知数量的周期。有不同的方法可以实现此目标,您应该查看Codebase64上的页面以了解更多有关此主题的信息并获取一些示例代码。但是,一旦您建立了稳定的光栅计时,您的方法对我来说很好。正如我所理解的那样而你,你的问题不是你的光栅条在闪烁(即你的光栅中断是稳定的),而是你在屏幕上绘制的光栅条的第二行不是完全红色的
您的问题是线路错误。(请参阅[1])
稳定光栅中断后,使用您发布的代码,“实际代码”将在光栅线$3A的第4周期开始运行
光栅栏的第二行(希望背景颜色和边框颜色为红色的位置)是一条坏线。(它是光栅线$3B。由于$D011=$1B,这是一条坏线,因为$D011和$D012的低3位相同)
在这条糟糕的线路上,第一个INC(INC$D020)成功运行,因此边框颜色变为红色。然后第二个INC(INC$D021)开始运行,但在完成之前由VIC接管,因此您的INC$D021直到VIC返回总线后才完成。(这是43个周期之后-即,将背景色设置为红色将延迟43个周期)
您几乎已经有了它,但是坏线位于与代码预期不同的光栅线上,您需要“推动几个周期”,以便在被VIC中断之前,两个INC都将在坏线上执行。(如果你想在VIC接管之前执行两个INC,那么在badline的第4个周期开始执行这两个INC有点太晚了)
更新示例:
尝试替换代码的此部分:
.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)
.for(var i=0;iNo)可以获得完全稳定的计时。这就是您使用的原因。稳定光栅是在C64上打开侧边界的唯一方法。
// a delay to get to some cycle at the end of the raster-line, so we have time to execute both inc's on
// each successive raster-line - in particular on the badlines before the VIC takes over the bus.
.for (var i=0; i<28; i++) nop
// just for illustrative purposes - not cool code :)
.for (var i=0; i<8*6; i++) {
inc $d020 // 6 cycles
inc $d021 // 6 cycles
.if ([i & %111] == 0) {
// badline
nop nop nop nop // 4*2=8 cycles
} else {
// non-badline
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
}
}