Please login or register.

Login with username, password and session length
Advanced search  


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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Glain

Pages: [1] 2 3 ... 27
PSX FFT Hacking / Re: ASM Requests
« on: November 11, 2019, 11:13:27 PM »
Actually, looking at this again, there would be a load delay issue with trying to copy the r17 value into r2 here.  While that could be avoided by loading r17's value earlier, there's no need to copy the value into r2 at all.  Just use r17 in the relevant locations.

Code: [Select]
   lhu r17, 4(r3)
   beq r17, r0, 0x0018cfd0      # Branch to end if No HP damage was dealt

Code: [Select]
   sh  r17, 0x0026(r3)

0x18cfc4 becomes free and could just be replaced with a nop (or a call to a routine in free space for a calculation?).

PSX FFT Hacking / Re: ASM Requests
« on: November 08, 2019, 05:22:36 AM »
Just eyeballing it, you also need to copy the HP damage into r2.  Also, why remove the branch?

Then look at what's happening at 0x18cfc4.  In the current modification, it's taking the HP damage, interpreting it as a RAM address and loading from it.
Instead, once again, just copy the HP damage into r2:

This would just try to absorb the full HP damage.  If you want to do a calculation like (dmg * 20 / maxHP) then you would need some more code space, and may need to use some free/kanji space.

War of the Lions Hacking / Re: Are multiple custom jobs now possible?
« on: October 26, 2019, 11:11:05 PM »
Check this post/thread:

I suspect he actually found the correct locations for WOTL in this post, but I never looked into it myself...

