MMC5 Hacking Adventures

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

Post Reply
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

MMC5 Hacking Adventures

Post by Ben Boldt »

As a lunchtime and after-work activity, I have slowly built and finally completed a setup to hack the MMC5.
  • 8x 16-bit TTL-compatible I2C I/O expanders (totaling 128 bits I/O)
  • USB to I2C adapter
  • Donor MMC5A chip from 'Just Breed', removed successfully
  • 0.65mm pitch QFP-100 20x30 breakout board, MMC5A mounted on it successfully
  • All connections from I/O expanders to MMC5 complete (except audio)
  • Preliminary C# GUI on computer to create automated tests, to let it run overnight, etc.
MMC5 hack rat's nest
MMC5 hack rat's nest
I put a series 100 ohm on each pin in case I goof up and hook 2 outputs together, hopefully saving it if that happens. I have a current-limited voltage source I plan to use as well. The I/O expanders default to input when power is applied and have a 100k internal pull-up when set as input. I created controllable 10k pull-downs for the CPU and PPU data busses so I can test whether the MMC5 is driving the bus or is in open bus / high impedance state.

The first auto-test that I want to create is to try reading from all possible CPU addresses, recording whether the MMC5 is open bus or reporting a value. If it is a value, recording the value. This will tell us each and every address to which the MMC5A responds, and nail down that aspect for the memory map. I will get this test working first, then we can think about what to do next. I would like to start reading and writing to PRG-RAM and watching the unknown lines in the not-too-distant future. I am pretty sure we will be OK on noise and wire length because I will be controlling the M2 line manually with the I/O expanders. This will definitely be a very slow-mo test process.

My goal is to work on the GUI this weekend and see if I can get some sort of test running. Will report progress!
Attachments
Current state of the GUI
Current state of the GUI
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: MMC5 Hacking Adventures

Post by Quietust »

Ben Boldt wrote:The first auto-test that I want to create is to try reading from all possible CPU addresses, recording whether the MMC5 is open bus or reporting a value. If it is a value, recording the value. This will tell us each and every address to which the MMC5A responds, and nail down that aspect for the memory map.
I believe this test was done many years ago using a CopyNES, and it revealed that the only readable addresses were $5010, $5015, $5204-$5206, and $5C00-$5FFF if ExRAM is in "ordinary RAM" mode (i.e. last value written to $5104 was 2 or 3).

Still, it never hurts to recheck these sorts of things, and it'll still be useful in confirming that your testing rig is working correctly.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking Adventures

Post by Ben Boldt »

Here is what I found today:

With these settings:
CPU R/W = 1
/ROMSEL = 1
M2 = 1

The MMC5A drives the CPU data bus when reading from these addresses:
$5010: $01
$5015: $00
$5204: $00
$5205: $01
$5206: $FE
$5208: $C0
$5209: $00


$5C00 - 5FFF: all $00

All reads result in open bus when /ROMSEL = 0.
When M2 = 1, MMC5 register data appears on CPU data bus asynchronously. For the entire test, I stuck M2 = 1, no toggling. However, running my same test with M2 = 0, the data bus is always open bus. I would suspect that the data bus updates when M2 = 1 and then latches whatever it had when M2 = 0.

Interesting to consider what the heck $5208 and $5209 are doing. This comes right after the 8x8->16 multiplier.
lidnariq
Posts: 11430
Joined: Sun Apr 13, 2008 11:12 am

Re: MMC5 Hacking Adventures

Post by lidnariq »

Ben Boldt wrote:However, running my same test with M2 = 0, the data bus is always open bus.
Isn't that what you expected? What were you testing for?
I would suspect that the data bus updates when M2 = 1 and then latches whatever it had when M2 = 0.
I fully expect it's the "normal" transparent latch interface we've seen through the design on the 2A03 / 2C02...
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking Adventures

Post by Ben Boldt »

I want you guys to know that I am going to be pretty new to a lot of this -- I have done a few things where I have changed ROMs in cartridges, but I have never gone deep like this. Never before have I had a need to think about which edge of the clock the data bus is updated, etc, so this is going to be pretty awesome for me, and maybe a little elementary for some of you veterans. I am good at making fancy tools and stuff to help me explore and learn, that is my forte. I would like your ideas to help design more useful tests. I do have all pins controllable with this setup, except for audio.

