News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Expanding the UNROM mapper for the NES  (Read 12051 times)

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Expanding the UNROM mapper for the NES
« on: February 27, 2013, 11:13:52 am »
 As some of you know, I am working Outlanders for the NES.

It is my understanding that UNROM is actually mapper 2.

PRG ROM:    8 x 16KiB
 CHR ROM:    0 x  8KiB
 ROM CRC32:  0x9268e877
 ROM MD5:  0x2e2ce52517e5b771ae72e1eb18119356
 Mapper #:  2
 Mapper name: UNROM
 Mirroring: Vertical
 Battery-backed: No
 Trained: No
 .segment "HEADER"
   .byte "NES", $1A
   .byte $08       ;UNROM has 8 16k banks
   .byte $00       ;UNROM uses CHR RAM, so no CHR ROM
   .byte $20, $00  ;UNROM is Mapper 2
   .byte $00       ;UNROM has no PRG RAM, though clone boards might

This is some info that I have found out about it.

Would it be safe to use NFlate made by KingMike to expand this type of mapper and not run into any problems down the road?
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Well... I tried it and the rom still works for now. Wow... Look at all this lovely space....
Now I gotta figure out what I'm gonna do with it!
« Last Edit: February 27, 2013, 11:47:18 am by Pikachumanson »

Bregalad

  • Hero Member
  • *****
  • Posts: 2746
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #1 on: February 27, 2013, 01:10:26 pm »
First, UNROM and mapper 2 are not exactly the same thing.

UNROM is the name of a physical PCB made by Nintendo which hold a particular mapping, and has room for 128kb PRG-ROMs (28 pins with non-standard pinout) and 8kb CHR-RAM.

