Test: ppu_read_buffer [VERIFICATION PENDING]
Moderator: Moderators
Test: ppu_read_buffer [VERIFICATION PENDING]
Here's another test I created. As usual, the ROM file, the readme, and the full source code are included.
http://bisqwit.iki.fi/src/nes_tests/ppu_read_buffer.zip
It is really a mammoth test suite, containing a whopping 78 tests in one.
The test topics mostly revolve around the PPU's $2007 read buffer, but a few ancillary topics are also tested, such as CHR-ROM write protection, PPU reading with the "ADC" instruction, $4014 DMA combined with RAM mirroring, and sprite-0 hit flag, with varying degree of intensity.
The test takes about 20 seconds, and either displays some graphics or plays a few audible tones during those sections where the user must just wait.
I would appreciate test results on the actual console before anyone cheers saying their emulator passes all tests. It is really hard to come up with tests that are failed by the best emulators, today, especially if you can only test on those very emulators.
From the set of Nintendulator, Nestopia, Rocknes and puNES, I only found that Nintendulator consistently fails when you pause / turbo during the DMA tests, but otherwise all four pass all tests.
The focus of this test suite is to catch a large set of typical beginner's mistakes in NES emulation coding. Because of this, the program actually executes as many tests as possible before reporting the results. Tests which depend on passing of an earlier test are not executed. Some tests contain a special workaround for a previously failed test, so that the actual topic can still be tested even if the PPU is broken in a predictable manner. The ROM also tries hard to catch and graciously handle any spuriously triggered BRKs and IRQs.
When the results are reported, the numeric list of all failed tests is shown, followed by the explanation of the first failed test. Tests are not always executed in numeric order. For example (FCEU):
The ROM is a CNROM (iNES mapper 3) with 1 × 16 kB of PRG-ROM, 3 × 8 kB of CHR-ROM and horizontal mirroring. I had to actually implement some compression schemes to fit everything in the ROM that I wanted to fit.
http://bisqwit.iki.fi/src/nes_tests/ppu_read_buffer.zip
It is really a mammoth test suite, containing a whopping 78 tests in one.
The test topics mostly revolve around the PPU's $2007 read buffer, but a few ancillary topics are also tested, such as CHR-ROM write protection, PPU reading with the "ADC" instruction, $4014 DMA combined with RAM mirroring, and sprite-0 hit flag, with varying degree of intensity.
The test takes about 20 seconds, and either displays some graphics or plays a few audible tones during those sections where the user must just wait.
I would appreciate test results on the actual console before anyone cheers saying their emulator passes all tests. It is really hard to come up with tests that are failed by the best emulators, today, especially if you can only test on those very emulators.
From the set of Nintendulator, Nestopia, Rocknes and puNES, I only found that Nintendulator consistently fails when you pause / turbo during the DMA tests, but otherwise all four pass all tests.
The focus of this test suite is to catch a large set of typical beginner's mistakes in NES emulation coding. Because of this, the program actually executes as many tests as possible before reporting the results. Tests which depend on passing of an earlier test are not executed. Some tests contain a special workaround for a previously failed test, so that the actual topic can still be tested even if the PPU is broken in a predictable manner. The ROM also tries hard to catch and graciously handle any spuriously triggered BRKs and IRQs.
When the results are reported, the numeric list of all failed tests is shown, followed by the explanation of the first failed test. Tests are not always executed in numeric order. For example (FCEU):
The ROM is a CNROM (iNES mapper 3) with 1 × 16 kB of PRG-ROM, 3 × 8 kB of CHR-ROM and horizontal mirroring. I had to actually implement some compression schemes to fit everything in the ROM that I wanted to fit.
Can you please include the list of failed tests, not just the last line?
The tests I would expect to have a chance of failing on the actual console are #67, and anything from #73 to #79.
#7 is: Sequential PALETTE reading with 1-byte increment does not work.
#63 is sprite-0 hit by poking data directly into $2003/$2004.
I'm rather surprised to hear fails at those two... Neither should also be sensitive to reset state. Sprite-0 hits may go wrong if CHR-ROM/mirroring does not work properly, or if a previously failed test changed nametable contents, but I cannot think of any explanation for #7. In #7, 32 bytes are written into the palette RAM (reprogramming PPUADDR before each byte), and then three bytes are read in sequence from a location that is not affected by mirroring in a conforming implementation. The read bytes are compared to the table data that was written earlier. But did it pass or fail #47 or #48 (TEST_PALETTE_READS and TEST_PALETTE_READS_UNRELIABLE respectively) when it failed #7?
Heh. Reversal of pass/fail status again, I guess :-) When emulators pass tests but the console fails them, it's really the emulators which fail the tests. But I would still appreciate understanding of why that happens.
The tests I would expect to have a chance of failing on the actual console are #67, and anything from #73 to #79.
#7 is: Sequential PALETTE reading with 1-byte increment does not work.
#63 is sprite-0 hit by poking data directly into $2003/$2004.
I'm rather surprised to hear fails at those two... Neither should also be sensitive to reset state. Sprite-0 hits may go wrong if CHR-ROM/mirroring does not work properly, or if a previously failed test changed nametable contents, but I cannot think of any explanation for #7. In #7, 32 bytes are written into the palette RAM (reprogramming PPUADDR before each byte), and then three bytes are read in sequence from a location that is not affected by mirroring in a conforming implementation. The read bytes are compared to the table data that was written earlier. But did it pass or fail #47 or #48 (TEST_PALETTE_READS and TEST_PALETTE_READS_UNRELIABLE respectively) when it failed #7?
Heh. Reversal of pass/fail status again, I guess :-) When emulators pass tests but the console fails them, it's really the emulators which fail the tests. But I would still appreciate understanding of why that happens.
It should give errors on RockNES 5.07x, since there's a sprite #0/overflow timing bug. Both flags are cleared one scanline later than expected. Version 5.08 (unreleased) fixes such problem though. I detected it with blargg's sprite timing tests.
Zepper
RockNES author
RockNES author
Regarding the sprite-0 hits, this test only expects shed-size accuracy on the timings (about 60 scanlines). Timings are not the issue, it's whether the DMA uploaded correct data or not.
EDIT: I updated the test, removing the fail-barrier before test 73. So now it should be possible to get results for 73-79 on the actual console, even if previous tests failed.
EDIT: I updated the test, removing the fail-barrier before test 73. So now it should be possible to get results for 73-79 on the actual console, even if previous tests failed.
Results from new version, again depending on reset:
BRK?
BRK executed where should not!
01010100ar01011D7800000100
Failed tests: 67 62
Untested: 73-79
Failed tests: 67 63 62
Untested: 73-79
Failed tests: 67 62 52 51 50 7
Untested: 73-79
Are you making sure to wait for $2002 bit 7 to be set a couple times? If you don't, reset might cause the PPU to ignore writes for a frame.
EDIT: I got a new one
Failed tests: 67 62 52 51 50 49
Untested: 8 73-79
BRK?
BRK executed where should not!
01010100ar01011D7800000100
Failed tests: 67 62
Untested: 73-79
Failed tests: 67 63 62
Untested: 73-79
Failed tests: 67 62 52 51 50 7
Untested: 73-79
Are you making sure to wait for $2002 bit 7 to be set a couple times? If you don't, reset might cause the PPU to ignore writes for a frame.
EDIT: I got a new one
Failed tests: 67 62 52 51 50 49
Untested: 8 73-79
I'm using Blargg's framework, which indeed does wait for two frames in the beginning.tepples wrote:Results from new version, again depending on reset:
BRK?
BRK executed where should not!
01010100ar01011D7800000100
[...]
Are you making sure to wait for $2002 bit 7 to be set a couple times? If you don't, reset might cause the PPU to ignore writes for a frame.
Code: Select all
jsr init_wait_vbl ; waits for VBL once here,
jsr wait_vbl_optional ; so only need to wait once more
Is there something I should know about $2007 and delays? Is it possible that under some situations $2007 might not respond as quickly as it should and might skip a read? When rendering is disabled, that is.
I can only predict three possible reasons for getting a BRK.
- Code that is copied from VROM into RAM and then executed was not perfectly copied.
- Code that is copied from ROM into RAM and then executed was not perfectly copied.
- Stack overflow (portions of the RAM-copied code are executed from memory page $100). But this should not happen either. S is set to $FF at reset, and the program's recursion stack is rather shallow. There should be overflow only if natural use of the stack consumes 0xA0 bytes or more.
Well, four:
- CPU does not honor RAM mirroring when fetching opcodes.
But I don't think that's a likely problem on the real CPU.
Hmm, after the "BRK executed where should not", shoud come a listing of CPU registers, but it should be in plain text, not some gibberish code. Turns out that was my mistake, a wrong polarity in a branch instruction. Can you please try it again, so I can at least get useful debugging information?
What.
What did I do wrong...?
Ah, I see. Commit in wrong directory. Did not include updated ROM.
Updated now. Sorry about that.
Code: Select all
534 cd source/
535 git commit . -m 'Fix BRK debugging'
536 cd ..
537 cd ..
538 git archive HEAD ppu_read_buffer > test.tar
539 cd t
540 tar xvf ../test.tar
541 kzip -r /WWW/src/nes_tests/ppu_read_buffer.zip `find -type f|sed 's/^..//'`
542 zip -9 /WWW/src/nes_tests/ppu_read_buffer.zip `find -type d`
Ah, I see. Commit in wrong directory. Did not include updated ROM.
Updated now. Sorry about that.
So it failed immediately upon landing in the supposedly VROM-loaded code.tepples wrote:BRK executed where should not!
PC=1B00, AXYSP=00/00/05/FB/37
I know it's not a power of two. Does PowerPak have a problem coping with that fact?tepples wrote:You mentioned VROM. Three CHR banks are not a power of two; might that have something to do with it?
However, before loading and executing any code from the ROM, the ROM executes test 70 (TEST_CHRROM_READ_BANKED), which verifies that each of the three VROM banks can be read pr...
Oh, I see. There is a possibility for a false positive. Bank 0 contains the same material in the same position that is tested from bank 2. Oops. It wasn't that way in a prior phase of the development, but became so later.
So, PowerPak cannot cope with CNROM, or it cannot cope with three CHR-ROM banks in particular? Should I make this four-banked just to make PowerPak happy?
PowerPak plays every regular CNROM game I've thrown at it, and recent mapper sets even support oversize CNROM workalikes such as the board used in Bubble Bath Babes.Bisqwit wrote:So, PowerPak cannot cope with CNROM
That and make it four-banked just to make burning-it-onto-an-EPROM happy.or it cannot cope with three CHR-ROM banks in particular? Should I make this four-banked just to make PowerPak happy?