Simple ROM works as expected on FCEUX but not on Mesen
Moderator: Moderators
Simple ROM works as expected on FCEUX but not on Mesen
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.
"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
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.
"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
- Attachments
-
- Sprite 2 disabled.nes
- (64.02 KiB) Downloaded 171 times
-
- Sprites test.nes
- (64.02 KiB) Downloaded 178 times
Re: Simple ROM works as expected on FCEUX but not on Mesen
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.
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.
Re: Simple ROM works as expected on FCEUX but not on Mesen
Oh, good to know!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.
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.
I see! Well, guess there's a reason why games generally use OAMDMAlidnariq 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.
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
Re: Simple ROM works as expected on FCEUX but not on Mesen
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.lidnariq wrote:Mesen picks a random bank on boot (unless he's changed that?), and your second bank is almost entirely 0.
Re: Simple ROM works as expected on FCEUX but not on Mesen
That's the thing! I had that option disabled and it defaulted to bank 0 as expected.Sour wrote: [...] but if you're getting a black screen in 0.9.6, it's most likely enabled)
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.
Re: Simple ROM works as expected on FCEUX but not on Mesen
Just to explicitly explain this:Thecoolestnerdguy wrote:but all writes to OAM seem to be ignored, at least according to the memory viewer.
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)
Re: Simple ROM works as expected on FCEUX but not on Mesen
Ah, so, Mesen's the one out of the two that correctly implements it, as you'd expectlidnariq wrote: So that's why it worked when you wrote one sprite, but not two.
Thanks for clarifying, it does make a lot more sense to me now
Re: Simple ROM works as expected on FCEUX but not on Mesen
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.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 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
Re: Simple ROM works as expected on FCEUX but not on Mesen
Haha, you've got a point.Sumez wrote: Don't worry about banks on your first test project, though. Just make it NROM
Since I plan on using ANROM for future projects tho, I wanted to try to figure out how it works too
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?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.
Re: Simple ROM works as expected on FCEUX but not on Mesen
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)
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)
Re: Simple ROM works as expected on FCEUX but not on Mesen
It'd have to either run from RAM or be at the same place in all banks.
Re: Simple ROM works as expected on FCEUX but not on Mesen
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.
- 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
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. )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.
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.