MMC5 Hacking Adventures

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

Moderator: Moderators

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 started a long overnight test on each PPU address, should take many hours. When getting that test running, I found that as I changed things here and there, it took different numbers of PPU /RD toggles to set the status bit and different numbers of M2 toggles to clear the status bit. It didn't seem random - things were very repeatable. For the purpose of this test (i.e. identify all addresses that do and do not cause the status to set), I toggled each of those a bunch of times. There is definitely some counter business going on here. Will be interesting to poke more at it and to see if anything in this test indicates a connection between particular addresses and numbers of toggles.
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 »

Results from the test:

"In Frame" status bit is able to be set in the PPU address range $2000 - $3000.

Additional observations:
  • As expected, PPU address $0000 did trigger the status bit to be set, based on prior knowledge that the first falling edge of PPU /RD always sets status regardless of PPU address.
  • PPU address $3000 IS included. $3001 is the first one not to set the status bit in this test.
  • Theory: It could be that after clearing in test $2FFF, the MMC5 has returned to it's "don't care about PPU address, just look for any PPU /RD falling edge" state. (Will test that.)
  • PPU Address $2000 set the status on the 4th falling edge of PPU /RD
  • All other addresses ($2001 - $3000 (including $3000)) set the status on the first falling edge of PPU /RD
  • In this test, clearing of status always occurred on the 3rd falling edge of M2.
User avatar
krzysiobal
Posts: 1036
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: MMC5 Hacking Adventures

Post by krzysiobal »

Yeah, there is some more complexity behind that, because not always three PPU read cycles set the bit (sometimes, one is just enough and sometimes four).

Now I can confirm that only $2000-$3fff adresses (when comes to three-cycle-read) are able to set the bit.
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 »

You were able to get the status bit to set with PPU address range $3001 - $3FFF? I tested each and every PPU address and gave 10 falling edges on PPU /RD, and nothing in that address range set the status bit for me.

My chip is marked MMC5A, is that what yours is marked?
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 »

Did a quick test, running PPU address range limited to just $2FF0 through $3003. Was able to repeat the status being set from beginning up to $3000 and then not set on $3001/2/3. I then made the test skip address $3000, so it tested $2FFE, $2FFF, [skipped], $3001. And the status did get set on $3001 this way and not on $3002. So it looks like it always is accepting the next one regardless of PPU address in this situation.

I am trying to keep in mind that this strange counter-type handling might be related to the difference between one scanline to the next vs. starting a whole new frame after v-blank. I might need to learn more about the PPU and how it accesses memory for different purposes.
Last edited by Ben Boldt on Tue Oct 02, 2018 10:46 am, edited 1 time in total.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: MMC5 Hacking Adventures

Post by lidnariq »

That does smell like there's something off with your test. Try testing addresses randomly?
User avatar
krzysiobal
Posts: 1036
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: MMC5 Hacking Adventures

Post by krzysiobal »

I have MMC5A from Just Breed.
Actually, the scanline counter is quite simple - at start of each PPU read cycle it just looks for the last three 3 PPU read addresses and whenever it sees three from same address, it increments its value.

What is also interesting is that even if the $5204.7 is set, /IRQ is asserted only if M2 toggles (if M2 stops toggling, it it deasserted) - same goes for the /IRQ asserted from $5209.
Attachments
mmc5_2.PNG
Last edited by krzysiobal on Tue Oct 02, 2018 11:35 am, edited 2 times in total.
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 just ran the same test except with random PPU address instead of sequential PPU address. I tested 10,000 random PPU addresses. The address range does correlate - the status bit could only get set in address range $2000 through $2FFF for me.

I noticed that in all cases after clearing the status, the next falling edge of PPU /RD always set the status again regardless of address, on the first falling edge. Will review the data more closely this evening.
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 my data. I put some conditional formatting colors to make it easier to see. Some clear patterns emerge in this test.
Attachments
Set Status Random Address.xlsx
(1.23 MiB) Downloaded 312 times
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 have found that the M2 counter for clearing status, resets its count any time PPU /RD has a falling edge, regardless of PPU address staying the same or changing. I found this by inserting PPU /RD toggles between each M2 toggle. It could never clear the status in this test.
User avatar
krzysiobal
Posts: 1036
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: MMC5 Hacking Adventures

Post by krzysiobal »

Yes, that's how it works - there must be three or more CPU cycles without PPU read between to clear the in-frame bit.
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 »

