MMC5 Hacking binge, found a few things.

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

Moderator: Moderators

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

MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

I took a long break from this place. We just had a big snowstorm here, and in preparation, I made a new test setup that allows me to run an MMC5A in an NES with easily reprogrammable ROM and easily probed on all signals. All of my previous MMC5 testing was bench-testing and not in a real NES, which was insightful in some ways, but not really realistic in other ways. So this let me finally dig into a few things that I was curious about, but were really too complicated to replicate with a bench test. The setup allows for relatively easy swapping between MMC5 and MMC5A, though I have only used MMC5A so far. The setup can also be relatively easily swapped to a PAL NES, which I do have available, though I have only used an NTSC NES so far. The setup does not have any consideration for expansion audio.

I found a few new things, which I have already updated in the wiki:
  • Found the function of pin 92; it disables all of the extended graphics modes when driven low.
  • We knew that $2001 disabled 8x16 independent bank sprite mode. I found that it also similarly disables Extended Attribute Mode and Vertical Split mode.
  • Found that extended attribute mode can be realistically used in conjunction with vertical split mode.
  • Found that extended attributes are applied for fill mode, thus disabling the global palette index in $5107. A multi-tile, animated pattern/tesselation covering the screen could be employed this way.
  • Confirmed that "in-frame" status does not reflect H-Blank (pretty sure we knew this already.)
  • Corrected error I made with $5207. Output/input selection has no effect when set in $5800 peripheral mode (always output in this mode).
I would like some feedback/challenges on these things, and any additional ideas. When I found pin 92, it lead me to test $2001 and a number of other things, so please give your thoughts if these spark any new ideas.

Also, I was wondering if anyone has heard from org about decapping the MMC5. I had sent an MMC5A to krzysiobal in hopes to forward it to org in Russia, but I think that global tensions may have understandably prevented it making it there. I am wondering if there is anything any of us can do to help make progress with that.
paulb_nl
Posts: 38
Joined: Fri Nov 18, 2016 7:57 am

Re: MMC5 Hacking binge, found a few things.

Post by paulb_nl »

Thanks for doing more MMC5 testing.

I am curious about some Vertical split specifics and I hope you can answer my questions.

What happens when the split is enabled and threshold tile count is set to zero in both Left and Right modes?

Does changing any of the settings in $5200 during split rendering have an immediate effect? I am most curious about the split side.
User avatar
Bregalad
Posts: 8060
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: MMC5 Hacking binge, found a few things.

Post by Bregalad »

Thanks for doing more MMC5 testing.

There's some things that still aren't fully clear when $5104 is %00 or %01 :
  • ExRAM access is "Write only" but what happens if you read from it ? Open bus ?
  • What exactly happens when writing to ExRAM during VBlank (which is "forbidden" but without more info) ?
  • What exactly happens when writing to ExRAM during forced blanking through $2001 ?
  • What happens if an ExRAM value is simulatenously read from the PPU side and written to from the CPU side ?
Useless, lumbering half-wits don't scare us.
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Thanks for the questions!
paulb_nl wrote: Fri Mar 29, 2024 5:44 am What happens when the split is enabled and threshold tile count is set to zero in both Left and Right modes?
I can try this very easily. Expect an answer tonight or this weekend.
paulb_nl wrote: Fri Mar 29, 2024 5:44 am Does changing any of the settings in $5200 during split rendering have an immediate effect? I am most curious about the split side.
Cool idea, I did not think about this. I will have a scanline interrupt and make all various changes to $5200 and also I will try V-scrolling with $5201. I think I can do this pretty easily.
Bregalad wrote: Fri Mar 29, 2024 3:54 pm ExRAM access is "Write only" but what happens if you read from it ? Open bus ?
I am guessing I could make a test that writes a $55 in ExRAM and read it in different situations with pull-ups and pull-downs on the CPU data bus. How hard of a pull-up or pull-down would be a good amount for this in system? I am guessing 1k should be stiff enough to but yet weak enough not to hurt anything? I can try that.

