All right, I think I'll work on this run. Huge thanks to VanillaCoke, his suggestion to change the config saved me a lot of time getting this game to work.
Anyway, I started today trying to understand the RNG. From my own experience this is much simpler than trying to brute force blindly, and can make the run much simpler to finish.
TL;DR
FFT uses the standard PSX bios RNG for everything, it's in the Python code below:
Language: Python
def rng(seed):
seed = (((0x41c64e6d*seed)&0xffffffff) + 12345)&0xffffffff
val = (seed >> 16)&0x7fff
return (val, seed)
As said, the code above is in the PSX bios (more precisely scph1001), so it could be used by many other PSX games.
Anyway, I still don't know what are the routines that call this and when they do. When you're waiting to confirm an attack sometimes the RNG is rolled once after a frame, other times it's rolled seven. I still have a lot of work to do =/
If you're not interested in how I found this code you can stop reading now.
Apparently every time the game needs a random value it will "call" the subroutine at 0x2230c:
.data:0x0002230c 240a00a0 li $10,160
.data:0x00022310 01400008 jr $10
.data:0x00022314 2409002f li $9,47
I say "call" in quotes because the instruction used is actually JAL (jump and link), every code that uses the RNG jumps to that code and stores where it has to come back at the link register (R31).
Why did I include an instruction after the jump? Because it's MIPS, and there's a delay after a jump instruction so compilers usually optimize this and put an LI after a jump. For our purposes, it jumps to A0, keeps R31 the same and sets R9 to 47. At 0xa0 we have:
.data:0x000000a0 3c080000 lui $8,0x0
.data:0x000000a4 250805c4 addiu $8,$8,1476
.data:0x000000a8 01000008 jr $8
.data:0x000000ac 00000000 nop
It jumps to 1476 (0x5c4)
.data:0x000005c4 24080200 li $8,512
.data:0x000005c8 00094880 sll $9,$9,0x2
.data:0x000005cc 01094020 add $8,$8,$9
.data:0x000005d0 8d080000 lw $8,0($8)
.data:0x000005d4 00000000 nop
.data:0x000005d8 01000008 jr $8
.data:0x000005dc 00000000 nop
Here we see something interesting. It multiplies R9 by 4, adds it to 512, fetches the value and jumps to that address. So, we should understand this as fetching a "function pointer" from the position R9 of the array. At 47*4+512=700 (0x2bc) we have the address 0xbfc02200. That's a BIOS address, and PSXjin doesn't show these addresses at the memory viewer (it can be modified to do that though). At that address we find the BIOS RNG:
.data:0x00002200 3c03a001 lui $3,0xa001
.data:0x00002204 8c639010 lw $3,-28656($3)
.data:0x00002208 3c0141c6 lui $1,0x41c6
.data:0x0000220c 34214e6d ori $1,$1,0x4e6d
.data:0x00002210 00610019 multu $3,$1
.data:0x00002214 3c01a001 lui $1,0xa001
.data:0x00002218 00001812 mflo $3
.data:0x0000221c 24633039 addiu $3,$3,12345
.data:0x00002220 00031402 srl $2,$3,0x10
.data:0x00002224 30427fff andi $2,$2,0x7fff
.data:0x00002228 03e00008 jr $31
.data:0x0000222c ac239010 sw $3,-28656($1)
If someone could double-check that my python function does the same as this, I'd be very happy. The seed is located at 0xa0010000 - 28656 = 0xa0009010
0xA0009010 is the same address as 0x00009010, and that's where the seed is (if you use SCPH1001, of course).
So,
whenever you TAS a PSX game, look at 0x9010. There's a reasonable chance that the RNG seed might be there. For now, I have to look at more code to make something useful of this address...