Help! / Re: Help installing "The Lion War" with slight modification
« on: October 09, 2019, 04:53:20 AM »
0x1179a4 in BATTLE.BIN would be the correct address, because the game loads that file into RAM at address 0x67000, so the location of its code in RAM is offset by that same amount.  That instruction would be at RAM address 0x17e9a4 at runtime.  (In fact, BATTLE.BIN isn't even big enough to have an offset 0x17e9a4)

PSX FFT Hacking / Re: ASM Requests
« on: July 31, 2019, 03:26:59 PM »
Yep.  This is a handy reference.  At first glance, the appropriate routine seems to be this one.

To get the AI to not spend JP, you could probably nop out the instruction at either 0x5d010 or 0x5d018.

PSX FFT Hacking / Re: ASM Requests
« on: July 31, 2019, 04:16:02 AM »
It only applies when learning an ability from the formation screen.

Are you asking if AI units would still spend JP to learn their skills?  They would.  Perhaps the title of the patch could be a bit more specific.

Help! / Re: Excising FMV to Save Space (PSX Version)
« on: July 25, 2019, 11:36:32 PM »
Regarding what is actually playing the FMVs at the titlescreen, the code in OPEN.BIN probably controls that, but it needs more investigation.  I did document some of it, starting with the main routine here.

if the registers got expanded

Haha what?  They're 32 bits wide at the hardware level.

Formula 0x38 is actually unique in that it doesn't have its own function and the formula table links directly to the status applying routine instead.  If you want to alter what the formula does without changing the status application routine, you have to change where it points.

At address 0x8018f610 in RAM (0x128610 in BATTLE.BIN) is the formula table.  Each entry is a 4-byte pointer to the function to call when that formula is used.  Entry 0x38 is at address 0x8018f6f0 in RAM and offset 0x1286F0 in BATTLE.BIN.  You would need to change that entry (from 0x80187f24) to the address of your custom function in free/kanji space.

Help! / Re: Routines that determine Move/Act CT costs
« on: May 30, 2019, 01:09:22 PM »
This routine looks like the right one.

As for a breakpoint that could determine this?  That would be a write breakpoint on a unit CT value (offset 0x0039 from the start of the unit's in-battle data - array starting at 0x801908cc - see this reference).

Help! / Re: Gender Byte
« on: May 21, 2019, 11:09:29 PM »
Those are two different arrays of unit data.  The first is the main party data, and the second is the unit data used in the formation screen.  I actually have a more detailed definition of that data structure in the Data/Table Locations page.  (Search for "801c8638 (WORLD.BIN)")

In the case of formation screen unit data offset 0x70, it's copied from party data offset 0x04, so those should have the same value. (This routine is the one that copies the data.)

As for why they sometimes used 2-byte fields when 1-byte fields would suffice, it probably wasn't a conscious decision.  They probably used a short data type instead of a char data type in their C source code, or something along those lines.

I had glossed over the palette thing without really looking into what it represented.  That value, offset 0x04 from unit data, as far as I am aware, is actually the unit's team ID (i.e. whose side it's on).  It just so happens that for human enemies that would also affect the palette, but for monsters it's different.  If you were thinking of it in the sense of lower tier vs. higher tier monsters, I think that should just be checked via job ID since each tier is a unique job.

Expanding the first table to check the job IDs is the way I would have handled it, so that looks good to me!

As for the status checks, I found a logic error in the code, on this line:

addu    t7, t3, t4      #   Status byte pointer

It should be:

addu    t7, t2, t4      #   Status byte pointer

Edit - I wouldn't think of the 0x80184360 routine as the Dance/Song Hit% routine.  It's the Hit X% routine and apparently only dance and song use it in the base game.

You should be able to just remove the branch by changing BATTLE.BIN at offset 0xD90BC (4 bytes) from 02 00 40 10 to 00 00 00 00.

Patch that does it:

According to the Wiki, the relevant routine seems to be this one.  The only thing that really catches my eye at first glance is that it seems to sometimes skip setting the red flashing status if the action is immediate (no charge time), based on the branch at 0x1400bc.

No problem, glad to hear the hit % looks right!

Right, so we've calculated the hit % but never applied it in the actual formula code.  There is a bunch of code related to actually making the hit % work that could be inserted, but I think it's easier if we make use of one of the existing routines.  We can do that by storing our Hit % value into the ability's X value instead of the action's hit % (assuming you aren't using X for something else, or have already made use of it in the formula and don't need it anymore).  The way it would work is that we would change the bottom of our new routine (the "end" section) to this:

Code: [Select]
                    lui     t0, 0x8019
                    jr      ra
                    sb      v0, 0x38f9(t0)  #   Store Hit% as X

Then in the calling (formula) routine...

Code: [Select]
#   Evade section up here (if necessary)

#   Custom tame hit % section
jal     @find_monster_tame_hit_percent
jal     0x80184360
bne     v0, zero, formula_end_section       #   Replace "formula_end_section" with the appropriate address (same address as evade would branch to on a miss)

#   Rest of the formula code (...)

I think that should work to get the Hit % actually applying.

Completed Patches / Re: FFT: Emergence (PSP)
« on: May 07, 2019, 03:07:55 PM »
Unfortunately, on the back end, the coding was really slapdash, which makes WotL extremely hard to work with from a hacking standpoint.

I don't think there's anything particularly wrong with the coding...  if anything, some of the limitations are removed -- code isn't scattered across multiple files, no load delay hazard, etc.  I'm unsure about free space, but there seem to be large gaps (of nops) between some of the routines in the main executable.  It's just... nobody's really bothered to document much of the PSP code, or make hacks for it.  The same goes for some of the modding tools.

I did poke around with the Effect Editor somewhat.  The effect Code Scripts section doesn't seem quite right, at least not for the effects I tested.

But the Emitter Control and Effect Timing/Control sections have some juicy knowledge buried in there regarding effect location/camera movement/rotation that I didn't notice on the first go-around.  This allows the proper data to be pinpointed without needing a debugger.  I've updated the relevant post to use the easier method.

Potentially, you could just make some of these changes in the editor directly, but it's good to know where the data is and/or how to find it.

Changing Effect colors/palette at runtime

I was able to place a hook into the code at 0x801a1930 in what I'm calling the Effect Stage Processing routine.
This is after the effect has been loaded but before the palette setup has been run.  (If you do hook this code, just remember that you still have to load the effect ID (from 0x801c24d0) as a parameter for the next routine...  I may or may not have crashed the game a few times and/or turned units into glitch blocks by forgetting to do this...)

To find the palette data:

Effect data pointer = Word (4-byte value) loaded from (EffectID * 4) + 0x801b48d0
Palette offset = Word (4-byte value) loaded from (Effect data pointer + 0x24)
Palette pointer = Effect data pointer + Palette offset

Code to get palette pointer may look something like this:
(If effect ID is in r4/a0)
Code: [Select]
sll     t1, a0, 2
lw      t2, 0x801b48d0 (t1)

lw      t1, 0x24 (t2)       #   Effect palette data offset

addu    t1, t2, t1          #   Effect palette data pointer

An effect palette contains 256 (0x100) colors at 2 bytes each, so it's 512 (0x200) bytes long.  It appears from looking at the code that there is actually another palette stored directly after the first one that is usually just all zeroes, but overall the palette data seems to be treated as two 256-color palettes next to each other for a total of 1024 (0x400) bytes.

The color information for each palette entry, by bit, is [ABBBBBGG][GGGRRRRR] where the bracketed sections are the bytes and the high order byte is listed first (they would be reversed in RAM).  Alpha value is 1 bit and RGB are 5 bits each (values ranging from 0 to 31).

Extracting the ARGB values from the combined value:

red = color & 0x1f
green = (color & 0x3d0) >> 5
blue = (color & 0x7c00) >> 10
alpha = color >> 15

Re-combining ARGB values back into a single color value (assuming values are in bounds):

color = red | (green << 5) | (blue << 10) | (alpha << 15)

Whatever changes you make to the colors here at runtime should be reflected in the displayed effect!

Changing Effects that animate on a single target to animate on multiple targets

My example effect for this one is Knife Hand / Damage Split (ID 0x155 = 341) (E341.BIN), which only animates on a single target.

At 0x801b48d0 in RAM is a table of data that defines where the effect file header is stored (in RAM) for each effect ID.
For ID 0x155, the table location is: 0x155 * 4 + 0x801b48d0 = 0x801b4e24
The value at 0x801b4e24 is 0x801c3cfc, the RAM location where the header data starts.
Effect files are loaded into RAM at 0x801c2500, so this results in a file offset of 0x801c3cfc - 0x801c2500 = 0x17FC.

Most effects have their header data stored right at the start of the file, but this one is different.  The start of this effect file is actually... an ASM subroutine.  More on that later.

Anyhow, at 0x17FC in the file, we find the header data.  These are offsets (from the start of header data) of where each section of the effect file starts.  Choto documented these (and a whole bunch of info about effect files) with a bunch more detail but I'm not sure if it's anywhere on the Wiki!

Code: [Select]
28 00 00 00
8C 02 00 00
E0 02 00 00     <-- Effect script offset (from start of header data)
08 03 00 00
F0 06 00 00
00 00 00 00
54 10 00 00
6C 10 00 00
F4 28 00 00
4C 29 00 00

"E0 02 00 00" is 0x02E0 in little endian.  0x17FC + 0x02E0 = 0x1ADC, where the effect script starts in the file.  Essentially, it's a series of script instructions that tell the effect how to animate.

Broken down by script instruction, and with the offsets shown (from the start of the effect script data), it looks like this (hex):

Code: [Select]
00: 05 30
02: 06 00 5F 00
06: 2A 00
08: 27 00
0A: 1F 00 26 00
0E: 1D 00 1A 00
12: 28 00
14: 25 00
16: 00 00 0E 00

1A: 25 00
1C: 16 00 00 00 26 00
22: 00 00 1A 00
26: 04 00

When run, it's like a header section, a loop, and an ending section.
Header section commands: 05, 06, 2A, 27, 1F
Loop commands: 1D, 28, 25, 00
Ending section commands: 25, 16, 00, 04

Compared to an effect that animates on multiple targets, say, Fire:

Code: [Select]
00: 05 20
02: 27 00
04: 1F 00 22 00

08: 1E 00 16 00
0C: 29 00 24 00
10: 25 00
12: 00 00 08 00

16: 25 00
18: 16 00 00 00 22 00
1D: 00 00 16 00
22: 04 00

24: 1D 00 30 00
28: 28 00
2A: 25 00
2C: 00 00 24 00

30: 25 00
32: 16 00 00 00 3C 00
38: 00 00 30 00
3C: 04 00

Header section commands: 05, 27, 1F
Loop commands (1): 1E, 29, 25, 00       <-- This seems to handle multiple targets
Ending section (1) commands: 25, 16, 00, 04
Loop commands (2): 1D, 28, 25, 00
Ending section (2) commands: 25, 16, 00, 04

Here is a somewhat general idea of what some of these script instructions are:

Code: [Select]
ID          Bytes       Desc

0x00        4           Jump (unconditional)
0x04        2           End Effect
0x05        2           Begin Effect
0x06        4           Setup Custom Routine Pointer
0x16        6           Decision branch?
0x1d        4           Conditional branch (Timing, duration?)
0x1e        4           Conditional branch (multi-target?)
0x1f        4           Conditional branch (based on hit counter)?
0x25        2           Effect processing (advance frame)?
0x27        2           Store motion data?
0x28        2           Graphics (timing?)
0x29        4           Graphics (multi-target?), can branch
0x2a        2           Clear temp data?

(You can also figure out the order that script instructions are being run by setting an execute breakpoint at 0x1a4d44 and noting which IDs are run in which order.)

Damage Split's header section is bigger because it has to set up a pointer to its own custom subroutine which it defines.

The key difference is that Damage Split doesn't have the first loop and ending section.  If we add it in:

Code: [Select]
00: 05 30
02: 06 00 5F 00
06: 2A 00
08: 27 00
0A: 1F 00 28 00
0E: 1E 00 1C 00
12: 29 00 2A 00
16: 25 00
18: 00 00 0E 00
1C: 25 00
1E: 16 00 00 00 28 00
24: 00 00 1C 00
28: 04 00
2A: 1D 00 36 00
2E: 28 00
30: 25 00
32: 00 00 2A 00
36: 25 00
38: 16 00 00 00 42 00
3E: 00 00 36 00
42: 04 00

As just the hex:
Code: [Select]
05 20 06 00 5F 00 2A 00 27 00 1F 00 28 00 1E 00
1C 00 29 00 2A 00 25 00 00 00 0E 00 25 00 16 00
00 00 28 00 00 00 1C 00 04 00 1D 00 36 00 28 00
25 00 00 00 2A 00 25 00 16 00 00 00 42 00 00 00
36 00 04 00

This seems to actually work as a pretty good all-purpose multi-target effect script for anything that doesn't have a custom routine or has one at the start of the file.  If there is another location for the custom routine then the 5F might need to change.

We can then replace the old effect script hex with the new effect script hex in the effect file (moving the rest of the file down). (This can be done in HxD by highlighting the old effect script and doing a Paste Insert with the new hex)

That handles the effect script itself, but this just added some bytes to the file.  In the case of Damage Split, the new script was 0x1C = 28 bytes larger.  That means the header section offsets have to be updated, way back up at file offset 0x17FC.

New offsets:
Code: [Select]
28 00 00 00
8C 02 00 00
E0 02 00 00     <-- Effect script offset (from start of header data)
24 03 00 00
0C 07 00 00
00 00 00 00
70 10 00 00
88 10 00 00
10 29 00 00
68 29 00 00

Everything below the effect script offset has 0x1C added (except for the 00 00 00 00).

Saving that and re-importing that effect file into the ISO, the Knife Hand / Damage Split effect can now animate over multiple targets. 

Since the file size changed, the file info in the ISO also has to change to reflect the new file size or you won't be able to import it.  I used TOC Changer for this.
We can get away with changing the file size as long as the size on disk of the file doesn't change.  In this case, the file size goes from 34124 to 34152 bytes but the size on disk remains at 36864 bytes.

Changing where an Effect animates

Using Heaven's Cloud effect (E137.BIN) as an example:
In the Effect header data (this is at the start of E137.BIN but can be more complicated to find in other effects; more detail on how to find this data in the next post):

Code: [Select]
28 00 00 00
A0 06 00 00
08 08 00 00
48 08 00 00     <-- Emitter control section offset
8C 11 00 00
00 00 00 00
F0 1A 00 00
08 1B 00 00
90 33 00 00
5C 34 00 00

At offset 0x0848 from the start of header data here, we find the number of emitters (12):
02 00 0C 00

There are 16 more bytes of header data.  After that, each emitter has a section that is 0xC4 (196) bytes long.  The fourth byte (offset 3) for each emitter section contains the number that defines where the effect animates (for more detail, see the Effect Graphics routine):

Code: [Select]
Test values (partial)

Value           Description

0x02            Animates on targeted panel
0x04            Animates on/over source unit
0x06            Animates on each target unit?

For the first emitter section, this value is at offset 0x85F in the file.  Each one after that is the previous value + 0xC4.  Given that there are 12 emitters, this means the final value is at 0x10CB.
Changing the byte from 04 to 02 at the specified locations (excluding the 06 at 0x1007) made Heaven's Cloud animate on the target panel!

There was still one issue, though:  the camera still rotated toward and centered on the source unit, not the target panel.
From the header data:

Code: [Select]
28 00 00 00
A0 06 00 00
08 08 00 00
48 08 00 00     
8C 11 00 00
00 00 00 00
F0 1A 00 00
08 1B 00 00    <-- Relevant offset that contains camera section
90 33 00 00
5C 34 00 00

The start of this section is 0x1b08.  There are three offsets that point you to camera commands:
   + 0x0806: 0x230e (Values: 7)
   + 0x168a: 0x3192 ((Non-zero) Values: 0x0444, 0x0543)
   + 0x185a: 0x3362 ((Non-zero) Values: 0x04c7, 0x0507)

The code does a bitwise-and with 0x01e0 on these values to get the final value it checks:

Code: [Select]
Test values (partial)
0x01c0: Rotate (or center) toward target panel ?
0x0140: Rotate (or center) toward source unit ?
0x0100: Rotate (or center) back to original point ?

By changing 0x543 to 0x5C3 (changing 0x43 to 0xC3 at file offset 0x3196), both the camera rotation and center went to the target panel instead of the source unit!

Here is a patch that would make the changes:

Recently I began investigating Effects because I wanted to use some of them for abilities in ways that wouldn't normally work.  For example, some effects only animate on one target, even if the ability hits multiple targets.  Some of them only center around the caster, even if the ability was targeted away from the caster (like the Draw Out effects). 

Here I'm going through three different ways to modify effects:

    * Changing where an Effect animates (target panel vs. source unit, for example)
    * Changing Effects that animate on a single target to animate on multiple targets
    * Changing Effect colors/palette at runtime

There wasn't a whole lot of previous documentation about this, so I had to do quite a bit of investigation, and I'm documenting what I found for posterity.  Choto's notes on effect data locations and routines (from years before!) were really helpful.

Pages: [1] 2 3 ... 27