I never actually tried reading in that mode yet. I did try writing, and the wiki said "$00 would be written". I was writing to the entire ExRAM at the beginning of V-blank, which took longer than the V-blank. The top part of the screen filled up with a lot of junk that kind of changed and flickered over time, and the bottom part (where the writes were when it was back in frame again), all of those writes worked correctly, confirming what the wiki said. I never saw $00's getting written during the V-blank time though.

My CHR-ROM in the test setup is basically an ASCII chart, and then I inverted the color for the $80-FF part. This makes it easy for me to type out debug stuff on the screen and I can easily identify tile numbers, basically telling me what is in the nametable. I was not seeing $00 tiles.
Bregalad wrote: Fri Mar 29, 2024 3:54 pm What exactly happens when writing to ExRAM during VBlank (which is "forbidden" but without more info) ?
I kind of talked through that in the previous answer above. I had put this into the wiki:

"If writes are attempted during V-blank, they may be ignored or cause a corruption at that memory address."

That is kind of the best description I could come up with based on what I saw.
Bregalad wrote: Fri Mar 29, 2024 3:54 pm What exactly happens when writing to ExRAM during forced blanking through $2001 ?
Could you provide an example code or pseudo-code that does this? I am not sure how to do it. I can put code in a scanline interrupt if you want the test positioned in the center of the screen for example. I already have some testing with this interrupt; I just don't know what to do inside in order to make forced blanking.
Bregalad wrote: Fri Mar 29, 2024 3:54 pm What happens if an ExRAM value is simulatenously read from the PPU side and written to from the CPU side ?
I do not know how to perform this test in system. I do not know how to attempt to align those things into a collision like that. Seems we may need a particle accelerator. Do you or anyone have an idea how to approach it? I am using a normal USA NTSC NES. It have 32kbytes Flash PRG-ROM, 32kbytes Flash CHR-ROM, MMC5A, and no other additional memories or logic, etc. I have easy probe access for OUT0, OUT1, OUT2.
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Here is the test result of the first one. Selecting tile #0 works as expected. I have made a test that steps through all 256 possible values of register $5200. Here is a video:

https://youtu.be/BBy78QB9t8w

The 2nd half of the test goes through values $00-7F, confirming that bit 7 has it disabled for all of those.

Here is the test code:
mmc5_5200_test.zip
(38.13 KiB) Downloaded 21 times
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

paulb_nl wrote: Fri Mar 29, 2024 5:44 am Does changing any of the settings in $5200 during split rendering have an immediate effect? I am most curious about the split side.
The answer is yes, you can change $5200 while in frame and the effect is immediate. I did come across a strange glitch that I do not understand though. At the point where I write to $5200, if the value has bit 4 set, I get a glitched scanline.

Video Link:
https://youtu.be/2uX_rf8s34Y

Test Code:
5200_update_while_in_frame.zip
(38.25 KiB) Downloaded 12 times
It could be a problem with my test code. The code is rather sloppy and inefficient; for quick tests like this my goal isn't really for polished code I guess.


I did another test where I successively write to $5200 during the frame in order to make a diagonal split:
diagonal_split.jpg
Video Link:
https://youtu.be/YzLxtsb4Rj0

Test Code:
5200_diagonal_split.zip
(38.19 KiB) Downloaded 19 times
Surprisingly, this test shows no such glitches and works exactly as one would expect.


My test setup:
nes.jpg
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Bregalad wrote: Fri Mar 29, 2024 3:54 pm ExRAM access is "Write only" but what happens if you read from it ? Open bus ?
Yes, it returns open bus when trying to read. I tried it in frame and not in frame. In the video, you can see me attaching a switch to each CPU data pin. When I click the switch, it changes between pull-up or pull-down through a 1k resistor. The test attempt to copy the nametable from the bottom right corner “00” into the bottom-left corner.

