ドラクエ風RPGファミコンプログラム講座

NES アセンブラ入門編】

【 算術演算と論理演算】

ファミコン(6502)の算術演算は、加算と減算のみで、

キャリー付きの加算命令と減算命令が1つずつあるだけです。

論理積命令( AND ) 〗 

 *論理積命令 AND は、Aレジスタオペランドの各BITを比較して、双方が1の時

 のみ そのBITを 1 にする。

 

  『例』

 lda #$44

  and #$0f

  *上記のコードは Aレジスタは #%01000100 オペランドが #$00001111

      なので。

Aレジスタ    #$01000100

オペランド     #$00001111

演算結果                 #$00000100    

*上の演算結果で、#$04 になるのが理解できるとおもう。このことから AND

 命令は、特定のBITを取り出すのに使われる。

 

論理和命令( ORA ) 〗 

 *論理積命令 ORA は、Aレジスタオペランドの各BITを比較して、片方が1の時

 そのBITを 1 にする。

『例』

 lda #$44

   and #$0f

  ora #$80

*上記のコードは Aレジスタは 論理積の続きで #%00000100 オペランドが #$1000000 なので。

Aレジスタ    #$00000100

オペランド     #$10000000

演算結果                 #$10000100    

*上の演算結果で、#$84 になるのが理解できるとおもう。このことから ORA

 命令は、特定のBITをはめ込むのに使われる。

 

  

 

 

f:id:chien1956:20200220202414p:plain

 

 

ドラクエ風RPGファミコンプログラム講座

NES アセンブラ入門編】

【 算術演算と論理演算】

ファミコン(6502)の算術演算は、加算と減算のみで、

キャリー付きの加算命令と減算命令が1つずつあるだけです。

〖 加算命令( ADC ) 〗 

 *加算命令 ADC は、Aレジスタオペランドを加算し更にキャリーフラグを

 加えます。

  『例』

 lda #$44

  clc

  adc #$56

  *CLC は、キャリーフラグをリセットする命令です。

 〖 減算命令(SBC ) 〗 

 *減算命令 SBC は、Aレジスタオペランド減算し更にキャリーフラグを

 引きます。

  『例』

 lda #$44

  sec

  sbc #$56

  *SEC は、キャリーフラグをセットする命令です。

 〖 インクリメント・デクリメント 

  ☆INC(インクリメント)は、メモリーの値を+1する命令。

  ☆DEC(デクリメント)は、メモリーの値を-1する命令。 

  ☆INX・INXYは、レジスタX・Y を +1する命令です。

  ☆DEX・DEYは、レジスタX・Y を -1 する命令です。

⁂インクリメント・デクリメント命令は、キャリーフラグ・オーバーフローフラグを

 変化させない。

f:id:chien1956:20200220202414p:plain

 

 

ドラクエ風RPGファミコンプログラム講座

NES アセンブラ入門編】

【 16bitの変数】

ファミコン(6502)は、扱えるDATAが8ビット(1byte)長なので16ビットを

 超えるDATAは、8ビットずつ数回にわけて処理する必要があります。

『 メインカウンターの設置』

*ゲームプログラムには欠かせないメインカウンター(CT)を設置します。

  ZEROPAGEに 変数 CTを宣言します。  CT  = $10

 TEST用プログラムの無限ループの中に inc CT を追加します。

 これを 2byte を連動させるには、繰り上がりが発生したときに上位BYTEに加算

 します。

loop000:

   inc CT

   jmp loop000

inc は、オペランド+1する命令。

inc CT

bne loop000

inc CT+1

jmp loop000

*上記は、キャリー判定ではなく CT が0になったかを見ています。

 bne は、ゼロ出ない時 loop000 にjmpします。 

 

 

 

 

f:id:chien1956:20200220202414p:plain

 

 

ドラクエ風RPGファミコンプログラム講座

NES アセンブラ入門編】

【 16bitの変数】

ファミコン(6502)は、扱えるDATAが8ビット(1byte)長なので16ビットを

 超えるDATAは、8ビットずつ数回にわけて処理する必要があります。

『 メインカウンターの設置』

*ゲームプログラムには欠かせないメインカウンター(CT)を設置します。

 

 TEST用プログラムの無限ループの中に

[例]

CT  = $10

*上記は、CT という名の変数を ゼロページ $10 で使うことを宣言しています、

 ファミコン(6502)では、レジスタが8bit なのでCTは8bitの変数に

 なりますが、16bit 以上の変数を扱う場合は CT,CT+1,CT+2 の様にアクセス

 します、この場合 CT が最下位 CT+2 が最上位になり $1034df という値だとすると

 CT = $df, CT+1 = $34, CT+2 = $10 に格納することになります。

 ファミコンの変数は、宣言のみで代入はできません、 ROM領域から格納します。

 lda #100, sta <$10 のように代入します、ゼロページ以外の宣言方法は .org $0300

 .dw 0,   db $00 の様に変数領域を確保します、DWは、2バイト  DBは、

  1バイトです。

 

f:id:chien1956:20200220202414p:plain

 

ドラクエ風RPGファミコンプログラム講座

NES アセンブラ入門編】

アセンブラでの変数】

