To do a mapper hack you need to know 3 things:
1) 6502 assembly (which I assume you are reasonably proficient in if you are adding SRAM to a game)
2) How the original mapper works (In this case, UxROM)
3) How the new mapper works (In this case, MMC1, I assume, unless you decide on something different).
Most mappers do more or less the same thing. So doing a mapper hack involves figuring out what the game is doing in one mapper, and doing the equivalent thing in another mapper.
In this case, UxROM only has 1 thing to do: Swap PRG. It does that with code similar to the following:
; Swap to bank 'some_bank_number'
LDA #some_bank_number
TAX
STA $C000,X ; address may vary -- must be between $8000-FFFF
The equivalent code on MMC1 (to swap PRG) would be the below:
LDA #some_bank_number
STA $F000 ; address may vary -- must be between $E000-FFFF
LSR A
STA $F000
LSR A
STA $F000
LSR A
STA $F000
LSR A
STA $F000
Both of these bits of code might seem strange at first, but what they're doing is very simple.
UxROMTo Swap PRG on UxROM, you just have to write the desired page number to any address in the $8000-FFFF range. The thing that makes it complicated is that most boards have bus conflicts, so the value you write must match EXACTLY to the value that is read from that address. IE, if you want to swap to page $05... you'd need to write $05 to an address in the $8000-FFFF range that already contains a $05.
Games often do this with a lookup table that just looks like this:
At address C000:
00 01 02 03 04 05 06 07
The game then uses the page number as the index to the lookup table to write:
LDA #5 ; want to swap to bank 5
TAX ; A and X are now both 5
STA $C000, X ; Since X=5, we will write to $C005, and we know $C005 contains 5 because
; that's the point of the lookup table.
Note that this is just an example, and not a definitive rule. A game might do something like this:
LDA #$02
STA $8016
... if it just happens to know that $8016 contains a 2. There isn'te specific routine to do this -- a game can do it any number of ways. It's up to you to look at the code and figure out what it's doing.
But you can know for sure that
every single write the original game does to the $8000-FFFF range is the game attempting to swap PRG to a specific page.
MMC1MMC1 is weirder. To Swap PRG here, you just have to write the desired page number to any address in the $E000-FFFF range. The plus side is there's no bus conflicts, so you don't have to worry about writing to an address that contains a certain value. The down side is MMC1 registers can only be written 1 bit at a time.
MMC1 regs are also 5 bits wide, which means each register write actually takes 5 writes (one for each bit)
Hence the LSR's between each STA. The low bit is written first, then you shift right to move the next bit into position 0, so it will be written on the next STA.
MMC1 also has additional functionality besides just PRG swapping. You don't have to use it, since the game you're hacking doesn't need it... however you still have to initialize everything. Common best practice is to write to all registers once at powerup to put everything in a known state. So take a look at MMC1's register list:
https://wiki.nesdev.com/w/index.php/MMC1#Control_.28internal.2C_.248000-.249FFF.29There are 4 registers:
1) Control ($8000-9FFF). This sets the mirroring mode, as well as the swap modes. To match UxROM, you want 8K CHR and 16K PRG swappable at $8000... and either horizontal or vertical mirroring depending on what the game is (I'm too lazy to check). So you'll want to write either $0E (vertical) or $0F (horizontal). But again, gotta write 1 bit at a time, so when I say "write" I mean "perform 5 STA's"
2) CHR bank 0 ($A000-BFFF). Since you'll be using CHR-RAM, the CHR swapped in doesn't really matter. You can probably get away with not writing to this reg at all, but if you want to be strict you can write $00.
3) CHR bank 1 ($C000-DFFF). Ditto. Although since you'll be using 8K CHR swapping this reg will actually be ignored, so you REALLY don't need to write to it at all.
4) PRG bank ($E000-FFFF). This is what controls the PRG swapping. Basically just write to this reg whatever the original game does when it bankswaps.