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

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

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7067
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #20 on: March 04, 2013, 03:29:23 pm »
If you want to copy the routine over from PRG-ROM to PRG-RAM and you have free space, I imagne it would probably work.

Though I don't know how forward-compatible that might be with emulators. NESDev lists mapper 2 (UxROM) as not supporting WRAM/SRAM. The PCBs I've looked do look full as it is. Once noticeable thing suggesting as such, looking at bootgod's NES Cart Database, is that Dragon Quest 2 was converted from UNROM (128k, no SRAM) to MMC1 for Dragon Warrior II (256k, SRAM).
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #21 on: March 04, 2013, 03:52:10 pm »
So basically, I should just locate the menu bankswitching routine in the PRG-ROM and change to what I want?

PRG-RAM seems out of the the question as well because when I tried to write my routine on the free space on 0000f020 I couldn't move my guy to the right when I played the game.

Converting to MMC1 seems way out of my league when I am struggling with bankswitching. I am sorry I am slow learner but once I grasp a concept, I got it on lock. I feel like I am just a couple steps away from doing what I want to do and it just frustrates me that I am stuck on this part.

Pennywise

  • Hero Member
  • *****
  • Posts: 2354
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #22 on: March 04, 2013, 04:17:23 pm »
Just to clarify a few things.

$6000-7FFF in the CPU memory map is not PRG-RAM, it's an area reserved for cartridge RAM that not all NES games/mappers have the ability to do.

Furthermore, bank swapping on mapper 2 only requires a minimum of 6 bytes for the code. Example:

LDA #$01
STA $C000
RTS

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7067
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #23 on: March 04, 2013, 07:04:41 pm »
Unfortunately, it looks like Outlanders is pretty stupid and has a bunch of hard-coded writes like
Code: [Select]
LDA #$03
STA $C003
all over the place in addition to
Code: [Select]
sta $C000,y
rts
when they could've saved space
Code: [Select]
ldy #value
jsr The Offset Where One Instance Of STA $C000,Y Is

If you need to expand the table, I found the controller routine has some fat that can be cut.
Original routine
[code]
 07:C29F:A9 01     LDA #$01
 07:C2A1:8D 16 40  STA $4016 = #$FF
 07:C2A4:A9 00     LDA #$00
 07:C2A6:8D 16 40  STA $4016 = #$FF ;strobe controller port 1
 07:C2A9:85 45     STA $0045 = #$00
 07:C2AB:A2 00     LDX #$00
 07:C2AD:20 B5 C2  JSR $C2B5
 07:C2B0:E8        INX
 07:C2B1:A9 00     LDA #$00
 07:C2B3:85 45     STA $0045 = #$00 ;$45 status of current pad
 07:C2B5:A0 08     LDY #$08 ;number of reads left
 07:C2B7:85 45     STA $0045 = #$00
 07:C2B9:BD 16 40  LDA $4016,X @ $4016 = #$FF ;read port
 07:C2BC:85 46     STA $0046 = #$00
 07:C2BE:4A        LSR ;D0 -> carry, D1 -> D0
 07:C2BF:05 46     ORA $0046 = #$00 ;$46 = 1 if D1/D0 = 1
 07:C2C1:4A        LSR ;button push into carry
 07:C2C2:A5 45     LDA $0045 = #$00
 07:C2C4:2A        ROL ;insert into button register
 07:C2C5:88        DEY
 07:C2C6:D0 EF     BNE $C2B7 ;repeat for all buttons
 07:C2C8:86 46     STX $0046 = #$00
 07:C2CA:06 46     ASL $0046 = #$00 ;$46 = 0 for pad 1, 2 for pad2
 07:C2CC:A6 46     LDX $0046 = #$00
 07:C2CE:B4 47     LDY $47,X @ $0047 = #$00 ;old button data
 07:C2D0:84 46     STY $0046 = #$00
 07:C2D2:95 47     STA $47,X @ $0047 = #$00
 07:C2D4:95 48     STA $48,X @ $0048 = #$00
 07:C2D6:29 FF     AND #$FF
 07:C2D8:10 08     BPL $C2E2
 07:C2DA:24 46     BIT $0046 = #$00
 07:C2DC:10 04     BPL $C2E2
 07:C2DE:29 7F     AND #$7F
 07:C2E0:95 48     STA $48,X @ $0048 = #$00
Replacement code, seems to work okay.
EDIT: NO IT'S NOT WORKING, DON'T INSERT YET. SEEMS I MADE AN ERROR.
I HAVE TO GO SO I WILL CHECK LATER TONIGHT AND FIX THIS.
Code: [Select]
ldx #$01
 stx $4016
 dex
 stx $4016 ;store controller
