• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
November 10, 2024, 02:20:21 pm

News:

Don't be hasty to start your own mod; all our FFT modding projects are greatly understaffed! Find out how you can help in the Recruitment section or our Discord!


Help coding new stealing/breaking routine

Started by Heisho, August 12, 2018, 07:35:10 pm

Heisho

Hello there!

I've been trying to develop a routine that allow you to either break or steal all equipment of the target, however I've hit a wall and do not know how to complete it.
At first it was a rutine that will jump if an item wasn't present and the formula that calls the routine had multihit but the game crashed after stealing the helmet (the first item to remove in the routine). Now with this new one I attempt to break/steal on one single hit by creating a loop, although I don't know if trying to send a routine to go back to the beginning using a jump is valid.

Can someone shed some light on this?

This is the code so far:

lui r3,0x8019   
lw r3,0x2d90(r3)   Current Action Data Pointer
ori r2,r0,0x00fe   
sb r2,0x0019(r3)   Store as 0x00FE
lui r4,0x8019   
lw r4,0x2d98(r4)   Load Defender's Stats
nop   
lbu r2,0x0006(r4)   Load Defender's Gender
nop   
andi r2,r2,0x0020   
bne r2,r0,0x000002bc   Branch to end if Gender is a Monster
nop   
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
nop   
lbu r3,0x001a(r2)   Load Defender's Headgear
ori r2,r0,0x00ff   
beq r3,r2,0x0000007c   Branch if Headgear ID is FF  (Doesn't exist?)
nop   
ori r2,r0,0x0080   R2 = 80
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
nop   
sb r2,0x0019(r3)   Store as remove helmet
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x001a(r2)   Load Defender's Headgear
j 0x0000025c           Jump to store item
nop   
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
nop   
lbu r3,0x001b(r2)   Load Defender's Armor
ori r2,r0,0x00ff   
beq r3,r2,0x000000c8   Branch if Armor doesn't exist
nop   
ori r2,r0,0x0040   R2=40
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
nop   
sb r2,0x0019(r3)   Store as remove helmet?
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x001b(r2)   Load Defender's Armor
j 0x0000025c           Jump to store item
nop   
lbu r3,0x001e(r4)   Load Defender's Right Hand Shield
ori r2,r0,0x00ff   
beq r3,r2,0x00000110   Branch if Right Hand Shield  doesn't exist?
nop   
ori r2,r0,0x0008   R2 = 8
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
nop   
sb r2,0x0019(r3)   Store as Remove Right Hand Shield
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x001e(r2)   Load Defender's Shield
j 0x0000025c           Jump to store item
nop
lbu r2,0x0020(r4)   Load Left Hand Shield
nop   
beq r2,r3,0x00000148   Branch if Left Hand Shield doesn't  exist
nop   
ori r2,r0,0x0002   R2=2
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
nop   
sb r2,0x0019(r3)   Store as remove Left Hand Shield
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x0020(r2)   Load Left Hand Shield
j 0x0000025c           Jump to store item
nop   
lbu r3,0x001c(r4)   Load Defender's Accessory
ori r2,r0,0x00ff   
beq r3,r2,0x00000188   Branch if Accessory doesn't exist?
nop   
ori r2,r0,0x0020   R2=20
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
nop   
sb r2,0x0019(r3)   Store as remove accessory
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x001c(r2)   Load Defender's Accessory
j 0x0000025c       Jump to store item
nop   
lui r6,0x8019   
lw r6,0x2d98(r6)   Load Defender's Stats
nop   
lbu r3,0x001d(r6)   Load Right Hand Weapon
ori r7,r0,0x00ff   
beq r3,r7,0x000001c8   Branch if Right Hand Weapon  doesn't exist
nop   
addiu r4,r0,0xffff   R4 = FFFF
sll r2,r3,0x01           Right Hand Weapon * 2
addu r2,r2,r3           Right Hand Weapon * 3
sll r2,r2,0x02      Right Hand Weapon * 12
lui r1,0x8006   
addu r1,r1,r2   
lbu r4,0x2eba(r1)   
lbu r3,0x001f(r6)   Load Left Hand Weapon
nop   
beq r3,r7,0x000001e8   Branch if Left Hand Weapon doesn't  exist
nop   
sll r2,r3,0x01           Left Hand Weapon * 2
addu r2,r2,r3           Left Hand Weapon * 3
sll r2,r2,0x02           Left Hand Weapon * 12
lui r1,0x8006   
addu r1,r1,r2   
lbu r5,0x2eba(r1)   
addiu r2,r0,0xffff   R2 = 0xFFFF
bne r4,r2,0x000001fc   
nop   
beq r5,r4,0x0000024a   
nop   
slt r2,r4,r5   
bne r2,r0,0x00000234   
ori r2,r0,0x0004   R2=4
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
ori r2,r0,0x0010   R2=10
sb r2,0x0019(r3)   Store as remove right hand weapon
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x001d(r2)   Load Right Hand Weapon
j 0x0000025c           Jump to store item
nop   
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
nop   
sb r2,0x0019(r3)   Store as remove left hand weapon
lui r2,0x8019   
lw r2,0x2d98(r2)   Load Defender's Stats
lui r4,0x8019   
lw r4,0x2d90(r4)   Load Current Action Data Pointer
lbu r3,0x001f(r2)   Load Left Hand Weapon
nop   
ori r2,r0,0x0073   
lui r3,0x8019   
lhu r3,0x38d6(r3)   Load ability used
nop   
beq r3,r2,0x0000028c   Branch if not Great Heist (Thief)
nop   
lui r3,0x8019   
lw r3,0x2d90(r3)   Target current action data pointer
ori r2,r0,0x0010   Special flag -Steal-
sh r2,0x0010(r3)   Store as steal item
j 0x00000000   
nop   
lui r3,0x8019   
lw r3,0x2d90(r3)   
ori r2,r0,0x0004   Special flag -Break-
sh r2,0x0010(r3)   Store as break item
j 0x00000000           return to beginning
nop   
lui r3,0x8019   
lw r3,0x2d90(r3)   Load Current Action Data Pointer
addiu r2,r0,0xffff   R2 = 0xFFFF
sb r0,0x0019(r3)   Store equipment as 0 ?
ori r2,r0,0x0007   
sb r2,0x0002(r3)   
jr r31   
nop   


Thanks in advance to anyone that can help.

Regards.
  • Modding version: PSX
Grrr, arwg, hiss, and some other zombie noises...
  • Discord username: Heisho

Xifanie

I'm not sure I can help (I'm ASM dyslexic, making me really bad at helping people with it), but your code looks really messy.

