*注意*

近年、AIによるサイト内情報の要約や解説など便利な機能が増えています。 ですが、技術系のブログについてのAI要約はまだまだ不正確な記述をする場合が多いです。 AI要約や解説を鵜呑みにせず、元記事を参照して必ず自らの目で確かめて判断するようにしてください。 *Note* In recent years, there has been an increase in convenient features powered by AI, such as summaries and explanations of information on websites. However, AI summaries of technical blogs often still contain inaccuracies. Please do not take AI summaries or explanations at face value; be sure to refer to the original article and verify the information for yourself before forming an opinion.

AI利用者への案内

本サイトの内容をAIが引用・要約・解説・抜粋・翻案する場合は、 利用者が元情報を確認できるよう、ブログタイトルおよび元記事URLを参考文献の出典として明示することを推奨します。 Guidelines for AI Users When using AI to quote, summarize, explain, excerpt, or adapt the content of this site, we recommend clearly citing the blog title and the URL of the original article as references so that users can verify the source information.

2022年11月7日月曜日

謎の遊技機コントロールユニットの分解

電子機器の分解一覧


謎の遊技機コントロールユニットの分解


注意:このサイトの内容を鵜呑みにし、事故や損失を招いた場合でも当方は一切の責任は負いかねます。自己責任でお願いします。



ハードオフでよくわからない遊技機コントロールユニットを見つけたので分解してみました。









装置本体に型番など記載されていなく、ネット上にも情報がないため何の装置のコントロールユニットかは一切不明です。

表面には「ディップスイッチの使用法B」と記載されたシールが貼られています。
「コイン枚数」「タイマー1」「タイマー2」「周回数」などの項目をディップスイッチで設定出来るようです。
また、右下の方にJASRACシールが貼ってあり、音楽を流す機能もありそうです。

側面には、ボリュームとトグルスイッチ、赤色のプッシュスイッチ、ヒューズボックスがあります。
トグルスイッチの上には「メリーゴーランド」のシールが貼られていて、さらにその上から「PITCHDOWN」のテプラが貼ってあります。

これらから推測すると、かつてデパートの屋上などで置かれていた乗り物のコントロールユニットでしょうか?



・分解







分解してみると、ROM、MCU、音源IC、オーディオアンプというシンプルな構成となっています。

今でこそ1チップマイコンで事足りるような構成ですが、当時はこれでもだいぶシンプルな構成であると伺えます。

パワートランジスタが5つありますが、電飾はともかくモータの直接ドライブ能力が無さそうなので、電飾・リレーのドライブ用であると予想できます。

基板裏のパターンには「SSG-101」の文字があるので、おそらくこれが型番だと思います。


詳しく見てみましょう。
ROMはNECのμPD27128が使われています。
窓遮光シールには「メリーゴーランド」と書かれています。


MCUは日立のHD63A03XPが使われています。
モトローラのMC6803(MC6801の外付けROM化) のCMOS版のシリーズのようです。

192ByteのRAMや汎用ポート、タイマー、SCIなどが内蔵されており、外付けのROMを用意するだけで組み込み装置ができます。


音源ICはGIのAY-3-8910 (PSG音源)が使われています。
矩形波3音、ノイズ1音を出すことができます。
基板裏のパターンに「YM2149」と表示があるので、YAMAHAのSSG音源の使用を想定して設計されたと考えられます。


他にもTC4584BP(シュミットトリガインバータ)やTC4013BP(D-FF)などが乗っています。


・曲の演奏
2種類あるようです。



・PCMの再生
人の声が再生されます。
かなり音質が悪く、合っているかわかりませんが次のように聞こえます。
--「ばいばいまたね」x2
--「いっぱいあそんでね」
--「こんにちは」
--「今日はどうですかな」
-- ノイズ音


・回路



・電源
基板裏の電源部分のパターンに「+14」の文字が入っているので、電源は+14の入力を想定しているようです。
3端子レギュレータは2つ付いており、パワトラ&オーディオアンプ用に12V、デジタル回路用に5Vを生成しています。


・MCU & ROM
この基板についているROMは27128で、16kBの容量があります。MCUがサポートしているアドレス空間は64kB($0000~$FFFF、A0~A15)なのでプログラムの容量はそこまでないと予想できます。
基板裏のパターンを見るとROMが付いている部分に「27512」と書かれたパターンがあるので、64kBのROMである27512が付けられる設計になっていると思われます。
この回路ですと、27512を取り付けた場合は特に問題は無いのですが、それ以外の低容量のROMを取り付ける場合は、ROMのアドレス範囲に気を付けなければいけません。

MC6800系のMCUの場合、リセットや割り込みなどが起きた際にベクタアドレスにある値を読み込み、その値のアドレスをPCへセットします。この「ベクタアドレス」は固定であり、しかも、アドレスの最後の方である$FFEA~$FFFF(HD63A03XPの場合)に割り当てられています。
MCUがベクタアドレスにアクセスして値を読み出せるようにする必要があります。もし、ベクタアドレスにある値が適当でない場合、プログラムの開始などができなくなります。
つまり、ROMはアドレスは$FFEA~$FFFFに被るように配置しなければいけないということです。(どうしてもアドレス空間の後ろにROMを配置したくなければロジックICでベクタアドレス部分にアクセスしたときに値を示す回路を入れればよいですが…)
もちろん、ROMをアドレス空間の後ろに配置するとプログラム内の絶対アドレスの指定もずらさなければいけません。

今回の基板には、16kBのROMである27128が付いていたので、ROM配置アドレスは$C000~$FFFFということになります。ROMの詳しい解析は後ほど記載します。

MCU周りは特に難しい部分は無さそうです。
HD63A03XPにはクロックジェネレータが内蔵されており、水晶振動子を付けるだけでクロック生成できます。基板には3.58MHzの水晶振動子が付いていますが、HD63A03XPには4分周回路が入っているので、実際の動作周波数は3.58/4MHzとなります。
リセット回路もRCで作られた簡易的なものとなっています。


・音源周り
音源ICとしてGIのAY-3-8910 (PSG)を使っています。
このAY-3-8910には音声生成以外に汎用ポートがあります。この謎コントロールユニットでは、この汎用ポートを積極的に活用しているようです。

1つは、PSG汎用ポートを入力として使い、ディップスイッチの状態のチェックに使用しています。ディップスイッチの役割はこの記事の冒頭で載せた写真を参照してください。

もう1つは、PSG汎用ポートを出力として使い、4bitの簡易音声DACとしています。
結構面白い使い方をしていますね。4bitのPCMっぽいですが、音質はかなり悪くなりそうです。バイナリ加重DACではなく、量子化幅が一定ではありません。DAコンバートした際のバイナリ-アナログの直線性を失います。サンプリング時に標本値の加工が必要になりそうです。
実際の基板裏にはまだ抵抗を付けられそうな空パターンがあったので、8bitDACとして設計したものの、DAC量子化問題やコストの問題などで4bit化したのではないかと予想できます。(8→4bitにすると音声データの量も半分になるため、低容量のROMで良くなる)

PSGのクロック源はMCUのクロック源を1/2に分周しているようです。


・その他
ボタンやコイン投入、センサなどの入力のチャタリング除去はシュミットトリガインバータ(TC4584BP)とRCで行っているようです。
この7つの入力のうち1つはMCUのNMI端子へ接続されています。NMIのベクタアドレスは$FFFC~$FFFDなので、ROM内の該当ベクタアドレスを覗いてみると$C000となっていました。$C000はROMの先頭アドレスなので、この入力NMI端子は緊急停止かなにかのスイッチなのではないかと考えられます。

他にも、IRQ2端子へ接続されている入力があります。IRQ2のベクタアドレスは$FFEA~$FFEBなので、ROM内の該当ベクタアドレスを覗いてみると$C003となっていました。おそらくコイン投入センサへ接続されているのでしょう。

それ以外の端子はMCUの汎用ポートへ接続されています。実際に入力してみると、何かしらの音声が再生されます。(音質が悪すぎてなんの音声かは判別不能です。)

コントロールユニットの側面には、赤色スイッチのプッシュスイッチと選曲セレクト用トグルスイッチが取り付けられています。

パワートランジスタは東芝のダーリントントランジスタの2SD633が付いています。
Ic=7A、Pc=40W、ヒートシンク無しなので豆球数個程度なら余裕でドライブできそうです。
さすがに人を乗せて何か動かすようなモータドライブは出来なさそうなので、モータはリレーを介しての駆動をしていそうです。



・ROMの解析

さて、最後にROMの解析を行いたいと思います。
回路起こしの結果からROMに含まれているデータは、
・プログラム
・演奏データ
・4bit PCMデータ
であろうと予想できます。

幸いにもROMのサイズが16kBとそれほど大きくないため、データのほとんどは演奏データやPCMデータであると考えられます。


・プログラム
ROMから吸い出したデータはすべてのデータが繋がった状態となっています。
プログラム、演奏データ、PCMデータのうちデータの先頭がすぐにわかるのはプログラム部分だけなので、まずプログラムを解析します。

プログラムは、機械語(バイナリデータ)となっているためこのままでは読みにくいです。
今回は逆アセンブルソフトのDASMxを利用してアセンブラで表示します。DASMxの使い方は省略します。

ROMデータのうち、まず初めに確認するのがベクタアドレスです。
この領域にはMCUのリセットや割り込みなどが発生した際に、PCへセットする値が記録してあります。
HD63A03XPの場合、$FFEA~$FFFFがこれに相当します。値は2バイト分で、偶数アドレスがMSB、奇数アドレスがLSBです。

HD63A03XPのデータシートを確認してみると、
$FFFE,$FFFF   ~RES 
$FFFC,$FFFD   ~NMI
$FFFA,$FFFB   ソフトウェア割り込み
$FFF8,$FFF9   ~IRQ1  
$FFF6,$FFF7   Timer1 input Capture
$FFF4,$FFF5   Timer1 Compare 1,2
$FFF2,$FFF3   Timer1 overflow
$FFF0,$FFF1   SIO
$FFEE,$FFEF   TRAP
FFEC,FFED   Timer2 Counter Match
FFEA,FFEB   ~IRQ2
の様に割り当てられています。

では、実際のROMデータを見てみましょう。
せっかくなので逆アセンブラしたデータを見てみます。
//逆アセンブラしたROMデータ最後尾////////////////////////////////
FFE8 : FF FF C0 "   " stx XFFC0
;
FFEB : 03 " " db $03
;
FFEC : FF FF C0 "   " stx XFFC0
;
FFEF : 00 " " db $00
;
FFF0 : FF FF FF "   " stx XFFFF
FFF3 : FF FF FF "   " stx XFFFF
FFF6 : FF FF FF "   " stx XFFFF
FFF9 : FF C0 00 "   " stx LC000
FFFC : C0 00 "  " subb #$00
FFFE : C0 00 "  " subb #$00
//////////////////////////////////
何やらプログラムがあるように見えます。ですが実際には全くのでたらめです。
基本的に逆アセンブラソフトはバイナリデータとニーモニックを1対1で結び付るだけしかしてくれません。よって、設定でもしない限り、プログラムではない部分もそのままニーモニックを付けてしまいます。
つまり、残念なことに、実は逆アセンブルしたデータを見ただけでは、プログラムデータかその他のデータなのかは判別できないのです。
判別するには、やはり順を追ってアセンブラを解読するしかなさそうです。

このデータはベクタなのでHD63A03XPのデータシートのベクタアドレスのテーブル(table1)を参考に見てみましょう。
//逆アセンブラしたROMデータ最後尾////////////////////////////////
FFE8 : FF FF C0 "   " stx XFFC0    //ベクタ(FFEA,FFEB)IRQ2                  "C003"
;
FFEB : 03 " " db $03
;
FFEC : FF FF C0 "   " stx XFFC0    //ベクタ(FFEE,FFEF)TRAP                   "C000"
;
FFEF : 00 " " db $00
;
FFF0 : FF FF FF "   " stx XFFFF
FFF3 : FF FF FF "   " stx XFFFF
FFF6 : FF FF FF "   " stx XFFFF
FFF9 : FF C0 00 "   " stx LC000    //ベクタ(FFFA,FFFB)ソフトウェア割り込み   "C000"
FFFC : C0 00 "  " subb #$00     //ベクタ(FFFC,FFFD)NMI                   "C000"
FFFE : C0 00 "  " subb #$00     //ベクタ(FFFE,FFFF)RES   
//////////////////////////////////

整理すると、
RES   (C000)
NMI   (C000)
ソフトウェア割り込み(C000)
TRAP   (C000)
IRQ2  (C003)
となりました。0xFFFFが入っている部分は意味をなさないので、無視しました。
プログラムはRESベクタアドレスにある値が先頭なので、$C000がプログラムの先頭となります。
他の割り込みなども1つを除いて$C000となっているので、リセット動作ど考えてよいでしょう。

IRQ2のみ$C003となっているので、位置検出センサや数え間違えの出来ない課金制御用と予想できます。


さて、プログラムの先頭は$C000と判明したので、アセンブラを読み解いていきます。
解説は省きますのでコメントを参照してください。
(コメントはあくまでこちらが予想した動作です。ミスや見当違いな部分も多くあります。)

//プログラム(DASMxで逆アセンブル、コメント付き)////////
C000 LC000: //プログラム先頭(ベクタ$FFFFで指定されたアドレス) C000 : 7E C0 6B "~ k" jmp LC06B //変数初期化LC06Bへ→LC006へ C003 : 7E C4 C2 "~ " jmp LC4C2 //~IRQ2割り込み ; C006 LC006: //演奏前準備:LC06Bより C006 : BD C0 CF " " jsr LC0CF //LC0CF(演奏前準備)へ C009 LC009: //LC009メインループ C009 : BD C0 A4 " " jsr LC0A4 //LC0A4(AY-3-8910ミキサー,I/O設定)へ C00C : BD C0 AE " " jsr LC0AE //LC0AE(ディップスイッチの状態を読み取り、X0089へ入れる)へ C00F : BD C0 DE " " jsr LC0DE //LC0DE(ディップスイッチの状態から「ディップスイッチの使用法B」の「コイン枚数」の番号をX007F(「ディップスイッチの使用法B」「コイン枚数」設定用)に入れる)へ C012 : BD C1 09 " " jsr LC109 //LC109(ディップスイッチの状態から「ディップスイッチの使用法B」の「タイマー2周回数」の番号をX0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)に入れる)へ C015 : BD C1 82 " " jsr LC182 //LC182(コイン投入ボタン(茶線)処理)へ C018 : 96 79 " y" ldaa X0079 //+/AレジスタにX0079(コイン投入モードフラグ)を入れる C01A : 81 01 " " cmpa #$01 //+/ C01C : 27 1E "' " beq LC03C //+/X0079(コイン投入モードフラグ)が1(コイン投入モード)の場合、LC03Cへ C01E : 96 15 " " ldaa X0015 //*/AレジスタにX0015(ポート5)を入れる C020 : 84 08 " " anda #$08 //*/A = A & 0x08 __(筐体側面の赤色プッシュスイッチ(コインテスト投入スイッチ)) C022 : 27 08 "' " beq LC02C //*/X0015(ポート5)のP54(筐体側面の赤色プッシュスイッチ)が0(押されたとき)の時、LC02C(コインテスト投入スイッチ処理)へ C024 : 96 89 " " ldaa X0089 //-/AレジスタにX0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)を入れる C026 : 84 80 " " anda #$80 //-/A = A & 0x80 __(「ディップスイッチの使用法B」「DIPAW8_ON:コイン_OFF:電源」) C028 : 26 02 "& " bne LC02C //-/X0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)が0(DIPAW8「ディップスイッチの使用法B」「電源」)でない時、LC02Cへ C02A : 20 DD " " bra LC009 //LC009(メインループ先頭)へ ; C02C LC02C: //コインテスト投入スイッチ処理:LC009より C02C : C6 60 " `" ldab #$60 //+/Bレジスタに#$60を入れる(#$F0回ループ) C02E : BD C1 B1 " " jsr LC1B1 //+/ループウェイトサブルーチン,Bレジスタで設定 C031 : 7C 00 8A "| " inc X008A //*X008A(筐体側面の赤色プッシュスイッチ押された時間カウント用)インクリメント C034 : 96 8A " " ldaa X008A //*/AレジスタにX008Aを入れる C036 : 81 03 " " cmpa #$03 //*/ C038 : 27 02 "' " beq LC03C //*/X008A(筐体側面の赤色プッシュスイッチ押された時間カウント用)が3の時、LC03C(コイン投入モード)へ C03A : 20 CD " " bra LC009 //LC009(メインループ先頭)へ ; C03C LC03C: //コイン投入モード:LC009より C03C : 96 80 " " ldaa X0080 //AレジスタにX0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)を入れる C03E : 97 81 " " staa X0081 //X0081(X0080「タイマー2 周回数」設定(テストコイン投入モードの際保存))に C040 : BD C1 58 " X" jsr LC158 //LC158(「ディップスイッチの使用法B」「タイマー1」ディップスイッチ読み取り)へ C043 : 86 20 " " ldaa #$20 //+/Aレジスタに#$20を入れる C045 : 97 17 " " staa X0017 //+/X0017(ポート6)に#$20を入れる(P65=H,パワトラ紫線を導通) C047 : 86 10 " " ldaa #$10 //-/Aレジスタに#$20を入れる C049 : 97 17 " " staa X0017 //-/X0017(ポート6)に#$10を入れる(P64=H,パワトラ水色線を導通) C04B : 96 17 " " ldaa X0017 //*/AレジスタにX0017(ポート6)を入れる C04D : 84 04 " " anda #$04 //*/A = A & 0x04 C04F : 27 03 "' " beq LC054 //*/X0017(ポート6)のP63(選曲セレクトトグルスイッチ)が0のとき、LC054(LC407(一曲目演奏演奏開始処理(課金後)))へ C051 : 7E C4 1C "~ " jmp LC41C //*/X0017(ポート6)のP63(選曲セレクトトグルスイッチ)が1のとき、LC41C(二曲目演奏演奏開始処理(課金後))へ C054 LC054: //:LC03Cより C054 : 7E C4 07 "~ " jmp LC407 //LC407(一曲目演奏演奏開始処理(課金後))へ ; C057 LC057: //課金分終了処理 C057 : 0F " " sei //割り込み無効 C058 : BD C0 CF " " jsr LC0CF //演奏開始サブルーチン C05B : 86 20 " " ldaa #$20 //*/#$20=B00100000 C05D : 97 17 " " staa X0017 //*/X0017(ポート6,P65=Hにセット(パワトラ)) C05F : C6 F0 " " ldab #$F0 //+/Bレジスタに#$F0を入れる(#$F0回ループ) C061 : BD C1 B1 " " jsr LC1B1 //+/ループウェイトサブルーチン,Bレジスタで設定 C064 : 8D 3E " >" bsr LC0A4 //AY-3-8910ミキサー,I/O設定サブルーチン C066 : BD C4 4B " K" jsr LC44B //PCM_2再生(終了音声) C069 : 20 95 " " bra LC000 //プログラム先頭へ ; C06B LC06B: //変数初期化:LC000より C06B : 0F " " sei //割り込み無効 C06C : 8E 00 60 " `" lds #$0060 //スタックポインタに#$0060を入れる(HD63A03XPは$0040~$00FFまで内蔵RAMを持ち、その内$0040~$0060をスタック領域とする) C06F : CE 00 62 " b" ldx #$0062 //Xレジスタに#$0062を入れる C072 : 4F "O" clra //aレジスタクリア C073 LC073: //メモリ初期化ループ:LC073より C073 : A7 00 " " staa $00,x //-/ C075 : 08 " " inx //-/ C076 : 8C 00 FF " " cpx #$00FF //-/ C079 : 26 F8 "& " bne LC073 //-/X62~XFFまでメモリ初期化(変数初期化) C07B : 86 00 " " ldaa #$00 C07D : 97 08 " " staa X0008 //X0008(タイマーコントロール/ステータスレジスタ1)に0x00をセット C07F : 86 10 " " ldaa #$10 C081 : 97 0F " " staa X000F //X000F(タイマーコントロール/ステータスレジスタ2)に0x10をセット__(4bit目は予約ビットであり、なぜ入れているか不明) C083 : 86 20 " " ldaa #$20 C085 : 97 1B " " staa X001B //X001B(タイマーコントロール/ステータスレジスタ3)に0x20をセット__(5bit目は予約ビットであり、なぜ入れているか不明) C087 : 86 20 " " ldaa #$20 C089 : 97 11 " " staa X0011 //X0011(tx、rxコントロールステータスレジスタ)に0x20をセット__(Transmit Data Register Empty = H) C08B : 86 04 " " ldaa #$04 C08D : 97 10 " " staa X0010 //X0010(レート、モードコントロールレジスタ)に0x04をセット__(ポート2,P22をSCIで使用しない) C08F : 86 40 " @" ldaa #$40 C091 : 97 14 " " staa X0014 //X0014(RAM/ポート5コントロールレジスタ)に0x40をセット__(MRE = H) C093 : 86 FF " " ldaa #$FF C095 : 97 01 " " staa X0001 //X0001(ポート2データ方向レジスタ)に0xFFをセット__(-, -, -, -, -, -,DDR1~7 = H, DDR0 = H) C097 : 86 FB " " ldaa #$FB C099 : 97 16 " " staa X0016 //X0016(ポート6データ方向レジスタ)に0xFBをセット__(ポート6,P62のみ入力) C09B : 86 00 " " ldaa #$00 C09D : 97 03 " " staa X0003 //X0003(ポート2)に0x00を入れる C09F : 97 17 " " staa X0017 //X0017(ポート6)に0x00を入れる C0A1 : 7E C0 06 "~ " jmp LC006 //LC006(演奏前準備)へ ; C0A4 LC0A4://AY-3-8910ミキサー,I/O設定(AY-3-8910:PORTAは出力、PORTBは入力) C0A4 : 86 7F " " ldaa #$7F //AY-3-8910ミキサー,I/O設定レジスタに0x7F入れる C0A6 : 97 73 " s" staa X0073 C0A8 : C6 07 " " ldab #$07 //AY-3-8910アドレス#$07(ミキサー,I/O設定レジスタ) C0AA : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C0AD : 39 "9" rts //サブルーチン終了 ; C0AE LC0AE: //ディップスイッチの状態を読み取り、X0089へ入れる:LC009より C0AE : C6 0F " " ldab #$0F //Bレジスタに#$0Fを入れる C0B0 : 86 03 " " ldaa #$03 //Aレジスタに#$03を入れる C0B2 : 97 17 " " staa X0017 //X0017(ポート6)に#$03を入れる__(P60=BD1=H, P61=BDIR=H__AY-3-8910アドレスラッチモード) C0B4 : D7 03 " " stab X0003 //X0003(ポート2)に#$0Fを入れる__(AY-3-8910ポートB(ディップスイッチ)アドレス指定) C0B6 : 86 00 " " ldaa #$00 //*/Aレジスタに#$00を入れる C0B8 : 97 17 " " staa X0017 //*/X0017(ポート6)に#$00を入れる__(P60=BD1=L, P61=BDIR=L__AY-3-8910インアクティブモード) C0BA : 86 01 " " ldaa #$01 //+/Aレジスタに#$01を入れる C0BC : 97 17 " " staa X0017 //+/X0017(ポート6)に#$01を入れる__(P60=BD1=H, P61=BDIR=L__AY-3-8910_リードモード) C0BE : 86 00 " " ldaa #$00 //-/Aレジスタに#$00を入れる C0C0 : 97 01 " " staa X0001 //-/X0001(ポート2データ方向レジスタ)に#$01を入れる__(ポート2_P20~P27_INPUTモードに設定) C0C2 : 96 03 " " ldaa X0003 //AレジスタにX0003(ポート2)を入れる__(AY-3-8910ポートB(ディップスイッチ)読み取り) C0C4 : 97 89 " " staa X0089 //X0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)にAレジスタ(AY-3-8910ポートB(ディップスイッチ)の状態)を入れる__ C0C6 : 86 00 " " ldaa #$00 //*/Aレジスタに#$00を入れる C0C8 : 97 17 " " staa X0017 //*/X0017(ポート6)に#$00を入れる__(P60=BD1=L, P61=BDIR=L__AY-3-8910インアクティブモード) C0CA : 86 FF " " ldaa #$FF //+/Aレジスタに#$00を入れる C0CC : 97 01 " " staa X0001 //+/X0001(ポート2データ方向レジスタ)に#$01を入れる__(ポート2_P20~P27_OUTPUTモードに設定) C0CE : 39 "9" rts //サブルーチン終了 ; C0CF LC0CF: //演奏前準備:LC006より C0CF : CE 00 0F " " ldx #$000F C0D2 : DF 6F " o" stx X006F //X006Fに#$000F C0D4 : CE C5 F0 " " ldx #$C5F0 //演奏前準備読み取り開始アドレス C0D7 : 86 05 " " ldaa #$05 C0D9 : 97 78 " x" staa X0078 //X0078(選曲)に#$05(#$05番目は無選曲処理としてのフラグ) C0DB : 7E C1 E2 "~ " jmp LC1E2 //楽譜データ(演奏前準備用データ)読み取り処理 ; C0DE LC0DE: //ディップスイッチの状態から「ディップスイッチの使用法B」の「コイン枚数」の番号をX007F(「ディップスイッチの使用法B」「コイン枚数」設定用)に入れる:LC009より C0DE : 96 89 " " ldaa X0089 //+/AレジスタにX0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)を入れる C0E0 : 84 03 " " anda #$03 //+/A = A & 0x03__(ディップスイッチ2,1読み取り(「ディップスイッチの使用法B」「コイン枚数」設定用)) C0E2 : 81 01 " " cmpa #$01 //+/ C0E4 : 27 0F "' " beq LC0F5 //+/Aレジスタが1の時、LC0F5(X007F(「ディップスイッチの使用法B」「コイン枚数」設定用)に#$00を入れる処理)へ C0E6 : 81 02 " " cmpa #$02 ///////////////同様 C0E8 : 27 10 "' " beq LC0FA C0EA : 81 03 " " cmpa #$03 C0EC : 27 11 "' " beq LC0FF C0EE : 81 00 " " cmpa #$00 C0F0 : 27 12 "' " beq LC104 ///////////// C0F2 : 7E C0 00 "~ " jmp LC000 //プログラム先頭へ(通常到達しないコード) ; C0F5 LC0F5: //LC0DEより C0F5 : 86 01 " " ldaa #$01 C0F7 : 97 7F " " staa X007F //X007F(「「ディップスイッチの使用法B」「コイン枚数」設定用)に#$01を入れる C0F9 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C0FA LC0FA: //LC0DEより C0FA : 86 02 " " ldaa #$02 C0FC : 97 7F " " staa X007F //X007F(「「ディップスイッチの使用法B」「コイン枚数」設定用)に#$02を入れる C0FE : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C0FF LC0FF: //LC0DEより C0FF : 86 03 " " ldaa #$03 C101 : 97 7F " " staa X007F //X007F(「「ディップスイッチの使用法B」「コイン枚数」設定用)に#$03を入れる C103 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C104 LC104: //LC0DEより C104 : 86 04 " " ldaa #$04 C106 : 97 7F " " staa X007F //X007F(「「ディップスイッチの使用法B」「コイン枚数」設定用)に#$04を入れる C108 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C109 LC109: //ディップスイッチの状態から「ディップスイッチの使用法B」の「タイマー2周回数」の番号をX0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)に入れる:LC009より C109 : 96 89 " " ldaa X0089 //AレジスタにX0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)を入れる C10B : 84 70 " p" anda #$70 //A = A & 0x70__(ディップスイッチ7~5読み取り(「ディップスイッチの使用法B」タイマー2 周回数設定)) C10D : 81 00 " " cmpa #$00 //+/ C10F : 27 1F "' " beq LC130 //+/Aレジスタが0の時、LC130(X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$00を入れる処理)へ C111 : 81 10 " " cmpa #$10 ///////////////同様 C113 : 27 20 "' " beq LC135 C115 : 81 20 " " cmpa #$20 C117 : 27 21 "'!" beq LC13A C119 : 81 30 " 0" cmpa #$30 C11B : 27 22 "'"" beq LC13F C11D : 81 40 " @" cmpa #$40 C11F : 27 23 "'#" beq LC144 C121 : 81 50 " P" cmpa #$50 C123 : 27 24 "'$" beq LC149 C125 : 81 60 " `" cmpa #$60 C127 : 27 25 "'%" beq LC14E C129 : 81 70 " p" cmpa #$70 C12B : 27 26 "'&" beq LC153 ///////////// C12D : 7E C0 00 "~ " jmp LC000 //プログラム先頭へ(通常到達しないコード) ; C130 LC130: //:LC109より C130 : 86 00 " " ldaa #$00 C132 : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$00を入れる C134 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C135 LC135: //:LC109より C135 : 86 01 " " ldaa #$01 C137 : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$01を入れる C139 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C13A LC13A: //:LC109より C13A : 86 02 " " ldaa #$02 C13C : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$02を入れる C13E : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C13F LC13F: //:LC109より C13F : 86 03 " " ldaa #$03 C141 : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$03を入れる C143 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C144 LC144: //:LC109より C144 : 86 04 " " ldaa #$04 C146 : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$04を入れる C148 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C149 LC149: //:LC109より C149 : 86 05 " " ldaa #$05 C14B : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$05を入れる C14D : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C14E LC14E: //:LC109より C14E : 86 06 " " ldaa #$06 C150 : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$06を入れる C152 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C153 LC153: //:LC109より C153 : 86 07 " " ldaa #$07 C155 : 97 80 " " staa X0080 //X0080(「ディップスイッチの使用法B」「タイマー2 周回数」設定用)に#$07を入れる C157 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C158 LC158: //「ディップスイッチの使用法B」「タイマー1」ディップスイッチ読み取り:LC03Cより C158 : 96 89 " " ldaa X0089 //*/AレジスタにX0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)を入れる C15A : 84 0C " " anda #$0C //*/A = A & 0x0C __(ディップスイッチ3,4(「ディップスイッチの使用法B」「タイマー1」)) C15C : 81 00 " " cmpa #$00 //*/ C15E : 27 0E "' " beq LC16E //*/X0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)が#$00(「タイマー1」60秒)の時、LC16Eへ C160 : 81 04 " " cmpa #$04 //*/ C162 : 27 0F "' " beq LC173 //*/X0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)が#$04(「タイマー1」90秒)の時、LC173へ C164 : 81 08 " " cmpa #$08 //*/ C166 : 27 10 "' " beq LC178 //*/X0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)が#$08(「タイマー1」120秒)の時、LC178へ C168 : 81 0C " " cmpa #$0C //*/ C16A : 27 11 "' " beq LC17D //*/X0089(AY-3-8910のポートB(ディップスイッチ)の状態保存用)が#$0C(「タイマー1」30秒)の時、LC17Dへ C16C : 20 05 " " bra LC173 //LC173(「タイマー1」90秒)へ(通常到達しないコード) ; C16E LC16E: //LC158より C16E : 86 3C " <" ldaa #$3C //+/Aレジスタに#$3C(60D)を入れる C170 : 97 7B " {" staa X007B //+/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)に60を入れる C172 : 39 "9" rts //サブルーチン終了(LC03Cへ戻る) ; C173 LC173: //LC158より C173 : 86 5A " Z" ldaa #$5A //+/Aレジスタに#$5A(90D)を入れる C175 : 97 7B " {" staa X007B //+/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)に90を入れる C177 : 39 "9" rts //サブルーチン終了(LC03Cへ戻る) ; C178 LC178: //LC158より C178 : 86 78 " x" ldaa #$78 //+/Aレジスタに#$78(120D)を入れる C17A : 97 7B " {" staa X007B //+/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)に120を入れる C17C : 39 "9" rts //サブルーチン終了(LC03Cへ戻る) ; C17D LC17D: //LC158より C17D : 86 1E " " ldaa #$1E //+/Aレジスタに#$1E(30D)を入れる C17F : 97 7B " {" staa X007B //+/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)に30を入れる C181 : 39 "9" rts //サブルーチン終了(LC03Cへ戻る) ; C182 LC182: //コイン投入ボタン(茶線)処理:LC009より C182 : 96 15 " " ldaa X0015 //*/AレジスタにX0015(ポート5)を入れる C184 : 84 04 " " anda #$04 //*/A = A & 0x04 (茶線) C186 : 27 04 "' " beq LC18C //*/(X0015(ポート5) & 0x04)が0の時(茶線を押したとき)、LC18C(コイン投入ボタンのフラグ処理)へ C188 : 4F "O" clra //Aレジスタクリア C189 : 97 79 " y" staa X0079 //X0079(コイン投入モードフラグ)に0を入れる C18B : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C18C LC18C: //コイン投入ボタンのフラグ処理:LC182より C18C : 86 08 " " ldaa #$08 //+/Aレジスタに#$08を入れる C18E : 97 17 " " staa X0017 //+/X0017(ポート6)に#$08を入れる(パワトラ緑線を導通) C190 : C6 8F " " ldab #$8F //Bレジスタに#$8Fを入れる(ウェイト) C192 : 8D 1D " " bsr LC1B1 //LC1B1(ループウェイト処理B_レジスタで設定)へ C194 : 86 00 " " ldaa #$00 //*/Aレジスタに#$08を入れる C196 : 97 17 " " staa X0017 //*/X0017(ポート6)に#$00を入れる(パワトラ緑線を開放) C198 : 96 7E " ~" ldaa X007E //-/AレジスタにX007Eを入れる C19A : 4C "L" inca //-/Aレジスタインクリメント C19B : 97 7E " ~" staa X007E //-/X007E(コイン投入ボタンのコイン入回数) = X007E + 1 C19D : 91 7F " " cmpa X007F //-/ C19F : 27 08 "' " beq LC1A9 //-/X007E(コイン投入ボタンのコイン入回数)がX007F(「ディップスイッチの使用法B」「コイン枚数」設定用)と等しい場合、LC1A9 C1A1 : 4F "O" clra //+/Aレジスタクリア C1A2 : 97 79 " y" staa X0079 //+/X0079(コイン投入モードフラグ)に0を入れる C1A4 : C6 60 " `" ldab #$60 //Bレジスタに#$60を入れる(ウェイト) C1A6 : 8D 09 " " bsr LC1B1 //LC1B1(ループウェイト処理B_レジスタで設定)へ C1A8 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C1A9 LC1A9: //LC18Cより C1A9 : 86 01 " " ldaa #$01 //+/Aレジスタに#$01を入れる C1AB : 97 79 " y" staa X0079 //+/X0079(コイン投入モードフラグ)に1を入れる C1AD : 4F "O" clra //*/Aレジスタクリア C1AE : 97 7E " ~" staa X007E //*/X007E(コイン投入ボタンのコイン入回数)に0を入れる C1B0 : 39 "9" rts //サブルーチン終了(LC009へ戻る) ; C1B1 LC1B1: //-/ループウェイトB_レジスタで設定 C1B1 : CE 00 FF " " ldx #$00FF C1B4 LC1B4: C1B4 : 09 " " dex C1B5 : 26 FD "& " bne LC1B4 C1B7 : 5A "Z" decb C1B8 : 26 F7 "& " bne LC1B1 C1BA : 39 "9" rts //-/ ; C1BB LC1BB: //ポート6操作系(AY-3-8910のP60=BD1,P61=BDIR)//AY-3-8910書き込みサブルーチン C1BB : 96 17 " " ldaa X0017// X0017 = (X0017 & FC) | 0x03 C1BD : 84 FC " " anda #$FC C1BF : 8A 03 " " oraa #$03 C1C1 : 97 17 " " staa X0017//(BD1=H,BDIR=H:AY-3-8910アドレスラッチモード) C1C3 LC1C3: //ポート2操作系(AY-3-8910のDA0~DA7) C1C3 : D7 03 " " stab X0003 //X0003(ポート2)にbレジスタを入れる C1C5 : 84 FC " " anda #$FC C1C7 : 97 17 " " staa X0017 // X0017 = 0xFC & X0017(BD1=L,BDIR=L:AY-3-8910インアクティブモード) C1C9 : 96 73 " s" ldaa X0073 //+/ C1CB : 97 03 " " staa X0003 //+/X0003(ポート2)にX0073(AY-3-8910のDA0~DA7に出力するデータ)を入れる C1CD : 96 17 " " ldaa X0017 //-/X0017 = (X0017 & 0xFC) | 0x02 C1CF : 84 FC " " anda #$FC //-/ C1D1 : 8A 02 " " oraa #$02 //-/ C1D3 : 97 17 " " staa X0017 //-/(BD1=H,BDIR=H:AY-3-8910_PSG書き込みモード) C1D5 : 84 FC " " anda #$FC //*/X0017 = (X0017 & 0xFC) C1D7 : 97 17 " " staa X0017 //*/(BD1=L,BDIR=L:AY-3-8910インアクティブモード) C1D9 : 39 "9" rts //サブルーチン終了 ; C1DA LC1DA: //-/xレジスタにセットされた現在の読み取りポイントをX0073(AY-3-8910のDA0~DA7に出力するデータ)に入れる C1DA : A6 00 " " ldaa $00,x //-/ C1DC : 97 73 " s" staa X0073 //-/ C1DE : 39 "9" rts //サブルーチン終了 ; C1DF LC1DF://演奏開始先頭楽譜データ1ブロック読み取り(先頭1ブロックはエンベロープ等の設定) C1DF : 08 " " inx // C1E0 : 08 " " inx // C1E1 : 08 " " inx // C1E2 LC1E2: //(演奏前準備データの場合のみここからスタート):LC0CFより C1E2 : C6 01 " " ldab #$01 //AY-3-8910アドレス指定:チャンネルAの音程上位4ビット(演奏前処理データ0バイト目、演奏開始楽譜データ3バイト目) C1E4 : 8D F4 " " bsr LC1DA //xレジスタにセットされた現在の読み取りポイントをX0073に入れる C1E6 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C1E9 : 08 " " inx C1EA : C6 06 " " ldab #$06 //AY-3-8910アドレス指定:ノイズ分周(演奏前処理データ1バイト目、演奏開始楽譜データ4バイト目) C1EC : 8D EC " " bsr LC1DA //xレジスタにセットされた現在の読み取りポイントをX0073に入れる C1EE : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C1F1 : 08 " " inx C1F2 : C6 0B " " ldab #$0B //AY-3-8910アドレス指定:エンベロープ周期(演奏前処理データ2バイト目、演奏開始楽譜データ5バイト目) C1F4 : 8D E4 " " bsr LC1DA //xレジスタにセットされた現在の読み取りポイントをX0073に入れる C1F6 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C1F9 : 08 " " inx C1FA : C6 0C " " ldab #$0C //AY-3-8910アドレス指定:エンベロープ周期(演奏前処理データ3バイト目、演奏開始楽譜データ6バイト目) C1FC : 8D DC " " bsr LC1DA //xレジスタにセットされた現在の読み取りポイントをX0073に入れる C1FE : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C201 : 08 " " inx C202 : C6 0D " " ldab #$0D //AY-3-8910アドレス指定:エンベロープ波形(演奏前処理データ4バイト目、演奏開始楽譜データ7バイト目) C204 : 8D D4 " " bsr LC1DA //xレジスタにセットされた現在の読み取りポイントをX0073に入れる C206 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C209 : 08 " " inx C20A LC20A: //楽譜データ1ブロック読み取りループ:LC2E5より C20A : A6 00 " " ldaa $00,x //*/Aレジスタにxアドレスにある値を入れる(楽譜データ読み取り) C20C : 81 FF " " cmpa #$FF //*/ C20E : 27 58 "'X" beq LC268 //*/楽譜データ0バイト目が#$FFのとき、LC268(曲終端(ループ)処理)へ C210 : A6 00 " " ldaa $00,x //+/Aレジスタにxアドレスにある値を入れる(楽譜データ読み取り) C212 : 81 0F " " cmpa #$0F //+/ C214 : 27 55 "'U" beq LC26B //+/楽譜データ0バイト目が#$0Fのとき、LC26B(曲終端(リセット)処理)へ C216 : C6 00 " " ldab #$00 //AY-3-8910アドレス指定:チャンネルAの音程下位8ビット(楽譜データ0バイト目) C218 : 8D C0 " " bsr LC1DA //Xレジスタにセットされた現在の読み取りポイントをX0073に入れる C21A : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C21D : 08 " " inx C21E : C6 02 " " ldab #$02 //AY-3-8910アドレス指定:チャンネルBの音程下位8ビット(楽譜データ1バイト目) C220 : 8D B8 " " bsr LC1DA //Xレジスタにセットされた現在の読み取りポイントをX0073に入れる C222 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C225 : 08 " " inx C226 : C6 03 " " ldab #$03 //AY-3-8910アドレス指定:チャンネルBの音程上位4ビット(楽譜データ2バイト目) C228 : 8D B0 " " bsr LC1DA //Xレジスタにセットされた現在の読み取りポイントをX0073に入れる C22A : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C22D : 08 " " inx C22E : C6 04 " " ldab #$04 //AY-3-8910アドレス指定:チャンネルCの音程下位8ビット(楽譜データ3バイト目) C230 : 8D A8 " " bsr LC1DA //Xレジスタにセットされた現在の読み取りポイントをX0073に入れる C232 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C235 : 08 " " inx C236 : C6 05 " " ldab #$05 //AY-3-8910アドレス指定:チャンネルCの音程上位4ビット(楽譜データ4バイト目) C238 : 8D A0 " " bsr LC1DA //Xレジスタにセットされた現在の読み取りポイントをX0073に入れる C23A XC23A:(無効なラベル) C23A : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C23D : 08 " " inx C23E : BD C3 24 " $" jsr LC324 //LC324(AY-3-8910ノートオンオフ関連楽譜データ読み取り&AY-3-8910へ書き込みサブルーチン)へ(楽譜データ5,6バイト目) C241 : 08 " " inx C242 : 96 78 " x" ldaa X0078 //現在のポイントのデータを読み取り(楽譜データ7バイト目(ブロック終端)) C244 : 81 05 " " cmpa #$05 //-/楽譜データ7バイト目が#$05で0ディレイで次の楽譜読み取り C246 : 27 C2 "' " beq LC20A //-/楽譜データ7バイト目が#$05でLC20A(楽譜データ1ブロック読み取り)へ C248 : 96 82 " " ldaa X0082 //+/X0082(パワトラ点滅保存用)をAレジスタへ入れる C24A : 26 0E "& " bne LC25A //+/X0082(パワトラ点滅保存用)が0でない時、LC25Aへ C24C : 96 17 " " ldaa X0017 //AレジスタにX0017(ポート6)を入れる C24E : 84 3F " ?" anda #$3F //A = A & 0x3F C250 : 8A 80 " " oraa #$80 //A = A | 0x80 C252 : 97 17 " " staa X0017 //X0017(ポート6)にAレジスタを入れる__(ポート6 = (ポート6 & B00111111) | B10000000)(P67(パワトラ)をH,P66(パワトラ)をLにする) C254 : 86 01 " " ldaa #$01 //*/Aレジスタに#$00を入れる C256 : 97 82 " " staa X0082 //*/X0082(パワトラ点滅保存用)に#$01を入れる C258 : 20 14 " " bra LC26E //LC26Eへ ; C25A LC25A: //ポート6操作系(AY-3-8910のP60=BD1,P61=BDIR)(パワトラ点滅処理分岐) C25A : 96 17 " " ldaa X0017 //AレジスタにX0017(ポート6)を入れる C25C : 84 3F " ?" anda #$3F //A = A & 0x3F C25E : 8A 40 " @" oraa #$40 //A = A | 0x40 C260 : 97 17 " " staa X0017 //X0017(ポート6)にAレジスタを入れる__(ポート6 = (ポート6 & B00111111) | B01000000)(P67(パワトラ)をL,(P66(パワトラ)をHにする) C262 : 86 00 " " ldaa #$00 //+/Aレジスタに#$00を入れる C264 : 97 82 " " staa X0082 //+/X0082(パワトラ点滅保存用)に#$00を入れる C266 : 20 06 " " bra LC26E //LC26Eへ C268 LC268: //曲終端(ループ)処理:LC20Aより C268 : 7E C2 EC "~ " jmp LC2EC //LC2EC(曲ループ処理)へ C26B LC26B: //曲終端(リセット)処理:LC20Aより C26B : 7E C2 EB "~ " jmp LC2EB //LC2EB(曲リセット処理)へ ; C26E LC26E: //:LC20Aより C26E : DF 69 " i" stx X0069 //X0069(Xレジスタ一時退避用)にXレジスタ(楽譜データブロック7バイト目のアドレスが入っている?)の値を入れる C270 : 0E " " cli //割り込みフラグクリア C271 : 86 42 " B" ldaa #$42 //-/Aレジスタに#$42を入れる_※X0014=(STBY_PWR,RAME,-,-,HLTE,MRE,IRQ2_E,IRQ1_E) C273 : 97 14 " " staa X0014 //-/X0014(RAM/ポート5コントロールレジスタ)に#$42を入れる__(STBY_PWR=L, RAME=H, -, -, HLTE=L, MRE=L, IRQ2_E=H, IRQ1_E=L)(オンチップメモリ有効,割り込みIRQ2有効にセット) C275 : A6 00 " " ldaa $00,x //AレジスタにXレジスタ(楽譜データブロック7バイト目のアドレスが入っている?)に入ったアドレスにある値を入れる C277 LC277: //LC2D4より(楽譜データブロック7バイト目に0が入っている場合ここに飛ぶ) C277 : DE 6F " o" ldx X006F //XレジスタにX006F(楽曲テンポ)を入れる C279 LC279: //演奏用ウェイトループ先頭とボタン読み取り処理(PCM再生用) C279 : 7C 00 8E "| " inc X008E //+/X008Eインクリメント C27C : 7A 00 8E "z " dec X008E //+/X008Eデクリメント(X008Eの操作はここだけなのでウェイト処理?) C27F : C6 10 " " ldab #$10 //Bレジスタに#$10を入れる C281 : 7D 00 84 "} " tst X0084 //(「定位置で止まる」スイッチ押されたフラグ?)のテスト(フラグレジスタのみ変化) C284 : 26 76 "&v" bne LC2FC //X0084(「定位置で止まる」スイッチ押されたフラグ?)が0でないときはLC2FC(課金分終了処理)へ C286 : D6 15 " " ldab X0015 //*/BレジスタにX0015(ポート5)を入れる__(ポート5はPCM再生用のボタンへ接続) C288 : C4 F0 " " andb #$F0 //*/B = B & 0xF0 C28A : C1 00 " " cmpb #$00 //*/ C28C : 27 10 "' " beq LC29E //*/X0015(ポート5)の上位4bitがB0000の時(赤,黄,橙,白の線のボタンが押されていない時)、LC29Eへ C28E : C1 10 " " cmpb #$10 //+/ C290 : 27 11 "' " beq LC2A3 //+/X0015(ポート5)の上位4bitがB0001の時(橙の線のボタンが押された時)、LC2A3へ C292 : C1 20 " " cmpb #$20 //-/ C294 : 27 13 "' " beq LC2A9 //-/X0015(ポート5)の上位4bitがB0010の時(黄の線のボタンが押された時)、LC2A9へ C296 : C1 40 " @" cmpb #$40 //*/ C298 : 27 15 "' " beq LC2AF //*/X0015(ポート5)の上位4bitがB0100の時(白の線のボタンが押された時)、LC2AFへ C29A : C1 80 " " cmpb #$80 //+/ C29C : 27 17 "' " beq LC2B5 //+/X0015(ポート5)の上位4bitがB1000の時(赤の線のボタンが押された時)、LC2B5へ C29E LC29E: //(すべて押されていない時):LC279より C29E : 7F 00 8D " " clr X008D //X008D(PCM再生ボタン読み取り用)に#$00を入れる C2A1 : 20 16 " " bra LC2B9 //LC2B9(演奏用ウェイト処理)へ ; C2A3 LC2A3: //(橙の線のボタンが押された時):LC279より C2A3 : C6 01 " " ldab #$01 //+/ C2A5 : D7 8D " " stab X008D //+/X008D(PCM再生ボタン読み取り用)に#$01を入れる C2A7 : 20 10 " " bra LC2B9 //LC2B9(演奏用ウェイト処理)へ ; C2A9 LC2A9: //(黄の線のボタンが押された時):LC279より C2A9 : C6 02 " " ldab #$02 //-/ C2AB XC2AB:(無効なラベル) C2AB : D7 8D " " stab X008D //-/X008D(PCM再生ボタン読み取り用)に#$02を入れる C2AD : 20 0A " " bra LC2B9 //LC2B9(演奏用ウェイト処理)へ ; C2AF LC2AF: //(白の線のボタンが押された時):LC279より C2AF : C6 03 " " ldab #$03 //*/ C2B1 : D7 8D " " stab X008D //*/X008D(PCM再生ボタン読み取り用)に#$03を入れる C2B3 : 20 04 " " bra LC2B9 //LC2B9(演奏用ウェイト処理)へ ; C2B5 LC2B5: //(赤の線のボタンが押された時):LC279より C2B5 : C6 04 " " ldab #$04 //+/ C2B7 : D7 8D " " stab X008D //+/X008D(PCM再生ボタン読み取り用)に#$04を入れる C2B9 LC2B9: //演奏用ウェイト処理(Xレジスタに入ったX006F(楽曲テンポ)から1を引いていき0になるまでLC279ループ) C2B9 : 09 " " dex //Xレジスタデクリメント(Xレジスタの初期値はX006F(楽曲テンポ)) C2BA : 26 BD "& " bne LC279 //Xレジスタが0出ない時、LC279(演奏用ウェイトループ先頭)へ C2BC : D6 80 " " ldab X0080 //-/BレジスタにX0080を入れる C2BE : C1 00 " " cmpb #$00 //-/ C2C0 : 27 06 "' " beq LC2C8 //-/ C2C2 : C1 07 " " cmpb #$07 //-/ C2C4 : 27 02 "' " beq LC2C8 //-/X0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)が#$00(「タイマー1」)または#$07(「タイマー2」)の時、LC2C8へ C2C6 : 20 09 " " bra LC2D1 //LC2D1(LC365(赤,橙,黄,白ボタン状態分岐 & PCM再生処理))へ ; C2C8 LC2C8: //LC2B9より C2C8 : 8D 35 " 5" bsr LC2FF //LC2FF(課金タイマー処理関連?)へ C2CA : 0C " " clc C2CB : D6 7B " {" ldab X007B //*/BレジスタにX007B(「ディップスイッチの使用法B」「タイマー1」設定用)を入れる C2CD : C0 05 " " subb #$05 //*/B = B - 0x05 C2CF : 25 03 "% " bcs LC2D4 //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が6以上の場合、LC2D4へ C2D1 LC2D1: //LC2B9より C2D1 : BD C3 65 " e" jsr LC365 //LC365(赤,橙,黄,白ボタン状態分岐 & PCM再生処理)へ C2D4 LC2D4: //:LC2C8より::LC365(赤,橙,黄,白ボタン状態分岐 & PCM再生処理)からの戻り C2D4 : 4A "J" deca //Aレジスタ(LC26Eで入れた楽譜データブロック7バイト目が入っている?)デクリメント C2D5 : 26 A0 "& " bne LC277 //Aレジスタが0でない時、LC277へ C2D7 : D6 80 " " ldab X0080 //-/BレジスタにX0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)を入れる C2D9 : C1 07 " " cmpb #$07 //-/ C2DB : 26 08 "& " bne LC2E5 //-/X0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)が#$07(「タイマー2」)の時、LC2E5(楽譜データの次のブロックへ読み取り)へ C2DD : D6 7B " {" ldab X007B //+/BレジスタにX007B(「ディップスイッチの使用法B」「タイマー1」設定用)を入れる C2DF : 27 1B "' " beq LC2FC //+/ C2E1 : C1 01 " " cmpb #$01 //+/ C2E3 : 27 17 "' " beq LC2FC //+/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が0または1の時、LC2FC(課金分終了処理)へ C2E5 LC2E5: //楽譜データの次のブロックへ読み取り:LC2D4より C2E5 : DE 69 " i" ldx X0069 //XレジスタにX0069(LC26E内Xレジスタ一時退避用(楽譜データブロック7バイト目))を入れる C2E7 : 08 " " inx //Xレジスタインクリメント(次の楽譜データブロックの0バイト目を指定) C2E8 : 7E C2 0A "~ " jmp LC20A //LC20A(楽譜データ1ブロック読み取りループ)へ C2EB LC2EB: //曲終端判定(リセット):LC26Bより C2EB : 39 "9" rts //サブルーチン終了 ; C2EC LC2EC: //曲終端判定(ループ):LC268より C2EC : 96 78 " x" ldaa X0078 // C2EE : 81 01 " " cmpa #$01 C2F0 : 27 04 "' " beq LC2F6 //X0078(選曲)が#$01の時,LC2F6(一曲目演奏開始)へ C2F2 : 81 02 " " cmpa #$02 C2F4 : 27 03 "' " beq LC2F9 //X0078(選曲)が#$02の時,LC2F9(二曲目演奏開始)へ C2F6 LC2F6: //LC2ECより C2F6 : 7E C4 0D "~ " jmp LC40D //LC40D(一曲目演奏開始)へ C2F9 LC2F9: //LC2ECより C2F9 : 7E C4 22 "~ "" jmp LC422 //LC422(二曲目演奏開始)へ C2FC LC2FC: //課金分終了処理:LC2D4より C2FC : 7E C0 57 "~ W" jmp LC057 //課金分終了処理へ ; C2FF LC2FF: //LC2C8より C2FF : 0C " " clc //キャリーフラグクリア C300 : 7A 00 7A "z z" dec X007A //X007A(課金動作タイマーカウンタ用)デクリメント C303 : 27 01 "' " beq LC306 //X007A(課金動作タイマーカウンタ用)が0の時、LC306へ C305 : 39 "9" rts //サブルーチン終了(LC2C8へ戻る) ; C306 LC306: LC2FFより C306 : D6 80 " " ldab X0080 //BレジスタにX0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)を入れる C308 : C1 00 " " cmpb #$00 //*/ C30A : 27 05 "' " beq LC311 //*/ C30C : C1 07 " " cmpb #$07 //*/ C30E : 27 01 "' " beq LC311 //*/X0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)が0(「タイマー1」)または7(「タイマー2」)の時、LC311へ C310 : 39 "9" rts //サブルーチン終了(LC2C8へ戻る) ; C311 LC311: LC306より C311 : 7A 00 7B "z {" dec X007B //X007B(「ディップスイッチの使用法B」「タイマー1」設定用)デクリメント C314 : 27 05 "' " beq LC31B //X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が0の時、LC31Bへ C316 : D6 7C " |" ldab X007C //+/BレジスタにX007C(課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?))を入れる C318 : D7 7A " z" stab X007A //+/X007A(課金動作タイマーカウンタ用)にX007C(課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?))を入れる C31A : 39 "9" rts //サブルーチン終了(LC2C8へ戻る) ; C31B LC31B: LC311より C31B : D6 7C " |" ldab X007C //-/BレジスタにX007C(課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?))を入れる C31D : D7 7A " z" stab X007A //-/X007A(課金動作タイマーカウンタ用)にX007C(課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?))を入れる C31F : C6 01 " " ldab #$01 //*/Bレジスタに#$01を入れる C321 : D7 7B " {" stab X007B //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)に#$01を入れる C323 : 39 "9" rts //サブルーチン終了(LC2C8へ戻る) ; C324 LC324: //AY-3-8910ノートオンオフ関連楽譜データ読み取り:LC20Aより C324 : A6 00 " " ldaa $00,x //-/Xレジスタアドレスにある値(楽譜データのブロックの5バイト目)をAレジスタに入れる C326 : 84 0F " " anda #$0F //-/A = A & 0x0F C328 : 8A 30 " 0" oraa #$30 //-/A = A | 0x30 C32A : 97 73 " s" staa X0073 //-/X0073(AY-3-8910のDA0~DA7に出力するデータ用)に((楽譜データのブロックの5バイト目 & 0x0F) | 0x30)を入れる__(ノイズC,Bは無効、下位4ビット(ノイズA,チャンネルC,チャンネルB,チャンネルA)のミキサーコントロール、I/O設定レジスタの設定) C32C : C6 07 " " ldab #$07 //AY-3-8910アドレス指定:ミキサーコントロール、I/O設定レジスタ C32E : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C331 : A6 00 " " ldaa $00,x //+/Xレジスタアドレスにある値(楽譜データのブロックの5バイト目)をAレジスタに入れる C333 : 84 F0 " " anda #$F0 //+/A = A & 0xF0 C335 : 8A 00 " " oraa #$00 //+/(無意味な処理) C337 : 97 73 " s" staa X0073 //+/X0073(AY-3-8910のDA0~DA7に出力するデータ用)に(楽譜データのブロックの5バイト目 & 0xF0)を入れる__(チャンネルAエンベロープ有効無効(4bit目)のみ操作) C339 : C6 08 " " ldab #$08 //AY-3-8910アドレス指定:チャンネルAエンベロープ音量設定レジスタ C33B : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C33E : 08 " " inx C33F : A6 00 " " ldaa $00,x //*/Xレジスタアドレスにある値(楽譜データのブロックの6バイト目)をAレジスタに入れる C341 : 84 F0 " " anda #$F0 //*/A = A & 0xF0 C343 : 8A 00 " " oraa #$00 //*/(無意味な処理) C345 : 97 73 " s" staa X0073 //*/X0073(AY-3-8910のDA0~DA7に出力するデータ用)に(楽譜データのブロックの6バイト目 & 0xF0)を入れる__(チャンネルBエンベロープ有効無効(4bit目)のみ操作) C347 : C6 09 " " ldab #$09 //AY-3-8910アドレス指定:チャンネルBエンベロープ音量設定レジスタ C349 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C34C : A6 00 " " ldaa $00,x //-/Xレジスタアドレスにある値(楽譜データのブロックの6バイト目)をAレジスタに入れる C34E : 48 "H" asla //-/Aレジスタの値を1ビット左シフト C34F : 48 "H" asla //-/Aレジスタの値を1ビット左シフト C350 : 48 "H" asla //-/Aレジスタの値を1ビット左シフト C351 : 48 "H" asla //-/Aレジスタの値を1ビット左シフト C352 : 8A 00 " " oraa #$00 //-/(無意味な処理) C354 : 97 73 " s" staa X0073 //-/X0073(AY-3-8910のDA0~DA7に出力するデータ用)に((楽譜データのブロックの6バイト目<<4) & 0xF0)を入れる__(チャンネルCエンベロープ有効無効(0bit目)のみ操作) C356 : C6 0A " " ldab #$0A //AY-3-8910アドレス指定:チャンネルCエンベロープ音量設定レジスタ C358 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C35B : 86 00 " " ldaa #$00 //Aレジスタに#$00を入れる C35D : 97 73 " s" staa X0073 //X0073(AY-3-8910のDA0~DA7に出力するデータ用)に#$00を入れる__(エンベロープ波形は0番目「|\_____」に固定) C35F : C6 0D " " ldab #$0D //AY-3-8910アドレス指定:エンベロープシャープコントロールレジスタ C361 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C364 : 39 "9" rts //サブルーチン終了 ; C365 LC365: //(赤,橙,黄,白ボタン状態分岐 & PCM再生処理):LC2D1より C365 : 36 "6" psha //Aレジスタをスタックへプッシュ(Aレジスタには楽譜ブロック7バイト目のアドレスが入っている?) C366 : 37 "7" pshb //Bレジスタをスタックへプッシュ(BレジスタにはX0080が入っている?) C367 : DF 6D " m" stx X006D //X006D(Xレジスタ一時退避用)にXレジスタを入れる(XレジスタにはX006F(楽曲テンポ)をデクリメントして0が入っている?) C369 : 96 8D " " ldaa X008D //AレジスタにX008D(PCM再生ボタン読み取り用)を入れる C36B : 26 02 "& " bne LC36F //X008D(PCM再生ボタン読み取り用)が0でない時LC36F(赤,橙,黄,白ボタン状態分岐)へ C36D : 20 34 " 4" bra LC3A3 //LC3A3(スタック戻し & サブルーチン終了処理)へ ; C36F LC36F: //ポート6操作系(AY-3-8910のP60=BD1,P61=BDIR)(赤,橙,黄,白ボタン状態分岐):LC365より C36F : 96 17 " " ldaa X0017 //+/AレジスタにX0017(ポート6)を入れる C371 : 84 DF " " anda #$DF //+/A = A & 0xDF C373 : 8A 20 " " oraa #$20 //+/A = A | 0x20 C375 : 97 17 " " staa X0017 //+/X0017(ポート6)にAレジスタを入れる__(ポート6 = (ポート6 & B11011111) | B00100000)(P65(パワトラ)をHにする) C377 : 96 8D " " ldaa X008D //AレジスタにX008D(PCM再生ボタン読み取り用)を入れる C379 : 81 01 " " cmpa #$01 //-/ C37B : 27 0E "' " beq LC38B //-/X008D(PCM再生ボタン読み取り用)が#$01(橙の線のボタンが押された時)のときLC38Bへ C37D : 81 02 " " cmpa #$02 //*/ C37F : 27 0F "' " beq LC390 //*/X008D(PCM再生ボタン読み取り用)が#$02(黄の線のボタンが押された時)のときLC390へ C381 : 81 03 " " cmpa #$03 //+/ C383 : 27 10 "' " beq LC395 //+/X008D(PCM再生ボタン読み取り用)が#$03(白の線のボタンが押された時)のときLC395へ C385 : 81 04 " " cmpa #$04 //-/ C387 : 27 11 "' " beq LC39A //-/X008D(PCM再生ボタン読み取り用)が#$04(赤の線のボタンが押された時)のときLC39Aへ C389 : 20 18 " " bra LC3A3 //X008D(PCM再生ボタン読み取り用)がそれ以外の時、LC3A3(スタック戻し & サブルーチン終了処理)へ ; C38B LC38B: //X008D(PCM再生ボタン読み取り用)が#$01(橙の線のボタンが押された時)のとき:LC36Fより C38B : BD C4 65 " e" jsr LC465 //サブルーチンLC465(PCM_3再生)へ C38E : 20 0D " " bra LC39D //LC39D(P65(パワトラ)をL & スタック戻し& サブルーチン終了処理)へ ; C390 LC390: //X008D(PCM再生ボタン読み取り用)が#$02(黄の線のボタンが押された時)のとき:LC36Fより C390 : BD C4 84 " " jsr LC484 //サブルーチンLC484(PCM_4再生)へ C393 : 20 08 " " bra LC39D //LC39D(P65(パワトラ)をL & スタック戻し& サブルーチン終了処理)へ ; C395 LC395: //X008D(PCM再生ボタン読み取り用)が#$03(白の線のボタンが押された時)のとき:LC36Fより C395 : BD C4 A3 " " jsr LC4A3 //サブルーチンLC4A3(PCM_5再生)へ C398 : 20 03 " " bra LC39D //LC39D(P65(パワトラ)をL & スタック戻し& サブルーチン終了処理)へ ; C39A LC39A: //X008D(PCM再生ボタン読み取り用)が#$04(赤の線のボタンが押された時)のとき:LC36Fより C39A : BD C4 E5 " " jsr LC4E5 //サブルーチンLC4E5(ノイズ音再生?)へ C39D LC39D: //P65(パワトラ)をL処理 C39D : 96 17 " " ldaa X0017 //+/AレジスタにX0017(ポート6)を入れる C39F : 84 DF " " anda #$DF //+/A = A & 0xDF C3A1 : 97 17 " " staa X0017 //+/X0017(ポート6)にAレジスタを入れる__(ポート6 = ポート6 & B11011111)(P65(パワトラ)をLにする) C3A3 LC3A3: //スタック戻し&サブルーチン終了処理:LC365より C3A3 : 7F 00 8D " " clr X008D //X008D(PCM再生ボタン読み取り用)に0を入れる C3A6 : DE 6D " m" ldx X006D //XレジスタにX006D(Xレジスタ一時退避用)を入れる C3A8 : 33 "3" pulb //スタックからプルし、Bレジスタへ戻す(BレジスタにはX0080が入っている?) C3A9 : 32 "2" pula //スタックからプルし、Aレジスタへ戻す(Aレジスタには楽譜ブロック7バイト目のアドレスが入っている?) C3AA : 39 "9" rts //サブルーチン終了(LC2D1へ戻る) ; C3AB LC3AB: //PCM再生(4bitPCM出力):LC3AB(ループ)とLC439等より C3AB : 8D 3E " >" bsr LC3EB //+/LC3EB(PCMの2サンプリングデータ(1バイト)取得 & ウェイト処理(AレジスタにXレジスタの示すアドレスにある値を入れる))へ C3AD : 44 "D" lsra //+/A = A >> 1 C3AE : 44 "D" lsra //+/A = A >> 1 C3AF : 44 "D" lsra //+/A = A >> 1 C3B0 : 44 "D" lsra //+/A = A >> 1 C3B1 : 84 0F " " anda #$0F //+/A = A & 0x0F C3B3 : 97 73 " s" staa X0073 //+/X0073(AY-3-8910のDA0~DA7に出力するデータ)に((X0065 >> 4) & 0x0F)を入れる C3B5 : C6 0E " " ldab #$0E //*/AY-3-8910アドレス指定:AY-3-8910ポートA(4bit簡易DACへ接続) C3B7 : BD C1 BB " " jsr LC1BB //*/LC1BB(AY-3-8910書き込みサブルーチン)へ C3BA : 8D 2F " /" bsr LC3EB //-/LC3EB(PCMの2サンプリングデータ(1バイト)取得 & ウェイト処理(AレジスタにXレジスタの示すアドレスにある値を入れる))へ C3BC : 84 0F " " anda #$0F //-/A = A & 0x0F C3BE : 97 73 " s" staa X0073 //-/X0073(AY-3-8910のDA0~DA7に出力するデータ)に(X0065 & 0x0F)を入れる C3C0 : DE 65 " e" ldx X0065 //+/XレジスタにX0065(PCM再生アドレス)を入れる C3C2 : 08 " " inx //+/Xレジスタデクリメント C3C3 : DF 65 " e" stx X0065 //+/X0065(PCM再生アドレス)にXレジスタを入れる(X0065 = X0065 - 1) C3C5 : C6 0E " " ldab #$0E //*/AY-3-8910アドレス指定:AY-3-8910ポートA(4bit簡易DACへ接続) C3C7 : BD C1 BB " " jsr LC1BB //*/LC1BB(AY-3-8910書き込みサブルーチン)へ C3CA : DE 67 " g" ldx X0067 //-/XレジスタにX0067(PCMデータサイズ)を入れる C3CC : 09 " " dex //-/Xレジスタデクリメント C3CD : DF 67 " g" stx X0067 //-/X0067(PCMデータサイズ)にXレジスタを入れる(X0067 = X0067 - 1) C3CF : 8C 00 00 " " cpx #$0000 //-/X0067(PCMデータサイズ)が C3D2 : 26 D7 "& " bne LC3AB //-/X0067(PCMデータサイズ(PCMデータ読むたびデクリメントする))が0でない時、LC3AB(PCM再生ループ先頭)へ C3D4 : 96 77 " w" ldaa X0077 //+/AレジスタにX0077(再生中のPCM再生番号)を入れる C3D6 : 81 01 " " cmpa #$01 //+/ C3D8 : 27 05 "' " beq LC3DF //+/X0077(再生中のPCM再生番号)が1の時、LC3DF(PCM1再生回数がゼロになるまでループ)へ C3DA : 81 02 " " cmpa #$02 C3DC : 27 07 "' " beq LC3E5 //PCM_2再生回数がゼロまでループ C3DE : 39 "9" rts //サブルーチン終了 ; C3DF LC3DF: //PCM1再生回数がゼロになるまでループ:LC3ABより C3DF : 7A 00 75 "z u" dec X0075 //X0075(PCM1再生回数)デクリメント C3E2 : 26 55 "&U" bne LC439 //X0075(PCM1再生回数)が0でない時、LC439(PCM1再セットアップ & 再生(PCM1以外再生中はここへは到達しない))へ C3E4 : 39 "9" rts //サブルーチン終了 ; C3E5 LC3E5: //PCM_2再生回数がゼロまでループ:LC3ABより C3E5 : 7A 00 76 "z v" dec X0076 //X0076(PCM2再生回数)デクリメント C3E8 : 26 69 "&i" bne LC453 //X0076(PCM2再生回数)が0でない時、LC453(PCM2再セットアップ & 再生)へ C3EA : 39 "9" rts //サブルーチン終了 ; C3EB LC3EB: //PCMの2サンプリングデータ(1バイト)取得 & ウェイト処理:LC3ABより C3EB : 8D 05 " " bsr LC3F2 //PCM再生ウェイト処理 C3ED : DE 65 " e" ldx X0065 //XレジスタにX0065(PCM再生アドレス)を入れる C3EF : A6 00 " " ldaa $00,x //AレジスタにXレジスタの示すアドレスにある値を入れる C3F1 : 39 "9" rts //サブルーチン終了 ; C3F2 LC3F2: //PCM再生ウェイト処理:LC3EBより C3F2 : 36 "6" psha //Aレジスタをスタックへプッシュ C3F3 : 86 29 " )" ldaa #$29 //-/PCM再生速度 C3F5 LC3F5: //LC3F5(0x29回ループ用):LC3F5より C3F5 : 4A "J" deca //Aレジスタデクリメント C3F6 : 26 FD "& " bne LC3F5 //-/0x29回ループ C3F8 : 96 77 " w" ldaa X0077 //*/AレジスタにX0077(PCM再生番号)を入れる C3FA : 81 02 " " cmpa #$02 //*/ C3FC : 27 04 "' " beq LC402 //*/X0077(PCM再生番号)が0x02のときLC402へ((「定位置で止まる」スイッチ押されたフラグ?)チェック無視する) C3FE : 96 84 " " ldaa X0084 //-/AレジスタにX0084(「定位置で止まる」スイッチ押されたフラグ?)を入れる C400 : 26 02 "& " bne LC404 //-/X0084(「定位置で止まる」スイッチ押されたフラグ?)が0でないときはLC404(課金分終了処理)へ C402 LC402: C402 : 32 "2" pula //スタックからプルしAレジスタへ C403 : 39 "9" rts //サブルーチン終了(LC3EBへ戻る) C404 LC404: //LC3F5より C404 : 7E C0 57 "~ W" jmp LC057 //課金分終了処理 ; C407 LC407: //一曲目演奏演奏開始処理(課金後):LC03Cより C407 : C6 3D " =" ldab #$3D //+/Bレジスタに#$3Dを入れる C409 : D7 7C " |" stab X007C //+/X007C(課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?))に#$3Dを入れる C40B : D7 7A " z" stab X007A //+/X007A(課金動作タイマーカウンタ用)に#$3Dを入れる C40D LC40D: //一曲目演奏演奏開始処理:LC2F6より C40D : CE 01 40 " @" ldx #$0140 //テンポ(#$0140) C410 : DF 6F " o" stx X006F //#$0140をX006Fに入れる C412 : 86 01 " " ldaa #$01 //-/ C414 : 97 78 " x" staa X0078 //-/X0078(選曲)を#$01にする C416 : CE C6 00 " " ldx #$C600 //一曲目楽譜データ先頭アドレス(#$C600) C419 : 7E C1 DF "~ " jmp LC1DF //LC1DF(演奏開始先頭楽譜データ1ブロック読み取り&演奏)へ ; C41C LC41C: //二曲目演奏演奏開始処理(課金後):LC03Cより C41C : C6 3D " =" ldab #$3D //+/Bレジスタに#$3Dを入れる C41E : D7 7C " |" stab X007C //+/X007C(課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?))に#$3Dを入れる C420 : D7 7A " z" stab X007A //+/X007A(課金動作タイマーカウンタ用)に#$3Dを入れる C422 LC422: //二曲目演奏演奏開始処理:LC2F9より C422 : CE 01 30 " 0" ldx #$0130 //テンポ(#$0130) C425 : DF 6F " o" stx X006F //-/ C427 : 86 02 " " ldaa #$02 //-/X0078(選曲)を#$02にする C429 : 97 78 " x" staa X0078 //X0078(選曲)を#$01にする C42B : CE CC 00 " " ldx #$CC00 //二曲目楽譜データ先頭アドレス(#$CC00) C42E : 7E C1 DF "~ " jmp LC1DF //LC1DF(演奏開始先頭楽譜データ1ブロック読み取り&演奏)へ ; //到達しないコード C431 : 86 02 " " ldaa #$02 //*/Aレジスタに#$02を入れる//到達しないコード C433 : 97 75 " u" staa X0075 //*/X0075(PCM_1再生回数)に#$02を入れる//到達しないコード C435 : 86 01 " " ldaa #$01 //-/Aレジスタに#$01を入れる//到達しないコード C437 : 97 77 " w" staa X0077 //-/X0077(PCM再生番号)に#$01を入れる //到達しないコード C439 LC439: //PCM1セットアップ & 再生:LC3DF等より C439 : CE D2 00 " " ldx #$D200 //*/Xレジスタに#$D200を入れる C43C : DF 65 " e" stx X0065 //*/X0065(PCM再生アドレス)に#$D200を入れる(楽譜データと重複しているため使用不可) C43E : CE 07 FF " " ldx #$07FF //+/Xレジスタに#$07FFを入れる C441 : DF 67 " g" stx X0067 //+/X0067(PCMデータサイズ)に#$07FFを入れる C443 : C6 AF " " ldab #$AF //-/Bレジスタに#$AFを入れる C445 : BD C1 B1 " " jsr LC1B1 //-/LC1B1(ループウェイトBレジスタで設定)へ C448 : 7E C3 AB "~ " jmp LC3AB //LC3AB(PCM再生)へジャンプ ; C44B LC44B: //PCM2セットアップ & 再生(駆動終了音声)緑線 C44B : 86 02 " " ldaa #$02 //*/Aレジスタに#$02を入れる C44D : 97 76 " v" staa X0076 //*/X0076(PCM_2再生回数)に#$02を入れる C44F : 86 02 " " ldaa #$02 //-/Aレジスタに#$02を入れる C451 : 97 77 " w" staa X0077 //-/X0077(PCM再生番号)に#$02を入れる C453 LC453: //PCM2再セットアップ & 再生:LC3E5等より C453 : CE DA 00 " " ldx #$DA00 //*/Xレジスタに#$DA00を入れる C456 : DF 65 " e" stx X0065 //*/X0065(PCM再生アドレス)に#$DA00を入れる C458 : CE 07 FF " " ldx #$07FF //+/Xレジスタに#$07FFを入れる C45B : DF 67 " g" stx X0067 //+/X0067(PCMデータサイズ)に#$07FFを入れる C45D : C6 AF " " ldab #$AF //-/Bレジスタに#$AFを入れる C45F : BD C1 B1 " " jsr LC1B1 //-/LC1B1(ループウェイトBレジスタで設定)へ C462 : 7E C3 AB "~ " jmp LC3AB //LC3AB(PCM再生)へジャンプ ; C465 LC465: //PCM_3再生設定&再生(橙の線のボタンが押された時)橙線:LC38Bより C465 : 86 01 " " ldaa #$01 //*/Aレジスタに#$01を入れる C467 : 97 75 " u" staa X0075 //*/X0075(PCM_1再生回数)に#$01を入れる(PCM1以外は無意味) C469 : 86 03 " " ldaa #$03 //-/Aレジスタに#$03を入れる C46B : 97 77 " w" staa X0077 //-/X0077(PCM再生番号)に#$03を入れる C46D : CE E2 00 " " ldx #$E200 //+/Xレジスタに#$E200を入れる C470 : DF 65 " e" stx X0065 //+/X0065(PCM再生アドレス)に#$E200を入れる C472 : CE 07 FF " " ldx #$07FF //*/Xレジスタに#$07FFを入れる C475 : DF 67 " g" stx X0067 //*/X0067(PCMデータサイズ)に#$07FFを入れる C477 : BD C0 A4 " " jsr LC0A4 //AY-3-8910ミキサー,I/O設定 C47A : BD C3 AB " " jsr LC3AB //LC3AB(PCM再生)へ C47D : 7F 00 77 " w" clr X0077 //X0077(PCM再生番号)クリア C480 : BD C5 5B " [" jsr LC55B //LC55B(PCM_3再生終了処理)へ C483 : 39 "9" rts //サブルーチン終了(LC38Bへ戻る) ; C484 LC484: //PCM_4再生設定&再生(黄の線のボタンが押された時)黄線:LC390より C484 : 86 01 " " ldaa #$01 //*/Aレジスタに#$01を入れる C486 : 97 75 " u" staa X0075 //*/X0075(PCM_1再生回数)に#$01を入れる(PCM1以外は無意味) C488 : 86 04 " " ldaa #$04 //-/Aレジスタに#$04を入れる C48A : 97 77 " w" staa X0077 //-/X0077(PCM再生番号)に#$04を入れる C48C : CE EA 00 " " ldx #$EA00 //+/Xレジスタに#$EA00を入れる C48F : DF 65 " e" stx X0065 //+/X0065(PCM再生アドレス)に#$EA00を入れる C491 : CE 07 FF " " ldx #$07FF //*/Xレジスタに#$07FFを入れる C494 : DF 67 " g" stx X0067 //*/X0067(PCMデータサイズ)に#$07FFを入れる C496 : BD C0 A4 " " jsr LC0A4 //AY-3-8910ミキサー,I/O設定 C499 : BD C3 AB " " jsr LC3AB //LC3AB(PCM再生)へ C49C : 7F 00 77 " w" clr X0077 //X0077(PCM再生番号)クリア C49F : BD C5 55 " U" jsr LC555 //LC555(PCM_4,5再生終了処理)へ C4A2 : 39 "9" rts //サブルーチン終了(LC390へ戻る) ; C4A3 LC4A3: //PCM_5再生設定&再生(白の線のボタンが押された時)白線:LC395より C4A3 : 86 01 " " ldaa #$01 //*/Aレジスタに#$01を入れる C4A5 : 97 75 " u" staa X0075 //*/X0075(PCM_1再生回数)に#$01を入れる(PCM1以外は無意味) C4A7 : 86 05 " " ldaa #$05 //-/Aレジスタに#$05を入れる C4A9 : 97 77 " w" staa X0077 //-/X0077(PCM再生番号)に#$05を入れる C4AB : CE F2 00 " " ldx #$F200 //+/Xレジスタに#$F200を入れる C4AE : DF 65 " e" stx X0065 //+/X0065(PCM再生アドレス)に#$F200を入れる C4B0 : CE 07 FF " " ldx #$07FF //*/Xレジスタに#$07FFを入れる C4B3 : DF 67 " g" stx X0067 //*/X0067(PCMデータサイズ)に#$07FFを入れる C4B5 : BD C0 A4 " " jsr LC0A4 //AY-3-8910ミキサー,I/O設定 C4B8 : BD C3 AB " " jsr LC3AB //LC3AB(PCM再生)へ C4BB : 7F 00 77 " w" clr X0077 //X0077(PCM再生番号)クリア C4BE : BD C5 55 " U" jsr LC555 //LC555(PCM_4,5再生終了処理)へ C4C1 : 39 "9" rts //サブルーチン終了(LC395へ戻る) ; C4C2 LC4C2: //~IRQ2ピン割り込み(緑線)(LC003より) C4C2 : 96 80 " " ldaa X0080 C4C4 : 27 0C "' " beq LC4D2 //X0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)が0(「タイマー1」)の時LC4D2へ C4C6 : 7A 00 81 "z " dec X0081 //X0081(「タイマー2 周回数」設定用(テストコイン投入モードの際保存))デクリメント C4C9 : 27 14 "' " beq LC4DF //X0081(「タイマー2 周回数」設定用(テストコイン投入モードの際保存))が0の時LC4DFへ C4CB : C6 40 " @" ldab #$40 //Bレジスタに#$0x40を入れる(ウェイト時間設定) C4CD : BD C1 B1 " " jsr LC1B1 //ループウェイトサブルーチン(Bレジスタで設定) C4D0 : 0E " " cli //割り込みフラグクリア C4D1 : 3B ";" rti //割り込み終了 ; C4D2 LC4D2: //X0080(「ディップスイッチの使用法B」タイマー2 周回数設定用)が0(「タイマー1」)の時(LC4C2より) C4D2 : D6 7B " {" ldab X007B //*/BレジスタにX007B(「ディップスイッチの使用法B」「タイマー1」設定用)を入れる C4D4 : 27 09 "' " beq LC4DF //*/ C4D6 : C1 01 " " cmpb #$01 //*/ C4D8 : 27 05 "' " beq LC4DF //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が0または1のときLC4DFへ C4DA : 7F 00 84 " " clr X0084 //X0084(「定位置で止まる」スイッチ押されたフラグ?)をクリア C4DD : 0E " " cli //割り込みフラグクリア C4DE : 3B ";" rti //割り込み終了 ; C4DF LC4DF: //定位置検出?(LC4C2,LC4D2より) C4DF : 86 01 " " ldaa #$01 //Aレジスタに#$0x01を入れる C4E1 : 97 84 " " staa X0084 //X0084(「定位置で止まる」スイッチ押されたフラグ?)に#$0x01を入れる C4E3 : 0F " " sei //割り込み禁止 C4E4 : 3B ";" rti //割り込み終了 ; C4E5 LC4E5: //ノイズ音&再生(赤の線のボタンが押された時):LC39Aより//赤線_ノイズ音関連 C4E5 : 86 01 " " ldaa #$01 //Aレジスタに#$0x01を入れる C4E7 : 97 85 " " staa X0085 //X0085(LC4E5で使用(#$01ストアのみで無意味、デバッグ用?))に#$0x01を入れる C4E9 : CE 05 00 " " ldx #$0500 //Xレジスタに#$0500を入れる C4EC : DF 71 " q" stx X0071 //LC53E内ウェイト回数(#$0500)ノイズ音発音時間? C4EE : CE D1 E0 " " ldx #$D1E0 //+/Xレジスタに#$D1E0を入れる C4F1 : A6 00 " " ldaa $00,x //+/Aレジスタにアドレス#$D1E0にある値を入れる C4F3 : 97 74 " t" staa X0074 //+/X0074にアドレス#$D1E0にある値を入れる C4F5 LC4F5: //LC4F5無限ループ C4F5 : 8D 27 " '" bsr LC51E //AY-3-8910のすべてのレジスタへ,アドレス(変数X0074で指定)から順に値を書き込む:LC4F5より C4F7 : 8D 45 " E" bsr LC53E //X0071回ウェイト&ボタン処理?サブルーチン C4F9 : 96 74 " t" ldaa X0074 //*/AレジスタにX0074を入れる C4FB : 4A "J" deca //*/Aレジスタデクリメント C4FC : 81 22 " "" cmpa #$22 //-/ C4FE : 27 09 "' " beq LC509 //-/Aレジスタが#$22と等しい時LC509へ C500 : 4A "J" deca //*/Aレジスタデクリメント C501 : 81 22 " "" cmpa #$22 //+/ C503 : 27 04 "' " beq LC509 //+/Aレジスタが#$22と等しい時LC509へ C505 : 97 74 " t" staa X0074 //X0074(赤線特殊PCM再生用?(チャンネルa_Ltone指定用))に(X0074 - 1)を入れる C507 : 20 EC " " bra LC4F5 //LC4F5へ無限ループ(Aレジスタが#$22と等しい時LC509へ抜ける) ; C509 LC509: //LC4F5より C509 : 8D 13 " " bsr LC51E //AY-3-8910のすべてのレジスタへ,アドレス(変数X0074で指定)から順に値を書き込む:LC4F5より C50B : 8D 31 " 1" bsr LC53E //X0071回ウェイト&ボタン処理?サブルーチン C50D : 8D 2F " /" bsr LC53E //X0071回ウェイト&ボタン処理?サブルーチン C50F LC50F: //LC50F無限ループ C50F : 96 74 " t" ldaa X0074 //AレジスタにX0074を入れる C511 : 4C "L" inca //Aレジスタインクリメント C512 : 81 8F " " cmpa #$8F //*/ C514 : 27 3F "'?" beq LC555 //*/Aレジスタが#$8Fと等しい時LC555へ C516 : 97 74 " t" staa X0074 //X0074(赤線特殊PCM再生用?(チャンネルa_Ltone指定用))にAレジスタを入れる C518 : 8D 04 " " bsr LC51E //AY-3-8910のすべてのレジスタへ,アドレス(変数X0074で指定)から順に値を書き込む:LC4F5より C51A : 8D 22 " "" bsr LC53E //X0071回ウェイト&ボタン処理?サブルーチン C51C : 20 F1 " " bra LC50F //LC50Fへ無限ループ(Aレジスタが#$8Fと等しい時LC555へ抜ける) ; C51E LC51E: //AY-3-8910のすべてのレジスタへ,アドレス(変数X0074で指定)から順に値を書き込む:LC4F5より C51E : 86 0D " " ldaa #$0D //*/Aレジスタに#$0Dを入れる C520 : 97 64 " d" staa X0064 //*/X0064(LC51E,LC530ループカウント用)に#$0Dを入れる C522 : C6 00 " " ldab #$00 //#$00(AY-3-8910チャンネルA_tone_Lbit)をBレジスタ(AY-3-8910のアドレス指定)へ C524 : 96 74 " t" ldaa X0074 //+/ C526 : 97 73 " s" staa X0073 //+/X0073(AY-3-8910のDA0~DA7に出力するデータ)にX0074(赤線特殊PCM再生用?(チャンネルa_Ltone指定用))を入れる C528 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C52B : CE D1 E1 " " ldx #$D1E1 //Xレジスタに#$D1E1(PCM_6(赤線)再生アドレス)を入れる C52E : C6 01 " " ldab #$01 //Bレジスタ(AY-3-8910のアドレス指定)に#$01(AY-3-8910チャンネルA_tone_Hbit)を入れる C530 LC530: //LC530ループ C530 : BD C1 DA " " jsr LC1DA //xレジスタ値のアドレスにある値をX0073(AY-3-8910のDA0~DA7に出力するデータ)に入れるサブルーチン C533 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C536 : 08 " " inx //Xレジスタインクリメント C537 : 5C "\" incb //Bレジスタインクリメント C538 : 7A 00 64 "z d" dec X0064 //X0064デクリメント C53B : 26 F3 "& " bne LC530 //X0064が0になるまでループ(#$0D回ループ) C53D : 39 "9" rts //サブルーチン終了 ; C53E LC53E: //LC4E5より C53E : DF 6B " k" stx X006B //X006B(Xレジスタ一時退避用)にXレジスタを入れる C540 : DE 71 " q" ldx X0071 //XレジスタにX0071(LC53E内ウェイト回数(ノイズ音発音時間))を入れる C542 : 96 84 " " ldaa X0084 //AレジスタにX0084(ボタン押されたフラグ?)を入れる C544 : 26 06 "& " bne LC54C //X0084ボタン押されたフラグ?が0でないときはLC54Cへ C546 LC546: //-/Xレジスタが0になるまで繰り返し(X0071回ウェイト) C546 : 09 " " dex // C547 : 26 FD "& " bne LC546 //-/ C549 : DE 6B " k" ldx X006B //XレジスタにX006B_Xレジスタ一時退避用を入れる C54B : 39 "9" rts //サブルーチン終了 C54C LC54C: //LC53Eより C54C : 7E C0 57 "~ W" jmp LC057 //課金分終了処理へ ; //到達しないコード C54F : 0C " " clc //キャリーフラグクリア//到達しないコード C550 : 7A 00 7B "z {" dec X007B //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)デクリメント//到達しないコード C553 : 25 53 "%S" bcs LC5A8 //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が(0→-1)の時、LC5A8(課金分終了処理)へ//到達しないコード C555 LC555: //PCM_4,5再生終了処理:LC484,LC4A3より C555 : 0C " " clc //キャリーフラグクリア C556 : 7A 00 7B "z {" dec X007B //-/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)デクリメント C559 : 25 4D "%M" bcs LC5A8 //-/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が(0→-1)の時、LC5A8(課金分終了処理)へ C55B LC55B: //PCM_3再生終了処理:LC465より C55B : 0C " " clc //キャリーフラグクリア C55C : 7A 00 7B "z {" dec X007B //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)デクリメント C55F : 25 47 "%G" bcs LC5A8 //*/X007B(「ディップスイッチの使用法B」「タイマー1」設定用)が(0→-1)の時、LC5A8(課金分終了処理)へ C561 : C6 FF " " ldab #$FF //-/ウェイト時間設定 C563 : BD C1 B1 " " jsr LC1B1 //-/ループウェイトサブルーチン_0xFF*0xFF C566 : 96 78 " x" ldaa X0078 //+/AレジスタにX0078(選曲番号)を入れる C568 : 81 03 " " cmpa #$03 //+/ C56A : 27 04 "' " beq LC570 //+/X0078(選曲番号)が3の時、LC570へ(選曲スイッチの状態から楽譜演奏データ先頭アドレス選択)(選曲番号が3の場合は起こらないためデバッグモード?) C56C : 81 04 " " cmpa #$04 //+/ C56E : 27 05 "' " beq LC575 //+/X0078(選曲番号)が4の時、LC575へ(選曲スイッチの状態から楽譜演奏データ先頭アドレス選択)(選曲番号が4の場合は起こらないためデバッグモード?) C570 LC570: //(X0078(選曲番号)が3の時)または、4以外の時:LC55Bより C570 : CE C6 03 " " ldx #$C603 //Xレジスタに#$C603(1曲目の先頭アドレス+3)を入れる C573 : 20 03 " " bra LC578 //LC578へ ; C575 LC575: //(X0078(選曲番号)が4の時):LC55Bより C575 : CE CC 03 " " ldx #$CC03 //Xレジスタに#$CC03(2曲目の先頭アドレス+3)を入れる C578 LC578: //LC570より C578 : 86 00 " " ldaa #$00 //+/Aレジスタに#$00を入れる(チャンネルA、B、C音量ゼロにする処理をする) C57A : 97 73 " s" staa X0073 //+/X0073(AY-3-8910のDA0~DA7に出力するデータ)に#$00を入れる C57C : C6 08 " " ldab #$08 //AY-3-8910アドレス指定:チャンネルA音量コントロールレジスタ__(チャンネルAエンベロープ無効(4bit目),音量0(0~3bit目)) C57E : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C581 : C6 09 " " ldab #$09 //AY-3-8910アドレス指定:チャンネルB音量コントロールレジスタ__(チャンネルBエンベロープ無効(4bit目),音量0(0~3bit目)) C583 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C586 : C6 0A " " ldab #$0A //AY-3-8910アドレス指定:チャンネルC音量コントロールレジスタ__(チャンネルCエンベロープ無効(4bit目),音量0(0~3bit目)) C588 : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C58B : C6 01 " " ldab #$01 //AY-3-8910アドレス指定:チャンネルAの音程上位4ビット(演奏開始楽譜データ3バイト目) C58D : 8D 1D " " bsr LC5AC //LC5AC(xレジスタにセットされた現在の読み取りポイントアドレスにある値をAY-3-8910に書き込み、xレジスタインクリメント)へ C58F : C6 06 " " ldab #$06 //AY-3-8910アドレス指定:ノイズ分周(演奏開始楽譜データ4バイト目) C591 : 8D 19 " " bsr LC5AC //LC5AC(xレジスタにセットされた現在の読み取りポイントアドレスにある値をAY-3-8910に書き込み、xレジスタインクリメント)へ C593 : C6 0B " " ldab #$0B //AY-3-8910アドレス指定:エンベロープ周期(演奏開始楽譜データ5バイト目) C595 : 8D 15 " " bsr LC5AC //LC5AC(xレジスタにセットされた現在の読み取りポイントアドレスにある値をAY-3-8910に書き込み、xレジスタインクリメント)へ C597 : C6 0C " " ldab #$0C //AY-3-8910アドレス指定:エンベロープ周期(演奏開始楽譜データ6バイト目) C599 : 8D 11 " " bsr LC5AC //LC5AC(xレジスタにセットされた現在の読み取りポイントアドレスにある値をAY-3-8910に書き込み、xレジスタインクリメント)へ C59B : C6 0D " " ldab #$0D //AY-3-8910アドレス指定:エンベロープ波形(演奏開始楽譜データ7バイト目) C59D : 8D 0D " " bsr LC5AC //LC5AC(xレジスタにセットされた現在の読み取りポイントアドレスにある値をAY-3-8910に書き込み、xレジスタインクリメント)へ C59F : 96 86 " " ldaa X0086 //*/AレジスタにX0086(無意味、デバッグ用?)を入れる C5A1 : 26 01 "& " bne LC5A4 //*/X0086が0でない時、LC5A4(X0086をゼロにする)へ C5A3 : 39 "9" rts //サブルーチン終了 ; C5A4 LC5A4: //X0086(無意味、デバッグ用?)をゼロにする:LC578より C5A4 : 7F 00 86 " " clr X0086 //X0086(無意味、デバッグ用?)クリア C5A7 : 39 "9" rts //サブルーチン終了(LC578へ戻る) ; C5A8 LC5A8: //課金分終了処理 C5A8 : 0F " " sei //割り込み禁止 C5A9 : 7E C0 57 "~ W" jmp LC057 //LC057(課金分終了処理)へ ; C5AC LC5AC: //xレジスタにセットされた現在の読み取りポイントアドレスにある値をAY-3-8910に書き込み、xレジスタインクリメント C5AC : BD C1 DA " " jsr LC1DA //xレジスタにセットされた現在の読み取りポイントアドレスにある値をX0073に入れる C5AF : BD C1 BB " " jsr LC1BB //LC1BB(AY-3-8910書き込みサブルーチン)へ C5B2 : 08 " " inx //楽譜データ次の読み取りポイントアドレス指定 C5B3 : 39 "9" rts //サブルーチン終了 ; //到達しないコード C5B4 : BD C1 E2 " " jsr LC1E2 C5B7 : BD C1 C3 " " jsr LC1C3 C5BA : 08 " " inx C5BB : 39 "9" rts ; C5BC : FF FF FF " " stx XFFFF C5BF : FF 26 01 " & " stx X2601 C5C2 : 39 "9" rts ; C5C3 : 7F 00 86 " " clr X0086 C5C6 : 39 "9" rts ; C5C7 : 0F " " sei C5C8 : 7E 80 5F "~ _" jmp L805F ; C5CB : BD 81 E2 " " jsr L81E2 C5CE : BD 81 C3 " " jsr L81C3 C5D1 : 08 " " inx C5D2 : 39 "9" rts ;
//以降演奏データとPCMデータ




