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

Author Topic: SNES - How to change what controller buttons do  (Read 4396 times)

DarknessSavior

  • Hero Member
  • *****
  • Posts: 5031
  • Darkness.
    • View Profile
    • DS: No, not the Nintendo one.
SNES - How to change what controller buttons do
« on: December 29, 2012, 07:35:20 pm »
One of the biggest problems with my FFIV hack right now is that after I made the items one-line, the d-pad controls are somewhat screwy. Up and down move up and down three items each, while left and right go up and down one item each.

KingMike suggested that I simply swap the functions of the two, and disable left and right.

How is this done on the SNES? I know this likely has to do with the controller registers 4218-421F, but I don't really understand how it works at all. Anomie's guide doesn't really explain it in an easy-to-understand manner either.

Any help would be greatly appreciated.

~DS
Red Comet: :'( Poor DS. Nobody loves him like RC does. :'(
Sliver-X: LET ME INFRINGE UPON IT WITH MY MOUTH
DSRH - Currently working on: Demon's Blazon, Romancing SaGa, FFIV EasyType.
http://www.youtube.com/user/DarknessSavior

Lestat

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: SNES - How to change what controller buttons do
« Reply #1 on: December 29, 2012, 08:20:27 pm »

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 6928
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: SNES - How to change what controller buttons do
« Reply #2 on: December 30, 2012, 02:06:36 am »
How is this done on the SNES? I know this likely has to do with the controller registers 4218-421F, but I don't really understand how it works at all. Anomie's guide doesn't really explain it in an easy-to-understand manner either.
Probably reading $4218-4219, then using AND to mask out the bits that don't correspond to the desired buttons.

Let's just create a trace log.
Open that game up in SNES9x Tracer. Open the menu. Turn on tracing. Push a few buttons to make stuff happen.
Open that trace file in a hex editor. Look for access to $4218 (search for ":4218]")

This is from FF2.
Spoiler:
Code: [Select]
$14/FD28 A0 18 42    LDY #$4218              A:0000 X:0100 Y:6800 D:0100 DB:00 S:02DF P:envMxdIZcHC:0702 VC:256 00 FL:14
$14/FD2B A2 04 00    LDX #$0004              A:0000 X:0100 Y:4218 D:0100 DB:00 S:02DF P:envMxdIzcHC:0726 VC:256 00 FL:14
$14/FD2E A9 04       LDA #$04                A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DF P:envMxdIzcHC:0750 VC:256 00 FL:14
;number of bytes to read (4218-421B, controllers 1 and 2)
$14/FD30 48          PHA                     A:0004 X:0004 Y:4218 D:0100 DB:00 S:02DF P:envMxdIzcHC:0766 VC:256 00 FL:14
$14/FD31 5A          PHY                     A:0004 X:0004 Y:4218 D:0100 DB:00 S:02DE P:envMxdIzcHC:0788 VC:256 00 FL:14
$14/FD32 20 90 FD    JSR $FD90  [$00:FD90]   A:0004 X:0004 Y:4218 D:0100 DB:00 S:02DC P:envMxdIzcHC:0818 VC:256 00 FL:14

$14/FD90 AD B8 16    LDA $16B8  [$00:16B8]   A:0004 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIzcHC:0864 VC:256 00 FL:15
$14/FD93 25 40       AND $40    [$00:0140]   A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:0896 VC:256 00 FL:15
$14/FD95 F0 1D       BEQ $1D    [$FDB4]      A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:0920 VC:256 00 FL:15
$14/FDB4 B9 00 00    LDA $0000,y[$00:4218]   A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:0942 VC:256 00 FL:15
$14/FDB7 19 02 00    ORA $0002,y[$00:421A]   A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:0972 VC:256 00 FL:15
;check which buttons are pushed on either or both controllers
$14/FDBA F0 04       BEQ $04    [$FDC0]      A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:1002 VC:256 00 FL:15
;branch to $fdc0 if no buttons are pressed
$14/FDBC D5 04       CMP $04,x  [$00:0109]   A:0001 X:0005 Y:4219 D:0100 DB:00 S:02DA P:envMxdIzcHC:0184 VC:257 00 FL:15
$14/FDBE F0 09       BEQ $09    [$FDC9]      A:0001 X:0005 Y:4219 D:0100 DB:00 S:02DA P:envMxdIzCHC:0214 VC:257 00 FL:15
$14/FDC0 95 04       STA $04,x  [$00:0108]   A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:1024 VC:256 00 FL:15
$14/FDC2 95 00       STA $00,x  [$00:0104]   A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:1054 VC:256 00 FL:15
;store the buttons pushed to both $0104-$0107 (buttons newly pushed this check) and $0108-010B (buttons held)
$14/FDC4 A9 18       LDA #$18                A:0000 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIZcHC:1084 VC:256 00 FL:15
$14/FDC6 95 08       STA $08,x  [$00:010C]   A:0018 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIzcHC:1100 VC:256 00 FL:15
;store #$18 to $010C-010F. Unknown purpose
$14/FDC8 60          RTS                     A:0018 X:0004 Y:4218 D:0100 DB:00 S:02DA P:envMxdIzcHC:1130 VC:256 00 FL:15
;same button pushed this check as last
$14/FDC9 D6 08       DEC $08,x  [$00:010D]   A:0001 X:0005 Y:4219 D:0100 DB:00 S:02DA P:envMxdIZCHC:0236 VC:257 00 FL:13
$14/FDCB F0 03       BEQ $03    [$FDD0]      A:0001 X:0005 Y:4219 D:0100 DB:00 S:02DA P:envMxdIzCHC:0280 VC:257 00 FL:13
;erase the button pushed data
$14/FDCD 74 00       STZ $00,x  [$00:0105]   A:0001 X:0005 Y:4219 D:0100 DB:00 S:02DA P:envMxdIzCHC:0296 VC:257 00
FL:13
$14/FDCF 60          RTS                     A:0001 X:0005 Y:4219 D:0100 DB:00 S:02DA P:envMxdIzCHC:0326 VC:257 00 FL:13


$14/FD35 7A          PLY                     A:0018 X:0004 Y:4218 D:0100 DB:00 S:02DC P:envMxdIzcHC:1172 VC:256 00 FL:14
$14/FD36 68          PLA                     A:0018 X:0004 Y:4218 D:0100 DB:00 S:02DE P:envMxdIzcHC:1208 VC:256 00 FL:14
$14/FD37 E8          INX                     A:0004 X:0004 Y:4218 D:0100 DB:00 S:02DF P:envMxdIzcHC:1236 VC:256 00 FL:14
$14/FD38 C8          INY                     A:0004 X:0005 Y:4218 D:0100 DB:00 S:02DF P:envMxdIzcHC:1250 VC:256 00 FL:14
$14/FD39 3A          DEC A                   A:0004 X:0005 Y:4219 D:0100 DB:00 S:02DF P:envMxdIzcHC:1264 VC:256 00 FL:14
$14/FD3A D0 F4       BNE $F4    [$FD30]      A:0003 X:0005 Y:4219 D:0100 DB:00 S:02DF P:envMxdIzcHC:1278 VC:256 00 FL:14
Well, that's a start. You'll have to follow the routines to find out where it's doing something with the data it reads.

Might be easier if you know the RAM addresses that hold the index of the item currently pointed to. (maybe using a cheat search?)
"My watch says 30 chickens" Google, 2018

DarknessSavior

  • Hero Member
  • *****
  • Posts: 5031
  • Darkness.
    • View Profile
    • DS: No, not the Nintendo one.
Re: SNES - How to change what controller buttons do
« Reply #3 on: December 30, 2012, 03:13:45 pm »
I did what you suggested, but most of the logs (I didn't check them all, there's something like 30+) show that routine as simply loading nothing.

Code: [Select]
$14/FD90 AD B8 16    LDA $16B8  [$00:16B8]   A:0004 X:0004 Y:4218 P:envMxdIzc
$14/FD93 25 40       AND $40    [$00:0140]   A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FD95 F0 1D       BEQ $1D    [$FDB4]      A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDB4 B9 00 00    LDA $0000,y[$00:4218]   A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDB7 19 02 00    ORA $0002,y[$00:421A]   A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDBA F0 04       BEQ $04    [$FDC0]      A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDC0 95 04       STA $04,x  [$00:0108]   A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDC2 95 00       STA $00,x  [$00:0104]   A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDC4 A9 18       LDA #$18                A:0000 X:0004 Y:4218 P:envMxdIZc
$14/FDC6 95 08       STA $08,x  [$00:010C]   A:0018 X:0004 Y:4218 P:envMxdIzc
$14/FDC8 60          RTS                     A:0018 X:0004 Y:4218 P:envMxdIzc

Is there a more precise way to see what it's doing when I move up/down versus left/right?

~DS
Red Comet: :'( Poor DS. Nobody loves him like RC does. :'(
Sliver-X: LET ME INFRINGE UPON IT WITH MY MOUTH
DSRH - Currently working on: Demon's Blazon, Romancing SaGa, FFIV EasyType.
http://www.youtube.com/user/DarknessSavior

justin3009

  • Hero Member
  • *****
  • Posts: 1617
  • Welp
    • View Profile
Re: SNES - How to change what controller buttons do
« Reply #4 on: December 30, 2012, 03:22:30 pm »
Wouldn't you have to trace log everything just by having the menu loaf, stop it, start a new trace log and press the arrow you want, stop and check that log?

Trace once by the way. It's not always 100%  depending, but that should garner you results
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

STARWIN

  • Sr. Member
  • ****
  • Posts: 449
    • View Profile
Re: SNES - How to change what controller buttons do
« Reply #5 on: December 31, 2012, 11:58:41 am »
I don't think you want to change the key reading routine, if it is global. Following the pointed-to index sounds like a better approach. I checked some snes debugger emulators because this sounds like a fun introduction to SNES, but didn't yet find a nice tool for me. My first try would be checking a realtime ram view to find the index location and then set a write breakpoint there.

edit: Well, Geiger's debugger has an acceptable quality level, now that I could download that microsoft thing it needs. So, for fun, I did the first part. I don't really care if you know all this already, of course. RAM locations as shown in the tool (I don't know snes arch):

7E0193 & 7E0194 - changes with item page (effect, not logical state)
7E1B23 - vertical location of cursor wrt screen
7E1B22 - horizontal location of cursor
7E1B1A - vertical page offset from beginning

and that should be all. I just moved the cursor in the item menu. Hopefully relevant to the topic.

edit2: just for fun, some analyzing:

From a bit higher routine level, routine at 01:82C0 handles key reading, methinks. Disassembly:

Code: [Select]
$01/9FC7 20 C0 82    JSR $82C0  [$01:82C0]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FCA A5 01       LDA $01    [$00:0101]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FCC 29 02       AND #$02                A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FCE F0 0B       BEQ $0B    [$9FDB]      A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FD0 AD 22 1B    LDA $1B22  [$7E:1B22]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FD3 1A          INC A                   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FD4 29 01       AND #$01                A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FD6 8D 22 1B    STA $1B22  [$7E:1B22]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FD9 D0 17       BNE $17    [$9FF2]      A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FDB A5 01       LDA $01    [$00:0101]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FDD 29 01       AND #$01                A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FDF F0 0B       BEQ $0B    [$9FEC]      A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FE1 AD 22 1B    LDA $1B22  [$7E:1B22]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FE4 1A          INC A                   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FE5 29 01       AND #$01                A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FE7 8D 22 1B    STA $1B22  [$7E:1B22]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FEA F0 58       BEQ $58    [$A044]      A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FEC A5 01       LDA $01    [$00:0101]   A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FEE 29 08       AND #$08                A:0000 X:0140 Y:6800 P:envMxdIZc
$01/9FF0 F0 4C       BEQ $4C    [$A03E]      A:0000 X:0140 Y:6800 P:envMxdIZc
...

Note that keystate affects RAM locations 0101, 0103, 0105, 0109 at least. 0101 seems to be the one that is used when down is pressed in item menu. Trace related to the above disasm, when down is pressed and 1B23 is increased by one (pressing right will also result in its increase when 1b22 is set):

Code: [Select]
$01/9FCA A5 01       LDA $01    [$00:0101]   A:0411 X:0140 Y:6800 P:envMxdIzc
$01/9FCC 29 02       AND #$02                A:0404 X:0140 Y:6800 P:envMxdIzc
$01/9FCE F0 0B       BEQ $0B    [$9FDB]      A:0400 X:0140 Y:6800 P:envMxdIZc
$01/9FDB A5 01       LDA $01    [$00:0101]   A:0400 X:0140 Y:6800 P:envMxdIZc
$01/9FDD 29 01       AND #$01                A:0404 X:0140 Y:6800 P:envMxdIzc
$01/9FDF F0 0B       BEQ $0B    [$9FEC]      A:0400 X:0140 Y:6800 P:envMxdIZc
$01/9FEC A5 01       LDA $01    [$00:0101]   A:0400 X:0140 Y:6800 P:envMxdIZc
$01/9FEE 29 08       AND #$08                A:0404 X:0140 Y:6800 P:envMxdIzc
$01/9FF0 F0 4C       BEQ $4C    [$A03E]      A:0400 X:0140 Y:6800 P:envMxdIZc
$01/A03E A5 01       LDA $01    [$00:0101]   A:0400 X:0140 Y:6800 P:envMxdIZc
$01/A040 29 04       AND #$04                A:0404 X:0140 Y:6800 P:envMxdIzc
$01/A042 F0 50       BEQ $50    [$A094]      A:0404 X:0140 Y:6800 P:envMxdIzc
$01/A044 AD 23 1B    LDA $1B23  [$7E:1B23]   A:0404 X:0140 Y:6800 P:envMxdIzc
$01/A047 C9 09       CMP #$09                A:0400 X:0140 Y:6800 P:envMxdIZc
$01/A049 90 45       BCC $45    [$A090]      A:0400 X:0140 Y:6800 P:eNvMxdIzc
$01/A090 1A          INC A                   A:0400 X:0140 Y:6800 P:eNvMxdIzc
$01/A091 8D 23 1B    STA $1B23  [$7E:1B23]   A:0401 X:0140 Y:6800 P:envMxdIzc

Routine 01:82C0 trace is some pages. For example, link to your FD90 is (trace):

Code: [Select]
$01/9FC7 20 C0 82    JSR $82C0  [$01:82C0]   A:0001 X:0140 Y:6800 P:envMxdIzc

$01/82C0 20 B6 82    JSR $82B6  [$01:82B6]   A:0001 X:0140 Y:6800 P:envMxdIzc

$01/82B6 22 03 FD 14 JSL $14FD03[$14:FD03]   A:0001 X:0140 Y:6800 P:envMxdIzc

$14/FD03 4C 12 FD    JMP $FD12  [$14:FD12]   A:0001 X:0140 Y:6800 P:envMxdIzc
$14/FD12 8B          PHB                     A:0001 X:0140 Y:6800 P:envMxdIzc
$14/FD13 DA          PHX                     A:0001 X:0140 Y:6800 P:envMxdIzc
$14/FD14 5A          PHY                     A:0001 X:0140 Y:6800 P:envMxdIzc
$14/FD15 0B          PHD                     A:0001 X:0140 Y:6800 P:envMxdIzc
$14/FD16 A9 00       LDA #$00                A:0001 X:0140 Y:6800 P:envMxdIzc
$14/FD18 48          PHA                     A:0000 X:0140 Y:6800 P:envMxdIZc
$14/FD19 AB          PLB                     A:0000 X:0140 Y:6800 P:envMxdIZc
$14/FD1A A2 00 01    LDX #$0100              A:0000 X:0140 Y:6800 P:envMxdIZc
$14/FD1D DA          PHX                     A:0000 X:0100 Y:6800 P:envMxdIzc
$14/FD1E 2B          PLD                     A:0000 X:0100 Y:6800 P:envMxdIzc
$14/FD1F AD 12 42    LDA $4212  [$00:4212]   A:0000 X:0100 Y:6800 P:envMxdIzc
$14/FD22 29 01       AND #$01                A:0082 X:0100 Y:6800 P:eNvMxdIzc
$14/FD24 D0 F9       BNE $F9    [$FD1F]      A:0000 X:0100 Y:6800 P:envMxdIZc
$14/FD26 64 EC       STZ $EC    [$00:01EC]   A:0000 X:0100 Y:6800 P:envMxdIZc
$14/FD28 A0 18 42    LDY #$4218              A:0000 X:0100 Y:6800 P:envMxdIZc
$14/FD2B A2 04 00    LDX #$0004              A:0000 X:0100 Y:4218 P:envMxdIzc
$14/FD2E A9 04       LDA #$04                A:0000 X:0004 Y:4218 P:envMxdIzc
$14/FD30 48          PHA                     A:0004 X:0004 Y:4218 P:envMxdIzc
$14/FD31 5A          PHY                     A:0004 X:0004 Y:4218 P:envMxdIzc
$14/FD32 20 90 FD    JSR $FD90  [$14:FD90]   A:0004 X:0004 Y:4218 P:envMxdIzc

FD90 seems to be called four times in the larger trace, inside 82C0.

Analyzing at this level is still easier than hacking it, of course.

edit3:

perhaps this disassembly helps

http://pastebin.com/HA1MMTaE

don't pay attention to 0601, it is 0101, i'm sure!

BEQ is taken if nothing is pressed
« Last Edit: January 01, 2013, 11:29:18 am by STARWIN »

DarknessSavior

  • Hero Member
  • *****
  • Posts: 5031
  • Darkness.
    • View Profile
    • DS: No, not the Nintendo one.
Re: SNES - How to change what controller buttons do
« Reply #6 on: January 04, 2013, 03:09:52 pm »
Thank you very much for looking into that for me! I really didn't expect anyone to go that far for this.

I've been, and still am, pretty sick lately, so I'll definitely look into it when I'm feeling better.

Thanks again!

~DS
Red Comet: :'( Poor DS. Nobody loves him like RC does. :'(
Sliver-X: LET ME INFRINGE UPON IT WITH MY MOUTH
DSRH - Currently working on: Demon's Blazon, Romancing SaGa, FFIV EasyType.
http://www.youtube.com/user/DarknessSavior

STARWIN

  • Sr. Member
  • ****
  • Posts: 449
    • View Profile
Re: SNES - How to change what controller buttons do
« Reply #7 on: January 04, 2013, 04:25:27 pm »
The above may or may not be relevant to the actual solution. I merely documented how I would approach the problem. It confuses me a bit how you can do some changes and end up in a situation like that, in case those RAM locations are unfamiliar to you. I hope the logical state of the game is in sync with what you see in your hack. I only considered menu -> item ingame, so I'm unsure if you meant that particular menu, or perhaps battle item menu. But, yeah, it's your hack so I'll try not to steal all the fun.  :police:

Although this is probably an easy hack, if you :banghead: later with this, I don't mind taking an another look at it.