この記事 の続きです。

 

先日セガマーク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へのアクセスを許可する

という手順を踏めばいいということがわかりました。
 
データバスの最下位ビットのデータを固定する理由は見当たりませんでしたので、ATtiny2313に移植するついでに回路も素直に組むことにしました。
 
○回路図
 
ATtiny2313に移植した変換アダプタの回路図です。
ATtiny2313に繋がる配線のみ載せています。
他にも配線が必要ですが、それはWikiのメガアダプタのページの脚注1にある回路図を確認してください。
 
オリジナルの回路図ではマイコンのクロックに16MHzのマイコン専用の発振素子を使っていますが、私はメガドライブのカートリッジスロットに出ている13.42MHzのクロックを使っています。
 
ATtiny2313のソースはこうなります。
こちらもオリジナルソースから変更した部分のみです。
 
//#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;

 

ソースをATtiny2313に合わせるついでに、データバスに繋ぐポートを出力に設定するタイミングを見直して、Z80に送るコードも最適化しました。

 

 
けど、最初のNOPも要らないかもしれないなぁ…。
 
以下、個人的備忘録
基板設計データはSMStoMD変換基板.lzh
(ATtiny2313のプロジェクト一式も含む)
 
クロックの原振:53.693175MHz
CLK:約7.67MHz、MC68kと同じクロック(原振の1/7)
HS_CLK:約13.42MHz(原振の1/4)
Z80のクロック:3.579545MHz(原振の1/15)
S_RESET:GNDへの接続を一度切ってから再度繋ぐとリセットがかかる。
      ただのスイッチでリセットできたのでおそらくプルアップされている。
 
いまはメガドライブのカートリッジスロット側のRESET信号を一切見ていないので、何度もリセットしているとスタックオーバーフローを起こすかも。