(適当な)ファミコンのプログラミング解説

ファミコンのプログラミング

ここではファミコンのプログラミングをゆる〜くフワッと解説します。
ソースコードも開示していますので、これを足掛かりに立派なゲームを作ってください。
なにかのお役に立てれば幸いです。

教材

以下の5つをダウンロードして任意のフォルダへ保存してください。

ROMファイルの作成

バッチファイルをダブルクリックすると、ソースコードBGデータBGデータパレットデータキャラクターデータNESASMによりアセンブルされて、ファミコンROMファイルが出来上がります。

成果物

AボタンまたはBボタンを押すと、オナラをして前へ進みます。
長〜く押すと、いっぱいオナラをしてもっと遠くへ進みます。
「僕はまだ見ぬ世界をたくさん見たいんだ!」そんな少年の心の叫びが聞こえてきそうですね(幻聴です)
ROMダウンロード

プログラム解説

INESヘッダー

作成するゲームのバンク数やマッパーを明示します。
私はマッパー0しか作ったことがありませんので、詳しい説明は他の方に聞いてください(汗)

	.inesprg 2	;プログラムバンク数(16KB*2=32KB)
	.ineschr 1	;グラフィックデータバンク数(8KB*1=8KB)
	.inesmir 0	;ミラーリング
	.inesmap 0	;マッパー0番

ゼロページ

ファミコンのCPUはMOS6502のカスタム版だそうです。MOS6502は以下の特徴があります。

今回は9個の変数を使用します。

RLE_LOW			= $00	;BGデータRLE読み出し
RLE_HIGH			= $01	;BGデータRLE読み出し
RLE_TAG			= $02	;BGデータRLE読み出し
RLE_BYTE			= $03	;BGデータRLE読み出し
Joypad1			= $0C	;1Pのジョイパッド押下
Joypad2			= $0D	;2Pのジョイパッド押下
Syori			= $30
Move_ct			= $31
Move_sw			= $32

おまじない

何も考えず、このように記載してください(笑)
VBlank、リセット、ハードウェア割り込みについての挙動設定です。

	.bank 3
	.org $FFFA	; $FFFAから開始
	.dw Mainloop	; VBlank割り込みハンドラ(1/60秒毎にmainLoopがコールされる)
	.dw Start	; リセット割り込み。起動時とリセットでStartに飛ぶ
	.dw Irq	; ハードウェア割り込みとソフトウェア割り込みによって発生

スプライトDMAの設定

8*8ドットキャラクターを7つ使用します。
8*8ドットキャラクター1つにつき、以下4つの設定が必要です。

	.bank 0	;バンク0へ切り替え
	.org $0200	;$0200から開始、スプライトDMAデータ配置
Jiki0_y:			.db 0
Jiki0_t:			.db 0
Jiki0_s:			.db 0
Jiki0_x:			.db 0
Jiki1_y:			.db 0
Jiki1_t:			.db 0
Jiki1_s:			.db 0
Jiki1_x:			.db 0
Jiki2_y:			.db 0
Jiki2_t:			.db 0
Jiki2_s:			.db 0
Jiki2_x:			.db 0
Jiki3_y:			.db 0
Jiki3_t:			.db 0
Jiki3_s:			.db 0
Jiki3_x:			.db 0
Puu0_y:			.db 0
Puu0_t:			.db 0
Puu0_s:			.db 0
Puu0_x:			.db 0
Puu1_y:			.db 0
Puu1_t:			.db 0
Puu1_s:			.db 0
Puu1_x:			.db 0
He_y:			.db 0
He_t:			.db 0
He_s:			.db 0
He_x:			.db 0

いよいよここからプログラムが始まります

	.org $8000	; $8000から開始

起動時またはリセット時の処理

おまじないから飛んできて処理されます。
ファミコンの電源が入った、リセット押された、そんな時に処理されるルーチンです。

Start:
	sei	; 割り込み不許可
	cld	; デシマルモードフラグクリア
	ldx #$FF
	txs	; スタックポインタ初期化 
	lda #%00001000	; VBlank割り込み禁止
	sta $2000
	lda #%00000110	; 初期化中はスプライトとBGを表示OFFにする
	sta $2001
	jsr Load_pal	;パレット読み込み
	jsr Bg_init	;背景初期化1
	jsr Name_init	;背景初期化2
	jsr Zero_init	;メモリ初期化
	jsr Spr_init	;スプライトDMA初期化
	jsr Wait_vsync
	lda #%00011110	; BGの表示をONにする
	sta $2001
	lda #%10001000	;割り込み許可フラグを立てる
	sta $2000
	
	lda #%00001111
	sta $4015
	
	lda #40	;自機の初期位置
	sta Jiki0_x
	lda #151
	sta Jiki0_y
	jsr Jiki_set
	
	lda #10
	sta <Syori
.Lp	; VBlank割り込み発生を待つだけの無限ループ
	jmp .Lp

メインルーチン

おまじないから飛んできて処理されます。
ゲーム中は、VBlankが発生するたびに、このメインルーチンが繰り返し実行されます。つまり1/60秒に1回処理されます。
ただ、最初の1回だけはゲーム画面を描画したいので、Syoriに保存された数字を見て処理の流れを作っています。

Mainloop:
	lda <Syori
	cmp #10
	beq .10
	cmp #20
	beq .20
	jmp .9
.10	;ステージ画面描画
	jsr Stage_byouga
	jmp .9
.20	;ゲームルーチン
	jsr Game_rtn
	jmp .9
.9
	rti

。。。つづく。。。