Created `docs` folder for helpful game guides

Figured out a more correct layout of items
Decompiled a couple more functions
Build: OK
This commit is contained in:
Ogre 2023-09-11 01:35:47 +02:00
parent 32432fe0a8
commit f0091a98ae
9 changed files with 7736 additions and 54 deletions

6460
docs/character-list.txt Normal file

File diff suppressed because it is too large Load Diff

1155
docs/class-spell-list.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,10 @@
#include <ultra64.h>
#include "element.h"
typedef struct {
// Possible data still undiscovered:
// - Element
// - Gender
// - Alignment
// - Held items (four u16's)
@ -15,10 +15,11 @@ typedef struct {
/* 0x11 */ u8 portrait;
/* 0x12 */ u8 class;
/* 0x13 */ u8 level;
/* 0x14 */ u8 field_0x14[0x2];
/* 0x14 */ u8 gender;
/* 0x15 */ u8 field_0x15;
/* 0x16 */ u16 max_hp;
/* 0x18 */ u16 cur_hp;
/* 0x1A */ u8 field_0x1a;
/* 0x1A */ Element element;
/* 0x1B */ u8 field_0x1b;
/* 0x1C */ u16 strength;
/* 0x1E */ u16 vitality;
@ -27,7 +28,12 @@ typedef struct {
/* 0x24 */ u16 agility;
// DEX affects melee and special attacks, as well as accuracy.
/* 0x26 */ u16 dexterity;
/* 0x28 */ u8 field_0x28[0x10];
/* 0x28 */ u8 field_0x28[3];
/* 0x2B */ u16 item_upper_left;
/* 0x2D */ u16 item_upper_right;
/* 0x2F */ u16 item_lower_left;
/* 0x31 */ u16 item_lower_right;
/* 0x33 */ u8 field_0x33[0x5];
} CharacterSlot; // size:0x38
#endif // __CHARACTER_H__

View File

@ -13,7 +13,7 @@ typedef u8 Element;
#define ELEMENT_VIRTUE 5
#define ELEMENT_BANE 6
#define ELEMENT_UNKNOWN_0x10 0x10
#define ELEMENT_UNKNOWN_0x10 16
#define ELEMENT_INVALID 0xFF

View File

@ -5,30 +5,33 @@
#include "element.h"
typedef u8 ItemType;
#define ITEM_TYPE_SWORD 1
#define ITEM_TYPE_GREATSWORD 2
#define ITEM_TYPE_THRUSTING_SWORD 3
typedef struct {
/* 0x00 */ u8 field_0x0;
/* 0x01 */ Element element;
/* 0x02 */ u8 field_0x2;
/* 0x03 */ u8 field_0x3;
/* 0x04 */ u16 field_0x4;
/* 0x06 */ s8 strength;
/* 0x07 */ s8 intelligence;
/* 0x08 */ s8 agility;
/* 0x09 */ s8 dexterity;
/* 0x10 */ s8 vitality;
/* 0x11 */ s8 mentality;
/* 0x12 */ s8 field_0xc;
/* 0x13 */ s8 res_strike;
/* 0x14 */ s8 res_wind;
/* 0x15 */ s8 res_fire;
/* 0x10 */ s8 res_earth;
/* 0x11 */ s8 res_water;
/* 0x12 */ s8 res_holy;
/* 0x13 */ u8 res_dark;
/* 0x14 */ u8 field_0x14;
/* 0x15 */ u8 field_0x15;
/* 0x16 */ u8 field_0x16;
/* 0x17 */ u8 field_0x17;
/* 0x00 */ char* name;
/* 0x04 */ ItemType type;
/* 0x05 */ Element element;
/* 0x06 */ u8 field_0x6;
/* 0x07 */ u8 field_0x7;
/* 0x08 */ u16 field_0x8;
/* 0x0a */ s8 strength;
/* 0x0b */ s8 intelligence;
/* 0x0c */ s8 agility;
/* 0x0d */ s8 dexterity;
/* 0x0e */ s8 vitality;
/* 0x0f */ s8 mentality;
/* 0x10 */ s8 field_0x10;
/* 0x11 */ s8 res_strike;
/* 0x12 */ s8 res_wind;
/* 0x13 */ s8 res_fire;
/* 0x14 */ s8 res_earth;
/* 0x15 */ s8 res_water;
/* 0x16 */ s8 res_holy;
/* 0x17 */ u8 res_dark;
/* 0x18 */ u8 field_0x18;
/* 0x19 */ u8 field_0x19;
/* 0x1a */ u8 field_0x1a;
@ -42,7 +45,8 @@ typedef struct {
extern ItemData ITEM_DATA[];
extern s8 (*FP_ITEM_GET_RESISTANCE[])(u16 index);
extern u8 item_get_field_0x0(u16 index);
extern char* item_get_name(u16 index);
extern ItemType item_get_type(u16 index);
extern Element item_get_element(u16 index);
extern u8 item_get_field_0x2(u16 index);
extern u16 item_get_field_0x4(u16 index);

View File

@ -149,15 +149,24 @@ INCLUDE_ASM(const s32, "item", func_8016F540);
INCLUDE_ASM(const s32, "item", func_8016F560);
INCLUDE_ASM(const s32, "item", func_8016F580);
/* 45480 8016F580 */
u8 func_8016F580(u16 index) {
return ITEM_DATA[index].field_0x1b;
}
INCLUDE_ASM(const s32, "item", func_8016F598);
/* 45498 8016F598 */
u8 func_8016F598(u16 index) {
return ITEM_DATA[index].field_0x1c;
}
INCLUDE_ASM(const s32, "item", func_8016F5B0);
/* 454B0 8016F5B0 */
char* item_get_name(u16 index) {
return ITEM_DATA[index].name;
}
/* 454C8 8016F5C8 */
u8 item_get_field_0x0(u16 index) {
return ITEM_DATA[index].field_0x0;
u8 item_get_type(u16 index) {
return ITEM_DATA[index].type;
}
/* 454E0 8016F5E0 */
@ -166,24 +175,24 @@ Element item_get_element(u16 index) {
element = ITEM_DATA[index].element;
if (element == ELEMENT_UNKNOWN_0x10) {
element = CHARACTER_SLOT[0].field_0x1a;
element = CHARACTER_SLOT[0].element;
}
return element;
}
/* 45514 8016F614 */
u8 item_get_field_0x2(u16 index) {
return ITEM_DATA[index].field_0x2;
return ITEM_DATA[index].field_0x6;
}
/* 4552C 8016F62C */
u16 item_get_field_0x4(u16 index) {
return ITEM_DATA[index].field_0x4;
return ITEM_DATA[index].field_0x8;
}
/* 45544 8016F644 */
s8 item_get_field_0xc(u16 index) {
return ITEM_DATA[index].field_0xc;
return ITEM_DATA[index].field_0x10;
}
/* 4555C 8016F65C */
@ -289,22 +298,22 @@ s8 item_get_resistance_dark(u16 index) {
/* 457E4 8016F8E4 */
u32 item_get_field_0x14_b68(u16 index) {
return ITEM_DATA[index].field_0x14 >> 6;
return ITEM_DATA[index].field_0x18 >> 6;
}
/* 45800 8016F900 */
u32 item_get_field_0x14_b46(u16 index) {
return (ITEM_DATA[index].field_0x14 >> 4) & 3;
return (ITEM_DATA[index].field_0x18 >> 4) & 3;
}
/* 45820 8016F920 */
u32 item_get_field_0x14_b24(u16 index) {
return (ITEM_DATA[index].field_0x14 >> 2) & 3;
return (ITEM_DATA[index].field_0x18 >> 2) & 3;
}
/* 45840 8016F940 */
u32 item_get_field_0x14_b12(u16 index) {
return ITEM_DATA[index].field_0x14 & 3;
return ITEM_DATA[index].field_0x18 & 3;
}
INCLUDE_ASM(const s32, "item", func_8016F95C);

View File

@ -19,8 +19,9 @@ STR_PHYSICAL = 0x80187660; // rom:0x5D560 type:asciz
ABILITY_DATA = 0x8018AA80; // rom:0x60980 size:0x10
ability_get_element = 0x8016E470;
ITEM_DATA = 0x8018C410; // size:0x20
item_get_field_0x0 = 0x8016F5C8;
ITEM_DATA = 0x8018C40C; // size:0x20
item_get_name = 0x8016F5B0;
item_get_type = 0x8016F5C8;
item_get_element = 0x8016F5E0;
item_get_field_0x2 = 0x8016F614;
item_get_field_0x4 = 0x8016F62C;

View File

@ -1,26 +1,64 @@
from ob import read_rom, ELEMENT_NAME
from ob import read_rom, ELEMENT_NAME, get_element_name
from struct import unpack_from
from struct import unpack_from, calcsize
NAME_VADDR_START = 0x8016AF80
NAME_ADDR_START = 0x40E80
ITEM_FORMAT = '>IBBBBHbbbbbbbbbbbbbbbbbbbbbb'
def read_item(index):
ITEM_SIZE = 0x20
ITEM_FORMAT = '>BBBBHbbbbbbbbbbbbbbbbbbbbbbBBBB'
item_start = 0x62310 + (index * ITEM_SIZE)
item_start = 0x6230C + (index * ITEM_SIZE)
item_end = item_start + ITEM_SIZE
return unpack_from(ITEM_FORMAT, read_rom(item_start, item_end))
for i in range(0, 130):
print(f"Length: 0x{calcsize(ITEM_FORMAT):X}")
ITEM_TYPE_NAME = {
0: "None",
1: "Sword",
2: "Greatsword",
3: "Thrusting Sword",
4: "1-Handed Hammer",
5: "2-Handed Hammer",
7: "Spear",
8: "Whip",
9: "Claw",
10: "Bow",
11: "Mace",
12: "Staff",
13: "Doll",
14: "Small Shield",
15: "Shield",
16: "Light Armor",
17: "Armor",
18: "Full Body Armor",
19: "Robe",
20: "Garment",
21: "Helm",
24: "Fan",
}
for i in range(1, 276):
# print(f"Item {i}:")
(field_0x0, element, field_0x2, field_0x3, field_0x4,
(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
name = read_rom(name_addr_diff, name_addr_diff + 32).split(b'\0', 1)[0]
(field_0xc, res_strike, res_wind, res_fire, res_earth, res_water,
res_holy, res_dark, *rest) = rest;
res_holy, res_dark, *rest) = rest
print(f"Element: {ELEMENT_NAME[element]}")
type_str = ITEM_TYPE_NAME[item_type] if item_type in ITEM_TYPE_NAME else f"Unknown({item_type})"
print(f"Name: {name}")
print(f"Type: {type_str}")
print(f"Element: {get_element_name(element)}")
print(f"STR: \t{strength} \tMEN: \t{mem}")
print(f"VIT: \t{vitality} \tAGI: \t{agility}")
print(f"INT: \t{intelligence} \tDEX: \t{dexterity}")
@ -33,5 +71,10 @@ for i in range(0, 130):
print(f"RES HOLY: \t{res_holy}")
print(f"RES DARK: \t{res_dark}")
print(field_0xc, rest)
for val in rest:
print(f"{val:X}")
print()
print("-------------------------------------------")
print()

View File

@ -23,6 +23,10 @@ ELEMENT_NAME = {
255: "Invalid"
}
def get_element_name(index):
return ELEMENT_NAME[index] if index in ELEMENT_NAME else f"Unknown({index})"
CLASS_NAME = {
0x01: "Soldier",
0x02: "Fighter",