アットウィキロゴ
 

第零章・・・もくじ

第一章・・・はじめに

このページは、普通の改造よりもっと上級な事がしたい!
って人のためのページです。
このページで書いてある事がわからなくても、
大丈夫!
何度も試行錯誤すれば
だんだんわかってくるでしょう。
では、始めましょう。

第二章・・・65C816とは~

65C816とは、スーパーファミコンのプログラム言語の事を示します。
言語と言っても、日本語や英語、中国語等がありますね。
65C816は、スーパーファミコンの機械語って事です。
これを習うと、スーパーファミコンに何でも命令できます。
食事を作れとか、お金を出せとか、そういうのは無理なんですけどね^^
とにかく、次へ参りましょう。

このページでは、直接機械語は習いません。
アセンブラを使って、一般人にもわかりやすいプログラミング言語を
わかりにくい機械語に変換していきます。
そのほうが効率がいいです。


第三章・・・始めにやること

では習い始めましょう・・・・って言っても= オリジナルROMを作るとか、エミュを作るとかは
専門のページを検索したほうがいいです。
ここでは、気軽にマリオワールドの上級者関連の事をしたい人にお勧めなページです。

カスタムスプライトから始めましょう。
テキストファイルなので簡単に改変できますから、楽です。
では、始めます


Step1〜サンプルスプライトを挿入しよう~

Sprite Toolの使い方

Step1.5〜カスタムスプライトの制約~

このページではスプライトを大文字の英語で書いていますが、小文字でも構いません。
ただし、例外もあります。

Step2〜サンプルスプライトを改変しよう~

ここからが本題です。
いきなり自分でスプライトを作るのは難しいので、サンプルスプライトを改変しましょう。

では、まず始めに、「普通のジャンプをしてもスピンジャンプになる処理」を「ハンマーブロス」 に加えましょう。
簡単な処理なので、指示通りにやっていけばうまくいきます。

始めに、「sprites」フォルダの中の「hammer_bro.asm」を開いてください。
※バックアップは忘れずに!
開くと、色々と意味不明な事が書いてあると思います。
その中で、以下の文字列を探してください。

                   dcb "MAIN"
HAMMER_BRO_JSL     PHB                     ; \
                   PHK                     ;  | main sprite function, just calls local subroutine
                   PLB                     ;  |

JSR DecrementTimers

                   JSR START_HB_CODE       ;  |
                   PLB                     ;  |
                   RTL                     ; /

場合によっては

JSR DecrementTimers

が、ないかもしれませんが、バージョンの違いなので気にしなくていいです。
次は、この文字列の中に

LDA #$01
STA $140D

と、書いてください。
と、言っても

           ここと→PLB

JSR DecrementTimers

                   JSR START_HB_CODE       ;  |
             ここ→PLB                     ;  |

の、間に書いてください。
さもないと、バグる可能性があります。
できたら、そのファイルを保存して、挿入してください。
そのスプライトの設置もして、そのマップをプレイしてください。

すると、
普通のジャンプをしてもスピンジャンプになると思います。
こうなるのは、「スピンジャンプかどうか」のフラグを、立てているからです。

それではここで、解説に行きましょう。

解説(1)

さて、なぜこうなってしまったのでしょうか。
それには、命令の上に書かれている、

dcb "INIT"
dcb "MAIN"

と、さっき付け足した文字列が関与しています。

LDA #$01
STA $140D

前者は、スプライトを動かすために大切な文字列です。
dcb "INIT"は、イニシャルルーチンと呼ばれます。
dcb "MAIN"は、メインルーチンと呼ばれます。
後者は、ある二つの命令をあらわしています。
それは、 LDA STA です。
どっちもAがついていますね。
このような命令は、殆どの場合 アキュムレータ を使う命令です。
アキュムレータとは、CPUの中にあるレジスタのひとつです。
これを使うと、基本的なことがいろいろできます。
一般では、Aレジスタと呼びます。

