Simple ROM works as expected on FCEUX but not on Mesen

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
Trirosmos
Posts: 50
Joined: Mon Aug 01, 2016 4:01 am
Location: Brinstar, Zebes
Contact:

Simple ROM works as expected on FCEUX but not on Mesen

Post by Trirosmos »

Howdy! :)

I'm trying to teach myself the basics of NES programming, and my first objective was to make a couple of sprites move around.
I got one sprite to display and wrap around the screen, but once I tried to have two sprites on screen Mesen (0.9.6) only displayed a black screen. FCEUX (2.2.3) however still worked as expected.

Looking at OAM on Mesen, it stayed static despite being written to, which doesn't seem quite right, unless I'm missing something.

Image

"Sprite 2 disabled.nes" has the writes to OAM relative to the second sprite commented out and works as expected on both emulators whereas "Sprites test.nes" is the ROM I'm trying to fix.

I'm probably missing something obvious, so, please, be patient with this noob :lol:
Attachments
Sprite 2 disabled.nes
(64.02 KiB) Downloaded 171 times
Sprites test.nes
(64.02 KiB) Downloaded 178 times
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by lidnariq »

First problem: You're using ANROM, and its power-up state is not guaranteed. Mesen picks a random bank on boot (unless he's changed that?), and your second bank is almost entirely 0.

Second problem: You basically cannot safely use $2003 and $2004 on the 2C02G that the majority of Famicoms and US NESes had; you more-or-less have to use ($2003 and) $4014.

There are very specific and narrow conditions under which you can use $2003 and $2004, but unless you know you're in a situation where that's true for you, it's best to not try.
Trirosmos
Posts: 50
Joined: Mon Aug 01, 2016 4:01 am
Location: Brinstar, Zebes
Contact:

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by Trirosmos »

lidnariq wrote:First problem: You're using ANROM, and its power-up state is not guaranteed. Mesen picks a random bank on boot (unless he's changed that?), and your second bank is almost entirely 0.
Oh, good to know!
I had wondered what the default behavior was but since these ROMs seemed to always work on the emulators I tested, I just assumed it defaulted to bank 0.
lidnariq wrote: There are very specific and narrow conditions under which you can use $2003 and $2004, but unless you know you're in a situation where that's true for you, it's best to not try.
I see! Well, guess there's a reason why games generally use OAMDMA :P
Using $2004 didn't seem like the quick and dirty way of updating OAM without reason, then...

Thanks for the fast response! I think that probably answers the questions I had for now :D
Sour
Posts: 891
Joined: Sun Feb 07, 2016 6:16 pm

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by Sour »

lidnariq wrote:Mesen picks a random bank on boot (unless he's changed that?), and your second bank is almost entirely 0.
0.9.6 adds a "Randomize mapper power-on state" option in Emulation->Advanced which randomizes the startup state for most common mappers (this is disabled by default though, but if you're getting a black screen in 0.9.6, it's most likely enabled). For homebrew dev, keeping this option on is recommended, though.
Trirosmos
Posts: 50
Joined: Mon Aug 01, 2016 4:01 am
Location: Brinstar, Zebes
Contact:

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by Trirosmos »

Sour wrote: [...] but if you're getting a black screen in 0.9.6, it's most likely enabled)
That's the thing! I had that option disabled and it defaulted to bank 0 as expected.
Everything seemed to run fine on the CPU side, looking at the debugger, but all writes to OAM seem to be ignored, at least according to the memory viewer.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by lidnariq »

Thecoolestnerdguy wrote:but all writes to OAM seem to be ignored, at least according to the memory viewer.
Just to explicitly explain this:
On the 2C02G
if OAMADDR is 8 or greater when rendering starts
the eight bytes at (OAMADDR & 0xF8) are copied over the first 8 bytes.
So that's why it worked when you wrote one sprite, but not two.

The klever thing that works is if you only need 1¾ sprites (you can't update the second sprite's X coordinate, because you can safely write 7 values)
Trirosmos
Posts: 50
Joined: Mon Aug 01, 2016 4:01 am
Location: Brinstar, Zebes
Contact:

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by Trirosmos »

lidnariq wrote: So that's why it worked when you wrote one sprite, but not two.
Ah, so, Mesen's the one out of the two that correctly implements it, as you'd expect :P
Thanks for clarifying, it does make a lot more sense to me now :D
User avatar
Sumez
Posts: 919
Joined: Thu Sep 15, 2016 6:29 am
Location: Denmark (PAL)

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by Sumez »

Thecoolestnerdguy wrote: I had wondered what the default behavior was but since these ROMs seemed to always work on the emulators I tested, I just assumed it defaulted to bank 0.
The trick is to never expect any "default behavior" with computer hardware. Any register and ram content can be any value at power on, and there's no way to reliably predict it.
The only reliable approach is to only depend on the static banks, and use that to initialize everything else to the states you want as the first thing in your reset vector.

Don't worry about banks on your first test project, though. Just make it NROM :)
Trirosmos
Posts: 50
Joined: Mon Aug 01, 2016 4:01 am
Location: Brinstar, Zebes
Contact:

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by Trirosmos »

Sumez wrote: Don't worry about banks on your first test project, though. Just make it NROM :)
Haha, you've got a point.
Since I plan on using ANROM for future projects tho, I wanted to try to figure out how it works too :)
Sumez wrote: The only reliable approach is to only depend on the static banks, and use that to initialize everything else to the states you want as the first thing in your reset vector.
Question: since ANROM switches the entire 32KB window at once, I believe the routine that switches banks would have to run from RAM, is that right?
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by lidnariq »

Mappers with 32KiB banking can be assembled in a way with a logical fixed bank, by having the exact same data in the same place in every bank.

For example, as part of Memblers's GTROM kit, he has a tool to convert an UNROM game into something compatible with GTROM by dividing it up into 16 KiB banks (01234567) and then recombining them (0717273747576777)
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by tepples »

It'd have to either run from RAM or be at the same place in all banks.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by tokumaru »

Even if the bankswitch code is in RAM, you need to have a "virtual" fixed bank (i.e. same code in the same place in all banks) for initialization. I personally prefer to have the bankswitch code in this "virtual" fixed bank too.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Simple ROM works as expected on FCEUX but not on Mesen

Post by rainwarrior »

tokumaru wrote:Even if the bankswitch code is in RAM, you need to have a "virtual" fixed bank (i.e. same code in the same place in all banks) for initialization. I personally prefer to have the bankswitch code in this "virtual" fixed bank too.
I agree this is a good way to do it, and it's what I'd normally do, myself. (I will share some example code sometime soon that demonstrates this. ;))

Though if you wanna get nuts, technically you don't actually need initialization in the same place in all banks. You can have a different RESET vector in each bank if you need it. Even the bankswitch code doesn't have to be at the same place in all banks, whenever you do that store instruction to store the bank, the next instruction will be fetched from the new bank, whatever happens to be at that particular location. Putting the same routine in all banks makes this easy, but you can put the code you intend to run in the new bank right there where it switches. ;) This would probably be bad organization for most situations though.
Post Reply