TL;DR: Added 9 new tests in v2:
1. Tests 6-7 test DMC DMA behavior relative to OAM DMA and show that:
- 1a. $4015-initiated DMC DMA adds 2 cycles if it lands on a $4014 write cycle.
- 1b. 4-cycle blips either immediately precede or follow the DMC DMA with a 0-cycle gap.
- 1c. 4-cycle blips add only 2 cycles during OAM DMA.
- 1d. 1-cycle blips add 0 cycles if they land in OAM DMA.
2. Tests 8-B show that the 1-cycle blip occurs 2 cycles after the $4015-initiated DMC DMA and does not occur if that is a write cycle. These blips are probably the RDY pin being deasserted for 1 cycle.
3. Tests C-E check for joypad 2 input corruption resulting from 4- and 1-cycle blips. These require a second joypad that returns 1's after 8 reads.
- 3a. On RP2A03H, the 4-cycle blips cause 1 extra joypad read (2 extra total) and the 1-cycle blips do not.
- 3b. On RP2A03, every DMA delay cycle causes an extra joypad read, so there are 2 extra reads from $4015-initiated DMA and 1 extra read from each 1-cycle blip. Normal DMC DMA causes 1-3 extra reads (not sure why this isn't always 3).
-----
I've written a new version with 9 additional tests and will walk through my analysis and results. Most of this is presented in the README in one place and with less analysis, so refer to that if you want the raw data in an easier-to-consume form. Here are the new tests:
Test 6: OAM DMA is performed. This serves as a control case for test 7.
Test 7: $4015 is written. A write cycle occurs 4 cycles later that triggers OAM DMA.
Test 8: $4015 is written. A write cycle occurs 5 cycles later.
Test 9: $4015 is written. A write cycle occurs 6 cycles later.
Test A: $4015 is written. Write cycles occur 5 and 6 cycles later.
Test B: $4015 is written. Write cycles occur 3 and 6 cycles later.
Test C: $4015 is written. Joypad 1 is read 4 cycles later.
Test D: $4015 is written. Joypad 1 is read 5 cycles later.
Test E: $4015 is written. Joypad 1 is read 6 cycles later.
An important note about the results below: the Frame toggle 1 and 2 data will swap when changing the cycle parity the test is run on using left or right. The results here are for the parity from the default cycle delay of 6F (the LR value), which puts cycle 3 DMA on Frame toggle 2 and cycle 4 DMA on Frame toggle 1.
First, I added tests 6 and 7 to test behavior around OAM DMA. Cycle 3 is the read cycle right before the $4014 write, and cycle 4 is the $4014 write.
Disch's findings were that landing on the $4014 write should take 2 cycles, regardless of whether the write is a get or put cycle. This matches up with my findings here, but the result I was more interested in is how this affects the blips. I'm not going to try to count the number of dots on the screen, but compared to test 6, test 7 shows:
Frame toggle 1 (cycle 4): +2 cycles solid. 2 cycle blips.
Frame toggle 2 (cycle 3): +2 cycles solid. 4 cycle blips.
Code: Select all
Blip pattern:
- Frame toggle 0: 2 4
- Frame toggle 1: 2
- Frame toggle 2: 4
(It's a little unintuitive, but the cycle 3 case only adds 2 cycles normally instead of the expected 3 from the length of the DMC DMA. This is because without DMC DMA, the $4014 write in this case always lands on a put cycle and so OAM DMA takes an extra cycle, while DMC DMA changes the alignment so the write is on a get cycle, saving a cycle on OAM DMA.)
I'm guessing at this point that the 4-cycle blip is a reload DMA that occurs immediately after the load DMA. We see that the length is 4 immediately before the start of OAM DMA and 2 immediately after, which suggests that there is no cycle gap between the load and glitch DMAs. DMC DMA always ends on a get cycle, so the very next cycle is a put and is suitable for a reload DMA. If it occurred before by delaying the load DMA, it would mean engaging on a get and making the load DMA engage on a put. Either arrangement results in the same cycle length, but occurring after lets both DMAs land on their preferred cycle parities instead of reversed parities. I can't guess the ordering if they get delayed by a write cycle.
The 1-cycle blips seem to be impacted by what follows the load DMA, which means they have to occur after and have at least a 1 cycle gap. In test 2, the cycle 3 case is followed by 2 write cycles and doesn't show 1-cycle blips. In test 5, the cycle 3 case is followed by a write cycle that ends greyscale and doesn't show the 1-cycle blips. In test 7, neither case shows 1 cycle blips, which means OAM DMA is interfering. It sounds like the RDY pin is being deasserted for one cycle either 1 or 2 cycles later if the cycle is a read; just 1 cycle would prevent cycle 3 in test 4 from having the blip, and more than 2 should show 1-cycle blips on test 2's cycle 3 case. Just a 2 cycle gap should explain everything we see.
To try to test the 1-cycle blip timing, I wrote tests 8-B assuming the blip occurs 2 cycles later and is suppressed by a write cycle. We get the following blip results on RP2A03H, and the same without the 4-cycle blips on RP2A03:
Code: Select all
Test 8:
- Frame toggle 0: 4 4 1
- Frame toggle 1: 4 1
- Frame toggle 2: 4
Test 9:
- Frame toggle 0: 4 4 1
- Frame toggle 1: 4
- Frame toggle 2: 4 1
Test A:
- Frame toggle 0: 4 4
- Frame toggle 1: 4
- Frame toggle 2: 4
Test B:
- Frame toggle 0: 4 4
- Frame toggle 1: 4
- Frame toggle 2: 4
This seems to confirm that the 1-cycle blips do indeed occur 2 cycles later and are suppressed by writes. Test B verifies that it's always a 2-cycle gap, even when the load DMA is delayed by a write cycle.
Next, I wanted to get a better idea of what's going on during the extra delays by checking how they interact with joypad reads. Tests C-E overlap cycle 4 load DMA and cycle 5 and 6 1-cycle blips with $4017 reads and display a count on the top right of the screen of the number of times joypad bits have been set, which indicates the number of lost bits (since each lost bit will shift in a 1 from after the button state). Here are the results:
RP2A03H:
Test C:
- Frame toggle 1: 1 bit deleted every frame. 1 additional bit deleted occasionally.
- Frame toggle 2: No bits deleted.
Test D: No bits deleted.
Test E: No bits deleted.
RP2A03:
Test C:
- Frame toggle 1: 2 bits deleted every frame.
- Frame toggle 2: No bits deleted.
Test D:
- Frame toggle 1: No bits deleted.
- Frame toggle 2: 1 bit deleted occasionally.
Test E:
- Frame toggle 1: 1 bit deleted occasionally.
- Frame toggle 2: No bits deleted.
Revision H matches what we would expect: the 4-cycle blip causes the joypad to be clocked 1 additional time, while the 1-cycle blips have no effect, so the joypads are only clocked on the first of consecutive-cycle reads (like with MMC1 writes). The letterless results are much more interesting: the joypads get clocked on every cycle, consecutive or not. I guessed that this means that normal DMC DMA, which takes 4 cycles, would clock 3 extra times, and a quick and dirty test confirms this, but I also saw cases where it clocked only 1 or 2 extra times. Since test C seems to consistently lose 2, never 1, perhaps something else is going on here, assuming my test is working correctly; I'll make a more targeted test for that later.
I can't think of any more tests I can run that can narrow down the behavior of the blip glitches any further. I'm open to suggestions on if anyone has ideas, but I suspect we may need to use Visual 2A03 to figure out the exact APU timing for triggering the problem.