I didn't really want to derail any recent threads with this question, so I figured I'd just start a new one to ask.
What exactly is a fixed bank?
Some mappers put a certain portion of the physical rom (say the top 16kB) permanently in a specific portion of the NES's accessible memory (say the last 16kB, as in UNROM).
Okay, so does this mean that you would typically put things like subroutines that you use alot in those banks? Or is this for CHR data only? I know nothing of how bankswitching for PRG works, and have only recently dabbled with CHR bankswitching.
Thanks : )
This is what you want to do when dealing with banks:
Fixed bank should contain:
-Your NMI
-Procedures you may want to call at any time
-Procedures for loading in the stuff from the swappable banks. For example, in my game I've got a procedure that handles the level loading. Now, that thing will swap out the banks when I want to grab in things such as the level data itself, the graphical data, etc. But the actual loading of all that is all handled by the procedure in the fixed bank.
You never want to go to some procedure in a swappable bank and the, while in that procedure, swap to a new bank cause you'll have big problems.
Yeah basically fixed bank should contain all interrupt code (Reset, NMI, and IRQ). If for example you have one bank dedicated to level data, it's good to have the routine to load level data in that bank as well, but if your level data is spawned across multiple banks, then it should be easier to have all the code for loading it in the fixed bank I guess. Else you'll have to call a routine in the fixed bank that switch the bank where your routine is, calls it, restore the old bank and return, and things like that slows things down a lot.
However, all of this is major trouble, that's why I do my first game using CNROM (I only do CHR bankswitching, which is a lot simpler and more intuitive).
And you definitley don't want to put CHR data in a fixed ROM bank. In CHR-RAM boards, once the tiles have been sent to the PPU you don't have to keep them mapped anymore.
Large amounts of data in general should be kept separated from code, because they are typically accessed at very predictable times, so you can map them in, use them, and map the next thing.
The fixed bank should contain your main program and other pieces of code that are used very often. Swappable banks can contain level maps, music engine and data (since the sound engine is usually called only once per frame), graphic data, code for specific game sections (such as bonus stages which differ from the main gameplay)...
Alrighty, so it sounds pretty much like what I thought : )
About the music in a different bank, though. How does that work? If all music was in one bank, does that generally mean that you would call that bank right before the play code, and then right after the play code go back to whatever bank you are working with at the time?
Yeah, that's what it sounds like to me.
Once you run the music code, the bank containing music data no longer needs to be mapped to the CPU address space because it isn't being accessed. You could safely swap that bank out until the next frame when it's needed again.
The DMC complicates music bankswitching if you're using it. The sequence data and PSG instrument data can go in any bank and get mapped out whenever the music code isn't running, but the currently playing wave needs to stay mapped in at all times.
In my game (MMC1 cart), I plan on making heavy use of bank-switching to store lots of game map data, battle algorithms, etc... in various banks.
I was hoping to copy music into $7800-$7fff and play it from there as a mechanism to deal with switching banks and DMC. I have not experimented with this yet.
I probably won't have enough room in the non-swapping bank ($c000-$ffff) for much music. Almost all of it will be critical game code and trampoline functions for allowing code in one bank to invoke code in another.
Any drawbacks to this approach (other than swapping MMC1 banks takes lots of CPU cycles compared to other mappers)?
clueless wrote:
Any drawbacks to this approach (other than swapping MMC1 banks takes lots of CPU cycles compared to other mappers)?
Lots of bankswitching during the same frame can become a huge overhead, more so on the MMC1, like you observed. I believe it would be OK to bankswitch up to a dozen times or so in a frame, but if you need to do it 100 times then it'll be a problem.
It is a bad idea to bankswitch data that is read in small pieces and alternated with something else, such as metatiles and level maps. For example, if you have a level map mapped in and you read a metatile index from it, then you need to switch in the bank that has the metatiles to get information about the specific one you need, only to restore the level map again, that will suck, because there are many metatile accesses every frame.
In such cases, it's better to either store data that will be used at the same time in the same bank, or use WRAM instead (if you have it) to hold a copy of one of the things you need to alternate, so that the other can remain mapped in for a longer period. Level maps are nice to keep in WRAM because they usually compress very well, and can be stored that way in ROM.
Just make sure you organize the data in your ROM to optimally minimize the numbers of bankswitches in the same frame, even if it means copying some stuff to WRAM.
I've been writing and optimizing 6502 code for nearly 20 years (unprofessionally, Apple IIe hobby stuff). One of my favorite computer books is the "Machine Language for Beginners, by Richard Mansfield, 1983" [1] I think I got my copy back in 1986, at the tender age of 10.
I don't intend to switch 100+ times per bank.
What I'm trying to avoid doing to restricting my game to the logic that can be squeezed into the upper 16K.
I imagine that I'll probably need to switch the banks 5 to 10 times / frame.
I've research a large chunk of the 8K ram ($6000-$7fff) for caching tile data about the current "view port" into the world map.
I was more interested in if anyone has ever had problems keeping the DMC channel saturated with samples copied from banks ROM into RAM. For example... every frame I'd copy the next XXX samples from whichever ROM bank into the ram cache. I have not worked out the math yet on how many samples get played per frame, how much read-ahead I want, the over-head of switching to the music bank and copying the data, etc...
[1]
http://www.atariarchives.org/mlb/
clueless wrote:
I was more interested in if anyone has ever had problems keeping the DMC channel saturated with samples copied from banks ROM into RAM. For example... every frame I'd copy the next XXX samples from whichever ROM bank into the ram cache.
DMC always reads samples from $Cxxx, so copying those to RAM isn't an option. Raw playback (via $4011) doesn't have this limitation.
BMF54123 wrote:
clueless wrote:
I was more interested in if anyone has ever had problems keeping the DMC channel saturated with samples copied from banks ROM into RAM. For example... every frame I'd copy the next XXX samples from whichever ROM bank into the ram cache.
DMC always reads samples from $Cxxx, so copying those to RAM isn't an option. Raw playback (via $4011) doesn't have this limitation.
Ah nuts. There went that idea...
I have yet to read much about sound generation. I'm still refactoring all of my CHR-RAM management code. I suppose that I'll need to tinker with sound sooner rather than later so that mis-understandings like this won't cause me too many problems down the road.
Thanks for the heads up.
ps- I need more cliches in the above text.
Some games use the channel only for drums and the like, which take less than 4 KB. If this is the case for your game, you should be able to fit them into $C000-$CFFF, along with 12 KB of resident code.
Ok.
I really have no idea what it takes to make reasonable sounds efficiently (in terms on cpu, ram and rom usage) on the NES.
How do games like Zelda, Metroid, Final Fantasy and Crystalis play "background" music while your character wanders around?
I guess I have not paid attention, but what happens when the game needs to make a specific sound (like getting hit by an enemy, or discharging an energy bolt from your sword)? Is this the proper time to use DMC, and keep the background music using the square, triangle and noise channels?
Actually - Don't answer here. I'll create a new post in a new thread.