Video Link:
https://youtu.be/_hBbokNZ59w

Test Code:
forbidden exram reads.zip
(11.67 KiB) Downloaded 16 times
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Bregalad wrote: Fri Mar 29, 2024 3:54 pm What exactly happens when writing to ExRAM during forced blanking through $2001 ?
I gave this a shot. Please see the attached test code and check if I did it right. There is a series of NOPs right where it does the test.
exram_write_in_forced_blanking.zip
(38.09 KiB) Downloaded 19 times
I wrote $00 to PPUMASK, then I tried writing a ‘?’ character in the lower left corner of the ExRAM nametable. Then turned the PPU back on in PPUMASK. I did this inside a scanline ISR. It caused a small artifact in the center of the screen as we probably would expect.

Without any additional delay, I did get a $00 written instead of a $3f (‘?’ Char). Adding additional delay with NOPs, I got different characters written. They usually flickered between 2 different tiles, and the tiles shown could be different when I reset the NES. I also added enough NOP to lose a whole scanline and it still acted flickery like that. Never did I see the correct tile written. It always wrote something wrong this way.
write_in_forced_blanking.jpg
paulb_nl
Posts: 38
Joined: Fri Nov 18, 2016 7:57 am

Re: MMC5 Hacking binge, found a few things.

Post by paulb_nl »

Ben Boldt wrote: Sat Mar 30, 2024 12:01 am Here is the test result of the first one. Selecting tile #0 works as expected. I have made a test that steps through all 256 possible values of register $5200

https://youtu.be/BBy78QB9t8w
Thank you for these tests and videos! They are very helpful in determining behavior.

Selecting tile 0 seems to trigger the split at the first tile so in Left mode with tile 0 it shows only normal tiles and in Right mode it shows only ExRam tiles.
Ben Boldt wrote: Sat Mar 30, 2024 9:48 am The answer is yes, you can change $5200 while in frame and the effect is immediate. I did come across a strange glitch that I do not understand though. At the point where I write to $5200, if the value has bit 4 set, I get a glitched scanline.

https://youtu.be/2uX_rf8s34Y
The glitched line is caused by the write to $5200 in the middle of the scanline. We start to see the glitched line when $5200 is changed from $91 to $88. This happens because at the time $88 is written the split has not been triggered yet but the tile counter has already passed $08 which means the split is never triggered on that line and so the whole line shows ExRam tiles.

Disabling the split by clearing $5200.7 shows only normal tiles but the split is still triggered at the selected tile #. For example $00->$88 shows only normal tiles and then when $88 is written it still shows normal tiles because the split has triggered at tile 0. When writing $11->$88 the split has not been triggered yet and so it shows ExRAM tiles on that line after the write.

Indeed changing $5200.6 also has an immediate effect. Writing $C8->$88 shows ExRam tiles starting at tile $08 until the write happens around tile $10.
Ben Boldt wrote: Wed Mar 27, 2024 11:13 am We knew that $2001 disabled 8x16 independent bank sprite mode. I found that it also similarly disables Extended Attribute Mode and Vertical Split mode.
Are those disabled because of the write to $2001 or because the PPU stops rendering and so the in-frame flag is cleared? Have you tried disabling rendering by writing to a $2001 mirror?
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Thanks for your analysis on the in-frame writes to v-split mode.
paulb_nl wrote: Sun Mar 31, 2024 2:34 am
Ben Boldt wrote: Wed Mar 27, 2024 11:13 am We knew that $2001 disabled 8x16 independent bank sprite mode. I found that it also similarly disables Extended Attribute Mode and Vertical Split mode.
Are those disabled because of the write to $2001 or because the PPU stops rendering and so the in-frame flag is cleared? Have you tried disabling rendering by writing to a $2001 mirror?
Yes, I tested with $2009 mirror. First I turned the PPU off with $2001, so the MMC5 saw that. Then I turned it back on with $2009. So the PPU was actually running but the MMC5 thought it was still off.
paulb_nl
Posts: 38
Joined: Fri Nov 18, 2016 7:57 am

