It is currently Sat Sep 21, 2019 4:07 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Mon May 06, 2019 10:38 pm 
Offline

Joined: Mon Mar 11, 2019 10:56 pm
Posts: 15
Hello. I've been doing cycle accurate PPU for a while but it just isn't finished ever. My test rom is Balloon fight as for other rom's I've not imeplemented proper mirroring of things so I just see garbage. Can someone shed some light by intuition where should I look at? For me it looks like X is being sheared/streched and also every other line is wrong so my guess it's something with scanlines which is problematic in my code.

PS: I've ran Blarrg's nmi timings ppu test and it immediately shows me "VBL PERIOD IS WAY OFF", I can't pinpoint why and is this related to the issue Im seeing in balloon fight logo maybe?

Attachment:
File comment: Balloon fight logo
bfight.png
bfight.png [ 562.25 KiB | Viewed 7890 times ]


Top
 Profile  
 
PostPosted: Mon May 06, 2019 10:51 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4211
NT fetch, AT fetch, Tile Fetch 1, Tile Fetch 2, output to the 16 pixel shift register.

First make sure those are all okay. First, the Address used for the Nametable fetch, and that the fetched value is correct. Then the address used for the Attribute table fetch, and the value is correct. These are probably okay.

Then validate the address used for the two bytes from CHR ROM, and the data fetched from CHR ROM.

Then the data is combined with the attribute data to get 16-color background pixels, and that data gets put onto the 16-pixel long shift register.

All I can say is validate the intermediate results.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Mon May 06, 2019 11:05 pm 
Offline

Joined: Mon Mar 11, 2019 10:56 pm
Posts: 15
@Dwedit thank you! Could you tell me some possible methods to check intermediate steps? Like what you would do? It's a lot of guesswork where I'm not sure where to start thus I've started to run Blarrg's PPU tests to see the deeper issue but I don't think they can help me much here. At least I see no recommendations for doing so. I thought to take an existing emulator and log out some intermediate PPU values, that could help but feels like a tedious task to juggle two projects at once


Top
 Profile  
 
PostPosted: Mon May 06, 2019 11:35 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 4208
Location: A world gone mad
This problem probably has nothing to do with VBlank length (read: amount of time), because you're actually drawing the title screen "mostly correctly". It's not entirely gobbledegook.

This problem does not appear to be mirroring related, otherwise you'd likely see nothing.

This problem really looks to be in how you're rendering data (I suspect this), or maybe a strange endian problem.

Balloon Fight is a CHR-ROM game, with 16KB PRG and 8KB CHR-ROM. That means the graphics are not "drawn" by 6502 code -- they are pre-done in CHR, and that CHR bank ends up in the pattern table (PPU RAM $0000-1FFF). If you're getting those wrong, then something much deeper is incorrect.

Try something logical, like: using a known working emulator with a good debugger and helper tools (read: Mesen, FCEUX), dump PPU RAM to disk while at the title screen, then have your emulator do the same at the same point. Now compare files and see if you can figure out why yours is wrong.

Another possible clue -- but not definitive, for the reasons I'm about to state -- is in the fact your palette is completely wrong. "A 1-PLAYER GAME, B 2-PLAYER GAME" etc. is supposed to be white. The "A" in "A 1-PLAYER GAME" is located (nametable-wise) in PPU RAM at $2248, and is supposed to be tile $0A in PPU RAM (address $10A0, i.e. upper half of the pattern table). This area of the screen should be using the attribute bytes from PPU RAM $23E2. Colour index #1 is what should be used for white (i.e. NES colour $30), taken from palette entry #0 (i.e. $3F00-3F03). If you haven't implemented palette lookups etc. then the colours being wrong is OK/acceptable/understood.

The complexity with threads like this is that your emulator is your code and nobody here understands it but you and only you. "Test ROMs" are not going to magically guarantee that those passing magically means you'll have a working NES emulator (I'm not sure why people think that either, but I digress). Lots of people here doing emulators have done things like run CPU instruction test ROMs and have them pass, but only to find things are completely wrong with where/how they were storing data (i.e. the ROM would pass fine, but things would functionally be incorrect).

One thing emulator authors do find universally helpful is to generate a log syntactically similar to http://www.qmtpro.com/~nes/misc/nestest.log -- which is from Nintendulator, known to be accurate, running the nestest ROM -- and then compare the log from their emulator to that log. This usually turns up several mistakes, the #1 problem being in adc/sbc emulation (if that turns out to be the case, see this post and the reference material within it).

When you find the problem, please be sure to post in this thread with a follow-up explaining the root cause. This tends to help other new emulator authors.


Top
 Profile  
 
PostPosted: Tue May 07, 2019 6:37 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4211
Let's start with something obvious, such as the Top Row of the "A".
In the nametable, it's at tile X=8, Y=18, or NT address 2248, and Attribute address 23E2. Screen coordinates X=64, Y=144.

It will be fetched 16 dots before the PPU outputs at scanline 144, dot 64.

So you should see NT address 2248 requested, fetch byte "0A" (the letter A), Attribute address 23E2 requested, fetch byte "00", graphic byte 1 fetched from 10A0, data 00111000, and graphic byte 2 fetched from 10A8, data 00000000.

Next step: extract the pixels from the graphic bytes.
Psuedocode:
Mask = 0x80
for x = 0, x < 8, x++
pixel = 0
if Byte1 & Mask, pixel += 1
if Byte2 & Mask, pixel += 2
pixel += Attribute Color (2 bits) * 4
Output[8 + x] = pixel
Shift Mask right 1.

'Output' is the 16 pixel wide shift register that outputs background graphics. When displaying from this, use the Fine X scroll value to determine which pixel to take from.
Palette lookup happens last.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Tue May 07, 2019 10:31 pm 
Offline

Joined: Mon Mar 11, 2019 10:56 pm
Posts: 15
thanks @Dwedit for an explanation! That sheds me a lot of light into the problem. I immediately went to see what is up in the main fetching loop and noticed the issue in attribute fetching code which now is fixed and looks like the attached image. So the strange tearing is now gone!
The only issue left is that everything seems tripled along the X axis which makes me thing that I miss some register clearing or something along the lines.
Attachment:
nesem.png
nesem.png [ 304.48 KiB | Viewed 7769 times ]


Top
 Profile  
 
PostPosted: Tue May 07, 2019 10:37 pm 
Offline

Joined: Mon Mar 11, 2019 10:56 pm
Posts: 15
@koitsu you've given a lot of details, thank you. I totally agree with you that I am too dependant on the tests however I see no way of coding something as complex as cycle perfect PPU in one go. Some intermediate results may be wrong and the output may yield nothing in return, so running some tests in automated fashion seems like a good idea to me. I also agree with you that VBL timing has nothing to do with my issue at least the view should be correct but maybe at the wrong vertical position.

I already do the nestest test and I pass it 100% though ignoring the PPU status and cycle so I thought my CPU is totally clear but can it be not the case that you mentioned ADC/SBC ? I will make sure to check those instructions out and see if that maybe helps.

I will of course post when I will find the issue :)
Thanks!


Top
 Profile  
 
PostPosted: Wed May 08, 2019 7:14 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4211
When you need to see intermediate results, you can use breakpoints for your debugger.
If you want to see what's going on at a particular screen position, you can do something vaguely like this:
Code:
if (x == 64 - 16 && y == 144)
{
   int dummy = 0;
}


The "int dummy = 0" line exists because Visual Studio will refuse to set breakpoints in C++ code in locations where there is no code.

Once you have reached your breakpoint, you can inspect your variables, and step through your code.

If you are unable to use a debugger, you can use "printf debugging", where you output information to the console. If you don't have a console, you can log data to a file instead.



The PPU problems seen here have NOTHING to do with the CPU at all.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Wed May 08, 2019 1:34 pm 
Offline

Joined: Sun Sep 19, 2004 11:07 pm
Posts: 172
The fact that it looks like every tile is splatted down 3-4x at a 2 pixel offset from each other is probably relevant.

If you are really trying for a cycle by cycle one, built around a set of shift registers, I'd suspect, in no particular order:

Splatting new bytes into the 16 bit buffer wrong
Corrupting the register while shifting
Dealing with x fine scroll wrong
Your x fine scroll solution interacting poorly with the increasing x coord across the screen
Trying something a bit too clever to avoid shifting each pixel
Not actually rendering pixel by pixel, but splatting tiles down, and accidentally splatting them multiple times
The coloration issues suggest something is also wrong with either the way you're handling attribute bits, or your palette mirroring is not quite right yet

I would suggest using a trick like Dwedit mentioned to break at the start of a character, and just looking at the data moving around for, say, the following 8 pixels


Top
 Profile  
 
PostPosted: Wed May 08, 2019 2:17 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4211
NES can't even display Yellow. Maybe your Blue channel is getting zeroed out.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Fri May 10, 2019 2:26 pm 
Offline

Joined: Mon Mar 11, 2019 10:56 pm
Posts: 15
So in the end I was the moron and finally debugged the issue into my... SWITCH statement where I forgot to add breaks, asserted stuff all over the place until clock started to assert which didn't match the main loop. I don't use switch statements, I prefer if-else pairs or just an array with callbacks as I code with JS and I thought well this makes for a perfect situation to use switch. So yeah, few evenings wasted on here and a super hard lesson learned.

On the positive size, BG rendering is much more clear now :D


Top
 Profile  
 
PostPosted: Wed Jun 05, 2019 11:53 pm 
Offline

Joined: Mon Mar 11, 2019 10:56 pm
Posts: 15
I just wanted to make an update on the issue as I've fixed it. This was totally a CPU bug cause by a faulty LSR instruction. Nestest why did you betray me... :D

// below is fixed code
// this.P[0] &= 0b11111110;
// this.P[0] |= (val & 1);

// below is old not working code
this.P[0] &= 0b11111110 | (val & 1); // this one doesn't work
^------- that was the problem


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group