首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C64上的稳定光栅

C64上的稳定光栅
EN

Stack Overflow用户
提问于 2014-06-23 21:50:18
回答 3查看 5.4K关注 0票数 13

使用6510组装商品64,我试图创造一个稳定的光栅效果。使用双IRQ原理,我在屏幕上画了一些光栅线。我垫与NOPs匹配63个周期的每一个正常扫描线,和23个周期为每坏线。我意识到,我需要设置一个特定的起跑线,以便将我的第8次迭代与一条坏线相匹配,但是无论我把第一行放在哪一行,或者我使用什么NOPs组合,我都不能正确地确定时间。我想要完整的线条,而不是“断裂”。有人能看出我做错了什么吗?代码是在踢汇编程序格式。这是一张截图:

代码语言:javascript
复制
.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      
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-01 22:10:10

据我所知,你的问题不是你的光栅条在闪烁(即你的光栅中断是稳定的),而是你在屏幕上画的光栅条的第二行不是完全红色的。

你的问题是台词不好。(见1)

当你稳定了你的光栅中断,与你张贴的代码,你的“实际代码”将开始运行在第4周期的光栅线$3A。

你的光栅条的第二行,你想要背景色和边框颜色是红色,是一条不好的线条。(这是光栅行的30亿美元。因为$D011 = $1B,这是一个坏行,因为$D011和$D012的下3位是相同的)

在这条糟糕的线路上,第一个INC (INC . $D020)设法运行,因此边框颜色变成红色。然后,第二个公司(公司$D021)开始运行,但国际中心接管之前,它完成,因此,您的公司的$D021是没有完成后,国际中心已将巴士送回。(这是43个周期后-即将背景颜色设置为红色被延迟了43个周期)。

您几乎得到了它,但是坏行位于与您的代码预期不同的栅格线上,您需要“推送几个周期”,以便两个INC在被国际中心中断之前都在坏行上执行。(如果您希望在国际中心接管之前执行这两个INC,那么在坏行的第4周期开始执行这两个INC就为时已晚了)

更新示例:

尝试替换代码的以下部分:

代码语言:javascript
复制
.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)

在这方面:

代码语言:javascript
复制
// 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
  }
}

(警告:就内存而言,这段代码非常浪费内存-同样的效果可以很容易地用普通循环来实现)(如果您不打算显示字符图形,则可以通过修改$D011,而不是改变延迟,而不是将坏行推开)。

尝试签出HOXS64模拟器中的机器代码监视器。对于调试时间相关的问题来说,这是非常完美的。它显示了在任何给定时间你所处的光栅线的哪个周期(+它可以在中断时中断)。

希望这有所帮助:)

注意,我还没有仔细检查过你的稳定光栅程序中的陷阱,但它似乎是好的-方法是正确的,你没有任何闪烁。如果你开始得到闪烁的光栅条,你知道该修复什么。;)

如果有人读了这篇文章,不知道什么是坏话:

酷参考文献:

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

基本上,当国际中心芯片开始绘制第一条光栅线的文本线,它从CPU偷40-43周期(见下文为什么不总是43)。这些光栅线被称为“坏线条”。在一条糟糕的线路上,只有20-23个周期可用,而不是63个周期。

(更准确地说,当$D011的3位最低位等于$D012的3位(我们不在边框,屏幕没有被$D011的4位“关闭”)时,就会出现坏行)

国际中心芯片使用这43个周期中的最后40个来读取将显示在文本行上的40个字符。在这40个周期中,CPU不能执行任何指令。

然而,在这43个周期的前3个周期中,CPU实际上可以执行其指令的“写周期”--但只执行写周期,而不是读周期。(请参阅2)因此,如果您的操作码时间正确,您可以在这三个周期内执行您的指令的一些周期。(注意:只有三个写周期的指令是"brk",这通常是无用的,所以在实践中,您最多只能使用这3个周期中的2个来做有用的事情)。

注意,除了偷坏线的周期外,国际中心还将从光栅线上的CPU窃取带有精灵的循环。

2 (参见"64doc“)以了解c64不同指令的哪个周期是写周期:http://vice-emu.sourceforge.net/plain/64doc.txt

(表中写周期标记为"W“,读周期标记为"R")

X ...And在http://codebase64.org上有很多好文章

票数 14
EN

Stack Overflow用户

发布于 2014-07-01 07:47:48

为了使光栅线自由闪烁,需要一些额外的诡计来稳定时间。原因是,您永远无法确定光栅例程是在行的开头执行的,但取决于CPU“离开”主程序代码的位置,浪费了大量未知的周期来执行最后一次操作。要达到这个目标,有不同的方法,您应该查看Codebase64上的Codebase64页面,以了解更多关于这个主题的内容,并获得一些示例代码。然而,一旦你建立了一个稳定的光栅时机,你的方法看起来不错。

票数 1
EN

Stack Overflow用户

发布于 2014-06-24 02:31:45

如果我没记错的话(几年前的20+ )。

由于小的中断抖动,不太可能获得完全稳定的光栅效果的时间;因此,无论您在软件中做什么,您将有一个“闪烁”点在一条扫描线开始。

要解决这个问题,请使用精灵来隐藏闪烁的点。

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24375150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档