Handling Writing to ROM or out of range addresses

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

ace314159
Posts: 27
Joined: Tue Apr 17, 2018 3:40 am

Handling Writing to ROM or out of range addresses

Post by ace314159 »

I'm not sure if it is a bug with some logic with my emulator or if games actually edit ROM or access out of range address, expecting some behavior which is not implemented.

When running Super Mario Bros, I see that the code tries to edit the pattern tables. When running Ice Climber, I see it trying to access a VRAM address greater than 0x4000. Both occur when writing to 0x2007 and both cause my emulator to crash.
This is how I handle a write to 0x2007:

Code: Select all

mem.setVRAM8(this->currentVramAddr++, this->DATA);
this->currentVramAddr += ((this->CTRL >> 2) & 0x1) * 31; // Ads extra 31 if bit 2 is set
Is this supposed to happen in those games or is something wrong with my implementation? My CPU passes all the tests from nestest and instr_test-v5. My PPU passes all of blargg's tests (blargg_ppu_tests_2005.09.15b) except for vbl_clear_time if I allow the code to edit CHR.

Another interesting thing to note is that everything works perfectly fine in Release mode in Visual Studio. Both Super Mario Bros and Ice Climber seem to work mostly fine, except for some sprites being all black, but I'm pretty sure that it is unrelated to this issue.
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Handling Writing to ROM or out of range addresses

Post by pubby »

I believe the PPU uses 14 bit addresses, so going past $4000 wraps around to $0000.

Writing to cartridge memory depends on the mapper. With NROM it's a nop.

BTW an emulator should never crash from bad user programs. One needs to handle every address.
ace314159
Posts: 27
Joined: Tue Apr 17, 2018 3:40 am

Re: Handling Writing to ROM or out of range addresses

Post by ace314159 »

BTW an emulator should never crash from bad user programs. One needs to handle every address.
Yeah, you're right. I made it overflow after reaching 0x4000 and made writing to ROM a nop.

I also figured out why it was working in Release, but not Debug. It was because I didn't initialize the PPU registers, and they got set to values that caused an NMI on the first cycle, stopping the CPU from running initialization code and messing everything up. I simply initialized them to 0 and made the changes you suggested and it worked! Thanks for the help!

However, on the scrolling page on the wiki, it says that the VRAM address is 15 bits long. Is that talking about a different address?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Handling Writing to ROM or out of range addresses

Post by tepples »

Bits 14-12 of the VRAM address have a different meaning between rendering on the one hand and video memory access through $2007 on the other. During rendering, bits 14-12 represent fine Y scroll, which is reflected as PA2-0 of pattern table fetches. During video memory access through $2007, bit 14 is ignored, and bits 13-12 represent actual PA13-12.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Handling Writing to ROM or out of range addresses

Post by koitsu »

ace314159 wrote:I also figured out why it was working in Release, but not Debug. It was because I didn't initialize the PPU registers, and they got set to values that caused an NMI on the first cycle, stopping the CPU from running initialization code and messing everything up. I simply initialized them to 0 and made the changes you suggested and it worked! Thanks for the help!
Read closely (not all are zero), and also understand the difference between power-on (power cycle) and reset:
https://wiki.nesdev.com/w/index.php/PPU_power_up_state

Similar applies to CPU:
https://wiki.nesdev.com/w/index.php/CPU_power_up_state
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Handling Writing to ROM or out of range addresses

Post by rainwarrior »

I've added a small note to the Wiki. Would this have helped understanding?
https://wiki.nesdev.com/w/index.php?tit ... ldid=15253
ace314159
Posts: 27
Joined: Tue Apr 17, 2018 3:40 am

Re: Handling Writing to ROM or out of range addresses

Post by ace314159 »

