• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
April 16, 2024, 05:16:18 am

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!


How do use ANDI to check if a flag is on?

Started by Dokurider, March 27, 2014, 03:26:37 pm

Dokurider

It was either here or Final Fantasy Tactics Hacking, so idk.

So I'm on the cusp of making my very first hack. I'm trying to turn the 255 AoE check into something I can toggle in FFTP by attaching to a unused flag. I've identified all the code that governs this check, I just some help in figuring out how to intelligently use ANDI to my purposes.

For an example, in the targeting routine, ability flag 2 is ANDI'd against 0x0006 to see if the attack is a linear AoE or not.

Ideally, I wanted to use the Math Skill flag for this check, since most patches ban that skill, but the Targeting Routine doesn't load that flag, so I'm going to have to piggyback on some of the (hopefully) blank flags.

I could just attach this hack to the Top Down Targeting Flag if worst comes to worst, because it's such a rare map feature to have tiles above other tiles...

Choto

basically, you'd just have to load the other set of flags (with math skill in it) and check vs. the math skill bit. I'm not sure where in the routine you're mentioning... if you post the code i could help a bit better.

Here's the set of data you want to use
8006fbf0 - Ability Data POinter 2 (loading to skillset?)
   0x00 - Range
   0x01 - Effect Area
   0x02 - Vertical
   0x03: Flags 1
      0x80 -
      0x40 -
      0x20 - Ranged Weapon
      0x10 - Vertical Fixed
      0x08 - Vertical Tolerence
      0x04 - Weapon Strike
      0x02 - Auto
      0x01 - Can't Target Self
   0x04: Flags 2
      0x80 - Can't Hit Enemies
      0x40 - Can't Hit Allies
      0x20 -
      0x10 - Can't Follow Target
      0x08 - Random Fire
      0x04 - Linear Attack
      0x02 - 3 Directions
      0x01 - Can't Hit Caster
   0x05: Flags 3
      0x80 - Reflectable
      0x40 - Math Skill
      0x20 - Affected By Silence
      0x10 - Can't Mimic
      0x08 - Normal Attack?
      0x04 - Persevere
      0x02 - Quote
      0x01 - Animate on Miss
   0x06: Flags 4
      0x80 - Counter Flood
      0x40 - Counter Magic
      0x20 - Direct
      0x10 - Blade Grasp
      0x08 - Requires Sword
      0x04 - Requires Materia Blade
      0x02 - Evadeable
      0x01 - No Targeting
   0x07 - Element
   0x08 - Formula
   0x09 - X
   0x0a - Y
   0x0b - Inflict Status
   0x0c - CT
   0x0d - MP Cost


I'm assuming in the routine they already load the pointer to this ability data since they load the AoE to check if it's 255. So then all you have to do:

lbu r1, 0x0005(r2)         #assuming r2 is the ability data address
nop
andi r1, r1, 0x0040        #this will set r1 = 0x40 if math skill is checked, 00 otherwise
beq, r1, r0, 0x00000000  #set this address to skip the following code for your hack
nop

*Code for your hack goes here*

So all we do is load the byte, use andi this way to check the 0x40 bit(flag), and use a branch command to skip the code if that flag is not flagged. If you still are unsure, post the section of code and I can describe it a bit better.

Glain

You can also avoid hardcoding the address by doing something like this:

beq r1, r0, after_hack
nop

*hack code*

after_hack:
(first line of code after the hack)