Mapper 2 is a logical abstraction which includes not only games with UNROM PCBs, but also any other variants of it which uses a similar mapping. For example there is also Konami boards which are functionally identical to UNROM, only the physical support is different. Included in Mapper 2 are also UOROM (which is identical to UNROM except that it uses 256kb PRG-ROMs instead), and some mapper-hacked games that originally used Mapper 1 (I don't know if those really counts though).

Reversedly, a particular game uses a UNROM board without being mapper 2 : Crazy Climber. Basically they replaced OR gates by AND games, making $c000-$ffff bankswitchable and $8000-$bfff hardwired (the opposite to mapper 2).

UNROM is limited to 128kb, mapper 2 is not limited.

To expand from 128kb to 256kb, you move from 8 banks (0-7) to 16 banks (0-15), you should make the hardwired bank 7 being bank 15, and insert new (blank) data for banks 8-14. This should work without hacking anything in the ROM data.

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #2 on: February 27, 2013, 02:00:34 pm »
Yes, I've read your posts on NESDev on the UNROM/Mapper 2 subject. Sorry for not making that distinction. Since FCEUX said the rom Mapper 2 in addition to being an UNROM, What I have done is expand the rom to 256kb so I'm guessing I now have a UOROM mapper.

At any rate I am confused about relocating pointers to a new bank and utilizing all that empty space.

For example I'm trying to relocate the Menu pointer B00C to another location in the rom

So I find the first instance of it being activated at line 00f920 in this pic here:


Which I am hoping is the table for all those other strange pointers that call a single line multiple times throughout the rom.

And then here is the actual pointer itself right here in line 0107cd:


which points to the menu on 010B00C


My free space begins at 01C010.

How would go about relocating my  text and pointers there?
And if have it all wrong thinking that I have found the command/origin of the menu pointer that tells it where to point to, then what are some techniques I can use to find it?

Bregalad

  • Hero Member
  • *****
  • Posts: 2746
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #3 on: February 27, 2013, 02:06:43 pm »
The most common thing in NES games is that pointers are 16-bit (actually 15-bit) and that the bank is fixed. In order to use free space you'll have to hack the program that switches the bank at $8000-$bfff to a different bank before actually using the pointers.

Some games might actually use different kinds of pointers where some bits also select the bank, but this should definitely be rarer than "hardwired bank" style pointers.

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #4 on: February 27, 2013, 02:23:33 pm »
I think this is one of those rare games where I will have to search for that special byte. Ugh... I hope it's hardwired...

Pennywise

  • Hero Member
  • *****
  • Posts: 2329
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #5 on: February 27, 2013, 03:37:21 pm »
There is no such thing as an UOROM (or UN for that matter) mapper. It's just mapper 2. If someone were going to make a reproduction from another game, they'd need the correct board. That would be the only time UN/UO would matter.

Bregalad

  • Hero Member
  • *****
  • Posts: 2746
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #6 on: February 27, 2013, 03:47:02 pm »
There is no such thing as an UOROM (or UN for that matter) mapper. It's just mapper 2.
Yes. On NESDev there is a lot of confusion where people started to name mappers with board names. Also people starting calling VRAM "PPU" when the PPU is actually a chip who is master on the VRAM bus, and so on... It gets really hard to keep clean and technical in such environment.

Quote
If someone were going to make a reproduction from another game, they'd need the correct board. That would be the only time UN/UO would matter.
Not really as switching from one to the other is trivial. Doing a 512kb mapper 2 game in hardware should be more complex (need for 5-bit latch and 5 OR gates), but definitely possible, if a new board were made for it specifically.

Pennywise

  • Hero Member
  • *****
  • Posts: 2329
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #7 on: February 27, 2013, 03:54:26 pm »
Anyhow, here's some of my expansion code for a mapper 2 game I hacked a few years ago.

FEF0:AD FF 06  LDA $06FF
FEF3:C9 5A     CMP #$5A
FEF5:B0 07     BCS $FEFE
FEF7:A9 03     LDA #$03
FEF9:AA        TAX
FEFA:9D 00 C0  STA $C000,X @ $C003 = #$03
FEFD:60        RTS -------------------------------
FEFE:A9 07     LDA #$07
FF00:A2 07     LDX #$07
FF02:9D 00 C0  STA $C000,X @ $C003 = #$03
FF05:60        RTS -------------------------------

Some context, what I did was hack the pointer table read routine to store the index in $06FF. Just before the text is read I added this code to check to see if the index is greater than #$5A and if so to swap to another bank where all the text that has that pointer index thing 5A and over are located. This essentially split the text in half and doubled my available space. Each game requires a custom solution, but my general method is to split text between banks to allow for greater room.
« Last Edit: February 27, 2013, 04:00:18 pm by Pennywise »

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #8 on: February 28, 2013, 04:47:59 pm »
@Pennywise Ok I am going to try to implement your code and aim at my menu.

Would 06FF be the equivalent to B00C, which is the pointer to the menu?
Also, could I just put it in as the pointer appears in the rom or do I have to switch it?
« Last Edit: February 28, 2013, 04:54:20 pm by Pikachumanson »

Pennywise

  • Hero Member
  • *****
  • Posts: 2329
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #9 on: February 28, 2013, 06:54:29 pm »
I did a little bit of checking and 175F2 is where the menu pointer data is. In fact the code that loads that ultimately determines which pointer to get is hard-coded with a simple addition function to choose data.

Alright, let me do a quick recap how I got to that. I set a write breakpoint to 20B0 in the PPU and saw that the menu was coming from $07xx in RAM. I scrolled up to find where it was writing $07xx in RAM in the trace logger and eventually came onto the address it was reading from, the 10Cxx address. The offsets for the address was being stored in $002A-2B in RAM, so I set a write breakpoint for $2A in the CPU. $2A however gets written to quite a bit and I have to initialize the menu first and quickly add in the breakpoint before the data is actually read. Eventually, I found what I was looking for, pointer offsets.

The important part is this code:

Code: [Select]
$BDBA:06 2A     ASL $002A = #$05                   A:05 X:00 Y:05 S:4A P:nvUBdIzc
$BDBC:26 2B     ROL $002B = #$00                   A:05 X:00 Y:05 S:4A P:nvUBdIzc
$BDBE:A9 D8     LDA #$D8                           A:05 X:00 Y:05 S:4A P:nvUBdIZc
$BDC0:18        CLC                                A:D8 X:00 Y:05 S:4A P:NvUBdIzc
$BDC1:65 2A     ADC $002A = #$0A                   A:D8 X:00 Y:05 S:4A P:NvUBdIzc
$BDC3:85 2A     STA $002A = #$0A                   A:E2 X:00 Y:05 S:4A P:NvUBdIzc
$BDC5:A9 B5     LDA #$B5                           A:E2 X:00 Y:05 S:4A P:NvUBdIzc
$BDC7:65 2B     ADC $002B = #$00                   A:B5 X:00 Y:05 S:4A P:NvUBdIzc
$BDC9:85 2B     STA $002B = #$00                   A:B5 X:00 Y:05 S:4A P:NvUBdIzc
$BDCB:A0 00     LDY #$00                           A:B5 X:00 Y:05 S:4A P:NvUBdIzc
$BDCD:B1 2A     LDA ($2A),Y @ $B5E2 = #$A1         A:B5 X:00 Y:00 S:4A P:nvUBdIZc
$BDCF:48        PHA                                A:A1 X:00 Y:00 S:4A P:NvUBdIzc
$BDD0:C8        INY                                A:A1 X:00 Y:00 S:49 P:NvUBdIzc
$BDD1:B1 2A     LDA ($2A),Y @ $B5E3 = #$8C         A:A1 X:00 Y:01 S:49 P:nvUBdIzc
$BDD3:85 2B     STA $002B = #$B5                   A:8C X:00 Y:01 S:49 P:NvUBdIzc
$BDD5:68        PLA                                A:8C X:00 Y:01 S:49 P:NvUBdIzc
$BDD6:85 2A     STA $002A = #$E2                   A:A1 X:00 Y:01 S:4A P:NvUBdIzc

And the goods.

Code: [Select]
$BDD8:60        RTS (from $B6FE) ----------------- A:A1 X:00 Y:01 S:4A P:NvUBdIzc
$F203:4C EE F1  JMP $F1EE                          A:A1 X:00 Y:01 S:4C P:NvUBdIzc
$F1EE:A9 04     LDA #$04                           A:A1 X:00 Y:01 S:4C P:NvUBdIzc
$F1F0:85 AC     STA $00AC = #$05                   A:04 X:00 Y:01 S:4C P:nvUBdIzc
$F1F2:8D 04 C0  STA $C004 = #$04                   A:04 X:00 Y:01 S:4C P:nvUBdIzc
$F1F5:60        RTS (from $F1FD) ----------------- A:04 X:00 Y:01 S:4C P:nvUBdIzc

A good litmus test to see how far along your understanding of ASM is, provided you understand everything up to this point, if you can explain how this code functions in relation and in context of this game.
« Last Edit: February 28, 2013, 08:20:50 pm by Pennywise »

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #10 on: March 01, 2013, 12:00:23 am »
Thank you very much! I was feeling very lost on what I should do next! 

-----------------------------------------------------------------------------------
Ok, let me know if I got this right.

The key to changing where my pointer is located is JMP $F1EE?
But it is located on 3F213 what would I need to do to relocate the pointers to 1C010 where my free space starts? This way I can write a pointer function function based on what I saw after the jmp statement.

My free space ends at 3C000.

Or would I need to change some things up at 175F2 where my data is so it points to a jmp statement is my free space?

Also is $BDD8:60        RTS (from $B6FE) ----------------- A:A1 X:00 Y:01 S:4A P:NvUBdIzc
necessary for what I am doing? It's part of the menu data and not the goods right?

I'm really confused because around that area of the rom EEF1 is used quite a bit in the form JSRs so I'm not sure if that is connected to other parts of the menu or what!

 
« Last Edit: March 01, 2013, 03:20:45 pm by Pikachumanson »

Pennywise

  • Hero Member
  • *****
  • Posts: 2329
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #11 on: March 01, 2013, 03:50:23 pm »
I mean no offense when I say this, but I think you're up shit creek without a paddle. I can relate though, but telling you what to do next probably wouldn't help you. The only thing I can do is try to get you on the right track.

Moving pointers around is generally too much of a hassle and considering that the pointers and corresponding data are in different banks, you really only need to move the data.

I'm trying here, but I feel like misinformation and confusion are a common theme. That code I posted is really important though, it's the key to what you want to do.

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #12 on: March 01, 2013, 04:04:11 pm »
I guess I'd better get to rowing with my hands then.

March 02, 2013, 12:08:47 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
-----------------------
Moving data around is the same as bankswitching or would it require bankswitching?
« Last Edit: March 02, 2013, 12:08:47 pm by Pikachumanson »

Pennywise

  • Hero Member
  • *****
  • Posts: 2329
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #13 on: March 02, 2013, 03:51:06 pm »
Bank switching/swapping is changing a bank that's been loaded into the PRG-RAM with another from the PRG-ROM that replaces the previous bank in the PRG-RAM. You can move data pretty much anywhere you want it, but the bank needs to be in the PRG-RAM. If you haven't downloaded disch's mapper docs, you should do so and take a look at the info for mapper 2.
« Last Edit: March 02, 2013, 04:24:29 pm by Pennywise »

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #14 on: March 03, 2013, 12:44:19 am »
Disch! I forgot all about him! Thanks! I am also going through the NintendoAge Nerdy Nights tutorials as the section on bank switching seems right up my alley.

Now as for moving data is it rewriting the data i want to move onto the free rom space?
Can i do whatever i want with the old data once i get the moved data working?

I'm sorry if These questions seem real stupid but this is brand new territory that i never intended getting into when i started this project.

but in the interest of a higher quality hack i am now gonna do it and increase my knowledge in the asm area.
« Last Edit: March 03, 2013, 01:51:43 am by Pikachumanson »

Pennywise

  • Hero Member
  • *****
  • Posts: 2329
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #15 on: March 03, 2013, 01:10:28 am »
The term write mostly applies to writing stuff to RAM and registers. By moving you're changing the location data is being read from.

Once you move the data and update whatever points to it, the old data becomes unused space and something you can blank out with FF etc.

So let me put this into context with this menu data. You are moving the data to another location so you can expand the data. In order to do so, you need to change the bank the data is being read from.

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7003
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #16 on: March 03, 2013, 01:23:58 am »
The PRG-ROM area is not RAM. Do not think of it as RAM. Bank swapping with swap the complete ROM bank out of access and swap the complete new ROM bank into access.

Be sure that when your code completes the bankswap (either the STA instruction that writes to the PRG bankswap address) or returns from a JSR to an existing function in the fixed bank, that you have valid code in the same location in the new bank or your game will crash.

Like, mapper 2 has a bank size of 16KB ($4000 bytes).
You had some code, and the JSR to a bankswap function was at ROM address $C567. Fine, let's say that's the address with iNES header. That means you have bank 3 swapped in (ROM $C000-FFFF not counting header), and address $557 within the bank.
Say you want to swap in bank 8 (ROM $20000-23FFF not counting header). The JSR is 3 bytes, so your new code better continue at address $20000+557+3+10 = $2056A.

Also, note than mapper 2 is considered to be a set of mappers with some including "bus-conflicts" mapper. I'm not entirely sure what that means, just that you better write the number of the bank you want to swap in, to a ROM address that has the same value, or the value written to the bankswap register will get corrupted (or at least you should assume it can, whether the emulator emulates that flaw or not).
Like most games will do something like
LDX #$05
STA $C000,X
where address $C000 has a list of all possible banks (00, 01, 02, etc.) If you don't have free space at the end of the table before other code, you'd have to move the list and update the pointer. (and hope the game handles all its bankswap calls through a single function)
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #17 on: March 03, 2013, 10:30:14 pm »
Thank you very much for your comments KingMike and Pennywise!
 The knowledge I have learned from you two and Disch's doc has been immense!

Ok I've moved my menu data offset 0001C090.
Is bank switching in mapper 2 really that simple?

 LDA #$00
  JSR Bankswitch  ; change to graphics bank 0
  LDA #$01
  JSR Bankswitch  ; change to graphics bank 1
  RTI             ; return from interrupt
Bankswitch:
  TAX                    ;;copy A into X
  STA Bankvalues, X      ;;new bank to use
  RTS

Bankvalues:
  .db $00, $01, $02, $03 ;;bank numbers

Say Pennywise...
Is that second part of the code you gave me a bankswitch?
Would changing that up be the key to problem?


KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7003
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #18 on: March 04, 2013, 09:54:15 am »
RTI should only be used to end the "interrupt" functions (NMI for all games, IRQ for games running on mappers that support IRQs). All other functions should end with RTS.
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #19 on: March 04, 2013, 03:01:52 pm »
Should i put my bank switch code and table in the 6000-7ffff area where the prg ram is located?

Nvm about the table it must be located in the C000-ffff bank.
« Last Edit: March 04, 2013, 03:18:05 pm by Pikachumanson »