Just how cranky is the PPU OAM?

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

Moderators: B00daW, Moderators

lidnariq
Posts: 9383
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Just how cranky is the PPU OAM?

Post by lidnariq » Mon Mar 11, 2013 8:41 pm

About half a year ago, nocash released his CHR-less Magic Floor, and verified it against his PAL NES. I recently tried to make a reproduction of it on my NTSC NES, and it haaaaates it. All the sprites are wrong, and the dot usually disappears immediately. (Which is because the PPU OAM readback is somewhat broken in the 2C02, but there's more).

Magic Floor originally moved the dot by doing something like

Code: Select all

LDA #0
STA $2003
LDA $2004
CLC
ADC YdirectionAndVelocity
STA $2004
LDA #3
STA $2003
LDA $2004
CLC
ADC XdirectionAndVelocity
STA $2004
I shadowed away the reads from $2004; tried resetting $2003 to 0 at the end, and even tried replacing the $2003←3 with $2004←#Tile; $2004←0, but none of them really ever made it happy.

And despite the entire OAM being set on powerup (all #$EF or #$FF, I tried both), there's still garbage sprites appearing in the upper left corner (if I had to guess, somewhere around X=Y=16). And behavior still gets worse as the PPU gets warmer.

I finally switched the entire code to just use OAM DMA like everyone else, and it worked fine. So what's going on? Just how tricky is the OAM? Is it possible to do partial OAM updates on an NTSC NES? It seems silly to spend 513 or 514 cycles doing OAM DMA instead of ≈24.

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Just how cranky is the PPU OAM?

Post by thefox » Tue Mar 12, 2013 12:37 pm

I'll be pretty surprised if after all these years it turns out that even the $2004 writes (using STA) do not work correctly on 2C02. I mean, is it really possible that nobody has tested this properly before? Although I *do* distinctly remember several people wondering why their $2004 writing code didn't work.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi

User avatar
Bregalad
Posts: 7879
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Re: Just how cranky is the PPU OAM?

Post by Bregalad » Tue Mar 12, 2013 12:44 pm

Sprite DMA technically IS writes to $2004, they are just done by DMA.

Reading from $2004 is however very ambigious. I think different revisions of the PPU are different, some allow reading OAM, some don't.
Anyway I see no valid reason to ever read OAM, to be honest.

User avatar
tokumaru
Posts: 11692
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Just how cranky is the PPU OAM?

Post by tokumaru » Tue Mar 12, 2013 12:53 pm

I remember someone saying a long time ago that using $2004 for sprites wasn't reliable. For a while I thought his was true, but more recently someone else said this was nonsense. I have no idea what the deal really is with $2003/$2004.

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Just how cranky is the PPU OAM?

Post by blargg » Tue Mar 12, 2013 1:52 pm

I remember spending tens of hours trying to make sense of it when writing some tests. Suffice to say, $2003/$2004 aren't a simple address-data read/write pair or at least OAM has lots of quirks that cause extra things to happen.

nocash
Posts: 1210
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: Just how cranky is the PPU OAM?

Post by nocash » Thu Mar 14, 2013 1:20 pm

Bregalad wrote:Sprite DMA technically IS writes to $2004, they are just done by DMA.
Yes, technically (concerning what is passed through addresss/data bus), DMA and non-DMA should be same.
The differences that may cause the problems on NTSC consoles might be transfer timing, or transfer length (DMA writes all 100h bytes, whilst my Magic Floor game updates only 2 bytes; the sprites X and Y coordinates).
lidnariq wrote:I shadowed away the reads from $2004; tried resetting $2003 to 0 at the end
Setting [2003h]=00h after manual transfers should leave the OAM address in same state as DMA transfer (assuming that DMA started at 00h, and wrapped to 00h after writing its 100h bytes).
However, as that didn't work: Did you try setting [2003h]=FFh, and then writing a dummy byte [2004h]=EFh? That would produce the same wrapping from FFh to 00h as happening at the end of DMA. Don't know if that will fix the problem... maybe the PPU is internally containing two OAM address registers, [2003h], and a second internal address register that gets updated only on writes to [2004h].

lidnariq
Posts: 9383
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Just how cranky is the PPU OAM?

Post by lidnariq » Thu Mar 14, 2013 3:00 pm

nocash wrote:Did you try setting [2003h]=FFh, and then writing a dummy byte [2004h]=EFh? That would produce the same wrapping from FFh to 00h as happening at the end of DMA.
You appear to be on to something.

I made test ROMs that tried any one of these sequences:
$2003←$00, $2004←ty, $2004←0, $2004←0, $2004←tx, $2003←$00
$2003←$00, $2004←ty, $2004←0, $2004←0, $2004←tx, $2003←$FF, $2004←tx
$2003←$FC, $2004←ty, $2004←$FC, $2004←$FC, $2004←tx
$2003←$FC, $2004←ty, $2004←$FC, $2004←$FC, $2004←tx, $2003←$00
$2003←$FC, $2004←ty, $2004←$FC, $2004←$FC, $2004←tx, $2003←$FF, $2004←tx

The ones in bold worked, i.e. the sprite not only appeared at all but also in the right place.

User avatar
rainwarrior
Posts: 7812
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Just how cranky is the PPU OAM?

Post by rainwarrior » Thu Mar 14, 2013 4:54 pm

I recently wrote an NES ROM using STA $2004 to fill up the OAM. It runs fine on a PowerPak, but strangely on the PowerPak Lite about half the sprites will be missing/elsewhere. (I should try it from an EPROM later...)

I find this really weird, especially since the sprites are still messed up on the PowerPak Lite even if I reset the cart. (And on the PowerPak they're still fine if I reset.) Exactly which sprites are messed up is mostly consistent, but sometimes changes a little from reset to reset.

I thought this might be a problem with my PowerPak Lite, but maybe there's some really weird conditions for when it's safe to write $2004, or maybe the wiring of the cartridge is important. I dunno!


Edit: After doing some testing, I have found that the $2004 writes work fine as long as I do them immediately before turning on rendering. See my later post for more info.

Edit: Hrm, it's not -quite- reliable even when doing that! Wow. See my later posts.
Last edited by rainwarrior on Fri Mar 15, 2013 9:20 pm, edited 3 times in total.

lidnariq
Posts: 9383
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Just how cranky is the PPU OAM?

Post by lidnariq » Thu Mar 14, 2013 5:56 pm

I idly wonder if this is at all related to the MMC1+OAM problems infiniteneslives was having.

Something I find additionally confusing: when I first made the test ROM, all the irrelevant sprites were (as I said) somewhere around X=Y=16. Now all the offscreen ones are staying offscreen.

For the record: I'm using NES-CNROM-256-05, where I removed the mask ROMs, desoldered H, V, and CPU A14 jumpers, shorted VRAM /OE to ground, connected VRAM A10 to PPU A13, jumpered PRG /WR to Vcc, and just for good measure I removed the 161. PRG has been socketed with pin 1 folded out (so /BUSY won't try to sink power from Vcc), and I'm using an AT28C64-15PC (so 150ns)

Maybe the reason the CPU has OAM DMA and asserts M2 for 15/24 of the cycle is for the PPU, not for external ROMs? Maybe the reason that the 2C07 isn't cranky is because the 2A07 is clocked just a little slower? … Probably not, given that people regularly report success at overclocking the 2A03 by 200%.

User avatar
Memblers
Site Admin
Posts: 3833
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: Just how cranky is the PPU OAM?

Post by Memblers » Fri Mar 15, 2013 3:22 pm

rainwarrior wrote:I recently wrote an NES ROM using STA $2004 to fill up the OAM. It runs fine on a PowerPak, but strangely on the PowerPak Lite about half the sprites will be missing/elsewhere. (I should try it from an EPROM later...)
I would guess that the PowerPak menu has used the DMA, and that would account for the difference.

Makes me wonder if using DMA for several frames, then switching over to manual writes would be any different. I think it's been established that the PPU displaying sprites isn't enough to refresh the DRAM (by Andrew Davie's story about testing The Three Stooges). I don't know much about the physics behind DRAM, but can we know if writing to $2004 is enough to refresh it? If not, I guess $2004 would never be safely usable (maybe interspersed with DMA copies?). But if it does, can a partially uninitialized/unrefreshed DRAM be unstable?

User avatar
Bregalad
Posts: 7879
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Re: Just how cranky is the PPU OAM?

Post by Bregalad » Fri Mar 15, 2013 3:35 pm

If I'm not mistaken, with DRAM, bits will randomly change from '1' to '0' after some time. When the same cell is written again, it will of course take the new value, and normally other cells shouldn't be affected.

I think it is common in DRAM that there is a mecanism that automatically writes back a read value during the same cycle. This way, just by reading the data, it can be refreshed, and this is simpler than doing a read cycle followed by a write cycle (especially if done in software !).
Nowadays most DRAM refresh in hardware (there is something that reads the cells permanently internally), but this is probably not the case with NES' DRAM.

I've heard some old computer even had their main RAM as non-refreshable DRAM, and the NMI-style interrupt was meant to tell the CPU that it should read all the RAM to refresh it. This should hurt the performance terribly though.

lidnariq
Posts: 9383
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Just how cranky is the PPU OAM?

Post by lidnariq » Fri Mar 15, 2013 3:46 pm

Memblers wrote:I don't know much about the physics behind DRAM, but can we know if writing to $2004 is enough to refresh it?
Generically, writing to DRAM is good enough to refresh it. With the OAM... dunno. One thought, given the experiment I had above: maybe when the address overflows from $FF to 0 it triggers a refresh?

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Just how cranky is the PPU OAM?

Post by thefox » Fri Mar 15, 2013 4:48 pm

lidnariq wrote:
Memblers wrote:I don't know much about the physics behind DRAM, but can we know if writing to $2004 is enough to refresh it?
Generically, writing to DRAM is good enough to refresh it. With the OAM... dunno. One thought, given the experiment I had above: maybe when the address overflows from $FF to 0 it triggers a refresh?
Why wouldn't these work then?
$2003←$FC, $2004←ty, $2004←$FC, $2004←$FC, $2004←tx, $2003←$00
$2003←$FC, $2004←ty, $2004←$FC, $2004←$FC, $2004←tx, $2003←$FF, $2004←tx
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi

User avatar
rainwarrior
Posts: 7812
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Just how cranky is the PPU OAM?

Post by rainwarrior » Fri Mar 15, 2013 5:31 pm

Memblers wrote:I think it's been established that the PPU displaying sprites isn't enough to refresh the DRAM (by Andrew Davie's story about testing The Three Stooges).
The two times I've built ROMs that loads once at startup through $2004, both of them were completely stable for at least 30 minutes with no writes at all to OAM but rendering on (don't think I've tested them for longer).

Reading should be enough to refresh DRAM, though I don't know if the system is guaranteed to read all OAM bytes every frame. Does it quit early in the case of an 8-sprite overflow? It could just be that my use case didn't include this possibility.

User avatar
Quietust
Posts: 1556
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Just how cranky is the PPU OAM?

Post by Quietust » Fri Mar 15, 2013 7:16 pm

It doesn't need to read every byte - all it needs to do is read all 32 rows, and that's guaranteed to happen every scanline if you have rendering enabled.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

Post Reply