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
*.py
!tools/extract_include_enum.py
*.pl
# graphics

View File

@ -57,15 +57,18 @@ DATA_ASM_SUBDIR = data
SONG_SUBDIR = sound/songs
MID_SUBDIR = sound/songs/midi
ASSET_SUBDIR = assets
ENUM_INCLUDE_SUBDIR = enum_include
C_BUILDDIR = $(OBJ_DIR)/$(C_SUBDIR)
ASM_BUILDDIR = $(OBJ_DIR)/$(ASM_SUBDIR)
ASM_ENUM_INCLUDE_DIR = $(ASM_BUILDDIR)/$(ENUM_INCLUDE_SUBDIR)
DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR)
SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR)
MID_BUILDDIR = $(OBJ_DIR)/$(MID_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
override CFLAGS += -O2 -Wimplicit -Wparentheses -Werror -Wno-multichar -g3
@ -90,6 +93,7 @@ SCANINC := tools/bin/scaninc
PREPROC := tools/bin/preproc
FIX := tools/bin/gbafix
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
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_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_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS))
SUBDIRS := $(sort $(dir $(OBJS)))
SUBDIRS := $(sort $(dir $(OBJS) $(ENUM_ASM_HEADERS)))
$(shell mkdir -p $(SUBDIRS))
@ -253,16 +260,19 @@ $(ASM_BUILDDIR)/%.o: asm_dep = $(shell $(SCANINC) -I . $(ASM_SUBDIR)/$*.s)
endif
$(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)
$(DATA_ASM_BUILDDIR)/%.o: data_dep :=
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
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $$(data_dep)
$(PREPROC) $(BUILD_NAME) $< charmap.txt | $(CPP) -I include -nostdinc -undef -Wno-unicode - | $(AS) $(ASFLAGS) -o $@
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $$(data_dep) $(ENUM_ASM_HEADERS)
$(PREPROC) $(BUILD_NAME) $< charmap.txt -- $(PREPROC_INC_PATHS) | $(CPP) -I include -nostdinc -undef -Wno-unicode - | $(AS) $(ASFLAGS) -o $@
$(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s
$(AS) $(ASFLAGS) -I sound -o $@ $<

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,8 @@
#ifndef PROJECTILE_H
#define PROJECTILE_H
#include "entity.h"
Entity* CreateProjectile(u32);
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) {
FILE* fp = std::fopen(filename.c_str(), "rb");
if (fp == NULL) {
// The include might be an asset.
fp = std::fopen(("build/" + g_buildName + "/assets/" + filename).c_str(), "rb");
for (int i = 0; fp == NULL && i < g_incPaths.size(); i++) {
fp = std::fopen((g_incPaths[i] + "/" + filename).c_str(), "rb");
}
if (fp == NULL)
FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str());
}
std::fseek(fp, 0, SEEK_END);

View File

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

View File

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