For hardware talk only (please avoid ROM dumper stuff)
-
Jazzmarazz
- Very interested
- Posts: 60
- Joined: Wed Mar 12, 2014 11:11 pm
- Location: Michigan
-
Contact:
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?
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
-
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: 885
- 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!
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.
-
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
-
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).
![Razz :P](./images/smilies/icon_razz.gif)
-
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.