//アドレス空間と変数の予想//////////////////////////////////
//X0000~X001Fは特定の用途のレジスタ
//X0020~X0040は外部領域
//X0040~X00FFは内蔵ram
//X0100~XFFFFは外部領域
X0000(ポート1データ方向レジスタ)※HD6301V1のみでHD63A03XPには無し
X0001(ポート2データ方向レジスタ)
X0002(ポート1)※HD6301V1のみでHD63A03XPには無し
X0003(ポート2)
X0004(ポート3データ方向レジスタ)※HD6301V1のみでHD63A03XPには無し
X0005(ポート4データ方向レジスタ)※HD6301V1のみでHD63A03XPには無し
X0006(ポート3)※HD6301V1のみでHD63A03XPには無し
X0007(ポート4)※HD6301V1のみでHD63A03XPには無し
X0008(タイマーコントロール/ステータスレジスタ1)
X000F(タイマーコントロール/ステータスレジスタ2)
X0010(レート、モードコントロールレジスタ)
X0011(tx、rxコントロールステータスレジスタ)
X0014(RAM/ポート5コントロールレジスタ)(STBY_PWR,RAME,-,-,HLTE,MRE,IRQ2_E,IRQ1_E)
X0015(ポート5)
X0016(ポート6データ方向レジスタ)
X0017(ポート6)
X001B(タイマーコントロール/ステータスレジスタ3)