dcb "INIT",dcb "MAIN"について

dcb "INIT"(イニシャルルーチン)は、スプライトが画面に入った時、 一瞬だけ動作します。
この文字列の下に命令を書くと、その命令はスプライトが画面に入った時、一回だけ動作するので、繰り返したくない命令を書くのに使います。
dcb "MAIN"(メインルーチン)は、スプライトが画面に入った時から、何回も繰り返します。
この下に命令を書くと、その命令は画面に入ったときから何回も動作します。
基本的には、こちらに命令を書きます。
ちなみに、INITとMAINは必ず大文字で書いてください。
dcbと"INIT"もしくは"MAIN"の間は必ずスペースを開けてください。

LDAについて

LDA は、Aレジスタに、数値をロード(格納)します。
数値の種類は、その後の記号によって変わってきます。

LDA $01  - 16進数でメモリ「01」に入ってる数値をAレジスタにロードする。
LDA #$01 - 16進数で数値「01」をAレジスタにロードする。
LDA #%00000001 - 2進数で数値「00000001」をAレジスタにロードする。

 $ は、この数値が16進数だという事を表します。
殆どの場合、この記号を必ずつけるといってもいいでしょう。
逆に、これをつけないと、数値を10進数としてロードする事になります。

 % は、数値を2進数で表記するという事を表します。
あまり使わないかもしれませんが、使う時がくるかもしれませんので、
しっかり覚えておきましょう。

 # は、この数値が直接入れる数値だという事を表します。
逆につけないと、その数値のメモリに入っている数値をロードしてしまうので、注意してください。

これらはアドレッシングモードと呼ばれ、その記述方法によって命令がちょっと変わってきます。

LDA の派生型として LDY LDX がありますが、これはまたの機会に説明します。

例では、数値「01」をAレジスタにロードしています。

STAについて

次は、 STA です。
この命令は、Aレジスタの数値を指定したメモリにストア(代入)します。
これもアドレッシングモードによってちょっと変わってきます。

STA $01  - 16進数でメモリ「01」にAレジスタの数値をストアする。
STA $0151  - 16進数でメモリ「0151」にAレジスタの数値をストアする。
STA $200103  - 16進数でメモリ「200103」にAレジスタの数値をストアする。

上記の命令は、ストアするメモリのビットが違ってきます。

$** - 8bit(2進数で8桁)
$**** - 16bit(2進数で16桁)
$****** - 24bit(2進数で24桁)

ビットの桁が違うと、アドレッシングモードが違う事になるので、よく覚えておいてください。

STA の派生型として STY STX がありますが、これもまたの機会に説明することになるでしょう。

例では、メモリ $140DにAレジスタの数値を書き込んでいます。

解説(1)のまとめ

では、さっきの命令をまとめてみましょう。
LDA  - 指定した数値(メモリの数値)をAにロード(格納)する。
STA  - 指定したメモリにAレジスタの数値をストア(代入)する。

$ - 命令の数値を16進数に直す。
% - 命令の数値を2進数に直す。
# - 数値を直接指定する。入れないとその数値に対応したメモリに。

$** - 8bitのアドレッシングモード。2進数で8桁なので8bit。
$**** - 16bitのアドレッシングモード。2進数で16桁なので16bit。
$****** - 24bitのアドレッシングモード。2進数で24桁なので24bit。

では、先ほどの文字列をまとめてみましょう。

LDA #$01 - 8bit,16進数で数値 01 をAレジスタにロードする。
STA $140D - 16bit,16進数でメモリ 140DにAレジスタに入っている数値(今は 01 が入っている。)をストアする。

このようにすると、メモリ$140DにあるスピンジャンプのフラグがONになり、
普通のジャンプをしてもスピンジャンプ状態になるのです。

はい、これで理解できなかったあなたは、
ここから読み返すといつかは理解できます。
これで理解できたあなたは、
第1の壁を乗り越えました!おめでとうございます!

