How to Make your own Cheat Codes
#51
Got the game. My checksums are diff than yours Hackwiz. Dumb question, but how do you use the checksumming utilities in Dolphin (I'm using an old version so maybe it simply doesn't exist for me).

I use the linux specific checksum utilities.

Anyway, my two instructions matches yours..

816035B0 lbz r0, 0x10 (r27)
816035b4 stw r0, 0x9C (r23)

Dolphin does indeed read this as RMKE01 (NTSC-U)
Reply
#52
Anyway, I went ahead and made two different Character Selection codes. I will discuss on "how" I made them. All I used was the character value list you have gave me earlier to speed up the initial memory search process. Nothing else.

My approach:
  • Choose character (slot 0), do NOT choose next character
  • Set value and do initial search
  • Press B, reselect with diff/new character
  • Change value on memory engine and do next scan

Repeat over and over til I had 3 Dynamic Memory results. Wrote them down

IMPORTANT NOTE: This game is odd, it has dynamic memory in mem80 with static memory (instructions) in mem81. This is reverse of games like MKWii.

I noticed that these 3 results also updated live (when hovering over to a new character before pressing A on him/her)

I set a Write BP on the 1st Dynamic Memory Result, got this address w/ corresponding instruction.

815B5234 : stb r5, 0x0498 (r3)

I removed the BP, and set a new Write BP on 2nd result, got this...

81603138 : stb r0, 0x00E8 (r17)

I removed that BP, and set a new Write BP on 3rd/final result, got this...

816035B4 : stw r0, 0x009C (r23)

I wanted to see which one would get triggered first out of all 3. The one that gets triggered first is usually the one that is suitable or best suitable for making the code. I cleared the recent 3rd Write BP, resumed emulation, and then set all 3 Write BPs at once. The one that gets triggered 1st out of the 3 was...

815B5234 : stb r5, 0x0498 (r3)

I then removed all 3 Write BPs, and set the above address as an Instruction BP. Instruction BPs are obviously for Instructions in Static Memory. I wanted to make sure this instruction would break for all 6 characters (3v3). It did. It would always break whenever I hovered over to a new character regardless of what current slot I was choosing it for.

So now I know this address & instruction effects P1 and all CPUs. I then made this basic code...

Code:
NTSC-U Force Character on All Slots [Vega]
C35B5234 00000002
38A000XX 98A30498
60000000 00000000

XX = Character to Force

li r5, 0xXX #Fill in XX value for Character
stb r5, 0x0498 (r3) #Original Instruction, write Char value to Memory

After a quick test on 3v3 Basketball, I confirmed this works. Now we need to move on to making this customizable for each slot/player..

Wii Games like to place character values of all players/CPUs nearby each other in memory, usually in a some sort of table format. So I decided to go back to the 1st Dynamic Address (out of the 3) I got from the initial memory search. While hovering over diff characters for different slots (P1, CPU1, CPU2, etc), I notice some patterns...
  • Halfword immediately before the Character Byte represents some bit flags (values here is something like 0x8016, 0x8017, 0x8013, etc). So its obvious that the first bit in this halfword value always gets flipped high when the character HAS been selected. No idea what the other flags represent
  • The byte immediately after the Character Byte is 0x00 for non-Mii and 0xFF for Mii
  • The byte after that is... 0x00 = Not on this current slot/CPU for character selection, 0x01 = Using this slot at the moment, 0x02 = Character selected/chosen

We can concatenate the halfword and 3 bytes and think of it as one whole "packet" that corresponds to each player/CPU.

After selecting and unselected multiple characters for each slot, I notice each player/CPU packet lies nearby each other in memory. They are all 0x28 (40 bytes) from each other. So for example let's say slot0 (P1) packet is at 0x80597000

Then slot1 (CPU1) packet is at 0x80597028
Then slot2 (CPU2) packet is at 0x80597050
etc etc

I noticed also that the in the game itself, it doesn't display the slot orders 100% true. For a 3v3 with one Human Player (P1), the slot orders for the characters on the TV screen, left to right are..

1 0 2 5 3 4

Not a big deal, just noting it.

