It is currently Mon Oct 16, 2017 2:54 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 76 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
PostPosted: Wed Jan 08, 2014 10:58 pm 
Offline

Joined: Mon Apr 01, 2013 11:17 pm
Posts: 437
Super Mario Bros is on the list of tricky-to-emulate games for having issues very similar to what you're describing.


Top
 Profile  
 
PostPosted: Wed Jan 08, 2014 11:20 pm 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
"Super Mario Bros. is probably the hardest game to emulate among the most popular NROM games, which are generally the first targets against which an emulator author tests his or her work. It relies on JMP indirect, correct palette mirroring (otherwise the sky will be black; see PPU palettes), sprite 0 detection (otherwise the game will freeze on the title screen), the 1-byte delay when reading from CHR ROM through $2007 (see The PPUDATA read buffer), and proper behavior of the nametable selection bits of $2000 and $2006.[1] In addition, there are several bad dumps floating around, some of which were ripped from pirate multicarts whose cheat menus leave several key parameters in RAM."

Thank you, Joe! Describes my situation exactly. I'll forget about SMB until I get Donkey Kong completely working.

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 7:48 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3940
Devil World is slightly harder to emulate, since it's the first game to use split screen vertical scrolling.

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


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 8:37 am 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
I've done my PPU timing exactly how the diagram shows, which is important for things like splitscreen right? Does the game just count cycles from vBlank and change the scroll half way through the scanline?

And good news, I got sprites working last night! Was much easier than I thought it would be. I haven't done flipping of sprites yet, but that should only take a couple minutes. Then on to controls :D

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 8:53 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19081
Location: NE Indiana, USA (NTSC)
Scroll changes between one scanline and the next are common. Scroll changes halfway through a scanline require much more precise synchronization to the raster, and I'm not aware of any commercial NES game with tight enough timing to do that stably. Some games, such as Super Mario Bros. 3 and Mega Man 3, slightly mistime a scroll change, causing a single glitched scanline with OK scanlines below it.


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 9:54 am 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
So that's not how splitscreen works? I don't know anything about scrolling yet. Once I do controls, I'll do scrolling. Is Excitebike a good one to start with? My rom gets to the demo screen and doesn't show sprites, but I'm guessing that's because I haven't added scrolling yet.

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 10:10 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19081
Location: NE Indiana, USA (NTSC)
I was confused by your use of "half way through the scanline". Split screen scrolling in NES games works by changing the scroll value mid-screen, usually in the 64-dot (21-cycle) period between one scanline and the next. Doing so mid-screen allows scrolling each horizontal strip separately. A game would have to change the scroll value mid-scanline in order to have vertical strips, and MMC5 is the only mapper I know of on NES that's capable of that.


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 11:03 am 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
Alright, that's what I thought. Getting the timing right for that is gonna suck.

And the big day's finally here guys! I added controls and I can now play games on my emulator :D
I was too lazy to fix the leftmost 2 tiles. It's just a matter of adding an if statement to check the dot an increment the scanline. What I don't understand is, why does my sprite rendering cause artifacts on the rightmost column of pixels? I'm rendering my sprites at the exact correct coordinates. I checked this with Nintendulator. When both emulators are maximized, they line up perfectly. Here's a screen.

Image

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 6:36 pm 
Offline

Joined: Wed Mar 31, 2010 12:40 pm
Posts: 207
janzdott wrote:
What I don't understand is, why does my sprite rendering cause artifacts on the rightmost column of pixels? I'm rendering my sprites at the exact correct coordinates. I checked this with Nintendulator. When both emulators are maximized, they line up perfectly.


IIRC sprites with X=$FF have the bit planes masked to $00 on load (dots 262, 264, 270, 272, 278, 280, 286, 288, 294, 296, 302, 304, 310, 312, 318, 320), that would cause those sprites to be rendered transparently. Either do that or refuse to output sprite pixels on that dot, and don't allow sprite zero collisions for that dot either.

As far as the first two tiles goes, are you sure that the tile pre-fetch (321-337) are being handled properly? Both fetches increment the 'x' bits of the counter, and both happen after the 'y' bits have been reset to the latched values.


Top
 Profile  
 
PostPosted: Thu Jan 09, 2014 11:07 pm 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
Ah, that makes sense. I'll add a check to make sprites with an x position of 0xFF clear.