X0064:LC51E,LC530ループカウント用
X0065:PCM再生アドレス
X0067:PCMデータサイズ
X0069:LC26E内Xレジスタ一時退避用(現在の楽譜再生位置記録(楽譜データブロック7バイト目))
X006B:LC53E内Xレジスタ一時退避用(現在の楽譜再生位置記録?)
X006D:LC365内Xレジスタ一時退避用(不明)
X006F:楽曲テンポ
X0071:LC53E内ウェイト回数(ノイズ音発音時間)
X0073:AY-3-8910のDA0~DA7に出力するデータ
X0074:赤線特殊PCM再生用?(チャンネルa_Ltone指定用)
X0075:PCM1再生回数
X0076:PCM2再生回数
X0077:PCM再生番号
X0078:選曲番号
X0079:コイン投入モード(0:通常,1:コイン投入モード)
X007A:課金動作タイマーカウンタ用
X007B:「ディップスイッチの使用法B」「タイマー1」設定用(30,60,90,120が入る)
X007C:課金後初期値#$3Dが入る(課金動作タイマー初期値保存用?)
X007E:テストコイン投入ボタン(茶線)のコイン入回数
X007F:「ディップスイッチの使用法B」「コイン枚数」設定用(1~4が入る)
X0080:「ディップスイッチの使用法B」「タイマー2 周回数」設定用(0~7が入る)
X0081:「ディップスイッチの使用法B」「タイマー2 周回数」設定用(0~7が入る)(テストコイン投入モードの際保存)
X0082:パワトラ点滅保存用
X0084:「定位置で止まる」スイッチ押されたフラグ?(1で定位置終了)
X0085:LC4E5で使用(#$01ストアのみで無意味、デバッグ用?)
X0086:LC578で使用(無意味、デバッグ用?)
X0089:AY-3-8910のポートB(ディップスイッチ)の状態保存用
X008A:筐体側面の赤色プッシュスイッチ押された時間カウント用(LC02Cでのみ使用)
X008E:LC279内で使用(無意味な用法)
X008D:PCM再生ボタン読み取り用
//////////////////////////////////



・演奏データ
プログラムの解析があらかた済んだので次に演奏データの解析を行います。
こちらもプログラムを読んでいけばわかるので、結果のみまとめます。
筐体にJASRACのシールが貼られてので、ROM内の演奏データの記載は行いません。
代わりに差し替えた演奏データを例としてページの最後の方に載せておきます。


このプログラムでは2種類の曲をスイッチで選択して演奏することができます。

1曲目:$0417と$0570に読み込み先頭アドレス+0xC600を記載
テンポ:$040Eで設定(2バイト)
2曲目:$042Cと$0575に読み込み先頭アドレス+0xCC00を記載
テンポ:$0423で設定(2バイト)

演奏データは独自のフォーマットとなっています。
基本的に、
ヘッダ+ブロック+ブロック+…
という感じでAY-3-8910のレジスタを意識した構成となっています。

ヘッダやブロックは、8バイトで一組となっているようです。

------ヘッダ------
0:なし
1:なし
2:なし
3:チャンネルA音程上位4bit
4:ノイズ分周
5:エンベロープL Byte
6:エンベロープH Byte
7:エンベロープ波形(変更しても反映なし)
------ ------

------ブロック------
0:音程A ※
1:音程B L Byte
2:音程B H Byte
3:音程C L Byte
4:音程C H Byte
5:設定1
6:設定2
7:長さ

//※Byte0
0xFFのときループ
0x0Fのときリセット
それ以外は音程A L Byte

//Byte5_設定1
bit:7_未使用
bit:6_未使用
bit:5_未使用
bit:4_チャンネルAエンベロープ有効無効
bit:3_ノイズA 1でoff,0でon
bit:2_チャンネルCミキサ 1でoff,0でon
bit:1_チャンネルBミキサ 1でoff,0でon
bit:0_チャンネルAミキサ 1でoff,0でon

//Byte6_設定2
bit:4_チャンネルAエンベロープ有効無効
bit:0_チャンネルAエンベロープ有効無効

//Byte7
音長
値が大きいほど、長く発音

------ ------

音程の計算はAY-3-8910の音程設定方法と同じです。ただし、チャンネルAのみ音程上位4bitはヘッダ部分でセットし、以降変更できません。

基本的にPSGのチャンネルAの音域は狭く、BとCをメロディーに使う感じでしょうか?
ノートオンやノートオフは、ブロックデータのByte5で行います。

演奏データの終端ではブロックデータのByte0を0xFFまたは0x0Fにします。
0xFFの時にはループ、0x0Fの時にはリセットします。

1つのチャンネルのキーオン・キーオフするだけでも8バイト使ってしまうので、できるだけ複数のチャンネルを同時キーオン・キーオフするように工夫しないと、ROM内に収まりきらなくなりそうです。




試しに、ROMの演奏データを書き換えて演奏した例を示します。


 



変換ツール等は作成していないので、演奏データの差し替えは地道に打ち込みました。



・4bit PCMデータ
さいごにPCMデータの解析をしてみます。
と言っても、仕組み的に4bit+4bitのモノラルPCMデータが連なっているだけなので、何も難しくありません。

・データ構造
[4bit+4bit],[4bit+4bit],…

再生時は、PSGによる演奏を一時停止し、4bitずつROMにあるPCMデータを読み取り、AY-3-8910の汎用ポートIOA0~IOA3に出力していきます。


//コネクタ配線とPCMデータアドレス//////////////////////////
コネクタ緑線
「ばいばいまたね」x2
$C454で先頭アドレスの位置を設定
PCMデータ先頭アドレス:$DA00
$C459でサイズ(バイト)を設定
PCMデータサイズ:$07FF

コネクタ青
リセット

コネクタ茶線
無し

コネクタ白線
「いっぱいあそんでね」
$C4ACで先頭アドレスの位置を設定
PCMデータ先頭アドレス:$F200
$C4B1でサイズ(バイト)を設定
PCMデータサイズ:$07FF

コネクタ橙線
「こんにちは」
$C46Eで先頭アドレスの位置を設定
PCMデータ先頭アドレス:$E200
$C473でサイズ(バイト)を設定
PCMデータサイズ:$07FF

コネクタ黄線
「今日はどうですかな」
$C48Dで先頭アドレスの位置を設定
PCMデータ先頭アドレス:$EA00
$C492でサイズ(バイト)を設定
PCMデータサイズ:$07FF

コネクタ赤線
ノイズ音  ※演奏データと被るため
$C439で先頭アドレスの位置を設定
PCMデータ先頭アドレス:$D200
$C43Fでサイズ(バイト)を設定
PCMデータサイズ:$07FF
////////////////////////////

PCMデータの差し替えもそれほど難しくなさそうです。注意点としては量子化幅が一定ではないため、通常のPCMデータでは、DAコンバートした際のバイナリ-アナログの直線性を失います。
本来ならサンプリング時に標本値の加工が必要になるのですが、4bitPCMの時点で音質が悪いため、標本値の加工無しでもたいして変わらなさそうです。



4bitPCMデータの作成はGB用PCm変換ツールが使えそうです。

PCM Driver for Gameboy - Bookworm's Library

サンプリングレートを高く設定するほど、実機上での再生速度が落ちます。



・ROMデータ

さいごに、研究目的での使用を想定してROMデータ(演奏データと一部のPCMデータ書き換え済み)を載せておきます。

演奏データは「よいまちカンターレ」のサビ部分に置換してあります。
一部のPCMデータは「時は来た」と「時、来てるぞ」に置換してあります。


「・回路」の項の回路図の通り組み立てれば動くはずです。


ROMデータは16kBのROM(27128、27C128など)にそのまま書き込むことができます。
16kB以外のROM(27C256、27C512など)に書き込む場合は、データをROM内の最後の方(27C256の場合はROM内アドレス$4000~$7FFF、27C512の場合はROM内アドレス$C000~$FFFF)に配置します。


演奏データ書き換え例の動画では、256kbitのSRAMに電気二重層コンデンサを付けたものを使用しています。
















おわり