It is currently Sat Dec 15, 2018 6:38 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Sun Sep 02, 2018 11:59 am 
Offline

Joined: Mon Aug 01, 2016 4:01 am
Posts: 18
Location: Brinstar, Zebes
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 71 times
Sprites test.nes [64.02 KiB]
Downloaded 72 times
Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 12:06 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7825
Location: Seattle
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.


Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 12:26 pm 
Offline

Joined: Mon Aug 01, 2016 4:01 am
Posts: 18
Location: Brinstar, Zebes
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


Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 2:05 pm 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 531
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.


Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 3:51 pm 
Offline

Joined: Mon Aug 01, 2016 4:01 am
Posts: 18
Location: Brinstar, Zebes
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.


Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 4:35 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7825
Location: Seattle
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)


Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 4:43 pm 
Offline

Joined: Mon Aug 01, 2016 4:01 am
Posts: 18
Location: Brinstar, Zebes
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


Top
 Profile  
 
PostPosted: Mon Sep 03, 2018 4:27 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 833
Location: Denmark (PAL)
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 :)


Top
 Profile  
 
PostPosted: Mon Sep 03, 2018 4:30 pm 
Offline

Joined: Mon Aug 01, 2016 4:01 am
Posts: 18
Location: Brinstar, Zebes
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?


Top
 Profile  
 
PostPosted: Mon Sep 03, 2018 4:40 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7825
Location: Seattle
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)


Top
 Profile  
 
PostPosted: Mon Sep 03, 2018 4:41 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20876
Location: NE Indiana, USA (NTSC)
It'd have to either run from RAM or be at the same place in all banks.


Top
 Profile  
 
PostPosted: Mon Sep 03, 2018 5:35 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11012
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Sep 03, 2018 5:58 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7017
Location: Canada
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 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