The following warnings occurred:
Warning [2] Undefined property: MyLanguage::$archive_pages - Line: 2 - File: printthread.php(287) : eval()'d code PHP 8.2.18 (Linux)
File Line Function
/inc/class_error.php 153 errorHandler->error
/printthread.php(287) : eval()'d code 2 errorHandler->error_callback
/printthread.php 287 eval
/printthread.php 117 printthread_multipage



Mario Kart Wii Gecko Codes, Cheats, & Hacks
Coding Questions and other Quandaries - Printable Version

+- Mario Kart Wii Gecko Codes, Cheats, & Hacks (https://mariokartwii.com)
+-- Forum: Hacks/Modding (https://mariokartwii.com/forumdisplay.php?fid=14)
+--- Forum: Code Support / Help / Requests (https://mariokartwii.com/forumdisplay.php?fid=61)
+--- Thread: Coding Questions and other Quandaries (/showthread.php?tid=1926)

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14


RE: Coding Questions and other Quandaries - Vega - 12-07-2021

(12-07-2021, 12:57 PM)Hackwiz Wrote: So here is a code for Super Mario Galaxy.

This is how I'm deciphering it

Mario Size Modifier [brkirch]

F6000001 80208030 #Searches for the following (single) line of code (C03E0024 7C7D1B78) in ram address range 0x80200000 -> 80300000
C03E0024 7C7D1B78 #String searched for in ram address range 0x80200000 -> 80300000

I believe this takes care of this part:

That is all correct.

(12-07-2021, 12:57 PM)Hackwiz Wrote: Creates an if (so this code requires an endif), then searches for the NN lines of Z values between XXXX0000 and YYYY0000 (or, if XXXX is 8000, between 80003000 and YYYY0000).

Since the F6 Codetype creates an If Statement, you need an End-If. These are also known as Halfway or Final Terminators. Simply put, at the end of your F6 Code, just add this ---> E0000000 80008000


(12-07-2021, 12:57 PM)Hackwiz Wrote: As far as the rest of the operation goes, is this done automatically?

To prevent this code from causing game lag, it will only search the first time it is read by the code handler (the result is saved to the code and reused). If the Z values are found, set po to the starting address of the values (SSSSSSSS) and replace the F6 line with F60003NN SSSSSSSS.
If the Z values are not found, then set code execution status to false and replace the F6 line with F60001NN XXXXYYYY.

So I just need to write the appropriate gecko code utilizing the po afterwards and hope for the best?

That part is all done automatically by the Gecko Code Handler. If it finds your unique string, it will set a pointer that will always 'hook' to the contents of your source within the F6 Code itself. That's why the Final Terminator is needed at the end (E0000000 80008000). That will reset all the Code Handler's saved pointers so other codes in your GCT/Cheat-Manager will work correctly.

(12-07-2021, 12:57 PM)Hackwiz Wrote: Also, you said "executed immediate upon boot. So if the string isn't found right away, it simply won't hook."

Is it possible to use a button activator to force it to try re-hooking?
You could use a button activator, but that would be annoying in my opinion to have to remember to always press a button before reaching a certain part of the game. The re-hooking (automatically with codetypes alone) is possible according to a post I found on the old WiiRD forums. It's a series of various uncommonly used Gecko codetypes that could force attempts on retrying the F6 'Hook'. --> https://mariokartwii.com/showthread.php?tid=743

I am not familiar with some of the other codetypes in that thread as I never needed to learn them and the documentation of the Codetypes is not explained all that well. Star simply copy pasted the content of that thread from another web source. We've never bothered to update it to be user friendly as Assembly (C2 and C0 codetypes) can solve most code problems.

Referring back to the Retry F6 Hook, it might be better and more efficient to write that out in Assembly. Honestly, a lot of those Gecko Codetypes were created by the Gecko team because beginners back in the day simply refused to learn Assembly.

Well in the mean time, I guess I'll be making that F6 tutorial Tongue


RE: Coding Questions and other Quandaries - Hackwiz - 12-07-2021

I have seen Celia's health stored in two areas of mem2 e.g.

90AA####

and

91DE####

Would:

F6000001 90AA91DE
###### #######

be permissible?


RE: Coding Questions and other Quandaries - Vega - 12-07-2021

You would want to adjust it to 90AA91DF <-- Searches for Instructions need to be done in mem80

EDIT: Actually the F6 Codetype won't work. If the instructions' addresses are changing while the game is running, that is a problem. I'm too not sure how that can be solved.


RE: Coding Questions and other Quandaries - Hackwiz - 12-08-2021

"EDIT: Actually the F6 Codetype won't work. If the instructions' addresses are changing while the game is running, that is a problem. I'm too not sure how that can be solved."

Indeed.

I wanted to see if I could make a working F6 code. So, using my save state, so I had a known address for the search range,
I hacked this:

F6000002 91D391D4
000000C8 00000000
000000C8 00000000
14000000 000000C8
E0000000 80008000

Works like a champ, until, like you said...

I can see where this is going to be a useful tool.
Lots of games to revisit.


RE: Coding Questions and other Quandaries - Vega - 12-08-2021

This might work... (btw your example F6 would technically be incorrect, you need to do the search in mem80)

Here's the gist of my idea (man this is really hacky, hopefully somebody can chime in on this issue lol)

We will use a C0 Code to constantly search for that 'unique string', similar to how F6 Codetypes work, but we will use a crude checksumming system for verification instead of doing some odd string comparison.

The C0 code will always keep checking even when the instruction's address has been found, That way updates are always preformed if the address changes. However, this constantly running C0 code might lag your game.

The found (always updated) address will be stored to a unused space in memory (called the EVA). The found address is also sent to what is called the Instruction Address Breakpoint Register (IABR).


---

There will be a 06 Codetype string write injected at 0x80001300. At 0x80001300 is the exception routine for the IABR. Basically if your instruction address gets executed, the CPU will on purposely take this exception. The 06 Code will overwrite part of this Exception with some custom instructions. The custom instructions will basically do this...

Check Instruction of Address of EVA vs what triggered IABR
If they are a match, we can modify the Health. If not, do not modify anything
End exception.

---

What I need from you are two things:
  • The address start and end parameters (what range of addresses the search will be preformed in). Try to get this range small to reduce the chance of game lag.
  • A unique hex string that includes the default instruction. Try to keep it word aligned (string byte size divisible by 4).

---

Here's a prelim source to give you some technical detail. In before there's something huge that I am missing and this obviously would never work.

C0 source:

Code:
#IABR compiler statement
.set IABR, 1010

#Set First Loop Load Address (minus 4)
lis r3, 0x80E9

#Set amount of times to search
li r0, 0x7FFF
mtctr r0

#Set the crude checksum
lis r5, 0xXXXX
ori r5, r5, 0xXXXX

#Backup a few GVR's
stmw r29, -0xC (sp)

#Loop
loop:
lmw r29, 0x4 (r3)
xor r10, r29, r30 #Crude checksumming, idk what im doing tbh
xor r10, r10, r31
cmpw r5, r10 #Verify checksums
beq- found

#not yet found, keep trying
addi r3, r3, 4
bdnz+ loop

#found
found:
lmw r29, -0xC (sp) #Restore GVRs
lis r5, 0x8000
stw r3, 0x1500 (r5)

#Flip bits of 30 and 31 high, this is needed for IABR (BE and TE)
ori r3, r3, 0x0003
mtspr IABR, r0
blr


06 Source:

Code:
#IABR #String Write at 0x80001300
#NOTE ABOUT IABR: The Instruction that triggered the IABR is not invoked til after the exception itself has completed operation

#I've never messed with the IABR before, so please don't laugh :(

#Load Current Found Instruction Address; r0 treated as literal zero. FYI we are in physical memory
lwz r12, 0x1500 (r0)

#Load Last Executed Instruction Address
mfspr r11, srr0 #Broadway manual says address that triggered IABR is placed into srr0 when exception occurred

#Compare Them; if not equal, the Instruction's Address has changed! Don't mess with the health
cmpw r11, r12
bne- end_exception

#We are a GO! Set the Health. Default Instruction will be carried at on its own after exception has ended
li r3, 0xC8

#End IABR Exception
#Store the Health (physically)
#Update srr0 by 4 or else the IABR will insta trigger right after we end the exception, thus we end up in an infinite loop
end_exception:
clrlwi r12, r29, 1
stw r3, 0x0014 (r12)
addi r11, r11, 4
mtsrr0 r11
rfi



RE: Coding Questions and other Quandaries - Hackwiz - 12-08-2021

"(btw your example F6 would technically be incorrect, you need to do the search in mem80)"

I was just trying to write to her health address and see if I could do it correctly in a controlled environment. Hence, the mem2 search range.
I get it though, this has to be attacked from the instruction angle.

What I need from you are two things:

The address start and end parameters (what range of addresses the search will be preformed in). Try to get this range small to reduce the chance of game lag.
A unique hex string that includes the default instruction. Try to keep it word aligned (string byte size divisible by 4).

I'll do a bunch of bp's on her health at various points and come up with a range of addresses [mem80] the instruction line may be written to.
And of course, unique hex string to search for.

As far as the rest of your post, I'll try to digest it as soon as I wake up Lol.


RE: Coding Questions and other Quandaries - Hackwiz - 12-09-2021

After doing a bunch of bp's after dying, entering new areas, starting a new game and continuing a saved game,
I discovered I was mistaken,

The address the store command is at is static once the game boots.

It is however, different with every start of a new or saved game.

I got 10 different addresses doing just that.
The address range the stw r3, 0x0014 (r29) command is stored at ranged from

0x80E9A1F0 -> 0X80F01368

Sorry!!!

This is the unique string found at those addresses: 907D0014 887D0020
In searching for the string I only got one result within the above address range.

The address for the health value of course changes with all the above listed conditions.

After doing all the bp's I found the address range larger than I originally seen. So far I have seen it go from:

0x90A9E554 -> 0X921AB454

All the addresses end with 0x4

I should think this will make things a bit easier.

That's enough for 2night.

Take care!


RE: Coding Questions and other Quandaries - Vega - 12-09-2021

That makes much more sense. I can't think of a reason why a game would constantly re-locate a module/object-file/elf while the game is running.

So the sources I included are not needed, but I'll probably end up trying them with being modified for an MKW code just because. Anyway, you will need the F6 Codetype. The address of where the Health is at is not a concern. Only the addresses where the stw instruction could reside at is what we need.

F60000nn 80E080FF
zzzzzzzz zzzzzzzz
D20000xx 00000002
386000C8 907D0014
60000000 00000000
E0000000 80008000

The unique hex string is a list of compiled executable instructions (mem80) that includes your compiled default instruction (907D0014) ,or is nearby the default instruction.

Obviously I don't have the game in front of me but lets pretend that a li r0, 0x500 instruction is right after your default instruction in memory. So that's a compiled hex string of 907D0014 38000500. As long as that specific string is unique in Memory, it can be used. Since that would only take 1 line/row in a compiled gecko code, the nn value for the F6 Code is 01. The string just mentioned is the z value. The xx is the offset relative to the saved pointer, it will be 00 in this case since the Default Instruction is the very first item of the unique string.

F6000001 80E080FF #Example unique string takes up 1 row/line. Search from 0x80E00000 thru 0x80FF0000
907D0014 38000500 #Example unique string to look for
D2000000 00000002 #Insert ASM at pointer (zero offset); D2 = Codetype for Pointer ASM
386000C8 907D0014 #ASM code (li r3, 0xC8; stw r3, 0x0014 (r29)
60000000 00000000 #End of ASM code
E0000000 80008000 #End if (final terminator)

The only issue is that this F6 code will execute immediately upon boot and fail because the relocatable elf hasn't been loaded into memory yet. So for initial testing just to get this working you will need to slap on a button activator. If you don't have those for your game, I can help you find them in Memory. Idk much about your game, is there a screen where you select New vs Saved Game? If so, you would want to press your activator after that screen.

The way the code is, the Health cheat will effect everyone, but let's just get this working first before fixing the minor quirks.


RE: Coding Questions and other Quandaries - Hackwiz - 12-09-2021

Ok.

Button activator no problem... already have.

"is there a screen where you select New vs Saved Game?"

Yes.


I'll give it a try after work.

As far as the ASM code, it seems to me we should be able to do a compare on the nibble of the LSB of r29.

If it's a 4 (health address always ends with a 4):

beq some_label

some_label:
li r3, 0x00C8
stw r3, 0x0014 (r29)

Have a great day!!

Thanks!!!


RE: Coding Questions and other Quandaries - Hackwiz - 12-09-2021

The D2 code type is very cool. I can think of a bunch of games I can revisit now and know how to get what I'm after.

I've learned more in the last week than I have in the last 8 months or so. Smile

In regards to using this type (pointer) code:

F6000001 80E080FF #Example unique string takes up 1 row/line. Search from 0x80E00000 thru 0x80FF0000
907D0014 38000500 #Example unique string to look for
D2000000 00000002 #Insert ASM at pointer (zero offset); D2 = Codetype for Pointer ASM
386000C8 907D0014 #ASM code (li r3, 0xC8; stw r3, 0x0014 (r29)
60000000 00000000 #End of ASM code
E0000000 80008000 #End if (final terminator)

Are you able to run two of these at the same time? One for health and one for another player attribute.

The reason I ask, is because Celia has another attribute, a special attack.

The address for the code that writes to this attribute behaves the same as the health code address.
And of course the address where the special attack value is stored behaves the same as the health code address.