• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
April 25, 2024, 09:06:52 am

News:

Use of ePSXe before 2.0 is highly discouraged. Mednafen, RetroArch, and Duckstation are recommended for playing/testing, pSX is recommended for debugging.


ASM notes

Started by nates1984, January 24, 2009, 05:19:14 am

nates1984

January 24, 2009, 05:19:14 am Last Edit: January 26, 2009, 07:32:08 am by nates1984
I'll probably add this to the wiki eventually, but for now I'll keep it on the forum for anyone who wants to take a look at it. I gotta give back to the forum in some way, and I figure something like this will help anyone trying to ASM edit.

The fact of the matter there is limited space in BATTLE.BIN and WORLD.BIN to write ASM code. Eventually we will run out of the space. However, if you aren't using every single ASM hack that has been posted on the site, you will actually have space in your own patch's files that hasn't been used. Anyone serious about making a patch should have some basic understanding of ASM so they can change jumps and what-not to add in stuff they wouldn't otherwise be able to. Changing jumps is fairly easy, and people like Razele and Zodiac do most of the footwork if that's all you have to do to add in stuff.

Mostly though, Razele's topic is swamped with requests, and some us don't feel comfortable walking into a topic and requesting shit. DIY isn't just for punk rock bitches.

Notes: (for anyone interested)

Clarification: raw value means the actual value you see, otherwise the "value" is referencing a memory address.

The PSX is little endian. This means values are "reversed" in a way. If an opcode (instruction) writes a value to the memory the bytes get reversed. Example: If it's writing 8019 to the memory, the two bytes are reversed, this means 80 19 is actually stored at the memory address as 19 80. They are read backwards just like they are stored backwards.

Some examples may seem confusing, like addiu (why would I use an example that has r29 as two values?), this is because I'm strictly going to use examples I have seen in the debugger, or "in the wild," unless I'm 100% sure I'm right.

This is meant to compliment Zodiac's ASM lessons which you'll find in another thread. You should read it, although a thorough understanding isn't really required. I barely understood it when I started anyways.

0x8FFFAAAA is the same thing as 0x0FFFAAAA, you'd know that if you read the lessons thread, and you'd know why you use the 8





addiu r29,r29,0xffe8

add r29 to 0xffe8 and store the result in back into r29, the first instance of r29 is the destination

r29 was 801ffec8
r29 became 801ffeb0

A difference of 18.

801ffec8 plus ffe8 is 8020feb0, but notice how the first four digits do not change, only the last four.

you can use addiu to store new values, like if r3 is nothing but zeros, you could do addiu r3,r3,0x0064 to store 64 to r3, this is probably more reliable then ori, addiu r?,r0,0x0000 can probably be used to zero out r?

addu r16,r4,r0

add r4 and r0 together and store the result to r16... r0 is ALWAYS a series of zeros, this particular example is used to move a value from r4 to r16 without changing it

blez r5,0x0005e664

if r5 is something, you do something, then something happens, and you get yummy pie, r5 was higher then the value at that address, which was 08, and r5 was less then 5e664, it skipped the instruction right after it

bne r2,r0,0x0005e650

if r2 and r0 are not equal, go to 0x8005e650

lbu r2,0x0026(r3)

take the value at r3, add 0x0026, and store the byte from the resulting memory address to r2, if r3 was 0x80192bcc, you add 26 to that, which is 80192bf2, the byte at 0x80192bf2 is then stored at r2

lui r1,0x8019

loads raw value 0x8019 into first four "slots" of r1

lw r2,0x2d98(r3)

add 0x2d98 to r3, go to that memory address, and write the 4 bytes (8 digits) to r2

ori r2,r0,0x0001

Zodiac said:
ori is more appropriate to set a value in a register.

ori r2, r0, 0x0000
r2 = 0x00000000

ori r3, r0, 0x0063
r3 = 0x00000063

I think you should go back at lessons to understand how or and ori works. 0x00000000 OR 0x0063 = 0x00000063.


basically ori is used to load constants/immediates into the registries, while lbu and lui are used to store memory addresses into the registries

sb r2,0x38e5(r1)

stores last two digits of r2 to r1+0x38e5, if r1 is 80190000, then it will store the two digits at 0x801938e5, it adds the two values together, although ive never seen it add to a value that didnt end with four zeros, it probably does at some point in time

ive seen sb r0,0x0000(r4), in that example it used the r0 register (which is always a series of zeros) to zero out the byte at he memory address r4 references

sh r2,-0x2f7e(r1)

this operates just like sb, except the length of data being stored is differed (sb is byte, sh is half-word), this is worthy of being noted because of the negative sign you see before 0x2f7e, this means exactly what you think it means, rather then take r1 and add 0x2f7e, it instead subtracts it, if r1 was 80150000, then it will store at 0x8014d084

slt r2,r3,r5

if r3 is less that r5, write r3 to r2

sw r31,0x0010(r29)

stores all eight digits of r31 at r29 + 0x0010

Shift Word commands (sll, sllv, sra, srav, srl, srlv, ect)

http://www.cs.uaf.edu/~cs301/notes/Chapter5/node3.html

QuoteBATTLE.BIN
Offset: 11EBA0
Change 0x38 to 0x36

Crossbow, Knife, and Ninja Blade Formulas become PA*WP

How this was accomplished:

First I looked at 0x80192D94, which is where the current units address is stored (http://www.ffhacktics.com/wiki/Current_ ... ts_address) then I added the SP value to the current units address (http://www.ffhacktics.com/wiki/Formula_Hacking), now I know what specific byte that units speed is stored at.

You have to look at the current units address after you've selected something to attack/cast a spell on/ect. There can be old or incorrect data at that address. Basically, if the game is telling you the amount of damage, or percentage to hit, then it has the correct unit address there. It's best to err on the side of caution in this instance.

Generally, just breaking on the units address is a bad idea. It's interesting enough, you get a chance to see the game loading all sorts of values, from X/Y coordinates to equipment, but it'd take an eternity to zero in on the relevant stat.

The problem I had with this particular edit is that it seemed to alter the SP stat right after throwing it into the registry rather then assigning a temporary address it could pull from later. This meant I could easily see the SP value in the registries after it was called, but no temporary address to follow after that. It is entirely possible I overlooked it though.

Instead, I took the address I got from the units address plus 0x0038 and just followed that. In this case It came up a number of times. It showed up six times at 0x80183968 for all three weapon types, once at 0x80185ba4 for the crossbow and ninja blade, and twice at 0x80133814 for the crossbow and ninja blade.

Rather then edit all three of those addresses I did one at a time to see which one effected all three weapon types. Even though the game never broke at 0x80185ba4 for knife, it ended up being the one that effected the damage on all three.

I wanted to stay as far away as I could from the address that showed up six times. You always have to keep in mind that parts of a formula may be reused elsewhere in the game. Logically it would make sense the address that only showed once would be the one the game uses for those formulas. Indeed, the edit I posted above could very well screw something else up and I just didn't pick up on it. It's probably a good idea to alter as little as possible.

Another thing to keep in mind, take a look at the area around 0x80133814. You see lots of different stats being loaded and stored right? To me that says that this is an area that is used by lots of things. As if the game goes through this area for a lot of skills/spells/weapons/ect, and loads up a whole bunch of (mostly irrelevant to these formulas) values. That was a red flag, if I screw with things here there's a much higher chance I'll inadvertently effect other things.

QuoteBATTLE.BIN
Offset: 1201F8
64000234
00000000

This removes the target's faith from damage calculations, and likely accuracy calculations as well.

How this was accomplished:

Just like the first edit, I found target unit's address using the same method. This time, I added 0x0026 to it for the exact location of the target's faith and set a break point on that stat, and the game broke 0x801838d2. However, once again, there are a lot of values being called and stored in this area, so it was best not to alter this area. This time I did find a temporary address, which was 0x801938d2, and thus it became my second break point.

The temporary address was called at 0x801871f8, and the game broke there. I wanted to know where the game jumps into this area though, because I see multiple mult commands, and I see these mult commands dumping out huge numbers. It jumps in at 0x801871f0, and the first two commands I want to stay clear of. It isn't loading any value from either units address. The address at 0x801871f8 is calling the target's faith, and this is where having a target and unit with different faiths helps, otherwise both values will be the same and it becomes harder to see which is which with certainty.

Rather then try to alter this large string of commands and mults to get it to dump out proper numbers while only considering the caster's faith (which is impossible unless you got a shitload of time to kill), I simply replaced the two commands used to call the target's faith with one "nop" (just zeros) and one ORI command (ori r2,r0,0x0064). 64 is 100 in hex, so basically I just forced a value of 100 instead of letting the game load the target's faith. The formula has a TargetFaith/100 part to it, and this makes it 100/100 (or 1) regardless of the target's faith.

After this the game did break one more time, but I ignored this because when I let the game go one step at a time it seemed to lead me nowhere. More importantly, the step I just did altered the damage the way I expected it to. In all likely hood this edit will effect both damage and accuracy calculations, but at this point I can't say for sure.

Why does the game line up mult commands the way it does around the area I edited? Well, rather then actually using division to calculate this stuff, it simply does a TaFa*CaFa*MA*Y / 10000 formula (to simplify it greatly). Those huge numbers are needed so that after the last mult command it can pull the value from hi rather then lo. This way no division command in necessary, thus it can avoid the nasty effect of division's quotient and remainder being split between hi and lo. It probably does it in less commands this way as well.

Xifanie

January 24, 2009, 07:16:59 am #1 Last Edit: December 31, 1969, 07:00:00 pm by Xifanie
ori is more appropriate to set a value in a register.

ori r2, r0, 0x0000
r2 = 0x00000000

ori r3, r0, 0x0063
r3 = 0x00000063

I think you should go back at lessons to understand how or and ori works. 0x00000000 OR 0x0063 = 0x00000063.
  • Modding version: PSX
Love what you're seeing? https://supportus.ffhacktics.com/ 💜 it's really appreciated

Anything is possible as long as it is within the hardware's limits. (ie. disc space, RAM, Video RAM, processor, etc.)
<R999> My target market is not FFT mod players
<Raijinili> remember that? it was awful

nates1984

January 24, 2009, 08:22:34 am #2 Last Edit: December 31, 1969, 07:00:00 pm by nates1984
Yeah, that was my initial thought on ORI, but when I used it to set Target's Faith to 0x0064 it kept popping out the wrong damage, but now that I'm getting the wrong damage output on a vanilla ISO it makes sense that I used ORI right.

I just assumed I wasn't understanding ORI correctly, considering I'm new to it.

VincentCraven

January 24, 2009, 08:25:21 am #3 Last Edit: December 31, 1969, 07:00:00 pm by VincentCraven
I think examples of hacks done would help me more.

Though I think all the easy stuff that I would need to do is done.
I changed jobs and that has made all the difference.

Choto

another invaluable ASM learning thread, this should be put with the other helpful ones.