;here we'll assume X = 0 for player 1
 jsr PadRead
 inx ;onto player 2 and repeat the loop
PadRead:
 ldy #$08
PadLoop:
 lda $4016,x ;$4016 for P1 and $4017 fot P2
 and #$03 ;check just D1/D0
 bne EitherPressed
 clc
 bcc $01
 sec
; now carry = 0 if neither line is pressed, 1 = if either pressed
 rol $45
 dey
 bne PadLoop

 txa
 asl a
 tax ;A = A*2  (by coincidence, it will still be 0 for P1, we don't care for P2)

 ldy $47,x ;last button press (from $47 for P1, $49 for P2)
 sty $46
 
 lda $45 ;current pad status
 sta $47,x ;store to last button status
 bpl End ;last button press wasn't A, quit
 lda $46 ;A wasn't pressed on previous check
 bpl End
 ;if we're here, A was pressed on both frames
 lda $47,x
 and #$7F
End:
 sta $48,x
 rts
Should free up 13 bytes at $1C2E6-1C2F2 after inserted. Maybe that's enough you move the beginning of the reset routine (starts at $C008, reset vector is at $2000C (on NES, is always at $FFFC-FFFD of fixed bank) to free up $C008-C00F to expand the bank table.
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #24 on: March 04, 2013, 07:12:47 pm »
You guys are awesome! Thanks a trillion! I can't wait to put the code in when you do fix it.

Though I do have a question. I can bankswitch to my normal banks ok, but how the heck do I access the expanded banks?

I am not sure how write the offsets out in the hex editor.

The bank I wanna go to is in 0001C000.

NVM I see that the expanded banks haven't been written to the table yet! I need to increase my reading comprehension.
« Last Edit: March 04, 2013, 07:34:30 pm by Pikachumanson »

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7067
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #25 on: March 05, 2013, 03:19:53 pm »
Alright. Optimized controller routine.
You can probably actually take out the AND #$03 through the SEC part if you wanted to free up some more bytes, which would leave enough for an expanded bank table.
I don't know why some single-player games do that. It allows pins D0 and D1 to both be used for gameplay. Which I think essentially allows you to use a multitap to allow P3/P4 to function as P1/P2.

Replacing the noted instructions with a single LSR A would remove multitap support (for whatever reason it was there in the first place :P ) but should still work.

Code: [Select]
07:C29F:A2 01     LDX #$01
 07:C2A1:8E 16 40  STX $4016 = #$FF
 07:C2A4:CA        DEX
 07:C2A5:8E 16 40  STX $4016 = #$FF   ;write 1, then 0 to reset the port.
 07:C2A8:20 AC C2  JSR $C2AC    ;jumping to routine for one game controller
 07:C2AB:E8        INX         ;set X to 1 to read pad 2.
 07:C2AC:A0 08     LDY #$08  ;8 buttons
 07:C2AE:BD 16 40  LDA $4016,X @ $4115 = #$FF  ;read port
 07:C2B1:29 03     AND #$03        ;only low 2 bits matter
 07:C2B3:D0 03     BNE $C2B8
 07:C2B5:18        CLC                    ;here button was not pressed on either controller. Set carry flag to no button press
 07:C2B6:90 01     BCC $C2B9      ;jump over next line
 07:C2B8:38        SEC                  ;button pressed on either P1 or P3. Set carry to button pressed
 07:C2B9:26 45     ROL $0045 = #$00  ;rotate carry bit into button status byte
 07:C2BB:88        DEY
 07:C2BC:D0 F0     BNE $C2AE    ;repeat for all 8 buttons
 07:C2BE:8A        TXA
 07:C2BF:0A        ASL          ;double X
 07:C2C0:AA        TAX
 07:C2C1:B4 47     LDY $47,X @ $0146 = #$FF        ;read LAST FRAME BUTTON
 07:C2C3:84 46     STY $0046 = #$00             ;backup of LAST FRAME
 07:C2C5:A5 45     LDA $0045 = #$00                 ;read CURRENT FRAME BUTTON
 07:C2C7:95 47     STA $47,X @ $0146 = #$FF    ;store to LAST FRAME BUTTON
 07:C2C9:10 08     BPL $C2D3                  ;if A button not pressed on last frame, finish this routine
 07:C2CB:A5 46     LDA $0046 = #$00
 07:C2CD:10 04     BPL $C2D3                  ;if A button not pressed this frame, finish this routine
 07:C2CF:B5 47     LDA $47,X @ $0146 = #$FF
 07:C2D1:29 7F     AND #$7F         ;if A was pushed on both this and the last frame, set as not pushed
 07:C2D3:95 48     STA $48,X @ $0147 = #$FF   ;store CURRENT BUTTONS PUSHED
 07:C2D5:60        RTS
and 13 FFs (up to and including address $1C2F2).

BTW, I'm thinking I should try to gather all of Pikachumanson's Outlanders posts into one thread? :)
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #26 on: March 05, 2013, 03:24:48 pm »
YESS!!! I found my bank tables right below where my free space ends. Now the question is what do I gotta do to utilize that free space so I can write write the bank numbers there?

