NESプログラミング1 (2)

1. 定数の利用

前回は,Aという文字を表示させることに成功しました.初めに,少し文字数を増やしてみましょう. まずは一行でHELLOと出力しましょう.

.setcpu "6502"
.feature c_comments                     ; /* comments */ の複数行のコメントを許可(通常はセミコロン)
.feature underline_in_numbers           ; 数値の途中に %1010_0010 のようにアンダーバーを挟めるようにする(2進数の表記に便利


; ここで指定しているものはiNESヘッダーという
; https://www.nesdev.org/wiki/INESを参照
.segment "HEADER"
        .byte "NES", $1a
        .byte $02                       ; プログラム領域のサイズ(16KB * 2)
        .byte $01                       ; キャラクタ領域のサイズ(8KB * 1)
        .byte $01                       ; 垂直ミラー(2画面が横方向につながる)
        .byte $00
        .byte $00, $00, $00, $00
        .byte $00, $00, $00, $00


;! 定数追加
PPU_CTRL1 = $2000                       ; 上位のビットからNMIのON/OFF,PPUのマスター/スレーブ(よくわからない),スプライトのサイズ,
                                        ; BGの開始アドレス,スプライトの開始アドレス,VRAMのインクリメント量,スクリーン番号
PPU_CTRL2 = $2001                       ; 赤強調,緑強調,青強調,スプライトの表示,BGの表示,左端スプライトの表示,左端BGの表示,カラーモード
PPU_SCROLL = $2005                      ; スクロール座標を指定するときに使う(一回目のストア→X座標,二回目のストア→Y座標)
PPU_ADDR = $2006                        ; VRAMのアドレス指定に使う(一回目→上位,二回目→下位のバイト)
PPU_DATA = $2007                        ; VRAMにストアするときに使う


.code                                   ; 以下プログラム領域

.segment "STARTUP"                      ; 起動時のプログラム開始位置

RESET:                                  ; RESETという名前のラベル(ここにジャンプさせることができる)
        sei                             ; IRQ禁止(割り込み処理の禁止)
        cld                             ; BCD禁止(BCD機能はファミコンで除外されているので,やる必要性はわからない)
        ldx #$ff                        ; X = #0xff(アドレスではなく,即値)
        txs                             ; スタックレジスタ(S)に#$ffを指定

        lda #0                          ; #がついてないのは10進数を示す
        ; 画面をOFFに
        sta PPU_CTRL1
        sta PPU_CTRL2

        ; RAMの初期化(ある初期値,ここでは0を入れること)を行う
        lda #0
CLEAR_MEMORY:
        sta $00, x                      ; $00XX番台は$XXと省略できる
        sta $0100, x
        sta $0200, x
        sta $0300, x
        sta $0400, x
        sta $0500, x
        sta $0600, x
        inx
        bne CLEAR_MEMORY                ; X == 0(Xが$ffからオーバーフローして0に戻る)までループ

        ; $0700番台にはスプライト情報を入れる
        ; 都合がいいので#$ffで初期化
        lda #$ff
CLEAR_SPRITE_MEMORY:
        sta $0700, x
        inx
        bne CLEAR_SPRITE_MEMORY

        ; VRAM(PPUのRAM)を初期化する
        ; アドレス$2000を初期化開始位置に指定
        lda #$20
        sta PPU_ADDR
        lda #$00
        sta PPU_ADDR

        ; $100回のループ(Xレジスタがカウンタ)を8回ループさせる(Yレジスタがカウンタ)
        ; なので,$2000~$27ff($800の領域)を初期化できる
        ; $2000~$23ffが画面1,$2400~$27ffが画面2(画面1の横隣り)の領域
        ldx #0
        ldy #8
CLEAR_VRAM:
        sta PPU_DATA
        inx
        bne CLEAR_VRAM
        dey
        bne CLEAR_VRAM

        lda #>($2000+13+14*$20)         ; 16bitのうち上位8bitだけ使う書き方
        sta PPU_ADDR
        lda #<($2000+13+14*$20)         ; 下位8bit
        sta PPU_ADDR
        lda #'H'
        sta PPU_DATA
        lda #'E'
        sta PPU_DATA
        lda #'L'
        sta PPU_DATA
        lda #'L'
        sta PPU_DATA
        lda #'O'
        sta PPU_DATA

        ; パレットテーブル(色を管理する領域)へパレットデータを転送
        ; $3f00から開始
        lda #$3f
        sta PPU_ADDR
        lda #$00
        sta PPU_ADDR
        ldx #$00
TRANSFAR_PALETTE:
        lda PALETTES, x                 ; 高級言語的に書くと A = palettes[x]
        sta PPU_DATA                    ; $3f00から順($3f00のあとは$3f01,そのあとは$3f02...)にストアされていく(ストア=RAMへの書き込み)
        inx
        cpx #$10
        bne TRANSFAR_PALETTE            ; X = $10までループ

;! 以下省略


このコードでは,HELLOと出力する以外に,少し異なっている点があります.1つめは,定数を導入したことです. 今までは直接$2006などとアドレスを指定していましたが,パッと見てわかりやすくするため,名前を付けました. (定数と呼びますが,実際にはラベル付けをしただけです.)
2つめは,表示するアルファベットを直接コード内に記述している(前はA=$41と書いていたが,今回は'A'と書いている)ことです. Aの文字コードが$41なので,'A'と書いても$41と書いても同じ値となるのです.
ここで,YY-CHRでbg_sprite.chrを開いてみましょう. Aにカーソルを当てると,下のアドレスが41と表示されるのがわかります(画像赤枠).このように,文字コードに対応する位置に文字を描いているため,'A'とすると同じAの文字を指定できるようになっています.
YY-CHRでAの文字を表示

では,次に二行でHELLO WORLDと表示してみましょう.まずは自力でやってみましょう.
        lda #>($2000+13+14*$20)         ; 16bitのうち上位8bitだけ使う書き方
        sta PPU_ADDR
        lda #<($2000+13+14*$20)         ; 下位8bit
        sta PPU_ADDR
        lda #'H'
        sta PPU_DATA
        lda #'E'
        sta PPU_DATA
        lda #'L'
        sta PPU_DATA
        lda #'L'
        sta PPU_DATA
        lda #'O'
        sta PPU_DATA

        lda #>($2000+13+16*$20)         ; 16bitのうち上位8bitだけ使う書き方
        sta PPU_ADDR
        lda #<($2000+13+16*$20)         ; 下位8bit
        sta PPU_ADDR
        lda #'W'
        sta PPU_DATA
        lda #'O'
        sta PPU_DATA
        lda #'R'
        sta PPU_DATA
        lda #'L'
        sta PPU_DATA
        lda #'D'
        sta PPU_DATA


HELLO WORLD
こうすればいいですね.前回メモリツールを使って遊んでみた人は余裕だったかもしれません.

続き制作中・・・

前の記事:NESプログラミング1 (1) | ホームへ

© 2025 astsb.net.