Assembly C64上的稳定光栅

Assembly C64上的稳定光栅,assembly,6510,Assembly,6510,使用Commodore64上的6510 assembly,我试图创建一个稳定的光栅效果。使用双IRQ原理,我在屏幕上绘制了一些光栅线。我用NOP进行pad,使每个正常扫描线匹配63个周期,每个不良扫描线匹配23个周期。我意识到我需要设定一个特定的开始线,以便将我的第八次迭代与一个坏线相匹配,但无论我把第一行放在哪一行,或者我使用的是哪种NOP组合,我都无法获得正确的时机。我想要完整的线,而不是“断”。有人能看出我做错了什么吗?代码采用Kick汇编程序格式。下面是一个屏幕截图: .pc = $08

使用Commodore64上的6510 assembly,我试图创建一个稳定的光栅效果。使用双IRQ原理,我在屏幕上绘制了一些光栅线。我用NOP进行pad,使每个正常扫描线匹配63个周期,每个不良扫描线匹配23个周期。我意识到我需要设定一个特定的开始线,以便将我的第八次迭代与一个坏线相匹配,但无论我把第一行放在哪一行,或者我使用的是哪种NOP组合,我都无法获得正确的时机。我想要完整的线,而不是“断”。有人能看出我做错了什么吗?代码采用Kick汇编程序格式。下面是一个屏幕截图:

.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
  }
}