「ダブルプロファイター」は1台でスーパーファミコンやメガドライブの2機種に対応できる、ユニークなコンセプトを持ったバックアップマシン(ディスクド ライブ)です。特に日本では「MGH」「スーパーマジックドライブ」「ASIC POWER」などがあまり出まわらなかったため、メガドラ用のバックアップマシンではもっとも多い機種と思われます。
ただ、この「ダブルプロファイター(以下ダブルプロ)」には、メガドラ側で使用した場合、いくつか不具合があります。今回はそれを多少とも解消するため、制御プログラムを解析してバグを取ってみました。
この解析および改造は、私の所有するダブルプロファイターXで行ったものです。ロットによってはROMバージョンが異なる可能性があります。
なおこの改造により、メーカ及び輸入元の保証が受けられなくなりますので改造は自分の責任において行ってください。
1.ダブルプロの底面、手前側に付いているネジ2本をはずします。
2.電源横の封印シール下のネジをはずします。
3.これで上面のフタが外れます。プログラムROMは「U2」とシルク印刷された部分の512Kbit EP-ROMです。これをソケットから取り外します。
4.ROMリーダで読みだし、後述のパッチを当てます。
5.新しいEP-ROMにパッチ後のプログラムを焼きこみます。
6.焼きこみ後のROMをソケットに差し込み、逆の手順で組み立てて完成です。
以下にダブルプロファイターで使われているROM(27C512,64KByte)のマップを示します。
開始アドレス | 内容 | サイズ |
0000 | メガドライブ側制御プログラムA | 16KByte |
4000 | メガドライブ側制御プログラムB | 16KByte |
8000 | スーパーファミコン側制御プログラム | 32KByte |
上の表で、メガドラ側プログラムA、Bは同じものです。これは実行時のメガドラ側メモリマップに理由があります。
ダブルプロ動作時、メガドライブのメインCPUである68000はHALTされ、サブCPUのZ80で全ての処理を行っています。以下にダブルプロ動作時のZ80側メモリマップを示します。
開始アドレス | 内容 | サイズ |
0000 | メガドライブ側制御プログラムA | 16KByte |
4000 | メガドライブ側制御プログラムB1 | 8KByte |
4000 | ROMウインドウ1(↑とバンク切り替え) | 8KByte |
4000 | SRAMウインドウ(↑とバンク切り替え) | 8KByte |
6000 | メガドライブ側制御プログラムB2 | 8KByte |
6000 | ROMウインドウ2(↑とバンク切り替え) | 8KByte |
8000 | RAMウインドウ1(256バンク切り替え) | 8KByte |
A000 | RAMウインドウ2(256バンク切り替え) | 8KByte |
C000 | ワークRAM | 8KByte |
E000 | 未使用エリア | 8KByte |
さらにこの上に、次のI/Oがメモリマップドでマップされます。
開始アドレス | 内容 | サイズ |
2000 | ダブルプロファイター制御システムレジスタ | 13Byte |
2800 | ROM/RAMバンクセレクト | 256Byte |
3000 | FDC(μPD765A)&FDD制御用I/O | 8Byte |
このような複雑なメモリマップ構成となっているため、プログラムROMを2重に持ち他と重ならない部分のみ使用しています。したがって以下の書き換えにおいても、両方のイメージを書き換えなければなりません。
まず最初に、コントローラセンスのバグ修正を行ないます。ダブルプロの読み取りルーチンでは純正3ボタンパッドは読み取れるのですが、6ボタンやジョイス ティックタイプなどのコントローラが正常に読み出せないという問題があります。読み出せない場合はたとえば一定方向しか利かなかったり、リピートがかかっ たりします。
まずオリジナルのセンスルーチンを紹介します。
; ; キースキャン ; 0B35 C5 PUSH BC 0B36 3A 03 30 LD A,(3003) 0B39 CB 7F BIT 7,A 0B3B 28 03 JR Z,0B40 0B3D CD 48 1D CALL 1D48 0B40 3E 55 LD A,55 0B42 D3 3F OUT (3F),A ; パッド情報1選択 0B44 00 NOP*16 0B54 DB DC IN A,(DC) ; パッド情報1読取り 0B56 07 RLCA 0B57 07 RLCA 0B58 E6 C0 AND C0 0B5A 47 LD B,A 0B5B 3E FF LD A,FF 0B5D D3 3F OUT (3F),A ; パッド情報2選択 0B5F 00 NOP*16 0B6F DB DC IN A,(DC) ; パッド情報2読み取り 0B71 E6 3F AND 3F 0B73 B0 OR B ; 合成 0B74 EE FF XOR FF 0B76 32 95 DF LD (DF95),A ; 格納 0B79 C1 POP BC 0B7A C9 RET
このルーチンでは時間を置いて2度読み、合成しているのですが、その間隔の取り方が甘いため3ボタン以外では動作しないのです。私は正確な(=セガ推奨の)読み取り間隔がわからなかったため、データが安定した時点で読み取るように変更しました。
テストの結果、好結果が得られたルーチンは以下の通りです。
; ; キースキャン ; 0B35 C5 PUSH BC 0B36 3A 03 30 LD A,(3003) 0B39 CB 7F BIT 7,A 0B3B 28 03 JR Z,0B40 0B3D 00 NOP ; よく解らないですが 0B3E 00 NOP ; カットしても動作に 0B3F 00 NOP ; 支障ないようです。 0B40 3E 55 LD A,55 0B42 D3 3F OUT (3F),A 0B44 06 40 LD B,40 0B46 DB DC IN A,(DC) ; パッド情報1読んでみる 0B48 E6 30 AND A,30 0B4A 4F LD C,A 0B4B DB DC IN A,(DC) ; 64回連続して同じ値が 0B4D E6 30 AND A,30 0B4F B9 CP C 0B50 20 F2 JR NZ,0B44 ; 読みだせなければやり直す 0B52 10 F7 DJNZ 0B4B 0B54 07 RLCA 0B55 07 RLCA 0B56 47 LD B,A 0B57 C5 PUSH BC 0B58 3E FF LD A,FF 0B5A D3 3F OUT (3F),A 0B5C 06 40 LD B,40 0B5E DB DC IN A,(DC) ; パッド情報2読んでみる 0B60 E6 3F AND 3F 0B62 4F LD C,A 0B63 DB DC IN A,(DC) ; 64回連続して同じ値が 0B65 E6 3F AND 3F 0B67 B9 CP C 0B68 20 F2 JR NZ,0B5C ; 読みだせなければやり直す 0B6A 10 F7 DJNZ 0B63 0B6C C1 POP BC 0B6D B0 OR B ; 合成 0B6E EE FF XOR FF 0B70 32 95 DF LD (DF95),A ; 格納 0B73 C1 POP BC 0B74 C9 RET
基本的には上の変更で正常にセンスできますが、もう1箇所ポートから読み出しているルーチンがあります。
; ; 離されるまで待つ ; 0B7B DB DC IN A,(DC) 0B7D E6 3F AND 3F 0B7F FE 3F CP 3F 0B81 20 F8 JR NZ,0B7B 0B83 C9 RET
(DF95)を壊しても支障はないので、ルーチンコールに変更します。
; ; 離されるまで待つ ; 0B7B CD 35 0B CALL 0B35 0B7E B7 OR A 0B7F 20 FA JR NZ,0B7B 0B80 C9 RET
ダブルプロファイターには256KビットのSRAMが搭載されており、セーブデータの保持が行なえる様になっています。ただしここでも問題があり、20Mビット以上のソフトではSRAMが使えません。
ここで書いた通り、メガドライブでは20Mビット以上のソフトでSRAMのマッピングが違います。ダブルプロファイターではハード的には両方のマッピングに対応しているのですが、振り分けているプログラムに問題があり実質使えないのです。
99/05/30 確証はありませんが、20MBit以上の場合はバンク切り替えにより16MBit目にSRAMを出現させている感じです。
では早速、サイズによって振り分けている部分を見てみます。
; ; RAMから起動 ; 1BC1 32 08 20 LD (2008),A 1BC4 32 00 20 LD (2000),A 1BC7 3A 00 DC LD A,(DC00) ; 最終ファイルのサイズ 1BCA B7 OR A ; (512byteヘッダの+0) 1BCB C8 RET Z 1BCC CD 2D 09 CALL 092D 1BCF 32 0C 20 LD (200C),A ; SRAM禁止 ; ヘッダ +1 によって分岐 1BD2 3A 01 DC LD A,(DC01) ; ヘッダ +1 1BD5 CB 7F BIT 7,A 1BD7 28 03 JR Z,1BDC 1BD9 32 02 20 LD (2002),A 1BDC E6 7F AND 7F ; $01 の場合 (20M以上タイプ SRAMマッピング) 1BDE FE 01 CP 01 1BE0 20 08 JR NZ,1BEA 1BE2 32 09 20 LD (2009),A 1BE5 32 0D 20 LD (200D),A ; SRAM有効 1BE8 18 22 JR 1C0C ; $05 の場合 (16M以下タイプ SRAMマッピング) 1BEA FE 05 CP 05 1BEC 20 08 JR NZ,1BF6 1BEE 32 0D 20 LD (200D),A ; SRAM有効 1BF1 32 01 28 LD (2801),A 1BF4 18 16 JR 1C0C ; $03 の場合 (ロードサイズによってSRAMタイプ振り分け) 1BF6 FE 02 CP 02 1BF8 28 18 JR Z,1C12 1BFA FE 04 CP 04 1BFC 28 08 JR Z,1C06 1BFE 3A AA DE LD A,(DEAA) ; ロード済みサイズ 1C01 3D DEC A ; (16KB単位) 1C02 FE 80 CP 80 ; 16Mを越えた場合 1C04 30 06 JR NC,1C0C ; 有効にならない(バグ) 1C06 32 0D 20 LD (200D),A ; SRAM有効 1C09 32 01 28 LD (2801),A 1C0C 32 07 20 LD (2007),A ; ダブルプロモードOFF 1C0F C3 00 00 JP 0000 ; リセット
このプログラムでは、ファイルヘッダ(512バイトヘッダ)の+1によって振り分けています。01hなら20M以上タイプ、05hなら16M以下タイプ、03hなら自動です。通常は03hになっています。
したがって、このバグについてはヘッダを05hに書き換えることでROMを焼き直すことなく対応可能ですが、やはり自動判定できたほうが良いことには違いありません。
修正については流れを見てわかるとおり、1C04での分岐先を1BE2にすれば良いわけです。
1C04 30 DC JR NC,1BE2
プロファイターシリーズでは起動時に必ず警告画面が表示されますが、何度も見てもしょうがないので、ダブルプロファイターでの画面カットの方法を紹介します。
; ; 警告文表示 ; 0BC5 3E 2A LD A,2A ; メッセージ番号 0BC7 CD 89 09 CALL 0989 ; メッセージ表示 0BCA 21 00 00 LD HL,0000 0BCD CD 35 0B CALL 0B35 ; キースキャン 0BD0 3A 95 DF LD A,(DF95) ; キーコード 0BD3 B7 OR A 0BD4 20 05 JR NZ,0BDB 0BD6 2B DEC HL 0BD7 7C LD A,H 0BD8 B5 OR L 0BD9 20 F2 JR NZ,0BCD
メッセージ表示した後で、一定時間過ぎるかキーが押されたら次へ進むようプログラムされている事がわかりますか?
このブロック自体をスキップすればカットできます。
0BC5 18 14 JR 0BDB