It is currently Sat Oct 21, 2017 8:52 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Fri Dec 06, 2013 6:17 am 
Offline

Joined: Wed Dec 04, 2013 1:34 am
Posts: 7
Location: Germany
Hi,

I didn't know if I should open a new topic for this or reuse my old one here. But because of the fact that this problem is "standalone" I opend a new topic. I hope this is okay for you.

For those who didn't read the other topic: I'm developing an nes emulator. Currently I'm working on the background. I think it looks really good; scrolling in x direction also works pretty nice. The colors arn't so hard - there is no problem. Oh wait:

While I'm developing I test my result with Super Mario Bros (1). Only to see if everything works. So you know, that the "general information" (time left, world etc.) is displayed in the top area of the screen. As you can see here only the first nametable displays this data. I figured out, that if the "camera" scrolls into the second nametable (0x2400) it "switches" for the first 31 scanlines the nametable to the first one (0x2000) containing this information bar; the rest of the screen is then rendered from the second nametable. Here some debug output from my program:

Code:
...
Nametable used: 0x2400 for scanline 238
Nametable used: 0x2400 for scanline 239
Nametable used: 0x2000 for scanline 0
Nametable used: 0x2000 for scanline 1
...
Nametable used: 0x2000 for scanline 31
Nametable used: 0x2400 for scanline 32
...


So now the problem: if my emulator runs normal everytime Mario is in the second nametable the information bar is flickering. Because sometimes the nametable is not set to 0x2000 for the first 31 scanlines:

Code:
Nametable used: 0x2400 for scanline 238
Nametable used: 0x2400 for scanline 239
Nametable used: 0x2400 for scanline 0
...
Nametable used: 0x2400 for scanline 29
Nametable used: 0x2400 for scanline 30
Nametable used: 0x2400 for scanline 31


So have you any idea where I made a mistake?

The used nametable is determined in my program every scanline with a statement like this:
Code:
       
        int NAMETABLE = 0x2000;
       switch (readCPURAM(0x2000) & 3) {
       case 3:
          NAMETABLE = 0x2c00;
          break;
       case 2:
          NAMETABLE = 0x2800;
          break;
       case 1:
          NAMETABLE = 0x2400;
       }

I think that this precludes a mistake in my emulator, because the program is responsible for maintaining the contents in register 0x2000. But this bug isn't present in other emulators - that is a hint for a bug in my emulator ...

Greetings,
mrhyde


Top
 Profile  
 
PostPosted: Fri Dec 06, 2013 6:31 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10065
Location: Rio de Janeiro - Brazil
Your approach to scrolling (yes, setting the name table is a form of scrolling) is not correct, and might be the reason you're having trouble. There are 3 registers that affect the PPU's internal address register: $2006, $2005 and the 2 lowest bits of $2000. The PPU doesn't keep track of "name tables" per se (specially considering that if the scroll is anything but 0 you end up with more than one name table rendered), it only has this internal address register that it uses to read data from VRAM.

Take a look at the infamous "The skinny on NES scrolling" document and you'll see how each of these writes ($2006, $2005, $2000) affect the address register (hint: there's also a temporary register, and at specific moments - indicated in the document - the temporary register is copied to the actual register). This register is used by the PPU to fetch data, so there are some automatic increments and resets it goes through (also pointed out in the document) as the image is rendered. The closer you stay to this model, the higher your chances of getting scrolling working correctly.

EDIT: guess we can still try to figure out what's wrong with your current implementation (even though the correct implementation would be based on the information above). So, I see that your debug informationg jumps from scanline 239 to scanline 0... are you emulating the VBlank scanlines at all? They might not be visible, but the PPU keeps working until scanline 261 before jumping back to scanline 0. It's during this time (VBlank) that games do all their PPU housekeeping, like sending data to VRAM and updating registers (including the scroll, which is often the very last operation done during VBlank). If you're not emulating this period, that might be why the name table isn't set correctly at scanline 0.


Top
 Profile  
 