Okay, my findings agree with that. You said 3 or more cycles -- not sure how literally you mean that. Have you seen it take more than 3 M2 falling edges to clear the status? I have only ever seen it take exactly 3 that I am aware of.

I still see a very persistent range of PPU addresses that can set the status which is different that yours:

$0000
-> Doesn't set
$1FFF

$2000
-> Does set after counting PPU /RD falling edges
$2FFF

$3000
-> Doesn't set for me, does set for you.
$3FFF

How can yours set in range $3000 - 3FFF but not mine? Do you write to any registers or drive any other inputs low at the beginning of your test?
User avatar
krzysiobal
Posts: 1036
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: MMC5 Hacking Adventures

Post by krzysiobal »

Okay, my findings agree with that. You said 3 or more cycles -- not sure how literally you mean that. Have you seen it take more than 3 M2 falling edges to clear the status? I have only ever seen it take exactly 3 that I am aware of.
I mean 3.
How can yours set in range $3000 - 3FFF but not mine? Do you write to any registers or drive any other inputs low at the beginning of your test?
No, you are right, only $2000-$2fff can set it. I haven't checked that before with so many datails.
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 »

Okay. I am trying to think of this from the perspective of FPGA or CPLD, that is why I am so paranoid about edges and what latches and what happens asynchronously, etc.

Do you agree that the in-frame status bit works like this?:

Code: Select all

// Declaration / initial values:
UInt16 prev_ppu_address = ? / don't care
bool always_set_in_frame_status_next_ppu_read = true;  // Default true: first falling edge of PPU /RD always sets in_frame_status regardless of PPU address and set counter.
int set_counter = 0;  // counts PPU /RD falling edges
int clear_counter = 0;  //  counts M2 falling edges

void on_ppu_rd_falling_edge( void )
{
    clear_counter = 0;  // Observation: Always resets M2 counter regardless if PPU address stayed the same or changed.

    if(prev_ppu_addr != ppu_addr)
    {
        set_counter = 0;
        prev_ppu_addr = ppu_addr;
    }
    
    if( true == always_set_in_frame_status_next_ppu_read )
    {
        in_frame_status = 1;
        always_set_in_frame_status_next_ppu_read = false;
    }
    else if( ppu address is in range $2000 to 2FFF )  // Observed this range.
    {
        set_counter++;
        if(set_counter >= 4)
        {
            in_frame_status = 1;
        }
    }
}

void on_m2_falling_edge (void)
{
    if(in_frame_status = 1)
    {
        if(PPU /RD is high)  // Observation: with PPU /RD held low, status can not clear with M2 toggles.
        {
            clear_counter++;
            if(clear_counter >= 3)  // Observation: always clears on the 3rd falling edge of M2, considering /RD had not reset the counter.
            {
                always_set_in_frame_status_next_ppu_read = true;
                in_frame_status = 0
            }
        }
    }
}

void combinational_logic (void)
{
    'and' these:
        M2, !(/ROMSEL), CPU A14,13,12,11,10,9,8,7,6,5,4,3,!2,1,in_frame_status
    result 1 -> always_set_in_frame_status_next_ppu_read = true, in_frame_status = 0
    
    // Observation: this part does not care about PPU /RD even if it is held low.
}
I am wondering if there is some way to simplify this - maybe the counters can be combined into 1 counter and the status bit is one of the bits of the counter, etc. I will think about it some more.

Edit:
Oops, nothing ever clears always_set_in_frame_status_next_ppu_read. hmmm...

Edit 2: fixed I think
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 made a state diagram of how we think it works. I think this is a better approach than pseudo-code. I would like to try to verify each arrow in the diagram. If everything checks out, then I think we can feel pretty confident that we nailed down M2 and /RD interaction with the in frame status bit. Reading from CPU address $FFFA/B is not shown in this diagram.
in_frame_bit_states.PNG
Edit: Something isn't right here because I know that you can loop through just the top 4 boxes if you keep reading PPU addresses in range 2000-2fff. This diagram shows the 4x /RD every other read even when PPU addresses remain in this range. Will think about how to fix the diagram.

Edit 2: This is better:
in_frame_bit_states_2.PNG
Edit 3: This still isn't right because it alternates between caring and not caring about the PPU address when the address is always in range... I will get this, probably a few more revisions...

Edit 4: More improvements:
in_frame_bit_states_3.PNG
Edit 5: I have looked at the diagram in edit 4 a fair bit now and I am feeling pretty good about it now. I think I will print it and start testing each arrow and checking them off.
Post Reply