基本的な命令を覚えたので、あなたもいろいろやってみましょう!
ここから好きなメモリを選んで、好きな数値を入れてみましょう。
下手な所に数値を入れるとバグるかもしれませんが、
うまくいけば面白いことになります。
つまり、チートと同じことですね。

では、次の章へ行きましょう・・・・

第四章・・・YレジスタとXレジスタ

さて、ここまでにサンプルスプライトの改変はできましたね。
次は、新たなレジスタを使いましょう。

テンプレートを使ってみよう

まずは、このファイルを保存してください。
スプライトのテンプレートみたいなものです。
中のasmファイルとcfgファイルを「sprites」フォルダにいれてください。
そして、そのasmファイルを開いてください。
中は、こうなってる筈です。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; INIT and MAIN JSL targets
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
                   dcb "INIT"
                   RTL

                   dcb "MAIN"
                   RTL

中身の確認ができたら、次へ参りましょう。

                   dcb "MAIN"
                   **ここ**
                   RTL

に、以下の命令を書き込んでください。 LDY #$01 LDX #$00 LDA #$3C STA $14AD,y STA $14AD,x 書き込んだら、挿入し、マップに設置して、ステージをプレイしてみましょう。
すると・・・・

#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (SMW_000.png)

これが、

#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (SMW_001.png)

こうなってる筈です。
挿入時点でエラーを吐いた人は、asmファイルの名前を変えたり、変な命令を書き込んでるかも知れません。
そのような事があった人は、1度第四章からやり直しましょう。
さて、なぜこうなったのでしょう。
それは、先ほどの命令に「青Pスイッチを押してる状態」にする命令と「銀Pスイッチを押してる状態」にする命令を書き込んでいるからです。

それでは、解説に行きましょう。

解説(2)

さて、さっき書き込んだ命令を見てみましょう。
LDY #$01 LDX #$00 LDA #$3C STA $14AD,y STA $14AD,x ふむふむ、 LDY という命令や LDX という命令がありますね。
それと、 STA のアドレッシングモードに、
,y という記号や、
,x というのがついていますね。これはなんでしょうか。

ストアしたメモリをRAM Mapで見てみると、

$7E:14AD Blue POW Timer

と、書いてますね。
その下には、

$7E:14AE Silver POW Timer

と、書いてます。
メモリ$14ADにしか書き込んでないのに、どうやって$14AEに書き込んだのでしょうか。
それは、 Yレジスタ と、 Xレジスタ が関係しています。

Yレジスタ Xレジスタ は、Aレジスタの基本的な事に加え、メモリアクセスに長けています。
その代わり、演算等の機能は使えません。
この二つのレジスタは、双子のような存在です。
どっちも同じ機能なので、好きな方を使うといいでしょう。

LDY,LDXについて

以前、解説(1)で、「命令の殆どはその文字に含まれているレジスタを使われる」と、説明しましたね。
LDY LDX は、その通り Yレジスタ Xレジスタ を使います。
基本的にはLDAと一緒です。

LDA  - 指定した数値(メモリの数値)をAにロードする。
LDY  - 指定した数値(メモリの数値)をYにロードする。
LDX  - 指定した数値(メモリの数値)をXにロードする。

このように、使うレジスタが違うだけです。
STY STX も同様です。

STA  - 指定したメモリにAレジスタの数値をストア(代入)する。
STY  - 指定したメモリにYレジスタの数値をストア(代入)する。
STX  - 指定したメモリにXレジスタの数値をストア(代入)する。

でも、基本的にストアは Aレジスタ で行うので、これらの命令はあまり必要ないのかもしれませんね。

例では、 Yレジスタ に 01 、 Xレジスタ に 00 、 Aレジスタ に 3C をロードしています。

新たなアドレッシングモード

