Initial version of enum extractor script

This commit is contained in:
Tal Hayon 2022-05-13 18:44:14 +03:00
parent b675bce0d1
commit 2062499f0c
14 changed files with 112 additions and 24 deletions

1
.gitignore vendored
View File

@ -22,6 +22,7 @@ tools/binutils
# scripts # scripts
*.py *.py
!tools/extract_include_enum.py
*.pl *.pl
# graphics # graphics

View File

@ -57,15 +57,18 @@ DATA_ASM_SUBDIR = data
SONG_SUBDIR = sound/songs SONG_SUBDIR = sound/songs
MID_SUBDIR = sound/songs/midi MID_SUBDIR = sound/songs/midi
ASSET_SUBDIR = assets ASSET_SUBDIR = assets
ENUM_INCLUDE_SUBDIR = enum_include
C_BUILDDIR = $(OBJ_DIR)/$(C_SUBDIR) C_BUILDDIR = $(OBJ_DIR)/$(C_SUBDIR)
ASM_BUILDDIR = $(OBJ_DIR)/$(ASM_SUBDIR) ASM_BUILDDIR = $(OBJ_DIR)/$(ASM_SUBDIR)
ASM_ENUM_INCLUDE_DIR = $(ASM_BUILDDIR)/$(ENUM_INCLUDE_SUBDIR)
DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR) DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR)
SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR) SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR)
MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR) MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR)
ASSET_BUILDDIR = $(OBJ_DIR)/$(ASSET_SUBDIR) ASSET_BUILDDIR = $(OBJ_DIR)/$(ASSET_SUBDIR)
PREPROC_INC_PATHS = $(ASSET_BUILDDIR) $(ASM_ENUM_INCLUDE_DIR)
ASFLAGS := -mcpu=arm7tdmi --defsym $(GAME_VERSION)=1 --defsym REVISION=$(REVISION) --defsym $(GAME_LANGUAGE)=1 -I $(ASSET_SUBDIR) -I $(ASSET_BUILDDIR) ASFLAGS := -mcpu=arm7tdmi --defsym $(GAME_VERSION)=1 --defsym REVISION=$(REVISION) --defsym $(GAME_LANGUAGE)=1 -I $(ASSET_SUBDIR) -I $(ASSET_BUILDDIR) -I $(ASM_ENUM_INCLUDE_DIR)
CC1 := tools/agbcc/bin/agbcc CC1 := tools/agbcc/bin/agbcc
override CFLAGS += -O2 -Wimplicit -Wparentheses -Werror -Wno-multichar -g3 override CFLAGS += -O2 -Wimplicit -Wparentheses -Werror -Wno-multichar -g3
@ -90,6 +93,7 @@ SCANINC := tools/bin/scaninc
PREPROC := tools/bin/preproc PREPROC := tools/bin/preproc
FIX := tools/bin/gbafix FIX := tools/bin/gbafix
ASSET_PROCESSOR := tools/bin/asset_processor ASSET_PROCESSOR := tools/bin/asset_processor
ENUM_PROCESSOR := tools/extract_include_enum.py
ASSET_CONFIGS = assets/assets.json assets/gfx.json assets/map.json assets/samples.json assets/sounds.json ASSET_CONFIGS = assets/assets.json assets/gfx.json assets/map.json assets/samples.json assets/sounds.json
TRANSLATIONS = translations/USA.bin translations/English.bin translations/French.bin translations/German.bin translations/Spanish.bin translations/Italian.bin TRANSLATIONS = translations/USA.bin translations/English.bin translations/French.bin translations/German.bin translations/Spanish.bin translations/Italian.bin
@ -142,10 +146,13 @@ SONG_OBJS := $(patsubst $(SONG_SUBDIR)/%.s,$(SONG_BUILDDIR)/%.o,$(SONG_SRCS))
MID_SRCS := $(wildcard $(MID_SUBDIR)/*.mid) MID_SRCS := $(wildcard $(MID_SUBDIR)/*.mid)
MID_OBJS := $(patsubst $(MID_SUBDIR)/%.mid,$(MID_BUILDDIR)/%.o,$(MID_SRCS)) MID_OBJS := $(patsubst $(MID_SUBDIR)/%.mid,$(MID_BUILDDIR)/%.o,$(MID_SRCS))
ENUM_ASM_SRCS := $(wildcard include/*.h)
ENUM_ASM_HEADERS := $(patsubst include/%.h,$(ASM_ENUM_INCLUDE_DIR)/%.inc,$(ENUM_ASM_SRCS))
OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) $(SONG_OBJS) $(MID_OBJS) OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) $(SONG_OBJS) $(MID_OBJS)
OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS)) OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS))
SUBDIRS := $(sort $(dir $(OBJS))) SUBDIRS := $(sort $(dir $(OBJS) $(ENUM_ASM_HEADERS)))
$(shell mkdir -p $(SUBDIRS)) $(shell mkdir -p $(SUBDIRS))
@ -253,16 +260,19 @@ $(ASM_BUILDDIR)/%.o: asm_dep = $(shell $(SCANINC) -I . $(ASM_SUBDIR)/$*.s)
endif endif
$(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s $$(asm_dep) $(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s $$(asm_dep)
$(PREPROC) $(BUILD_NAME) $< | $(AS) $(ASFLAGS) -o $@ $(PREPROC) $(BUILD_NAME) $< -- $(PREPROC_INC_PATHS) | $(AS) $(ASFLAGS) -o $@
$(ASM_ENUM_INCLUDE_DIR)/%.inc: include/%.h
$(ENUM_PROCESSOR) $< $(CC) "-D__attribute__(x)=" "-E" "-nostdinc" "-Itools/agbcc" "-Itools/agbcc/include" "-iquote include" > $@
ifeq ($(NODEP),1) ifeq ($(NODEP),1)
$(DATA_ASM_BUILDDIR)/%.o: data_dep := $(DATA_ASM_BUILDDIR)/%.o: data_dep :=
else else
$(DATA_ASM_BUILDDIR)/%.o: data_dep = $(shell $(SCANINC) -I . -I $(ASSET_SUBDIR) -I $(ASSET_BUILDDIR) $(DATA_ASM_SUBDIR)/$*.s) $(DATA_ASM_BUILDDIR)/%.o: data_dep = $(shell $(SCANINC) -I . -I $(ASSET_SUBDIR) -I $(ASSET_BUILDDIR) -I $(ASM_ENUM_INCLUDE_DIR) $(DATA_ASM_SUBDIR)/$*.s)
endif endif
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $$(data_dep) $(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $$(data_dep) $(ENUM_ASM_HEADERS)
$(PREPROC) $(BUILD_NAME) $< charmap.txt | $(CPP) -I include -nostdinc -undef -Wno-unicode - | $(AS) $(ASFLAGS) -o $@ $(PREPROC) $(BUILD_NAME) $< charmap.txt -- $(PREPROC_INC_PATHS) | $(CPP) -I include -nostdinc -undef -Wno-unicode - | $(AS) $(ASFLAGS) -o $@
$(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s $(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s
$(AS) $(ASFLAGS) -I sound -o $@ $< $(AS) $(ASFLAGS) -I sound -o $@ $<

View File

@ -484,9 +484,14 @@
.2byte \s .2byte \s
.endm .endm
.macro MessageNoOverlap s:req .macro MessageNoOverlap a:req, b
.2byte 0x085b .2byte 0x085b
.2byte \s .ifnb \b
.byte \b
.byte \a
.else
.2byte \a
.endif
.endm .endm
.macro MessageFromTargetPos a:req, b:req .macro MessageFromTargetPos a:req, b:req

View File

@ -3,6 +3,9 @@
.include "asm/macros/scripts.inc" .include "asm/macros/scripts.inc"
.include "flags.inc"
.include "message.inc"
.syntax unified .syntax unified
.text .text

View File

@ -5,7 +5,7 @@ SCRIPT_START script_Din
SetAnimationState 0x0004 SetAnimationState 0x0004
DoPostScriptAction 0x0001 DoPostScriptAction 0x0001
DoPostScriptAction 0x000a DoPostScriptAction 0x000a
CheckGlobalFlag 0x0047 CheckGlobalFlag GOMAN_RENTED_HOUSE
JumpIf script_08011CC2 JumpIf script_08011CC2
EndBlock EndBlock
script_08011C9A: script_08011C9A:
@ -17,7 +17,7 @@ script_08011C9A:
SetPlayerIdle SetPlayerIdle
FacePlayer FacePlayer
DoPostScriptAction 0x0000 DoPostScriptAction 0x0000
MessageNoOverlap 0x4515 MessageNoOverlap TEXT_HAPPY_HEARTH, 0x15
WaitUntilTextboxCloses WaitUntilTextboxCloses
EnablePlayerControl EnablePlayerControl
SetAnimationState 0x0004 SetAnimationState 0x0004
@ -26,9 +26,9 @@ script_08011C9A:
script_08011CC2: script_08011CC2:
EndBlock EndBlock
BeginBlock BeginBlock
CheckGlobalFlag 0x002c CheckGlobalFlag RENTED_HOUSE_NAYRU
JumpIf script_08011C9A JumpIf script_08011C9A
CheckGlobalFlag 0x002d CheckGlobalFlag RENTED_HOUSE_FARORE
JumpIf script_08011C9A JumpIf script_08011C9A
CheckEntityInteractType CheckEntityInteractType
JumpIfNot script_08011CC2 JumpIfNot script_08011CC2
@ -36,7 +36,7 @@ script_08011CC2:
SetPlayerIdle SetPlayerIdle
FacePlayer FacePlayer
DoPostScriptAction 0x0000 DoPostScriptAction 0x0000
MessageNoOverlap 0x3105 MessageNoOverlap TEXT_GORMAN_ORACLES, 0x5
WaitUntilTextboxCloses WaitUntilTextboxCloses
CheckTextboxResult CheckTextboxResult
JumpIf script_08011D0E JumpIf script_08011D0E
@ -51,9 +51,9 @@ script_08011D00:
FacePlayer FacePlayer
DoPostScriptAction 0x0000 DoPostScriptAction 0x0000
script_08011D0E: script_08011D0E:
MessageNoOverlap 0x3108 MessageNoOverlap TEXT_GORMAN_ORACLES, 0x8
WaitUntilTextboxCloses WaitUntilTextboxCloses
SetGlobalFlag 0x002b SetGlobalFlag RENTED_HOUSE_DIN
EnablePlayerControl EnablePlayerControl
SetAnimationState 0x0004 SetAnimationState 0x0004
DoPostScriptAction 0x0001 DoPostScriptAction 0x0001

View File

@ -1,6 +1,9 @@
#ifndef SPRITEDATA_H #ifndef SPRITEDATA_H
#define SPRITEDATA_H #define SPRITEDATA_H
#include "gba/types.h"
#include "entity.h"
// Definition for enemies and projectiles // Definition for enemies and projectiles
typedef struct EnemyDefinition { typedef struct EnemyDefinition {
u16 gfx; u16 gfx;

View File

@ -1,6 +1,8 @@
#ifndef TMC_DROPTABLES_H #ifndef TMC_DROPTABLES_H
#define TMC_DROPTABLES_H #define TMC_DROPTABLES_H
#include "global.h"
typedef union { typedef union {
struct { struct {
s16 none; s16 none;

View File

@ -1,5 +1,8 @@
#ifndef HITBOX_H #ifndef HITBOX_H
#define HITBOX_H #define HITBOX_H
#include "entity.h"
extern const Hitbox gHitbox_0; extern const Hitbox gHitbox_0;
extern const Hitbox gHitbox_1; extern const Hitbox gHitbox_1;
extern const Hitbox gHitbox_2; extern const Hitbox gHitbox_2;

View File

@ -2,6 +2,7 @@
#define KINSTONE_H #define KINSTONE_H
#include "global.h" #include "global.h"
#include "entity.h"
extern void sub_08018C58(u32); extern void sub_08018C58(u32);

View File

@ -1,6 +1,8 @@
#ifndef PROJECTILE_H #ifndef PROJECTILE_H
#define PROJECTILE_H #define PROJECTILE_H
#include "entity.h"
Entity* CreateProjectile(u32); Entity* CreateProjectile(u32);
bool32 IsProjectileOffScreen(Entity*); bool32 IsProjectileOffScreen(Entity*);

48
tools/extract_include_enum.py vendored Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env python3
import argparse
import pycparser
class EnumVisitor(pycparser.c_ast.NodeVisitor):
def __init__(self, file):
self.file = file
def visit_Enum(self, enum):
if enum.coord.file != self.file:
return
next_value = 0
for enum_value in enum.values.enumerators:
if enum_value.value is not None:
# Unsure how to handle assignment of non-numerical value - maybe leave as is?
if isinstance(enum_value.value, pycparser.c_ast.Constant):
next_value_str = enum_value.value.value
next_value = int(next_value_str, 16) if "x" in next_value_str else int(next_value_str)
print(f".set {enum_value.name}, {next_value}")
next_value += 1
else:
print(f".set {enum_value.name}, {next_value}")
next_value += 1
def main():
parser = argparse.ArgumentParser(description="Prints out enum values for assembler.", prefix_chars='+')
parser.add_argument("file", help="input include file")
parser.add_argument("cpp", help="c pre-processor")
parser.add_argument("cppflags", help="c pre-processor flags", nargs="*")
args = parser.parse_args()
ast = pycparser.parse_file(args.file, True, args.cpp, args.cppflags)
# print guard
guard_prefix = args.file.replace("include/", "")
guard_prefix = guard_prefix.replace(".", "_")
guard_name = guard_prefix.upper() + "_ASM_INC"
print(f".ifndef {guard_name}")
print(f".set {guard_name}, 1\n")
visitor = EnumVisitor(args.file)
visitor.visit(ast)
print(f"\n.endif @ {guard_name}")
if __name__ == '__main__':
main()

View File

@ -30,13 +30,12 @@
AsmFile::AsmFile(std::string filename) : m_filename(filename) { AsmFile::AsmFile(std::string filename) : m_filename(filename) {
FILE* fp = std::fopen(filename.c_str(), "rb"); FILE* fp = std::fopen(filename.c_str(), "rb");
if (fp == NULL) { for (int i = 0; fp == NULL && i < g_incPaths.size(); i++) {
// The include might be an asset. fp = std::fopen((g_incPaths[i] + "/" + filename).c_str(), "rb");
fp = std::fopen(("build/" + g_buildName + "/assets/" + filename).c_str(), "rb"); }
if (fp == NULL) if (fp == NULL)
FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str()); FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str());
}
std::fseek(fp, 0, SEEK_END); std::fseek(fp, 0, SEEK_END);

View File

@ -19,7 +19,9 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <string> #include <string>
#include <cstring>
#include <stack> #include <stack>
#include <vector>
#include "preproc.h" #include "preproc.h"
#include "asm_file.h" #include "asm_file.h"
#include "c_file.h" #include "c_file.h"
@ -27,6 +29,7 @@
Charmap* g_charmap; Charmap* g_charmap;
std::string g_buildName; std::string g_buildName;
std::vector<std::string> g_incPaths;
void PrintAsmBytes(unsigned char* s, int length) { void PrintAsmBytes(unsigned char* s, int length) {
if (length > 0) { if (length > 0) {
@ -117,13 +120,20 @@ char* GetFileExtension(char* filename) {
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (argc != 4 && argc != 3) { if (argc < 3) {
std::fprintf(stderr, "Usage: %s BUILD_NAME SRC_FILE CHARMAP_FILE", argv[0]); std::fprintf(stderr, "Usage: %s BUILD_NAME SRC_FILE [CHARMAP_FILE] -- [ASM INC PATH] ...", argv[0]);
return 1; return 1;
} }
int pathStart = 0;
while (pathStart < argc && strcmp(argv[pathStart], "--") != 0) pathStart++;
for (int i = pathStart + 1; i < argc; i++) {
g_incPaths.push_back(argv[i]);
}
g_buildName = std::string(argv[1]); g_buildName = std::string(argv[1]);
g_charmap = new Charmap(argc == 4 ? argv[3] : ""); g_charmap = new Charmap(argc > 3 && pathStart > 3 ? argv[3] : "");
char* extension = GetFileExtension(argv[2]); char* extension = GetFileExtension(argv[2]);

View File

@ -49,5 +49,6 @@ const unsigned long kMaxCharmapSequenceLength = 16;
extern Charmap* g_charmap; extern Charmap* g_charmap;
extern std::string g_buildName; extern std::string g_buildName;
extern std::vector<std::string> g_incPaths;
#endif // PREPROC_H #endif // PREPROC_H