The current hook address I didn't like because registers such as r11 weren't safe for use (which is very rare). So I needed to find a better hook address nearby.

The current hook address is within what is known as a Function.

When you get more advanced, you will learn about Function Calls -> https://mariokartwii.com/showthread.php?tid=1052

In a nutshell, my hook address was in a small small function, one without a prologue or epilogue. So its easy to know mostly what is going on in this function (form a higher level programming standpoint).

Anyway, if you scroll down a bit, the final instructions of the function are....

Address | Instruction
815b5268 | li r3, 0
815b526C | blr

Basically the function places a zero in r3 and uses the blr to return to its Parent function. It's telling the Parent funciton, "hey everything is good to go, keep doing what we need to do"

So anyway, this is a good hook address. At the end of functions (epilogues), registers r4 thru r12 are safe.

After some more analysis (GVR analysis) I have noticed r27 + 0x496 always points to slot0's packet. Remember that GVRs can hold constants that can be used as reliable address's to always point to a spot in dynamic memory regardless of what the actual value of the address is. It will be updated if the stuff in dynamic memory has been moved.

So I was able to make this.... (code only tested once in 3v3 basketball)

Code:
NTSC-U Custom Character Selection [Vega]
C35B5268 00000008
7D8802A6 4800000D
RRTTVVXX YYZZ0000
7D6802A6 396BFFFF
38600006 395B0470
7C6903A6 8C0B0001
9C0A0028 4200FFF8
7D8803A6 38600000
60000000 00000000

RR = Character for Slot 0
TT = Character for Slot 1
VV = Character for Slot 2
XX = Character for Slot 3
YY = Character for Slot 4
ZZ = Character for Slot 5

#START ASSEMBLY  1st

#Hook Address's
#NTSC-U = 815b5268

#r3 safe for use if original instruction is last

#Backup LR
mflr r12

#Set Lookup Table
bl table
.byte 0x00 #Values plugged in so Source can compile
.byte 0x01
.byte 0x02
.byte 0x03
.byte 0x04
.byte 0x05
.align 2
table:
mflr r11

#Set Initial Load Address for BL Table
addi r11, r11, -1

#Set Loop Count for 6 character slots (slots 0 thru 5)
li r3, 6

#Set Initial Loop Store Address
#r27 + 0x496 = slot 0's character "packet"
#r27 + 0x498 = slot 0's character byte within packet
#So do... r27 + 0x470
#Each character byte will be 0x28 away from each other
addi r10, r27, 0x470

#Set CTR now
mtctr r3

#Transfer shit
loop:
lbzu r0, 0x1 (r11)
stbu r0, 0x28 (r10)
bdnz+ loop

#Restore LR
mtlr r12

#Original Instruction
#Tell parent function that this child function was a success (always success)
li r3, 0

#END ASSEMBLY

The code utilizes the BL Trick -> https://mariokartwii.com/showthread.php?tid=977

The BL Trick will create my own custom table of just the custom Character Bytes and transfer those into each Packet of the Game's Table in Dynamic Memory which is referenced via r27.

In conclusion, most of this info will just fly right over your head. But as your learn more and more, you can come back to this post for more help.

Assembly coding for cheats in games is not an exact science. You need some intuition and be able to investigate what you are "given".

If you are familiar with stock/forex/crypto trading, think of Wii Coding like Discretionary Trading with sometimes using small amounts of Technical Analysis. It is *not* 100% systematic.



EDIT:

I went ahead and made my own version of Instant SP Bar code and Freeze Timer code. I was unable to make a "Start Game with Full SP" or "SP Never Decrements" code.

Here are the two codes~

RMKE01 Instant Max SP Bar Gain [Vega]

X = Team
0 = Blue
1 = Red

NTSC-U
C218B460 00000003
2C04000X 40820008
FC210824 9421FFE0
60000000 00000000

#Hook Address
#NTSC-U = 8018B460

#Check for slot (r4 arg of func)
cmpwi r4, 0 #Set on Blue Team, adjust to 1 for Red
bne- original_instruction