(Either way, don't forget to change the address. :)  Branching to the beginning of memory is probably not the desired effect... although it would be kind of funny...)
  • Modding version: Other/Unknown

Dokurider

Yeah, I'll just post the current code
From the Targeting Routine (Thanks FFH wiki!)
Assume that we are working with a 255 AoE spell or 0x00ff

0017b8d0: 90690003 lbu r9,0x0003(r3) ability flags 1 # loaded for vertical flags and self/auto target
0017b8d4: 90710004 lbu r17,0x0004(r3) ability flags 2 # Hit Allies/Enemies flags, Top Down Targeting, Linear/3 Direction and Hit Caster
0017b8d8: 90640006 lbu r4,0x0006(r3) ability flags 4 # Stop at Obstacle and maybe select target
0017b8dc: 90730001 lbu r19,0x0001(r3) load aoe # r19 is the big deal here
0017b8e0: 90750002 lbu r21,0x0002(r3) load verticle # whatevs
0017b8e4: 30840020 andi r4,r4,0x0020            # direct attack, aka Stop at Obstacle flag check
0017b8e8: 10800003 beq r4,r0,0x0017b8f8       # why don't we just pretend our spell is not direct and move on, hmm?
0017b8f8: 32220006 andi r2,r17,0x0006 Check linear flag
0017b8fc: 10400006 beq r2,r0,0x0017b918 Branch if not linear # our spell is not linear either, so let's skip ahead
0017b918:: 93a3001a lbu r3,0x001a(r29)          # begin the target/caster x/y coordinate routines. This doesn't concern us now, so I'm just going to skip ahead
0017b9fc: 326300ff andi r3,r19,0x00ff              # That's the gold here. This is the beginning of the 255 AoE check, what we want to mess with today. Since r19 is 0x00ff here, it will spit out a result of...0x00ff. Saved to r3.
0017ba00: 340200ff ori r2,r0,0x00ff                 # preparing a value for the branching routine
0017ba04: 1462000c bne r3,r2,0x0017ba38       # skipping some really dumb looking loop.
0017ba38: 3c038019 lui r3,0x8019                   # Only to jump right into another one
0017ba3c: 24632dd8 addiu r3,r3,0x2dd8
0017ba40: a0600000 sb r0,0x0000(r3)
0017ba44: a0600001 sb r0,0x0001(r3)
0017ba48: 24840001 addiu r4,r4,0x0001
0017ba4c: 28820200 slti r2,r4,0x0200
0017ba50: 1440fffb bne r2,r0,0x0017ba40          # I'm befuddled at what this routine is supposed to do. Rewriting a RAM location is well and good, but what good does rewriting the exact same data to the exact same place...512 times do???? Whatever.
0017ba54: 24630005 addiu r3,r3,0x0005           # that above loop would make more sense with this line in there, but it's not apart of the loop. I think. Oh well.
0017ba58: 00061080 sll r2,r6,0x02                  # the following code isn't important, but it does check r19 (the AoE a few times, but it's not for the 255 check, so let's skip ahead again.
0017bb60: 3a6700ff xori r7,r19,0x00ff              # We are preparing to jump to the Allies/Enemies Targeting routine, so we are saving whether r19 = 255 or not. Since it is, r7 is 0x0000
0017bb64: 0c05ef1e jal 0x0017bc78                # we are now headed to the Allies/Enemies target routine

Allies/Enemies Targeting Routine

0017bc78: 27bdffc0 addiu r29,r29,0xffc0
0017bc7c: afb5002c sw r21,0x002c(r29)
0017bc80: 00a0a821 addu r21,r5,r0 r21 = Can Hit Enemies Flag
0017bc84: afb60030 sw r22,0x0030(r29)
0017bc88: 00c0b021 addu r22,r6,r0 r22 = Can Hit Allies Flag
0017bc8c: afb70034 sw r23,0x0034(r29)
0017bc90: 00e0b821 addu r23,r7,r0 r23 = 255 AoE check # r23 is our register of interest here. r23 is not called until:
0017bd68: 32e200ff andi r2,r23,0x00ff
0017bd6c: 1440000c bne r2,r0,0x 0017bda0 # Skip the Tile Counter Routine if not 255 AoE. This is why Song/Dance skills don't have tiles all over the map. Since we are equal to r0, we proceed into the routine.
0017bd84: 00000000 nop
0017bd88: 10400002 beq r2,r0,0x 0017bd94 Branch if AoE = 0
0017bd8c: 26100001 addiu r16,r16,0x0001 Tile Counter ++
0017bd90: a0640001 sb r4,0x0001(r3) Store Tile Targeted? = True
0017bd94: 2a020200 slti r2,r16,0x0200
0017bd98: 1440fff9 bne r2,r0,0x 0017bd80 Branch if Tile Counter < 0x200
0017bd9c: 24630005 addiu r3,r3,0x0005 Pointer += 5
0017bda0: 8fbf0038 lw r31,0x0038(r29)
0017bda4: 8fb70034 lw r23,0x0034(r29)           # The game is done with the check
0017bda8: 8fb60030 lw r22,0x0030(r29)
0017bdac: 8fb5002c lw r21,0x002c(r29)
0017bdb0: 8fb40028 lw r20,0x0028(r29)
0017bdb4: 8fb30024 lw r19,0x0024(r29)
0017bdb8: 8fb20020 lw r18,0x0020(r29)
0017bdbc: 8fb1001c lw r17,0x001c(r29)
0017bdc0: 8fb00018 lw r16,0x0018(r29)
0017bdc4: 27bd0040 addiu r29,r29,0x0040
0017bdc8: 03e00008 jr r31
0017bdcc: 00000000 nop


What I want to do:
0x17b9fc: 322300XX andi r3, r17, 0x00XX # if I want to check the Top Down Targeting Flag in Ability Flag 2
0x17b9fc: 312300XX andi r3, r9, 0x00XX # if I want to check against one of the blank flags in Ability Flag

0017ba00: 340200XX ori r2,r0,0x00XX # needs to equal r3

0017bb60: 3a6700XX xori r7,r19,0x00XX # needs to be result in r7 being 0x0000

The problem I see with just loading the Ability Flag 3 is that the loading flag data routine would have to be relocated to a location that has space and I have no idea where any free space would be. Even if we found some space, what register can take it?

I would just rather work out a way to check against the Top Down Flag. Seems to be a lot less trouble.

Choto

March 28, 2014, 08:48:06 pm #4 Last Edit: March 28, 2014, 08:58:06 pm by Choto
Warning: Wall of text

First off, congrats on learning ASM. The biggest hurdle is the first one, it gets much smoother from here on out lol.

Ok, so what actually happens with the 255 aoe? Does the game target differently than if it were 254? I can't remember what it looks like in game >_>

couple things to note here. Check this data, it's used heavily in these routines:
80192dd8 - Moveable/Targetable Panel Grid (By rows of X panels, 0x10 in each row)
   0x00 - AoE of panels to highlight (1 only highlights panel, 2 highlights AoE 1 panels, etc.)
   0x01 - set to 01 when panel is green (targeted with ability)
   0x02 - Unit Number (battle) of unit standing on panel?
   0x03 -
   0x04 - Obstructed (set to 0xff if panel is obstructed)/ Not reachable?

There are 0x200 panels, 0x100 for each map level. I forget how the panels progress in the grid... if it increases X or Y, but it should help give you an idea of what the big 0x200 long loops are doing. In each run through the loop they increase the counter of this grid data in some way to get to another panel. By writing algorithms you could progress through a different set of panels and set the ones you want targetable/highlighted/etc.

Unfortunately I think you have to get some more room to do what you want to do, but not much. At this point, you should learn how to find free space, jump to free space to make your code, and jump back anyway. It's not too terrible and you do this with most hacks:

1. Get a clean Iso
2. Use Raven's Kanji Space Nopper to erase all free space (I'll attach it to this post)
3. Apply your other hacks
4. Extract Battle.bin, open it in a hex editor, and all the free space should be 00000000's