Re: MMC5 Hacking binge, found a few things.

Post by paulb_nl »

Thanks. Now I am curious what happens with the split if you enable substitutions with $2001 in the middle of the frame and the middle of the scanline while the PPU is already rendering. If the tile counter and split scroll counter are also disabled by $2001 then it should start drawing the top left split in the middle of the screen if $5201 is 0.
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Ohh cool idea, I will try it tonight! This will give more insight how much stuff keeps operating and what gets actually disabled by $2001. I know that scanline interrupts still work with $2001 disabled, so I am going to predict that it will resume from the proper point, but we will see. I can try this with extended attributes as well and see what happens.

Pin 92 low acts very similar to $2001 disabled, except I observed that scanline interrupts do get disabled with pin 92. (I do not know if pin 92 disables the entire scanline counter or just disables the IRQ.)

It might be interesting to hook a function generator up to pin 92, say 10kHz square wave, and observe what happens on the screen.
User avatar
Ben Boldt
Posts: 1164
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: MMC5 Hacking binge, found a few things.

Post by Ben Boldt »

Oh my god I really did not expect this:
enable_rendering_mid_frame.jpg
The test code does this:

In V-blank:
Write $00 to $2001. (MMC5 and actual PPU turn off.)
Then write $0E to $2009 (ppu turns on, MMC5 doesn’t see it.)

In middle of frame via scanline interrupt, write $0E to $2001 (MMC5 sees this, PPU already running.)

Test code:
enable_rendering_mid_frame.zip
(38.09 KiB) Downloaded 48 times

We already knew from the forced blanking test that it doesn’t “reset” the split area back from the top. But I tried another test anyway, where I just removed both writes in V-blank and left the write $0E to $2001 in the scanline interrupt. This looked completely normal this way.


Does this mean there are TWO scanline counters? Because the scanline interrupt still operates, but it starts from zero drawing the vertical split region? Wow, that is a surprise to me.


(Edit)
I did one more test just now. I added 1 to the scanline number at which to generate interrupt. (I.e. register $5203 was $80, I tried $81).

The entire split region moved down 1 pixel as expected. CHR A0..A2 must have operated correctly and been aware of this because no tiles were “rolled” in SL mode. I double-checked CL mode and confirmed that they were rolled.

It seems that A0..A2 represent the lowest 3 bits of this 2nd scanline counter.

(Edit 2)
Okay, I have new info explaining how there are NOT 2 scanline counters.

First of all, when I referred to the forced blanking test that I did a couple days ago, I was not showing a vertical split region when I did that. I was showing a nametable in ExRAM. That is completely different. This test we are talking about now is specifically for vertical split. I was using that basis to say that the main scanline counter didn’t reset.

I did a new test. In V-blank, I set a scanline interrupt at scanline $80, then in the scanline ISR, I set the scanline to $05, wrote $00 to $2001, then $0E to 2001 (I.e. a short forced blank.)

I then got a scanline interrupt each 5 scanlines and the vertical split region started over each time:
reset_scanline_counter.jpg
So there is just one scanline counter and it resets when the MMC5 thinks the PPU went from off to on.
User avatar
Bregalad
Posts: 8060
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: MMC5 Hacking binge, found a few things.

Post by Bregalad »

Ben Boldt wrote: Sat Mar 30, 2024 8:19 pmI gave this a shot. Please see the attached test code and check if I did it right. There is a series of NOPs right where it does the test.

exram_write_in_forced_blanking.zip

I wrote $00 to PPUMASK, then I tried writing a ‘?’ character in the lower left corner of the ExRAM nametable. Then turned the PPU back on in PPUMASK. I did this inside a scanline ISR. It caused a small artifact in the center of the screen as we probably would expect.

