I've written a few NTSC PPU tests that I used to verify the PPU in my NES emulator. They use the same format as my previous APU tests, reporting the result with a code on screen and a number of beeps (I like this format because it's easy to write new tests and I can keep the asm source files really short). I had a few more tests I wanted to include but couldn't get them to work reliably on my NES.
blargg_ppu_tests.zip
- Palette RAM access, mirroring, transparent entry mirroring
- VRAM read/write, read buffer operation, effect of palette read on read buffer
- Sprite RAM read and write, third byte masking, $4014 DMA copying
- Power-up values of palette (based on what my NES gives back)
- Time VBL flag is cleared
The asm source should help if it's unclear as to what a particular test is doing. Feedback welcome.
Nice one, blargg. Please DO keep them coming. The more the better. Perhaps write one that tests the WHOLE PPU like NEStress does. Although I must admit my emulator fails most of 'em (sob).
vbl_clear_time.nes gives me a black screen (also with Nintendulator)
*edit* What 'few more tests' did you want to include ?
yeah vbl_clear_time.nes just appears as a grey screen on my emulator. Other tests could include testing absolutely every aspect of the PPU no matter how vague. I am going to write something myself someday.
Great stuff. Anyway, what's the power-up values of palette???
Sorry about the VBL hanging. I found that I was testing on my NES using the serial-based console instead of the graphics-based one (I need to simplify my build setup). I added a fix, re-tested them properly (I hope), and updated the [url="http://www.slack.net/~ant/nes-tests/blargg_ppu_tests.zip"]archive[/url].
The power-up values of the palette are what my test program reads back after powering the NES. I have one of the older units that shows a green screen (I think newer front-loading ones had a gray screen). These values probably vary slightly from one console to the next.
Code:
Palette at power-up
0x09,0x01,0x00,0x01,
0x00,0x02,0x02,0x0D,
0x08,0x10,0x08,0x24,
0x00,0x00,0x04,0x2C,
0x09,0x01,0x34,0x03,
0x00,0x04,0x00,0x14,
0x08,0x3A,0x00,0x02,
0x00,0x20,0x2C,0x08
One I wanted to include tests the timing of sprite 0 hit flag clearing, upper-left corner, upper-middle, and the same on the second scanline. I figured that this would catch major timing errors in sprite hit code. But on my NES it often fails one of the tests, seemingly at random.
I doubt I'll write lots of PPU tests since the detailed behavior of the PPU is exceedingly complex (or so I've read). Also I have modest aims for the PPU in my emulator (scanline accuracy only).
I get the 6th error in "VRAM access" test, which translates into "Palette read should also read VRAM into read buffer". Could anyone tell me what is the expected behaviour here? I guess it has something to do with "read buffer operation" and "third byte masking"..
By the way, nice work blargg!
Thx in advance.
Confusion is likely due to my terseness (but at least anyone can correct that).
Reading from $2007 when the VRAM address is $3fxx will fill the internal read buffer with the contents at VRAM address $3fxx, in addition to reading the palette RAM.
The "third byte masking" refers to the third byte (attributes) of each sprite not having all bits implemented, where writing $ff is equivalent to writing $e3.
My old NES would always flash blue, sometimes purple for one reset cycle.
blargg wrote:
Confusion is likely due to my terseness (but at least anyone can correct that).
Reading from $2007 when the VRAM address is $3fxx will fill the internal read buffer with the contents at VRAM address $3fxx, in addition to reading the palette RAM.
The "third byte masking" refers to the third byte (attributes) of each sprite not having all bits implemented, where writing $ff is equivalent to writing $e3.
Uhm.. I still don't get it (sorry). Aren't "the contents at VRAM address $3fxx" and "palette RAM" contents at address $xx the same thing?
Anyway, is that the expected behaviour of the PPU? And if so, what is it useful for?
Thx again.
Muchaserres wrote:
Uhm.. I still don't get it (sorry). Aren't "the contents at VRAM address $3fxx" and "palette RAM" contents at address $xx the same thing?
No, they are not the same thing. Palette RAM consists of twenty-eight 6-bit words of DRAM embedded within the PPU and accessible when the VRAM address is between $3F00 and $3FFF (inclusive). When you read PPU $3F00-$3FFF, you get immediate data from Palette RAM (
without the 1-read delay usually present when reading from VRAM) and the PPU will
also fetch
nametable data from the corresponding address (which is mirrored from PPU $2F00-$2FFF). This phenomenon does not occur during writes (as it would result in corrupting the contents of the nametables when writing to the palette) and only happens during reading (since it has no noticeable side effects).
Thanks Quietust, that clears it up. Just one more question, which may be offtopic, but.. is PPU $3000-$3EFF really a mirror of PPU $2000-$2EFF? And if so, what is the point of it being like that? I mean, wouldn't it be more practical to have the palettes at PPU $3000-$3F1F? A restriction of the PPU hardware scheme?
The PPU does not natively access PPU $3000-$3FFF during any of the rendering process, but it IS possible to map ROM/RAM at that location and then access it $2006/$2007. The VRAM region $3F00-$3FFF is effectively read-only (and reading it is rather cumbersome).
Mapping palettes at $3000-$3F1F makes absolutely no sense - if anything, the palette could have been mapped at $3FE0-$3FFF only, but that would have required checking additional address lines (i.e. more hardware). One significant advantage of using $3F00-$3FFF is that the first write to $2006 discards the upper 2 bits, so you can write $FF,$00 (using INX/INY) to jump to the palette.
Thanks again. It is always interesting to know these kind of things.
Quietust wrote:
The PPU does not natively access PPU $3000-$3FFF during any of the rendering process, but it IS possible to map ROM/RAM at that location and then access it $2006/$2007. The VRAM region $3F00-$3FFF is effectively read-only (and reading it is rather cumbersome).
So, if I understand it right, it is the cartridge who maps PPU $2000-$2FFF at PPU $3000-$3FFF, isn't it? I don't really see any advantage in using this address range to map RAM/ROM.. is it there any program which actually takes any advantage of it?
Excuse me if all those questions sound too stupid or something..
Dwedit wrote:
My old NES would always flash blue, sometimes purple for one reset cycle.
Kind of interesting. I always thought my memories of a green screen at startup were shared by other NES owners, but now I find I might be among a minority! Almost like the philosophical issue of whether anyone else sees colors as one does. :)
At one point in time I had two NES's because someone sent one for Christmas after I already had one. On the older NES, the default screen color (seen when no game was loaded or during the few split-seconds before a game drew the title screen) was light blue. On the newer NES, the screen color was pinkish (don't remember exactly how it looked - that NES kicked the bucket years ago and we threw it out). Strangely, Legend of Zelda got a different result - during the second or so it takes to boot, the older NES would flash two or three different colors on the screen before the title screen. I haven't found any emulators that show this, and I don't remember it ever happening when starting LOZ with a Game Genie (which blackens the screen before starting the game, and no colors showed up before the title screen). To this day I've wondered what it was about LOZ that caused the NES to show multiple screen colors during the bootup phase. None of the colors matched the background color of the title screen.
On the 2 NES I have, one is just gray and the other is yellow.
I think that all we really want for our nes emulators is for the screen to be black. That would be the most neutral colour, i believe. It would also meant that there would be no flickering at the start of a ROM load.
That would imply initializing the palette to $0F. Would this break any games?
Right, the point of initializing the palette to particular values is in case a game expects certain values. Someone could do the work of checking this by modifying an emulator to log whenever the first access to a particular palette entry is a read rather than a write.
The color shown at power-up is presumably determined only by the value in the first palette entry, so it would be only one modification. But being an emulator, the accuracy of the simulation doesn't need to be compromised. An emulator can make a special case in graphic rendering and treat the first palette entry as black until unless it's been written since power-up.
It would be stupid for any game to rely on the initial palettes values. Final Fantasy seems to rely on an initial value into ram for pseudo-random encounder, but after all, the encounters are supposed to be random, so no problem here. Read the initial palette to seed a random number generator would be pretty stupid, I think.
I just noted than some games, such as Dragon Warrior 3 and Hanjuku Hero does a palette fade-out in the reset routine. It's pretty fun, because the screen is supposed to be totally off at that time. However, maybe it is not the case on a real nes (?) and it could fade out the screen if the reset button would be pushed (?) I have no DW3 card, so if someone could confirm this with more detail it would be cool.
So I don't know if the games reads the palette from the PPU or from a RAM buffer to do the fade-out at the begining. If it is from ram, gabarage may be written to the palette at power up, but it would do a nice fade out at reset (not power up), if bg and sprites are still turned on via $2001 trough the whole reset routine (but I suppose that gabarage would be seen when the PPU is reseted for two frame, else waiting two frames would make no sense, right ?). Anyway, the screen is off when the reset button is down, so I think it isn't that overall.
Quote:
It would be stupid for any game to rely on the initial palettes values.
Yes it would, but when programming, especially in assembly language, sometimes code unintentionally depends on obscure aspects of hardware. If these aspects are stable, it might not get caught in testing. The point of writing an emulator to be as accurate as possible is to handle cases like these.
When coding for the NES, one should rely on hardware details only where there is significant benefit. About the only use of this kind of information when programming for the NES is when trying to understand exactly why some code isn't working.
Bregalad wrote:
I just noted than some games, such as Dragon Warrior 3 and Hanjuku Hero does a palette fade-out in the reset routine. It's pretty fun, because the screen is supposed to be totally off at that time. However, maybe it is not the case on a real nes (?)
If you hit the reset button to do a soft reset, the screen might not be off, especially if you're playing on a Famicom where the CPU reset button doesn't affect the PPU at all.
Hey blargg,
If I wanted to run this on real hardware, what would I do about the CHR-ROM? (or are you using CHR-RAM?)
My devcart has CHR RAM (Zelda modified to always have the SRAM switched in at $E000), so I load the ASCII tiles there when printing the result code on screen. But I'm pretty sure none of the tests even access the CHR area, just the code that prints the result. Since it also makes audible beeps, they'll probably be usable with CHR ROM.
Hello,
It's my first time here in the forums and it has provided a lot of help for us aspiring emulator developers.
Currently, my emulator's failing on Blargg's vram_test with an error code of #6 (Palette read should also read VRAM into read buffer)
Digging the test's source code I have outlined from what I understand is the flow of the test.
1. Set VRAM addr to $2F12 (non-palette address)
2. Write $9A
3. Read from VRAM (returns whatever the buffer's old value was, buffer = $9A)
4. Set VRAM addr to $3F12 (palette address)
5. Read from VRAM (returns the palette value, buffer = palette value)
6. Set VRAM addr to $2F13 (non-palette address)
7. Read from VRAM (returns buffered palette value, buffer = value at $2F13)
8. Compare buffered palette value with $9A (and not with the value stored at $2F12)
9. If equal, test is OK, else Fail.
Please correct my understanding on the flow of the test.
Code:
lda #6;) Palette read should also read VRAM into read buffer
sta result
lda #$12
jsr set_vram_pos
lda #$9a
sta $2007
lda $2007
lda #$3f
sta $2006
lda #$12
sta $2006
lda $2007 ; fills buffer with VRAM hidden by palette
lda #$13 ; change back to non-palette addr to enable buffer
jsr set_vram_pos
lda $2007
cmp #$9a
jsr error_if_ne
breathermachine wrote:
Code:
lda $2007 ; fills buffer with VRAM hidden by palette
That is the key. The palette value doesn't go in the buffer, instead the buffer receives the value from the nametable mirror that is "behind" the palette. What happens is that PPU is still doing the nametable access like it normally would, but internally overrides the returned value with the value from the palette. So the palette value doesn't get buffered.
Thank you for your reply thefox.
Okay so the palette value doesn't go into the buffer, instead, the value from the mirrored nametable that is "behind" the palette. My question is, how exactly is this mirrored nametable address computed from the palette address?
Is it just palette address - $1000 = mirrored nametable address?
Or does nametable mirroring have an effect?
Okay I was able to make the test pass by subtracting the palette address by $1000 and then applying nametable mirroring to the subtracted addres. Thank you for your help!
Mirroring is not about subtraction, but about clearing bits to make it seem like they're being ignored (which is what happens on hardware). The range $2000-3FFF (8KB) is dedicated to name/attribute tables, but the PPU can work with 4KB worth of name/attribute tables at most, so the same 4KB is visible twice in that 8KB window. That happens because the memory chip where the name/attribute tables are simply ignores bit 12 of the VRAM address, so it can't distinguish between ranges $2000-$2FFF and $3000-$FFFF. Look at these 2 addresses in binary form:
$23C0 = %10001111000000
$33C0 = %11001111000000
The only difference is bit 12, but since that's ignored, the PPU will access the same memory when either of these addresses is used. Your fix of subtracting $1000 worked because the end result is the same in this case, but conceptually, mirroring is a result of bits being ignored, so it would be more accurate for you to clear that bit (i.e. address = address & 0xefff;) rather than subtract $1000.
Note that I'm discussing only the underlying NT/AT fetches, the last 256 bytes of $2000-$3FFF are obviously used to read the palette and override what would otherwise be returned by the $2007 read.
Thanks for the reply tokumaru!
Thanks for the info about the mirroring. I already have some of those masks already implemented in other parts of my emulator (ex: Using $E7FF to perform mirroring for CPU addresses in $0000-$1FFF range). Saves a lot of unnecessary writes (I used to have code that writes to all mirrored locations)
I was just stuck with this "mirrored nametable behind the palette" thing.
The link for the PPU-tests blargg_ppu_tests.zip (found in the first entry in this thread) doesn't seem to be working anymore. Anyone got these files?
oRBIT2002 wrote:
The link for the PPU-tests blargg_ppu_tests.zip (found in the first entry in this thread) doesn't seem to be working anymore. Anyone got these files?
Google it.
http://blargg.8bitalley.com/nes-tests/