News:

11 March 2016 - Forum Rules

Main Menu

Expansion of an UNROM (Mapper 2) rom?

Started by Timaeus, July 17, 2022, 11:29:58 PM

Previous topic - Next topic

Timaeus

  Hello there. These weeks, I am finally learning how to code attack patterns and movement patterns for my current Megaman 1 hack, and I even managed to code a more complex boss too. However, I am starting to have abit of trouble to find or create new free/unused spaces to use for said new patterns. I did managed to get some good space by simplifying the code from a couple of enemies, but honestly, I feel like expanding the ROM size and changing it's Mapper would maybe be a better idea.

My hack is using the original mapper, which is UNROM (Mapper 2), with PRG-ROM size of 8 x 16kb and CHR-ROM size  of 0 x 8kb. Since my only need with more free space is just for attack-movement patterns for bosses, I think  double the size would be more than enough. I do know that bank switching will probably be required, and I have bisqwit's written text disassembly of the game, with the location of anything I need and bytes too.

The problem is that I am a little confused about which method is the best to get extra space. Can someone help me out, please? I did found threads and text documents about this topic as well. I can link them up if needed.

Thank you very much~
Do little by little, one thing at a time, and never forget why you do what it should be done!

Cyneprepou4uk

Write byte 10 at 0x00004, then insert 20000h FF bytes at 0x1C010 in a hex editor. In case the game won't start after that, insert bytes at 0x00010 instead.

Timaeus

#2
  It worked, and the game loaded as well. Thank you VERY much! Now, I am abit confused at how to make the game jumps to the new location (which was the old bank 7 location). Normal pointer jumps will not work, since the new space goes one byte after $FFFF. I know I need to make a code in an empty space where $XXXX can reach that will make some math to make reaching the new location be possible. How do I do this code?
Do little by little, one thing at a time, and never forget why you do what it should be done!

Cyneprepou4uk

#3
nesdev.org/wiki/UxROM#Bank_select_($8000-$FFFF)

Keep your bankswitch routine inside a fixed bank, which is C000-FFFF. Jump there to write bank number to 8000-FFFF register in order to swap 8000-BFFF area, then jump to/read data from 8000-BFFF. When you're done, swap back to the original bank (if necessary).

This mapper has bus conflicts, so make sure that the value you write is equal to the value of the memory address. For example if you write bank 08 to CDEF register, then CDEF location must have value 08 as well.

UNROM games usually have some kind of a table for 00-07 bytes and write bank number to a register with a STA,X. Set a write breakpoint to 8000-FFFF in your game to see how it works.

QuoteI am abit confused at how to make the game jumps to the new location (which was the old bank 7 location).

It's bank 0F now after expansion, and it's loaded into the CPU memory at C000-FFFF as a fixed bank as usual. Nothing has changed basically, last 4000h PRG bytes are always there.

Timaeus

How do I jump to the new place? It is out of the XXXX location, and I did not understood parts of what you said. Can you show me an example?
Do little by little, one thing at a time, and never forget why you do what it should be done!

Cyneprepou4uk

Let's say you're currently somewhere in 8000-BFFF in bank 02. You jump somewhere to a fixed bank in C000-FFFF. From here you execute your bankswitch code in order to swap to bank 07. That makes 8000-BFFF bank 07. Now you can jump here or read data from it. After that you jump back to a fixed bank, swap 8000-BFFF back to bank 02, and continue.

Does this make sense? If not, then be more specific about what you don't understand exactly.

Timaeus

I got the logic better now. I looked at the bisqwit Written disassembly, and everytime the game needs to switch banks, they do this (this next example is to make that specific location where the code is be bank 5):

"A9 05 85 42 8D 05 C0"

C005 (which is what the last two bytes represent, but they must be written in reverse) is a table that stores the number of each bank (which goes from 0 to 7, being $C000 to $C007. This table is in bank 0F, which is the old bank 7).

So, since MMC1 mapper reads each bank as 4000 bytes, and since my new space is starts at 1C010, that makes this new space until 20010 the new bank 7 I believe, and 20010 until 24010 bank 8, 24010 until 28010 bank 9. etc.

So all I have to do is add the bank swapping code above in bank 0f ($c000-$ffff, so the pointer can reach it), create a table with numbers from 08 until 0E, change 05 C0 to the bytes that represent the location of said table, and then jump to the location I need?

Do little by little, one thing at a time, and never forget why you do what it should be done!

Cyneprepou4uk

#7
Depends on your code, but if you need just one single bank for your stuff, you don't need a whole table for that. Since your game already has byte 07 at C007, that's perfect, use this address.

Everything else you've said is correct.

QuoteA9 05 85 42 8D 05 C0

Also, seems like your game stores bank number in $0042 before writing to a register, you should probably do that as well. This is usually done in order to restore correct bank in case interrupt handlers (NMI for example) will do their own bankswitching.

Timaeus

#8
Now that I think of it, I think only one new bank is enough. Ok, I will not need to add a new table for that. Ok so, I wrote this code based on the game's bank 05 switching code:

A9 07 85 42 8D 07 C0 4C xx xx 60

I added this code in 3E428 hex ($E418, bank 0F) and made the pointer that reads Fireman's boss code go there. Now it loads it up, switching bank 0F (the bank where this code is and where the bosses pointers are) to bank 07. That should make $C000-FFFF bank 7 (where my empty space is, at 1C010 hex), but I am confused at which location I should put after JMP (4C). I realized that I cannot see it in NES Memory from FCEUX because it is out of reach, so that is why switching banks is required, to make a location be somewhere else. I am just attempting at knowing how to make the game go to where I need after switching banks properly. Based that MMC1 banks have $4000 of size, maybe I have to use it for said calculation perhaps.

I did not wrote the "switch back to bank 0F" yet, but I believe it follows the same logic and I know what bytes to put after JMP, and I do believe I have to add it after my boss code when it is done. I added JMP instead of jsr because the boss code needs RTS to go to the next one. So I am going to add a JMP "switch to bank 0f" after it.

EDIT: Ok, I got it, it is 8000 to 1C010, 8001 to 1C110, etc. Ok, I will add the code for the boss and JMP back to bank 0f if needed. I will edit this again saying the results.

Wait, do I need to rewrite all the "jumps" and ""go to" that the boss code does?
Do little by little, one thing at a time, and never forget why you do what it should be done!

Cyneprepou4uk

QuoteNow it loads it up, switching bank 0F (the bank where this code is and where the bosses pointers are) to bank 07. That should make $C000-FFFF bank 7 (where my empty space is, at 1C010 hex), but I am confused at which location I should put after JMP (4C).

First of all, you can't swap C000-FFFF, it's FIXED. You can only swap 8000-BFFF. Second, adding RTS after JMP is pointless. JMP (4C) doesn't have a return address, unlike JSR (20).

Timaeus

  After weeks, I finally got it to work thanks to you and a few friends, including Kuja and Zieldak. Thanks you all! I can finally have better bosses now. My eternal gratitude!
Do little by little, one thing at a time, and never forget why you do what it should be done!