generate common_structs.h from star rod database

This commit is contained in:
Alex Bates 2020-08-14 21:10:34 +01:00
parent afc0415a2c
commit 5e6173f25b
12 changed files with 1616 additions and 540 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "n64splitter"]
path = tools/n64splitter
url = https://github.com/ethteck/sm64tools.git
[submodule "tools/star-rod"]
path = tools/star-rod
url = https://github.com/nanaian/star-rod.git

View File

@ -9,18 +9,22 @@ BUILD_DIR = build
SRC_DIRS := src src/os
ASM_DIRS := asm asm/os
INCLUDE_DIRS := include include/PR
DATA_DIRS := bin
COMPRESSED_DIRS := yay0
MAP_DIRS := Map_Assets.FS
BGM_DIRS := bgm
STAR_ROD_STRUCT_DIRS := tools/star-rod/database/structs/ram tools/star-rod/database/structs/rom tools/star-rod/database/structs/wip
# Source code files
C_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
S_FILES := $(foreach dir,$(ASM_DIRS),$(wildcard $(dir)/*.s))
H_FILES := $(foreach dir,$(INCLUDE_DIRS),$(wildcard $(dir)/*.h))
DATA_FILES := $(foreach dir,$(DATA_DIRS),$(wildcard $(dir)/*.bin))
COMPRESSED_FILES := $(foreach dir,$(COMPRESSED_DIRS),$(wildcard $(dir)/*.yay0))
MAP_FILES := $(foreach dir,$(MAP_DIRS),$(wildcard $(dir)/*.FS))
BGM_FILES := $(foreach dir,$(BGM_DIRS),$(wildcard $(dir)/*.bgm))
STAR_ROD_STRUCT_FILES := $(foreach dir,$(STAR_ROD_STRUCT_DIRS),$(wildcard $(dir)/*.struct))
# Object files
O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \
@ -82,6 +86,9 @@ setup: clean submodules n64split split
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
include/common_structs.h: tools/starrod_structs_to_h.py $(STAR_ROD_STRUCT_FILES)
python3 tools/starrod_structs_to_h.py
$(BUILD_DIR):
mkdir $(BUILD_DIR)
@ -91,7 +98,7 @@ $(BUILD_DIR)/$(TARGET).elf: $(O_FILES) $(LD_SCRIPT)
$(BUILD_DIR)/%.o: %.s
$(AS) $(ASFLAGS) -o $@ $<
$(BUILD_DIR)/%.o: %.c
$(BUILD_DIR)/%.o: %.c $(H_FILES)
cpp $(CPPFLAGS) $< | $(CC) $(CFLAGS) -o - | $(OLD_AS) $(OLDASFLAGS) - -o $@
$(BUILD_DIR)/%.o: %.bin

File diff suppressed because it is too large Load Diff

View File

@ -8,4 +8,15 @@
#define UNK_FUN_PTR(name) void(*name)(void)
#define UNK_ARGS
typedef s32 bytecode[];
typedef struct {
/* 0x00 */ u32 raster; // swap these?
/* 0x04 */ u32 palette; // ^
/* 0x08 */ u16 startX;
/* 0x0A */ u16 startY;
/* 0x0C */ u16 width;
/* 0x0E */ u16 height;
} bg_header; // size = 0x10
#endif

View File

@ -16,7 +16,7 @@ INCLUDE_ASM(code_111f0_len_860, func_80035EEC);
void func_800360FC(void) {
game_status* gameStatus = *gGameStatusPtr;
if (gameStatus->unk_AC == 2) {
if (gameStatus->loadMenuState == 2) {
func_800E973C();
}
}
@ -28,11 +28,11 @@ void func_80036130(void) {
D_800A0942 = 0x14;
D_800A0944 = 0x00;
if (gameStatus->unk_88 != gameStatus->unk_86) {
gameStatus->unk_8A = 0x01;
gameStatus->unk_88 = gameStatus->unk_86;
if (gameStatus->prevArea != gameStatus->areaID) {
gameStatus->changedArea = 0x01;
gameStatus->prevArea = gameStatus->areaID;
} else {
gameStatus->unk_8A = 0;
gameStatus->changedArea = 0;
}
}

View File

@ -35,7 +35,7 @@ s32 func_8002ACDC(void) {
}
s32 heap_malloc(s32 size) {
if ((*gGameStatusPtr)->unk_70 == 0) {
if ((*gGameStatusPtr)->isBattle == 0) {
return general_heap_malloc(size);
} else {
return _heap_malloc(&D_803DA800, size);
@ -43,7 +43,7 @@ s32 heap_malloc(s32 size) {
}
s32 heap_free(s32 size) {
if ((*gGameStatusPtr)->unk_70 != 0) {
if ((*gGameStatusPtr)->isBattle != 0) {
return _heap_free(&D_803DA800, size);
} else {
return general_heap_free(size);
@ -56,7 +56,7 @@ INCLUDE_ASM(code_6000, collision_heap_malloc);
INCLUDE_ASM(code_6000, collision_heap_free);
/*s32 collision_heap_free(s32 size) {
s32 unk_70 = (*gGameStatusPtr)->unk_70;
s32 isBattle = (*gGameStatusPtr)->isBattle;
return _heap_free((unk_70 == 0) ? (&D_80268000) : (&D_803DA800), size);
return _heap_free((isBattle == 0) ? (&D_80268000) : (&D_803DA800), size);
}*/

View File

@ -31,15 +31,15 @@ void clear_player_data(void) {
playerData->merleeTurnCount = -1;
playerData->maxStarPower = 0;
playerData->specialBarsFilled = 0;
playerData->unk_292 = 0;
playerData->unk_292[0] = 0;
playerData->currentPartner = 0;
for (i = 0; i < ARRAY_COUNT(playerData->partners); i++) {
playerData->partners[i].enabled = 0;
playerData->partners[i].level = 0;
playerData->partners[i].unk_2 = 0;
playerData->partners[i].unk_4 = 0;
playerData->partners[i].unk_6 = 0;
playerData->partners[i].unk_02[0] = 0;
playerData->partners[i].unk_02[2] = 0;
playerData->partners[i].unk_02[4] = 0;
}
for (i = ARRAY_COUNT(playerData->keyItems) - 1; i >= 0; i--) {
@ -63,19 +63,19 @@ void clear_player_data(void) {
}
playerData->otherHitsTaken = 0;
playerData->unk_296 = 0;
playerData->unk_296[0] = 0;
playerData->hitsTaken = 0;
playerData->hitsBlocked = 0;
playerData->playerFirstStrikes = 0;
playerData->enemyFirstStrikes = 0;
playerData->powerBounces = 0;
playerData->battlesCount = 0;
playerData->unk_2A4 = 0;
playerData->unk_2A6 = 0;
playerData->unk_2A8 = 0;
playerData->unk_2AA = 0;
playerData->unk_2AC = 0;
playerData->unk_2B0 = 0;
playerData->unk_2A4[0x0] = 0;
playerData->unk_2A4[0x2] = 0;
playerData->unk_2A4[0x4] = 0;
playerData->unk_2A4[0x8] = 0;
playerData->unk_2A4[0xA] = 0;
playerData->unk_2A4[0xC] = 0;
playerData->idleFrameCounter = 0;
playerData->totalCoinsEarned = 0;
playerData->frameCounter = 0;
@ -84,10 +84,10 @@ void clear_player_data(void) {
for (i = 0; i < ARRAY_COUNT(playerData->unk_2C4); i++) {
playerData->unk_2C4[i] = 0;
playerData->unk_2F4[i] = 0;
playerData->unk_2C4[i + 0xB0] = 0;
}
playerData->unk_328 = 0;
playerData->unk_2C4[0x64] = 0;
playerData->starPiecesCollected = 0;
playerData->jumpGamePlays = 0;
playerData->jumpGameTotal = 0;
@ -283,7 +283,7 @@ void coin_counter_draw_content(UNK_TYPE arg0, s32 posX, s32 posY) {
ui_status* uiStatus = &gUIStatus;
s32 iconIndex;
if ((gPlayerData.coins != uiStatus->displayCoins) && (((*gGameStatusPtr)->unk_134 % 3) == 0)) {
if ((gPlayerData.coins != uiStatus->displayCoins) && (((*gGameStatusPtr)->frameCounter % 3) == 0)) {
play_sound(0x211);
}
@ -304,9 +304,9 @@ void update_coin_counter(void) {
do {} while(0); // Needed to match
if (uiStatus->unk_6D != 0) {
uiStatus->unk_6D -= 1;
if (((uiStatus->unk_6D << 24) == 0) && (uiStatus->iconIndex12 >= 0)) {
if (uiStatus->unk_6C[1] != 0) {
uiStatus->unk_6C[1] -= 1;
if (((uiStatus->unk_6C[1] << 24) == 0) && (uiStatus->iconIndex12 >= 0)) {
free_icon(uiStatus->iconIndex12);
free_icon(uiStatus->iconIndex13);
uiStatus->iconIndex12 = -1;
@ -314,24 +314,24 @@ void update_coin_counter(void) {
D_8010CD12 = 0;
}
if (uiStatus->unk_6C != 0) {
if ((uiStatus->displayCoins == playerData->coins) && (uiStatus->unk_6C > 30)) {
uiStatus->unk_6C = 30;
if (uiStatus->unk_6C[0] != 0) {
if ((uiStatus->displayCoins == playerData->coins) && (uiStatus->unk_6C[0] > 30)) {
uiStatus->unk_6C[0] = 30;
}
if ((uiStatus->displayCoins == playerData->coins) || (uiStatus->unk_6C <= 30)) {
uiStatus->unk_6C -= 1;
if (uiStatus->unk_6C == 0) {
if ((uiStatus->displayCoins == playerData->coins) || (uiStatus->unk_6C[0] <= 30)) {
uiStatus->unk_6C[0] -= 1;
if (uiStatus->unk_6C[0] == 0) {
func_80147E7C(20, &D_80147574);
uiStatus->unk_6D = 15;
uiStatus->unk_6C[1] = 15;
D_8010CD10 = 0;
D_8010CD12 = 1;
uiStatus->iconIndex12 = uiStatus->iconIndex10;
uiStatus->iconIndex13 = uiStatus->iconIndex11;
uiStatus->displayCoins = playerData->coins;
if (uiStatus->unk_6E > -1) {
uiStatus->ignoreChanges = uiStatus->unk_6E;
uiStatus->unk_6E = -1;
if (uiStatus->unk_6C[2] > -1) {
uiStatus->ignoreChanges = uiStatus->unk_6C[2];
uiStatus->unk_6C[2] = -1;
}
}
}
@ -350,13 +350,13 @@ void show_coin_counter(void) {
free_icon(uiStatus->iconIndex11);
uiStatus->iconIndex12 = -1;
}
uiStatus->unk_6C = 0;
uiStatus->unk_6D = 0;
uiStatus->unk_6C[0] = 0;
uiStatus->unk_6C[1] = 0;
*coinCounterUnk = 0;
D_8010CD12 = 0;
}
if (uiStatus->unk_6C == 0) {
if (uiStatus->unk_6C[0]== 0) {
func_80147CC8(0x14, 0x20, 0xa4, 0x40, 0x14, 0x15, &D_800E92D8, 0, -1);
func_80147E7C(0x14, &D_80147474);
index = create_icon(&D_80109270);
@ -367,10 +367,10 @@ void show_coin_counter(void) {
uiStatus->iconIndex11 = index;
set_icon_flags(index, 0x80);
func_80144EFC(index, 0xff, 0xff, 0xff);
uiStatus->unk_6C = 0;
uiStatus->unk_6C[0] = 0;
if (uiStatus->unk_6E < 0) {
uiStatus->unk_6E = uiStatus->ignoreChanges;
if (uiStatus->unk_6C[2] < 0) {
uiStatus->unk_6C[2] = uiStatus->ignoreChanges;
}
uiStatus->ignoreChanges = 1;
@ -382,16 +382,16 @@ void show_coin_counter(void) {
void hide_coin_counter(void) {
ui_status* uiStatus = &gUIStatus;
if ((D_8010CD10 != 0) && (uiStatus->unk_6C == 0)) {
uiStatus->unk_6C = 60;
if ((D_8010CD10 != 0) && (uiStatus->unk_6C[0]== 0)) {
uiStatus->unk_6C[0] = 60;
}
}
void func_800E96C8(void) {
ui_status* uiStatus = &gUIStatus;
if ((D_8010CD10 != 0) && (uiStatus->unk_6C == 0)) {
uiStatus->unk_6C = 1;
if ((D_8010CD10 != 0) && (uiStatus->unk_6C[0]== 0)) {
uiStatus->unk_6C[0]= 1;
}
}
@ -415,7 +415,7 @@ void open_status_menu_long(void) {
if (uiStatus->hidden) {
uiStatus->showTimer = 210;
uiStatus->hidden = 0;
uiStatus->unk_3B = 1;
uiStatus->unk_3B[0] = 1;
}
}
@ -425,7 +425,7 @@ void open_status_menu_short(void) {
if (uiStatus->hidden) {
uiStatus->showTimer = 105;
uiStatus->hidden = 0;
uiStatus->unk_3B = 1;
uiStatus->unk_3B[0] = 1;
}
}
@ -435,7 +435,7 @@ void func_800E97B8(void) {
if (uiStatus->hidden != 1) {
uiStatus->hidden = 1;
uiStatus->showTimer = 0;
uiStatus->unk_3B = 1;
uiStatus->unk_3B[0] = 1;
}
}
@ -446,8 +446,8 @@ void func_800E97E4(void) {
uiStatus->ignoreChanges = 0;
uiStatus->showTimer = 0;
uiStatus->hidden = 1;
uiStatus->unk_3B = 0;
uiStatus->unk_3C = 0;
uiStatus->unk_3B[0] = 0;
uiStatus->unk_3B[1] = 0;
}
void func_800E9810(void) {
@ -457,24 +457,24 @@ void func_800E9810(void) {
uiStatus->drawPosY = 0;
uiStatus->ignoreChanges = 0;
uiStatus->hidden = 0;
uiStatus->unk_3B = 1;
uiStatus->unk_3C = 0;
uiStatus->unk_3B[0] = 1;
uiStatus->unk_3B[1] = 0;
}
void func_800E983C(void) {
gUIStatus.unk_45 = 0;
gUIStatus.unk_45[0] = 0;
}
void func_800E984C(void) {
gUIStatus.unk_45 = 1;
gUIStatus.unk_45[0] = 1;
}
s32 func_800E9860(void) {
ui_status* uiStatus = &gUIStatus;
ui_status* uiStatus2 = &gUIStatus;
s32 ret = 1 - uiStatus->unk_45;
s32 ret = 1 - uiStatus->unk_45[0];
if (uiStatus->unk_46 != 0) {
if (uiStatus->unk_45[1] != 0) {
ret = 0;
}
if (uiStatus2->ignoreChanges) {
@ -501,15 +501,15 @@ void status_menu_disable_ignore_changes(void) {
s32 func_800E98D4(void) {
ui_status* uiStatus = &gUIStatus;
return uiStatus->unk_46 + uiStatus->ignoreChanges;
return uiStatus->unk_45[1] + uiStatus->ignoreChanges;
}
void func_800E98EC(void) {
gUIStatus.unk_46 = 1;
gUIStatus.unk_45[1] = 1;
}
void func_800E9900(void) {
gUIStatus.unk_46 = 0;
gUIStatus.unk_45[1] = 0;
}
s32 is_status_menu_visible(void) {
@ -521,7 +521,7 @@ void status_menu_start_blinking_hp(void) {
ui_status* uiStatus = &gUIStatus;
ui_status* uiStatus2 = &gUIStatus;
if (gameStatus->unk_70 == 0) {
if (gameStatus->mainScriptID == 0) {
uiStatus->hpBlinkTimer = 120;
}
@ -546,7 +546,7 @@ void status_menu_start_blinking_fp(void) {
ui_status* uiStatus = &gUIStatus;
ui_status* uiStatus2 = &gUIStatus;
if (gameStatus->unk_70 == 0) {
if (gameStatus->mainScriptID == 0) {
uiStatus->fpBlinkTimer = 120;
}
@ -570,7 +570,7 @@ void status_menu_start_blinking_coins(void) {
ui_status* uiStatus = &gUIStatus;
ui_status* uiStatus2 = &gUIStatus;
if (gameStatus->unk_70 == 0) {
if (gameStatus->mainScriptID == 0) {
uiStatus->coinsBlinkTimer = 120;
}
@ -666,16 +666,15 @@ void sync_status_menu(void) {
void reset_status_menu(void) {
player_data* playerData = &gPlayerData;
ui_status* uiStatus = &gUIStatus;
s32 i;
uiStatus->drawPosX = 12;
uiStatus->drawPosY = -100;
uiStatus->hidden = 0;
uiStatus->showTimer = 210;
uiStatus->unk_3B = 0;
uiStatus->unk_3B[0] = 0;
uiStatus->ignoreChanges = 0;
uiStatus->unk_45 = 0;
uiStatus->unk_46 = 0;
uiStatus->unk_45[0] = 0;
uiStatus->unk_45[1] = 0;
uiStatus->hpBlinking = 0;
uiStatus->hpBlinkCounter = 0;
uiStatus->hpBlinkTimer = 0;
@ -690,22 +689,18 @@ void reset_status_menu(void) {
uiStatus->disabled = 0;
uiStatus->starpointsBlinking = 0;
uiStatus->starpointsBlinkCounter = 0;
uiStatus->unk_6E = -1;
uiStatus->unk_6C[2] = -1;
uiStatus->displayHP = playerData->curHP;
uiStatus->displayFP = playerData->curFP;
uiStatus->displayCoins = playerData->coins;
uiStatus->displayStarpoints = playerData->starPoints;
uiStatus->displaySP = playerData->specialBarsFilled;
uiStatus->unk_3C = 0;
for (i = 0; i < 2; i++) {
func_801452B4(uiStatus->hpIconIndexes[i], uiStatus->hpIconIndexes[i]);
}
for (i = 0; i < 2; i++) {
func_801452B4(uiStatus->fpIconIndexes[i], uiStatus->fpIconIndexes[i]);
}
uiStatus->unk_3B[1] = 0;
func_801452B4(uiStatus->hpIconIndex, uiStatus->hpIconIndex);
func_801452B4(uiStatus->heartIconIndex, uiStatus->heartIconIndex);
func_801452B4(uiStatus->fpIconIndex, uiStatus->fpIconIndex);
func_801452B4(uiStatus->flowerIconIndex, uiStatus->flowerIconIndex);
func_801452B4(uiStatus->coinIconIndex, uiStatus->coinIconIndex);
func_801452B4(uiStatus->coinIconIndex2, uiStatus->coinIconIndex2);
func_801452B4(uiStatus->starpointsIconIndex, uiStatus->starpointsIconIndex);
@ -807,14 +802,14 @@ void add_SP(s32 amt) {
s32 phi_v1;
s32 blah;
uiStatus->unk_57 = 1;
uiStatus->unk_58 = 60;
uiStatus->unk_57[0] = 1;
uiStatus->unk_57[1] = 60;
phi_v1 = playerData->specialBarsFilled;
if (phi_v1 < 0) {
phi_v1 = playerData->specialBarsFilled + 31;
}
uiStatus->unk_59 = phi_v1 >> 5;
uiStatus->unk_57[2] = phi_v1 >> 5;
playerData->specialBarsFilled += amt;

View File

@ -9,7 +9,7 @@ INCLUDE_ASM(code_dbd70_len_700, clear_trigger_data);
//INCLUDE_ASM(code_dbd70_len_700, init_trigger_list);
void init_trigger_list(void) {
if ((*gGameStatusPtr)->unk_70 == 0) {
if ((*gGameStatusPtr)->isBattle == 0) {
*gCurrentTriggerListPtr = gTriggerList1;
} else {
*gCurrentTriggerListPtr = gTriggerList2;

View File

@ -26,30 +26,30 @@ void func_80145DF8(void) {
D_801595A0 = 0;
D_8014F12F = 0;
gameStatus->unk_15C = 0xB4;
gameStatus->unk_148 &= 0xF0;
gameStatus->unk_15C[0] = 0xB4;
gameStatus->enableBackground &= 0xF0;
}
void read_background_size(bg_header *bg) {
game_status* gameStatus = *gGameStatusPtr;
gameStatus->unk_14E = bg->width;
gameStatus->unk_150 = bg->height;
gameStatus->unk_14A = bg->startX;
gameStatus->unk_14C = bg->startY;
gameStatus->unk_154 = bg->palette;
gameStatus->unk_158 = bg->raster;
gameStatus->unk_148 |= 1;
gameStatus->backgroundMaxW = bg->width;
gameStatus->backgroundMaxH = bg->height;
gameStatus->backgroundMinW = bg->startX;
gameStatus->backgroundMinH = bg->startY;
gameStatus->backgroundRaster = bg->palette; // wtf?
gameStatus->backgroundPalette = bg->raster;
gameStatus->enableBackground |= 1;
}
void set_background_size(s16 startX, s16 startY, s16 sizeX, s16 sizeY) {
game_status* gameStatus = *gGameStatusPtr;
gameStatus->unk_148 &= ~1;
gameStatus->unk_14E = startX;
gameStatus->unk_150 = startY;
gameStatus->unk_14A = sizeX;
gameStatus->unk_14C = sizeY;
gameStatus->enableBackground &= ~1;
gameStatus->backgroundMaxW = startX;
gameStatus->backgroundMaxH = startY;
gameStatus->backgroundMinW = sizeX;
gameStatus->backgroundMinH = sizeY;
}
u16 func_80145E98(s32 arg0, s32 arg1, s32 arg2) {

View File

@ -3,24 +3,24 @@
void func_800337D0(s16 new_alpha) {
game_status* gameStatus = *gGameStatusPtr;
gameStatus->boot_alpha = new_alpha;
gameStatus->bootAlpha = new_alpha;
}
void func_800337E0(s16 arg0) {
game_status* gameStatus = *gGameStatusPtr;
gameStatus->boot_red = arg0;
gameStatus->boot_green = arg0;
gameStatus->boot_blue = arg0;
gameStatus->bootRed = arg0;
gameStatus->bootGreen = arg0;
gameStatus->bootBlue = arg0;
}
s16 func_800337F8(subtract_val) {
game_status* gameStatus = *gGameStatusPtr;
if (gameStatus->boot_alpha != 0) {
gameStatus->boot_alpha -= subtract_val;
if (gameStatus->boot_alpha << 16 < 0) {
gameStatus->boot_alpha = 0;
if (gameStatus->bootAlpha != 0) {
gameStatus->bootAlpha -= subtract_val;
if (gameStatus->bootAlpha << 16 < 0) {
gameStatus->bootAlpha = 0;
}
} else {
return 1;
@ -31,10 +31,10 @@ s16 func_800337F8(subtract_val) {
s16 func_80033830(add_val) {
game_status* gameStatus = *gGameStatusPtr;
if (gameStatus->boot_alpha != 0xFF) {
gameStatus->boot_alpha += add_val;
if ((gameStatus->boot_alpha > 0xFF)) {
gameStatus->boot_alpha = 0xFF;
if (gameStatus->bootAlpha != 0xFF) {
gameStatus->bootAlpha += add_val;
if ((gameStatus->bootAlpha > 0xFF)) {
gameStatus->bootAlpha = 0xFF;
}
} else {
return 1;
@ -44,8 +44,8 @@ s16 func_80033830(add_val) {
void func_80033874(void) {
func_80137D88(0, (*gGameStatusPtr)->boot_alpha);
func_80137E10(0, (*gGameStatusPtr)->boot_blue, (*gGameStatusPtr)->boot_green, (*gGameStatusPtr)->boot_red);
func_80137D88(0, (*gGameStatusPtr)->bootAlpha);
func_80137E10(0, (*gGameStatusPtr)->bootBlue, (*gGameStatusPtr)->bootGreen, (*gGameStatusPtr)->bootRed);
}
void start_battle_countdown(void) {

1
tools/star-rod Submodule

@ -0,0 +1 @@
Subproject commit 3a32d3d6dda7374e4f32ae86530444e45956d803

197
tools/starrod_structs_to_h.py Executable file
View File

@ -0,0 +1,197 @@
#!/usr/bin/env python3
from os import path
from glob import glob
import re
DIR = path.dirname(__file__)
SR_DATABASE = path.join(DIR, "star-rod/database")
# SR currently defines a struct with the "name" struct. This causes
# problems, so we'll call it the following instead.
STRUCT_STRUCT_ALIAS = "texture_header"
STRUCT_FILES = (
# structs which need to be forward declared (because they're used
# without indirection in other structs)
glob(path.join(SR_DATABASE, f"structs/**/matrix4f.struct")) +
glob(path.join(SR_DATABASE, f"structs/**/matrix4s.struct")) +
glob(path.join(SR_DATABASE, f"structs/**/cam_pos_settings.struct")) +
glob(path.join(SR_DATABASE, f"structs/**/partner_data.struct")) +
# other structs
glob(path.join(SR_DATABASE, f"structs/**/*.struct"))
)
def convert_type(type, structs):
size = 1
suffix = ""
# replace basic types
basic_types = [
("ubyte", "u8", 1),
("byte", "s8", 1),
("uchar", "u8", 1),
("char", "s8", 1),
("ushort", "u16", 2),
("short", "s16", 2),
("uint", "u32", 4),
("int", "s32", 4),
("ulong", "u64", 8),
("long", "s64", 8),
("float", "f32", 4),
("double", "f64", 8),
("ptr", "UNK_PTR", 4),
("struct", f"struct {STRUCT_STRUCT_ALIAS}", 0x30),
]
for name, size in structs:
basic_types.append((name, f"struct {name}", size))
for sr_name, decomp_name, basic_size in basic_types:
match = re.search(f"(\\b|^)({sr_name})(\\b|$)", type)
if match:
size = basic_size
start, end = match.span(2)
type = type[:start] + decomp_name + type[end:]
break
# array
while array_match := re.search(r"\[(([0-9]+)`|([a-fA-F0-9]+))\]", type):
bin_len_str = array_match.group(2)
hex_len_str = array_match.group(3)
array_len = int(bin_len_str) if bin_len_str else int(hex_len_str, 16)
size *= array_len
suffix += f"[{array_len}]"
# strip match from type
start, end = array_match.span()
type = type[:start] + type[end:]
# pointer
if "*" in type:
size = 4
return type, size, suffix
# read struct names and their sizes in advance
structs = []
for filename in STRUCT_FILES:
struct_name = path.splitext(path.basename(filename))[0]
if struct_name == "struct":
struct_name = STRUCT_STRUCT_ALIAS
with open(filename) as file:
for line in file.readlines():
if line.startswith("%"):
continue
parts = [x.strip() for x in line.split(":")]
if len(parts) == 0:
continue
if parts[0] == "size":
struct_size = int(parts[1], 16)
structs.append((struct_name, struct_size))
continue
with open(path.join(DIR, f"../include/common_structs.h"), "w") as h:
h.write(f"""#ifndef _COMMON_STRUCTS_H_
#define _COMMON_STRUCTS_H_
#include "ultra64.h"
#include "types.h"
""")
# write all structs out to common_structs.h
struct_names_seen = []
for filename in STRUCT_FILES:
struct_name = path.splitext(path.basename(filename))[0]
struct_size = None
offset_len = 2 # string length for hex offsets
if struct_name == "struct":
struct_name = STRUCT_STRUCT_ALIAS
# avoid repeat declarations
if struct_name.startswith("_") or struct_name.startswith("OS") or "." in struct_name or struct_name == "sprite":
continue
if struct_name in struct_names_seen:
continue
struct_names_seen.append(struct_name)
h.write(f"typedef struct {struct_name} {{\n")
with open(filename) as file:
in_fields = False
cur_offset = 0
def update_offset(offset):
global cur_offset
delta = offset - cur_offset
ofs_str = ("%X" % cur_offset).zfill(2)
ofs_str_z = ofs_str.zfill(offset_len)
# insert unknown char array
if delta == 1:
h.write(f" /* 0x{ofs_str_z} */ char unk_{ofs_str};\n")
elif delta > 0:
h.write(f" /* 0x{ofs_str_z} */ char unk_{ofs_str}[{delta}];\n")
cur_offset += delta
for line in file.readlines():
# read and strip line comment
comment = re.search(r"%(.*)$", line)
if comment:
pos = comment.span()[0]
line = line[0:pos]
comment = comment.group(1).strip()
parts = [x.strip() for x in line.split(":")]
if len(parts) == 0:
continue
if in_fields:
if parts[0] == "}":
in_fields = False
else:
offset, name, type = parts
# clean name
name = re.sub(r"[^a-zA-Z0-9_]", "", name)
offset = int(offset, 16)
ofs_str = ("%X" % offset).zfill(offset_len)
update_offset(offset)
if type == "code":
h.write(f" /* 0x{ofs_str} */ UNK_FUN_PTR({name});")
cur_offset += 4
else:
type, size, suffix = convert_type(type, structs)
h.write(f" /* 0x{ofs_str} */ {type} {name}{suffix};")
cur_offset += size
if comment:
h.write(f" /* {comment} */")
h.write("\n")
else:
if parts[0] == "size":
struct_size = int(parts[1], 16)
structs.append((struct_name, struct_size))
offset_len = max(2, len(parts[1]))
elif parts[0] == "{":
in_fields = True
update_offset(struct_size)
h.write(f"}} {struct_name}; // size = 0x{('%X' % struct_size).zfill(offset_len)}\n\n")
h.write("#endif\n")