Possible DIY USB Genesis/MD Reader/writer

For hardware talk only (please avoid ROM dumper stuff)
Post Reply
Jazzmarazz
Very interested
Posts: 60
Joined: Wed Mar 12, 2014 11:11 pm
Location: Michigan
Contact:

Possible DIY USB Genesis/MD Reader/writer

Post by Jazzmarazz » Wed Oct 15, 2014 4:19 am

I eventually want to make a fully capable reader/writer supporting many mappers, roms and rams, but for now I spent the night working on this.

It is a Gen/MD cart reader and writer based on the Arduino MEGA using the EXTernal MEMory interface. I have used the exmem interface for normal external RAM expansion, but I think it would be nice to use as a reader and writer for both 16-bit Mask ROMs/EEPROMs and 8-bit SRAM/serial eeprom.

Does anyone think this would not work? Can I use three latches in this fashion to emulate a 16-bit data bus?

Image
Image

Obviously I would have to tie the second and third latch enable pins to an IO on the arduino and a few other miscellaneous pins such as !TIME, but I like the way it looks so far.

HardWareMan
Very interested
Posts: 745
Joined: Sat Dec 15, 2007 7:49 am
Location: Kazakhstan, Pavlodar

Post by HardWareMan » Wed Oct 15, 2014 12:23 pm

I've already done this before. Using Funduino Mega2560 it don't require any additional ICs.
Image
ImageImage
Image
Image
It can generate full set of MD M68K bus signals. It even can dump some protected cartridges. :3 The dumping speed is about 32KBytes/s. Packet protocol with CRC check.

Anyway, continue with DIY.

Jazzmarazz
Very interested
Posts: 60
Joined: Wed Mar 12, 2014 11:11 pm
Location: Michigan
Contact:

Post by Jazzmarazz » Wed Oct 15, 2014 12:56 pm

Hey, that is wonderful! Where can I get some more info? Does your board allow for writing to any address as well?

HardWareMan
Very interested
Posts: 745
Joined: Sat Dec 15, 2007 7:49 am
Location: Kazakhstan, Pavlodar

Post by HardWareMan » Wed Oct 15, 2014 1:43 pm

Here:

Code: Select all

// Cold reset
void DoColdReset()
// MRES/VRES --______--
{
  PORTB = 0xFF;
  PORTD = 0x00;
  delay(1000);
  PORTD = 0x03;  
}
// Warm reset
void DoWarmReset()
// VRES --______--
{
  PORTB = 0xFF;
  PORTD = 0x02;
  delay(100);
  PORTD = 0x03;  
}
// Read word
word DoReadWord(long Adr)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --________--
// CTRL --________--
// CAS0 --________--
// CAS2 ------____--
{
  byte Cmd, Adm, Adh;
  word Result;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEE; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; Cmd = Cmd & 0xFD; Result = PINC; PORTB = Cmd;
  // Three times for required delay
  Result = (PINA << 8) | PINC;
  Result = (PINA << 8) | PINC;
  Result = (PINA << 8) | PINC;
  PORTB = 0xFF;
  return (Result);
}
// Write word
void DoWriteWord(long Adr, word Data)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --____________--
// CTRL --____________--
// LWR  -------_______--
// UWR  -------_______--
{
  byte Cmd, Adm, Adh;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEF; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; 
  DDRA = 0xFF; PORTA = lowByte(Data); DDRC = 0xFF; PORTC = highByte(Data);
  PORTB = Cmd; Cmd = Cmd & 0xF3; PORTB = Cmd;
  PORTB = 0xFF; DDRA = 0x00; PORTA = 0xFF; DDRC = 0x00; PORTC = 0xFF;
}
// Write low byte (D0-D7)
void DoWriteLow(long Adr, byte Data)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --____________--
// CTRL --____________--
// LWR  -------_______--
// UWR  ----------------
{
  byte Cmd, Adm, Adh;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEF; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; 
  DDRA = 0xFF; PORTA = Data; DDRC = 0x00; PORTC = 0xFF;
  PORTB = Cmd; Cmd = Cmd & 0xFB; PORTB = Cmd;
  PORTB = 0xFF; DDRA = 0x00; PORTA = 0xFF;
}
// Write high byte (D8-D15)
void DoWriteHigh(long Adr, byte Data)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --____________--
// CTRL --____________--
// LWR  ----------------
// UWR  -------_______--
{
  byte Cmd, Adm, Adh;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEF; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; 
  DDRA = 0x00; PORTA = 0xFF; DDRC = 0xFF; PORTC = Data;
  PORTB = Cmd; Cmd = Cmd & 0xF7; PORTB = Cmd;
  PORTB = 0xFF; DDRC = 0x00; PORTC = 0xFF;
}
Full range 3 bytes addres used. A0 is not used, A1 connected to VA1 and so thru A23->VA23.

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Wed Oct 15, 2014 3:06 pm

You might also be interested ArDUMPino and SGCExplorer from Bruno Freitas.

www.brunofreitas.com/node/31
www.brunofreitas.com/node/42

I have the latter and the firmware is easily modifiable to poke & dump heavily protected cartridges.

Jazzmarazz
Very interested
Posts: 60
Joined: Wed Mar 12, 2014 11:11 pm
Location: Michigan
Contact:

Post by Jazzmarazz » Wed Oct 15, 2014 10:01 pm

HardWareMan wrote:Here:

Code: Select all

