Genesis Expansion Port Cartridge
ECART

By David Senabre, May 2006.
Revisited: March 2007.


Introduction

 

I wanted to build a cartridge for the expansion port of Genesis/Megadrive (from now on, Megadrive). The reason for this, is to run code from the expansion port, leaving free the cartridge conector, so I could run a BIOS from the expansion port, to read or wirte ROM and SRAM of game cartridges.

To make things clear, I'll call the expansion cartridge ECART.

I made ECART to boot code from it, that would act as a BIOS for Megadrive. A BIOS is some program that runs on a machine to give some basic services. I wrote a PC link service, that lets you transfer files (rom, save games,...) between the console and a PC , similar to what transfer suite for SegaCD does, but using ECART instead. Using control pad port 2, you can connect to a PC parallel port, to get about 11-12Kb/s transfer speed.
Then I wrote services to access compact flash cards, and browse and load games stored there to a rewirtable cartridge. This required aditional electronics for the expansion port cart to be able to access the compact flash card I/O ports.

The ECART is flasheable, so the onboard BIOS can be upgraded and functionalites added.

and a PC software let's you control the address ranges to be read/write, and acts as a master, that sends commands to Megadrive.


For what purposes can ECART be used for?

The expansion port has only enough address lines to access 256Kb (A1-A17)

128 Kwords of 16 bits, to be exact. So, you can use this cart to run homebrew software. It is not intened to for games,... only those up to 256Kb in size will work, which are rare. As I'll discuss later, it is possible to even access 512Kb size code (with some considerations). This does not mean you can run 512Kb games, as you'll see, but lets you use it for other purposes.


General construction overview

As Megadrive has a 16 bit data bus, all memory positions can be seen as made up from a low byte, and a high byte. If you want to run code in a real system, it must be stored in a 16 bit memory chip (ROM, Flash ROM, EPROM, SRAM or whatever). But at the moment I started this project, I had none of these memories.

I used two 8 bits Flash ROMs (29F040) wired in parallel, to get 16 bits. One ROM provides odd bytes, the other one provides even bytes.
Of course, address bus is shared, following this scheme:

Expansion port (EP)
Flash ROM
A1
A0
A2
A1
A3
A2
A4
A3
A5
A4
A6
A5
A7
A6
A8
A7
A9
A8
A10
A9
A11
A10
A12
A11
A13
A12
A14
A13
A15
A14
A16
A15
A17
A16

One of the ROM chips conects its 8 data bits to EP A0-A7
The other one conectes its 8 data bits to EP A8-A15

As ROM /CE, I initially used GND, so they were always enabled.
As ROM /OE, I used /CAS0 signal (pin A03 from exp port). This signal is a read 000000-7FFFFF strobe, so it does the job.
Then I connected ROM /WR to 5V, to disable any possible wirte.

Ok, this cartridge can hold 256Kb data (128Kb each chip), so you need to ground ROM A17 and higher, if present.
This is not a limitation of using a small memory chip, but a limitation of the addressing capabilities of the expansion port, which has ony 17 address lines.

As is, code stored in this cartridge is mapped at $000000-03FFFF and mirrored up to $3FFFFF.
This means that cartridge's ROMs will respond to any read access in range $000000-3FFFFF.

Fine. This can get better, though. I used this scheme to start experimenting as soon as possible. I'll comment further improvements.


As I used 8 bit Flash ROMs, I needed to use two of them, or else I won't be able to run code from it. Yes, sure you can use a single 8 bit ROM or RAM to read and write *data* from it. Genesis/Megadrive can do byte access to any high or low byte. But when running *code*, it definitively needs 16 bit data, as the CPU requires it to fetch instructions.


/ROM signal

When I came to get documentation about bus control lines, I found little info about the EP /ROM signal. I was told that it probably was the $000000-03FFFF strobe for expansion port. This seemed reasonable, when looking at the SegaCD. It hooks up to the expansion port, as my cartridge does, mapping a ROM and RAM like this:

$000000-$01FFFF : BIOS ROM
$020000-$03FFFF : Program RAM
$200000-$23FFFF : Data RAM

