第14章 スタック


初期化

 ここまで、あまりちゃんと初期化していませんでしたが、少し見直そうかと思います。 ファミコンのリセットの初頭では以下のような記述をするのが一般的のようです。

Start:
	sei			; 割り込み不許可
	cld			; デシマルモードフラグクリア
	ldx #$ff
	txs			; スタックポインタ初期化(Xレジスタ→Sレジスタ) 

 IRQ/BRK割り込み(NMI割り込みとは別)を禁止し、デシマルモードフラグをクリアしています。(ただしファミコンはデシマルモードは無い) そしてスタックポインタを$FF番地(実際は$1FF)に初期化します。 このサイト程度のプログラムではあまりちゃんと初期化しなくても動きますが、ファミコンの初期化では最初にこれを行うのが常識的らしいので、 素直に記述したほうがよいのでしょう。

 またIRQ/BRK割り込みは、使わない場合でも以下のように記述するのが一般的のようです。


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

IRQ:
	rti

 そして、ここまで作ってきたプログラムは、ゼロページを初期化してないので、リセットしてもその状態で実行されてしまいます。 今回クリアすることにします。 スプライトDMA転送領域も初期化すべきですが、これは今回は見送ります。

ローカルラベル

 ラベルが増えてくると、ラベル名が重複しないように一意にするのが大変です。そういう時は、以下のようにローカルラベルを使用しましょう。 "."で始まる名前を使うと、":"が後ろに付く従来のグローバルラベル2つの間に、他の場所で重複している名前を使うことができます。

AKEYSound:
	; サウンド待ちカウンタAが0でない場合はサウンドを鳴らさない
	lda <Sound_A
	beq .soundSub
	rts
.soundSub
	lda #10			; 1/6秒に1回鳴らす
	sta <Sound_A

スタック

 RAMの$100〜$1FFがスタック領域と以前説明しました。(スタックの概念自体はここでは説明しないので、わからない人は調べてください) この領域を使わないのは勿体ないのですが、何も気にせず使うことはできません。 NMI割り込みが発生すると、発生前の上位アドレス、下位アドレス、ステータスレジスタの内容がスタックに保存され、rtiで復帰したときにスタックポインタが戻されます。 また、jsrで移動すると、移動した上位アドレス、下位アドレスが保存され、rtsで戻ったときにスタックポインタが戻されます。 スタックをPUSHしたままサブルーチンや割り込みから復帰するとスタックの整合性が破綻して暴走してしまうので、PUSHした同じ回数だけPULLして元の位置に戻します。

 ここまでのプログラムでは、スタックを使う必要性は特に無いのですが、無理矢理使いましょう。 前章までのプログラムを、キー入力の値をスタックに次々とPUSHして、後でPULLして参照するように直します。


	; パッド入力チェック
	lda $4016  	; Aボタン
	pha		; AをPUSH
	lda $4016  	; Bボタン
	pha		; AをPUSH
	lda $4016  	; Selectボタンをスキップ
	lda $4016  	; Startボタンをスキップ
	lda $4016  	; 上ボタン
	pha		; AをPUSH
	lda $4016  	; 下ボタン
	pha		; AをPUSH
	lda $4016  	; 左ボタン
	pha		; AをPUSH
	lda $4016  	; 右ボタン
	pha		; AをPUSH

 以上のように、キー情報を取得してphaでスタック領域に格納し、

	pla		; AをPULL(右ボタンの内容)
	and #1     	; AND #1
	beq pull_A1	; 0ならばPull_A1へジャンプ
	jsr RIGHTKEYdown
pull_A1:
	pla		; AをPULL(左ボタンの内容)
	and #1     	; AND #1
	beq pull_A2	; 0ならばPull_A2へジャンプ
	jsr LEFTKEYdown
pull_A2:
	pla		; AをPULL(下ボタンの内容)
	and #1     	; AND #1
	beq pull_A3	; 0ならばPull_A3へジャンプ
	jsr DOWNKEYdown
pull_A3:
	pla		; AをPULL(上ボタンの内容)
	and #1     	; AND #1
	beq pull_A4	; 0ならばPull_A4へジャンプ
	jsr UPKEYdown
pull_A4:
	pla		; AをPULL(Bボタンの内容)
	and #1     	; AND #1
	beq pull_A5	; 0ならばPull_A5へジャンプ
	jsr BKEYSound
pull_A5:
	pla		; AをPULL(Aボタンの内容)
	and #1     	; AND #1
	beq setSpr	; 0ならばsetSprへジャンプ
	jsr AKEYSound

 そしてこのように、plaでAレジスタにキー情報を次々と戻して判定します。これがソースです。 注意する点は、A→B→上→下→左→右の順で格納し、右→左→下→上→B→Aのように逆順で取り出してるところです。
 しかし、このように1bitずつで済む情報に1byteずつ領域を使っていては、残りの7bitが無駄です。 キー入力処理は、1ビットずつバッファにビットシフトしながらためていって、あとで取り出すやり方のほうが良いです。
 興味がある人は、これをダウンロードしてgetPadBitラベル以下を見てください。
トップページ 前のページ 次のページ
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送