Problems rendering Donkey Kong's first frame

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
Paul_Atreides
Posts: 9
Joined: Mon Apr 13, 2020 5:24 am

Problems rendering Donkey Kong's first frame

Post by Paul_Atreides » Mon Apr 13, 2020 9:52 am

Some weeks ago I came across Javid9x's *excellent* YouTube channel "One Lone Coder", where he's got a pretty interesting series on how to code a NES emulator. I've started my own emulator with the sole purpose of learning and understanding, and, inevitably, I'm facing a not small number of problems.

If anyone is interested, here's the source code of my modest attempt. It uses Javid9x's rendering library, which I'll eventually replace with my own.
Lots of code for logging and so on. Sorry about that.
https://bitbucket.org/ismarlowe/mynesem ... rc/master/

Below this paragraph is how my very basic (still) emulator is rendering Donkey Kong's first frame.
It's never transitioning to the next screen, where you can see a game setting already with some platforms and ladders. I don't know why that's not happening. I'm wondering if somebody, off the bat, could make a guess as to what's going on:

Image

I'm also trying to run the full_palette.nes ROM, with the following result:

Image

I've compared traces from MESEN side by side with traces produced by my emulator.
At CPU cycle ~25k traces start differing, but this is due to a timing issue. At PPU cycle 0 the vblank bit in MESEN is still set, whereas in my emulator it's not, and that changes the result of a branch instruction.
I've also seen that attribute memory is not exactly the same, or it's the same up to a point. But the code governing the writes to nametables is correct (well...). I can provide memory dumps if you think this could be helpful.
Attachments
2020-04-13 18_40_04-Window.png
2020-04-13 18_40_50-Window.png
2020-04-13 18_40_50-Window.png (5.61 KiB) Viewed 1233 times

dink
Posts: 41
Joined: Sun Jan 12, 2020 8:42 pm

Re: Problems rendering Donkey Kong's first frame

Post by dink » Tue Apr 14, 2020 5:13 am

Hi,
I can at least help with full_palette, refer to https://wiki.nesdev.com/w/index.php/PPU_palettes "The background palette hack" :)
In your pixel output function - something like this:

Code: Select all

		if (!RENDERING && (v & 0x3f00) == 0x3f00) {
			// https://wiki.nesdev.com/w/index.php/PPU_palettes "The background palette hack"
			pix = v & 0x1f;
		}
best regards,
- dink

Paul_Atreides
Posts: 9
Joined: Mon Apr 13, 2020 5:24 am

Re: Problems rendering Donkey Kong's first frame

Post by Paul_Atreides » Tue Apr 14, 2020 9:13 am

dink wrote:
Tue Apr 14, 2020 5:13 am
Hi,
I can at least help with full_palette, refer to https://wiki.nesdev.com/w/index.php/PPU_palettes "The background palette hack" :)
In your pixel output function - something like this:

Code: Select all

		if (!RENDERING && (v & 0x3f00) == 0x3f00) {
			// https://wiki.nesdev.com/w/index.php/PPU_palettes "The background palette hack"
			pix = v & 0x1f;
		}
best regards,
- dink
I can't believe my eyes. So many hours trying to figure out what exactly was wrong with my code, and I was missing this 'hack', which I'm assuming is emulating an actual behavior of the ppu silicon, correct?

Here's how my emulator's render looks like now:

2020-04-14 18_12_18-Window.png

Paul_Atreides
Posts: 9
Joined: Mon Apr 13, 2020 5:24 am

Re: Problems rendering Donkey Kong's first frame

Post by Paul_Atreides » Tue Apr 14, 2020 12:42 pm

I've been debugging the donkey kong issue for a while and have found out it is a NAMETABLE issue.
My PPU code is correctly rendering what appear to be incorrect nametable values.

Black tiles in Donkey Kong are represented by value 0x24.
However, starting at address 0x2220, tiles that are supposed to be black have value 0x0, which directs to the tile containing a '0' in the Pattern table 1.

Address 0x2200 maps to the first tile (starting on the left) under the '1 PLAYER GAME A' line.
In MESEN I've verified this address should contain value 0x24; in my NAMETABLE, it has value 0x00.
What's puzzling is that all the tiles with values other than the black background contain good values.

Extract:
@0x221e: 0x24
@0x221f: 0x24
@0x2220: 0x0 // Start of line '1 PLAYER GAME B'
@0x2221: 0x0
@0x2222: 0x0
@0x2223: 0x0
@0x2224: 0x0
@0x2225: 0x0
@0x2226: 0x0
@0x2227: 0x0
@0x2228: 0x0
@0x2229: 0x0
@0x222a: 0x0
@0x222b: 0x0
@0x222c: 0x0
@0x222d: 0x0
@0x222e: 0x0
@0x222f: 0x0
@0x2230: 0x0
@0x2231: 0x0
@0x2232: 0x0
@0x2233: 0x0
@0x2234: 0x0
@0x2235: 0x0
@0x2236: 0x0
@0x2237: 0x0
@0x2238: 0x0
@0x2239: 0x0
@0x223a: 0x0
@0x223b: 0x0
@0x223c: 0x0
@0x223d: 0x0
@0x223e: 0x0
@0x223f: 0x0
@0x2240: 0x0
@0x2241: 0x0
@0x2242: 0x0
@0x2243: 0x0
@0x2244: 0x0
@0x2245: 0x0
@0x2246: 0x0
@0x2247: 0x0
@0x2248: 0x0
@0x2249: 0x1 // Tile with char '1'

Paul_Atreides
Posts: 9
Joined: Mon Apr 13, 2020 5:24 am

Re: Problems rendering Donkey Kong's first frame