#rtoc - 0x6474 constants the constant of 1.0
#However f1 is always non-zero, and fdiv is MUCH faster than lfs
#f1 = func 1st float arg, it is next bar level to increment up to
#Always make f1 = 1.0 (max SP bar)
fdiv f1, f1, f1

#OG instruction, make frame for function
original_instruction:
stwu sp, -0x0020 (sp)

============

RMKE01 Freeze Timer [Vega]

Press & hold button to freeze timer. Let go to allow timer to continue.

NTSC-U
0418A468 3C60804D
284CCF12 YYYYZZZZ
0418A468 4E800020
E0000000 80008000

"Source":
Instruction of "lis r3, 0x804D" at address 0x8018A468 is replaced with "blr".

This instruction is the start of a very small function that is called to updates/writes (decrement) the frame count (frames left in game) in dynamic memory. We can simply "cancel" the function with a "blr" at the very start. You could also instead place a nop on the parent function's corresponding "bl XXXXXXXX" instruction, but I'm not 100% sure if any other parent functions call this function. So to be safe, a blr inside the function itself was done.
Reply
#53
(05-04-2023, 11:15 AM)Hackwiz Wrote: Ok, so on Vimm's site the checksums they list are:

Vimm’s Checksums
CRC b67d2cf3
MD5 29c4d4d4e9853b95b769105a746d544f
SHA1 aa1079bc1d0eaaa4f5b0bfd8466695a98a3ee9cb

I downloaded the game twice from there this morning and ran the verify function using both Dolphin 5.0-11380 and 5.0-17269.

My results in all cases were:

My Results 5.0-11380
CRC a163373e
MD5 3d945b8cf6c3174137558c96f06d5a28
SHA1 1a77b8a8f72b2f08e2a2ff11cc943cc04b292435

My Results w/5.0-17269
CRC a163373e
MD5 3d945b8cf6c3174137558c96f06d5a28
SHA1 1a77b8a8f72b2f08e2a2ff11cc943cc04b292435

Please run the verify again on your game and post the results.

Vega, I put that link on discord.

My Results 5.0-18498 (The version I use)

CRC: a163373e
MD5: 3d945b8cf6c3174137558c96f06d5a28
SHA1: 1a77b8a8f72b2f08e2a2ff11cc943cc04b292435

My Results 5.0-11380

CRC: a163373e
MD5: 3d945b8cf6c3174137558c96f06d5a28
SHA1: 1a77b8a8f72b2f08e2a2ff11cc943cc04b292435

Well, in my case, like yours, the results based on the version I use (5.0-18498) compared to the one you use (5.0-11380) were exactly the same. The problem remains unanswered so far, since Vega also claims that their checksums are different from ours, but the instructions match yours.

(05-05-2023, 12:13 AM)Vega Wrote: Anyway, I went ahead and made two different Character Selection codes. I will discuss on "how" I made them. All I used was the character value list you have gave me earlier to speed up the initial memory search process. Nothing else.

My approach:
  • Choose character (slot 0), do NOT choose next character
  • Set value and do initial search
  • Press B, reselect with diff/new character
  • Change value on memory engine and do next scan

Repeat over and over til I had 3 Dynamic Memory results. Wrote them down

IMPORTANT NOTE: This game is odd, it has dynamic memory in mem80 with static memory (instructions) in mem81. This is reverse of games like MKWii.

I noticed that these 3 results also updated live (when hovering over to a new character before pressing A on him/her)

I set a Write BP on the 1st Dynamic Memory Result, got this address w/ corresponding instruction.

815B5234 : stb r5, 0x0498 (r3)

I removed the BP, and set a new Write BP on 2nd result, got this...

81603138 : stb r0, 0x00E8 (r27)

I removed that BP, and set a new Write BP on 3rd/final result, got this...

816035B4 : stw r0, 0x009C (r23)

I wanted to see which one would get triggered first out of all 3. The one that gets triggered first is usually the one that is suitable or best suitable for making the code. I cleared the recent 3rd Write BP, resumed emulation, and then set all 3 Write BPs at once. The one that gets triggered 1st out of the 3 was...

815B5234 : stb r5, 0x0498 (r3)