,y 」や、「 ,x 」を使うと、そのレジスタの数値の分だけ使うメモリの番号が増やされます。
つまり、こういうことです。

LDY #$03 - Yレジスタに03をロード
LDA $01 ,y  - $01にYレジスタを足した数値に値するメモリの数値をAレジスタにロード
=メモリ$04に入ってる数値をAレジスタにロード

このように、、 Yレジスタ の数値だけメモリの番号がずれます。
かなり重要です。

例では、Aレジスタの数値を$14AD+Xのメモリと$14AD+Yのメモリにストアしてます。

解説(2)のまとめ

LD*,ST* - 三文字目のレジスタを使う。(A,Y,Xのみ)

,y & ,x  - Y,Xレジスタの数値をオペランドに足して命令を行う。

ああ、そういえば
指定した数値の事をオペランドと言います。
アドレッシングモードとはまた違ってきます。
これも覚えておいてください。

さて、さっき実行した命令を纏めてみましょう。

LDY #$01 - 8bit,16進数で数値 01 をYレジスタにロードする。
LDX #$00 - 8bit,16進数で数値 00 をXレジスタにロードする。
LDA #$3C - 8bit,16進数で数値 3C をAレジスタにロードする。
STA $14AD,y - 16bit,16進数でAレジスタの数値(今は3C)を14AD+y(今Yには01が入ってるので14AEになる)にストアする。
STA $14AD,x - 16bit,16進数でAレジスタの数値(今は3C)を14AD+x(今Xには00が入ってるので変化無し)にストアする。

こういう訳で、結果的に青Pスイッチと銀Pスイッチが押してる状態になるのです。

言い忘れてましたが、カスタムスプライトでは Xレジスタ の値が重要になります。
このゲームのスプライトの枠(席?)は12枠あるのですが、その区別をつけるために Xレジスタ にインデックスの数値を入れておくのです。

それでは、次に進みましょう。

第五章・・・比較と条件分岐

それでは、新しい命令を使ったコマンドを、作ってみましょう。
第四章では、スプライトのテンプレートを使いましたね?
そのテンプレートを使ってみましょう。
第四章で追加した命令を消して、ちょっと長いですが以下の命令を書き込んでください。
dcb "MAIN"

		    LDA	#$00	;A←0

STA $0DC2 ;ストックの中身←A LDA $1490 ;A←スタータイマー BNE STAR ;A=0でないならSTARへ飛ぶ LDA $19 ;A←マリオのパワーアップ状態 BEQ RETURN ;A=0ならRETURNへ飛ぶ CMP #$01 BEQ SUPER ;A=1ならSUPERへ飛ぶ CMP #$02 BEQ CAPE ;A=2ならCAPEへ飛ぶ CMP #$03 BEQ FIRE ;A=3ならFIREへ飛ぶ RTL


STAR		    LDA	#$03	;A←分岐によって様々な値

BRA BOX ;BOXへ飛ぶ


SUPER		    LDA	#$01	;A←分岐によって様々な値

BRA BOX ;BOXへ飛ぶ


CAPE		    LDA	#$04	;A←分岐によって様々な値

BRA BOX ;BOXへ飛ぶ


FIRE		    LDA	#$02	;A←分岐によって様々な値

BRA BOX ;BOXへ飛ぶ


BOX		    STA	$0DC2	;ストックの中身←A

RETURN		    RTL

書き込めましたか?
書き込めたら、挿入してください。
そして、マップにそのスプライトを設置し、
できれば
スーパーキノコ
ファイアフラワー
マント羽根
スーパースター
ブラックパックン
を設置してテストプレイしてください。

すると、こうなる筈です。
チビマリオ

#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (Chapter_7_1.png)

スーパーマリオ
#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (Chapter_7_2.png)

ファイアマリオ
#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (Chapter_7_3.png)

マントマリオ
#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (Chapter_7_4.png)

無敵マリオ
#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (Chapter_7_5.png)