The thing is, I believe they might be in different banks as the free space ends at 0003C000 and the bank table begins at 0003C010.

March 05, 2013, 03:27:29 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Alright. Optimized controller routine.
You can probably actually take out the AND #$03 through the SEC part if you wanted to free up some more bytes, which would leave enough for an expanded bank table.
I don't know why some single-player games do that. It allows pins D0 and D1 to both be used for gameplay. Which I think essentially allows you to use a multitap to allow P3/P4 to function as P1/P2.

Replacing the noted instructions with a single LSR A would remove multitap support (for whatever reason it was there in the first place :P ) but should still work.

Code: [Select]
07:C29F:A2 01     LDX #$01
 07:C2A1:8E 16 40  STX $4016 = #$FF
 07:C2A4:CA        DEX
 07:C2A5:8E 16 40  STX $4016 = #$FF   ;write 1, then 0 to reset the port.
 07:C2A8:20 AC C2  JSR $C2AC    ;jumping to routine for one game controller
 07:C2AB:E8        INX         ;set X to 1 to read pad 2.
 07:C2AC:A0 08     LDY #$08  ;8 buttons
 07:C2AE:BD 16 40  LDA $4016,X @ $4115 = #$FF  ;read port
 07:C2B1:29 03     AND #$03        ;only low 2 bits matter
 07:C2B3:D0 03     BNE $C2B8
 07:C2B5:18        CLC                    ;here button was not pressed on either controller. Set carry flag to no button press
 07:C2B6:90 01     BCC $C2B9      ;jump over next line
 07:C2B8:38        SEC                  ;button pressed on either P1 or P3. Set carry to button pressed
 07:C2B9:26 45     ROL $0045 = #$00  ;rotate carry bit into button status byte
 07:C2BB:88        DEY
 07:C2BC:D0 F0     BNE $C2AE    ;repeat for all 8 buttons
 07:C2BE:8A        TXA
 07:C2BF:0A        ASL          ;double X
 07:C2C0:AA        TAX
 07:C2C1:B4 47     LDY $47,X @ $0146 = #$FF        ;read LAST FRAME BUTTON
 07:C2C3:84 46     STY $0046 = #$00             ;backup of LAST FRAME
 07:C2C5:A5 45     LDA $0045 = #$00                 ;read CURRENT FRAME BUTTON
 07:C2C7:95 47     STA $47,X @ $0146 = #$FF    ;store to LAST FRAME BUTTON
 07:C2C9:10 08     BPL $C2D3                  ;if A button not pressed on last frame, finish this routine
 07:C2CB:A5 46     LDA $0046 = #$00
 07:C2CD:10 04     BPL $C2D3                  ;if A button not pressed this frame, finish this routine
 07:C2CF:B5 47     LDA $47,X @ $0146 = #$FF
 07:C2D1:29 7F     AND #$7F         ;if A was pushed on both this and the last frame, set as not pushed
 07:C2D3:95 48     STA $48,X @ $0147 = #$FF   ;store CURRENT BUTTONS PUSHED
 07:C2D5:60        RTS
and 13 FFs (up to and including address $1C2F2).

BTW, I'm thinking I should try to gather all of Pikachumanson's Outlanders posts into one thread? :)

Thanks mike! As usual you are the man. I think you should merge my Outlander's threads too! It'd make for a great tutorial for the next crop of romhackers coming up.

The code worked like a charm by the way!
« Last Edit: March 05, 2013, 04:04:55 pm by Pikachumanson »

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7067
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #27 on: March 05, 2013, 03:30:38 pm »
I assume you're including the headers. Assuming the ROM has been expanded by doubling the PRG and copying/moving the last 16KB of PRG-ROM to keep it the last 16KB PRG-ROM like it should be, then yes, $3C000-3C00F is the last 16 bytes of the last non-fixed bank. $3C010 is the START of the fixed bank.
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #28 on: March 05, 2013, 04:07:48 pm »
 :-\ Hmm... just as I thought. Well guess I'll try and figure out what to do with that extra 13 bytes you gave me!