You can just use r1 for lui... just once:
lui r1,0x8019   
lw r2,0x2d98(r1)   Load Defender's Stats
lw r4,0x2d90(r1)   Load Current Action Data Pointer
lbu r3,0x001a(r2)   Load Defender's Headgear
j 0x0000025c           Jump to store item
nop   
lw r2,0x2d98(r1)   Load Defender's Stats
nop   
lbu r3,0x001b(r2)   Load Defender's Armor


But you should also just free up some registers by temporarily moving them in the stack instead of reloading again.

Is the multi-hit necessary though? That sounds like it could cause problems
  • 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

Heisho

Thanks for help, I'll take your advice and see if freeing registers might do the trick.

The reason for multihit goes way back. I tested a random steal formula from one of the hackers here but added a multihit routine (5 hits) and a 100% chance to steal in order to get all equipment. To my surprise the random element allowed to steal 3 or 4 of the hits but the fifth was very rare. Curiously enough it always was the same type of equipment that survived the steal barrage. Then I tried to make something by editing the original steal/break routine with a 5 hit formula. It worked on the first item (Helmet) but on the second attempt the game crashed. Later I made a test againt a target without a helmet and it also crashed, so i believe that something must be done on the routine. The version I'm posting is the vanilla routine with some edits from my part (that haven't worked so far). The multihit would be necessary only it a one hit steal/break all is not possible to make.

However I believe it can be done but maybe I need to understand more about ASM, for starters (and please forgive my ignorance) how can you move registers to the stack? and also (forgive me again) what exactly is the stack? Maybe I already know the answers but don't know the lexicon.

Anyway I'll give a try once I got a chance and will let you guys if I found something.

Thanks once again.
  • Modding version: PSX
Grrr, arwg, hiss, and some other zombie noises...
  • Discord username: Heisho

Glain

The main conceptual issue I see with this is that the game might not support it as-is because the action data can only have one item ID for stolen/broken item.  That being said, I took a look at this... a few things stand out.  You need to either use labels or have some idea of what address in RAM this code is going to be stored at.  This line is pretty much guaranteed to crash the game:


j 0x00000000


Jumps to literally the beginning of RAM.  Jumping to 0x25c or what have you will also crash the game.  You need to be jumping to the address in RAM where your code is.  Labels can help a ton with this, as you'll see in my code example below.  There's also a ton of inefficiency, as Xifanie touched on, but since your register values aren't even being overwritten, you don't even need to save anything to the stack.  You're reloading values just to reload them...

I simplified the logic down to this, which I believe should largely do what was intended (though is completely untested).  It fills out the action's 0x19 flags with the items to break/steal by using a loop.  Since you were basically doing the same thing for each item type, I just made that logic part of the loop.  This routine doesn't do the normal checks like evasion, Maintenance, etc., but those could possibly be checked in another routine if this is to be an inner routine... otherwise those checks would need to be added here.


    lui     at, 0x8019   
    lw      t1, 0x2d98(at)          #   Load Defender's Stats
    lw      t0, 0x2d90(at)          #   Current Action Data Pointer
    lbu     t2, 6(t1)               #   Load Defender's 0x06 flags
    nop   
    andi    t2, t2, 0x20   
    bne     t2, zero, end           #   Branch to end if Defender is a Monster
    nop   

    li      t4, 0x1a
    li      t5, 0x80
    li      t6, 0

loop_top:   
    addu    t2, t1, t4
    lbu     t3, 0(t2)
    li      t2, 0xff
    beq     t3, t2, loop_bottom
    nop
    or      t6, t6, t5
   