と、このように
違いが分かりますか?

そう、マリオの状態で、アイテムボックスの中身が変わるのです。
それでは、解説に行きましょう。

解説(3)

新しい命令が4つ出てきました。


 CMP  Aレジスタとオペランドを比較する命令
 CPY  Yレジスタとオペランドを比較する命令
 CPX  Xレジスタとオペランドを比較する命令

 BEQ  CMPの結果「A=オペランド」ならラベルへ移動
 BNE  CMPの結果「A≠オペランド」ならラベルへ移動
 BCS  CMPの結果「A≧オペランド」ならラベルへ移動
 BCC  CMPの結果「A<オペランド」ならラベルへ移動
 BRA  無条件にラベルへ移動


これらの分岐命令 は符号付き条件分岐命令です。
BEQBNEだけでは不便なのでもう2つ命令を紹介しています。使い方は一緒です。

ラベルとは、先ほどのソースの「STAR」や「SUPER」などです。
好きな場所に記述でき、好きな時にBRABEQなどで移動できます。
処理が進んでいる途中にラベルにぶつかっても処理が停止することはありません。
ラベルはソース内の目印です。

上のソースでは、最初にスターのタイマーをAレジスタに読み込んでそれが0でなければ(=スターの効果が切れてなければ)BNEでSTARに飛ばしています。
マリオがパワーアップしていない状態ならBEQでRETURNに飛ばしています。
次に、スーパーマリオ、マント、ファイアー…と順に判定して、それぞれのラベルに飛ばしています。
飛ばされた先にはLDAでそれぞれ違った値を読み込ませてBRAでBOXに飛ばしています。
BOXでは先ほどLDAでAレジスタに読み込ませた値をストックの中身にSTAで代入しています。

分岐命令を使う時には注意してください。
例えば、

 LDA $00
 CMP #$50
 BCS GET
 命令
 命令
 ・・・
 命令
 命令
GET
 LDA #$FF
 STA $01
 RTL

分岐命令で飛ぶラベルと分岐命令の間に命令が沢山入っているとSpriteToolがエラーを吐きます。
これは、分岐命令で移動できる距離が短いから。符号付で1バイトしか用意されていないんです。
そんな時はこうすれば解決できます。

 GOTOGET JMP GET
 LDA $00
 CMP #$50
 BCS GOTOGET
 命令
 命令
 ・・・
 命令
 命令
GET
 LDA #$FF
 STA $01
 RTL


分岐命令の近くにラベルを置き、そこにJMP命令で目的のラベルまで飛ばすようにします。
JMP命令は移動できる距離が長いので(符号無し2バイト)余程のことではエラーを吐きません。

第六章・・・増加と減少

前章と同様に前回の命令を消して次の命令を書き込んでください。

dcb "INIT" LDA #$00 ;A←0 STA $0DBF ;コインの数←A LDA #$32 ;A←50 STA $0F48 ;ボーナススターの数←A RTL

   

dcb "MAIN" INC $0DBF ;コインの数を増加 DEC $0F48 ;ボーナススターの数を減少 LDA $0DBF ;A←コインの数 CMP #$32 BEQ LABEL ;A=50ならLABELへ LDA $0F48 ;A←ボーナススターの数 BEQ LABEL2 ;A=0ならLABEL2へ RTL

 
LABEL		LDA #$00		;A←0

STA $0DBF ;コインの数←A RTL

  
LABEL2		LDA #$32		;A←50

STA $0F48 ;ボーナススターの数←A RTL 書き込めたら、挿入してください。
マップにそのスプライトを設置しテストプレイしてみましょう。
マリオのコインの数とボーナススターの数に注目してください。
コインの数はだんだん増え、ボーナススターは減っていきます。

#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (math.png)

コインの数が50、ボーナススターの数が0になると コインの数が0、ボーナススターが50になり、増加/減少を続けます。
それでは解説に移ります。

解説(4)

