[Solved] Tile rendering in the tests

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
skink
Posts: 3
Joined: Mon Jun 22, 2020 11:52 pm

[Solved] Tile rendering in the tests

Post by skink » Tue Jun 23, 2020 12:34 am

Hello,

I tried to run some PPU tests on my simulator, but the rendered background somehow is messed up:

sprite_hit_tests_2005.10.05/01.basics.nes
wrong.png
wrong.png (653 Bytes) Viewed 418 times
oam_read.nes
wrong2.png
wrong2.png (1.07 KiB) Viewed 418 times
What's interesting is that if I suspend the PPU from the start of the simulation until some experimentally found cycle, the background gets rendered correctly:

Code: Select all

if (cpu_cycle > 300000) {
  ppu_tick();
  ppu_tick();
  ppu_tick();
}

cpu_tick();
sprite_hit_tests_2005.10.05/01.basics.nes
right.png
right.png (678 Bytes) Viewed 418 times
oam_read.nes
right2.png
right2.png (962 Bytes) Viewed 418 times
If the PPU is suspended for more cycles, the background is still rendered correctly. If I change number of PPU cycles executed per CPU cycle (e.g. 1 or 5 PPU cycles per CPU cycle), the behavior doesn't change, which most likely means that the PPU is fine. My next guess was that NMI/IRQ are getting triggered too late, but at least the sprite 0 hit rom does not seem to contain any interrupts whatsoever.

I'm checking my CPU logs against Nintendulator now, and while there are differences, they only seem to be related to the fact that I haven't implemented the sprite 0 hit yet. I'll keep looking, but maybe someone could guess what may be wrong here?

Thank you.
Last edited by skink on Tue Jun 23, 2020 6:08 am, edited 1 time in total.

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

Re: Tile rendering in the tests

Post by tokumaru » Tue Jun 23, 2020 5:58 am

skink wrote:
Tue Jun 23, 2020 12:34 am
if I suspend the PPU from the start of the simulation until some experimentally found cycle, the background gets rendered correctly
The PPU is known to have a "warm-up" period during which writes to several registers are ignored. Here's what the wiki says about it:
Writes to the following registers are ignored if earlier than ~29658 CPU clocks after reset: PPUCTRL, PPUMASK, PPUSCROLL, PPUADDR. This also means that the PPUSCROLL/PPUADDR latch will not toggle. The other registers work immediately: PPUSTATUS, OAMADDR, OAMDATA ($2004), PPUDATA, and OAMDMA ($4014).
There is an internal reset signal that clears PPUCTRL, PPUMASK, PPUSCROLL, PPUADDR, the PPUSCROLL/PPUADDR latch, and the PPUDATA read buffer. (Clearing PPUSCROLL and PPUADDR corresponds to clearing the VRAM address latch (T) and the fine X scroll. Note that the VRAM address itself (V) is not cleared.) This reset signal is set on reset and cleared at the end of VBlank, by the same signal that clears the VBlank, sprite 0, and overflow flags. Attempting to write to a register while it is being cleared has no effect, which explains why writes are "ignored" after reset.

skink
Posts: 3
Joined: Mon Jun 22, 2020 11:52 pm

Re: Tile rendering in the tests

Post by skink » Tue Jun 23, 2020 6:07 am

This is it, thank you very much Tokumaru.

skink
Posts: 3
Joined: Mon Jun 22, 2020 11:52 pm

Re: [Solved] Tile rendering in the tests

Post by skink » Thu Jun 25, 2020 9:24 am

OK, this is a bit embarassing to admit, but the real problem was much sillier — the VBLANK flag was not reset properly at the $2002 read:

Code: Select all

case 0x2002:
  ppu->status |= 0x7F; // should have been &=
This became evident as soon as I logged the PPU position together with the CPU instructions, just like Nintendulator does it. The first difference against their log was at BIT $2002 PPU:164,105, where the flag was set. It's funny how this change alone made several games like Circus Charlie and Pinball playable on my simulator!

But thank you again for mentioning the warm-up period. It actually pointed me to another problem that I have in the codebase.

Post Reply