Jump to content

Ideka's ASM hacks


Ideka
 Share

Recommended Posts

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!

  • Like 11
Link to comment
Share on other sites

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). :)

  • Like 3
Link to comment
Share on other sites

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

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

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

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

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

  • 2 weeks later...
  • 4 weeks later...

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

  • 6 months later...

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

  • Like 1
Link to comment
Share on other sites

  • 1 year later...

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

 Share

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.