なぜ増加と減少が起こったかというと新しい命令  INC  DEC が関係しています。

 INC  Aレジスタの増加
 INX  Xレジスタの増加
 INY  Yレジスタの増加

 DEC  Aレジスタの減少
 DEX  Xレジスタの減少
 DEY  Yレジスタの減少

上のソースでは、イニシャルルーチンでコインの数を0、ボーナススターを50に初期設定しています。
コインのAを増加させていき、16進数で32 即ち50と比較させ50になったらラベル移動、移動先でコインの数を0にします。
ボーナススターも同じく減少させ、0になったらラベル移動、移動先で50に戻しています。
ちなみにLABEL2への分岐時にCMPを用いていません、この場合BEQは=0で分岐、BNEは≠0で分岐します。


この説明ではありませんでしたが、INC,DECは命令の仕方によってはアキュムレーターの値も変化させることができます。

INC A     ;アキュムレーターに1を足す
DEC A     ;アキュムレーターから1引く
INC $00   ;$00に1を足す
DEC $00   ;$00から1引く

INC       ;INC Aと全く同じ動作をします
DEC       ;DEC Aと全く同じ動作をします


説明が不適切なら適当に直しといてください。

第七章・・・論理積

今度はasmの前回の命令を消して次の命令を書き込んでください。

dcb "INIT" RTL

   

dcb "MAIN"

                 LDA $15
                 CMP #$08
                 BEQ LABEL;上を押したらLABELへ

RTL

LABEL            LDA #$01
                 STA $1426;メッセージ1を表示
                 RTL

これを挿入してプレイ!
すると、上を押せばメッセージが表示されますが、他のボタンと同時押しだと動作しません。
そこで、さっきのasmを

dcb "INIT" RTL

   

dcb "MAIN"

                 LDA $15
                 AND #%00001000
                 BNE LABEL;上を押したらLABELへ

RTL

LABEL            LDA #$01
                 STA $1426;メッセージ1を表示
                 RTL

と書き変えて挿入して見ましょう。
すると、今度は同時押しでも動作します。

解説(5)

ではなぜ出来たのでしょうか。
答えは、AND #%00001000←これです。
AND という命令は、2進数で考えて、同じ位で掛け算をします。
例えば、YとBと↑を同時押しした場合、
16進数で40+80+8=C8という結果が出ます。
それを2進数にすると、11001000になります。
結果をANDという命令で計算すると、
   00001000
 * 11001000
  ̄ ̄ ̄ ̄ ̄ ̄
  00001000
となり、16進数で8となります。
つまり、YとBが無視されます。
また、ANDの演算結果により、ゼロフラグが変化するためCMPも必要なくなります

第八章…加算と減算

dcb "INIT"
LDA $0DBF
CLC
ADC #10
STA $0DBF
RTL
dcb "MAIN"
RTL

ADCは、Aレジスタをオペランド+キャリーフラグの分加算する命令です。
実際にこれを実行してみるとコインが10枚増えるはずです。
CLCは、キャリーフラグをクリア(0にする)命令。これは繰り上がりなどで使われます。詳しくは鬼畜王氏のサイトで。

LDA $0DBF
SEC
SBC #10
STA $0DBF

減算はSECSBCを使います。
SBCはAレジスタをオペランド-キャリーフラグの分減算する命令。
SECはキャリーフラグをセット(1にする)命令。繰り下がりなどで使われます。

第九章…ループとデータベース


同じ処理をn回だけ行いたい時はループを使います。
今何回目か数えるカウンタが必要ですが、
Xレジスタがよく使われます。


         LDX #$08
Loop     

         [処理A]
         


         DEX              ;Xを1減らす
         BPL Loop         ;Xがマイナスでなければやり直し


上のようにすると、[処理A]が「08+1」の9回だけ実行されます。
その仕組みを考えてみましょう。

X=8 で処理A
X=7 で処理A
  :
  :