Now to jump there in vanilla code. Pick a spot in the code to at which to jump. Think of it like the jump command is inserted at that spot and the original command is bumped down. The jump command should be the RAM address of free space that you pick.

After you put your code in free space, you just need to make sure your hack leaves things the way it found it, or that what you leave in the registers won't cause a problem.

To find registers that aren't in use, you can look for any load commands used after where you jumped from. If vanilla code loads to a register, it didn't need that register anymore. Also, at the end of some routines you'll see this:
0017bda0: 8fbf0038 lw r31,0x0038(r29)
0017bda4: 8fb70034 lw r23,0x0034(r29)           
0017bda8: 8fb60030 lw r22,0x0030(r29)
0017bdac: 8fb5002c lw r21,0x002c(r29)
0017bdb0: 8fb40028 lw r20,0x0028(r29)
0017bdb4: 8fb30024 lw r19,0x0024(r29)
0017bdb8: 8fb20020 lw r18,0x0020(r29)
0017bdbc: 8fb1001c lw r17,0x001c(r29)
0017bdc0: 8fb00018 lw r16,0x0018(r29)
. In case you don't know, they're loading the original registers before the routine started before returning to the next routine. So if those registers aren't used between where you jump from and where they're reloaded, they're fair game.

For your hack, I would jump here:

0017bd68: 32e200ff andi r2,r23,0x00ff
0017bd6c: 1440000c bne r2,r0,0x 0017bda0      Branch if AoE = 255

and turn it into:

0017bd68:  j 0x152000                              #just some random address in free space atm
0017bd6c: andi r2,r23,0x00ff                       #r2 = aoe

Then in free space, you just need to set the return locations according to your logic. Also if you look back here:

0017bcbc: afb1001c sw r17,0x001c(r29)

This is where the game stores that set of flags in the Check Allies/Enemies routine. We can load from that when we want to check it ourselves. At this point, I'm going to post the code I wrote here. I know this is a blitzkreig of info but I think you're ready to handle it.

[0x00152000] bne r2, r0, 0x152020                 # branch if 255 aoe
[0x00152004] lw r20, 0x001c(r29)                   # load flags
[0x00152008] nop
[0x0015200c] andi r17, r20, 0x0040                 # top down targeting flag check
[0x00152010] bne r17, r0, 0x152020                # branch if flag is set
[0x00152014] nop
[0x00152018] j 0x17bd84                               # return to routine if not one of the above
[0x0015201c] nop
[0x00152020] j 0x17bda0     # return to location of the original branch command that we moved
[0x00152024] nop


Let me know if this helps or confuses the fuck out of you >_>
Also, I re-uploaded that targeting routine with more notes

Dokurider