I then removed all 3 Write BPs, and set the above address as an Instruction BP. Instruction BPs are obviously for Instructions in Static Memory. I wanted to make sure this instruction would break for all 6 characters (3v3). It did. It would always break whenever I hovered over to a new character regardless of what current slot I was choosing it for.

So now I know this address & instruction effects P1 and all CPUs. I then made this basic code...

Code:
NTSC-U Force Character on All Slots [Vega]
C35B5234 00000002
38A000XX 98A30498
60000000 00000000

XX = Character to Force

li r5, 0xXX #Fill in XX value for Character
stb r5, 0x0498 (r3) #Original Instruction, write Char value to Memory

Well, in my case I got exactly the same instructions as yours (with the exception of the second one, since it appeared to me as r17 and not as r27), the funny thing is that now what changed was the address:

1. 815b59b4: stb r5, 0x0498 (r3)
2. 816038b8: stb r0, 0x00E8 (r17)
3. 81603d34: stw r0, 0x009C (r23)

In my case too, only the first address helped me to create the code, and it ended up like this:

Code:
NTSC-U Force Character on All Slots [LightKingdom666]
C35B59B4 00000002
38A000XX 98A30498
60000000 00000000

XX = Character to Force

li r5, 0xXX #Fill in XX value for Character
stb r5, 0x0498 (r3) #Original Instruction, write Char value to Memory

Try to test my code and tell me if it works, since I tried yours and unfortunately it didn't work (for me).
Reply
#54
I most likely typed the r17 vs r27 part for the blue/2nd instruction.

Yes it is odd your instructions match but not the addresses.

Whenever there are slight address differences, that means the game is a different region (i.e. NTSC-U vs PAL)

Apologies if this has been done already but have you verified the game ID on Dolphin? If so, what's the game ID output using Wiimms tools?

Only other explanation is the game is using a relocatable module basically meaning static memory isn't static.
Reply
#55
(05-06-2023, 12:51 AM)Vega Wrote: I most likely typed the r17 vs r27 part for the blue/2nd instruction.

Yes it is odd your instructions match but not the addresses.

Whenever there are slight address differences, that means the game is a different region (i.e. NTSC-U vs PAL)

Apologies if this has been done already but have you verified the game ID on Dolphin? If so, what's the game ID output using Wiimms tools?

Only other explanation is the game is using a relocatable module basically meaning static memory isn't static.

I have already checked it several times and if it is NTSC-U, since the game ID in that version is RMKE01.

Well, it's very strange, since the same addresses always appear to me every time I do the same method over and over again, what I don't understand is why completely different addresses/instructions appear to you two when we use the same version.

I have noticed that the addresses you used (815B5234 and 815B5268) have an offset between them of 0x34, and what about that? Well, the address that I have was 815B59B4, plus an offset of 0x34 took me to 815B59E8, and there the same instructions as you appeared:

815b59e8 li r3, 0
815b59ec blr

Although I didn't find anything in r27, since the registry never changes its value.

I tried to create other codes with other values and I got this:

Code:
P1 Character Modifier
C35B59B4 00000003
2C000000 40A20008
38A000XX 98A30498
60000000 00000000

P2 Character Modifier
C35B59B4 00000003
2C000028 40A20008
38A000XX 98A30498
60000000 00000000

P3 Character Modifier
C35B59B4 00000003
2C000050 40A20008
38A000XX 98A30498
60000000 00000000

P4 Character Modifier
C35B59B4 00000003
2C000078 40A20008
38A000XX 98A30498
60000000 00000000

P5 Character Modifier
C35B59B4 00000003
2C0000A0 40A20008
38A000XX 98A30498
60000000 00000000

P6 Character Modifier
C35B59B4 00000003
2C0000C8 40A20008
38A000XX 98A30498
60000000 00000000

The problem is that when I use one (any one), it works, but when I use all 6 (or even 2) none of them work, what do you think is the reason?

The assembly is this:

Code:
cmpwi r0, 0xXX #Player slot
bne+ jump_code

li r5, 0xXX #Character

jump_code:
stb r5, 0x0498 (r3)
Reply
#56
Okay, that rules out everything external, we have exact copies of the game.
I'm thinking you may have something checked/unchecked in dolphin that is affecting your address offset(s).

