11 March 2016 - Forum Rules

Main Menu

Zelda 1 (NES) How to Fix Bank Overflow?

Started by binomnpx, December 09, 2021, 09:58:35 PM

Previous topic - Next topic


I've been using a combination of this (aldonunez/zelda1-disassembly) disassembly and Mesen to create a Zelda 1 ROM hack. Things are going pretty well actually but I've run into the dreaded Bank Overflow error which makes building the ROM impossible. This doomed my last project, which I ended up abandoning. So, I never learned these skills.

It is my understanding that the solution involves optimizing code so it fits better, as well as moving memory to other ROM banks. If anyone has a script to find code to optimize that would be amazing. If not, I am going to focus on moving memory around to fit everything.

Here's my actual question. How does one go about this? Are not all of the banks full? What memory is ok to move?

Thanks in advance!

PS: If there are any other communities devoted to hacking Zelda 1 specifically, I am open to suggestions.


Scripts to optimise code on the NES are less likely to be a thing than they are with more compiled efforts where you have more predictable outputs and things to optimise (for space*) accordingly, not to mention the real gains will come from code that nothing short of strong AI is likely to find. You then get to look at original aspects of the code (and presumably your own additions), figure out what the end goal is and whether you can do it in fewer instructions but still in and acceptable timeframe and being 6502 you are in some ways more limited and other ways dodge some of the complexities involved in doing that. Comments on the disassembly might hint at things they devs did oddly, or did in a certain way to ensure a valid outcome in all random cases but might not have thought through as well as they could have.

*as opposed to speed, for latency, or robustness, and depending upon what you go in for here you might find you want to do one or more of those too.

Full banks.
In all that (plus what extra you can gain from reading the stock ROM disassembly) as split down into the banks level, with special attention paid to any sections left in memory at all points, you get to find free space not occupied with another task and stick your code there and jump to those. You might even take existing code and move that to free up a larger area for your purposes (10 bytes here and there is less fun to handle with jumping in and out of it gobbling up gains, manage to move things such that you get a larger run of free space and you spare yourself many jumps and thus gain more effective space), along with sorting all pointers/relative jumps/... that reference the thing you just moved (very tedious but often doable, especially if you have a nice commented disassembly with memory labels to begin with).

There is also the whole mapper change thing -- back when then larger cartridges with more complexity cost more than might be desirable for mass production, today it is an emulator setting that the user does not even see, "fast shipping costs 100x more" if making cartridges, or thing flash carts inherently support and thus becomes an option. says mmc1 which is one of the shinier mappers but by no means the shiniest. MMC3 is probably where most would head first but there are other options for known mappers (don't define your own).

Cowboy option. You delete something from the existing game, tell users to take their save and load it in another game at a certain point (if you are good you can code that into the game itself). Classically you see this more in ROM ripping where someone will delete say the last half of the levels, use the space for something else (or indeed a space saving) and then get the user to copy the save/password across to another ROM to finish the game.


QuoteHow does one go about this?
The best way is to add more banks in order to set yourself for life. But who knows how much space you need. Maybe you've added just a single byte and already got an overflow with no idea what to do next.

QuoteAre not all of the banks full?
I have my own disassembly of this game, link is in my signature. Search for "bzk garbage" inside asm files.

QuoteWhat memory is ok to move?
If your disassembly is fully labeled, you can move almost any memory (within reason).


Thank you FAST6191 for the excellent write up. Everything is a lot clearer now, and I feel a lot less overwhelmed. I will aim to find a big chunk and prepare it for bank switching. Most of my edits need to be quick so I will just have to find code that doesn't need to be called often or run particularly fast. Thanks again.

And thank you Cyneprepou4uk for the suggestion. I found "bzk garbage" and even attempted to delete and build the ROM. I still got the same error though which is rather perplexing. And yes, I added like 10 lines of code (just a few bytes) and immediately got bank overflow. On the NESDev discord disassembly channel someone mentioned that the "fixed bank" is full but there is still plenty of space in the other banks. I have yet to identify which is the fixed bank but if what they said is true then it is probably the one I added code to.

Btw, the assembly I mentioned was finished earlier this year. The person who disassembled it has labeled almost all of the code pretty clearly. Not all of the code is disassembled (I think) so you can't directly view the map data for example (I think). The ROM map on datacrystal does help with this somewhat, as well as Mesen's Memory Tools.


Fixed bank is the very last bank that cannot be swapped on a mapper, bank_FF in my case. It's always loaded at C000-FFFF. When expanding the game, usually you insert the new ones right before the fixed one.

If you have deleted some garbage, then added your code and still get an overflow, check out ".segment" inside the asm file, plus the locations and size of those segments inside a config file. Also, in rare cases this error can be caused by incorrect syntax. Try simple NOPs.

If his disassembly doesn't work for some reason, feel free to use mine as a base for your hack. For example you can safely delete garbage at 0x01FFD0 and then add several lines of code there, at the same spot.