No worries, hopefully the issue is fixed soon, it seems like an interesting game!@awesomeee
I didn't know this topic had already been discussed, sorry.
No worries, hopefully the issue is fixed soon, it seems like an interesting game!@awesomeee
I didn't know this topic had already been discussed, sorry.
According to this old pre-release review the actions with motion controls are waggle based. https://www.nintendoworldreport.com/hands-on-preview/17000/tenchu-shadow-assassins-wii^
|
Post automatically merged:
Does that game use motion controls a lot? What specific movements happen?

Building on your mapping and identifying all the relevant functions (nice work), here's what I've got for Max currently:Sounds good! Ill modify your Rhythm Heaven ASM soon and give it better mappings
Post automatically merged:
Hello @Vague Rant ! Here is the modifed ASM that has some example mappings for Max. Make sure to add the extension data stuff
Make sure to change any values aswell if some are incorrect.
; bypass nunchuk error
; 8002C578 for USA
lwz r0, 0x8(sp)
cmpwi r0, 2
bne- RETURN
li r0, 1
RETURN:
; read_kpad_acc
; 8044BF94 for USA
lfs f1, 0x4DC(r30)
; magic
bl GRAB
MAGIC:
CONTINUE: .int 0
SHAKE: .float 3.4
GRAB:
mflr r4
lwz r3, CONTINUE-MAGIC(r4)
cmpwi r3, 0
ble- NEW_SHAKE
subi r3, r3, 1
b DO_SHAKE
NEW_SHAKE:
lwz r3, 0x4(r30)
andi. r0, r3, 0x80
beq- RETURN
li r3, 5
DO_SHAKE:
lfs f1, SHAKE-MAGIC(r4)
cmpwi r20, 1
bne- RETURN
stw r3, CONTINUE-MAGIC(r4)
; hold B for player
lwz r3, 0x0(r30)
ori r3, r3, 0x400
stw r3, 0x0(r30)
lwz r3, 0x8(r30)
andi. r3, r3, 0xFBFF
stw r3, 0x8(r30)
RETURN:
; calc_dpd_variable
; 8044C9D8 for USA
stw r0, 0x24(sp)
; player using real pointer? (gravity already valid)
cmpwi r4, 0x0
bne- NO_CLASSIC
; check for Classic Controller
lbz r0, 0x5C(r3)
cmpwi r0, 0x2
bne- NO_CLASSIC
stb r0, 0x5E(r3)
cmpwi r20, 0x1
bne- RETURN
; magic
bl GRAB
MAGIC:
GETASPECT: .int 0x80468490 ; USA 0x80468490
ASPECT: .float 1.3333333333
MULTIPLIER: .float 0.025 ; pointer speed
MAX_RANGE: .float 1.0
GRAB:
mflr r5
DELTA:
lwz r3, GETASPECT-MAGIC(r5) ; SCGetAspectRatio()
cmplwi r3, 0x1
ble- CHECK_ASPECT
; run aspect ratio check
stw r5, 0x0C(sp) ; save magic pointer
mtlr r3
blrl
lwz r5, 0x0C(sp) ; restore magic pointer
stw r3, GETASPECT-MAGIC(r5)
CHECK_ASPECT:
cmpwi r3, 0x1
mr r3, r31 ; restore input pointer
lfs f2, ASPECT-MAGIC(r5)
bne- FULLSCREEN
fmuls f2, f2, f2 ; widescreen
FULLSCREEN:
lfs f3, MULTIPLIER-MAGIC(r5)
; pointer X axis
lfs f0, 0x20(r3)
lfs f1, 0x74(r3) ; right stick X
fdiv f1, f1, f2 ; divide by aspect ratio
bl RANGE_CHECK
stfs f0, 0x20(r3)
; pointer Y axis
lfs f0, 0x24(r3)
lfs f1, 0x78(r3) ; right stick Y
fneg f1, f1
lfs f2, MAX_RANGE-MAGIC(r5)
bl RANGE_CHECK
stfs f0, 0x24(r3)
RETURN:
lwz r0, 0x24(sp)
mtlr r0
addi sp, sp, 0x20
blr
RANGE_CHECK:
fmadd f0, f1, f3, f0
fcmpu cr0, f0, f2
blt CHECK_NEGATIVE
fmr f0, f2
b IN_RANGE
CHECK_NEGATIVE:
fneg f2, f2
fcmpu cr0, f0, f2
bgt IN_RANGE
fmr f0, f2
IN_RANGE:
blr
NO_CLASSIC:
read_kpad_ext
stick redirection
USA
0444D8D0 7FC3F378
KPADRead
drop fix
USA
0444E4F8 60000000
0444E648 60000000
; read_kpad_button
; 8044B9E4 for USA
; r4 holds extType
; r6 holds wiimote bitfield
; r7 holds wiimote+nunchuk bitfield
; r8 holds classic bitfield
; magic
mflr r9
bl GRAB
MAGIC:
HELD: .double 0
GRAB:
mflr r10
mtlr r9
slwi r9, r25, 1
add r10, r10, r9
; check dropped extension
cmplwi r8, 0xFFFF
bne- CLASSIC
lhz r8, HELD-MAGIC(r10)
b DROPPED_CONNECTION
CLASSIC:
cmpwi r4, 0x2
bne- RETURN
li r4, 0x1 ; i'm a nunchuk
sth r8, HELD-MAGIC(r10)
DROPPED_CONNECTION:
CLASSIC_HOME:
andi. r9, r8, 0x800
beq- CLASSIC_UP
ori r7, r7, 0x8000 ; home
CLASSIC_UP:
andi. r9, r8, 0x1
beq- CLASSIC_DOWN
ori r7, r7, 0x8 ; up
CLASSIC_DOWN:
andi. r9, r8, 0x4000
beq- CLASSIC_LEFT
ori r7, r7, 0x4 ; down
CLASSIC_LEFT:
andi. r9, r8, 0x2
beq- CLASSIC_RIGHT
ori r7, r7, 0x1 ; left
CLASSIC_RIGHT:
andi. r9, r8, 0x8000
beq- CLASSIC_A
ori r7, r7, 0x2 ; right
CLASSIC_A:
andi. r9, r8, 0x10
beq- CLASSIC_B
ori r7, r7, 0x800 ; A (Draw Ink)
CLASSIC_B:
andi. r9, r8, 0x40
beq- CLASSIC_X
ori r7, r7, 0x2000 ; Z (Jump)
CLASSIC_X:
andi. r9, r8, 0x8
beq- CLASSIC_Y
ori r7, r7, 0x80 ; wiimote shake + B (Erases ALL Ink)
CLASSIC_Y:
andi. r9, r8, 0x20
beq- CLASSIC_L
ori r7, r7, 0x4000 ; Nunchuk C (Push and Pull objects)
CLASSIC_L:
andi. r9, r8, 0x2000
beq- CLASSIC_R
ori r7, r7, 0x4000 ; Nunchuk C (Push and Pull objects)
CLASSIC_R:
andi. r9, r8, 0x200
beq- CLASSIC_ZL
ori r7, r7, 0x2000 ; Z (Jump)
CLASSIC_ZL:
andi. r9, r8, 0x80
beq- CLASSIC_ZR
ori r7, r7, 0x400 ; B (Erase Ink)
CLASSIC_ZR:
andi. r9, r8, 0x4
beq- CLASSIC_PLUS
ori r7, r7, 0x800 ; A (Draw Ink)
CLASSIC_PLUS:
andi. r9, r8, 0x400
beq- CLASSIC_MINUS
ori r7, r7, 0x10 ; plus
CLASSIC_MINUS:
andi. r9, r8, 0x1000
beq- RETURN
ori r7, r7, 0x1000 ; minus
RETURN:
or r6, r6, r7
andi. r9, r6, 0x9FFF
C202C578 00000003
80010008 2C000002
40820008 38000001
60000000 00000000
C244BF94 0000000D
C03E04DC 4800000D
00000000 4059999A
7C8802A6 80640000
2C030000 4081000C
3863FFFF 48000014
807E0004 70600080
41820030 38600005
C0240004 2C140001
40820020 90640000
807E0000 60630400
907E0000 807E0008
7063FBFF 907E0008
60000000 00000000
C244C9D8 0000001C
90010024 2C040000
408200D0 8803005C
2C000002 408200C4
9803005E 2C140001
40820080 48000015
80468490 3FAAAAAB
3CCCCCCD 3F800000
7CA802A6 80650000
28030001 40810018
90A1000C 7C6803A6
4E800021 80A1000C
90650000 2C030001
7FE3FB78 C0450004
40820008 EC4200B2
C0650008 C0030020
C0230074 FC211024
48000031 D0030020
C0030024 C0230078
FC200850 C045000C
48000019 D0030024
80010024 7C0803A6
38210020 4E800020
FC0100FA FC001000
4180000C FC001090
48000014 FC401050
FC001000 41810008
FC001090 4E800020
60000000 00000000
0444D8D0 7FC3F378
0444E4F8 60000000
0444E648 60000000
C244B9E4 00000020
7D2802A6 4800000D
00000000 00000000
7D4802A6 7D2803A6
5729083C 7D4A4A14
2808FFFF 4082000C
A10A0000 48000014
2C040002 408200C0
38800001 B10A0000
71090800 41820008
60E78000 71090001
41820008 60E70008
71094000 41820008
60E70004 71090002
41820008 60E70001
71098000 41820008
60E70002 71090010
41820008 60E70800
71090040 41820008
60E72000 71090008
41820008 60E70080
71090020 41820008
60E74000 71092000
41820008 60E74000
71090200 41820008
60E72000 71090080
41820008 60E70400
71090004 41820008
60E70800 71090400
41820008 60E70010
71091000 41820008
60E71000 7CC63B78
70C99FFF 00000000
Me too. Race-O-Rama is definitely the most complicated of the Cars trilogy because a bunch of the minigames are motion-controlled QTEs. But there's a pretty good chance it'll happen.Since you've done Mater-National i assume you're also going to do Race-o-rama right? I've wanted to try that one for a while.
The original Wiimote shake should definitely still work for the times when it's needed. Anybody with knowledge of assembly hacking Wii games could get it implemented. Obviously I've let it sit in my backlog for quite a while but I don't think it should be an extremely complex game. As I understand it, it tilting side-to-side for one minigame and generic shaking for a badge that lets you do extra damage by jumping on enemies or something?Hello, thank you for the amazing work you've done on these hacks (along with the contributions of the other members as well)!
For the case of the missing shake support in super paper mario, can i still utilize the shake of the wiimote while using the classic control hack? and is there a way any one of us can help add it to the classic control hack? thanks again.
0x58(r3) for horizontal Wiimote tilting (e.g. steering), so if Paper Mario works like that, then it's basically a matter of reading in the X axis of the Right Stick (a range from -1 to +1) from 0x74(r3), maybe multiplying it by 0.5 or something then writing it to the tilt address. The accelerometer tilt is also from -1 to +1, but most games don't expect you to tilt the full 180 degrees, so you also want to reduce the value of the stick.; calc_acc_vertical
; note: these are NSMBW addresses, not Paper Mario
; 801EB038 for USA (Rev 1/2)
; 801EB178 for EUR (Rev 2)
; 801EAE48 for JPN (Rev 2)
; 801EB578 for KOR
stw r0, 0x44(r1)
; check if this is a classic controller
lbz r0, 0x5C(r3)
cmpwi r0, 0x2
bne- RETURN
; magic
bl GRAB
MAGIC:
RANGE: .float 0.5
GRAB:
mflr r5
lfs f0, RANGE-MAGIC(r5)
; load in right stick, constrain and write
lfs f1, 0x74(r3)
fmuls f0, f0, f1
stfs f0, 0x58(r3)
; restore lr and stack then get outta here
lwz r0, 0x44(sp)
mtlr r0
addi sp, sp, 0x40
blr
RETURN:
To remap B to B in Epic Mickey, you'll want to Ctrl+F for this part in the code:Hello, I would like to map the B of the Wiimote to the B of the Classic Controller in Epic Mickey. I think it's okay to only jump with A and in return be able to cancel with B in the menu. How do I do that?
60C60800 71000040
41820008 60C60800
0800 (A), the one at the end, with 0400 (B), so you've got this:60C60800 71000040
41820008 60C60400
8 to a 4, the rest is just so you know which 8 is the right one to change.I included a couple of extra options in the Technical Notes section for Mario Kart Wii which you might like better when using a mix of Classic Controller generations. The "main" version of the code I made definitely assumes you have easy access to the ZL/ZR buttons which are obviously not very convenient on the original Classic. However, in the Technical Notes there's a code which swaps L/R with ZL/ZR. I labelled it as L Item, R Drift, ZL/ZR/D-Pad Wheelie. I think that one is probably ideal when using both types of CC simultaneously, because all of them have reasonably easy access to L/R. With that version, you can still wheelie with the Z buttons or D-Pad but otherwise the control layout is much closer to Mario Kart 8.hi there, I had a question about mario kart wii's MK8 controller hack:
if using a mix of classic controller and classic controller pro, should i leave controls to default, or is there a compromise that can be used to improve the experience on both? thanks.
Aha, yeah, the registers are not always consistent across SDK versions. The button mapper needs a "garbage" register it can replace over and over while doing button checks. Each of theHello again @Vague Rant Im running into a new issue with the pointer / buttons.
For some reason, Adding the pointer code is causing everything to drag to the right of the screen. It also causes some buttons (I think) to be held for some reason. Any idea why everything is breaking when the Pointer code is added?
EDIT: I dont know if its specificially the pointer code, but its very weird. It also breaks WPAD inputs (Wii Remote)
EDIT 2: Its not the pointer problem. But it seems to be with the games that use KPAD differently. The one below
On a seperate note, how do you handle games with andi. r6, r9, 0x9FFF? Games that handle KPAD way differently. Im trying to finish one of my hacks but it handles KPAD differently, and that instruction in read_kpad_button looks different. Thanks.
Post automatically merged:
Update: Max and the Magic Marker seems to use andi. r6, r9, 0x9FFF aswellThat will make things complicated if the same issue arises
andi. instructions in the button injector replaces the value in the first register. The button mapping code I gave in the tutorial, for Rhythm Heaven, uses r0 as the garbage register, because after the button injection finishes, the game populates r0 itself, so it doesn't matter what we left behind.r9 where other games would use r0, so we need to make r9 our garbage register instead. If you scroll back up to the start of this post, you can look at the button injector code I used for Max and see that I've made r9 the garbage register, so that's the one we dump the output in each time we check a button.Whoops, you've spotted an error in the Technical Notes I wrote up for Lego Star Wars. That was a pretty early Wii game, before@Vague Rant I am currently trying to replicate the button-hack for Lego Star Wars - The Complete Saga from your guide. (I want to get familiar with creating gecko hacks, so that i eventually might be able to fix Lego Star Wars 3, Back To The Future and some others if i stumble upon issues. (I have no idea if that will be possible with my skillset, i am currently in the hubris-phase)
The problem with my own hack is, that it does not work. I have identified the adress (8032f380) of the andi-instruction, but it differs from the one in your hack (which does work, as far as i can tell)
The adress in your hack is 8019AC18 which seems to be inside the parent call.
Is this expected, as you chose a better location for the hack for that game, or is the guide only "very" barebones?
There is also the question what happens if it is not easy to find the kpad-functions when the symbols are not recognized. (Both BTTF and LSW3 dont show any results for either kpad or select_1obj_continue).
Do you have any hints on how to approach this? Or is this simply too hard (for me)?
Thank you very much anyway, both for the existing hacks and the guide!
read_kpad_button() existed, so the injector goes directly in KPADRead(), but my notes say read_kpad_button() incorrectly I'll go back and edit that, thanks for spotting it.read_kpad_button(). I'll answer the second part below, since it's on the same subject.awesomeee did mean to breakpoint it once you've found it rather than just searching for it. Really sorry if you already know this, but a breakpoint is a feature in debuggers that pauses the application when a specific state occurs. An execution breakpoint means pausing when an instruction gets executed. In Dolphin, you can toggle an execution breakpoint by clicking to the left of the address. In this screenshot you can see where I've set a breakpoint at the beginning ofYou mean search for the symbol "WPADProbe"?
The WPADProbe only calls externally to manage interrupts, otherwise it is pretty much self-contained. Is WPADProbe a child function of KPADRead?
WPADProbe(), because there's a little circle indicating an execution breakpoint, which is where I clicked.KPADRead() is to pause Dolphin, search for WPADProbe(), set a breakpoint at the start, then resume execution in Dolphin. It will stop again almost instantly, because WPADProbe() usually runs 3, 4 or more times on each frame, called from all over the place. As you correctly guessed, one of those callers is KPADRead().WPADProbe() gets called. If you're in the situation where the select_1obj_continue() approach isn't working, it's most likely that Dolphin has not recognized KPADRead() as a function at all, so in the Callstack panel in the top left, KPADRead() will show up as ---.--- you see is KPADRead() as there may be multiple unrecognized functions, but basically you just want to keep resuming Dolphin until you see --- as caller, then click it in the Callstack and try to figure out whether you're looking at KPADRead() by scrolling down and seeing if you recognize anything from the tutorial, like the three read calls in a row (stick/ext, acc and dpd), although obviously with autogenerated names, not the real ones.It does look like a pretty complicated one, with different motions for attacks and finishers and stuff. I'll add it to my list, but it's going in the complicated section with other games I've either struggled or failed with.Any chance you could try with Tenchu: Shadow Assassins? Since the game was ported to PSP maybe it could serve as a prompt guideline for the Classic Controller.
I've literally never heard of this game, interesting one. I actually just successfully looked at another game from Incinerator Studios which also had things triggered by motions, so while it does look somewhat complex, maybe we'll get lucky and I can leverage previous work on it. Fingers crossed.Someone make classic controller patch or at least take a look at SpongeBob SquarePants featuring NickToons: Globs of Doo
Wondering about make it so wii ver has controller support is batter ver of game over ps2 port.
Classic Controller Support [Vague Rant]
C209A8C4 00000005
880DE234 2C000002
40820008 38000001
2C000001 41820008
38000000 901D0544
60000000 00000000
C20AE100 00000005
88ADE234 2C050002
40820008 38A00001
2C050001 41820008
38A00000 98BF006C
60000000 00000000
040AE11C 60000000
C227CDAC 00000002
28000001 41820008
28000002 00000000
C227CF54 00000002
28000001 41820008
28000002 00000000
C227D4B4 00000002
28000001 41820008
28000002 00000000
C23650D8 00000008
8803005C 2C000002
40820030 48000009
4059999A 7CA802A6
C0250000 C0030074
EC000072 D01E04D8
C0830078 EC840072
FC002050 D01E04DC
80C3000C 00000000
C2365B48 0000001F
90010024 2C040000
408200E8 8803005C
2C000002 408200DC
9803005E 2C140001
40820094 48000015
80320E50 3FAAAAAB
3D4CCCCD 3F800000
7CA802A6 80030004
70008000 41820010
38000000 90030020
90030024 80650000
28030001 40810018
90A1000C 7C6803A6
4E800021 80A1000C
90650000 2C030001
7FE3FB78 C0450004
40820008 EC4200B2
C0650008 C0030020
C0230060 FC211024
4800002D D0030020
C0030024 C0230064
FC200850 48000019
D0030024 80010024
7C0803A6 38210020
4E800020 FC0100FA
C025000C FC000800
4180000C FC000890
48000014 FC200850
FC000800 41810008
FC000890 4E800020
60000000 00000000
04366A40 7FC3F378
043677B0 60000000
04367900 60000000
C2364B54 00000020
7D2802A6 4800000D
00000000 00000000
7D4802A6 7D2803A6
5729083C 7D4A4A14
2808FFFF 4082000C
A10A0000 48000014
2C040002 408200C0
38800001 B10A0000
71090800 41820008
60E78000 71090001
41820008 60E70008
71094000 41820008
60E70004 71090002
41820008 60E70001
71098000 41820008
60E70002 71090010
41820008 60E70900
71090040 41820008
60E70400 71090008
41820008 60E70200
71090020 41820008
60E70004 71092000
41820008 60E70008
71090200 41820008
60E70001 71090080
41820008 60E72000
71090004 41820008
60E74000 71090400
41820008 60E70010
71091000 41820008
60E71000 7CC63B78
70C99FFF 00000000
Classic Controller Support [Vague Rant]
C209A8C4 00000005
880DE234 2C000002
40820008 38000001
2C000001 41820008
38000000 901D0544
60000000 00000000
C20AE100 00000005
88ADE234 2C050002
40820008 38A00001
2C050001 41820008
38A00000 98BF006C
60000000 00000000
040AE11C 60000000
C227CDEC 00000002
28000001 41820008
28000002 00000000
C227CF94 00000002
28000001 41820008
28000002 00000000
C227D4F4 00000002
28000001 41820008
28000002 00000000
C2365128 00000008
8803005C 2C000002
40820030 48000009
4059999A 7CA802A6
C0250000 C0030074
EC000072 D01E04D8
C0830078 EC840072
FC002050 D01E04DC
80C3000C 00000000
C2365B98 0000001F
90010024 2C040000
408200E8 8803005C
2C000002 408200DC
9803005E 2C140001
40820094 48000015
80320EA0 3FAAAAAB
3D4CCCCD 3F800000
7CA802A6 80030004
70008000 41820010
38000000 90030020
90030024 80650000
28030001 40810018
90A1000C 7C6803A6
4E800021 80A1000C
90650000 2C030001
7FE3FB78 C0450004
40820008 EC4200B2
C0650008 C0030020
C0230060 FC211024
4800002D D0030020
C0030024 C0230064
FC200850 48000019
D0030024 80010024
7C0803A6 38210020
4E800020 FC0100FA
C025000C FC000800
4180000C FC000890
48000014 FC200850
FC000800 41810008
FC000890 4E800020
60000000 00000000
04366A90 7FC3F378
04367800 60000000
04367950 60000000
C2364BA4 00000020
7D2802A6 4800000D
00000000 00000000
7D4802A6 7D2803A6
5729083C 7D4A4A14
2808FFFF 4082000C
A10A0000 48000014
2C040002 408200C0
38800001 B10A0000
71090800 41820008
60E78000 71090001
41820008 60E70008
71094000 41820008
60E70004 71090002
41820008 60E70001
71098000 41820008
60E70002 71090010
41820008 60E70900
71090040 41820008
60E70400 71090008
41820008 60E70200
71090020 41820008
60E70004 71092000
41820008 60E70008
71090200 41820008
60E70001 71090080
41820008 60E72000
71090004 41820008
60E74000 71090400
41820008 60E70010
71091000 41820008
60E71000 7CC63B78
70C99FFF 00000000
| Wii Remote/Nunchuk | Classic Controller | Function |
|---|---|---|
| Wiimote Home | Home | Open/Close Home Menu |
| Wiimote D-Pad | D-Pad | Menus Navigation |
| Wiimote D-Pad Up | L | Gameplay Tilt Vehicle |
| Wiimote D-Pad Down | Y | Gameplay E-Brake |
| Wiimote D-Pad Left | R | Gameplay Reverse Camera |
| Wiimote A | A | Menus Confirm Gameplay Brake/Reverse |
| Wiimote B | B | Menus Cancel Gameplay Accelerate |
| Wiimote 1 | X | Gameplay Switch Camera |
| Wiimote 2 | A | Menus Confirm (Wiimote mode) |
| Wiimote Plus | Plus | Gameplay Pause |
| Wiimote Minus | Minus | Gameplay Switch Garage |
| Wiimote Motions | Right Stick | Gameplay Various Minigame QTEs |
| Wiimote Pointer | Left Stick | Home Button Menu Navigation |
| Nunchuk Stick | Left Stick | Menus Navigation Gameplay Steering |
| Nunchuk C | ZR | Gameplay Nitro |
| Nunchuk Z | ZL | Gameplay Powerslide |
C2: check extension controller on boot, switch to Config 2 if Nunchuk/ClassicC2 and 04: check extension controller when creating a new save, switch to Config 2 if Nunchuk/ClassicC2: bypass Nunchuk errorC2 and C2: accept Classic Controller as Nunchuk-type controllerC2 in read_kpad_acc(): fake accelerometer motions on Right StickC2 in calc_dpd_variable(): simulate IR pointer on Left Stick04 in read_kpad_ext(): stick redirection04 and 04 in KPADRead(): dropped connection fixC2 in read_kpad_button(): button injector; read_kpad_button
; 80364B54 for USA
; 80364BA4 for EUR (En,Fr,Es,It)/EUR (Fr,De)
; r4 holds extType
; r6 holds wiimote bitfield
; r7 holds wiimote+nunchuk bitfield
; r8 holds classic bitfield
; magic
mflr r9
bl GRAB
MAGIC:
HELD: .double 0
GRAB:
mflr r10
mtlr r9
slwi r9, r25, 1
add r10, r10, r9
; check dropped extension
cmplwi r8, 0xFFFF
bne- CLASSIC
lhz r8, HELD-MAGIC(r10)
b DROPPED_CONNECTION
CLASSIC:
cmpwi r4, 0x2
bne- RETURN
li r4, 0x1 ; i'm a nunchuk
sth r8, HELD-MAGIC(r10)
DROPPED_CONNECTION:
CLASSIC_HOME:
andi. r9, r8, 0x800
beq- CLASSIC_UP
ori r7, r7, 0x8000 ; home
CLASSIC_UP:
andi. r9, r8, 0x1
beq- CLASSIC_DOWN
ori r7, r7, 0x8 ; up (v) / left (h)
CLASSIC_DOWN:
andi. r9, r8, 0x4000
beq- CLASSIC_LEFT
ori r7, r7, 0x4 ; down (v) / right (h)
CLASSIC_LEFT:
andi. r9, r8, 0x2
beq- CLASSIC_RIGHT
ori r7, r7, 0x1 ; left (v) / down (h)
CLASSIC_RIGHT:
andi. r9, r8, 0x8000
beq- CLASSIC_A
ori r7, r7, 0x2 ; right (v) / up (h)
CLASSIC_A:
andi. r9, r8, 0x10
beq- CLASSIC_B
ori r7, r7, 0x900 ; a + 2
CLASSIC_B:
andi. r9, r8, 0x40
beq- CLASSIC_X
ori r7, r7, 0x400 ; b
CLASSIC_X:
andi. r9, r8, 0x8
beq- CLASSIC_Y
ori r7, r7, 0x200 ; 1
CLASSIC_Y:
andi. r9, r8, 0x20
beq- CLASSIC_L
ori r7, r7, 0x4 ; down (v) / right (h)
CLASSIC_L:
andi. r9, r8, 0x2000
beq- CLASSIC_R
ori r7, r7, 0x8 ; up (v) / left (h)
CLASSIC_R:
andi. r9, r8, 0x200
beq- CLASSIC_ZL
ori r7, r7, 0x1 ; left (v) / down (h)
CLASSIC_ZL:
andi. r9, r8, 0x80
beq- CLASSIC_ZR
ori r7, r7, 0x2000 ; z
CLASSIC_ZR:
andi. r9, r8, 0x4
beq- CLASSIC_PLUS
ori r7, r7, 0x4000 ; c
CLASSIC_PLUS:
andi. r9, r8, 0x400
beq- CLASSIC_MINUS
ori r7, r7, 0x10 ; plus
CLASSIC_MINUS:
andi. r9, r8, 0x1000
beq- RETURN
ori r7, r7, 0x1000 ; minus
RETURN:
or r6, r6, r7
andi. r9, r6, 0x9FFF

No see me game for used most normal button beside shake for some combio moves again see one more different thing get done but do hope it won't two hard of task do unsure really work all know someone make code and game they magical work with classic controller on Dophin emulatorReply-O-Rama.
Building on your mapping and identifying all the relevant functions (nice work), here's what I've got for Max currently:
I found out that this game got a sequel on Xbox 360, so I did look at that a little and edited the mapping a tiny bit (swapped X and Y IIRC?) to match that game. For L and R, I mapped them as C and Z again, so that you can in theory play entirely with the shoulder buttons and never need to take your thumb off the Right Stick.Code:; bypass nunchuk error ; 8002C578 for USA lwz r0, 0x8(sp) cmpwi r0, 2 bne- RETURN li r0, 1 RETURN:Code:; read_kpad_acc ; 8044BF94 for USA lfs f1, 0x4DC(r30) ; magic bl GRAB MAGIC: CONTINUE: .int 0 SHAKE: .float 3.4 GRAB: mflr r4 lwz r3, CONTINUE-MAGIC(r4) cmpwi r3, 0 ble- NEW_SHAKE subi r3, r3, 1 b DO_SHAKE NEW_SHAKE: lwz r3, 0x4(r30) andi. r0, r3, 0x80 beq- RETURN li r3, 5 DO_SHAKE: lfs f1, SHAKE-MAGIC(r4) cmpwi r20, 1 bne- RETURN stw r3, CONTINUE-MAGIC(r4) ; hold B for player lwz r3, 0x0(r30) ori r3, r3, 0x400 stw r3, 0x0(r30) lwz r3, 0x8(r30) andi. r3, r3, 0xFBFF stw r3, 0x8(r30) RETURN:Code:; calc_dpd_variable ; 8044C9D8 for USA stw r0, 0x24(sp) ; player using real pointer? (gravity already valid) cmpwi r4, 0x0 bne- NO_CLASSIC ; check for Classic Controller lbz r0, 0x5C(r3) cmpwi r0, 0x2 bne- NO_CLASSIC stb r0, 0x5E(r3) cmpwi r20, 0x1 bne- RETURN ; magic bl GRAB MAGIC: GETASPECT: .int 0x80468490 ; USA 0x80468490 ASPECT: .float 1.3333333333 MULTIPLIER: .float 0.025 ; pointer speed MAX_RANGE: .float 1.0 GRAB: mflr r5 DELTA: lwz r3, GETASPECT-MAGIC(r5) ; SCGetAspectRatio() cmplwi r3, 0x1 ble- CHECK_ASPECT ; run aspect ratio check stw r5, 0x0C(sp) ; save magic pointer mtlr r3 blrl lwz r5, 0x0C(sp) ; restore magic pointer stw r3, GETASPECT-MAGIC(r5) CHECK_ASPECT: cmpwi r3, 0x1 mr r3, r31 ; restore input pointer lfs f2, ASPECT-MAGIC(r5) bne- FULLSCREEN fmuls f2, f2, f2 ; widescreen FULLSCREEN: lfs f3, MULTIPLIER-MAGIC(r5) ; pointer X axis lfs f0, 0x20(r3) lfs f1, 0x74(r3) ; right stick X fdiv f1, f1, f2 ; divide by aspect ratio bl RANGE_CHECK stfs f0, 0x20(r3) ; pointer Y axis lfs f0, 0x24(r3) lfs f1, 0x78(r3) ; right stick Y fneg f1, f1 lfs f2, MAX_RANGE-MAGIC(r5) bl RANGE_CHECK stfs f0, 0x24(r3) RETURN: lwz r0, 0x24(sp) mtlr r0 addi sp, sp, 0x20 blr RANGE_CHECK: fmadd f0, f1, f3, f0 fcmpu cr0, f0, f2 blt CHECK_NEGATIVE fmr f0, f2 b IN_RANGE CHECK_NEGATIVE: fneg f2, f2 fcmpu cr0, f0, f2 bgt IN_RANGE fmr f0, f2 IN_RANGE: blr NO_CLASSIC:Code:read_kpad_ext stick redirection USA 0444D8D0 7FC3F378 KPADRead drop fix USA 0444E4F8 60000000 0444E648 60000000Code:; read_kpad_button ; 8044B9E4 for USA ; r4 holds extType ; r6 holds wiimote bitfield ; r7 holds wiimote+nunchuk bitfield ; r8 holds classic bitfield ; magic mflr r9 bl GRAB MAGIC: HELD: .double 0 GRAB: mflr r10 mtlr r9 slwi r9, r25, 1 add r10, r10, r9 ; check dropped extension cmplwi r8, 0xFFFF bne- CLASSIC lhz r8, HELD-MAGIC(r10) b DROPPED_CONNECTION CLASSIC: cmpwi r4, 0x2 bne- RETURN li r4, 0x1 ; i'm a nunchuk sth r8, HELD-MAGIC(r10) DROPPED_CONNECTION: CLASSIC_HOME: andi. r9, r8, 0x800 beq- CLASSIC_UP ori r7, r7, 0x8000 ; home CLASSIC_UP: andi. r9, r8, 0x1 beq- CLASSIC_DOWN ori r7, r7, 0x8 ; up CLASSIC_DOWN: andi. r9, r8, 0x4000 beq- CLASSIC_LEFT ori r7, r7, 0x4 ; down CLASSIC_LEFT: andi. r9, r8, 0x2 beq- CLASSIC_RIGHT ori r7, r7, 0x1 ; left CLASSIC_RIGHT: andi. r9, r8, 0x8000 beq- CLASSIC_A ori r7, r7, 0x2 ; right CLASSIC_A: andi. r9, r8, 0x10 beq- CLASSIC_B ori r7, r7, 0x800 ; A (Draw Ink) CLASSIC_B: andi. r9, r8, 0x40 beq- CLASSIC_X ori r7, r7, 0x2000 ; Z (Jump) CLASSIC_X: andi. r9, r8, 0x8 beq- CLASSIC_Y ori r7, r7, 0x80 ; wiimote shake + B (Erases ALL Ink) CLASSIC_Y: andi. r9, r8, 0x20 beq- CLASSIC_L ori r7, r7, 0x4000 ; Nunchuk C (Push and Pull objects) CLASSIC_L: andi. r9, r8, 0x2000 beq- CLASSIC_R ori r7, r7, 0x4000 ; Nunchuk C (Push and Pull objects) CLASSIC_R: andi. r9, r8, 0x200 beq- CLASSIC_ZL ori r7, r7, 0x2000 ; Z (Jump) CLASSIC_ZL: andi. r9, r8, 0x80 beq- CLASSIC_ZR ori r7, r7, 0x400 ; B (Erase Ink) CLASSIC_ZR: andi. r9, r8, 0x4 beq- CLASSIC_PLUS ori r7, r7, 0x800 ; A (Draw Ink) CLASSIC_PLUS: andi. r9, r8, 0x400 beq- CLASSIC_MINUS ori r7, r7, 0x10 ; plus CLASSIC_MINUS: andi. r9, r8, 0x1000 beq- RETURN ori r7, r7, 0x1000 ; minus RETURN: or r6, r6, r7 andi. r9, r6, 0x9FFFCode:C202C578 00000003 80010008 2C000002 40820008 38000001 60000000 00000000 C244BF94 0000000D C03E04DC 4800000D 00000000 4059999A 7C8802A6 80640000 2C030000 4081000C 3863FFFF 48000014 807E0004 70600080 41820030 38600005 C0240004 2C140001 40820020 90640000 807E0000 60630400 907E0000 807E0008 7063FBFF 907E0008 60000000 00000000 C244C9D8 0000001C 90010024 2C040000 408200D0 8803005C 2C000002 408200C4 9803005E 2C140001 40820080 48000015 80468490 3FAAAAAB 3CCCCCCD 3F800000 7CA802A6 80650000 28030001 40810018 90A1000C 7C6803A6 4E800021 80A1000C 90650000 2C030001 7FE3FB78 C0450004 40820008 EC4200B2 C0650008 C0030020 C0230074 FC211024 48000031 D0030020 C0030024 C0230078 FC200850 C045000C 48000019 D0030024 80010024 7C0803A6 38210020 4E800020 FC0100FA FC001000 4180000C FC001090 48000014 FC401050 FC001000 41810008 FC001090 4E800020 60000000 00000000 0444D8D0 7FC3F378 0444E4F8 60000000 0444E648 60000000 C244B9E4 00000020 7D2802A6 4800000D 00000000 00000000 7D4802A6 7D2803A6 5729083C 7D4A4A14 2808FFFF 4082000C A10A0000 48000014 2C040002 408200C0 38800001 B10A0000 71090800 41820008 60E78000 71090001 41820008 60E70008 71094000 41820008 60E70004 71090002 41820008 60E70001 71098000 41820008 60E70002 71090010 41820008 60E70800 71090040 41820008 60E72000 71090008 41820008 60E70080 71090020 41820008 60E74000 71092000 41820008 60E74000 71090200 41820008 60E72000 71090080 41820008 60E70400 71090004 41820008 60E70800 71090400 41820008 60E70010 71091000 41820008 60E71000 7CC63B78 70C99FFF 00000000
The accelerometer stuff for this game requires a swing that last at least 5 frames. I also set it up to hold B for those 5 frames as well, because otherwise you could easily hold the button for <5 frames and the shake would work but it would fail on the button press. This way everything seems to work reliably.
I made the IR pointer quite slow for this game because you do need to do things like draw a circle then color it in, and the fine motions are very tough at full speed. I think everything should be working with this, I was able to run through the first stage without any issues. If you could test this and see if everything works right and/or make any changes you feel like, I'll see if I can port it to EUR/JPN and create IPS patches for people playing via injection.
Me too. Race-O-Rama is definitely the most complicated of the Cars trilogy because a bunch of the minigames are motion-controlled QTEs. But there's a pretty good chance it'll happen.
The original Wiimote shake should definitely still work for the times when it's needed. Anybody with knowledge of assembly hacking Wii games could get it implemented. Obviously I've let it sit in my backlog for quite a while but I don't think it should be an extremely complex game. As I understand it, it tilting side-to-side for one minigame and generic shaking for a badge that lets you do extra damage by jumping on enemies or something?
A lot of games use the value at0x58(r3)for horizontal Wiimote tilting (e.g. steering), so if Paper Mario works like that, then it's basically a matter of reading in the X axis of the Right Stick (a range from -1 to +1) from0x74(r3), maybe multiplying it by 0.5 or something then writing it to the tilt address. The accelerometer tilt is also from -1 to +1, but most games don't expect you to tilt the full 180 degrees, so you also want to reduce the value of the stick.
It might also require a bit of remapping of the buttons, because your right thumb is now "stuck" on the Right Stick managing the tilt controls (and your left thumb is doing movement on the Left Stick), so only the L/R/ZL/ZR buttons are really usable while you're doing that. So depending on how many buttons are needed in the tilt minigame, you'd probably need to map some of those (e.g. Jump?) up there so that you can move, jump and tilt simultaneously.
Assuming it works in roughly the same way, the tilt stuff I did for New Super Mario Bros. Wii might be relatively close. That would look something like this:
Code:; calc_acc_vertical ; note: these are NSMBW addresses, not Paper Mario ; 801EB038 for USA (Rev 1/2) ; 801EB178 for EUR (Rev 2) ; 801EAE48 for JPN (Rev 2) ; 801EB578 for KOR stw r0, 0x44(r1) ; check if this is a classic controller lbz r0, 0x5C(r3) cmpwi r0, 0x2 bne- RETURN ; magic bl GRAB MAGIC: RANGE: .float 0.5 GRAB: mflr r5 lfs f0, RANGE-MAGIC(r5) ; load in right stick, constrain and write lfs f1, 0x74(r3) fmuls f0, f0, f1 stfs f0, 0x58(r3) ; restore lr and stack then get outta here lwz r0, 0x44(sp) mtlr r0 addi sp, sp, 0x40 blr RETURN:
To remap B to B in Epic Mickey, you'll want to Ctrl+F for this part in the code:
... and replace the secondCode:60C60800 71000040 41820008 60C608000800(A), the one at the end, with0400(B), so you've got this:
Just to be clear, you're only changing a single digit, anCode:60C60800 71000040 41820008 60C604008to a4, the rest is just so you know which8is the right one to change.
I included a couple of extra options in the Technical Notes section for Mario Kart Wii which you might like better when using a mix of Classic Controller generations. The "main" version of the code I made definitely assumes you have easy access to the ZL/ZR buttons which are obviously not very convenient on the original Classic. However, in the Technical Notes there's a code which swaps L/R with ZL/ZR. I labelled it as L Item, R Drift, ZL/ZR/D-Pad Wheelie. I think that one is probably ideal when using both types of CC simultaneously, because all of them have reasonably easy access to L/R. With that version, you can still wheelie with the Z buttons or D-Pad but otherwise the control layout is much closer to Mario Kart 8.
Aha, yeah, the registers are not always consistent across SDK versions. The button mapper needs a "garbage" register it can replace over and over while doing button checks. Each of theandi.instructions in the button injector replaces the value in the first register. The button mapping code I gave in the tutorial, for Rhythm Heaven, usesr0as the garbage register, because after the button injection finishes, the game populatesr0itself, so it doesn't matter what we left behind.
Max and the Magic Marker is usingr9where other games would user0, so we need to maker9our garbage register instead. If you scroll back up to the start of this post, you can look at the button injector code I used for Max and see that I've mader9the garbage register, so that's the one we dump the output in each time we check a button.
Whoops, you've spotted an error in the Technical Notes I wrote up for Lego Star Wars. That was a pretty early Wii game, beforeread_kpad_button()existed, so the injector goes directly inKPADRead(), but my notes sayread_kpad_button()incorrectly I'll go back and edit that, thanks for spotting it.
IIRC, Lego Star Wars 3 was pretty late in the Wii life cycle, so without looking at it, I suspect that it actually would useread_kpad_button(). I'll answer the second part below, since it's on the same subject.
awesomeee did mean to breakpoint it once you've found it rather than just searching for it. Really sorry if you already know this, but a breakpoint is a feature in debuggers that pauses the application when a specific state occurs. An execution breakpoint means pausing when an instruction gets executed. In Dolphin, you can toggle an execution breakpoint by clicking to the left of the address. In this screenshot you can see where I've set a breakpoint at the beginning ofWPADProbe(), because there's a little circle indicating an execution breakpoint, which is where I clicked.
So the idea when using this method to locateKPADRead()is to pause Dolphin, search forWPADProbe(), set a breakpoint at the start, then resume execution in Dolphin. It will stop again almost instantly, becauseWPADProbe()usually runs 3, 4 or more times on each frame, called from all over the place. As you correctly guessed, one of those callers isKPADRead().
Each time you resume execution in Dolphin, it will run until the next timeWPADProbe()gets called. If you're in the situation where theselect_1obj_continue()approach isn't working, it's most likely that Dolphin has not recognizedKPADRead()as a function at all, so in the Callstack panel in the top left,KPADRead()will show up as---.
There's no guarantee that the first---you see isKPADRead()as there may be multiple unrecognized functions, but basically you just want to keep resuming Dolphin until you see---as caller, then click it in the Callstack and try to figure out whether you're looking atKPADRead()by scrolling down and seeing if you recognize anything from the tutorial, like the three read calls in a row (stick/ext,accanddpd), although obviously with autogenerated names, not the real ones.
It absolutely looks like you know what you're doing and are grasping all the concepts, so it doesn't sound like this is outside of your skillset to me.
It does look like a pretty complicated one, with different motions for attacks and finishers and stuff. I'll add it to my list, but it's going in the complicated section with other games I've either struggled or failed with.
I've literally never heard of this game, interesting one. I actually just successfully looked at another game from Incinerator Studios which also had things triggered by motions, so while it does look somewhat complex, maybe we'll get lucky and I can leverage previous work on it. Fingers crossed.
View attachment 481114
As previously established, Cars Race-O-Rama is the real third entry in the Cars trilogy. Although development moved from Rainbow Studios to Incinerator Studios (who had worked on the Wii ports of the first two Cars...es), this game was built on Rainbow's engine from the first two games and continues in a similar vein, with a mix of racing and minigames taking on the roles of several "car"-acters. Race-O-Rama is a bit of an odd case: it's often regarded as the best Cars game in the trilogy and/or the entire series, with highlights being a greater focus on racing, the new drift-boost mechanic and the massively expanded open world environments compared to the first two games. At the same time, it seems to have been the most rushed entry, with performance issues, wonkier crash physics than ever, and occasional bugs marring the effort, even on the ports to more powerful consoles. Can it be the best in the series and also a bit rushed and sloppy?
Highlight for @frankybuster_, who was interested in this game.
USAEUR
Code:Classic Controller Support [Vague Rant] C209A8C4 00000005 880DE234 2C000002 40820008 38000001 2C000001 41820008 38000000 901D0544 60000000 00000000 C20AE100 00000005 88ADE234 2C050002 40820008 38A00001 2C050001 41820008 38A00000 98BF006C 60000000 00000000 040AE11C 60000000 C227CDAC 00000002 28000001 41820008 28000002 00000000 C227CF54 00000002 28000001 41820008 28000002 00000000 C227D4B4 00000002 28000001 41820008 28000002 00000000 C23650D8 00000008 8803005C 2C000002 40820030 48000009 4059999A 7CA802A6 C0250000 C0030074 EC000072 D01E04D8 C0830078 EC840072 FC002050 D01E04DC 80C3000C 00000000 C2365B48 0000001F 90010024 2C040000 408200E8 8803005C 2C000002 408200DC 9803005E 2C140001 40820094 48000015 80320E50 3FAAAAAB 3D4CCCCD 3F800000 7CA802A6 80030004 70008000 41820010 38000000 90030020 90030024 80650000 28030001 40810018 90A1000C 7C6803A6 4E800021 80A1000C 90650000 2C030001 7FE3FB78 C0450004 40820008 EC4200B2 C0650008 C0030020 C0230060 FC211024 4800002D D0030020 C0030024 C0230064 FC200850 48000019 D0030024 80010024 7C0803A6 38210020 4E800020 FC0100FA C025000C FC000800 4180000C FC000890 48000014 FC200850 FC000800 41810008 FC000890 4E800020 60000000 00000000 04366A40 7FC3F378 043677B0 60000000 04367900 60000000 C2364B54 00000020 7D2802A6 4800000D 00000000 00000000 7D4802A6 7D2803A6 5729083C 7D4A4A14 2808FFFF 4082000C A10A0000 48000014 2C040002 408200C0 38800001 B10A0000 71090800 41820008 60E78000 71090001 41820008 60E70008 71094000 41820008 60E70004 71090002 41820008 60E70001 71098000 41820008 60E70002 71090010 41820008 60E70900 71090040 41820008 60E70400 71090008 41820008 60E70200 71090020 41820008 60E70004 71092000 41820008 60E70008 71090200 41820008 60E70001 71090080 41820008 60E72000 71090004 41820008 60E74000 71090400 41820008 60E70010 71091000 41820008 60E71000 7CC63B78 70C99FFF 00000000 Code:Classic Controller Support [Vague Rant] C209A8C4 00000005 880DE234 2C000002 40820008 38000001 2C000001 41820008 38000000 901D0544 60000000 00000000 C20AE100 00000005 88ADE234 2C050002 40820008 38A00001 2C050001 41820008 38A00000 98BF006C 60000000 00000000 040AE11C 60000000 C227CDEC 00000002 28000001 41820008 28000002 00000000 C227CF94 00000002 28000001 41820008 28000002 00000000 C227D4F4 00000002 28000001 41820008 28000002 00000000 C2365128 00000008 8803005C 2C000002 40820030 48000009 4059999A 7CA802A6 C0250000 C0030074 EC000072 D01E04D8 C0830078 EC840072 FC002050 D01E04DC 80C3000C 00000000 C2365B98 0000001F 90010024 2C040000 408200E8 8803005C 2C000002 408200DC 9803005E 2C140001 40820094 48000015 80320EA0 3FAAAAAB 3D4CCCCD 3F800000 7CA802A6 80030004 70008000 41820010 38000000 90030020 90030024 80650000 28030001 40810018 90A1000C 7C6803A6 4E800021 80A1000C 90650000 2C030001 7FE3FB78 C0450004 40820008 EC4200B2 C0650008 C0030020 C0230060 FC211024 4800002D D0030020 C0030024 C0230064 FC200850 48000019 D0030024 80010024 7C0803A6 38210020 4E800020 FC0100FA C025000C FC000800 4180000C FC000890 48000014 FC200850 FC000800 41810008 FC000890 4E800020 60000000 00000000 04366A90 7FC3F378 04367800 60000000 04367950 60000000 C2364BA4 00000020 7D2802A6 4800000D 00000000 00000000 7D4802A6 7D2803A6 5729083C 7D4A4A14 2808FFFF 4082000C A10A0000 48000014 2C040002 408200C0 38800001 B10A0000 71090800 41820008 60E78000 71090001 41820008 60E70008 71094000 41820008 60E70004 71090002 41820008 60E70001 71098000 41820008 60E70002 71090010 41820008 60E70900 71090040 41820008 60E70400 71090008 41820008 60E70200 71090020 41820008 60E70004 71092000 41820008 60E70008 71090200 41820008 60E70001 71090080 41820008 60E72000 71090004 41820008 60E74000 71090400 41820008 60E70010 71091000 41820008 60E71000 7CC63B78 70C99FFF 00000000Button Mapping
[TABLE=full]
[TR]
[TH]Wii Remote/Nunchuk[/TH]
[TH]Classic Controller[/TH]
[TH]Function[/TH]
[/TR]
[TR]
[TD]Wiimote Home[/TD]
[TD]Home[/TD]
[TD]Open/Close Home Menu[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad[/TD]
[TD]D-Pad[/TD]
[TD]Menus
Navigation[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad Up[/TD]
[TD]L[/TD]
[TD]Gameplay
Tilt Vehicle[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad Down[/TD]
[TD]Y[/TD]
[TD]Gameplay
E-Brake[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad Left[/TD]
[TD]R[/TD]
[TD]Gameplay
Reverse Camera[/TD]
[/TR]
[TR]
[TD]Wiimote A[/TD]
[TD]A[/TD]
[TD]Menus
Confirm
Gameplay
Brake/Reverse[/TD]
[/TR]
[TR]
[TD]Wiimote B[/TD]
[TD]B[/TD]
[TD]Menus
Cancel
Gameplay
Accelerate[/TD]
[/TR]
[TR]
[TD]Wiimote 1[/TD]
[TD]X[/TD]
[TD]Gameplay
Switch Camera[/TD]
[/TR]
[TR]
[TD]Wiimote 2[/TD]
[TD]A[/TD]
[TD]Menus
Confirm (Wiimote mode)[/TD]
[/TR]
[TR]
[TD]Wiimote Plus[/TD]
[TD]Plus[/TD]
[TD]Gameplay
Pause[/TD]
[/TR]
[TR]
[TD]Wiimote Minus[/TD]
[TD]Minus[/TD]
[TD]Gameplay
Switch Garage[/TD]
[/TR]
[TR]
[TD]Wiimote Motions[/TD]
[TD]Right Stick[/TD]
[TD]Gameplay
Various Minigame QTEs[/TD]
[/TR]
[TR]
[TD]Wiimote Pointer[/TD]
[TD]Left Stick[/TD]
[TD]Home Button Menu
Navigation[/TD]
[/TR]
[TR]
[TD]Nunchuk Stick[/TD]
[TD]Left Stick[/TD]
[TD]Menus
Navigation
Gameplay
Steering[/TD]
[/TR]
[TR]
[TD]Nunchuk C[/TD]
[TD]ZR[/TD]
[TD]Gameplay
Nitro[/TD]
[/TR]
[TR]
[TD]Nunchuk Z[/TD]
[TD]ZL[/TD]
[TD]Gameplay
Powerslide[/TD]
[/TR]
[/TABLE]
General Notes
- Cars Race-O-Rama boots into sideways Wiimote mode (Configuration 1 in the Options menu) by default, regardless of what extension controller is connected. That's bad news for our purposes, because the mapping used here is all wrong for sideways Wiimote. I improved on this somewhat by automatically switching to Nunchuk mode (Configuration 2) if a Nunchuk or Classic Controller is connected when you boot the game or when starting a new save file. If you don't do anything goofy, you should be fine. Goofy things include:
- Booting up the game before you connect a Nunchuk/Classic Controller.
- Loading a previously created save file which is set to Wiimote mode.
- Going into Options > Control Options and switching to Wiimote mode (Configuration 1).
- Any of the above will make the game run in sideways Wiimote mode (Configuration 1). If you get yourself into Wiimote mode, the Classic Controller D-Pad will be rotated. You will just have to deal with that until you switch back to Nunchuk mode (Configuration 2). Use the X and A buttons as 1 and 2 to navigate the menus.
- As mentioned in the intro, Race-O-Rama is from a different developer to the previous two Cars games and introduces some of its own mechanics. Incinerator's control scheme for the game is pretty radically different to Rainbow's setup for the first two. Even on the HD console versions with traditional controllers, the button mapping doesn't have much in common with the controls of Cars/Mater-National. I considered reverting the layout to make it match the earlier games, but I decided to take this game on its own terms and map it like the other console ports, even though that means it's completely different to the previous Mater-National hack.
- The most significant change is probably that Incinerator has inverted the accelerate/brake controls from previous games, so it's B to accelerate and A to brake. This is definitely pretty weird and I never entirely wrapped my head around it, but this hack respects that setup (which was the same on other consoles as well). If you don't like it, the assembly is in the Technical Notes for you to come up with your own mapping.
Technical Notes
Code breakdown:
C2: check extension controller on boot, switch to Config 2 if Nunchuk/ClassicC2and04: check extension controller when creating a new save, switch to Config 2 if Nunchuk/ClassicC2: bypass Nunchuk errorC2andC2: accept Classic Controller as Nunchuk-type controllerC2inread_kpad_acc(): fake accelerometer motions on Right StickC2incalc_dpd_variable(): simulate IR pointer on Left Stick04inread_kpad_ext(): stick redirection04and04inKPADRead(): dropped connection fixC2inread_kpad_button(): button injectorCode:; read_kpad_button ; 80364B54 for USA ; 80364BA4 for EUR (En,Fr,Es,It)/EUR (Fr,De) ; r4 holds extType ; r6 holds wiimote bitfield ; r7 holds wiimote+nunchuk bitfield ; r8 holds classic bitfield ; magic mflr r9 bl GRAB MAGIC: HELD: .double 0 GRAB: mflr r10 mtlr r9 slwi r9, r25, 1 add r10, r10, r9 ; check dropped extension cmplwi r8, 0xFFFF bne- CLASSIC lhz r8, HELD-MAGIC(r10) b DROPPED_CONNECTION CLASSIC: cmpwi r4, 0x2 bne- RETURN li r4, 0x1 ; i'm a nunchuk sth r8, HELD-MAGIC(r10) DROPPED_CONNECTION: CLASSIC_HOME: andi. r9, r8, 0x800 beq- CLASSIC_UP ori r7, r7, 0x8000 ; home CLASSIC_UP: andi. r9, r8, 0x1 beq- CLASSIC_DOWN ori r7, r7, 0x8 ; up (v) / left (h) CLASSIC_DOWN: andi. r9, r8, 0x4000 beq- CLASSIC_LEFT ori r7, r7, 0x4 ; down (v) / right (h) CLASSIC_LEFT: andi. r9, r8, 0x2 beq- CLASSIC_RIGHT ori r7, r7, 0x1 ; left (v) / down (h) CLASSIC_RIGHT: andi. r9, r8, 0x8000 beq- CLASSIC_A ori r7, r7, 0x2 ; right (v) / up (h) CLASSIC_A: andi. r9, r8, 0x10 beq- CLASSIC_B ori r7, r7, 0x900 ; a + 2 CLASSIC_B: andi. r9, r8, 0x40 beq- CLASSIC_X ori r7, r7, 0x400 ; b CLASSIC_X: andi. r9, r8, 0x8 beq- CLASSIC_Y ori r7, r7, 0x200 ; 1 CLASSIC_Y: andi. r9, r8, 0x20 beq- CLASSIC_L ori r7, r7, 0x4 ; down (v) / right (h) CLASSIC_L: andi. r9, r8, 0x2000 beq- CLASSIC_R ori r7, r7, 0x8 ; up (v) / left (h) CLASSIC_R: andi. r9, r8, 0x200 beq- CLASSIC_ZL ori r7, r7, 0x1 ; left (v) / down (h) CLASSIC_ZL: andi. r9, r8, 0x80 beq- CLASSIC_ZR ori r7, r7, 0x2000 ; z CLASSIC_ZR: andi. r9, r8, 0x4 beq- CLASSIC_PLUS ori r7, r7, 0x4000 ; c CLASSIC_PLUS: andi. r9, r8, 0x400 beq- CLASSIC_MINUS ori r7, r7, 0x10 ; plus CLASSIC_MINUS: andi. r9, r8, 0x1000 beq- RETURN ori r7, r7, 0x1000 ; minus RETURN: or r6, r6, r7 andi. r9, r6, 0x9FFF
There's no guarantee that the first --- you see is KPADRead() as there may be multiple unrecognized functions, but basically you just want to keep resuming Dolphin until you see --- as caller, then click it in the Callstack and try to figure out whether you're looking at KPADRead() by scrolling down and seeing if you recognize anything from the tutorial, like the three read calls in a row (stick/ext, acc and dpd), although obviously with autogenerated names, not the real ones.
(from the guide, for the new sdk)look ahead one instruction to find the following: andi. r0, r6, 0x9FFF
Yeah, i did have some x86 assembly/computer architecture courses in uni (versity), and we did build (virtual) 8 bit cpu's from scratch.It absolutely looks like you know what you're doing and are grasping all the concepts, so it doesn't sound like this is outside of your skillset to me.

Crash of the Titans was one of my favorite games as a child. I tried the Wii version, but was disappointed with the controls. A CC hack would be awesome.Has anyone requested Crash of the Titans and Mind Over Mutant yet? it'd be very cool to have classic controller mods for these games since they're better looking than the PS2 versions, especially the latter which almost matches the 360 version in asset quality but without being as demanding to emulate and having a 60fps hack.
I'm requesting this mainly for because these games require pointer and waggle usage for certain things, like for projectile based mutants and for using their super attacks (not to mention that the TK mutant has a strafe only seen in the Wii version). If possible it'd be great if a classic controller setup somewhat matched the controller layouts seen in the other versions
Oh yeah, and classic controller codes for the Skylanders games would be really cool too if it could be done sometime in the future, those games have pretty basic waggle and pointer usage, with the waggle stuff being simplified to mashing the X button in the Wii U ports.
OK someone games people asking form should work base on the quality of the game order should be.Reply-O-Rama.
Building on your mapping and identifying all the relevant functions (nice work), here's what I've got for Max currently:
I found out that this game got a sequel on Xbox 360, so I did look at that a little and edited the mapping a tiny bit (swapped X and Y IIRC?) to match that game. For L and R, I mapped them as C and Z again, so that you can in theory play entirely with the shoulder buttons and never need to take your thumb off the Right Stick.Code:; bypass nunchuk error ; 8002C578 for USA lwz r0, 0x8(sp) cmpwi r0, 2 bne- RETURN li r0, 1 RETURN:Code:; read_kpad_acc ; 8044BF94 for USA lfs f1, 0x4DC(r30) ; magic bl GRAB MAGIC: CONTINUE: .int 0 SHAKE: .float 3.4 GRAB: mflr r4 lwz r3, CONTINUE-MAGIC(r4) cmpwi r3, 0 ble- NEW_SHAKE subi r3, r3, 1 b DO_SHAKE NEW_SHAKE: lwz r3, 0x4(r30) andi. r0, r3, 0x80 beq- RETURN li r3, 5 DO_SHAKE: lfs f1, SHAKE-MAGIC(r4) cmpwi r20, 1 bne- RETURN stw r3, CONTINUE-MAGIC(r4) ; hold B for player lwz r3, 0x0(r30) ori r3, r3, 0x400 stw r3, 0x0(r30) lwz r3, 0x8(r30) andi. r3, r3, 0xFBFF stw r3, 0x8(r30) RETURN:Code:; calc_dpd_variable ; 8044C9D8 for USA stw r0, 0x24(sp) ; player using real pointer? (gravity already valid) cmpwi r4, 0x0 bne- NO_CLASSIC ; check for Classic Controller lbz r0, 0x5C(r3) cmpwi r0, 0x2 bne- NO_CLASSIC stb r0, 0x5E(r3) cmpwi r20, 0x1 bne- RETURN ; magic bl GRAB MAGIC: GETASPECT: .int 0x80468490 ; USA 0x80468490 ASPECT: .float 1.3333333333 MULTIPLIER: .float 0.025 ; pointer speed MAX_RANGE: .float 1.0 GRAB: mflr r5 DELTA: lwz r3, GETASPECT-MAGIC(r5) ; SCGetAspectRatio() cmplwi r3, 0x1 ble- CHECK_ASPECT ; run aspect ratio check stw r5, 0x0C(sp) ; save magic pointer mtlr r3 blrl lwz r5, 0x0C(sp) ; restore magic pointer stw r3, GETASPECT-MAGIC(r5) CHECK_ASPECT: cmpwi r3, 0x1 mr r3, r31 ; restore input pointer lfs f2, ASPECT-MAGIC(r5) bne- FULLSCREEN fmuls f2, f2, f2 ; widescreen FULLSCREEN: lfs f3, MULTIPLIER-MAGIC(r5) ; pointer X axis lfs f0, 0x20(r3) lfs f1, 0x74(r3) ; right stick X fdiv f1, f1, f2 ; divide by aspect ratio bl RANGE_CHECK stfs f0, 0x20(r3) ; pointer Y axis lfs f0, 0x24(r3) lfs f1, 0x78(r3) ; right stick Y fneg f1, f1 lfs f2, MAX_RANGE-MAGIC(r5) bl RANGE_CHECK stfs f0, 0x24(r3) RETURN: lwz r0, 0x24(sp) mtlr r0 addi sp, sp, 0x20 blr RANGE_CHECK: fmadd f0, f1, f3, f0 fcmpu cr0, f0, f2 blt CHECK_NEGATIVE fmr f0, f2 b IN_RANGE CHECK_NEGATIVE: fneg f2, f2 fcmpu cr0, f0, f2 bgt IN_RANGE fmr f0, f2 IN_RANGE: blr NO_CLASSIC:Code:read_kpad_ext stick redirection USA 0444D8D0 7FC3F378 KPADRead drop fix USA 0444E4F8 60000000 0444E648 60000000Code:; read_kpad_button ; 8044B9E4 for USA ; r4 holds extType ; r6 holds wiimote bitfield ; r7 holds wiimote+nunchuk bitfield ; r8 holds classic bitfield ; magic mflr r9 bl GRAB MAGIC: HELD: .double 0 GRAB: mflr r10 mtlr r9 slwi r9, r25, 1 add r10, r10, r9 ; check dropped extension cmplwi r8, 0xFFFF bne- CLASSIC lhz r8, HELD-MAGIC(r10) b DROPPED_CONNECTION CLASSIC: cmpwi r4, 0x2 bne- RETURN li r4, 0x1 ; i'm a nunchuk sth r8, HELD-MAGIC(r10) DROPPED_CONNECTION: CLASSIC_HOME: andi. r9, r8, 0x800 beq- CLASSIC_UP ori r7, r7, 0x8000 ; home CLASSIC_UP: andi. r9, r8, 0x1 beq- CLASSIC_DOWN ori r7, r7, 0x8 ; up CLASSIC_DOWN: andi. r9, r8, 0x4000 beq- CLASSIC_LEFT ori r7, r7, 0x4 ; down CLASSIC_LEFT: andi. r9, r8, 0x2 beq- CLASSIC_RIGHT ori r7, r7, 0x1 ; left CLASSIC_RIGHT: andi. r9, r8, 0x8000 beq- CLASSIC_A ori r7, r7, 0x2 ; right CLASSIC_A: andi. r9, r8, 0x10 beq- CLASSIC_B ori r7, r7, 0x800 ; A (Draw Ink) CLASSIC_B: andi. r9, r8, 0x40 beq- CLASSIC_X ori r7, r7, 0x2000 ; Z (Jump) CLASSIC_X: andi. r9, r8, 0x8 beq- CLASSIC_Y ori r7, r7, 0x80 ; wiimote shake + B (Erases ALL Ink) CLASSIC_Y: andi. r9, r8, 0x20 beq- CLASSIC_L ori r7, r7, 0x4000 ; Nunchuk C (Push and Pull objects) CLASSIC_L: andi. r9, r8, 0x2000 beq- CLASSIC_R ori r7, r7, 0x4000 ; Nunchuk C (Push and Pull objects) CLASSIC_R: andi. r9, r8, 0x200 beq- CLASSIC_ZL ori r7, r7, 0x2000 ; Z (Jump) CLASSIC_ZL: andi. r9, r8, 0x80 beq- CLASSIC_ZR ori r7, r7, 0x400 ; B (Erase Ink) CLASSIC_ZR: andi. r9, r8, 0x4 beq- CLASSIC_PLUS ori r7, r7, 0x800 ; A (Draw Ink) CLASSIC_PLUS: andi. r9, r8, 0x400 beq- CLASSIC_MINUS ori r7, r7, 0x10 ; plus CLASSIC_MINUS: andi. r9, r8, 0x1000 beq- RETURN ori r7, r7, 0x1000 ; minus RETURN: or r6, r6, r7 andi. r9, r6, 0x9FFFCode:C202C578 00000003 80010008 2C000002 40820008 38000001 60000000 00000000 C244BF94 0000000D C03E04DC 4800000D 00000000 4059999A 7C8802A6 80640000 2C030000 4081000C 3863FFFF 48000014 807E0004 70600080 41820030 38600005 C0240004 2C140001 40820020 90640000 807E0000 60630400 907E0000 807E0008 7063FBFF 907E0008 60000000 00000000 C244C9D8 0000001C 90010024 2C040000 408200D0 8803005C 2C000002 408200C4 9803005E 2C140001 40820080 48000015 80468490 3FAAAAAB 3CCCCCCD 3F800000 7CA802A6 80650000 28030001 40810018 90A1000C 7C6803A6 4E800021 80A1000C 90650000 2C030001 7FE3FB78 C0450004 40820008 EC4200B2 C0650008 C0030020 C0230074 FC211024 48000031 D0030020 C0030024 C0230078 FC200850 C045000C 48000019 D0030024 80010024 7C0803A6 38210020 4E800020 FC0100FA FC001000 4180000C FC001090 48000014 FC401050 FC001000 41810008 FC001090 4E800020 60000000 00000000 0444D8D0 7FC3F378 0444E4F8 60000000 0444E648 60000000 C244B9E4 00000020 7D2802A6 4800000D 00000000 00000000 7D4802A6 7D2803A6 5729083C 7D4A4A14 2808FFFF 4082000C A10A0000 48000014 2C040002 408200C0 38800001 B10A0000 71090800 41820008 60E78000 71090001 41820008 60E70008 71094000 41820008 60E70004 71090002 41820008 60E70001 71098000 41820008 60E70002 71090010 41820008 60E70800 71090040 41820008 60E72000 71090008 41820008 60E70080 71090020 41820008 60E74000 71092000 41820008 60E74000 71090200 41820008 60E72000 71090080 41820008 60E70400 71090004 41820008 60E70800 71090400 41820008 60E70010 71091000 41820008 60E71000 7CC63B78 70C99FFF 00000000
The accelerometer stuff for this game requires a swing that last at least 5 frames. I also set it up to hold B for those 5 frames as well, because otherwise you could easily hold the button for <5 frames and the shake would work but it would fail on the button press. This way everything seems to work reliably.
I made the IR pointer quite slow for this game because you do need to do things like draw a circle then color it in, and the fine motions are very tough at full speed. I think everything should be working with this, I was able to run through the first stage without any issues. If you could test this and see if everything works right and/or make any changes you feel like, I'll see if I can port it to EUR/JPN and create IPS patches for people playing via injection.
Me too. Race-O-Rama is definitely the most complicated of the Cars trilogy because a bunch of the minigames are motion-controlled QTEs. But there's a pretty good chance it'll happen.
The original Wiimote shake should definitely still work for the times when it's needed. Anybody with knowledge of assembly hacking Wii games could get it implemented. Obviously I've let it sit in my backlog for quite a while but I don't think it should be an extremely complex game. As I understand it, it tilting side-to-side for one minigame and generic shaking for a badge that lets you do extra damage by jumping on enemies or something?
A lot of games use the value at0x58(r3)for horizontal Wiimote tilting (e.g. steering), so if Paper Mario works like that, then it's basically a matter of reading in the X axis of the Right Stick (a range from -1 to +1) from0x74(r3), maybe multiplying it by 0.5 or something then writing it to the tilt address. The accelerometer tilt is also from -1 to +1, but most games don't expect you to tilt the full 180 degrees, so you also want to reduce the value of the stick.
It might also require a bit of remapping of the buttons, because your right thumb is now "stuck" on the Right Stick managing the tilt controls (and your left thumb is doing movement on the Left Stick), so only the L/R/ZL/ZR buttons are really usable while you're doing that. So depending on how many buttons are needed in the tilt minigame, you'd probably need to map some of those (e.g. Jump?) up there so that you can move, jump and tilt simultaneously.
Assuming it works in roughly the same way, the tilt stuff I did for New Super Mario Bros. Wii might be relatively close. That would look something like this:
Code:; calc_acc_vertical ; note: these are NSMBW addresses, not Paper Mario ; 801EB038 for USA (Rev 1/2) ; 801EB178 for EUR (Rev 2) ; 801EAE48 for JPN (Rev 2) ; 801EB578 for KOR stw r0, 0x44(r1) ; check if this is a classic controller lbz r0, 0x5C(r3) cmpwi r0, 0x2 bne- RETURN ; magic bl GRAB MAGIC: RANGE: .float 0.5 GRAB: mflr r5 lfs f0, RANGE-MAGIC(r5) ; load in right stick, constrain and write lfs f1, 0x74(r3) fmuls f0, f0, f1 stfs f0, 0x58(r3) ; restore lr and stack then get outta here lwz r0, 0x44(sp) mtlr r0 addi sp, sp, 0x40 blr RETURN:
To remap B to B in Epic Mickey, you'll want to Ctrl+F for this part in the code:
... and replace the secondCode:60C60800 71000040 41820008 60C608000800(A), the one at the end, with0400(B), so you've got this:
Just to be clear, you're only changing a single digit, anCode:60C60800 71000040 41820008 60C604008to a4, the rest is just so you know which8is the right one to change.
I included a couple of extra options in the Technical Notes section for Mario Kart Wii which you might like better when using a mix of Classic Controller generations. The "main" version of the code I made definitely assumes you have easy access to the ZL/ZR buttons which are obviously not very convenient on the original Classic. However, in the Technical Notes there's a code which swaps L/R with ZL/ZR. I labelled it as L Item, R Drift, ZL/ZR/D-Pad Wheelie. I think that one is probably ideal when using both types of CC simultaneously, because all of them have reasonably easy access to L/R. With that version, you can still wheelie with the Z buttons or D-Pad but otherwise the control layout is much closer to Mario Kart 8.
Aha, yeah, the registers are not always consistent across SDK versions. The button mapper needs a "garbage" register it can replace over and over while doing button checks. Each of theandi.instructions in the button injector replaces the value in the first register. The button mapping code I gave in the tutorial, for Rhythm Heaven, usesr0as the garbage register, because after the button injection finishes, the game populatesr0itself, so it doesn't matter what we left behind.
Max and the Magic Marker is usingr9where other games would user0, so we need to maker9our garbage register instead. If you scroll back up to the start of this post, you can look at the button injector code I used for Max and see that I've mader9the garbage register, so that's the one we dump the output in each time we check a button.
Whoops, you've spotted an error in the Technical Notes I wrote up for Lego Star Wars. That was a pretty early Wii game, beforeread_kpad_button()existed, so the injector goes directly inKPADRead(), but my notes sayread_kpad_button()incorrectly I'll go back and edit that, thanks for spotting it.
IIRC, Lego Star Wars 3 was pretty late in the Wii life cycle, so without looking at it, I suspect that it actually would useread_kpad_button(). I'll answer the second part below, since it's on the same subject.
awesomeee did mean to breakpoint it once you've found it rather than just searching for it. Really sorry if you already know this, but a breakpoint is a feature in debuggers that pauses the application when a specific state occurs. An execution breakpoint means pausing when an instruction gets executed. In Dolphin, you can toggle an execution breakpoint by clicking to the left of the address. In this screenshot you can see where I've set a breakpoint at the beginning ofWPADProbe(), because there's a little circle indicating an execution breakpoint, which is where I clicked.
So the idea when using this method to locateKPADRead()is to pause Dolphin, search forWPADProbe(), set a breakpoint at the start, then resume execution in Dolphin. It will stop again almost instantly, becauseWPADProbe()usually runs 3, 4 or more times on each frame, called from all over the place. As you correctly guessed, one of those callers isKPADRead().
Each time you resume execution in Dolphin, it will run until the next timeWPADProbe()gets called. If you're in the situation where theselect_1obj_continue()approach isn't working, it's most likely that Dolphin has not recognizedKPADRead()as a function at all, so in the Callstack panel in the top left,KPADRead()will show up as---.
There's no guarantee that the first---you see isKPADRead()as there may be multiple unrecognized functions, but basically you just want to keep resuming Dolphin until you see---as caller, then click it in the Callstack and try to figure out whether you're looking atKPADRead()by scrolling down and seeing if you recognize anything from the tutorial, like the three read calls in a row (stick/ext,accanddpd), although obviously with autogenerated names, not the real ones.
It absolutely looks like you know what you're doing and are grasping all the concepts, so it doesn't sound like this is outside of your skillset to me.
It does look like a pretty complicated one, with different motions for attacks and finishers and stuff. I'll add it to my list, but it's going in the complicated section with other games I've either struggled or failed with.
I've literally never heard of this game, interesting one. I actually just successfully looked at another game from Incinerator Studios which also had things triggered by motions, so while it does look somewhat complex, maybe we'll get lucky and I can leverage previous work on it. Fingers crossed.
View attachment 481114
As previously established, Cars Race-O-Rama is the real third entry in the Cars trilogy. Although development moved from Rainbow Studios to Incinerator Studios (who had worked on the Wii ports of the first two Cars...es), this game was built on Rainbow's engine from the first two games and continues in a similar vein, with a mix of racing and minigames taking on the roles of several "car"-acters. Race-O-Rama is a bit of an odd case: it's often regarded as the best Cars game in the trilogy and/or the entire series, with highlights being a greater focus on racing, the new drift-boost mechanic and the massively expanded open world environments compared to the first two games. At the same time, it seems to have been the most rushed entry, with performance issues, wonkier crash physics than ever, and occasional bugs marring the effort, even on the ports to more powerful consoles. Can it be the best in the series and also a bit rushed and sloppy?
Highlight for @frankybuster_, who was interested in this game.
USAEUR
Code:Classic Controller Support [Vague Rant] C209A8C4 00000005 880DE234 2C000002 40820008 38000001 2C000001 41820008 38000000 901D0544 60000000 00000000 C20AE100 00000005 88ADE234 2C050002 40820008 38A00001 2C050001 41820008 38A00000 98BF006C 60000000 00000000 040AE11C 60000000 C227CDAC 00000002 28000001 41820008 28000002 00000000 C227CF54 00000002 28000001 41820008 28000002 00000000 C227D4B4 00000002 28000001 41820008 28000002 00000000 C23650D8 00000008 8803005C 2C000002 40820030 48000009 4059999A 7CA802A6 C0250000 C0030074 EC000072 D01E04D8 C0830078 EC840072 FC002050 D01E04DC 80C3000C 00000000 C2365B48 0000001F 90010024 2C040000 408200E8 8803005C 2C000002 408200DC 9803005E 2C140001 40820094 48000015 80320E50 3FAAAAAB 3D4CCCCD 3F800000 7CA802A6 80030004 70008000 41820010 38000000 90030020 90030024 80650000 28030001 40810018 90A1000C 7C6803A6 4E800021 80A1000C 90650000 2C030001 7FE3FB78 C0450004 40820008 EC4200B2 C0650008 C0030020 C0230060 FC211024 4800002D D0030020 C0030024 C0230064 FC200850 48000019 D0030024 80010024 7C0803A6 38210020 4E800020 FC0100FA C025000C FC000800 4180000C FC000890 48000014 FC200850 FC000800 41810008 FC000890 4E800020 60000000 00000000 04366A40 7FC3F378 043677B0 60000000 04367900 60000000 C2364B54 00000020 7D2802A6 4800000D 00000000 00000000 7D4802A6 7D2803A6 5729083C 7D4A4A14 2808FFFF 4082000C A10A0000 48000014 2C040002 408200C0 38800001 B10A0000 71090800 41820008 60E78000 71090001 41820008 60E70008 71094000 41820008 60E70004 71090002 41820008 60E70001 71098000 41820008 60E70002 71090010 41820008 60E70900 71090040 41820008 60E70400 71090008 41820008 60E70200 71090020 41820008 60E70004 71092000 41820008 60E70008 71090200 41820008 60E70001 71090080 41820008 60E72000 71090004 41820008 60E74000 71090400 41820008 60E70010 71091000 41820008 60E71000 7CC63B78 70C99FFF 00000000 Code:Classic Controller Support [Vague Rant] C209A8C4 00000005 880DE234 2C000002 40820008 38000001 2C000001 41820008 38000000 901D0544 60000000 00000000 C20AE100 00000005 88ADE234 2C050002 40820008 38A00001 2C050001 41820008 38A00000 98BF006C 60000000 00000000 040AE11C 60000000 C227CDEC 00000002 28000001 41820008 28000002 00000000 C227CF94 00000002 28000001 41820008 28000002 00000000 C227D4F4 00000002 28000001 41820008 28000002 00000000 C2365128 00000008 8803005C 2C000002 40820030 48000009 4059999A 7CA802A6 C0250000 C0030074 EC000072 D01E04D8 C0830078 EC840072 FC002050 D01E04DC 80C3000C 00000000 C2365B98 0000001F 90010024 2C040000 408200E8 8803005C 2C000002 408200DC 9803005E 2C140001 40820094 48000015 80320EA0 3FAAAAAB 3D4CCCCD 3F800000 7CA802A6 80030004 70008000 41820010 38000000 90030020 90030024 80650000 28030001 40810018 90A1000C 7C6803A6 4E800021 80A1000C 90650000 2C030001 7FE3FB78 C0450004 40820008 EC4200B2 C0650008 C0030020 C0230060 FC211024 4800002D D0030020 C0030024 C0230064 FC200850 48000019 D0030024 80010024 7C0803A6 38210020 4E800020 FC0100FA C025000C FC000800 4180000C FC000890 48000014 FC200850 FC000800 41810008 FC000890 4E800020 60000000 00000000 04366A90 7FC3F378 04367800 60000000 04367950 60000000 C2364BA4 00000020 7D2802A6 4800000D 00000000 00000000 7D4802A6 7D2803A6 5729083C 7D4A4A14 2808FFFF 4082000C A10A0000 48000014 2C040002 408200C0 38800001 B10A0000 71090800 41820008 60E78000 71090001 41820008 60E70008 71094000 41820008 60E70004 71090002 41820008 60E70001 71098000 41820008 60E70002 71090010 41820008 60E70900 71090040 41820008 60E70400 71090008 41820008 60E70200 71090020 41820008 60E70004 71092000 41820008 60E70008 71090200 41820008 60E70001 71090080 41820008 60E72000 71090004 41820008 60E74000 71090400 41820008 60E70010 71091000 41820008 60E71000 7CC63B78 70C99FFF 00000000Button Mapping
[TABLE=full]
[TR]
[TH]Wii Remote/Nunchuk[/TH]
[TH]Classic Controller[/TH]
[TH]Function[/TH]
[/TR]
[TR]
[TD]Wiimote Home[/TD]
[TD]Home[/TD]
[TD]Open/Close Home Menu[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad[/TD]
[TD]D-Pad[/TD]
[TD]Menus
Navigation[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad Up[/TD]
[TD]L[/TD]
[TD]Gameplay
Tilt Vehicle[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad Down[/TD]
[TD]Y[/TD]
[TD]Gameplay
E-Brake[/TD]
[/TR]
[TR]
[TD]Wiimote D-Pad Left[/TD]
[TD]R[/TD]
[TD]Gameplay
Reverse Camera[/TD]
[/TR]
[TR]
[TD]Wiimote A[/TD]
[TD]A[/TD]
[TD]Menus
Confirm
Gameplay
Brake/Reverse[/TD]
[/TR]
[TR]
[TD]Wiimote B[/TD]
[TD]B[/TD]
[TD]Menus
Cancel
Gameplay
Accelerate[/TD]
[/TR]
[TR]
[TD]Wiimote 1[/TD]
[TD]X[/TD]
[TD]Gameplay
Switch Camera[/TD]
[/TR]
[TR]
[TD]Wiimote 2[/TD]
[TD]A[/TD]
[TD]Menus
Confirm (Wiimote mode)[/TD]
[/TR]
[TR]
[TD]Wiimote Plus[/TD]
[TD]Plus[/TD]
[TD]Gameplay
Pause[/TD]
[/TR]
[TR]
[TD]Wiimote Minus[/TD]
[TD]Minus[/TD]
[TD]Gameplay
Switch Garage[/TD]
[/TR]
[TR]
[TD]Wiimote Motions[/TD]
[TD]Right Stick[/TD]
[TD]Gameplay
Various Minigame QTEs[/TD]
[/TR]
[TR]
[TD]Wiimote Pointer[/TD]
[TD]Left Stick[/TD]
[TD]Home Button Menu
Navigation[/TD]
[/TR]
[TR]
[TD]Nunchuk Stick[/TD]
[TD]Left Stick[/TD]
[TD]Menus
Navigation
Gameplay
Steering[/TD]
[/TR]
[TR]
[TD]Nunchuk C[/TD]
[TD]ZR[/TD]
[TD]Gameplay
Nitro[/TD]
[/TR]
[TR]
[TD]Nunchuk Z[/TD]
[TD]ZL[/TD]
[TD]Gameplay
Powerslide[/TD]
[/TR]
[/TABLE]
General Notes
- Cars Race-O-Rama boots into sideways Wiimote mode (Configuration 1 in the Options menu) by default, regardless of what extension controller is connected. That's bad news for our purposes, because the mapping used here is all wrong for sideways Wiimote. I improved on this somewhat by automatically switching to Nunchuk mode (Configuration 2) if a Nunchuk or Classic Controller is connected when you boot the game or when starting a new save file. If you don't do anything goofy, you should be fine. Goofy things include:
- Booting up the game before you connect a Nunchuk/Classic Controller.
- Loading a previously created save file which is set to Wiimote mode.
- Going into Options > Control Options and switching to Wiimote mode (Configuration 1).
- Any of the above will make the game run in sideways Wiimote mode (Configuration 1). If you get yourself into Wiimote mode, the Classic Controller D-Pad will be rotated. You will just have to deal with that until you switch back to Nunchuk mode (Configuration 2). Use the X and A buttons as 1 and 2 to navigate the menus.
- As mentioned in the intro, Race-O-Rama is from a different developer to the previous two Cars games and introduces some of its own mechanics. Incinerator's control scheme for the game is pretty radically different to Rainbow's setup for the first two. Even on the HD console versions with traditional controllers, the button mapping doesn't have much in common with the controls of Cars/Mater-National. I considered reverting the layout to make it match the earlier games, but I decided to take this game on its own terms and map it like the other console ports, even though that means it's completely different to the previous Mater-National hack.
- The most significant change is probably that Incinerator has inverted the accelerate/brake controls from previous games, so it's B to accelerate and A to brake. This is definitely pretty weird and I never entirely wrapped my head around it, but this hack respects that setup (which was the same on other consoles as well). If you don't like it, the assembly is in the Technical Notes for you to come up with your own mapping.
Technical Notes
Code breakdown:
C2: check extension controller on boot, switch to Config 2 if Nunchuk/ClassicC2and04: check extension controller when creating a new save, switch to Config 2 if Nunchuk/ClassicC2: bypass Nunchuk errorC2andC2: accept Classic Controller as Nunchuk-type controllerC2inread_kpad_acc(): fake accelerometer motions on Right StickC2incalc_dpd_variable(): simulate IR pointer on Left Stick04inread_kpad_ext(): stick redirection04and04inKPADRead(): dropped connection fixC2inread_kpad_button(): button injectorCode:; read_kpad_button ; 80364B54 for USA ; 80364BA4 for EUR (En,Fr,Es,It)/EUR (Fr,De) ; r4 holds extType ; r6 holds wiimote bitfield ; r7 holds wiimote+nunchuk bitfield ; r8 holds classic bitfield ; magic mflr r9 bl GRAB MAGIC: HELD: .double 0 GRAB: mflr r10 mtlr r9 slwi r9, r25, 1 add r10, r10, r9 ; check dropped extension cmplwi r8, 0xFFFF bne- CLASSIC lhz r8, HELD-MAGIC(r10) b DROPPED_CONNECTION CLASSIC: cmpwi r4, 0x2 bne- RETURN li r4, 0x1 ; i'm a nunchuk sth r8, HELD-MAGIC(r10) DROPPED_CONNECTION: CLASSIC_HOME: andi. r9, r8, 0x800 beq- CLASSIC_UP ori r7, r7, 0x8000 ; home CLASSIC_UP: andi. r9, r8, 0x1 beq- CLASSIC_DOWN ori r7, r7, 0x8 ; up (v) / left (h) CLASSIC_DOWN: andi. r9, r8, 0x4000 beq- CLASSIC_LEFT ori r7, r7, 0x4 ; down (v) / right (h) CLASSIC_LEFT: andi. r9, r8, 0x2 beq- CLASSIC_RIGHT ori r7, r7, 0x1 ; left (v) / down (h) CLASSIC_RIGHT: andi. r9, r8, 0x8000 beq- CLASSIC_A ori r7, r7, 0x2 ; right (v) / up (h) CLASSIC_A: andi. r9, r8, 0x10 beq- CLASSIC_B ori r7, r7, 0x900 ; a + 2 CLASSIC_B: andi. r9, r8, 0x40 beq- CLASSIC_X ori r7, r7, 0x400 ; b CLASSIC_X: andi. r9, r8, 0x8 beq- CLASSIC_Y ori r7, r7, 0x200 ; 1 CLASSIC_Y: andi. r9, r8, 0x20 beq- CLASSIC_L ori r7, r7, 0x4 ; down (v) / right (h) CLASSIC_L: andi. r9, r8, 0x2000 beq- CLASSIC_R ori r7, r7, 0x8 ; up (v) / left (h) CLASSIC_R: andi. r9, r8, 0x200 beq- CLASSIC_ZL ori r7, r7, 0x1 ; left (v) / down (h) CLASSIC_ZL: andi. r9, r8, 0x80 beq- CLASSIC_ZR ori r7, r7, 0x2000 ; z CLASSIC_ZR: andi. r9, r8, 0x4 beq- CLASSIC_PLUS ori r7, r7, 0x4000 ; c CLASSIC_PLUS: andi. r9, r8, 0x400 beq- CLASSIC_MINUS ori r7, r7, 0x10 ; plus CLASSIC_MINUS: andi. r9, r8, 0x1000 beq- RETURN ori r7, r7, 0x1000 ; minus RETURN: or r6, r6, r7 andi. r9, r6, 0x9FFF
Here order focused on do Game qualityThis is amazing and I’ve loved the games so far. Is there any way you could take a peek at Thrillville: Off The Rails? PSP/PS2 lacks features, Wii is perfect and is the 360 version of the game but there’s some incredibly iffy motion controls for mini games.

Huh, very weird, I'll have to double-check what's going on there.@Vague Rant Your max code seems to be corrupting the ingame audio on Dolphin emulator! Whenever its enabled the audio is super choppy and corrupted! I can make out some of the music but its very broken. Whats going on?
This might be a case where the language menu is set up to support a solo Wiimote (you could try unplugging the CC entirely and see if the Wiimote works standalone) but the game after that point only responds while a Nunchuk is connected. I just had this situation with the game in this post, where the controls would work initially but then once the game starts checking if the Nunchuk is available, they quit. Fixing it was a similar process to fixing Nunchuk error messages, trying to identify some code that checks that the extension byte is 1 and misbehaves when it isn't.It seems that the language-selector does support the classic controller with my gecko code (at least i can use the dpad and a to continue), but not after that. It seems that the same function is beeing called in the menu aswell. (I did the same procedure identifying kpad in the main menu)
WPADProbe() run is checked. That function doesn't return the result in r3, instead the way it works is that you pass it an address and it writes the extension byte to that address. If you go back to my previous post where I screenshotted WPADProbe(), you can see the instruction at 80325638: stw r0, 0 (r30). That's where the extension is being written out (as a 32-bit value, so generally 00000002 in our case). If you breakpoint that address (the equivalent in your game, I mean), then copy the address from r30 and paste it into the top right of the Memory tab, you can see that address in memory, right click it and set a read breakpoint, to pause execution any time the game reads that value. This can sometimes be a quick way to find what's looking for a 1, because if something reads that address then immediately compares it against 1, you can be sure it's some type of Nunchuk check, and then you can insert your own code something like this, replacing the compare instruction:; bypass nunchuk check
cmplwi r0, 1
beq- RETURN
cmplwi r0, 2
RETURN:
cmpwi for this comparison and others use cmplwi; for our purposes either is fine but just match whatever the OG game does for safety.)WPADProbe() which will often be part of the WPAD library itself, as well as ignoring the call that comes from KPADRead() itself. We don't want to mess with the extension byte this early, because KPAD relies on knowing the real extension to handle reading the Classic Controller. That's why we jump in after KPAD is done for this frame to start patching extension checks.WPADProbe() directly to grab the extension byte. They might grab it out of the KPADStatus struct or anywhere else that the extension byte has previously been copied to outside of either. Another approach that's sometimes decent is to set a breakpoint at the start of KPADRead() and explore the parent function to see if there's any cmpwi rX, 1s within the function after KPADRead() runs. Again, no guarantees, but sometimes that's a handy way to find extension checks. You can set a breakpoint on that compare and make sure that it's coming in as 2. If you want to be extra sure, you can change the extension in the controller settings and see if it changes on the next break as well--keep in mind, Dolphin spends a few frames reporting that the extension was removed and such before it actually updates to the new extension type.0x0C00read_kpad_button()r3 and paste that into the Memory tabKPADStatusKPADRead() itself, possibly some more copies after that before they start being read for gameplay purposesThis is normal Dolphin behavior. As far as I understand it, turning off a Gecko code in Dolphin means "stop writing this piece of code into memory." However, it doesn't un-write the code, so any code that you've already inserted/replaced this session is still being applied, unless or until the game itself writes over that memory. As a general rule, nothing ever writes to the area of memory where the binary is held, so patches to code like we're doing are essentially "permanent" for as long as the current session lasts.The thing is, i am not sure how it is working at all. I can enter a "random" starting adress for the gecko code, and it will still behave the same weird way:
- If i enable my code, usually the mapped classic controls work and seemingly press a button. (Button A, for selecting the lang)
- Disabling the code does not reliably disable that behaviour. (I have to restart dolphin to get back to the "buttons dont do anything"-state). Also changing the controls does not reliably change them for the emulator, the only surefire way to do that is to restart the emulator.
The only way i can explain this is that dolphin caches some instructions somewhere. Is this normal or is dolphin (flatpak, ubuntu) broken?
That is inside(from the guide, for the new sdk)
Does this have to be 0x9fff? Also, is this inside the bl call/read_kpad_button or above it? (the one inside is not the second instruction, but the thuird, and it uses different registers and 0x0800 as a constant)
I tried the same for Lego Lord of the Rings as a sanity check, and while i could find what i assume are the proper calls, this time it didn't work at all. Though i didn't spend much time figuring out why, first SW3, then the next thing!
read_kpad_button(). In my experience it's absolutely always 0x9FFF. This code is specifically separating out the Nunchuk buttons C and Z (the two highest bits, 0x4000 and 0x2000 in hex) from the rest of the bits (0x9FFF) so that there's a register that's holding only the lower 14 bits which represent the Wiimote's buttons (plus three empty spaces where buttons theoretically could be but aren't). If it's not doing that, you might be looking at the wrong place.A few more questions related to these hacks:
1. How do you locate read_kpad_ext, and if a game does not use that, are there any further instructions to finding KPADStatus? It seems a little confusing
2. Do you have the knowledge of modifying existing controls? (EX: Modifying metroid other M to remap DPAD down for the wiimote tilt, etc)
If I get more knowledge I would be interested in enhancing some CC hacks to support nunchuk aswell, but its a maybe. It probably wont even happen aswell, but It is good for documentation.
Of course, no hassle. I already have been replying A lot so no need to rush anything![]()
read_kpad_ext() is basically the same thing as read_kpad_stick(), it's found in the same place and does mostly the same stuff. They just renamed it in some later SDK versions, probably in line with adding some extra functionality or something. I haven't actually looked into it, but technically there are other things that plug into the EXT port on the base of the Wiimote, so maybe a new accessory launched and they expanded the functionality of read_kpad_stick() and renamed it in the process. Nothing about how we interact with it changes, because we're just messing with the analog sticks, not any of the later additions.read_kpad_stick() or read_kpad_ext() for each hack. Basically if a game is relatively late in the Wii's lifespan I say ext, otherwise stick. I guarantee there are times where I've incorrectly guessed what the function was called internally as I go through labelling what I'm looking at, but they're basically synonymous so it's not very important to know which is which.; KPADRead
; r4 holds extType
; r7 holds wiimote bitfield
; r8 holds wiimote+nunchuk bitfield
; r9 holds classic bitfield
li r7, 0 ; blank out real wiimote buttons
WIIMOTE_HOME:
andi. r0, r8, 0x8000
beq- WIIMOTE_UP
ori r7, r7, 0x8000 ; home
WIIMOTE_UP:
andi. r0, r8, 0x8
beq- WIIMOTE_DOWN
ori r7, r7, 0x8 ; up (v) / left (h)
WIIMOTE_DOWN:
andi. r0, r8, 0x4
beq- WIIMOTE_LEFT
ori r7, r7, 0x4 ; down (v) / right (h)
WIIMOTE_LEFT:
andi. r0, r8, 0x1
beq- WIIMOTE_RIGHT
ori r7, r7, 0x1 ; left (v) / down (h)
WIIMOTE_RIGHT:
andi. r0, r8, 0x2
beq- WIIMOTE_A
ori r7, r7, 0x2 ; right (v) / up (h)
WIIMOTE_A:
andi. r0, r8, 0x800
beq- WIIMOTE_B
ori r7, r7, 0x800 ; a
WIIMOTE_B:
andi. r0, r8, 0x400
beq- WIIMOTE_1
ori r7, r7, 0x400 ; b
WIIMOTE_1:
andi. r0, r8, 0x200
beq- WIIMOTE_2
ori r7, r7, 0x200 ; 1
WIIMOTE_2:
andi. r0, r8, 0x100
beq- WIIMOTE_PLUS
ori r7, r7, 0x100 ; 2
WIIMOTE_PLUS:
andi. r0, r8, 0x10
beq- WIIMOTE_MINUS
ori r7, r7, 0x10 ; plus
WIIMOTE_MINUS:
andi. r0, r8, 0x1000
beq- NUNCHUK_C
ori r7, r7, 0x1000 ; minus
NUNCHUK_C:
andi. r0, r8, 0x4000
beq- NUNCHUK_Z
ori r7, r7, 0x4000 ; c
NUNCHUK_Z:
andi. r0, r8, 0x2000
beq- WIIMOTE_DONE
ori r7, r7, 0x2000 ; z
WIIMOTE_DONE:
mr r8, r7
RETURN:
andi. r0, r7, 0x9FFF
ori r7, r7, 0x800 ; a to change which button they virtually press. For newer games you'd need to adjust the registers (r7/r8 would be r6/r7 in read_kpad_button(), and the same rules apply to the garbage register as usual. If the first argument to the andi. where you're injecting the code is a different number than r0, you need to replace all the r0s with that register.Yeah, that is definitely something that would be more complicated and not something you could do via just KPAD hacks. You'd need to find where the individual game handles its control scheme and decouple the camera and pointer as you mention. The way we're handling the pointer in these hacks is basically just tricking the games into thinking we're pointing the Wii Remote, so we can't do anything that a real pointer can't do. It would definitely be possible, but it's not something I know how to do or would be much help with.@Vague Rant On a different topic, do you know how hard it would be to "fix" the call of duty games? Some have classic support natively (which works *flawless*).
Some others have "pointing" control, where you point the rifle where you want to shoot, while the camera follows the pointer.
From what i tried in that game, it should be nicely playable with a classic controller *if* it is possible to decouple the camera from the pointer, and fix the rifle in the center of the screen. I guess this would be quite a bit more involved than just figuring out buttonmappings.
I definitely keep quality in mind as a metric for which games to look at (except when I don't; Flip's Twisted World), but there's a lot of other factors that go into it as well. For example, the previous game I did was by Incinerator Studio, so I decided to stick with that developer for the next game, just in the hope that I could recognize some similarities while the previous game was fresh in my memory--ultimately, I didn't, but that was the plan.OK someone games people asking form should work base on the quality of the game order should be.
1. Crash Bandicoot Crash of the Titans
2. Crash bandicoot Mind Over Mutant
3. SpongeBob SquarePants featuring Nicktoons: Globs of Doom
Also should do patch for cars 1 unsure different that whould be in itself as batter og ver should focused games people asking form first as take quite some time for patch to be made.
Neat, this is another one I've never heard of, sounds like a pretty cool game though. Depending on the complexity of the motions needed, it might be a tough one, but I'll definitely add it to my investigation list.This is amazing and I’ve loved the games so far. Is there any way you could take a peek at Thrillville: Off The Rails? PSP/PS2 lacks features, Wii is perfect and is the 360 version of the game but there’s some incredibly iffy motion controls for mini games.
Classic Controller Support [Vague Rant]
C20C2138 00000002
28000001 41820008
28000002 00000000
C20C2C3C 00000002
28000001 41820008
28000002 00000000
C20EC900 00000002
28000001 41820008
28000002 00000000
0414F6A4 41820034
C2086874 00000028
90010024 2C040000
40820134 8803005C
2C000002 40820128
2C0F0001 408200E4
48000021 80097D5C
3FAAAAAB 3D4CCCCD
00000000 00000000
3DCCCCCD 3F800000
7CA802A6 90A1000C
5727083C 38E7000C
C0030074 FC000210
C0230078 FC200A10
FC00082A C0450014
FC001040 4080001C
7CC53AAE 28060000
408100C4 80030000
70000800 4182000C
38C0012C 48000008
38C6FFFF 7CC53B2E
38C00002 98C3005E
80650000 28030001
40810018 90A1000C
7C6803A6 4E800021
80A1000C 90650000
2C030001 7FE3FB78
C0450004 40820008
EC4200B2 C0650008
C0030020 C0230074
FC211024 4800002D
D0030020 C0030024
C0230078 FC200850
48000019 D0030024
80010024 7C0803A6
38210020 4E800020
FC0100FA C0250018
FC000800 4180000C
FC000890 48000014
FC200850 FC000800
41810008 FC000890
4E800020 00000000
0408772C 7FC3F378
04087E18 60000000
C2087E1C 0000001F
4800000D 00000000
00000000 7C6802A6
5760083C 7C630214
2809FFFF 4082000C
A1230000 48000014
2C040002 408200C4
38800001 B1230000
71200800 41820008
61088000 71200001
41820008 61080008
71204000 41820008
61080004 71200002
41820008 61080001
71208000 41820008
61080002 71200010
41820008 61080800
71200040 41820008
61080800 71200008
41820008 61084000
71200020 41820008
61080400 71202000
41820008 61081000
71200200 41820008
61081000 71200080
41820008 61080001
71200004 41820008
61082000 71200400
41820008 61080010
71201000 41820008
61081000 7CE74378
70E09FFF 00000000
Skip Gadget Combo Motion Controls [Vague Rant]
063324C8 00000014
806DC928 38000001
98030011 98030012
48000078 00000000
Classic Controller Support [Vague Rant]
C20C1B04 00000002
28000001 41820008
28000002 00000000
C20C2684 00000002
28000001 41820008
28000002 00000000
C20EBC4C 00000002
28000001 41820008
28000002 00000000
0414F22C 48000038
C2086874 00000028
90010024 2C040000
40820134 8803005C
2C000002 40820128
2C0F0001 408200E4
48000021 80097D5C
3FAAAAAB 3D4CCCCD
00000000 00000000
3DCCCCCD 3F800000
7CA802A6 90A1000C
5727083C 38E7000C
C0030074 FC000210
C0230078 FC200A10
FC00082A C0450014
FC001040 4080001C
7CC53AAE 28060000
408100C4 80030000
70000800 4182000C
38C0012C 48000008
38C6FFFF 7CC53B2E
38C00002 98C3005E
80650000 28030001
40810018 90A1000C
7C6803A6 4E800021
80A1000C 90650000
2C030001 7FE3FB78
C0450004 40820008
EC4200B2 C0650008
C0030020 C0230074
FC211024 4800002D
D0030020 C0030024
C0230078 FC200850
48000019 D0030024
80010024 7C0803A6
38210020 4E800020
FC0100FA C0250018
FC000800 4180000C
FC000890 48000014
FC200850 FC000800
41810008 FC000890
4E800020 00000000
0408772C 7FC3F378
04087E18 60000000
C2087E1C 0000001F
4800000D 00000000
00000000 7C6802A6
5760083C 7C630214
2809FFFF 4082000C
A1230000 48000014
2C040002 408200C4
38800001 B1230000
71200800 41820008
61088000 71200001
41820008 61080008
71204000 41820008
61080004 71200002
41820008 61080001
71208000 41820008
61080002 71200010
41820008 61080800
71200040 41820008
61080800 71200008
41820008 61084000
71200020 41820008
61080400 71202000
41820008 61081000
71200200 41820008
61081000 71200080
41820008 61080001
71200004 41820008
61082000 71200400
41820008 61080010
71201000 41820008
61081000 7CE74378
70E09FFF 00000000
Skip Gadget Combo Motion Controls [Vague Rant]
063325E0 00000014
806DC948 38000001
98030011 98030012
48000078 00000000
Classic Controller Support [Vague Rant]
C20C1B04 00000002
28000001 41820008
28000002 00000000
C20C2684 00000002
28000001 41820008
28000002 00000000
C20EBC4C 00000002
28000001 41820008
28000002 00000000
0414F240 48000038
C2086874 00000028
90010024 2C040000
40820134 8803005C
2C000002 40820128
2C0F0001 408200E4
48000021 80097D5C
3FAAAAAB 3D4CCCCD
00000000 00000000
3DCCCCCD 3F800000
7CA802A6 90A1000C
5727083C 38E7000C
C0030074 FC000210
C0230078 FC200A10
FC00082A C0450014
FC001040 4080001C
7CC53AAE 28060000
408100C4 80030000
70000800 4182000C
38C0012C 48000008
38C6FFFF 7CC53B2E
38C00002 98C3005E
80650000 28030001
40810018 90A1000C
7C6803A6 4E800021
80A1000C 90650000
2C030001 7FE3FB78
C0450004 40820008
EC4200B2 C0650008
C0030020 C0230074
FC211024 4800002D
D0030020 C0030024
C0230078 FC200850
48000019 D0030024
80010024 7C0803A6
38210020 4E800020
FC0100FA C0250018
FC000800 4180000C
FC000890 48000014
FC200850 FC000800
41810008 FC000890
4E800020 00000000
0408772C 7FC3F378
04087E18 60000000
C2087E1C 0000001F
4800000D 00000000
00000000 7C6802A6
5760083C 7C630214
2809FFFF 4082000C
A1230000 48000014
2C040002 408200C4
38800001 B1230000
71200800 41820008
61088000 71200001
41820008 61080008
71204000 41820008
61080004 71200002
41820008 61080001
71208000 41820008
61080002 71200010
41820008 61080800
71200040 41820008
61080800 71200008
41820008 61084000
71200020 41820008
61080400 71202000
41820008 61081000
71200200 41820008
61081000 71200080
41820008 61080001
71200004 41820008
61082000 71200400
41820008 61080010
71201000 41820008
61081000 7CE74378
70E09FFF 00000000
Skip Gadget Combo Motion Controls [Vague Rant]
063325F4 00000014
806DC948 38000001
98030011 98030012
48000078 00000000
Classic Controller Support [Vague Rant]
C20C1B04 00000002
28000001 41820008
28000002 00000000
C20C2684 00000002
28000001 41820008
28000002 00000000
C20EBC4C 00000002
28000001 41820008
28000002 00000000
0414F258 48000038
C2086874 00000028
90010024 2C040000
40820134 8803005C
2C000002 40820128
2C0F0001 408200E4
48000021 80097D5C
3FAAAAAB 3D4CCCCD
00000000 00000000
3DCCCCCD 3F800000
7CA802A6 90A1000C
5727083C 38E7000C
C0030074 FC000210
C0230078 FC200A10
FC00082A C0450014
FC001040 4080001C
7CC53AAE 28060000
408100C4 80030000
70000800 4182000C
38C0012C 48000008
38C6FFFF 7CC53B2E
38C00002 98C3005E
80650000 28030001
40810018 90A1000C
7C6803A6 4E800021
80A1000C 90650000
2C030001 7FE3FB78
C0450004 40820008
EC4200B2 C0650008
C0030020 C0230074
FC211024 4800002D
D0030020 C0030024
C0230078 FC200850
48000019 D0030024
80010024 7C0803A6
38210020 4E800020
FC0100FA C0250018
FC000800 4180000C
FC000890 48000014
FC200850 FC000800
41810008 FC000890
4E800020 00000000
0408772C 7FC3F378
04087E18 60000000
C2087E1C 0000001F
4800000D 00000000
00000000 7C6802A6
5760083C 7C630214
2809FFFF 4082000C
A1230000 48000014
2C040002 408200C4
38800001 B1230000
71200800 41820008
61088000 71200001
41820008 61080008
71204000 41820008
61080004 71200002
41820008 61080001
71208000 41820008
61080002 71200010
41820008 61080800
71200040 41820008
61080800 71200008
41820008 61084000
71200020 41820008
61080400 71202000
41820008 61081000
71200200 41820008
61081000 71200080
41820008 61080001
71200004 41820008
61082000 71200400
41820008 61080010
71201000 41820008
61081000 7CE74378
70E09FFF 00000000
Skip Gadget Combo Motion Controls [Vague Rant]
0633260C 00000014
806DC948 38000001
98030011 98030012
48000078 00000000
Classic Controller Support [Vague Rant]
C20C2024 00000002
28000001 41820008
28000002 00000000
C20C2BA4 00000002
28000001 41820008
28000002 00000000
C20EC0D8 00000002
28000001 41820008
28000002 00000000
0414F710 41820034
C2086834 00000028
90010024 2C040000
40820134 8803005C
2C000002 40820128
2C0F0001 408200E4
48000021 80097D1C
3FAAAAAB 3D4CCCCD
00000000 00000000
3DCCCCCD 3F800000
7CA802A6 90A1000C
5727083C 38E7000C
C0030074 FC000210
C0230078 FC200A10
FC00082A C0450014
FC001040 4080001C
7CC53AAE 28060000
408100C4 80030000
70000800 4182000C
38C0012C 48000008
38C6FFFF 7CC53B2E
38C00002 98C3005E
80650000 28030001
40810018 90A1000C
7C6803A6 4E800021
80A1000C 90650000
2C030001 7FE3FB78
C0450004 40820008
EC4200B2 C0650008
C0030020 C0230074
FC211024 4800002D
D0030020 C0030024
C0230078 FC200850
48000019 D0030024
80010024 7C0803A6
38210020 4E800020
FC0100FA C0250018
FC000800 4180000C
FC000890 48000014
FC200850 FC000800
41810008 FC000890
4E800020 00000000
040876EC 7FC3F378
04087DD8 60000000
C2087DDC 0000001F
4800000D 00000000
00000000 7C6802A6
5760083C 7C630214
2809FFFF 4082000C
A1230000 48000014
2C040002 408200C4
38800001 B1230000
71200800 41820008
61088000 71200001
41820008 61080008
71204000 41820008
61080004 71200002
41820008 61080001
71208000 41820008
61080002 71200010
41820008 61080800
71200040 41820008
61080800 71200008
41820008 61084000
71200020 41820008
61080400 71202000
41820008 61081000
71200200 41820008
61081000 71200080
41820008 61080001
71200004 41820008
61082000 71200400
41820008 61080010
71201000 41820008
61081000 7CE74378
70E09FFF 00000000
Skip Gadget Combo Motion Controls [Vague Rant]
06332CB8 00000014
806DC948 38000001
98030011 98030012
48000078 00000000
| Wii Remote/Nunchuk | Classic Controller | Function |
|---|---|---|
| Wiimote Home | Home Remember: Right Stick as pointer | Open/Close Home Menu |
| Wiimote D-Pad | D-Pad ZL | Menus Navigation Gameplay Gadget Combo |
| Wiimote A | A B | Menus Confirm Gameplay Jump |
| Wiimote B | Y | Menus Cancel Gameplay Attack |
| Wiimote 1 & 2 | Not mapped | Not used? |
| Wiimote Plus | Plus | Gameplay Pause Drop In (player 2) |
| Wiimote Minus | Minus L/R | Gameplay Switch Character Drop Out (player 2) |
| Wiimote Pointer | Right Stick | Menus Navigation Home Button Menu Navigation |
| Nunchuk Stick | Left Stick | Gameplay Movement |
| Nunchuk C | X | Gameplay Interact (pull levers, etc.) |
| Nunchuk Z | ZR | Gameplay Gadget Attack |
C2 in InGameDevicesCheck(): bypass Nunchuk checkC2 in AreAllAttachmentsAttached(): bypass Nunchuk check (again)C2 in FormatDeviceMessage(): fffff are you fu--yes, it's another one04 in Update: read Classic Controller as Nunchuk-type controllerC2 in calc_dpd_variable(): simulate IR pointer on Right Stick04 in read_kpad_stick(): stick redirection04 and C2 in KPADRead(): dropped connection fix and button injector; KPADRead
; button injector
; 80087E1C for USA/EUR (En,Fr)/EUR (De,Es,It)/SCN
; 80087DDC for KOR
; r4 holds extType
; r7 holds wiimote bitfield
; r8 holds wiimote+nunchuk bitfield
; r9 holds classic bitfield
; magic
bl GRAB
MAGIC:
HELD: .double 0
GRAB:
mflr r3
slwi r0, r27, 1
add r3, r3, r0
; check dropped extension
cmplwi r9, 0xFFFF
bne- CLASSIC
lhz r9, HELD-MAGIC(r3)
b DROPPED_CONNECTION
CLASSIC:
cmpwi r4, 0x2
bne- RETURN
li r4, 0x1 ; i'm a nunchuk
sth r9, HELD-MAGIC(r3)
DROPPED_CONNECTION:
CLASSIC_HOME:
andi. r0, r9, 0x800
beq- CLASSIC_UP
ori r8, r8, 0x8000 ; home
CLASSIC_UP:
andi. r0, r9, 0x1
beq- CLASSIC_DOWN
ori r8, r8, 0x8 ; up (v) / left (h)
CLASSIC_DOWN:
andi. r0, r9, 0x4000
beq- CLASSIC_LEFT
ori r8, r8, 0x4 ; down (v) / right (h)
CLASSIC_LEFT:
andi. r0, r9, 0x2
beq- CLASSIC_RIGHT
ori r8, r8, 0x1 ; left (v) / down (h)
CLASSIC_RIGHT:
andi. r0, r9, 0x8000
beq- CLASSIC_A
ori r8, r8, 0x2 ; right (v) / up (h)
CLASSIC_A:
andi. r0, r9, 0x10
beq- CLASSIC_B
ori r8, r8, 0x800 ; a
CLASSIC_B:
andi. r0, r9, 0x40
beq- CLASSIC_X
ori r8, r8, 0x800 ; a
CLASSIC_X:
andi. r0, r9, 0x8
beq- CLASSIC_Y
ori r8, r8, 0x4000 ; c
CLASSIC_Y:
andi. r0, r9, 0x20
beq- CLASSIC_L
ori r8, r8, 0x400 ; b
CLASSIC_L:
andi. r0, r9, 0x2000
beq- CLASSIC_R
ori r8, r8, 0x1000 ; minus
CLASSIC_R:
andi. r0, r9, 0x200
beq- CLASSIC_ZL
ori r8, r8, 0x1000 ; minus
CLASSIC_ZL:
andi. r0, r9, 0x80
beq- CLASSIC_ZR
ori r8, r8, 0x1 ; left (v) / down (h)
CLASSIC_ZR:
andi. r0, r9, 0x4
beq- CLASSIC_PLUS
ori r8, r8, 0x2000 ; z
CLASSIC_PLUS:
andi. r0, r9, 0x400
beq- CLASSIC_MINUS
ori r8, r8, 0x10 ; plus
CLASSIC_MINUS:
andi. r0, r9, 0x1000
beq- CLASSIC_DONE
ori r8, r8, 0x1000 ; minus
CLASSIC_DONE:
or r7, r7, r8
RETURN:
andi. r0, r7, 0x9FFF
Okay, thank you! Ill look into remapping Rhythm Heaven to support the Horizontal remote soon as a test.This is completely untested, expect typos or anything going on here, but ideally it should work basically the way the injector you're used to does. In the above snippet every button is just mapped back to itself, so the code does literally nothing, but you can rearrange the buttons (e.g.ori r7, r7, 0x800 ; ato change which button they virtually press. For newer games you'd need to adjust the registers (r7/r8would ber6/r7inread_kpad_button(), and the same rules apply to the garbage register as usual. If the first argument to theandi.where you're injecting the code is a different number thanr0, you need to replace all ther0s with that register.
Thank you very much, but the batch file fails with "ERROR: Could not find 00000007.app file." Any idea how to remedy this?
View attachment 475483
Ever get a chance to look at Blaster Master: Overdrive again btw? If not no worries!I appreciate the quick reply!
Here's what I got by verifying with the latest version of Dolphin:
View attachment 475679
The European WAD shows the same messages except "key index is 20 but should be 0."
I then tried WADs from different sources but got the same result as before, the USA WAD saying "key index is 199" and European "key index is 20."