And yeah, it's doing the nametable and attribute fetching correctly, where it wraps around to the next scanline. I just didn't do the same with the pattern fetches. That's why it draws the correct tiles on the left, they're just 1 pixel down from where they should be. I haven't fixed that yet because of laziness on my part. I was too excited to get working on sprites :D

I just fixed both those problems, so graphics should be 100% correct now. I'm going to add scrolling next. I'm not understanding it very well at the moment. I'm still learning about all this stuff as I go.

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Fri Jan 10, 2014 3:53 pm 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
I have a problem that I can't figure out, and it's driving me absolutely crazy. :x If anyone could help me, I would very very much appreciate it.

I started emulating the v, t, x and w registers for the PPU. I'm not yet using them during rendering at all. I'm only using them when reading or writing $2000, and writing $2005 and $2006. My writes to the PPU registers set the values of v, t, x and w correctly. I am positive of this.

Since the second write to $2005 (PPU scroll) doesn't set v equal to t, PPU scroll must be written to before rendering, and the PPU must set v equal to t before rendering. This happens at dot 304 of the pre-render scanline. So far, this is the only time I'm changing the value of v during rendering. When entering the first level of a game, new nametable data needs to be written. The problem is, the PPU changes the value of v on the pre-render scanline, then the games AREN'T writing a new address to $2006 after rendering, before they start writing data to $2007. It's like they are expecting v to not change. So parts of the title screen are not being overwritten. If I don't set the v equal to t on the pre-render scanline, the problem goes away. This happens with every game I try.

I have verified 100% that they are NOT writing a new address to $2006 before they start writing to $2007. I have also verified that they aren't writing to $2007 outside of vBlank. They write to PPU scroll, which changes the value of t. Then on the pre-render scanline, the PPU sets v equal to t. After that frame is rendered, and vBlank starts, the games start writing to $2007, without writing to $2006 first. So the address being written to isn't correct.

So my question: At the start of vBlank, does the PPU restore the value of v to what it was before it was changed on the pre-render scanline? That's the only way I can make sense of this... I haven't seen that mentioned anywhere in the wiki.

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Fri Jan 10, 2014 4:00 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19081
Location: NE Indiana, USA (NTSC)
The PPU doesn't set v equal to t when rendering is turned off in $2001. When loading a level, a game will keep rendering off until an entire screen has been constructed, then set the scroll and turn on rendering before the pre-render line.


Top
 Profile  
 
PostPosted: Fri Jan 10, 2014 9:57 pm 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
Here's what the problem is. I was unable to solve it correctly, but I fixed it temporarily with a hack.

When leaving the title screen and entering the first level, the games must replace the nametable data. They don't finish writing the nametable data before the end of vBlank. Once rendering starts, the value of the v register changes. At the end of the frame, when vBlank starts again, the games try to continue writing nametable data. Since v changed during rendering, the nametable data is written to incorrect addresses. This is happening with every game I try, now that I'm emulating v, t, x and w.

I tried slowing my PPU down by a factor of 3, and the CPU still wrote nametable data past vBlank. It would be okay if it set the address again when it resumes, but it doesn't.

I have no idea how to fix this. What I did was add a second v register, which is used only by the $2006 and $2007 registers. That way, the address written to by $2007 doesn't change after rendering a frame. That fixed the problem temporarily. If anyone has any ideas why this is happening, I would be glad to hear them.

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
PostPosted: Fri Jan 10, 2014 10:25 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19081
Location: NE Indiana, USA (NTSC)
"Second V register" is the solution adopted by the ColecoVision, MSX, and Master System, not the NES. The correct solution for the NES is just to skip setting v = t on the prerender line if rendering is turned off.


Top
 Profile  
 
PostPosted: Fri Jan 10, 2014 11:38 pm 
Offline
User avatar

Joined: Fri Oct 04, 2013 11:56 pm
Posts: 42
Location: Wisconsin
I do only set v on the pre-render line when rendering is on. I have all of my rendering code (except for the vBlank flag set/reset and the NMI interrupt) inside an if statement that checks if rendering is enabled. Rendering is enabled if bits 3 or 4 are set in PPUMASK. It still increments the dot and scanline, and geneterates NMIs normally if rendering is off. Is there something about rendering being on/off that I'm missing?

_________________
Current emulator progress http://forums.nesdev.com/viewtopic.php?f=3&t=10558


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 76 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Bing [Bot] and 7 guests


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