(They're yellow, not green, goddamnit.)

Progress Report:
I finally succeeded in spoofing the 255 AoE. My code works 100%!* I didn't even need to write over any kanji space because I figured out a way to do it without overwriting any extra space.

0x17b8d4: 90710004 lbu r17, 0x0004(r3)
to
0x1148d4: 94710004 lhu r17, 0x0004(r3)
BAM!
(Of course, I adjusted all of the offsets and following commands.)

Problem is, it doesn't work like I thought it would (like anything ever does). See, instead of ignoring unoccupied space like I thought it would, it scans the entire map and sets occupied spaces as the targets. So, no matter what your AoE is, it'll always set every possible target on the map. Also, I think there's some...interaction with the Only Hit Enemies\Only Hit Allies/Self (As opposed to the Hit Enemies and Hit Allies Flags of Ability Flags 2). So my work's not done yet. I'll need to overwrite some instructions because I think I could program that functionality.

I think.

Fortunately, I found juuuust the perfect routine to overwrite.

Did you know that Morbol Virus, oh excuse me, Moldball Virus, has it's very own, unique targeting routine? I have no earthly clue what it's supposed to really do. The wiki says it's effects what depths it can target. The problem with that it that Moldball Virus has 0 Vertical and Vertical Threshold on by default. It cannot target anything you're not on level with! It's...pretty pointless. Even if it wasn't made redundant by default, I'm 90% certain it's actual function would still be dumb. C'mon now, it's just Moldball Virus. Why should it have custom targeting routine?

So, I'm overwriting for my purposes. It's a shame no one has mapped out the flags of the Tile Data Routine, so then I can know with certainty, or at least so I can satisfy my curiosity. Anyways, I want to avoid writing over Kanji space because I want to avoid potential conflicts with other codes that are or could overwrite the same space.

So without ado, here's what I got so far:

<?xml version="1.0" encoding="utf-8" ?>
<Patches>
  <Patch name="Math Skill Flag into Target Units Only Flag">
    <Description>
Turn the Math Skill flag into a flag that targets only tiles with units on them. Basically it just spoofs the 255 AoE check.</Description>
    <Location file="BATTLE_BIN" offset="1148d4">
      04007194
    </Location>
    <Location file="BATTLE_BIN" offset="1148f4">
      39403132
    </Location>
    <Location file="BATTLE_BIN" offset="1149fc">
     00402332
    </Location>
    <Location file="BATTLE_BIN" offset="114a00">
      00400234
    </Location>
    <Location file="BATTLE_BIN" offset="114ae4">
      20002632
    </Location>
    <Location file="BATTLE_BIN" offset="114aec">
      00000000
    </Location>
    <Location file="BATTLE_BIN" offset="114b60">
      00402732
    </Location>
    <Location file="BATTLE_BIN" offset="114b68">
      00000000
    </Location>
    <Location file="BATTLE_BIN" offset="114d68">
      0040E23A
    </Location>
   </Patch>
</Patches>


Still, it's technically a successful hack, just not very useful one right now, so yay go me.

I'd like to thank Xifaine, Glain, Pokey and Choto for their attempts at helping me as well as their ASM guides that helped me so much. I'd like to take everyone that has contributed to the FFHWiki's code depository, without it, this would not have been possible, or as fast as it was, and saving me a lot of potential headaches. I'd like to give a special thanks and shout out to FDC for his attempts at teaching me as well as inspiration and whatnot (oh and his guide too). And yes, I am kicking myself for not learning this earlier, so feel free to say I told you so. I'll be back in full as soon as I get internet here in my new home in Idaho.


*Statement is considered a figure of speech and is inadmissible in court of law.

QuoteOk, so what actually happens with the 255 aoe? Does the game target differently than if it were 254? I can't remember what it looks like in game >_>

When an ability is 255 AoE, it only targets panels with units on them, not the space. Just take the vanilla game, make it 254 AoE, and watch the map light up YELLOW, NOT GREEN. I'm hoping to combine this behavior with Random Fire to make Random Fire skills that can be practical when it's larger than 1 AoE. I listed my initial ideas here. The point is, if I can succeed, this can have a lot of awesome applications.

Oh and thanks for the Kanji Buster.

Choto

Nice work! now learning is going to start to get much easier as you understand more. I want to emphasize again that you should learn how to A. look for free space, B. be able to jump there and return. It may not have been needed here but it will be on many hacks in the future.

Also, I'm a little colorblind goddammit. Mah bad

And also know that all of the red routines on the wiki that I have, just haven't been uploaded. If you need one let me know and i'll put it up. Routines in locations that aren't listed haven't been gone through by anyone. You should also check the ASM starter kit thread for the most up-to-date Data Locations.txt that I have. Actually come to think of it I think "Battle.bin routines 2.txt" has alot of the red routines in it.

Dokurider

Progress Report:
So maybe my code wasn't really complete. There was some errors. Maybe I copied the wrong RAM data to the wrong offsets, maybe I missed a few checks here and there. I've since fixed them. But what was really throwing me off was the behavior that the 255 check was displaying. When I had both the Target Ally and Enemy on, all it did was throw tiles every where and pout. But, if I where to uncheck both Target Ally and Enemy, it would like it was supposed to if the flags were on in the first place!

I...don't really know why it does that. All at. Mainly because how the Ally/Enemy Flag check doesn't make much sense to me in the first place. But what is clear is that the routine was not really designed to handle normal team flagging. Makes sense, after all, I *am* bypassing the check that prevents the game from going into that routine if both flags are active. Too bad though, because in the vanilla game, you can't access the 255 AoE routine if both your team flags are active.

That's right, I tested it. In the vanilla game, this behavior is present. Go into FFTP and modify 255 AoEs to to either be 254, both ally/enemy flagged, neither flagged, or any combination of those, and you'll see why all 255 AoEs either attack only enemies or allies. Better yet, I'll just show you now. (This isn't going to be easy without actually being able to see the damn pictures in the first place. Thanks, 10+ year old computer and Internet Explorer.) Remember, this is vanilla code.










I...can't really fix this behavior. Clearly the best way is to just roll with it. If you want to just target all units with a 255 AoE, unflag both target ally and enemy in the vanilla game.

