Ideka Posted April 9, 2015 Share Posted April 9, 2015 So, I've devoted a few weeks to it, and I think that I'm finally starting to get a grasp around the basics of ASM hacking. Here's where I'll post any future major hacks I'll eventually make. OoT Magic Armor: Source: .org 80087234 j 80600000 ; jump to routine nop .org 80600000 lui k0, 8016 ; load upper adress into k0 lb k1, e6d0(k0) ; load current equipped tunic value into k1 li t2, 0013 ; load 0013 (normal boots and zora tunic equipeed value) into t2 beql k1, t2, magic ; if k1 is equal to t2, branch to "magic" label lb k1, e693(k0) ; delay slot, loads current magic value into k1 if above statement is true li t2, 0023 ; load 0033 (heavy boots and zora tunic equipped value) into t2 beql k1, t2, magic ; if k1 is equal to t2, branch to "magic" label lb k1, e693(k0) ; delay slot, loads current magic value into k1 if above statement is true li t2, 0033 ; load 0033 (heavy boots and zora tunic equipped value) into t2 beql k1, t2, magic ; if k1 is equal to t2, branch to "magic" label lb k1, e693(k0) ; delay slot, loads current magic value into k1 if above statement is true j return ; if any of the above statements are false, jump to "return" label sh t9, 0030(t0) magic: bgezl s0, return ; if new health value is greater than zero, branch to "return" label sh t9, 0030(t0) ; blezl k1, return ; if magic amount is less than or equal to zero, branch to "return" label sh t9, 0030(t0) li t2, 0004 ; load 0004 into t2 beql t2, k1, return ; if k1 is equal to t2, branch to "return" label sb r0, e693(k0) ; delay slot, nulls the magic amount if above statement is true li t2, 0003 ; load 0003 into t2 beql t2, k1, return ; if k1 is equal to t2, branch to "return" label sb r0, e693(k0) ; delay slot, nulls the magic amount if above statement is true li t2, 0002 ; load 0002 into t2 beql t2, k1, return ; if k1 is equal to t2, branch to "return" label sb r0, e693(k0) ; delay slot, nulls the magic amount if above statement is true li t2, 0001 ; load 0001 into t2 beql t2, k1, return ; if k1 is equal to t2, branch to "return" label sb r0, e693(k0) ; delay slot, nulls the magic amount if above statement is true addiu k1, k1, fffa ; decreasing the current magic amount stored in k1 j return ; jumps to "return" label sb k1, e693(k0) ; stores new magic value into k0 return: j 80087238 ; jumps back to original routine lh a1, 0030(t0) Yes, it could probably be made a lot shorter, but there's nothing I can do with my current capabilites. Thanks for reading, and keep a look out for any future updates! 11 Link to comment Share on other sites More sharing options...
Jason777 Posted April 9, 2015 Share Posted April 9, 2015 Nice one, for a second I thought it was a remake of TP's magic armor but then I realized that your hack takes its name seriously. Do you have the hack patched to the ROM? EDIT: You should look into using bitwise operations. Usage of ANDI would have greatly reduced your code for checking if the Zora Tunic was equipped by simply checking if ((*(u8*)(0x8015E6D0)) & 0x03) was equal to 3. Also, I see that you handle the case where subtracting from the current magic amount avoids overflowing the byte value by just setting the magic value to 0 if it was less than or equal to 4; one instruction which would help you greatly would be the SLTI (Set on Less Than Immediate) opcode. I know that you realize you code could be shorter, I'm just offering what I think to be helpful tips (I don't mean to come off as a nitpicker). 3 Link to comment Share on other sites More sharing options...
Ideka Posted April 9, 2015 Author Share Posted April 9, 2015 Wow, thanks a lot Jason, I'm impressed by how easily you analyzed my hack! Those are definitely really useful advice, I think my opcode list is quite outdated (circa 98) so I'll look into that to avoid future mistakes. And yes, I have it patched to ROM. I would release a patch, but there's a possibility that this is going to be used in a major hack, so I'll wait until that's decided. Link to comment Share on other sites More sharing options...
LastWWolf Posted April 10, 2015 Share Posted April 10, 2015 This is freaking awesome, we need more stuff like this! Link to comment Share on other sites More sharing options...
Hayate Posted April 10, 2015 Share Posted April 10, 2015 Wow, that's an awesome hack. It could be in the game without any problem. Link to comment Share on other sites More sharing options...
haddockd Posted April 10, 2015 Share Posted April 10, 2015 Nice one, for a second I thought it was a remake of TP's magic armor but then I realized that your hack takes its name seriously. Do you have the hack patched to the ROM? EDIT: You should look into using bitwise operations. Usage of ANDI would have greatly reduced your code for checking if the Zora Tunic was equipped by simply checking if ((*(u8*)(0x8015E6D0)) & 0x03) was nonzero. Also, I see that you handle the case where subtracting from the current magic amount avoids overflowing the byte value by just setting the magic value to 0 if it was less than or equal to 4; one instruction which would help you greatly would be the SLTI (Set on Less Than Immediate) opcode. I know that you realize you code could be shorter, I'm just offering what I think to be helpful tips (I don't mean to come off as a nitpicker). God Jason, must you be such a nitpicker?!?!? Kidding haha. I also liked that he used the actual magic instead of rupees. I thought it was a twist that folks would also enjoy. Link to comment Share on other sites More sharing options...
CM30 Posted April 11, 2015 Share Posted April 11, 2015 God Jason, must you be such a nitpicker?!?!? Kidding haha. I also liked that he used the actual magic instead of rupees. I thought it was a twist that folks would also enjoy. To be honest, magic armour using actual magic already exists, it's in The Wind Waker. That said, I like this version better, because it only uses magic upon Link actually being attacked. That's a cool twist, especially if it was edited so Link would take damage or immediately drop down dead if hit when his magic was at zero. Link to comment Share on other sites More sharing options...
Ideka Posted April 11, 2015 Author Share Posted April 11, 2015 Hmm... Using ANDI doesn't seem to work very well, it always makes the effect present with multiple other tunics. Perhaps I'm using it the wrong way? Here's the most recent source (haven't looked into the SLTI opcode yet): .org 80087234 j 80600000 nop .org 80600000 lui k0, 8016 lb k1, e6d0(k0) andi k1, k1, 0003 bnel k1, r0, magic lb k1, e693(k0) j return sh t9, 0030(t0) magic: bgezl s0, return sh t9, 0030(t0) blezl k1, return sh t9, 0030(t0) li t2, 0004 beql t2, k1, return sb r0, e693(k0) li t2, 0003 beql t2, k1, return sb r0, e693(k0) li t2, 0002 beql t2, k1, return sb r0, e693(k0) li t2, 0001 beql t2, k1, return sb r0, e693(k0) addiu k1, k1, fffa j return sb k1, e693(k0) return: j 80087238 lh a1, 0030(t0) Thanks for any help! Link to comment Share on other sites More sharing options...
Jason777 Posted April 12, 2015 Share Posted April 12, 2015 Ahh, no I made a mistake when advising how to check for it. What you should be doing is checking if ((*(u8*)(0x8015E6D0)) & 0x03) is equal to 0x03. So you would change this... andi k1, k1, 0003 bnel k1, r0, magic lb k1, e693(k0) To this... andi k1, k1, 0003 ori t2, r0, 0003 bnel k1, t2, magic lb k1, e693(k0) Link to comment Share on other sites More sharing options...
Ideka Posted April 12, 2015 Author Share Posted April 12, 2015 1 Link to comment Share on other sites More sharing options...
mzxrules Posted April 14, 2015 Share Posted April 14, 2015 @@PwnzLPsI wrote some notes on boolean operators here for him, which every hacker should know: http://pastebin.com/aMGkS8en One thing I forgot to mention is the shift operators (bitwise and logical). Link to comment Share on other sites More sharing options...
PwnzLPs Posted April 28, 2015 Share Posted April 28, 2015 Yay! Boolean operators! Lucky for me, I know what a Boolean is because I know *any* kind of programming language. Link to comment Share on other sites More sharing options...
Ideka Posted May 24, 2015 Author Share Posted May 24, 2015 Okay. The last month(s?) I've been taking a break from the whole hacking thing, simply because I didn't have any time to spare for it. But now that Summer's coming up, I can gradually start picking up this hobby again! Here's a code I wrote quickly for a simple "marathon" mini-game where you gain 200 rupees if you win, or lose them if you don't: .org HOOK J game nop .org 80600000 game: Lui t0, UPPER ADRESS OF OPPONENT Z POSTION Lh k0, LOWER ADRESS OF OPPONENT Z POSITION(t0) ; loads the opponent z coordinate into k0 Li k1, c58f ; Z coordinate for winning point Beq k1, k0 lose ; if the opponent's z postition is equal to the winning point, branch to lose nop Lui gp, 8022 Lh gp, 45dc(gp) ; loads link's z coordinate into gp Beq k1, gp, win ; if link's z position is equal to the winning point, branch to win Nop j game nop Win: Sw r0, LOWER ADRESS OF OPPONENT Z POSITION(t0) ; sets the opponent's z position to 0 Lui t0, 8016 Lh t1, e694(t0) ; loads rupee amount Addiu t1, t1, 00c8 ; calculates new rupee amount Sh t1, e694(t0) ; stores new rupee amount J return: Lose: Lui t0, 8016 Lh t1, e694(t0) ; loads rupee amount Addiu t1, t1, fe00 ; calculates new rupee amount Sh t1, e694(t0) ; stores new rupee amount Return: J game ; jumps back to start of hack Nop I obviously need to locate the adress of the Z coordinate of the opponent actor (which I plan to be the Running Man), but this is quite easy. My major problem is finding a good hook that runs every frame. If any of you guys have any tips or feedback on this hack, please tell me! Anything would be appreciated, really. Thanks. Link to comment Share on other sites More sharing options...
Vexiant Posted December 9, 2015 Share Posted December 9, 2015 Looking for a good hook, huh? http://doc.kodewerx.org/documents/r4300i_datasheet.pdf(Page 18) The GameShark hooks in a similar location, as noted near the bottom of this excerpt. Let me give you a rundown pertaining to what's around said address where the GameShark hooks to: "0x80000400 (physical address 0x400) is by default the boot location. All R4xxx series processors uses the first 0x200 of RAM for exception handlers. The first 0x400 of physical memory contains the Interrupt Vector Table (and first 0x180 are the Processor Exception Vectors) and configuration parameters. The "interrupt vector table" is a data structure that associates a list of interrupt handlers with a list of interrupt requests. Put simply, an interrupt and exception handler both alter program flow. Interrupts handle external event, e.g. cartridge issue (peripheral interrupt), Pre-nmi (reset type), etc. Exceptions handle instruction faults, e.g. dividing by zero, etc. One thing to note about interrupts and exceptions with the Nintendo 64 that the R4300i architecture doesn't distinguish between them as there's essentially a single handler for them and the two merely have unique masks. However, in applications outside of this situation, they have individual handlers. Along with that, the CIC chip can relocate the boot location/entry point (which I linked to information relating to this initially at the top of this category). You can locate the start of the code segment by going to 0x8 (a word long) in any Nintendo 64 ROM, copying the address and breakpointing (linebreaking) it (as explained further down the page). The word found there is a pointer to the start of the real game code (Where memory officially starts). Everything before that is pretty much bootstrapping related and is for the most part, the same between games. For games that make use of the 64DD keep a copy of the original disk's disk header at 800001A0 for reference. Exception Vectors Four exceptions are hardcoded to specific addresses: 0x80000000 is for TLB miss, 0x80000080 XTLB miss (64-bit), 0x80000100 for cache errors, and 0x80000180 for general exceptions (including caught interrupts). In addition to 0x80000180 the exception vector is here and can be used as a place to hook (to execute every frame) for Nintendo 64 GameShark codes ( made in assemby). However, a con to that is your code probably won't work on an actual GameShark as it hooks with a similar method (described below). In practice these are all just redirects to the general exception handler. Just a note about the exceptions: COP0 says why an exception occurs at a given point in time, but the vector table is the address where the CPU will jump to when said exception occurs/where the CPU goes to handle an exception. Speaking of which, the GameShark works by relocating the general exception handler to 0xA0000120 (uncached memory) and hooking GameShark utilities into the "regular" general exception handler at 0xA0000180 during which point in the execution path, a "code generator" gets executed. The code generator is basically an engine made up of instructions which act on behalf of GameShark codes, usually to make data at an address be written with a chosen value over and over again every time an interrupt occurs. Note, the GameShark writes to both cacheable and non-cachable memory (For a better understanding, read "CPU Addressing above")." Those excerpts are taken from a Nintendo 64 hacking wiki that is currently in the works. In conclusion, you can use 0x80000180, however your code probably won't work on an actual GS due to identical hooking methods (the GS overwriting your hook). I know Jason777 uses osWriteBackDCacheAll which seems to work great for him. For OoT 1.0 hooks, I shall direct you here: http://cloudmodding.com/zelda/oot 1 Link to comment Share on other sites More sharing options...
Ideka Posted January 23, 2017 Author Share Posted January 23, 2017 My latest accomplishment in ASM hacking: Coded the actor in pure MIPS assembly. I suppose it was a bit trickier than it'd have been with C, but it allowed for a very optimized overlay at only 0x310 bytes long. 1 Link to comment Share on other sites More sharing options...
SoulofDeity Posted January 23, 2017 Share Posted January 23, 2017 That's pretty badass! Link to comment Share on other sites More sharing options...
Zeth Ryder Posted January 24, 2017 Share Posted January 24, 2017 That's a pretty neat hack but omg that framerate and stuttering made it really hard to watch. Link to comment Share on other sites More sharing options...
Ideka Posted January 24, 2017 Author Share Posted January 24, 2017 Like stated in the video description (on Youtube though, so I get why you missed it) that's simply caused by my crappy computer. This was the best, least laggy footage I could manage to record, believe it or not. Link to comment Share on other sites More sharing options...
Zeth Ryder Posted January 26, 2017 Share Posted January 26, 2017 Like stated in the video description (on Youtube though, so I get why you missed it) that's simply caused by my crappy computer. This was the best, least laggy footage I could manage to record, believe it or not. Yeah I figured it was something like that but either way it's still a pretty awesome hack! Great job! Link to comment Share on other sites More sharing options...
Recommended Posts