X=0 で処理A
Xがマイナスになってしまったので戻らず


注意として、処理AがXを変える物であってはなりません。
なぜかって…数えてる指をぐちゃぐちゃにされるようなものだからです。
下手すると永久にループから抜けられなくなってフリーズします。

さて、そうは言うものの、本当に同じ処理を
何回もやりたい機会なんてほとんどありません。
毎回の処理をちょっとずつ変える、ということが多いです。
つまり、同じ処理ではなく、似ている処理をまとめて行う。
ループってのはそういうものです。
例のループではどの回の処理Aも同じ処理Aですが、
Xの値というシチュエーションが異なっています。
これがヒント。
もし処理Aが、Xによって微妙に違う処理を行うものだとしたらどうでしょう。
「X=0のときの処理A」をA0
「X=1のときの処理A」をA1…と、かっこよく書きますと、
例のループでは単に『処理Aを9回くりかえす』のではなく、
『処理A0、A1、A2、A3、A4、A5、A6、A7、A8を全て行う』
という意味を持つことになります。


「Xによって違う処理」と言うと抽象的ですが、
具体的にはLDA $7ECD00,xとかですね。
X=8〜0のループの中においてこいつは
$7ECD08〜$7ECD00という「一まとまりの配列」を扱う感じです。
配列の内容ははRAMかもしれませんし、単なる用意されたデータ群かもしれません。
$??????,xというのは、「??????から始まる配列の、X+1番目
という意味合いが強いです。
なぜX+1かって?X=0のときが1番目だからです。
「LDA $aa,x ⇒STA $bb,x」は、 
「配列aaのX+1番目を配列bbのX+1番目にコピー」ということになり、
これをXが(配列の長さ分-1⇒0)となるまでループさせれば
「配列aaをまるまる配列bbにコピー」という結果になります。


さて、ここまで来たら実例を見てみましょう。
HDMA入門の実践?をやってみます。
やるべきことをまとめると、
「08 00 06 40 FE 7Fという配列を、$7FFE18以降に書き写す」
「40 AF 40 6F 40 2F 40 00 00という配列を、$7FFE40以降に書き写す」

自前で配列を用意するには配列名ラベルとdcbを使います。

HAIRETU      dcb $08,$00,$06,$40,$FE,$7F

とすれば、

             LDA HAIRETU,x

は、先に用意したHAIRETUという名の配列のX番目をLDAすることになります。~ 完成品を見てみましょう。



		LDX #$05 
Loop1			LDA.l SETTING,x
			STA $7FFE18,x
		DEX
		BPL Loop1



		LDX #$08 
Loop2			LDA.l CONTENT,x
			STA $7FFE40,x
 		DEX
		BPL Loop2


		RTL


SETTING		dcb $08,$00,$06,$40,$FE,$7F

CONTENT		dcb $40,$AF		
		dcb $40,$6F		
		dcb $40,$2F	;最初は00なので	
		dcb $40,$00	;正直最後の2バイトは不要	
		dcb $00	

上のはTRASM用書式で書いています。
注意したいのが、この処理は1回やれば十分だということです。
Sprite toolで使うなら、INITルーチンに書けばいいです。
LevelASMで使うなら、LDA $7FFE18  BNE Return(RTLへ)
を付け加えましょう。

残念ながら、LevelASMで使おうと普通にTRASMでbin化してもだめです。
SETTINGやCONTENTというラベルを使っていますが、
これはLDAにおいては絶対パスなので、
bin化後は配列の位置を正しく指してくれません。
xkasなら一撃で挿入できるので便利です。
あっぷろだXのLevel.asmを(CMry
xkas書式に変えるときは、
「ラベル本体に:をつける(ラベル指定では不要)」「dcbをdbに変える」。

その他

どのような命令があるかはここでも見てください。ある程度のことは載ってます。

コメント

最終更新:2011年04月16日 17:40