Without any additional delay, I did get a $00 written instead of a $3f (‘?’ Char). Adding additional delay with NOPs, I got different characters written. They usually flickered between 2 different tiles, and the tiles shown could be different when I reset the NES. I also added enough NOP to lose a whole scanline and it still acted flickery like that. Never did I see the correct tile written. It always wrote something wrong this way.

write_in_forced_blanking.jpg
Thank you very much for testing this. So basically ExRAM access through $5c00-$5fff doesn't work at all during either VBlank or forced blanking. I clearly remember Just Breed was setting $5120 to %01 (Extended attribute mode) once at startup and never touched this register again. I wonder how it did its ExRAM updates when rendering a new screen, which is typically done by forced blanking. I just confirmed that Just Breed indeed uses forced blanking for its NT updates when rendering a whole new screen. So either I missed something, or it should update the ExRAM part after enabling rendering back and have all palettes as "black" so that the updates doesn't make visible glitches.

There is some tests on MMC5 I think should be interesting :
  • Are you sure using ExRAM as NT in mode %10 or %11 always reads back as $00, or this is some kind of open bus that returned $00 in your particular case ?
  • Can we confirm that negative vertical scroll ($f0 to $ff) displaying AT data ($5fc0-$5fff) as NT works for the split region ? (i.e. it should displays tiles from $5fc0-$5fdf on 1st row, $5fe0-$5fff for second row and use the normally unused upper nybble of $5ff8-$5fff for AT data).
  • Can we confirm that negative vertical scroll ($f0 to $ff) while using ExRAM mode %01 works as expected, that is - use PPU $2xC0-$2xFF as NT data and use $5fc0-$5fff as extended attributes ? Unlike negative scroll in "traditional" modes, this should create a clean, 32x32 playground where that data is not used simultaneously as NT and AT data.
  • What happens when using negative vertical scroll and fill mode ? Does the fill tile still get rendered, or does it render tile $00, $55, $aa or $ff based on the fill colour ?
Useless, lumbering half-wits don't scare us.
paulb_nl
Posts: 38
Joined: Fri Nov 18, 2016 7:57 am

Re: MMC5 Hacking binge, found a few things.

Post by paulb_nl »

Ben Boldt wrote: Mon Apr 01, 2024 10:38 pm Oh my god I really did not expect this:

Does this mean there are TWO scanline counters? Because the scanline interrupt still operates, but it starts from zero drawing the vertical split region? Wow, that is a surprise to me.
Awesome finding :) It is kind of what I expected.

I expected there to be a separate scanline counter for the split because of the 239->0 reset. This would need complex logic if it was done with just one scanline counter.
First of all, when I referred to the forced blanking test that I did a couple days ago, I was not showing a vertical split region when I did that. I was showing a nametable in ExRAM. That is completely different. This test we are talking about now is specifically for vertical split. I was using that basis to say that the main scanline counter didn’t reset.
Indeed, I was confused at first why the split did not start over after the forced blanking in that test but then I noticed the split was not enabled.
I did a new test. In V-blank, I set a scanline interrupt at scanline $80, then in the scanline ISR, I set the scanline to $05, wrote $00 to $2001, then $0E to 2001 (I.e. a short forced blank.)

I then got a scanline interrupt each 5 scanlines and the vertical split region started over each time:

So there is just one scanline counter and it resets when the MMC5 thinks the PPU went from off to on.
If there was only one scanline counter then the split starting over in the middle of the screen which we see in the first image would not be possible.

Actually what I think happens is that after the forced blanking when the in-frame flag goes high the main scanline counter is reset and $5201 is copied to the split scanline counter. That is also how it is implemented in the MiSTer NES core. That copying to a separate counter also explains why you see attribute data as tiles if you set $5201 to 240-255 because it only resets the counter when it wants to increment 239.

It does look like the tile counter is not disabled with $2001 because the second half of the line where you write to $2001 is still blue so the split was already triggered.
Post Reply