As only $000000-03FFFF addresses can be access using the address lines present on the expansion port, if EP /ROM really was a $000000-03FFFF strobe, SegaCD could enable its Data RAM when EP /ROM has high (disabling BIOS ROM and Program RAM), and /ASEL low (meaning a valid data on the bus).

But it isn't. I'm sure now, as my first attemps to map a device using this info failed. I used my logic analyzer, and realised that EP /ROM asserts for addresses over $03FFFF. I'm quite sure it is a $000000-1FFFFF strobe.

Now, for the improvements I made to the original cart.


Improvements

Use 512Kb ROMs.

Fine, you just need to set ROM A17 high when EP /ROM is high. So, wire EP /ROM to ROM A17. This works because EP /ROM asserts in range $000000-1FFFFF. Above that, it gets high, so, setting ROM A17 high, and accessing another 256Kb.

BUT beware, first 256Kb are mapped at $000000-03FFFF and mirrored up to $1FFFFF.

Upper 256Kb will be mapped at $20000-$23FFF, an mirrored up to $3FFFFF, at least.

Anyway, make sure yo don't access any higher addresses as they are dedicated to cartridge when botting from expansion port.

Not mirroring ROM

Similar to the previous case.

This is good if you want to add another device or RAM to the expansion port cart.

So, you'd want to map ROM at $000000-03FFFF, but keep it disabled for higher addresses than $1FFFFF. Very easy.

Just use EP /ROM instead GND ad ROM /CS.

This way, you can only use 256Kb ROM, but can manage other memory chips, or devices, from $200000-23FFFF, mirrored up to $3FFFFF.

As ROM /WR is tied to 5V, you could probably keep ROM /CE always enabled, tied to GND, and /ROM /OE tied to EP /ROM, as no write to any other RAM or device will affect ROM, and it will not drive the bus for addresses over $200000. But I find my final aproach to be a better option.


I chose not mirroring 256Kb ROM.

 

Bottom and top view of ECART

What I ended up doing, is making a cartridge with a maximun storage capacity of 256Kb, as I needed to add I/O ports later, I didn't need more size, and I did not want mirroring. The wiring is as follows:

Expansion port (EP)
Flash ROM
/CAS0
/OE
/ROM
/CS
5V
Vcc
GND
GND
Expansion port (EP)
Flash ROM (even)
D8-D15
D0-D7
Expansion port (EP)
Flash ROM (odd)
D0-D7
D0-D7

My final design.
Adding I/O ports.

 

Bottom and top view of ECART with added IDE interface conector and decoder logic.

There're at least two aproach, depending on if you need to access a cartridge or not.

A) If you don't need to (not my case)

You can add a decoder chip (74LS00 nand gates) to generate a /PORT signal, enabling when EP /ROM high and EP /ASEL low, and so, being a $200000-$3FFFFF strobe.

Just connect EP /ASEL to both inputs of a 2 input nand gate, and its output along with EP /ROM, to the inputs of another nand gate. Its output would be this /PORT signal.

$000000-$03FFFF : BIOS ROM
$040000-$1FFFFF : BIOS ROM (mirror)
$200000-$23FFFF : I/O Ports

Remember that if you use this scheme, and you need to access the cart area (mapped $400000-$7FFFFF when booting from expansion port) you can't use this /PORT signal, as it will enable for these addresses too. This was my case. So I did never build this.

B) If you need to (what I did)

An easy way is to use a decoder like 74LS138. Use EP /ROM as select line 1, and EP A17 as select line 0. Ground the third select line.

Output 0 will be a $000000-$01FFFF strobe.

Output 1 will be a $020000-$03FFFF strobe.

$000000-$01FFFF : BIOS ROM
$020000-$03FFFF : I/O Ports
$200000-$23FFFF : -

None of the expansion cart devices will enable for addresses above $1FFFFF, as EP /ROM goes high and so, it disables ROM, and /PORT signal. You lose some space in the expansion port memory map. Your ROM can now only be 128Kb. This was fine for me, as my BIOS will probable not get to even 32Kb in size.

 

 

Hope you learned something useful here :)