MMC3(マッパー4)でラスタスクロール
ギコ猫でもわかるファミコンプログラミング - ラスタースクロール を MMC3 で書き換えたもの。画面走査のタイミングのプログラムだなんて、ファミコンはおっかない世界だねぇ。
参考文書
;;; MMC3 でラスタスクロールするテスト ;;; http://gikofami.fc2web.com/nes/nes015.html の改変 ;;; giko3.pal, giko3.bkg は上のページから拾ってね .inesprg 1 ; プログラムバンク数 .ineschr 1 ; CHR バンク数 .inesmir 0 ; 水平ミラーリング .inesmap 4 ; mapper #4 (MMC3) .bank 0 .org $C000 SIZE: .equ 3 ; スクロールする領域の数 lines: .byte 120, 50 ; スクロールする領域の高さ。スキャンライン数 speeds: .byte 0, 1, 2 ; スクロールスピード target: .equ $00 ; 次の IRQ でこのインデックスのスクロール領域を設定する scrolls: .equ $01 ; 現在のスクロールX位置. ここから SIZE bytes ;;; スタート/リセット時に呼ばれる start: ;; 初期化中は割り込み禁止 sei ; IRQ lda #%00001000 ; NMI sta $2000 cld ; デシマルモードクリア ldx #$ff ; スタック初期化 txs jsr vwait ; VBlank待ち lda #%00000110 ; 初期化中はスプライトとBGをOFF sta $2001 lda #$40 ; frame counter off sta $4017 ; (mapper のみ IRQ 発行) lda #$01 sta $a000 ; MMC3 水平ミラーリング lda #$00 sta $a001 ; これなに? ;; ゼロページ初期化 lda #$00 ldx #$00 .initZeroPage: sta <$00, x inx bne .initZeroPage ;; パレット初期化 ldx #$3F ; PPU $3F00 stx $2006 ldx #$00 stx $2006 .initPalette lda PALETTE_DATA, x sta $2007 inx cpx #$20 bne .initPalette ;; ネームテーブル生成 (空と地面を480こずつ) lda #$20 ; PPU $2000 sta $2006 lda #$00 sta $2006 lda #$00 ; 空 ldx #250 jsr writeVRAM ldx #230 jsr writeVRAM lda #$01 ; 地面 ldx #250 jsr writeVRAM ldx #230 jsr writeVRAM lda #%00011110 ; スプライトとBGの表示をONにする sta $2001 lda #%10001000 ; NMI割り込み許可 sta $2000 cli ; IRQ割り込み許可 .loop jmp .loop ;;; VBlank のタイミングで呼ばれる nmi: lda #$00 sta target jsr scroll rti ;;; scroll でセットしたスキャンラインのタイミングで呼ばれる irq: ;; レジスタをスタックに退避 pha txa pha tya pha jsr scroll ;; レジスタを IRQ 前の状態に復帰 pla tay pla tax pla rti ;;; target 番目のスクロールをセット ;;; target のインクリメントと IRQ のセットもする scroll: lda $2002 ; スクロールクリア ldx target lda scrolls, x sta $2005 ; set scroll X lda #$00 sta $2005 ; Y スクロールは固定 lda scrolls, x clc adc speeds, x sta scrolls, x ; increment scroll ;; target をインクリメント inx cpx #SIZE beq .quit ;; 次の IRQ セット dex lda lines, x ; IRQ を呼ぶまでのスキャンライン sta $c000 sta $c001 lda #$01 sta $e000 ; acknowledge the IRQ sta $e001 ; enable the IRQ inx stx target rts .quit ;; 最後なら IRQ 終わり lda #$01 sta $e000 ldx #$00 stx target rts ;;; VBlank 待ち vwait: .wait: lda $2002 bpl .wait rts ;;; a を $2007 に x 回書き込む writeVRAM: .write: sta $2007 dex bne .write rts PALETTE_DATA: .incbin "giko3.pal" .bank 1 .org $fffa .dw nmi, start, irq .bank 2 .incbin "giko3.bkg"