loop_bottom:
    addiu   t4, t4, 1
    sltiu   t2, t4, 0x21
    bne     t2, zero, loop_top
    srl     t5, t5, 1
   
    sb      t6, 0x19(t0)
    lhu     t3, 0x38d6(at)          #   Load ability used
    li      t2, 0x73
    bne     t3, t2, break_item      #   Branch if not Great Heist (Thief)
    li      t2, 0x10                #   Special flag -Steal-
    sh      t2, 0x10(t0)            #   Store as steal item

break_item:
    li      t2, 4                   #   Special flag -Break-     
    sh      t2, 0x10(t0)            #   Store as break item   

end:
    jr      ra   
    nop


  • Modding version: Other/Unknown

Heisho

Hello everyone! Sorry for taking so long but I just finished testing this.

First of all,  Glain thanks for the code man, I appreciate the help. The thing missing from my original idea was a jump after stealing which I added in order to steal.

Regarding the results of the test I have good news and bad news.

Good news: It work as expect, it stole and broke every single piece of equipment, I even equip it after stealing and the items worked as they should. Tested the stolen items in the formation screen after the battle and they worked fine.

Bad news: After the ability finished it gave a message text: "" Destroyed / Got "". So it seems that i would not load every item name which might be a little problem aesthetically. Also due to my limited knowledge I don't if this can generate bugs later. I even added the text from another skill (Invite) to see if the message could be hidden and it plays the sound and it shows proper text (XXX joined) but after that the Got "" showed.

So pretty much it kinda work, I don't know if not displaying the name of stolen/broken items might create bugs later. Maybe I can make a multi hit version that steal one item at a time so it can display every item name. I tested this before with the random steal formula that I got from another member and it gave good results, however the random factor didn't allow to steal all items on one single try (which is the purpose)

One more thing. For some reason the last jump wasn't working and I replaced it with a jump and return. Could that be a problem?

It looks like this:

[0x0000005c] ori r10,r0,0x0073
[0x00000060] bne r11,r10,0x00000074
[0x00000064] ori r10,r0,0x0010
[0x00000068] sh r10,0x0010(r8)
[0x0000006c] jr r31
[0x00000070] nop
[0x00000074] ori r10,r0,0x0004
[0x00000078] sh r10,0x0010(r8)
[0x0000007c] jr r31
[0x00000080] nop

So anyways thanks for helping, I'll see if editing this formula for a multihit can be better. In the meantime feel free to leave comments or feedback on this strange quest.

Regards.

  • Modding version: PSX
Grrr, arwg, hiss, and some other zombie noises...
  • Discord username: Heisho

Pride

What does the rest of the routine look like?
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Glain

Oh right, there should have been a jump there.  That way will work but it's good form (although not required) to have one jr r31 per routine.  The way it should be is:

li      t2, 0x10                #   Special flag -Steal-
j      end
sh    t2, 0x10(t0)           #   Store as steal item
  • Modding version: Other/Unknown

Heisho

@Glain: Yeah I though the same, some routine I have and formulas have only one jr r31, I just though of this a drastic measure to allow testing.
I'll add later what you recommended, I just got out of bed, rough night.

@Pride:
The routine goes like this

[0x00000000] lui r1,0x8019
[0x00000004] lw r9,0x2d98(r1)
[0x00000008] lw r8,0x2d90(r1)
[0x0000000c] lbu r10,0x0006(r9)
[0x00000010] nop
[0x00000014] andi r10,r10,0x0020
[0x00000018] bne r10,r0,0x0000007c
[0x0000001c] nop
[0x00000020] ori r12,r0,0x001a
[0x00000024] ori r13,r0,0x0080
[0x00000028] ori r14,r0,0x0000
[0x0000002c] addu r10,r9,r12
[0x00000030] lbu r11,0x0000(r10)
[0x00000034] ori r10,r0,0x00ff
[0x00000038] beq r11,r10,0x00000044
[0x0000003c] nop
[0x00000040] or r14,r14,r13
[0x00000044] addiu r12,r12,0x0001
[0x00000048] sltiu r10,r12,0x0021
[0x0000004c] bne r10,r0,0x0000002c
[0x00000050] srl r13,r13,0x01
[0x00000054] sb r14,0x0019(r8)
[0x00000058] lhu r11,0x38d6(r1)
[0x0000005c] ori r10,r0,0x0073
[0x00000060] bne r11,r10,0x00000074
[0x00000064] ori r10,r0,0x0010
[0x00000068] sh r10,0x0010(r8)
[0x0000006c] jr r31
[0x00000070] nop
[0x00000074] ori r10,r0,0x0004
[0x00000078] sh r10,0x0010(r8)
[0x0000007c] jr r31
[0x00000080] nop

This is a subroutine, so it lacks Maintenance checks, and all that.
  • Modding version: PSX
Grrr, arwg, hiss, and some other zombie noises...
  • Discord username: Heisho

zinkBR1986


Could you please publish this completed formula?
  • Modding version: PSX