Anyway, I think that this test has proven that my tools are running pretty well. I might try messing with the multiplier next, seeing how many clocks it requires (if any) to get the correct result. Then I might poke at 5208/5209. Does anyone have any idea what these 2 registers might do? Hopefully it is a divide, that would be awesome.
lidnariq
Posts: 11430
Joined: Sun Apr 13, 2008 11:12 am

Re: MMC5 Hacking Adventures

Post by lidnariq »

Ben Boldt wrote:I want you guys to know that I am going to be pretty new to a lot of this
Ah, ok. That makes sense!

My best guess is that $5208 and $5209 expose some portion of the internal multiplier state.

The only real thing left to be done with the MMC5 audio is characterize its amplifier. The last time I hooked up this copy of Laser Invasion to anything I apparently only got as far as measuring its slew rate: the really quite slow 0.42V/µs. But I never got as far measuring a transfer curve ... ok, fine, I should stop putting that off...

I hooked up a variety of resistors and capacitors from the calibration output out of my 'scope, trying to make something sufficiently similar to a function generator to generate a voltage sweep. Unfortunately, my test conditions are lousy enough that I'm only seeing bad behaviors due to recovering from hitting the supply rails: gains in the linear region vary from 50 to 500, and there's a DC difference between recovering from positive rail and negative rail.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking Adventures

Post by Ben Boldt »

I created a new test today that gives every possible combination of inputs to the multiplier and reads its output, and also $5208 and $5209.

The test runs like this:

for( int i = 0; i < 65536, i++ )
{
Drive M2 high
Drive CPU R/W low (write mode)
Drive CPU address bus to $5205
Drive bits 0-7 of i onto data bus
(Record bits 0-7 to spreadsheet)
Drive M2 Low (falling edge of the clock registering the data into the multiplier)
Drive M2 back high

Drive CPU address bus to $5206
Drive bits 8-15 of i onto data bus
(Record bits 8-15 to spreadsheet)
Drive M2 Low (falling edge of the clock registering the data into the multiplier)

Stop driving CPU data bus - make it an input on my analyzer.
Drive M2 back high
Drive CPU R/W high

Read from $5205, 5206, 5208, 5209, recording each to spreadsheet.
}

After an hour of so, the test was complete and I had my spreadsheet. Then I added additional columns to check the results and see if there was any effect on $5208 and $5209. I found that the multiplier provided the correct answer with no extra M2 cycles for all 65536 combinations, and there was no change ever witnessed on $5208 and $5209. It seems they are not related to the result of the multiplier.

I attached the spreadsheet. I had to zip it to fit under 4 MiB attachment limit.
Attachments
mmc5_multiplier.zip
MMC5 Multiplier Test
(3.97 MiB) Downloaded 1018 times
lidnariq
Posts: 11430
Joined: Sun Apr 13, 2008 11:12 am

Re: MMC5 Hacking Adventures

Post by lidnariq »

Do you know how much time happens between when you drive M2 high and M2 low?

The multiplier in the MMC5 could plausibly not be clocked but instead just asynchronous. Although... we don't say anything about required delays on the MMC5 wiki page so maybe it really is just that fast.
Ben Boldt wrote:Drive M2 Low (falling edge of the clock registering the data into the multiplier)
Drive M2 back high
Drive CPU address bus to $5206
When the actual 6502/2A03 writes, the address bus and data bus are stable, then M2 goes high and then low. Evidently things work otherwise, but.

Given the asynchronous nature you've already observed, you might be able to get away without toggling M2 at all, much like how asynchronous writes to a SRAM work: just
A<- $5205
R/W low
M2 high
D<- mutlipland
A<-$5206
D<- multiplier
R/W high
upper byte of result ->D
A<-$5205
lower byte of result ->D
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking Adventures

Post by Ben Boldt »

Each group of 8-bits in the analyzer takes me approx. 15 msec to read or write. So basically forever compared to a real NES. I guess we don't know if the MMC5 has an internal clock. I know that it isn't uncommon for microcontrollers to have a 1-cycle multiply. I will see about writing a test for multiply without M2 as you prescribed.

