This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

OAM reading isn't reliable

OAM reading isn't reliable
by on (#62008)
I've found some very weird OAM read behavior on my NTSC NES, and I'm pretty sure it occurs on the PAL one as well (I know it also acts weird, just haven't swapped boards back to try it yet). Basically, reading from OAM is broken for three out of the four PPU-CPU synchronizations that the system will be in after power or reset. I've been tearing my hair out trying to make sense of this, thinking my NTSC NES was damaged. Once I realized it was related to PPU-CPU synchronization, and that there were exactly four possible patterns of behavior, it started falling into place.

When SPRDATA reads are working correctly, they give you the contents of OAM at whatever SPRADDR is set to. When they're not, some/many/most addresses give you OAM at a different address. I haven't tested writing thoroughly, but I'm pretty sure that SPRDATA writes and SPRDMA work reliably all the time, explaining why this crazy behavior wouldn't have been a problem, as SPRDATA reads are rarely/never used.

I wrote a test program to determine what OAM byte is actually read for each address. It tries them from $00-$FF, with 16 per row. So when working correctly, we'd expect it to begin

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
...

But let's say it's all correct as above, except that reading from address $04 really reads from $48:

00 01 02 03 48 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
...

Since it's difficult to easily see the incorrect entry, the test program prints -- for correct entries, so for the second example above, it prints

-- -- -- -- 48 -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
...

So, here are the three insane mappings I get, randomly chosen at reset, but unchanging until I reset/power again:
Code:
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
18 19 1A 1B 1C 1D 1E 1F -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
-- -- -- -- -- -- -- -- 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27

-- 21 22 23 24 25 26 27 -- 21 22 23 24 25 26 27
-- 21 22 23 24 25 26 27 -- 21 22 23 24 25 26 27
-- -- -- -- -- -- -- -- 20 21 22 23 24 25 26 27
-- 21 22 23 24 25 26 27 -- 21 22 23 24 25 26 27
-- 21 22 23 24 25 26 27 -- 29 2A 23 2C 25 26 27
-- 21 22 23 24 25 26 27 -- 39 0A 23 2C 25 26 27
-- -- -- -- -- -- -- -- -- 61 62 63 64 65 66 67
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
-- -- 82 -- -- -- 26 A7 -- -- -- -- -- 8D 0E AF
-- -- -- -- -- 25 26 27 -- A1 A2 A3 A4 25 26 27
-- A1 A2 A3 A4 25 26 27 -- -- -- -- -- -- AE AF
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

The first two are stable. The first one simply reads $18-$1F when $20-$27 are read, nice and simple. The second one mirrors $20-$27 over the entire range! The last one is unstable, where the mappings change somewhat randomly, but still follow the above general pattern.

I'll probably be working more on this tomorrow, hopefully making the test program standalone so others can see how their NES behaves (I imagine each will be slightly different). Any thoughts on it?

by on (#62014)
This isn't at all helpful, but wasn't there at least one production game that read back OAM? Micro Machines? Maybe it just wrote OAM mid frame?

I would be interested in a test app. Will be interesting to see what clones do too. Would there be a separate way to identify which clock alignment is running, other than looking at the mapping results?

by on (#62025)
This could be related to the refresh bug I helped discover that caused pieces to flicker in LJ65. The working hypothesis was that there is an uncompleted 8-byte DRAM refresh transaction in the PPU's internal buffer, which gets sprayed somewhere else if you do "funny" things. Try displaying at least one full frame with rendering turned on before you fill and then read back OAM.

by on (#62029)
I'm getting a feeling that OAM was never meant to be read, that the read functionality was meant exactly for what Micro Machines does. That would explain why reading doesn't increment the address (so it wouldn't disturb when you read while PPU rendering is occurring). Still probing this behavior, right now writing a program to see whether OAM even works as expected on the one PPU-CPU alignment that seems normal.

by on (#62044)
tepples: enabling sprite rendering beforehand didn't seem to have any effect. This seems to be entirely based on the PPU-CPU synchronization. It'll be interesting to see how this behaves on PAL, now that I've got the cause figured out.

Here's a test ROM that visually shows what addresses don't read back normally (full ca65 source included):

oam_read.zip

It tests OAM reading ($2004), being sure it reads the byte from OAM at the current address in $2003. It scans OAM from 0 to $FF, testing each byte in sequence. It prints a '-' where it reads back from the current address, and '*' where it doesn't. Each row represents 16 bytes of OAM, 16 rows total.

On my NTSC front-loader NES, I get the following four general patterns at random after power/reset:

Image

I also wrote another test that thoroughly tests OAM:

oam_stress.zip

It randomly sets the address, then randomly either writes a random number of random bytes, or reads from the current address a random number of times and verifies that it matches what's expected. It does this for tens of seconds (refreshing OAM periodically so it doesn't fade). Once done, it verifies that all bytes in OAM match what's expected. This only passes for the left-hand pattern above. It also prints a pattern, but it's just based on what it's modified so far, so it might not exactly match the pattern from the first test.

by on (#62118)
I would've tried this on my PAL NES but couldn't get my piece of shit toasters to work. Gave up after 15 minutes of cycling power and adjusting the cart. I'm very interested in the results for PAL though.

I guess this would also explain why sprites were sometimes corrupted in some games when using my PowerPak save state mappers.

BTW oam_stress fails in Nintendulator, I wonder why?

by on (#62136)
I realized that having these tests fail isn't correct, since they should never fail on a NES. The system under test is merely failing to meet our desirable simple model of behavior.

How quickly does Nintendulator fail? That's surprising.

bunnyboy, sorry I ignored one of your questions. Yes, it's possible to determine the PPU-CPU synchronization separately from these tests. I did so and verified that each pattern corresponds to a particular synchronization. Or are you requesting a ROM to test that via the other means (VBL timing, sprite hit, overflow)?

by on (#62137)
I tested oam_read on a PAL NES and famicom and got the following results:

PAL NES
Most of the reads on lines 3-8 always failed, it never passed completely. The errors started from midway on line 3 and ended on beginning of line 8, and all other lines passed without errors. The exact patterns on these lines was random each time after reset. So nothing like the NTSC results, and I'd test on my other PAL unit also but the controller port is broken. Would be interesting to see if it behaves similar or is completely random.

Famicom
The famicom always failed on all reads every time, seems like sprite reads doesn't work at all.

by on (#62140)
blargg wrote:
I'm getting a feeling that OAM was never meant to be read, that the read functionality was meant exactly for what Micro Machines does.


What exacly is it that Micro Machines does?

by on (#62145)
Very interesting that Famicom fails all the time. I'll have to write a test for you to run to see what exactly $2004 returns.

I still need to go back to PAL testing (it's tedious because all I have is a PAL nes board, but no case, so I have to pull my NTSC NES apart and put the PAL board in and hook everything up to it). I was seeing what you mentioned before, where they work except a certain part of the frame. I'm guessing that it's because the PPU-CPU synchronization on PAL constantly drifts around, rather than being frozen at power/reset as on NTSC.

Micro Machines is covered in previous posts. I'm not sure of the details. In one thread Disch and I discussed this and came up with some code to reliably use it in place of sprite #0 hit.

by on (#62221)
blargg wrote:
How quickly does Nintendulator fail? That's surprising.

Very quickly.

by on (#62229)
I had JSR run a further test on the Famicom and it seems that reading from $2004 is like reading from any other write-only PPU register, at least when rendering is disabled. We're going to see whether it behaves any differently when rendering is enabled.

by on (#62231)
So that scanline detection method based on $2004 reads is history, right?

by on (#62234)
We have yet to see what $2004 reads back with rendering enabled on a Famicom. I also haven't tested that technique on my NTSC NES with the various PPU synchronizations. I'm betting it'll work fine on NTSC, that $2004 reading exists for this very purpose.

EDIT: Jsr pretty well verified that $2004 is a write-only register on Famicom in all cases, so yeah, I guess the $2004 read during rendering approach to scanline synchronization is dead, at least if you want Famicom compatibility.

by on (#62567)
blargg wrote:
Very interesting that Famicom fails all the time.


On the Famicom, both PPU and CPU are connected to the reset circuit/switch, which implies that there might be no variations in cycle alignment at all on this system, since every reset brings both PPU and CPU in a defined state. On the NES, the PPU reset line is tied to VCC (deactivated), hence the picture stays stable when pushing reset, unlike the Famicom.

by on (#62569)
Dang, I just checked the Famicom schematics here, and they also have deactivated the PPU reset line. But I swear I read somewhere that pushing the Famicom RESET button also resets the PPU. Maybe an earlier or later PCB revision?

@jsr

What happens when you push RESET on your Famicom?

EDIT: Argh, too much caffeine! On the Famicom, the PPU reset is tied to VCC, while the NES resets the PPU!

Nevertheless, it might be related to this problem.

by on (#62571)
So does Micro Machines fail on a Famicom?

by on (#62603)
6502freak wrote:
What happens when you push RESET on your Famicom?

EDIT: Argh, too much caffeine! On the Famicom, the PPU reset is tied to VCC, while the NES resets the PPU!

Nevertheless, it might be related to this problem.

If you mean it would affect $2004 on the famicom, then I don't see the connection. Making that register write-only requires a change in the PPU hardware, right?

Dwedit wrote:
So does Micro Machines fail on a Famicom?

I only have the famicom so I cannot compare against a NTSC NES, but the game actually runs but clearly with visible glitches. I don't know how sprite reads affects the picture (haven't disassembled it) but I assume that is the source of the glitches. (I don't own the game so I'm running it on the powerpak but I don't think that's a problem since it only uses mapper 2.)

Actually, I found that the FCE ultra emulator appears to emulate $2004 reads as open bus and behaves almost identical to the famicom (while every other emulator I tried instead returned OAM data), and the errors are very similar when running the game on that emulator. This would be one way to detect famicom/NES, does anyone know if there are more differences?

by on (#62604)
jsr wrote:
6502freak wrote:
What happens when you push RESET on your Famicom?

EDIT: Argh, too much caffeine! On the Famicom, the PPU reset is tied to VCC, while the NES resets the PPU!

Nevertheless, it might be related to this problem.

If you mean it would affect $2004 on the famicom, then I don't see the connection. Making that register write-only requires a change in the PPU hardware, right?


According to blargg's findings, it depends on the CPU<->PPU clock alignment, which is random on an NES. In 3 out of 4 possible cases, the readback fails. One particular alignment however yields success. This case seems to never occur on the Famicom.

The Famicom uses the same PPU as the NES. However, on the NES, the RESET line of the PPU is connected to the reset button/circuit, while on the Famicom, it is disabled. This could be the reason for the behaviour, as it seems to affect the initial state of the PPU on power-up.

If you push RESET on your Famicom, the picture remains stable and visible, while on the NES, the TV loses sync due to the PPU H and V counters being reset.

by on (#62605)
6502freak wrote:
[...] on the Famicom, [PPU reset] is disabled. This could be the reason for the behaviour, as it seems to affect the initial state of the PPU on power-up.

As I wrote, on Famicom, $2004 reads back no differently than say $2000; it's a write-only register. It never behaves this way on NTSC or PAL NES.
Quote:
If you push RESET on your Famicom, the picture remains stable and visible, while on the NES, the TV loses sync due to the PPU H and V counters being reset.

Wow. That's enough proof right there that its reset line isn't connected. I had never realized there were so many small differences between the systems.

I got fed up with OAM weirdness on my NES a few days ago. There's just too much obscure behavior when setting even $2003. As far as I'm concerned, the only things a game should do are write 0 to $2003 then write to $4014 to DMA sprites. Anything else is going to give you headaches and break your game for some systems/phases of the moon.

by on (#62608)
6502freak wrote:
If you push RESET on your Famicom, the picture remains stable and visible,


I'm pretty sure this is the case on the top-loading NES as well, from what I remember.

by on (#62610)
Can you test Super Cars on a Famicom?

by on (#62611)
Quote:
If you push RESET on your Famicom, the picture remains stable and visible, while on the NES, the TV loses sync due to the PPU H and V counters being reset.


So this means that any game that uses any raster screen effects will show a garbage screen while reset is held down on the Famicom? Interesting. Punch out would probably still show a stable picture.

I guess Nintendo changed this so that the lockout chip would actually lock you out.

by on (#62612)
Dwedit wrote:
So this means that any game that uses any raster screen effects will show a garbage screen while reset is held down on the Famicom?

Super Mario Bros. 3 on a PlayChoice corrupts when time expires and uncorrupts once more credits are added.

by on (#62614)
Memblers wrote:
6502freak wrote:
If you push RESET on your Famicom, the picture remains stable and visible,


I'm pretty sure this is the case on the top-loading NES as well, from what I remember.

I think my Famiclones are like that too... Games with raster effects do glitch.

by on (#62624)
Yes, on the toploader NES the picture remains stable when the RESET button is held. There is even a few games (at least Hanjuku Hero) that manages to fade out the palette nicely when you release the button, before resetting :p

Quote:
As I wrote, on Famicom, $2004 reads back no differently than say $2000; it's a write-only register. It never behaves this way on NTSC or PAL NES.

I don't see how this would have anything to do with clock alignment. I guess your famicom has a earlier PPU revision, that's the only possible explanation. Then it opens up to the possibility that later FCs allow OAM reading, and that earlier NES don't. Some eariler Famicoms also lacks short-repeating noise I've heard. Does yours fall in that category ?

by on (#62633)
Bregalad wrote:
I don't see how this would have anything to do with clock alignment. I guess your famicom has a earlier PPU revision, that's the only possible explanation. Then it opens up to the possibility that later FCs allow OAM reading, and that earlier NES don't. Some eariler Famicoms also lacks short-repeating noise I've heard. Does yours fall in that category ?


I would be careful with terms like "only possible explanation", unless you have seen the PPU schematics. On blargg's NES, the clock alignment apparently DOES determine the read behaviour, which on the other hand is dependant on the power-up state. So on the Famicom, it may very well be related to the fact that the PPU is in a different power-up state than the NES. It may of course also be true that this is because of a different PPU revision (though not being able to read something flaky sounds more like FIXING a glitch).

One practical way to find out is to run the test on a NES where the /RES pin of the PPU is tied to VCC in a similar fashion as the Famicom.

by on (#62641)
Quote:
On blargg's NES, the clock alignment apparently DOES determine the read behaviour, which on the other hand is dependant on the power-up state.

It affacts reads behavior, but it DOESNT affect the fact it read something. (as opposed to open bus).

by on (#62655)
Bregalad, I think his point was that since the synchronization affects that, it could therefore affect anything. I don't think that's a useful premise. I'm satisfied with JSR's $2004 read test in all sorts of situations, always returning PPU open bus on his Famicom.

by on (#67668)
jsr wrote:
Dwedit wrote:
So does Micro Machines fail on a Famicom?

I only have the famicom so I cannot compare against a NTSC NES, but the game actually runs but clearly with visible glitches. I don't know how sprite reads affects the picture (haven't disassembled it) but I assume that is the source of the glitches. (I don't own the game so I'm running it on the powerpak but I don't think that's a problem since it only uses mapper 2.)

Actually, I found that the FCE ultra emulator appears to emulate $2004 reads as open bus and behaves almost identical to the famicom (while every other emulator I tried instead returned OAM data), and the errors are very similar when running the game on that emulator. This would be one way to detect famicom/NES, does anyone know if there are more differences?

Sorry for digging up an old thread, but this topic came up again at IRC #nesdev so, just for fun, I took a look at what Micro Machines does. I know the principle of this is old info, just wanted to see how this specific game ticks.

In the title screen it reads $2004 8 times on scanlines 16..23 around scanline clock ~310:

FD6E BIT $2004
FD71 BMI $FD73
FD73 ...

So it adds an extra cycle whenever the value returned by $2004 has the top bit set. It's exploiting the fact that at certain times $2004 read always returns $FF and at certain times proper values from OAM, depending on which PPU cycle the read falls on. That way they get a more precise CPU-PPU sync.

So yeah, no reason for this game to fail on Famicom.

...

On the same note, has anybody tested if the palette readback through $2007 works on Famicom?

by on (#68971)
jsr wrote:
PAL NES
Most of the reads on lines 3-8 always failed, it never passed completely. The errors started from midway on line 3 and ended on beginning of line 8, and all other lines passed without errors. The exact patterns on these lines was random each time after reset. So nothing like the NTSC results, and I'd test on my other PAL unit also but the controller port is broken. Would be interesting to see if it behaves similar or is completely random.

I tested on my PAL NES also and got exactly the same results.

Did people test this on different revisions of the NTSC PPU? Also what revision was the PPU in jsr's Famicom?