// Cold reset
void DoColdReset()
// MRES/VRES --______--
{
  PORTB = 0xFF;
  PORTD = 0x00;
  delay(1000);
  PORTD = 0x03;  
}
// Warm reset
void DoWarmReset()
// VRES --______--
{
  PORTB = 0xFF;
  PORTD = 0x02;
  delay(100);
  PORTD = 0x03;  
}
// Read word
word DoReadWord(long Adr)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --________--
// CTRL --________--
// CAS0 --________--
// CAS2 ------____--
{
  byte Cmd, Adm, Adh;
  word Result;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEE; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; Cmd = Cmd & 0xFD; Result = PINC; PORTB = Cmd;
  // Three times for required delay
  Result = (PINA << 8) | PINC;
  Result = (PINA << 8) | PINC;
  Result = (PINA << 8) | PINC;
  PORTB = 0xFF;
  return (Result);
}
// Write word
void DoWriteWord(long Adr, word Data)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --____________--
// CTRL --____________--
// LWR  -------_______--
// UWR  -------_______--
{
  byte Cmd, Adm, Adh;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEF; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; 
  DDRA = 0xFF; PORTA = lowByte(Data); DDRC = 0xFF; PORTC = highByte(Data);
  PORTB = Cmd; Cmd = Cmd & 0xF3; PORTB = Cmd;
  PORTB = 0xFF; DDRA = 0x00; PORTA = 0xFF; DDRC = 0x00; PORTC = 0xFF;
}
// Write low byte (D0-D7)
void DoWriteLow(long Adr, byte Data)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --____________--
// CTRL --____________--
// LWR  -------_______--
// UWR  ----------------
{
  byte Cmd, Adm, Adh;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEF; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; 
  DDRA = 0xFF; PORTA = Data; DDRC = 0x00; PORTC = 0xFF;
  PORTB = Cmd; Cmd = Cmd & 0xFB; PORTB = Cmd;
  PORTB = 0xFF; DDRA = 0x00; PORTA = 0xFF;
}
// Write high byte (D8-D15)
void DoWriteHigh(long Adr, byte Data)
// ASEL - $000000..$7FFFFF
// CE0  - $000000..$3FFFFF
// TIME - $A13000..$A130FF
// AS   --____________--
// CTRL --____________--
// LWR  ----------------
// UWR  -------_______--
{
  byte Cmd, Adm, Adh;
  Adm = (Adr >> 8) & 0xFF; Adh = (Adr >> 16) & 0xFF;
  PORTF = Adr & 0xFF; PORTK = Adm; PORTL = Adh;
  Cmd = 0xEF; PORTB = 0xFF;
  if ((Adh & 0x80) == 0x00) { Cmd = Cmd & 0xDF; }
  if ((Adh & 0xC0) == 0x00) { Cmd = Cmd & 0xBF; }
  if ((Adh == 0xA1) & (Adm == 0x30)) { Cmd = Cmd & 0x7F; }
  PORTB = Cmd; 
  DDRA = 0x00; PORTA = 0xFF; DDRC = 0xFF; PORTC = Data;
  PORTB = Cmd; Cmd = Cmd & 0xF7; PORTB = Cmd;
  PORTB = 0xFF; DDRC = 0x00; PORTC = 0xFF;
}
Full range 3 bytes addres used. A0 is not used, A1 connected to VA1 and so thru A23->VA23.
Thanks a load! I am definitely going to look at this code and see if I want to go that path. Having no extra IC's would be a great goal. My main concern was the speed, and that is why I went with the EXMEM direction. 32k/s is fast enough for me though!
Eke wrote:You might also be interested ArDUMPino and SGCExplorer from Bruno Freitas.

www.brunofreitas.com/node/31
www.brunofreitas.com/node/42

I have the latter and the firmware is easily modifiable to poke & dump heavily protected cartridges.
Yes, I have seen both of those and the first one has too many components for what i would like to make. The second one uses a teensy ++ which are very expensive compared to the MEGA. I just bought three Teensy 2.0 for another project, but they are too limited.

Thanks for the links though.

KanedaFr
Administrateur
Posts: 1139
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post by KanedaFr » Thu Oct 16, 2014 12:24 pm

If you use expander, you'll won't need a lot of pin (i2c ones)

I tried this one myself
http://gendev.spritesmind.net/wip/2011/ ... perwriter/

(and yes, it's a teensy, but anything with the i2c pins we'll do it)

Jazzmarazz
Very interested
Posts: 60
Joined: Wed Mar 12, 2014 11:11 pm
Location: Michigan
Contact:

Post by Jazzmarazz » Mon Nov 17, 2014 4:15 am

Thanks for all the great links guys. I went ahead and decided to remove the IC's and wire up my own board based on the MEGA. I am going to start on the code now.

Image
Image
Image
Image

sega16
Very interested
Posts: 251
Joined: Sat Jan 29, 2011 3:16 pm
Location: U.S.A.

Post by sega16 » Tue Nov 18, 2014 12:50 am

SPI io expander are faster than i2c generally. Remember to consult with the datasheet instead of just assuming however.

Jazzmarazz
Very interested
Posts: 60
Joined: Wed Mar 12, 2014 11:11 pm
Location: Michigan
Contact:

Post by Jazzmarazz » Tue Nov 18, 2014 1:01 am

Speed is not my concern, just functionality. I still have time for changes though, since this is just a prototype (obviously). :P

Jazzmarazz
Very interested
Posts: 60
Joined: Wed Mar 12, 2014 11:11 pm
Location: Michigan
Contact:

Post by Jazzmarazz » Mon Dec 01, 2014 9:51 pm

Small update. I can now read the content of carts directly to the PC!
I am simply using bit manipulation within loops and pin arrays. I need to clean up the code first and write some intelligent functions (read header first, check for cart/backwards cart, etc) and then I can write a simple GUI and make it capable of writing to carts.

Thanks again for all of the help folks.

KanedaFr
Administrateur
Posts: 1139
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post by KanedaFr » Tue Dec 02, 2014 12:51 am

while cleaning the forum, I also found this post which could help you :
viewtopic.php?p=20062#20062

Post Reply