PostPosted: Fri Dec 06, 2013 9:02 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1389
Another minor nitpick:

mrhyde wrote:
Code:
readCPURAM(0x2000)


Most of the PPU (and APU) registers are not readable - what you should be doing is setting variables during writes and then reading those variables in the necessary places.

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
PostPosted: Fri Dec 06, 2013 9:25 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10065
Location: Rio de Janeiro - Brazil
Oh yeah, Quietust has a good point. All access to memory-mapped registers is redirected, there's no RAM to store the values written or to read previously written values from. What you should be doing is intercepting the writes at the moment they happen and update the system's state to reflect the new settings, and for the few registers that are readable, you should intercept the reads and assemble the return value from the current system state.


Top
 Profile  
 
PostPosted: Sat Dec 07, 2013 3:03 am 
Offline

Joined: Wed Dec 04, 2013 1:34 am
Posts: 7
Location: Germany
Hi,

tokumaru wrote:
Most of the PPU (and APU) registers are not readable - what you should be doing is setting variables during writes and then reading those variables in the necessary places.
tokumaru wrote:
... and update the system's state to reflect the new settings ...

oh yes. You are totally right. I haven't thought about the two registers (v and t) of the PPU yet and this was my mistake. I implemented the behavior of this two registers as described in the wiki and now it works pretty well. :D :D

Thank you for your help!

Greetings,
mrhyde

P.S.: do you know a game or rom image that I can use to test vertical scrolling and which only uses NROM (no mapper) and is in the iNES file format? I know this are many conditions, but memory mappers arn't so important for me than getting my emulator running ...


Top
 Profile  
 
PostPosted: Sat Dec 07, 2013 3:20 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1020
Vertical Scrolling? Ice Climber.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Sat Dec 07, 2013 7:58 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10065
Location: Rio de Janeiro - Brazil
If you want to considerably broaden the range of games you can use for testing, you could consider implementing mapper 2 (UNROM). It's incredibly simple to implement and a significant number of games use it.


Top
 Profile  
 
PostPosted: Sat Dec 07, 2013 10:25 am 
Offline

Joined: Thu Sep 15, 2005 9:23 am
Posts: 1194
Location: Behind you with a knife!
tokumaru wrote:
If you want to considerably broaden the range of games you can use for testing, you could consider implementing mapper 2 (UNROM). It's incredibly simple to implement and a significant number of games use it.


UNROM and CNROM are like 1 line of code each. AxROM 2 lines.

_________________
http://www.jamesturner.de/


Top
 Profile  
 
PostPosted: Sat Dec 07, 2013 2:53 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10065
Location: Rio de Janeiro - Brazil
WedNESday wrote:
UNROM and CNROM are like 1 line of code each. AxROM 2 lines.

If you have prepared for implementing mappers, that is... If not you might have some pointer work to do.


Top
 Profile  
 
PostPosted: Sun Dec 08, 2013 3:40 am 
Offline

Joined: Thu Sep 15, 2005 9:23 am
Posts: 1194
Location: Behind you with a knife!
tokumaru wrote:
WedNESday wrote:
UNROM and CNROM are like 1 line of code each. AxROM 2 lines.

If you have prepared for implementing mappers, that is... If not you might have some pointer work to do.


Of course. They could use memcpy just to start off with.

_________________
http://www.jamesturner.de/


Top
 Profile  
 
PostPosted: Tue Sep 05, 2017 2:12 am 
Offline

Joined: Mon Sep 04, 2017 8:02 pm
Posts: 1
mrhyde wrote:
..... I haven't thought about the two registers (v and t) of the PPU yet and this was my mistake. I implemented the behavior of this two registers as described in the wiki and now it works pretty well. :D :D
...

Hello,

I try to fix a bug relate to flicker. In detail, when i move the main character by up/down keyboard then the flicker line appear on edge of screen.
it's no matter if i use right/left keyboard to move right or left. :roll:
could you plz give me any suggestion? thanks :)


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 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