tepples wrote:Bits 14-12 of the VRAM address have a different meaning between rendering on the one hand and video memory access through $2007 on the other. During rendering, bits 14-12 represent fine Y scroll, which is reflected as PA2-0 of pattern table fetches. During video memory access through $2007, bit 14 is ignored, and bits 13-12 represent actual PA13-12.
Thank you! This clears everything up!
koitsu wrote: Read closely (not all are zero), and also understand the difference between power-on (power cycle) and reset:
https://wiki.nesdev.com/w/index.php/PPU_power_up_state

Similar applies to CPU:
https://wiki.nesdev.com/w/index.php/CPU_power_up_state
So if I'm understanding this right, on a power cycle, I set everything but 0x2002 to 0 and set 0x2002 to 0xA0. What I don't understand is the diference between a power cycle and reset. I couldn't find an explanation on the page or through a Google search. Is a reset just a way to change the ROM without resetting all of the registers, and on a physical device without turning it on and off?
rainwarrior wrote:I've added a small note to the Wiki. Would this have helped understanding?
https://wiki.nesdev.com/w/index.php?tit ... ldid=15253
This would have definitely helped!
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Handling Writing to ROM or out of range addresses

Post by rainwarrior »

ace314159 wrote:What I don't understand is the diference between a power cycle and reset. I couldn't find an explanation on the page or through a Google search. Is a reset just a way to change the ROM without resetting all of the registers, and on a physical device without turning it on and off?
The NES and famicom have two separate buttons: POWER and RESET.

The power switch removes power from the system and turns it off. The reset button doesn't turn anything off, it just restarts the software from the beginning.

A lot of stuff that was happening, most contents of RAM, etc. is preserved across a reset that is not preserved when you power off. Some games will behave differently for a reset than for powering off and on, though I think most games will be the same either way.
ace314159
Posts: 27
Joined: Tue Apr 17, 2018 3:40 am

Re: Handling Writing to ROM or out of range addresses

Post by ace314159 »

So you can't change the game or cartridge when you hit RESET? It's just to restart the current game?
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Handling Writing to ROM or out of range addresses

Post by rainwarrior »

You can yank a cartridge out of your NES while it's on, if you want, but that's not really something I've ever seen emulated. You can also do that while holding reset, I suppose?

If you pull a cartridge out of the machine while it's powered on, the system will more or less just crash. You can stick a new game in without powering it off, but to get it to run you will need to press reset (or power off and on).

There's some obscure possibilities involved with this, but emulators can usually do the same thing in a more convenient way with game genie codes or other methods.
ace314159
Posts: 27
Joined: Tue Apr 17, 2018 3:40 am

Re: Handling Writing to ROM or out of range addresses

Post by ace314159 »

That's definitely out of the scope of my emulator, but I understand what a power cycle and reset does now. Thanks for the help!
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Handling Writing to ROM or out of range addresses

Post by koitsu »

ace314159 wrote:So if I'm understanding this right, on a power cycle, I set everything but 0x2002 to 0 and set 0x2002 to 0xA0.
Don't miss the part about the PPU RAM contents, specifically the nametable regions. "Mostly" in this case can probably be interpreted as, for emulation purposes, "fill completely with".
ace314159
Posts: 27
Joined: Tue Apr 17, 2018 3:40 am

Re: Handling Writing to ROM or out of range addresses

Post by ace314159 »

I'll make sure to remember that.

Looking at it again, I noticed that for OAM and CHR RAM it mentions a "pattern". What does this mean?
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Handling Writing to ROM or out of range addresses

Post by rainwarrior »

ace314159 wrote:Looking at it again, I noticed that for OAM and CHR RAM it mentions a "pattern". What does this mean?
Hmm, that seems misleading. We probably shouldn't suggest that there is some specific pattern these boot with.

They are unreliable. You can implement it as powering on all 0, all FF, all random, doesn't really matter.

There are usually some pattern tendencies to any particular RAM's power on, but it will vary a bit from time to time your turn it on.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Handling Writing to ROM or out of range addresses

Post by tepples »

I've replaced most of the "pattern" stuff in the article with "unspecified values".
Post Reply