NESASMのBG描きこみルーチンについて
NESASMのBG描きこみルーチンについて
ファミコンソフトをC言語で作るのは実用的ではないと思いまして、ファミコンのアセンブリ言語を
使っています。そこで問題が生じました。以下のC言語で実装したBG描きこみルーチンを
6502のアセンブリ言語で実装しようとしたらエラーが出てしまいました。
どうすればエラーを回避し、思い通りの結果が期待できるでしょうか?
どうかみなさまお力を貸してください。
あと、アセンブリ言語でもこの掲示板に書き込むのは適切だったでしょうか…?
他に有名なアセンブリ言語の掲示板を知らないので良かったらそちらも教えていただくと嬉しいです。
void DrawBG(unsigned char x,unsigned char y,unsigned char number)
{
  int adr;
  adr = (y-1)*32+x;
  *(char*)0x2006 = 0x20+adr/256;
  *(char*)0x2006 = adr;
  *(char*)0x2007 = number;
}
C言語で記述するとこうなるのですが、NESASMというファミコン用のアセンブラでこうなるように
記述してみたのですが、エラーが出てしまいます。
Sum EQU $0010
Count EQU $0011
AA EQU $0012
B EQU $0013
A2 EQU $0014
B2 EQU $0015
Sum2 EQU $0016
ADR EQU $0017
XX EQU $0018
YY EQU $0019
NUM EQU $0020
Div:
lda AA
sta Sum
lda #$00
sta Count
lda Sum
loop:
inc Count
sbc B
bne loop
rts
Mul:
lda #$00
sta Sum2
loop2:
ldx B2
adc A2
dex
bne loop2
sta Sum2
rts
wrtBG:
lda YY
dec a
lda YY
sta A2
lda #32
sta B2
jsr mul
lda Sum2
adc XX
sta ADR
lda ADR
sta AA
lda #256
sta B
jsr div
lda Count
adc #$20
sta $2006
lda ADR
sta $2006
lda NUM
sta $2007
rts
エラーは次のとおりです。
Microsoft (R) KKCFUNC バージョン 1.10
Copyright (C) Microsoft Corp. 1991,1993. All rights reserved.
KKCFUNC が組み込まれました.
マイクロソフトかな漢字変換 バージョン 2.51
(C)Copyright Microsoft Corp. 1992-1993
NES Assembler (v2.0)
#[1] PUTSTRING.ASM
131 03:0038 jsr mul
Undefined symbol in operand field!
137 03:004A lda #256
Incorrect immediate value!
139 03:004D jsr div
Undefined symbol in operand field!
# 3 ERROR(s)
C:\DOCUME~1\HP\デスク~1\PUTSTR~1>
使っています。そこで問題が生じました。以下のC言語で実装したBG描きこみルーチンを
6502のアセンブリ言語で実装しようとしたらエラーが出てしまいました。
どうすればエラーを回避し、思い通りの結果が期待できるでしょうか?
どうかみなさまお力を貸してください。
あと、アセンブリ言語でもこの掲示板に書き込むのは適切だったでしょうか…?
他に有名なアセンブリ言語の掲示板を知らないので良かったらそちらも教えていただくと嬉しいです。
void DrawBG(unsigned char x,unsigned char y,unsigned char number)
{
  int adr;
  adr = (y-1)*32+x;
  *(char*)0x2006 = 0x20+adr/256;
  *(char*)0x2006 = adr;
  *(char*)0x2007 = number;
}
C言語で記述するとこうなるのですが、NESASMというファミコン用のアセンブラでこうなるように
記述してみたのですが、エラーが出てしまいます。
Sum EQU $0010
Count EQU $0011
AA EQU $0012
B EQU $0013
A2 EQU $0014
B2 EQU $0015
Sum2 EQU $0016
ADR EQU $0017
XX EQU $0018
YY EQU $0019
NUM EQU $0020
Div:
lda AA
sta Sum
lda #$00
sta Count
lda Sum
loop:
inc Count
sbc B
bne loop
rts
Mul:
lda #$00
sta Sum2
loop2:
ldx B2
adc A2
dex
bne loop2
sta Sum2
rts
wrtBG:
lda YY
dec a
lda YY
sta A2
lda #32
sta B2
jsr mul
lda Sum2
adc XX
sta ADR
lda ADR
sta AA
lda #256
sta B
jsr div
lda Count
adc #$20
sta $2006
lda ADR
sta $2006
lda NUM
sta $2007
rts
エラーは次のとおりです。
Microsoft (R) KKCFUNC バージョン 1.10
Copyright (C) Microsoft Corp. 1991,1993. All rights reserved.
KKCFUNC が組み込まれました.
マイクロソフトかな漢字変換 バージョン 2.51
(C)Copyright Microsoft Corp. 1992-1993
NES Assembler (v2.0)
#[1] PUTSTRING.ASM
131 03:0038 jsr mul
Undefined symbol in operand field!
137 03:004A lda #256
Incorrect immediate value!
139 03:004D jsr div
Undefined symbol in operand field!
# 3 ERROR(s)
C:\DOCUME~1\HP\デスク~1\PUTSTR~1>
Re:NESASMのBG描きこみルーチンについて
ざっとしか見ていませんが...
> 131 03:0038 jsr mul
> Undefined symbol in operand field!
> 139 03:004D jsr div
> Undefined symbol in operand field!
この二つは、単にシンボルの大文字・小文字がそろっていないだけでは?
> 137 03:004A lda #256
> Incorrect immediate value!
ldaのオペランドに指定できるイミディエイト値は8ビットなので、256だと大きすぎます。
このアセンブリ言語のコードをどうやって得たのかわかりませんが、ぱっと見ただけでもいろいろ怪しいところがあります。
そもそも乗除算は必要ありませんし、個々の命令の使い方もおかしいところだらけです。
(キャリーフラグを放置したままadcとか...)
> 131 03:0038 jsr mul
> Undefined symbol in operand field!
> 139 03:004D jsr div
> Undefined symbol in operand field!
この二つは、単にシンボルの大文字・小文字がそろっていないだけでは?
> 137 03:004A lda #256
> Incorrect immediate value!
ldaのオペランドに指定できるイミディエイト値は8ビットなので、256だと大きすぎます。
このアセンブリ言語のコードをどうやって得たのかわかりませんが、ぱっと見ただけでもいろいろ怪しいところがあります。
そもそも乗除算は必要ありませんし、個々の命令の使い方もおかしいところだらけです。
(キャリーフラグを放置したままadcとか...)
Re:NESASMのBG描きこみルーチンについて
>このアセンブリ言語のコードをどうやって得たのかわかりませんが、
>ぱっと見ただけでもいろいろ怪しいところがあります。
>そもそも乗除算は必要ありませんし、個々の命令の使い方もおかしいところだらけです。
>(キャリーフラグを放置したままadcとか...)
すみません。。ファミコンのアセンブリ言語やるの久しぶりなもので…私が書いたコードです。
> 131 03:0038 jsr mul
> Undefined symbol in operand field!
> 139 03:004D jsr div
> Undefined symbol in operand field!
>この二つは、単にシンボルの大文字・小文字がそろっていないだけでは?
そうですね。ありがとうございます。
> 137 03:004A lda #256
> Incorrect immediate value!
>ldaのオペランドに指定できるイミディエイト値は8ビットなので、256だと大きすぎます。
256だと大きすぎる場合、どうすれば実装すればいいでしょうか?
>ぱっと見ただけでもいろいろ怪しいところがあります。
>そもそも乗除算は必要ありませんし、個々の命令の使い方もおかしいところだらけです。
>(キャリーフラグを放置したままadcとか...)
すみません。。ファミコンのアセンブリ言語やるの久しぶりなもので…私が書いたコードです。
> 131 03:0038 jsr mul
> Undefined symbol in operand field!
> 139 03:004D jsr div
> Undefined symbol in operand field!
>この二つは、単にシンボルの大文字・小文字がそろっていないだけでは?
そうですね。ありがとうございます。
> 137 03:004A lda #256
> Incorrect immediate value!
>ldaのオペランドに指定できるイミディエイト値は8ビットなので、256だと大きすぎます。
256だと大きすぎる場合、どうすれば実装すればいいでしょうか?
Re:NESASMのBG描きこみルーチンについて
> >ldaのオペランドに指定できるイミディエイト値は8ビットなので、256だと大きすぎます。
> 256だと大きすぎる場合、どうすれば実装すればいいでしょうか?
この256は、adr/256の除数ですよね。
adrのアドレスはADRだと思いますが、1バイト分しか確保されていないようです(直後はXXなので)。それでよいのでしょうか?
そうではなく、ADRとADR+1の2バイトでadrを表現するのであれば、256で割るということは上位1バイトを取ればよいので、割り算なんかしなくても、
lda ADR+1
で済むはずですね。
> 256だと大きすぎる場合、どうすれば実装すればいいでしょうか?
この256は、adr/256の除数ですよね。
adrのアドレスはADRだと思いますが、1バイト分しか確保されていないようです(直後はXXなので)。それでよいのでしょうか?
そうではなく、ADRとADR+1の2バイトでadrを表現するのであれば、256で割るということは上位1バイトを取ればよいので、割り算なんかしなくても、
lda ADR+1
で済むはずですね。
Re:NESASMのBG描きこみルーチンについて
>たかぎさん
256を割らなくても、+1すればいいという事でしょうか?
アセンブリソースコードを次のように直してみたのですが、
やはりBGに書き込めませんでした。
何が駄目だったのでしょうか?
wrtBG:
lda YY
dec a
clc
asl a
asl a
asl a
asl a
asl a
clc
adc XX
sta ADR
clc
lda ADR+1
clc
adc #$20
sta $2006
lda ADR
sta $2006
lda NUM
sta $2007
rts
256を割らなくても、+1すればいいという事でしょうか?
アセンブリソースコードを次のように直してみたのですが、
やはりBGに書き込めませんでした。
何が駄目だったのでしょうか?
wrtBG:
lda YY
dec a
clc
asl a
asl a
asl a
asl a
asl a
clc
adc XX
sta ADR
clc
lda ADR+1
clc
adc #$20
sta $2006
lda ADR
sta $2006
lda NUM
sta $2007
rts
Re:NESASMのBG描きこみルーチンについて
もしかして、僕はものすごい勘違いをしてますか?
ビット演算系は、かなり不得意なので、丁寧に教えてください。
(アセンブリ言語向いてないかも)
ビット演算系は、かなり不得意なので、丁寧に教えてください。
(アセンブリ言語向いてないかも)
Re:NESASMのBG描きこみルーチンについて
レジスタが8ビットしかないことを再認識してください。
> ADR+1の意味がよく分からないです。
変数adrの値は、ADR+0, ADR+1の2バイトに格納されるはずですね。
6502はリトルエンディアンですので、ADR+0に下位8ビット、ADR+1に上位8ビットが入ります。
16ビットの値を256で割るということは、上位8ビットだけを取り出せばよいので、ADR+1を読めばよいことになります。
> ADR+1の意味がよく分からないです。
変数adrの値は、ADR+0, ADR+1の2バイトに格納されるはずですね。
6502はリトルエンディアンですので、ADR+0に下位8ビット、ADR+1に上位8ビットが入ります。
16ビットの値を256で割るということは、上位8ビットだけを取り出せばよいので、ADR+1を読めばよいことになります。
Re:NESASMのBG描きこみルーチンについて
>レジスタが8ビットしかないことを再認識してください。
> ADR+1の意味がよく分からないです。
>変数adrの値は、ADR+0, ADR+1の2バイトに格納されるはずですね。
>6502はリトルエンディアンですので、ADR+0に下位8ビット、ADR+1に上位8ビットが入ります。
>16ビットの値を256で割るということは、上位8ビットだけを取り出せばよいので、
>ADR+1を読めばよいことになります。
分かりました。ありがとうございます。
あと、計算式で32倍するところがあるのですが、これはどう実装すればいいでしょうか?
32倍の限界はレジスタが8ビットしかないので、7*32までしか出来ません。
> ADR+1の意味がよく分からないです。
>変数adrの値は、ADR+0, ADR+1の2バイトに格納されるはずですね。
>6502はリトルエンディアンですので、ADR+0に下位8ビット、ADR+1に上位8ビットが入ります。
>16ビットの値を256で割るということは、上位8ビットだけを取り出せばよいので、
>ADR+1を読めばよいことになります。
分かりました。ありがとうございます。
あと、計算式で32倍するところがあるのですが、これはどう実装すればいいでしょうか?
32倍の限界はレジスタが8ビットしかないので、7*32までしか出来ません。
Re:NESASMのBG描きこみルーチンについて
> あと、計算式で32倍するところがあるのですが、これはどう実装すればいいでしょうか?
5ビット分左シフトします。
ただし、シフト対象は16ビットにしなければなりません。
下位ビットに対してはASL命令で、上位8ビットに対してはROL命令でシフトしてください。
5ビット分左シフトします。
ただし、シフト対象は16ビットにしなければなりません。
下位ビットに対してはASL命令で、上位8ビットに対してはROL命令でシフトしてください。
Re:NESASMのBG描きこみルーチンについて
ソースを書いてみたらこうなったのですが、何がいけなかったのでしょうか?
wrtBG:
lda YY
dec a
clc
sta N
rol N+1
rol N+1
rol N+1
rol N+1
rol N+1
asl N
asl N
asl N
asl N
asl N
clc
lda N
adc XX
sta ADR
sta ADR+1
clc
adc #$20
sta ADR
sta $2006
lda ADR+1
clc
adc #32
sta $2006
lda NUM
sta $2007
rts
wrtBG:
lda YY
dec a
clc
sta N
rol N+1
rol N+1
rol N+1
rol N+1
rol N+1
asl N
asl N
asl N
asl N
asl N
clc
lda N
adc XX
sta ADR
sta ADR+1
clc
adc #$20
sta ADR
sta $2006
lda ADR+1
clc
adc #32
sta $2006
lda NUM
sta $2007
rts
Re:NESASMのBG描きこみルーチンについて
もう少し命令セットの解説をよく読んで、レジスタやフラグの振る舞いを把握するようにしてください。
rol N+1
rol N+1
rol N+1
rol N+1
rol N+1
asl N
asl N
asl N
asl N
asl N
上はどういう意図なのか、説明していただけますか?
rol N+1
rol N+1
rol N+1
rol N+1
rol N+1
asl N
asl N
asl N
asl N
asl N
上はどういう意図なのか、説明していただけますか?
Re:NESASMのBG描きこみルーチンについて
ネットカフェから書き込みます。
rol a+1がエラーでうまくいかなかったのでNという変数をでっちあげ
sta N
rol N+1
rol N+1
rol N+1
rol N+1
rol N+1
asl N
asl N
asl N
asl N
asl N
としました。
rol a+1がエラーでうまくいかなかったのでNという変数をでっちあげ
sta N
rol N+1
rol N+1
rol N+1
rol N+1
rol N+1
asl N
asl N
asl N
asl N
asl N
としました。
Re:NESASMのBG描きこみルーチンについて
シフトに入る前にclcを行っていますから、初期の時点でキャリーフラグは0、Nにはstaでストアした値、N+1は不定です。
N、N+1およびキャリーの状態を追っていくと...
このように、命令を実行する度に、各ビットがどうなるのかを追っていくことが大切です。

N、N+1およびキャリーの状態を追っていくと...
C N N+1 sta N 0 ABCDEFGH IJKLMNOP rol N+1 I ABCDEFGH JKLMNOP0 rol N+1 J ABCDEFGH KLMNOP0I rol N+1 K ABCDEFGH LMNOP0IJ rol N+1 L ABCDEFGH MNOP0IJK rol N+1 M ABCDEFGH NOP0IJKL asl N A BCDEFGH0 NOP0IJKL asl N B CDEFGH00 NOP0IJKL asl N C DEFGH000 NOP0IJKL asl N D EFGH0000 NOP0IJKL asl N E FGH00000 NOP0IJKL上のようになります。ここで、A~Pは各ビットの初期値で状況に依存します。
このように、命令を実行する度に、各ビットがどうなるのかを追っていくことが大切です。
