Hehe, looks nice! Now you can deal all of the damage in the world
Update to the Monster structure:
Note, the offsets listed are for the first struct in the array, they are usually referenced with address + (208*monster_id) - the unknown padding is mostly in sizes of 8 so it's easy to replace it when I find out what some values are.
//0x1D27B10
#pragma pack(push, 1)
struct Character
{
BYTE **monster_info; //0x1D27B10 - could just be used for the name but points to section 7 of a loaded dat file
BYTE unk[8]; //0x1D27B14
BYTE status; //0x1D27B1C - MSB - reflect / shell / protect / regen / stop / slow / haste / ? - LSB
BYTE unk1[3]; //0x1D27B1D
DWORD unkdword1D27B20; //0x1D27B20 - used in opcode 0x24
DWORD unkdword1D27B24; //0x1D27B24 - used in opcode 0x24
DWORD currentHP; //0x1D27B28
DWORD maxHP; //0x1D27B2C
BYTE unk2_0[4]; //0x1D27B30
DWORD localVars[8]; //0x1D27B34 - DC to E3 - base address used is 0x1D277C4
WORD unkwordarr1D27B54[6]; //0x1D27B54 at least 6 items, changed by opcode 2D
BYTE unk3_0[4]; //0x1D27B60
WORD unkword1D27B64[16]; //0x1D27B64
DWORD unkdword1D27B84[3]; //0x1D27B84
BYTE status1; //0x1D27B90 MSB - ? / zombie / berserk / ? / ? / ? / ? / ? - LSB
BYTE unk4[7]; //0x1D27B91
BYTE lastAttacker; //0x1D27B98 - used in opcode 0x0E case 0xCB - 0, 1 or 2 for SeeD 3+ for monsters
BYTE unk5_0[7]; //0x1D27B99 - this whole section of unknowns looks to be status resistances
BYTE unk5_1[8]; //0x1D27BA0
BYTE unk5_2[8]; //0x1D27BA8
BYTE unk5_3[8]; //0x1D27BB0
BYTE unk5_4[8]; //0x1D27BB8
BYTE unk5_5[8]; //0x1D27BC0
BYTE unkbyte1D27BC8; //0x1D27BC8 used in case 0x2A
BYTE unk6[3]; //0x1D27BC9
BYTE lvl; //0x1D27BCB
BYTE str; //0x1D27BCC
BYTE vit; //0x1D27BCD
BYTE mag; //0x1D27BCE
BYTE spr; //0x1D27BCF
BYTE spd; //0x1D27BD0
BYTE luck; //0x1D27BD1
BYTE eva; //0x1D27BD2
BYTE unk7[12];
};
#pragma pack(pop)
I'd imagine that the struct above is referenced all over the battle code, so I'm trying to decipher as much of it as I can so that understanding what other battle functions do will be a lot easier.
I've found that generally the ID of the monsters is 3, 4 and 5 (no idea what happens with 8 monster battles yet), so the first monster you fight will have its parameters at 0x1D27D80 rather than 0x1D27B10. It looks like it stores most of the parameters for the monsters that you're fighting, all I need now is to finish decoding it
.
There's a bunch of interesting things I didn't know about the AI code, you have to be careful with some opcodes because you can override bits of memory that you shouldn't - which could lead to some random crashes.
opcode 0x0E is used to set a variable as mentioned by random_npc, there's a special case where the immediate is 0xCB which causes the variable to be assigned the value of last attacker instead of the immediate - it appears that 0xCB is treated as a special case in quite a few opcodes.
After further investigation, it seems there are 2 sets of variables DC-E3 (which are stored in the struct above) and 60-67 (which are stored separately - I assume these are global for the battle).
It looks like bad things would happen if you used opcode 0x0E to write outside the range DC-E3 but there's no constraint checking!
The 71 byte structure I mentioned before contains a series of multipliers for stats (str, mag etc.) which default to 10 (1x multiplier) among some other things that I haven't identified.
Notes on opcode 0x04 - Targeting:
the final form of this in the function is a bit mask to represent which enemies are targeted, looking at the code I can see the following:
0xC8: 0000 0000 0000 1000 //self (it just shifts 1 left by the monster id - this represents and id of 3)
0xC9: //random enemy - probably one of the first 3 bits is set
0xCA: //??
0xCB: //last attacker - does 1 << the value in it's struct (see struct above)
0xCC: 1000 0000 0000 0111 //all enemies
0xCD: 1000 0000 1111 1000 //all allies
0xCE: 1000 0000 1111 1111 //everyone?
0xCF: //random ally
0xD0: 1010 0000 0000 0111 //something to do with enemies
0xD1: //?? does 1 << the value in 0x1D28DFB
0xDC-0xE3: //does 1 << the value in the corresponding variable