この記事 の続きです。
先日セガマークIII/マスターシステムのカートリッジをメガドライブで遊ぶためのアダプタを試作しましたが、初代メガドライブではカートリッジをロックする部品とカートリッジスロットのシャッターが干渉していまひとつ使いづらいものでした。(まあ、裸基板でしたし…)
そこでジャンクのカートリッジのシェルに基板を収めるように再設計しました。
○変換基板再設計後
基板を再設計するついでに、試作版アダプタでは起動しなかったソフトにも対応しました。
対応方法はWikiのメガアダプタの脚注2から辿ったページに載っていましたので、参考にしました。
○カートリッジシェル格納後
カートリッジシェルに収めるとこうなります。
古いシールをきれいに剥がすのに苦労しました。
○変換アダプタ実装
メガドライブ本体に挿すとこんな感じです。
カートリッジシェルの加工は初めてだったのでカードエッジコネクタ下の配線が見えちゃってますが、もう少し工夫すればカードエッジコネクタ下の配線部分も隠せます。
次回はもうちょっとうまくやれるでしょう(次回があるかはわかりませんが)
○動作確認
無事動作確認ができました。
確認に使ったのは試作版アダプタで起動しなかった
・アレスタ
・魔王ゴルベリアス
です。どちらもCOMPILEの作品ですね。
◇◇◇
さて、試作版アダプタで起動できないソフトへの対応なんですが。
参考にした記事ではATmega8aを使っていましたが、私はATmegaを持っていないので手持ちのATtiny2313に移植しました。
しかし、参考にしたソースおよび回路図は
・データバスの最下位ビットが1(High)に固定
・データバスのうち6本をATmega8aのポートC、残り1本をATmega8aのポートBで制御
・Z80に送る命令が冗長
という不思議な実装でした。
どうも何らかの理由で最下位ビットを1(High)固定にするために、Z80に送る命令も冗長になっているようです。
参考にしたサイトの記事も、他のサイトの掲示板の情報を参考にしたらしく、データバスの1本を1(High)固定にしていることに疑問を感じているようでした。
回路図とソースコードを読み解いた結果、
1. 電源投入直後はカートリッジROMへのアクセスを禁止する
2. Z80のスタックポインタを0xE001に設定する
3. Z80をソフトリセットする
4. カートリッジROMへのアクセスを許可する
//#include <util/delay.h> /* comment out by Fram *///#define WAIT_RD() do { } while (PIND & 0x04)
//#define WAIT_RD_HIGH() do { } while (!(PIND & 0x04))
//#define OUTVAL(a,b) do { PORTC = a; PORTB = b | 0x10; } while(0)
//#define RD_SYNC() do { WAIT_RD(); WAIT_RD_HIGH(); } while(0)
// optimize code
// 21 01 E0 : LD HL, $E001
// F9 -- -- : LD SP,HL
// C7 -- -- : RST $00
#define WAIT_RD() loop_until_bit_is_clear(PIND, PIND6)
#define WAIT_RD_HIGH() loop_until_bit_is_set(PIND, PIND6)
#define RD_SYNC() { WAIT_RD(); WAIT_RD_HIGH(); }
int main(void)
{
// PORTB wired to D0-D7
// PORTD5 wired to CE (on the SMS cart side of a 1.5k resistor between megadrive and SMS cart)
// /RD on PORTD6
DDRD = (1 << DDD5); // Set PORTD5 to outputs, others to inputs
PORTD = 0x7F; // Force CE high on the cart at PORTD5, with pull-up input resistors
/* Wait for bus freed */
WAIT_RD_HIGH();
DDRB = 0xFF; // All outputs
/* NOP */
PORTB = 0x00;
RD_SYNC();
/* LD HL, $E001 */
PORTB = 0x21;
RD_SYNC();
PORTB = 0x01;
RD_SYNC();
PORTB = 0xE0;
RD_SYNC();
/* LD SP,HL */
PORTB = 0xF9;
RD_SYNC();
/* RST $00 */
PORTB = 0xC7;
RD_SYNC();
// hands-off the bus
while (1) {
DDRB = 0;
DDRD = 0;