Let's try this:
-create a new folder to backup some files into
-Navigate to Documents->Dolphin Emulator->Config
-Copy the contents of the config folder and store in the folder you created.
-Delete all the files and folders in the Config folder
-Close window
-Boot up Dolphin.
-Click on options
-Click on configuration
-In the General tab, make sure the enable cheats box is checked
-You will have to reconfigure your controller. In my case, I use a real Wiimote and nunchuck, all I
had to do was go into the backup folder I created, and copy the WiimoteNew.ini file and replace the one in the
Documents->Dolphin Emulator->Config folder
-Set your path to Mario Sports Mix [RMKE01]
-Boot the game
-Once up and fully running, Pause it and navigate to address 0x816035B0
-What do you see?

Vega, I can do this with 5.0-11380 to get checksums, not sure when and if they didn't have that feature available in previous revisions.

-Start up dolphin
-Right click on the game in the game list
-Click on properties
-Click on verify tab
-Make sure all the calculate boxes are checked
-Click on Verify Integrity
-Let it do its thing
Reply
#57
So I went ahead and launched the game on a different dolphin on a different computer. The nand on the dolphin was different too so new save state.

All my addresses remain the same.

Btw the r17 & r27 thing was indeed a typo.

Anyway this only boils down to two things. Either its a relocatable module issue or a user issue.
Reply
#58
Found a way to hijack the Timer. Ended up being a pain because it uses a single float frame count as a arg in a function which was difficult to hunt down.

So I made a speed-o-meter code from that



And also stumbled across being able to modify the text of the game, so I made this.



Well now it looks like I'm going back into hibernation again (in regards to code making).
Reply
#59
Hello, I have a short question regarding Dolphin and Breakpoints.

For some codes I wanted to set memory breakpoints, which is fine for the main menu and character/vehicle menu and so on, but as soon as I start a match, the dolphin speed drops to almost 0 frames per second. I am using windows 10, and Dolphin with OpenGL and JIT-recompiler.  After removing this BP, all works fine again (speed goes up). I also tried out other combinations but they seem only to be worse.

Is there a way to get a better speed when I set memory breakpoints?


Thank you already in advance.
Reply
#60
(05-06-2023, 03:57 PM)Hackwiz Wrote: Okay, that rules out everything external, we have exact copies of the game.
I'm thinking you may have something checked/unchecked in dolphin that is affecting your address offset(s).

Let's try this:
-create a new folder to backup some files into
-Navigate to Documents->Dolphin Emulator->Config
-Copy the contents of the config folder and store in the folder you created.
-Delete all the files and folders in the Config folder
-Close window
-Boot up Dolphin.
-Click on options
-Click on configuration
-In the General tab, make sure the enable cheats box is checked
-You will have to reconfigure your controller. In my case, I use a real Wiimote and nunchuck, all I
had to do was go into the backup folder I created, and copy the WiimoteNew.ini file and replace the one in the
Documents->Dolphin Emulator->Config folder
-Set your path to Mario Sports Mix [RMKE01]
-Boot the game
-Once up and fully running, Pause it and navigate to address 0x816035B0
-What do you see?

Vega, I can do this with 5.0-11380 to get checksums, not sure when and if they didn't have that feature available in previous revisions.

-Start up dolphin
-Right click on the game in the game list
-Click on properties
-Click on verify tab
-Make sure all the calculate boxes are checked
-Click on Verify Integrity
-Let it do its thing

Which config folder? I don't see anything at all.

(05-08-2023, 01:22 AM)Vega Wrote: So I went ahead and launched the game on a different dolphin on a different computer. The nand on the dolphin was different too so new save state.

All my addresses remain the same.

Btw the r17 & r27 thing was indeed a typo.

Anyway this only boils down to two things. Either its a relocatable module issue or a user issue.

Do you mean that you made a mistake writing r27 instead of r17?

P.S: By the way, a huge apology for the time I was absent (it was almost a month and a half), but I'm sorry, I also have responsibilities in my daily life.
Reply


Forum Jump:


Users browsing this thread: 4 Guest(s)