I tried writing a few values to $5207, 5208, and 5209, including all 00 00 00, then FF FF FF, and then xx 00 00 where xx repeated attempts 00-ff. All of these fed back the same C0 00 response from $5208/5209. So no clues yet figuring out what that might be.
lidnariq
Posts: 11430
Joined: Sun Apr 13, 2008 11:12 am

Re: MMC5 Hacking Adventures

Post by lidnariq »

Ben Boldt wrote:I will see about writing a test for multiply without M2 as you prescribed.
Only if you want. I don't think it'll establish anything new; I'm just pointing out how asynchronous interfaces work: changing the address is as good as ending the active condition (M2 falling).
So no clues yet figuring out what that might be.
Other possibilities would be for factory verification of things; perhaps it reflects banking status. Does anything change in those two registers when the PPU address changes?
User avatar
krzysiobal
Posts: 1036
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: MMC5 Hacking Adventures

Post by krzysiobal »

*Yes, I can confirm, on my Just Breed it gives similar read results on powerup:
Image

*Maybe this C0 at $5208 is some kind of version (signature), or it returns some what mode MMC5 is is (SL/CL)

*Multiplicator is asynchronous and gives result immediatelly (not like in Mapper 90 when you have to wait 8 cycles for shifting 8 bits of multiplicands internally)

*MMC5 must have some kind of internal clock OR reset detector, because if you stop cycling M2 at 1.7MHz, it returns to power-up state (EXRAM and RAMs becomes write-protected, same applies to the read-back of register below)

*If you write something nonzero to $5209, interrupt is immediatelly asserted. First read of $5209 returns $80 (and interrupt is deasserted), next ones return $00. It is completely independent from $5204 (disabling interrupts through $5204 does not make any effect, also reading $5204 does not report IRQ pending when IRQ is asserted b $5209)

*If there is battery, MMC5's EXRAM content is backed up.

* If you try to read back $5c00-$5fff on powerup, it returns zeros. If you switch EXRAM mode to 0/1 - it returns FFs, if you switch it to 2/3 - it returns its content. So the power up state is something different.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking Adventures

Post by Ben Boldt »

New test, reading from all PPU addresses this time. I am VERY unfamiliar with the PPU, so please help me interpret the results.

CPU R/W = driven to 1
/ROMSEL = driven to 0
M2 = driven to 1

PPU /WR = driven to 1
PPU /RD = driven to 0

for (int i = 0; i < 16384; i++)
{
- Set PPU data bus to have pull-up (i.e. high-z shows up as $FF)
- Drive PPU address bus to i, with bit 13 of i inverted before fed to PPU /A13
- Read and record PPU data bus to spreadsheet.
- Set PPU data bus to have pull-down (i.e. high-z = $00.)
- Read and record PPU data bus again.
- Read and record various control bits.
}

During this entire test, I observed:
- all unknown pins (29, 30, 73, 75, 81, 82, 92, 93) stayed high.
- CIRAM /CE stayed high
- CIRAM A10 stayed high

But please someone explain this to me:
- MMC5 drove the PPU data bus to $FF for all address in the range $2000 to $2FFF. (i.e. the pull downs were overcome, the bus stayed high)
- PPU data bus was high-z for $0000 to $1FFF and $3000 to $3FFF
User avatar
krzysiobal
Posts: 1036
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: MMC5 Hacking Adventures

Post by krzysiobal »

But please someone explain this to me:
- MMC5 drove the PPU data bus to $FF for all address in the range $2000 to $2FFF. (i.e. the pull downs were overcome, the bus stayed high)
Power up state for many MMC5 registers is $FFs (if $5105 = $FF, $5106=$FF, $5107=$FF), so all four nametables are in fill-mode byte mode which returns $FF for all $2000-$2fff.
User avatar
Ben Boldt
Posts: 1148
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking Adventures

Post by Ben Boldt »

Thanks krzysiobal, I'm glad it makes sense.

My intention with this test was to answer your question lidnariq:
Does anything change in those two registers when the PPU address changes?
And of course I forgot to read those registers. Will do so tomorrow.
lidnariq
Posts: 11430
Joined: Sun Apr 13, 2008 11:12 am

Re: MMC5 Hacking Adventures

Post by lidnariq »

Ben Boldt wrote: - all unknown pins (29, 30, 73, 75, 81, 82, 92, 93) stayed high.
So much for my guess that pin 29 or 30 could possibly be PPUA13 OR /PPURD...
Post Reply