アセンブラに於いて変数の扱いは、基本的にRAMの領域なら自由に使えますが、

 プログラムの領域と分けて使うのが望ましいでしょう。

 ファミコンでは、プログラムの領域はROMになっているので競合の心配は、 

 ありません。 ファミコンでは、変数用にゼロページが用意されていて、

 高速且つ利便性にも優れています,   RAM領域は $0000~$07ff まででスタック領域

 以外は自由につかえます。

『 変数の宣言』

*ゼロページに変数を宣言するには、下記の様に書きます。

変数名 = $**

[例]

CT  = $10

*上記は、CT という名の変数を ゼロページ $10 で使うことを宣言しています、

 ファミコン(6502)では、レジスタが8bit なのでCTは8bitの変数に

 なりますが、16bit 以上の変数を扱う場合は CT,CT+1,CT+2 の様にアクセス

 します、この場合 CT が最下位 CT+2 が最上位になり $1034df という値だとすると

 CT = $df, CT+1 = $34, CT+2 = $10 に格納することになります。

 ファミコンの変数は、宣言のみで代入はできません、 ROM領域から格納します。

 lda #100, sta <$10 のように代入します、ゼロページ以外の宣言方法は .org $0300

 .dw 0,   db $00 の様に変数領域を確保します、DWは、2バイト  DBは、

  1バイトです。

 

f:id:chien1956:20200220202414p:plain

 

ドラクエ風RPGファミコンプログラム講座

NES アセンブラプログラミング編】

【libraryの作成 】

 

*今回からは、前回のプログラムを使って、ライブラリーを作成していきます。

 ファイル名は、library.asm とします。

【TEST用プログラム再掲載】 

;------------------------------------------------------

.inesprg 1
.ineschr 1
.inesmir 1
.inesmap 0
;-------------------------------------------------------

.bank 1
.org $FFFA
.dw 0
.dw Start
.dw 0
;--------------------------------------------------------------
.bank 0

.org $8000;
Start:
sei ;割り込み禁止
cld ;フラグクリア
ldx #$ff ;スタックポインターの初期化
txs
lda #%00001000 ; ここではVBlank割り込み禁止
sta $2000

lda #%00011000

sta $2001

VB0:

lda $2002

bpl VB0

jsr palette

jsr zero_init

 

*********

*********


main_loop:
jmp main_loop

.include  "library.asm"

palette:

lda #$3f
sta $2006
lda #$00
sta $2006
ldx #0
pal_loop:
lda pall,x
sta $2007
inx
cpx #32
bne pal_loop
rts

zero_init:
lda #0
tax
lp00:
sta <$00,x
inx
bne lp00
rts

;-------------------------------------------------------------pall:
.db $0f,$30,$11,$21
.db $0f,$29,$1a,$27
.db $0f,$10,$00,$29
.db $0f,$29,$37,$11
.db $0f,$35,$30,$12
.db $0f,$26,$24,$25
.db $0f,$26,$27,$28
.db $0f,$11,$12,$13

*赤色の部分を切り取って、別ファイルにしファイル名を付けて保存します。

 そこへ  .include "library.asm” を追加します。

   .include は、この場所にアセンブラファイルを挿入しますという疑似命令です。

 バイナリーファイルをインクルードするには、.incbin を使います。

 

 

 

 

ドラクエ風RPGファミコンプログラム講座

NES アセンブラプログラミング編】

【 TEST用プログラムの作成 】

 〖 〗

*下記のコードはエミュレータで動く最小プログラムでFCEUXでは、動きましたが

 VirtualNES では、ゼロページの初期化とパターンDATAの設置までしないと

 動かないようです。ネストピアは、さらにシビアなようです。

 *****印の所にテストプログラムを書いていきます。

 

;------------------------------------------------------

.inesprg 1
.ineschr 1
.inesmir 1
.inesmap 0
;-------------------------------------------------------

.bank 1
.org $FFFA
.dw 0
.dw Start
.dw 0
;--------------------------------------------------------------
.bank 0

.org $8000;
Start:
sei ;割り込み禁止
cld ;フラグクリア
ldx #$ff ;スタックポインターの初期化
txs
lda #%00001000 ; ここではVBlank割り込み禁止
sta $2000

lda #%00011000

sta $2001

VB0:

lda $2002

bpl VB0

jsr palette

jsr zero_init

 

*********

*********


main_loop:
jmp main_loop

  

palette:

lda #$3f
sta $2006
lda #$00
sta $2006
ldx #0
pal_loop:
lda pall,x
sta $2007
inx
cpx #32
bne pal_loop
rts

zero_init:
lda #0
tax
lp00:
sta <$00,x
inx
bne lp00
rts

;-------------------------------------------------------------pall:
.db $0f,$30,$11,$21
.db $0f,$29,$1a,$27
.db $0f,$10,$00,$29
.db $0f,$29,$37,$11
.db $0f,$35,$30,$12
.db $0f,$26,$24,$25
.db $0f,$26,$27,$28
.db $0f,$11,$12,$13

*コントロールレジスタの設定は、BGパターンが $0000 スプライトパターンが

 $1000,  BG・スプライトの表示ON