Post by Paul_Atreides » Wed Apr 15, 2020 2:24 pm

An update:

There is a whole section in which the CPU writes the value 0x24 (code for the black bg tile) to the nametable:

...
ppuWrite()/nametable: write 0x24 @ 0x21d1
ppuWrite()/nametable: write 0x24 @ 0x21d2
ppuWrite()/nametable: write 0x24 @ 0x21d3
ppuWrite()/nametable: write 0x24 @ 0x21d4
ppuWrite()/nametable: write 0x24 @ 0x21d5
ppuWrite()/nametable: write 0x24 @ 0x21d6
ppuWrite()/nametable: write 0x24 @ 0x21d7
...

From the CPU perspective, what's happening is a loop until reg Y reaches 0:

18567 F1CE 141:STA-abs(4+0) $720 A:24 X:03 Y:2F P:24 SP:FD CYC:281 SL:259 FC:3 CPUCycle:59313 STA:80 MSK:06
18568 F1D1 136:DEY-imp(2+0) $D0FA A:24 X:03 Y:2F P:24 SP:FD CYC:293 SL:259 FC:3 CPUCycle:59317 STA:80 MSK:06
18569 F1D2 208:BNE-rel(2+0) $FACA A:24 X:03 Y:2E P:24 SP:FD CYC:299 SL:259 FC:3 CPUCycle:59319 STA:80 MSK:06
ppuWrite()/nametable: write 0x24 @ 0x21d2

The problem is that, during the loop, the value of the mask register in the PPU is 0x6, which means that the flag for background rendering is set.

Before the loop is completed, scanline -1 arrives, and with it the cycles in which the vram register is overwritten with temp_vram:
2020-04-15 23_21_14-Window.png
2020-04-15 23_21_14-Window.png (2.88 KiB) Viewed 1062 times
So the CPU continues writing the value 0x24 at earlier nametable addresses which have already been written to.
This corrupts the nametable and generates the broken first frame shown above.

I do not know why this is happening.
I have run nestest.nes and it's passing until the section for hidden instructions.

User avatar
Dwedit
Posts: 4309
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Problems rendering Donkey Kong's first frame

Post by Dwedit » Wed Apr 15, 2020 3:17 pm

Might be related:

PPU wait for ready in Donkey Kong viewtopic.php?f=3&t=19792
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

dink
Posts: 41
Joined: Sun Jan 12, 2020 8:42 pm

Re: Problems rendering Donkey Kong's first frame

Post by dink » Wed Apr 15, 2020 3:27 pm

Paul_Atreides wrote:
Tue Apr 14, 2020 9:13 am
I can't believe my eyes. So many hours trying to figure out what exactly was wrong with my code, and I was missing this 'hack', which I'm assuming is emulating an actual behavior of the ppu silicon, correct?

Here's how my emulator's render looks like now:


2020-04-14 18_12_18-Window.png

Looks good! Yes, it's really how the ppu functions :)

Paul_Atreides
Posts: 9
Joined: Mon Apr 13, 2020 5:24 am

Re: Problems rendering Donkey Kong's first frame

Post by Paul_Atreides » Sat Apr 18, 2020 2:20 pm

Update:

I managed to solve the issue. The cause is sort of appalling... I'd been using a macro [ TRANSFER_ADDR_Y() ] which consisted in 3 lines of code, under an if clause without curly brakets. The result is obvious; only the first line of code was being executed conditionally, the other two always. :lol: :lol: :lol: :roll: :roll: :roll:

Code: Select all

if (_mask_reg.show_bg || _mask_reg.show_spr)
    TRANSFER_ADDR_Y();
Sadly, that's not the last problem I gotta solve.

The problem now (and before) is that Donkey isn't transitioning to the next frame (the scene with the platforms and the ladders).
Does anyone have any idea what could be failing?

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

Re: Problems rendering Donkey Kong's first frame

Post by Quietust » Sat Apr 18, 2020 3:46 pm

Paul_Atreides wrote:
Sat Apr 18, 2020 2:20 pm
Update:

I managed to solve the issue. The cause is sort of appalling... I'd been using a macro [ TRANSFER_ADDR_Y() ] which consisted in 3 lines of code, under an if clause without curly brakets. The result is obvious; only the first line of code was being executed conditionally, the other two always. :lol: :lol: :lol: :roll: :roll: :roll:

Code: Select all

if (_mask_reg.show_bg || _mask_reg.show_spr)
    TRANSFER_ADDR_Y();
Any particular reason why you weren't using inline functions instead of macros?
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

Paul_Atreides
Posts: 9
Joined: Mon Apr 13, 2020 5:24 am

Re: Problems rendering Donkey Kong's first frame

Post by Paul_Atreides » Sat Apr 18, 2020 11:24 pm

Quietust wrote:
Sat Apr 18, 2020 3:46 pm


Any particular reason why you weren't using inline functions instead of macros?
Call it professional degeneration.
At work I mainly use C and C++ in C-style (apart from assembly)... :roll:

I'll consider using inline functions, but, from what I'm reading, they're not exactly equivalent.

User avatar
Dwedit
Posts: 4309
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Problems rendering Donkey Kong's first frame

Post by Dwedit » Sat Apr 18, 2020 11:39 pm

Due to being text replacements, Macros can access local variables, while Inline Functions can not.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

Fiskbit
Posts: 119
Joined: Sat Nov 18, 2017 9:15 pm

Re: Problems rendering Donkey Kong's first frame

Post by Fiskbit » Sun Apr 19, 2020 12:28 am

I recommend just using curly braces on all if statements, even if just one line. I've worked on several projects where this has been a requirement specifically to avoid this kind of bug.

Post Reply