March 06, 2013, 07:41:50 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Ok, new problem. I just  realized that my UNROM is seeing the expansion banks as mirrored where if it was a UOROM that would not be the case.

How do I convert to a UOROM? Before the rom was expanded there was an 8 on the fifth byte. When it was expanded it changed to a 10. So I poked around on NESDEV and got the idea to change it 16. But the game would not start after I did so.

How would you guys handle that or maybe I can change to some other mapper that handles 16 banks? Is it a simple matter of changing the header up?
« Last Edit: March 06, 2013, 07:41:50 pm by Pikachumanson »

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7067
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #29 on: March 07, 2013, 01:16:36 am »
The mapper SHOULD detect UNROM or UOROM based on the ROM size byte.

I think 10 should be the right value. It is the size of PRG-ROM in multiples of 16KB (10 hex = 16. 16 x 16KB = 256KB).
"My watch says 30 chickens" Google, 2018

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #30 on: March 07, 2013, 01:22:52 am »
Ok then it must be something else I'm doing wrong. Back to the drawing board...
« Last Edit: March 10, 2013, 08:23:31 pm by Pikachumanson »

Pennywise

  • Hero Member
  • *****
  • Posts: 2354
  • I'm curious
    • View Profile
    • Yojimbo's Translations
Re: Expanding the UNROM mapper for the NES
« Reply #31 on: March 07, 2013, 01:30:53 am »
I'm not following you. Once you use nflate on the rom, it automatically becomes UOROM, the 256kb variant of mapper 2. Are you wondering how you access to expanded space? If so, it done the same way as original space.

You also need to drop the whole UN/UOROM thing. The only difference between the two is the size of the ROM, one is 128kb, the other is 256kb.
« Last Edit: March 07, 2013, 01:45:21 am by Pennywise »

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: Expanding the UNROM mapper for the NES
« Reply #32 on: March 07, 2013, 02:00:21 am »
Ok here is what i have done, after i put in kingmike's controller routine into my rom i was left with 13 bytes of space. So i tried putting some of the reset up where my bank is located into that space. That wouldn't work so i made a new bank with expansion there and it worked with just fine when i called the original from that address. So i try the expanded address and it worked or so I thought. All it was doing was seeing it as bank 4 through the pointer when I wanted bank 8. When i tried to change the pointer to where it was in the new bank i just got garbled sprites and frozen game.

I think my whole problem is I need to expand my bank tables but I can't really find a space to do it. Should i just erase the original and replace the addresses in the fixed bank with the new bank? I won't need those addresses for the rest of the rom will i?

Edit: i did the bankswitch in the 3f1ee area by the way.

Or maybe... I can put the bankswitch where the old menu data is by doing something like this..
   
   lda #8 ;expanded menu bank
   sta $e2c3
   
Edit 2: that didn't work so um... How the heck do you split up a reset routine and still get it to work? I got the reset vector that much I know, what i wanna do is take the first 8 bytes and put it where my controller routine ends and then make a pointer or vector to the rest of it. Is that possible?

Edit 3: Yes it is!! Now on to switching that bank!

March 10, 2013, 11:03:53 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Ok, I've been studying this code and I think I finally have an understand of it.

$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
;reads the bytes from ram.
$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
;This ^ up here is the bank where the the pointer A18C is located.
$BDCD:B1 2A     LDA ($2A),Y @ $B5E2 = #$A1         A:B5 X:00 Y:00 S:4A P:nvUBdIZc 
;This ^up here is the first byte of A18C pointer along with the address.

$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
;This is the second byte of A1 along with the address

$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
;This part of the routine sets the address for the pointer.
P:NvUBdIzc


I don't understand all the code but I keep looking at it because I know if I can change that A18C pointer to one of my expanded banks then maybe I can finally make the rom see the data I moved. I'm not asking for much just an explanation of the code or at least a nod to say I am on the right track.


March 11, 2013, 03:18:23 am - (Auto Merged - Double Posts are not allowed before 7 days.)
------------------------------------------

Aaaahh... I get it! NVM!
« Last Edit: March 11, 2013, 03:18:23 am by Pikachumanson »

Dr. Floppy

  • Restricted Access
  • Hero Member
  • *
  • Posts: 970
  • Make America GREAT Again!
    • View Profile
    • BaddestHacks.net
Re: Expanding the UNROM mapper for the NES
« Reply #33 on: March 12, 2013, 08:44:39 pm »
Converting to MMC1 seems way out of my league when I am struggling with bankswitching.

Not necessarily. Converting ROM's to more friendly mappers is one of the most rewarding aspects of this hobby. And, once you get it down, it's surprisingly straightforward.  :crazy: