Changed ability_data, class_data and item_data scripts

Identified more fields in ClassData
Identified more elements
Decompiled class_data functions
This commit is contained in:
Ogre 2023-09-12 18:31:47 +02:00
parent 7c766d07f9
commit 053f0d5cda
8 changed files with 419 additions and 87 deletions

View File

@ -21,6 +21,7 @@ typedef struct {
/* 0x18 */ u16 cur_hp; /* 0x18 */ u16 cur_hp;
/* 0x1A */ Element element; /* 0x1A */ Element element;
/* 0x1B */ u8 field_0x1b; /* 0x1B */ u8 field_0x1b;
/* 0x1C */ u16 strength; /* 0x1C */ u16 strength;
/* 0x1E */ u16 vitality; /* 0x1E */ u16 vitality;
/* 0x20 */ u16 intelligence; /* 0x20 */ u16 intelligence;
@ -28,12 +29,17 @@ typedef struct {
/* 0x24 */ u16 agility; /* 0x24 */ u16 agility;
// DEX affects melee and special attacks, as well as accuracy. // DEX affects melee and special attacks, as well as accuracy.
/* 0x26 */ u16 dexterity; /* 0x26 */ u16 dexterity;
/* 0x28 */ u8 field_0x28[3]; /* 0x28 */ u8 field_0x28[3];
/* 0x2B */ u16 item_upper_left; /* 0x2B */ u16 item_upper_left;
/* 0x2D */ u16 item_upper_right; /* 0x2D */ u16 item_upper_right;
/* 0x2F */ u16 item_lower_left; /* 0x2F */ u16 item_lower_left;
/* 0x31 */ u16 item_lower_right; /* 0x31 */ u16 item_lower_right;
/* 0x33 */ u8 field_0x33[0x5]; /* 0x33 */ u8 field_0x33;
/* 0x34 */ s8 field_0x34;
/* 0x35 */ u8 field_0x35;
/* 0x36 */ u8 field_0x36;
/* 0x37 */ u8 field_0x37;
} CharacterSlot; // size:0x38 } CharacterSlot; // size:0x38
#endif // __CHARACTER_H__ #endif // __CHARACTER_H__

View File

@ -321,11 +321,15 @@ extern Element ability_get_element(u8 index, u16 arg1, u16 arg2, s32 arg3, u16
extern u16 func_8016FA34(u16, u16, u16, u16); extern u16 func_8016FA34(u16, u16, u16, u16);
extern u16 func_8016FB50(u16, u16, u16, u16); extern u16 func_8016FB50(u16, u16, u16, u16);
#define RANK_NONE 0
#define RANK_UNIT_LEADER 1
#define RANK_LEGION_LEADER 2
typedef struct { typedef struct {
/* 0x00 */ char* name; /* 0x00 */ char* name;
/* 0x04 */ u8 field_0x4; /* 0x04 */ u8 field_0x4;
/* 0x05 */ u8 field_0x5; /* 0x05 */ u8 gender;
/* 0x06 */ u8 field_0x6; /* 0x06 */ u8 leadership_rank;
/* 0x07 */ u8 field_0x7; /* 0x07 */ u8 field_0x7;
/* 0x08 */ u16 field_0x8; /* 0x08 */ u16 field_0x8;
/* 0x0a */ u8 field_0xa; /* 0x0a */ u8 field_0xa;
@ -360,18 +364,27 @@ typedef struct {
/* 0x2b */ u8 field_0x2b; /* 0x2b */ u8 field_0x2b;
/* 0x2c */ u8 field_0x2c; /* 0x2c */ u8 field_0x2c;
/* 0x2d */ u8 field_0x2d; /* 0x2d */ u8 field_0x2d;
/* 0x2e */ u16 field_0x2e;
/* 0x30 */ u16 field_0x30; /* 0x2e */ u16 item_upper_left;
/* 0x32 */ u16 field_0x32; /* 0x30 */ u16 item_upper_right;
/* 0x34 */ u16 field_0x34; /* 0x32 */ u16 item_lower_left;
/* 0x34 */ u16 item_lower_right;
/* 0x36 */ u8 field_0x36; /* 0x36 */ u8 field_0x36;
/* 0x37 */ u8 field_0x37;
/* 0x38 */ u8 field_0x38; // The ability which is used when the unit is placed in the front row.
/* 0x39 */ u8 field_0x39; /* 0x37 */ u8 ability_front;
/* 0x3a */ u8 field_0x3a; // The amount of hits the unit performs when placed in the front row.
/* 0x3b */ u8 field_0x3b; /* 0x38 */ u8 ability_front_hitcount;
/* 0x3c */ u8 field_0x3c; // The ability which is used when the unit is placed in the middle row.
/* 0x39 */ u8 ability_middle;
// The amount of hits the unit performs when placed in the middle row.
/* 0x3a */ u8 ability_middle_hitcount;
// The ability which is used when the unit is placed in the back row.
/* 0x3b */ u8 ability_back;
// The amount of hits the unit performs when placed in the back row.
/* 0x3c */ u8 ability_back_hitcount;
/* 0x3d */ u8 field_0x3d; /* 0x3d */ u8 field_0x3d;
/* 0x3e */ u8 field_0x3e; /* 0x3e */ u8 field_0x3e;
/* 0x3f */ u8 field_0x3f; /* 0x3f */ u8 field_0x3f;
@ -383,11 +396,26 @@ typedef struct {
/* 0x44 */ u8 field_0x44; /* 0x44 */ u8 field_0x44;
/* 0x45 */ u8 field_0x45; /* 0x45 */ u8 field_0x45;
/* 0x46 */ u8 field_0x46; /* 0x46 */ u8 field_0x46;
/* 0x47 */ u8 field_0x47; /* 0x47 */ u8 max_items;
} ClassData; // size:0x48 } ClassData; // size:0x48
extern ClassData CLASS_DATA[]; extern ClassData CLASS_DATA[];
extern ItemId class_get_item_lower_right(u8 arg0, u8 arg1);
extern char* class_get_ability_front_name(u8 arg0, u8 arg1);
extern char* class_get_ability_middle_name(u8 arg0, u8 arg1);
extern char* class_get_ability_back_name(u8 arg0, u8 arg1);
extern char* class_get_name(u8 arg0, u8 arg1);
extern struct {
/* 0x0 */ u8 field_0x0;
/* 0x1 */ u8 field_0x1;
/* 0x2 */ u8 field_0x2;
/* 0x3 */ u8 field_0x3;
/* 0x4 */ u8 field_0x4;
/* 0x5 */ u8 field_0x5;
} D_8018ECE4[]; // size:0x6
extern musConfig __MUS_CONFIG_8010A710; extern musConfig __MUS_CONFIG_8010A710;
#endif #endif

View File

@ -12,6 +12,14 @@ typedef u8 Element;
#define ELEMENT_WATER 4 #define ELEMENT_WATER 4
#define ELEMENT_VIRTUE 5 #define ELEMENT_VIRTUE 5
#define ELEMENT_BANE 6 #define ELEMENT_BANE 6
#define ELEMENT_DRAKONITE 7
#define ELEMENT_VARIABLE 8
#define ELEMENT_WIND_FLAME 9
#define ELEMENT_FLAME_WIND 10
#define ELEMENT_EARTH_FLAME 11
#define ELEMENT_WATER_EARTH 12
#define ELEMENT_WIND_BANE 13
#define ELEMENT_FLAME_BANE 14
#define ELEMENT_UNKNOWN_0x10 16 #define ELEMENT_UNKNOWN_0x10 16

View File

@ -60,43 +60,178 @@ INCLUDE_ASM(const s32, "item", func_8016DB30);
INCLUDE_ASM(const s32, "item", func_8016DB84); INCLUDE_ASM(const s32, "item", func_8016DB84);
INCLUDE_ASM(const s32, "item", func_8016DBD8); /* 43AD8 8016DBD8 */
u8 class_get_field_0x2c(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].field_0x2c;
INCLUDE_ASM(const s32, "item", func_8016DC2C); return CLASS_DATA[arg1].field_0x2c;
}
INCLUDE_ASM(const s32, "item", func_8016DC80); /* 43B2C 8016DC2C */
u8 class_get_ability_front(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].ability_front;
INCLUDE_ASM(const s32, "item", func_8016DCD4); return CLASS_DATA[arg1].ability_front;
}
INCLUDE_ASM(const s32, "item", func_8016DD20); /* 43B80 8016DC80 */
u8 class_get_ability_front_hitcount(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].ability_front_hitcount;
INCLUDE_ASM(const s32, "item", func_8016DD74); return CLASS_DATA[arg1].ability_front_hitcount;
}
INCLUDE_ASM(const s32, "item", func_8016DDC8); /* 43BD4 8016DCD4 */
u8 class_get_ability_middle(u8 arg0, u8 arg1) {
s32 var_v0;
INCLUDE_ASM(const s32, "item", func_8016DE1C); if (CLASS_DATA[arg0].field_0x45 != arg1) {
var_v0 = arg1 * 9;
} else {
var_v0 = CLASS_DATA[arg0].field_0x45 * 9;
}
return *(&CLASS_DATA->ability_middle + (var_v0 * 8));
}
INCLUDE_ASM(const s32, "item", func_8016DE70); /* 43C20 8016DD20 */
u8 class_get_ability_middle_hitcount(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].ability_middle_hitcount;
INCLUDE_ASM(const s32, "item", func_8016DEC4); return CLASS_DATA[arg1].ability_middle_hitcount;
}
INCLUDE_ASM(const s32, "item", func_8016DF18); /* 43C74 8016DD74 */
u8 class_get_ability_back(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].ability_back;
INCLUDE_ASM(const s32, "item", func_8016DF88); return CLASS_DATA[arg1].ability_back;
}
INCLUDE_ASM(const s32, "item", func_8016DFDC); /* 43CC8 8016DDC8 */
u8 class_get_ability_back_hitcount(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].ability_back_hitcount;
INCLUDE_ASM(const s32, "item", func_8016E030); return CLASS_DATA[arg1].ability_back_hitcount;
}
INCLUDE_ASM(const s32, "item", func_8016E084); /* 43D1C 8016DE1C */
u8 class_get_field_0x4(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].field_0x4;
INCLUDE_ASM(const s32, "item", func_8016E0D8); return CLASS_DATA[arg1].field_0x4;
}
INCLUDE_ASM(const s32, "item", func_8016E140); /* 43D70 8016DE70 */
u8 class_get_gender(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].gender;
INCLUDE_ASM(const s32, "item", func_8016E174); return CLASS_DATA[arg1].gender;
}
/* 43DC4 8016DEC4 */
u8 class_get_leadership_rank(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].leadership_rank;
return CLASS_DATA[arg1].leadership_rank;
}
/* 43E18 8016DF18 */
u8 class_get_global_flag(u8 arg0, u8 arg1) {
u8 var_a1;
var_a1 = arg1;
if (D_8018ECE4[arg0].field_0x0 & 0x80) {
if (CLASS_DATA[arg0].field_0x45 == var_a1) {
var_a1 = arg0;
}
}
return D_8018ECE4[var_a1].field_0x0 & 0x3F;
}
/* 43E88 8016DF88 */
ItemId class_get_item_upper_left(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].item_upper_left;
return CLASS_DATA[arg1].item_upper_left;
}
/* 43EDC 8016DFDC */
ItemId class_get_item_upper_right(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].item_upper_right;
return CLASS_DATA[arg1].item_upper_right;
}
/* 43F30 8016E030 */
ItemId class_get_item_lower_left(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].item_lower_left;
return CLASS_DATA[arg1].item_lower_left;
}
/* 43F84 8016E084 */
ItemId class_get_item_lower_right(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].item_lower_right;
return CLASS_DATA[arg1].item_lower_right;
}
/* 43FD8 8016E0D8 */
char* class_get_ability_front_name(u8 arg0, u8 arg1) {
u8 var_v0;
if (CLASS_DATA[arg0].field_0x45 == arg1) {
var_v0 = CLASS_DATA[arg0].ability_front;
} else {
var_v0 = CLASS_DATA[arg1].ability_front;
}
return ability_get_name(var_v0);
}
/* 44040 8016E140 */
char* class_get_ability_middle_name(u8 arg0, u8 arg1) {
// Possible a C macro wrapping?
do {
char* ret = ability_get_name(CLASS_DATA[arg1].ability_middle);
return ret;
} while(0);
}
/* 44074 8016E174 */
char* class_get_ability_back_name(u8 arg0, u8 arg1) {
u8 var_v0;
if (CLASS_DATA[arg0].field_0x45 == arg1) {
var_v0 = CLASS_DATA[arg0].ability_back;
} else {
var_v0 = CLASS_DATA[arg1].ability_back;
}
return ability_get_name(var_v0);
}
/* 440DC 8016E1DC */
char* class_get_name(u8 arg0, u8 arg1) {
if (CLASS_DATA[arg0].field_0x45 == arg1)
return CLASS_DATA[arg0].name;
return CLASS_DATA[arg1].name;
}
INCLUDE_ASM(const s32, "item", func_8016E1DC);
INCLUDE_ASM(const s32, "item", func_8016E230); INCLUDE_ASM(const s32, "item", func_8016E230);

View File

@ -1,3 +1,16 @@
// Set by calls to bzero
D_80193BC0 = 0x80193BC0; // size:0x15E0
D_801971F0 = 0x801971F0; // size:0x4E2
D_801969B8 = 0x801969B8; // size:0x6E
D_80190F80 = 0x80190F80; // size:0x16C
D_80196B00 = 0x80196B00; // size:0x458
D_80193AB0 = 0x80193AB0; // size:0xA
D_801977D8 = 0x801977D8; // size:0x1E
D_80197710 = 0x80197710; // size:0x64
D_80196A58 = 0x80196A58; // size:0x94
DEFAULT_BATTALION_NAME = 0x80190EFC; // rom:0x66DFC type:asciz
STR_SERIFU_POSITION_X_ERROR = 0x8019E20C; // rom:0xEAF8C type:asciz STR_SERIFU_POSITION_X_ERROR = 0x8019E20C; // rom:0xEAF8C type:asciz
STR_IS_THE_NAME_ACCEPTABLE = 0x8018FDC4; // rom:0x65CC4 type:asciz STR_IS_THE_NAME_ACCEPTABLE = 0x8018FDC4; // rom:0x65CC4 type:asciz
@ -26,10 +39,35 @@ STR_ELEMENT_VIRTUE = 0x8018768C; // rom:0x5D58C type:asciz
STR_ELEMENT_BANE = 0x80187694; // rom:0x5D594 type:asciz STR_ELEMENT_BANE = 0x80187694; // rom:0x5D594 type:asciz
STR_ELEMENT_DRAKONITE = 0x8018769C; // rom:0x5D59C type:asciz STR_ELEMENT_DRAKONITE = 0x8018769C; // rom:0x5D59C type:asciz
STR_ELEMENT_VARIABLE = 0x801876A8; // rom:0x5D5A8 type:asciz STR_ELEMENT_VARIABLE = 0x801876A8; // rom:0x5D5A8 type:asciz
STR_ELEMENT_WIND_FLAME = 0x801876B4; // rom:0x5D5B4 type:asciz
STR_ELEMENT_FLAME_WIND = 0x801876C0; // rom:0x5D5C0 type:asciz
STR_ELEMENT_EARTH_FLAME = 0x801876CC; // rom:0x5D5CC type:asciz
STR_ELEMENT_WATER_EARTH = 0x801876D8; // rom:0x5D5D8 type:asciz
STR_ELEMENT_WIND_BANE = 0x801876E4; // rom:0x5D5E4 type:asciz
STR_ELEMENT_FlAME_BANE = 0x801876F0; // rom:0x5D5F0 type:asciz
D_80187BD4 = 0x80187BD4; // rom:0x5DAD4 type:u32 D_80187BD4 = 0x80187BD4; // rom:0x5DAD4 type:u32
CLASS_DATA = 0x80187C14; // rom:0x5DB14 size:0x48 type:u32 CLASS_DATA = 0x80187C14; // rom:0x5DB14 size:0x48 type:u32
class_get_field_0x2c = 0x8016DBD8; // rom:0x43AD8
class_get_ability_front = 0x8016DC2C; // rom:0x43B2C
class_get_ability_front_hitcount = 0x8016DC80; // rom:0x43B80
class_get_ability_middle = 0x8016DCD4; // rom:0x43BD4
class_get_ability_middle_hitcount = 0x8016DD20; // rom:0x43C20
class_get_ability_back = 0x8016DD74; // rom:0x43C74
class_get_ability_back_hitcount = 0x8016DDC8; // rom:0x43CC8
class_get_field_0x4 = 0x8016DE1C; // rom:0x43D1C
class_get_gender = 0x8016DE70; // rom:0x43D70
class_get_leadership_rank = 0x8016DEC4; // rom:0x43DC4
class_get_global_flag = 0x8016DF18; // rom:0x43E18
class_get_item_upper_left = 0x8016DF88; // rom:0x43E88
class_get_item_upper_right = 0x8016DFDC; // rom:0x43EDC
class_get_item_lower_left = 0x8016E030; // rom:0x43F30
class_get_item_lower_right = 0x8016E084; // rom:0x43F84
class_get_ability_front_name = 0x8016E0D8; // rom:0x43FD8
class_get_ability_middle_name = 0x8016E140; // rom:0x44040
class_get_ability_back_name = 0x8016E174; // rom:0x44074
class_get_name = 0x8016E1DC; // rom:0x440DC
ITEM_TYPE_NAMES = 0x802130A4; // rom:0x164214 type:char* ITEM_TYPE_NAMES = 0x802130A4; // rom:0x164214 type:char*
FORMATION_COMMAND_NAMES = 0x8021315C; // rom:0x1642CC type:char* FORMATION_COMMAND_NAMES = 0x8021315C; // rom:0x1642CC type:char*

View File

@ -16,7 +16,8 @@ def read_ability(index):
return unpack_from(ABILITY_FORMAT, read_rom(ability_start, ability_end)) return unpack_from(ABILITY_FORMAT, read_rom(ability_start, ability_end))
for i in range(1, 130): MAX_ABILITIES = 162
for i in range(1, MAX_ABILITIES):
(name_vaddr, field_0x0, element, field_0x2, field_0x3, field_0x4, (name_vaddr, field_0x0, element, field_0x2, field_0x3, field_0x4,
field_0x5, field_0x6, field_0x7, field_0x8, field_0x9, field_0x5, field_0x6, field_0x7, field_0x8, field_0x9,
@ -25,6 +26,6 @@ for i in range(1, 130):
name_addr_diff = (name_vaddr - NAME_VADDR_START) + NAME_ADDR_START name_addr_diff = (name_vaddr - NAME_VADDR_START) + NAME_ADDR_START
name = read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0] name = read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0]
print(f"{name}:\t", (field_0x0, field_0x2, field_0x3, field_0x4, field_0x5, print(f"{name} ({i}):\t", (field_0x0, field_0x2, field_0x3, field_0x4, field_0x5,
field_0x6, field_0x7, field_0x8, field_0x9, field_0xa, field_0x6, field_0x7, field_0x8, field_0x9, field_0xa,
field_0xb)) field_0xb))

View File

@ -1,27 +1,112 @@
from ob import read_rom, ELEMENT_NAME from ob import read_rom, ELEMENT_NAME
from struct import unpack_from from struct import unpack_from, calcsize
from typing import NamedTuple
import textwrap
import item_data
NAME_VADDR_START = 0x8016AF80 NAME_VADDR_START = 0x8016AF80
NAME_ADDR_START = 0x40E80 NAME_ADDR_START = 0x40E80
CLASS_DATA = 0x5DB14 CLASS_DATA = 0x5DB14
CLASS_FORMAT = '>IBBBBHBBHBBHBBHBBHBBHBBHBBBBBBBBBBBBHHHHBBBBBBBBBBBBBBBBBB'
class ClassData(NamedTuple):
name: int
field_0x4: int
gender: int
# None, Unit Leader, Legion Leader
leadership_rank: int
field_0x7: int
field_0x8: int
field_0xa: int
field_0xb: int
field_0xc: int
field_0xe: int
field_0xf: int
field_0x10: int
field_0x12: int
field_0x13: int
field_0x14: int
field_0x16: int
field_0x17: int
field_0x18: int
field_0x1a: int
field_0x1b: int
field_0x1c: int
field_0x1e: int
field_0x1f: int
field_0x20: int
field_0x22: int
field_0x23: int
field_0x24: int
field_0x25: int
field_0x26: int
field_0x27: int
field_0x28: int
field_0x29: int
field_0x2a: int
field_0x2b: int
field_0x2c: int
field_0x2d: int
item_upper_left: int
item_upper_right: int
item_lower_left: int
item_lower_right: int
field_0x36: int
ability_front: int
ability_front_hits: int
ability_middle: int
ability_middle_hits: int
ability_back: int
ability_back_hits: int
field_0x3d: int
field_0x3e: int
field_0x3f: int
field_0x40: int
field_0x41: int
field_0x42: int
field_0x43: int
field_0x44: int
field_0x45: int
field_0x46: int
max_items: int
def read_class(index): def read_class(index):
CLASS_SIZE = 0x48 CLASS_SIZE = 0x48
CLASS_FORMAT = '>IH'
class_start = CLASS_DATA + (index * CLASS_SIZE) class_start = CLASS_DATA + (index * CLASS_SIZE)
class_end = class_start + CLASS_SIZE class_end = class_start + CLASS_SIZE
return unpack_from(CLASS_FORMAT, read_rom(class_start, class_end)) return ClassData(*unpack_from(CLASS_FORMAT, read_rom(class_start, class_end)))
for i in range(1, 10): if __name__ == "__main__":
MAX_CLASSES = 165
for i in range(1, MAX_CLASSES):
class_data = read_class(i)
(name_vaddr, rest) = read_class(i) name_addr_diff = (class_data.name - NAME_VADDR_START) + NAME_ADDR_START
name_addr_diff = (name_vaddr - NAME_VADDR_START) + NAME_ADDR_START
name = read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0] name = read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0]
print(f"{name}:\t") print(f"Class= {name} ({i})\t")
print(rest) print(f"ItemUpperLeft= {item_data.item_get_name(item_data.item_read(class_data.item_upper_left).name)}")
print(f"ItemUpperRight= {item_data.item_get_name(item_data.item_read(class_data.item_upper_right).name)}")
print(f"ItemLowerLeft= {item_data.item_get_name(item_data.item_read(class_data.item_lower_left).name)}")
print(f"ItemLowerRight= {item_data.item_get_name(item_data.item_read(class_data.item_lower_right).name)}")
unidentified = []
for val in class_data._fields:
if val.startswith("field_"):
unidentified.append(f"{val}: {getattr(class_data, val)}")
print("Unidentified fields: ")
print("\n".join(unidentified), end="")
print()
print("-----------------------------------------")
print()

View File

@ -1,21 +1,48 @@
from ob import read_rom, ELEMENT_NAME, get_element_name from ob import read_rom, ELEMENT_NAME, get_element_name
from struct import unpack_from, calcsize from struct import unpack_from, calcsize
from typing import NamedTuple
NAME_VADDR_START = 0x8016AF80 OVERLAY_VADDR_START = 0x8016AF80
NAME_ADDR_START = 0x40E80 OVERLAY_ADDR_START = 0x40E80
ITEM_FORMAT = '>IBBBBHbbbbbbbbbbbbbBBBBBBBBB' ITEM_FORMAT = '>IBBBBHbbbbbbbbbbbbbBBBBBBBBB'
def read_item(index):
ITEM_SIZE = 0x20 ITEM_SIZE = 0x20
item_start = 0x6230C + (index * ITEM_SIZE) class ItemData(NamedTuple):
item_end = item_start + ITEM_SIZE name: int
item_type: int
element: int
field_0x2: int
field_0x3: int
field_0x4: int
strength: int
intelligence: int
agility: int
dexterity: int
vitality: int
mem : int
field_0xc: int
res_strike: int
res_wind: int
res_fire: int
res_earth: int
res_water: int
res_holy: int
res_dark: int
field_0x18: int
field_0x19: int
field_0x1a: int
field_0x1b: int
field_0x1c: int
field_0x1d: int
field_0x1e: int
field_0x1f: int
return unpack_from(ITEM_FORMAT, read_rom(item_start, item_end)) def item_get_name(ptr):
# Read the name from the ROM
print(f"Length: 0x{calcsize(ITEM_FORMAT):X}") name_addr_diff = (ptr - OVERLAY_VADDR_START) + OVERLAY_ADDR_START
return read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0]
ITEM_TYPE_NAME = { ITEM_TYPE_NAME = {
0: "None", 0: "None",
@ -48,41 +75,45 @@ ITEM_TYPE_NAME = {
255: "Invalid" 255: "Invalid"
} }
for i in range(0, 279): def item_get_type_name(item_type):
# print(f"Item {i}:") return ITEM_TYPE_NAME[item_type] if item_type in ITEM_TYPE_NAME else f"Unknown({item_type})"
(name_vaddr, item_type, element, field_0x2, field_0x3, field_0x4,
strength, intelligence, agility, dexterity, vitality,
mem, *rest) = read_item(i)
name_addr_diff = (name_vaddr - NAME_VADDR_START) + NAME_ADDR_START def item_read(index):
name = read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0] item_start = 0x6230C + (index * ITEM_SIZE)
item_end = item_start + ITEM_SIZE
(field_0xc, res_strike, res_wind, res_fire, res_earth, res_water, return ItemData(*unpack_from(ITEM_FORMAT, read_rom(item_start, item_end)))
res_holy, res_dark, *rest) = rest
rest = (field_0xc, *rest)
type_str = ITEM_TYPE_NAME[item_type] if item_type in ITEM_TYPE_NAME else f"Unknown({item_type})" if __name__ == "__main__":
MAX_ITEM = 279
for i in range(0, 5):
item = item_read(i)
print(f"Name: {name} ({i})") print(f"Name: {item_get_name(item.name)} ({i})")
print(f"Type: {type_str}") print(f"Type: {item_get_type_name(item.item_type)}")
print(f"Element: {get_element_name(element)}") print(f"Element: {get_element_name(item.element)}")
print(f"STR: \t{strength} \tMEN: \t{mem}") print(f"STR: \t{item.strength} \tMEN: \t{item.mem}")
print(f"VIT: \t{vitality} \tAGI: \t{agility}") print(f"VIT: \t{item.vitality} \tAGI: \t{item.agility}")
print(f"INT: \t{intelligence} \tDEX: \t{dexterity}") print(f"INT: \t{item.intelligence} \tDEX: \t{item.dexterity}")
print() print()
print(f"RES STRIKE: \t{res_strike}") print(f"RES STRIKE: \t{item.res_strike}")
print(f"RES WIND: \t{res_wind}") print(f"RES WIND: \t{item.res_wind}")
print(f"RES FIRE: \t{res_fire}") print(f"RES FIRE: \t{item.res_fire}")
print(f"RES EARTH: \t{res_earth}") print(f"RES EARTH: \t{item.res_earth}")
print(f"RES WATER: \t{res_water}") print(f"RES WATER: \t{item.res_water}")
print(f"RES HOLY: \t{res_holy}") print(f"RES HOLY: \t{item.res_holy}")
print(f"RES DARK: \t{res_dark}") print(f"RES DARK: \t{item.res_dark}")
for val in rest: unidentified = []
print(f"{val:X}") for val in item._fields:
if val.startswith("field_"):
unidentified.append(f"{val}: {getattr(item, val)}")
print("Unidentified fields: ")
print(", ".join(unidentified), end="")
print() print()
print("-------------------------------------------") print("-------------------------------------------")
print() print()