With my hack, the same rules apply. My code...shouldn't have any more problems now. A word of caution, however. If you use my hack, do not make your AoE 255 without the Math Flag on. Otherwise, you'll overflow. Make it 254 if you must.

<?xml version="1.0" encoding="utf-8" ?>
<Patches>
  <Patch name="Math Skill Flag into Target Units Only Flag">
    <Description>
Turn the Math Skill flag into a flag that targets only tiles with units on them. Basically it just spoofs the 255 AoE check.</Description>
    <Location file="BATTLE_BIN" offset="1148d4">
      04007194
    </Location>
    <Location file="BATTLE_BIN" offset="1148f4">
      39403132
    </Location>
    <Location file="BATTLE_BIN" offset="1149fc">
     00402332
    </Location>
    <Location file="BATTLE_BIN" offset="114a00">
      00400234
    </Location>
    <Location file="BATTLE_BIN" offset="114ae4">
      E0002632
    </Location>
    <Location file="BATTLE_BIN" offset="114aec">
      2000C630
    </Location>
    <Location file="BATTLE_BIN" offset="114b40">
      C0403032
    </Location>
    <Location file="BATTLE_BIN" offset="114b60">
      00402732
    </Location>
    <Location file="BATTLE_BIN" offset="114b68">
      823B0700
    </Location>
    <Location file="BATTLE_BIN" offset="114cbc">
      1C00B1A3
    </Location>
    <Location file="BATTLE_BIN" offset="114d68">
      0000e226
    </Location>
   </Patch>
</Patches>

Dokurider

Anyone have a way to export code to xml format? Doing this by hand is a pain.


Dokurider

April 17, 2014, 03:54:19 pm #10 Last Edit: April 17, 2014, 04:00:37 pm by Dokurider
And it's done.

<?xml version="1.0" encoding="utf-8"?>
<Patches>

  <Patch name="Math Skill into Target Unit Only">
    <Description>Overwrites Morbol Depth Routine. Takes the 255 AoE check and modifies it to target only tiles with units in them. Good for Random Fire Skills. </Description>
    <Location file="BATTLE_BIN" offset="0011220c">
      0800E003
      00000000
      0E00E012
      00000000
      00006290
      02007490
      00000000
      0100942E
      0100422C
      21105400
      02004014
      01001026
      010064A0
      0002022A
      F5FF4014
      05006324
      2000FF27
      0800E003
      00000000
      00000000
    </Location>
    <Location file="BATTLE_BIN" offset="001148d4">
      04007194
    </Location>
    <Location file="BATTLE_BIN" offset="001148f4">
      39403132
    </Location>
    <Location file="BATTLE_BIN" offset="00114ae4">
      e0002632
    </Location>
    <Location file="BATTLE_BIN" offset="00114aec">
      2000c630
    </Location>
    <Location file="BATTLE_BIN" offset="00114b40">
      c0403032
    </Location>
    <Location file="BATTLE_BIN" offset="00114b60">
      00402732
    </Location>
    <Location file="BATTLE_BIN" offset="00114b68">
      823b0700
    </Location>
    <Location file="BATTLE_BIN" offset="00114cbc">
      1c00b1a3
    </Location>
    <Location file="BATTLE_BIN" offset="00114d68">
      21800000
      01000434
      1980033C
      D82D6324
      85E4050C
      00000000
    </Location>
  </Patch>
</Patches>


Couple of things to note before you use this hack:
Again, this overwrites the Morbol Depth Routine. Be sure to check if you have any hack applied that writes over that space.
This uses the Math Skill Flag to determine what has this property. Most patches don't use Math Skill anymore, so I deemed it a safe choice for flagging. Be mindful if you do use Math Skill in your patch with this patch enabled.
255 AoE still has a hard code on it, meaning if you make a still with 255 AoE, this hack will not work and it'll just make the whole map yellow.
If you want your skill to hit both ally and enemy, unflag both boxes. The Check Ally/Enemy Routine is simply not designed for both of them. Even if I knew how to correct this behavior, it's not really my prerogative.
F_MA*Y doesn't take Weapon Elemental :(

Other than that, enjoy everybody.