mirror of
https://github.com/izzy2lost/Diddy-Kong-Racing.git
synced 2026-06-19 01:16:26 -07:00
Merge pull request #216 from DavidSM64/rev2_b
This commit is contained in:
@@ -12,6 +12,16 @@ VERSION := us_1.0
|
||||
NON_MATCHING ?= 0
|
||||
$(eval $(call validate-option,NON_MATCHING,0 1))
|
||||
|
||||
COMPILE_ASSETS ?= 0
|
||||
$(eval $(call validate-option,COMPILE_ASSETS,0 1))
|
||||
|
||||
ifeq ($(COMPILE_ASSETS),1)
|
||||
DUMMY != ./tools/dkr_assets_tool -c $(VERSION) ./assets >&2 || echo FAIL
|
||||
ifeq ($(DUMMY),FAIL)
|
||||
$(error Failed to compile assets)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(VERSION),us_1.0)
|
||||
DEFINES += VERSION_US_1_0=1
|
||||
endif
|
||||
@@ -37,6 +47,7 @@ COLOR ?= 1
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(MAKECMDGOALS),clean_lib)
|
||||
ifneq ($(MAKECMDGOALS),clean_src)
|
||||
ifneq ($(MAKECMDGOALS),distclean)
|
||||
ifneq ($(MAKECMDGOALS),reset)
|
||||
|
||||
################ Check if a baserom exists ################
|
||||
@@ -75,7 +86,11 @@ RECOMP_PROJECT := ./tools/ido-static-recomp/
|
||||
|
||||
DUMMY != ls $(RECOMP_PROJECT)ido >/dev/null || echo FAIL
|
||||
ifeq ($(DUMMY),FAIL)
|
||||
$(error Missing submodule ido-static-recomp. Please run 'git submodule update --init')
|
||||
DUMMY != git submodule update --init
|
||||
DUMMY != ls $(RECOMP_PROJECT)ido >/dev/null || echo FAIL
|
||||
ifeq ($(DUMMY),FAIL)
|
||||
$(error Missing submodule ido-static-recomp. Please run 'git submodule update --init')
|
||||
endif
|
||||
endif
|
||||
|
||||
# List of IDO tools required for the repo.
|
||||
@@ -110,6 +125,12 @@ endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
################################
|
||||
|
||||
# Removes the enums_cache if it exists in the build folde, incase someone modified the include/enums.h file.
|
||||
DUMMY != rm -Rf build/enums_cache
|
||||
|
||||
################ Target Executable and Sources ###############
|
||||
|
||||
@@ -175,8 +196,8 @@ FixPath = $(subst /,,$1)
|
||||
|
||||
N64CRC = $(TOOLS_DIR)/n64crc
|
||||
FIXCHECKSUMS = python3 $(TOOLS_DIR)/python/calc_func_checksums.py $(VERSION)
|
||||
TEXBUILDER = $(TOOLS_DIR)/dkr_texbuilder
|
||||
COMPRESS = $(TOOLS_DIR)/dkr_decompressor -c
|
||||
COMPRESS = $(TOOLS_DIR)/dkr_assets_tool -fc
|
||||
BUILDER = $(TOOLS_DIR)/dkr_assets_tool -b $(VERSION) ./assets
|
||||
|
||||
LIB_DIRS := lib/
|
||||
ASM_DIRS := asm/ asm/boot/ asm/assets/ lib/asm/ lib/asm/non_decompilable
|
||||
@@ -208,8 +229,6 @@ CC_CHECK_CFLAGS += -Wno-builtin-declaration-mismatch -Wno-pointer-to-int-cast -W
|
||||
|
||||
####################### ASSETS #########################
|
||||
|
||||
# TODO: Clean this up if possible
|
||||
|
||||
# All the asset subfolders to create in the build folder.
|
||||
ASSETS_DIRS := audio bin fonts ids levels levels/headers levels/models levels/names levels/objectMaps misc objects objects/animations objects/headers objects/models particles particles/behaviors particles/particles sprites text text/game text/menu textures textures/2d textures/3d tt_ghosts unknown_0 ucode
|
||||
|
||||
@@ -218,100 +237,67 @@ UCODE_DIR = ucode/$(VERSION)
|
||||
|
||||
ASSETS_COPY = cp
|
||||
|
||||
AUDIO_IN_DIR = $(ASSETS_DIR)/audio
|
||||
AUDIO_OUT_DIR = $(BUILD_DIR)/audio
|
||||
ALL_ASSETS_BUILT += $(patsubst $(AUDIO_IN_DIR)/%.bin,$(AUDIO_OUT_DIR)/%.bin,$(wildcard $(AUDIO_IN_DIR)/*.bin))
|
||||
# Makes name uppercase, and also replaces '/' with '_' for subfolders.
|
||||
# Doing all those subst calls *should* be faster than `$(shell echo '$1' | tr '[:lower:]' '[:upper:]')
|
||||
GET_VAR_NAME = $(subst /,_,$(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$1)))))))))))))))))))))))))))
|
||||
|
||||
BIN_IN_DIR = $(ASSETS_DIR)/bin
|
||||
BIN_OUT_DIR = $(BUILD_DIR)/bin
|
||||
ALL_ASSETS_BUILT += $(patsubst $(BIN_IN_DIR)/%.bin,$(BIN_OUT_DIR)/%.bin,$(wildcard $(BIN_IN_DIR)/*.bin))
|
||||
# $1 = Input/Output directories name
|
||||
define DEFINE_BINARY_FILES
|
||||
ALL_ASSETS_BUILT += $(patsubst $($1_IN_DIR)/%.bin,$($1_OUT_DIR)/%.bin,$(wildcard $($1_IN_DIR)/*.bin))
|
||||
endef
|
||||
# $1 = Input/Output directories name
|
||||
define DEFINE_COMPRESSED_BINARY_FILES
|
||||
ALL_ASSETS_BUILT += $(patsubst $($1_IN_DIR)/%.cbin,$($1_OUT_DIR)/%.bin,$(wildcard $($1_IN_DIR)/*.cbin))
|
||||
endef
|
||||
# $1 = Input/Output directories name
|
||||
define DEFINE_JSON_FILES
|
||||
ALL_ASSETS_BUILT += $(patsubst $($1_IN_DIR)/%.json,$($1_OUT_DIR)/%.bin,$(wildcard $($1_IN_DIR)/*.json))
|
||||
endef
|
||||
# $1 = Input/Output directories name
|
||||
define DEFINE_JSON_AND_BINARY_FILES
|
||||
$(eval $(call DEFINE_JSON_FILES,$1))
|
||||
$(eval $(call DEFINE_BINARY_FILES,$1))
|
||||
endef
|
||||
|
||||
FONTS_IN_DIR = $(ASSETS_DIR)/fonts
|
||||
FONTS_OUT_DIR = $(BUILD_DIR)/fonts
|
||||
ALL_ASSETS_BUILT += $(patsubst $(FONTS_IN_DIR)/%.bin,$(FONTS_OUT_DIR)/%.bin,$(wildcard $(FONTS_IN_DIR)/*.bin))
|
||||
# $1 = folder name, $2 = define function
|
||||
define DEFINE_SECTION_FILES
|
||||
$(eval VAR_NAME := $(call GET_VAR_NAME,$1))
|
||||
$(eval $(VAR_NAME)_IN_DIR = $(ASSETS_DIR)/$1)
|
||||
$(eval $(VAR_NAME)_OUT_DIR = $(BUILD_DIR)/$1)
|
||||
$(eval $(call $2,$(VAR_NAME)))
|
||||
endef
|
||||
|
||||
IDS_IN_DIR = $(ASSETS_DIR)/ids
|
||||
IDS_OUT_DIR = $(BUILD_DIR)/ids
|
||||
ALL_ASSETS_BUILT += $(patsubst $(IDS_IN_DIR)/%.bin,$(IDS_OUT_DIR)/%.bin,$(wildcard $(IDS_IN_DIR)/*.bin))
|
||||
###### Define section files into the ALL_ASSETS_BUILT variable ######
|
||||
|
||||
LEVELS_IN_DIR = $(ASSETS_DIR)/levels
|
||||
LEVELS_OUT_DIR = $(BUILD_DIR)/levels
|
||||
LEVEL_HEADERS_IN_DIR = $(LEVELS_IN_DIR)/headers
|
||||
LEVEL_HEADERS_OUT_DIR = $(LEVELS_OUT_DIR)/headers
|
||||
LEVEL_MODELS_IN_DIR = $(LEVELS_IN_DIR)/models
|
||||
LEVEL_MODELS_OUT_DIR = $(LEVELS_OUT_DIR)/models
|
||||
LEVEL_NAMES_IN_DIR = $(LEVELS_IN_DIR)/names
|
||||
LEVEL_NAMES_OUT_DIR = $(LEVELS_OUT_DIR)/names
|
||||
LEVEL_OBJMAPS_IN_DIR = $(LEVELS_IN_DIR)/objectMaps
|
||||
LEVEL_OBJMAPS_OUT_DIR = $(LEVELS_OUT_DIR)/objectMaps
|
||||
ALL_ASSETS_BUILT += $(patsubst $(LEVEL_HEADERS_IN_DIR)/%.bin,$(LEVEL_HEADERS_OUT_DIR)/%.bin,$(wildcard $(LEVEL_HEADERS_IN_DIR)/*.bin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(LEVEL_MODELS_IN_DIR)/%.cbin,$(LEVEL_MODELS_OUT_DIR)/%.bin,$(wildcard $(LEVEL_MODELS_IN_DIR)/*.cbin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(LEVEL_NAMES_IN_DIR)/%.bin,$(LEVEL_NAMES_OUT_DIR)/%.bin,$(wildcard $(LEVEL_NAMES_IN_DIR)/*.bin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(LEVEL_OBJMAPS_IN_DIR)/%.cbin,$(LEVEL_OBJMAPS_OUT_DIR)/%.bin,$(wildcard $(LEVEL_OBJMAPS_IN_DIR)/*.cbin))
|
||||
|
||||
MISC_IN_DIR = $(ASSETS_DIR)/misc
|
||||
MISC_OUT_DIR = $(BUILD_DIR)/misc
|
||||
ALL_ASSETS_BUILT += $(patsubst $(MISC_IN_DIR)/%.bin,$(MISC_OUT_DIR)/%.bin,$(wildcard $(MISC_IN_DIR)/*.bin))
|
||||
|
||||
OBJECTS_IN_DIR = $(ASSETS_DIR)/objects
|
||||
OBJECTS_OUT_DIR = $(BUILD_DIR)/objects
|
||||
OBJECT_ANIMS_IN_DIR = $(OBJECTS_IN_DIR)/animations
|
||||
OBJECT_ANIMS_OUT_DIR = $(OBJECTS_OUT_DIR)/animations
|
||||
OBJECT_HEADERS_IN_DIR = $(OBJECTS_IN_DIR)/headers
|
||||
OBJECT_HEADERS_OUT_DIR = $(OBJECTS_OUT_DIR)/headers
|
||||
OBJECT_MODELS_IN_DIR = $(OBJECTS_IN_DIR)/models
|
||||
OBJECT_MODELS_OUT_DIR = $(OBJECTS_OUT_DIR)/models
|
||||
ALL_ASSETS_BUILT += $(patsubst $(OBJECTS_IN_DIR)/%.bin,$(OBJECTS_OUT_DIR)/%.bin,$(wildcard $(OBJECTS_IN_DIR)/*.bin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(OBJECT_ANIMS_IN_DIR)/%.cbin,$(OBJECT_ANIMS_OUT_DIR)/%.bin,$(wildcard $(OBJECT_ANIMS_IN_DIR)/*.cbin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(OBJECT_HEADERS_IN_DIR)/%.bin,$(OBJECT_HEADERS_OUT_DIR)/%.bin,$(wildcard $(OBJECT_HEADERS_IN_DIR)/*.bin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(OBJECT_MODELS_IN_DIR)/%.cbin,$(OBJECT_MODELS_OUT_DIR)/%.bin,$(wildcard $(OBJECT_MODELS_IN_DIR)/*.cbin))
|
||||
|
||||
PARTICLES_IN_DIR = $(ASSETS_DIR)/particles
|
||||
PARTICLES_OUT_DIR = $(BUILD_DIR)/particles
|
||||
PART_BEHAVIORS_IN_DIR = $(PARTICLES_IN_DIR)/behaviors
|
||||
PART_BEHAVIORS_OUT_DIR = $(PARTICLES_OUT_DIR)/behaviors
|
||||
PART_PARTICLES_IN_DIR = $(PARTICLES_IN_DIR)/particles
|
||||
PART_PARTICLES_OUT_DIR = $(PARTICLES_OUT_DIR)/particles
|
||||
ALL_ASSETS_BUILT += $(patsubst $(PART_BEHAVIORS_IN_DIR)/%.bin,$(PART_BEHAVIORS_OUT_DIR)/%.bin,$(wildcard $(PART_BEHAVIORS_IN_DIR)/*.bin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(PART_PARTICLES_IN_DIR)/%.bin,$(PART_PARTICLES_OUT_DIR)/%.bin,$(wildcard $(PART_PARTICLES_IN_DIR)/*.bin))
|
||||
|
||||
SPRITES_IN_DIR = $(ASSETS_DIR)/sprites
|
||||
SPRITES_OUT_DIR = $(BUILD_DIR)/sprites
|
||||
ALL_ASSETS_BUILT += $(patsubst $(SPRITES_IN_DIR)/%.bin,$(SPRITES_OUT_DIR)/%.bin,$(wildcard $(SPRITES_IN_DIR)/*.bin))
|
||||
|
||||
TEXT_IN_DIR = $(ASSETS_DIR)/text
|
||||
TEXT_OUT_DIR = $(BUILD_DIR)/text
|
||||
TEXT_GAME_IN_DIR = $(TEXT_IN_DIR)/game
|
||||
TEXT_GAME_OUT_DIR = $(TEXT_OUT_DIR)/game
|
||||
TEXT_MENU_IN_DIR = $(TEXT_IN_DIR)/menu
|
||||
TEXT_MENU_OUT_DIR = $(TEXT_OUT_DIR)/menu
|
||||
ALL_ASSETS_BUILT += $(patsubst $(TEXT_GAME_IN_DIR)/%.bin,$(TEXT_GAME_OUT_DIR)/%.bin,$(wildcard $(TEXT_GAME_IN_DIR)/*.bin))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(TEXT_MENU_IN_DIR)/%.bin,$(TEXT_MENU_OUT_DIR)/%.bin,$(wildcard $(TEXT_MENU_IN_DIR)/*.bin))
|
||||
|
||||
TEXTURES_IN_DIR = $(ASSETS_DIR)/textures
|
||||
TEXTURES_OUT_DIR = $(BUILD_DIR)/textures
|
||||
TEXTURES_2D_IN_DIR = $(TEXTURES_IN_DIR)/2d
|
||||
TEXTURES_2D_OUT_DIR = $(TEXTURES_OUT_DIR)/2d
|
||||
TEXTURES_3D_IN_DIR = $(TEXTURES_IN_DIR)/3d
|
||||
TEXTURES_3D_OUT_DIR = $(TEXTURES_OUT_DIR)/3d
|
||||
ALL_ASSETS_BUILT += $(patsubst $(TEXTURES_2D_IN_DIR)/%.png,$(TEXTURES_2D_OUT_DIR)/%.bin,$(wildcard $(TEXTURES_2D_IN_DIR)/*.png))
|
||||
ALL_ASSETS_BUILT += $(patsubst $(TEXTURES_3D_IN_DIR)/%.png,$(TEXTURES_3D_OUT_DIR)/%.bin,$(wildcard $(TEXTURES_3D_IN_DIR)/*.png))
|
||||
|
||||
TT_GHOSTS_IN_DIR = $(ASSETS_DIR)/tt_ghosts
|
||||
TT_GHOSTS_OUT_DIR = $(BUILD_DIR)/tt_ghosts
|
||||
ALL_ASSETS_BUILT += $(patsubst $(TT_GHOSTS_IN_DIR)/%.bin,$(TT_GHOSTS_OUT_DIR)/%.bin,$(wildcard $(TT_GHOSTS_IN_DIR)/*.bin))
|
||||
|
||||
UNKNOWN_0_IN_DIR = $(ASSETS_DIR)/unknown_0
|
||||
UNKNOWN_0_OUT_DIR = $(BUILD_DIR)/unknown_0
|
||||
ALL_ASSETS_BUILT += $(patsubst $(UNKNOWN_0_IN_DIR)/%.bin,$(UNKNOWN_0_OUT_DIR)/%.bin,$(wildcard $(UNKNOWN_0_IN_DIR)/*.bin))
|
||||
$(call DEFINE_SECTION_FILES,audio,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,bin,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,fonts,DEFINE_JSON_AND_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,ids,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,levels/headers,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,levels/models,DEFINE_COMPRESSED_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,levels/names,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,levels/objectMaps,DEFINE_COMPRESSED_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,misc,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,objects,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,objects/animations,DEFINE_COMPRESSED_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,objects/headers,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,objects/models,DEFINE_COMPRESSED_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,particles/behaviors,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,particles/particles,DEFINE_BINARY_FILES)
|
||||
$(call DEFINE_SECTION_FILES,sprites,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,text/game,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,text/menu,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,textures/2d,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,textures/3d,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,tt_ghosts,DEFINE_JSON_FILES)
|
||||
$(call DEFINE_SECTION_FILES,unknown_0,DEFINE_BINARY_FILES)
|
||||
|
||||
# Microcode
|
||||
UCODE_IN_DIR = $(UCODE_DIR)
|
||||
UCODE_OUT_DIR = $(BUILD_DIR)/ucode
|
||||
UCODE = $(wildcard $(UCODE_IN_DIR)/*.bin)
|
||||
ALL_ASSETS_BUILT += $(patsubst $(UCODE_IN_DIR)/%.bin,$(UCODE_OUT_DIR)/%.bin,$(UCODE))
|
||||
|
||||
#ALL_ASSETS_BUILT := $(ANIMATIONS_BUILT) $(AUDIO_BUILT) $(BILLBOARDS_BUILT) $(BINS_BUILT) $(CHEATS_BUILT) $(FONTS_BUILT) $(LEVELS_BUILT) $(OBJECTS_BUILT) $(TEXTURES_BUILT) $(PARTICLES_BUILT) $(TEXT_BUILT) $(TT_GHOSTS_BUILT) $(UCODE_BUILT) $(LUT_BUILT)
|
||||
|
||||
####################### LIBULTRA #########################
|
||||
|
||||
$(BUILD_DIR)/lib/%.o: OPT_FLAGS := -O2 -Xfullwarn
|
||||
@@ -358,7 +344,15 @@ ifneq ($(wildcard ./build/.*),)
|
||||
rm -r build
|
||||
else
|
||||
@echo "/build/ directory has already been deleted."
|
||||
endif
|
||||
endif
|
||||
|
||||
distclean:
|
||||
rm -rf build
|
||||
rm -rf assets
|
||||
rm -rf ucode
|
||||
rm -rf dkr.ld
|
||||
rm -rf tools/ido-static-recomp/{,.[!.],..?}* # Deletes all files, including hidden ones.
|
||||
$(MAKE) -C tools distclean
|
||||
|
||||
clean_lib:
|
||||
ifneq ($(wildcard $(BUILD_DIR)/lib/.*),)
|
||||
@@ -388,98 +382,55 @@ dont_remove_asset_files: $(ALL_ASSETS_BUILT)
|
||||
|
||||
# All assets should output a .bin file
|
||||
|
||||
$(AUDIO_OUT_DIR)/%.bin: $(AUDIO_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
# $1 = folder name, $2 = Print Message
|
||||
define CREATE_BINARY_ASSET_TARGET
|
||||
$(eval VAR_NAME := $(call GET_VAR_NAME,$1))
|
||||
$$($$(VAR_NAME)_OUT_DIR)/%.bin: $$($$(VAR_NAME)_IN_DIR)/%.bin
|
||||
$$(call print,$2:,$$<,$$@)
|
||||
$$(V)$$(ASSETS_COPY) $$^ $$@
|
||||
endef
|
||||
|
||||
$(BIN_OUT_DIR)/%.bin: $(BIN_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(FONTS_OUT_DIR)/%.bin: $(FONTS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(IDS_OUT_DIR)/%.bin: $(IDS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(LEVEL_HEADERS_OUT_DIR)/%.bin: $(LEVEL_HEADERS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
# $1 = folder name, $2 = Print Message
|
||||
define CREATE_COMPRESSED_ASSET_TARGET
|
||||
$(eval VAR_NAME := $(call GET_VAR_NAME,$1))
|
||||
$$($$(VAR_NAME)_OUT_DIR)/%.bin: $$($$(VAR_NAME)_IN_DIR)/%.cbin
|
||||
$$(call print,$2:,$$<,$$@)
|
||||
$$(V)$$(COMPRESS) $$^ $$@
|
||||
endef
|
||||
|
||||
$(LEVEL_MODELS_OUT_DIR)/%.bin: $(LEVEL_MODELS_IN_DIR)/%.cbin
|
||||
$(call print,Compressing:,$<,$@)
|
||||
$(V)$(COMPRESS) $^ $@
|
||||
|
||||
$(LEVEL_NAMES_OUT_DIR)/%.bin: $(LEVEL_NAMES_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
# $1 = folder name, $2 = Print Message
|
||||
define CREATE_JSON_ASSET_TARGET
|
||||
$(eval VAR_NAME := $(call GET_VAR_NAME,$1))
|
||||
$$($$(VAR_NAME)_OUT_DIR)/%.bin: $$($$(VAR_NAME)_IN_DIR)/%.json
|
||||
$$(call print,$2:,$$<,$$@)
|
||||
$$(V)$$(BUILDER) $$^ $$@
|
||||
endef
|
||||
|
||||
$(LEVEL_OBJMAPS_OUT_DIR)/%.bin: $(LEVEL_OBJMAPS_IN_DIR)/%.cbin
|
||||
$(call print,Compressing:,$<,$@)
|
||||
$(V)$(COMPRESS) $^ $@
|
||||
|
||||
$(MISC_OUT_DIR)/%.bin: $(MISC_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(OBJECTS_OUT_DIR)/%.bin: $(OBJECTS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(OBJECT_ANIMS_OUT_DIR)/%.bin: $(OBJECT_ANIMS_IN_DIR)/%.cbin
|
||||
$(call print,Compressing:,$<,$@)
|
||||
$(V)$(COMPRESS) $^ $@
|
||||
|
||||
$(OBJECT_HEADERS_OUT_DIR)/%.bin: $(OBJECT_HEADERS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(OBJECT_MODELS_OUT_DIR)/%.bin: $(OBJECT_MODELS_IN_DIR)/%.cbin
|
||||
$(call print,Compressing:,$<,$@)
|
||||
$(V)$(COMPRESS) $^ $@
|
||||
|
||||
$(PART_BEHAVIORS_OUT_DIR)/%.bin: $(PART_BEHAVIORS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(PART_PARTICLES_OUT_DIR)/%.bin: $(PART_PARTICLES_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(SPRITES_OUT_DIR)/%.bin: $(SPRITES_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(TEXT_GAME_OUT_DIR)/%.bin: $(TEXT_GAME_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(TEXT_MENU_OUT_DIR)/%.bin: $(TEXT_MENU_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(TEXTURES_2D_OUT_DIR)/%.bin: $(TEXTURES_2D_IN_DIR)/%.png
|
||||
$(call print,Building Texture:,$<,$@)
|
||||
$(V)$(TEXBUILDER) $^ $@
|
||||
|
||||
$(TEXTURES_3D_OUT_DIR)/%.bin: $(TEXTURES_3D_IN_DIR)/%.png
|
||||
$(call print,Building Texture:,$<,$@)
|
||||
$(V)$(TEXBUILDER) $^ $@
|
||||
|
||||
$(TEXT_MENU_OUT_DIR)/%.bin: $(TEXT_MENU_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(TT_GHOSTS_OUT_DIR)/%.bin: $(TT_GHOSTS_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
|
||||
$(UNKNOWN_0_OUT_DIR)/%.bin: $(UNKNOWN_0_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,audio,Copying Audio Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,bin,Copying Bin Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,fonts,Copying Fonts Binary))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,fonts,Building Fonts))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,ids,Copying IDs Binary))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,levels/headers,Building Level Header))
|
||||
$(eval $(call CREATE_COMPRESSED_ASSET_TARGET,levels/models,Compressing Level Model Binary))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,levels/names,Building Level Name))
|
||||
$(eval $(call CREATE_COMPRESSED_ASSET_TARGET,levels/objectMaps,Compressing Level Object Map Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,misc,Copying Misc Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,objects,Copying Object Binary))
|
||||
$(eval $(call CREATE_COMPRESSED_ASSET_TARGET,objects/animations,Compressing Object Animation Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,objects/headers,Copying Object Header Binary))
|
||||
$(eval $(call CREATE_COMPRESSED_ASSET_TARGET,objects/models,Compressing Object Model Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,particles/behaviors,Copying Particle Behavior Binary))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,particles/particles,Copying Particle Binary))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,sprites,Building Sprite))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,text/game,Building Game Text))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,text/menu,Building Menu Text))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,textures/2d,Building Texture (2D)))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,textures/3d,Building Texture (3D)))
|
||||
$(eval $(call CREATE_JSON_ASSET_TARGET,tt_ghosts,Building T.T. Ghost))
|
||||
$(eval $(call CREATE_BINARY_ASSET_TARGET,unknown_0,Copying Unknown_0 Binary))
|
||||
|
||||
# Microcode target
|
||||
$(UCODE_OUT_DIR)/%.bin: $(UCODE_IN_DIR)/%.bin
|
||||
$(call print,Copying:,$<,$@)
|
||||
$(V)$(ASSETS_COPY) $^ $@
|
||||
@@ -540,7 +491,7 @@ test: $(BUILD_DIR)/$(TARGET).z64
|
||||
load: $(BUILD_DIR)/$(TARGET).z64
|
||||
$(LOADER) $(LOADER_FLAGS) $<
|
||||
|
||||
.PHONY: all clean default diff test
|
||||
.PHONY: all clean distclean default diff test
|
||||
|
||||
# Remove built-in rules, to improve performance
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
+9392
-9319
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Regular → Executable
+1041
-557
File diff suppressed because one or more lines are too long
+8
-10
@@ -1,32 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $# == 0 || (($1 != "us_1.0") && ($1 != "us_1.1") && ($1 != "eu_1.0") && ($1 != "eu_1.1") && ($1 != "jp"))]]; then
|
||||
echo 'Usage: ./extract.sh <version>'
|
||||
echo 'Acceptable versions: us_1.0, us_1.1, eu_1.0, eu_1.1, jp'
|
||||
exit 1
|
||||
echo 'No valid version specified, defaulting to us_1.0...'
|
||||
VER="us_1.0"
|
||||
else
|
||||
VER=$1
|
||||
fi
|
||||
|
||||
echo 'Extracting Assets...'
|
||||
|
||||
# Remove assets directory if it exists.
|
||||
ASSETS_DIR="./assets/$1"
|
||||
ASSETS_DIR="./assets/vanilla/$VER"
|
||||
if [ -d "$ASSETS_DIR" ]; then
|
||||
rm -r $ASSETS_DIR
|
||||
fi
|
||||
|
||||
# Remove ucode directory if it exists.
|
||||
UCODE_DIR="./ucode/$1"
|
||||
UCODE_DIR="./ucode/$VER"
|
||||
if [ -d "$UCODE_DIR" ]; then
|
||||
rm -r $UCODE_DIR
|
||||
fi
|
||||
|
||||
if ! ./tools/dkr_extractor "$1" ./extract-ver ./baseroms . ; then
|
||||
if ! ./tools/dkr_assets_tool -e "$VER" ./assets ./extract-ver ./baseroms . ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate the linker file (dkr.ld)
|
||||
./generate_ld.sh "$1"
|
||||
|
||||
echo 'Done.'
|
||||
|
||||
exit 0
|
||||
exit 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
#ifndef ENUMS_H
|
||||
#define ENUMS_H
|
||||
|
||||
/* All the enums defined here can be used in asset files */
|
||||
|
||||
typedef enum Vehicle {
|
||||
VEHICLE_CAR,
|
||||
VEHICLE_HOVERCRAFT,
|
||||
VEHICLE_PLANE,
|
||||
} Vehicle;
|
||||
|
||||
typedef enum Language {
|
||||
LANGUAGE_ENGLISH,
|
||||
LANGUAGE_GERMAN,
|
||||
LANGUAGE_FRENCH,
|
||||
LANGUAGE_JAPANESE,
|
||||
} Language;
|
||||
|
||||
typedef enum World {
|
||||
WORLD_NONE = -1, // This enum starts at -1 instead of 0.
|
||||
WORLD_CENTRAL_AREA,
|
||||
WORLD_DINO_DOMAIN,
|
||||
WORLD_SHERBET_ISLAND,
|
||||
WORLD_SNOWFLAKE_MOUNTAIN,
|
||||
WORLD_DRAGON_FOREST,
|
||||
WORLD_FUTURE_FUN_LAND,
|
||||
} World;
|
||||
|
||||
typedef enum RaceType {
|
||||
RACETYPE_DEFAULT = 0,
|
||||
RACETYPE_HORSESHOE_GULCH = 3,
|
||||
RACETYPE_HUBWORLD = 5,
|
||||
RACETYPE_CUTSCENE_1 = 6, // Not sure what the difference between these two are.
|
||||
RACETYPE_CUTSCENE_2 = 7,
|
||||
RACETYPE_BOSS = 8,
|
||||
RACETYPE_CHALLENGE_BATTLE = 64,
|
||||
RACETYPE_CHALLENGE_BANANAS = 65,
|
||||
RACETYPE_CHALLENGE_EGGS = 66,
|
||||
} RaceType;
|
||||
|
||||
typedef enum HorizontalAlignmentFlags {
|
||||
HORZ_ALIGN_LEFT = 0,
|
||||
HORZ_ALIGN_RIGHT = 1,
|
||||
HORZ_ALIGN_CENTER = 4,
|
||||
} HorizontalAlignmentFlags;
|
||||
|
||||
typedef enum VerticalAlignmentFlags {
|
||||
VERT_ALIGN_TOP = 0,
|
||||
VERT_ALIGN_BOTTOM = 2,
|
||||
VERT_ALIGN_MIDDLE = 8,
|
||||
} VerticalAlignmentFlags;
|
||||
|
||||
typedef enum AlignmentFlags {
|
||||
ALIGN_TOP_LEFT = VERT_ALIGN_TOP | HORZ_ALIGN_LEFT,
|
||||
ALIGN_TOP_CENTER = VERT_ALIGN_TOP | HORZ_ALIGN_CENTER,
|
||||
ALIGN_TOP_RIGHT = VERT_ALIGN_TOP | HORZ_ALIGN_RIGHT,
|
||||
ALIGN_MIDDLE_LEFT = VERT_ALIGN_MIDDLE | HORZ_ALIGN_LEFT,
|
||||
ALIGN_MIDDLE_CENTER = VERT_ALIGN_MIDDLE | HORZ_ALIGN_CENTER,
|
||||
ALIGN_MIDDLE_RIGHT = VERT_ALIGN_MIDDLE | HORZ_ALIGN_RIGHT,
|
||||
ALIGN_BOTTOM_LEFT = VERT_ALIGN_BOTTOM | HORZ_ALIGN_LEFT,
|
||||
ALIGN_BOTTOM_CENTER = VERT_ALIGN_BOTTOM | HORZ_ALIGN_CENTER,
|
||||
ALIGN_BOTTOM_RIGHT = VERT_ALIGN_BOTTOM | HORZ_ALIGN_RIGHT,
|
||||
} AlignmentFlags;
|
||||
|
||||
#endif
|
||||
+3
-5
@@ -1,7 +1,5 @@
|
||||
/n64crc
|
||||
/dkr_decompressor
|
||||
/dkr_cheats_encryptor
|
||||
/dkr_extractor
|
||||
/dkr_texbuilder
|
||||
/dkr_assets_tool
|
||||
/dkr_assets_tool_classes/_build
|
||||
/binutils
|
||||
/ido5.3_recomp
|
||||
/ido5.3_recomp
|
||||
|
||||
+32
-24
@@ -1,41 +1,49 @@
|
||||
CC := gcc
|
||||
CXX := g++
|
||||
CFLAGS := -I . -Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 -O2 -s
|
||||
CXXFLAGS := --std=c++17 -lstdc++fs -lcrypto -lssl -lpthread
|
||||
LDFLAGS := -lm
|
||||
PROGRAMS := n64crc
|
||||
CXX_PROGRAMS := dkr_cheats_encryptor dkr_decompressor dkr_extractor dkr_texbuilder
|
||||
CXX_PROGRAMS := dkr_assets_tool
|
||||
|
||||
BUILD_DIR := dkr_assets_tool_classes/_build
|
||||
|
||||
ENUMS_HEADER := ../include/enums.h
|
||||
|
||||
# From: https://stackoverflow.com/questions/2483182/recursive-wildcards-in-gnu-make/18258352#18258352
|
||||
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
|
||||
|
||||
default: all
|
||||
|
||||
n64crc_SOURCES := n64crc.c
|
||||
|
||||
dkr_cheats_encryptor_SOURCES := dkr_cheats_encryptor.cpp
|
||||
|
||||
dkr_decompressor_SOURCES := dkr_decompressor.cpp $(wildcard dkr_decompressor_src/*.cpp dkr_decompressor_src/*.c)
|
||||
dkr_decompressor_CXXFLAGS := -lstdc++fs -lcrypto -lssl
|
||||
|
||||
dkr_extractor_SOURCES := dkr_extractor.cpp $(wildcard dkr_decompressor_src/*.cpp dkr_decompressor_src/*.c dkr_extractor_classes/*.cpp n64graphics/*.c)
|
||||
dkr_extractor_CXXFLAGS := -lstdc++fs -lcrypto -lssl -lpthread
|
||||
|
||||
dkr_texbuilder_SOURCES := dkr_texbuilder.cpp $(wildcard dkr_decompressor_src/*.cpp dkr_decompressor_src/*.c n64graphics/*.c)
|
||||
dkr_texbuilder_CXXFLAGS := -lstdc++fs
|
||||
|
||||
all: $(PROGRAMS) $(CXX_PROGRAMS)
|
||||
|
||||
clean:
|
||||
$(RM) $(PROGRAMS) $(CXX_PROGRAMS)
|
||||
rm -Rf $(PROGRAMS) $(CXX_PROGRAMS) $(BUILD_DIR)
|
||||
|
||||
define COMPILE
|
||||
$(1): $($1_SOURCES)
|
||||
$(CC) $(CFLAGS) $($1_CFLAGS) $$^ -o $$@ $(LDFLAGS) $($1_LDFLAGS)
|
||||
endef
|
||||
distclean: clean
|
||||
|
||||
define COMPILE_CXX
|
||||
$(1): $($1_SOURCES)
|
||||
$(CXX) $$^ -o $$@ $($1_CXXFLAGS) $(LDFLAGS) $($1_LDFLAGS)
|
||||
endef
|
||||
n64crc: n64crc.c
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
|
||||
$(foreach p,$(PROGRAMS),$(eval $(call COMPILE,$(p))))
|
||||
$(foreach p,$(CXX_PROGRAMS),$(eval $(call COMPILE_CXX,$(p))))
|
||||
dkr_assets_tool_CPP_FILES := dkr_assets_tool.cpp \
|
||||
$(call rwildcard,dkr_assets_tool_classes,*.cpp)
|
||||
|
||||
dkr_assets_tool_C_FILES := $(call rwildcard,dkr_assets_tool_classes,*.c)
|
||||
|
||||
dkr_assets_tool_OBJ_FILES := $(foreach file,$(dkr_assets_tool_C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \
|
||||
$(foreach file,$(dkr_assets_tool_CPP_FILES),$(BUILD_DIR)/$(file:.cpp=.o))
|
||||
|
||||
DUMMY != mkdir -p $(sort $(dir $(dkr_assets_tool_OBJ_FILES)))
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
$(CXX) -c $^ -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
$(BUILD_DIR)/%.o: %.cpp
|
||||
$(CXX) -c $< -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
dkr_assets_tool: $(dkr_assets_tool_OBJ_FILES)
|
||||
$(CXX) $^ -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
.PHONY: all clean distclean default
|
||||
|
||||
.PHONY: all clean default
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* This tool handles everything assets-related including extracting and building.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dkr_assets_tool_classes/common/util.h"
|
||||
#include "dkr_assets_tool_classes/extractor/extractor.h"
|
||||
#include "dkr_assets_tool_classes/builder/builder.h"
|
||||
#include "dkr_assets_tool_classes/make_asset_files/asset_enums_header.h"
|
||||
#include "dkr_assets_tool_classes/make_asset_files/asset_asm_data.h"
|
||||
#include "dkr_assets_tool_classes/compiler/compiler.h"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
void print_usage() {
|
||||
std::cout << "---- Usages -------------------------------------------------------------" << std::endl;
|
||||
std::cout << "Extracting assets: ./dkr_assets_tool -e <version> <configs path> <baseroms path> <output path>" << std::endl;
|
||||
std::cout << "Building an asset: ./dkr_assets_tool -b <version> <assets path> <source path> <output path>" << std::endl;
|
||||
std::cout << "Creating includes: ./dkr_assets_tool -i <version> <assets path> <include directory> <build directory> <asm output directory>" << std::endl;
|
||||
std::cout << "Compiling assets: ./dkr_assets_tool -c <version> <assets path>" << std::endl;
|
||||
std::cout << "Compress file: ./dkr_assets_tool -fc <input_filename> <output_filename>" << std::endl;
|
||||
std::cout << "Decompress file: ./dkr_assets_tool -fd <input_filename> <output_filename>" << std::endl;
|
||||
std::cout << "-------------------------------------------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
typedef enum _ToolType {
|
||||
TT_DO_NOTHING,
|
||||
TT_EXTRACT,
|
||||
TT_BUILD,
|
||||
TT_ASSET_INCLUDES,
|
||||
TT_ASSET_COMPILE,
|
||||
TT_ASSET_COMPRESS_FILE,
|
||||
TT_ASSET_DECOMPRESS_FILE,
|
||||
} ToolType;
|
||||
|
||||
typedef struct _CmdArgOptions {
|
||||
ToolType type;
|
||||
std::vector<std::string> paths;
|
||||
} CmdArgOptions;
|
||||
|
||||
CmdArgOptions options;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
typedef enum _CurrentParseOption {
|
||||
PO_NONE,
|
||||
PO_TYPE
|
||||
} CurrentParseOption;
|
||||
|
||||
std::string get_cmd_from_parse_option(ToolType type) {
|
||||
switch(type) {
|
||||
case TT_EXTRACT: return "-e";
|
||||
case TT_BUILD: return "-b";
|
||||
case TT_ASSET_INCLUDES: return "-i";
|
||||
case TT_ASSET_COMPILE: return "-c";
|
||||
case TT_ASSET_COMPRESS_FILE: return "-fc";
|
||||
case TT_ASSET_DECOMPRESS_FILE: return "-fd";
|
||||
}
|
||||
return "(Invalid option)";
|
||||
}
|
||||
|
||||
bool parse_options(int argc, char *argv[]) {
|
||||
std::vector<std::string> args(argv, argv+argc);
|
||||
|
||||
if(argc == 1) {
|
||||
return false; // Display usage
|
||||
}
|
||||
|
||||
// Parse options from command line.
|
||||
bool parsingCmd = false;
|
||||
int curOptionState = 0;
|
||||
int curOptionArgs = 0;
|
||||
CurrentParseOption curOption = PO_NONE;
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
if(args[i][0] == '-') {
|
||||
if(parsingCmd) {
|
||||
display_error("Not enough args for the current command \"", get_cmd_from_parse_option(options.type), "\"");
|
||||
return false;
|
||||
}
|
||||
if(args[i] == "-e") {
|
||||
curOption = PO_TYPE;
|
||||
curOptionState = 1;
|
||||
options.type = TT_EXTRACT;
|
||||
parsingCmd = true;
|
||||
} else if(args[i] == "-b") {
|
||||
curOption = PO_TYPE;
|
||||
curOptionState = 2;
|
||||
options.type = TT_BUILD;
|
||||
parsingCmd = true;
|
||||
} else if(args[i] == "-i") {
|
||||
curOption = PO_TYPE;
|
||||
curOptionState = 3;
|
||||
options.type = TT_ASSET_INCLUDES;
|
||||
parsingCmd = true;
|
||||
} else if(args[i] == "-c") {
|
||||
curOption = PO_TYPE;
|
||||
curOptionState = 4;
|
||||
options.type = TT_ASSET_COMPILE;
|
||||
parsingCmd = true;
|
||||
} else if(args[i] == "-fc") {
|
||||
curOption = PO_TYPE;
|
||||
curOptionState = 5;
|
||||
options.type = TT_ASSET_COMPRESS_FILE;
|
||||
parsingCmd = true;
|
||||
} else if(args[i] == "-fd") {
|
||||
curOption = PO_TYPE;
|
||||
curOptionState = 6;
|
||||
options.type = TT_ASSET_DECOMPRESS_FILE;
|
||||
parsingCmd = true;
|
||||
} else if(args[i] == "-h") {
|
||||
return false;
|
||||
} else {
|
||||
display_error("Invalid option \"", args[i], "\"");
|
||||
return false;
|
||||
}
|
||||
curOptionArgs = 0;
|
||||
} else {
|
||||
if(!parsingCmd) {
|
||||
display_error("Too many args for the current command \"", get_cmd_from_parse_option(options.type), "\"");
|
||||
return false;
|
||||
}
|
||||
switch(curOption) {
|
||||
case PO_TYPE:
|
||||
switch(curOptionState) {
|
||||
case 1: // Extractor
|
||||
switch(curOptionArgs) {
|
||||
case 0: // version
|
||||
case 1: // assets directory
|
||||
case 2: // configs directory
|
||||
case 3: // baseroms directory
|
||||
options.paths.push_back(args[i]);
|
||||
break;
|
||||
case 4: // output
|
||||
options.paths.push_back(args[i]);
|
||||
// End of arguments.
|
||||
parsingCmd = false;
|
||||
curOption = PO_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: // Builder
|
||||
switch(curOptionArgs) {
|
||||
case 0: // version
|
||||
case 1: // assets directory
|
||||
case 2: // source path
|
||||
options.paths.push_back(args[i]);
|
||||
break;
|
||||
case 3: // output
|
||||
options.paths.push_back(args[i]);
|
||||
// End of arguments.
|
||||
parsingCmd = false;
|
||||
curOption = PO_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: // Asset header
|
||||
switch(curOptionArgs) {
|
||||
case 0: // Assets directory
|
||||
case 1: // Enum file output path
|
||||
case 2: // Build directory
|
||||
case 3: // Asm output directory
|
||||
options.paths.push_back(args[i]);
|
||||
break;
|
||||
case 4: // DKR version
|
||||
options.paths.push_back(args[i]);
|
||||
// End of arguments.
|
||||
parsingCmd = false;
|
||||
curOption = PO_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4: // Compile assets
|
||||
case 5: // Compress file
|
||||
case 6: // Decompress file
|
||||
switch(curOptionArgs) {
|
||||
case 0: // Assets directory / Input filename
|
||||
options.paths.push_back(args[i]);
|
||||
break;
|
||||
case 1: // version / Output filename
|
||||
options.paths.push_back(args[i]);
|
||||
// End of arguments.
|
||||
parsingCmd = false;
|
||||
curOption = PO_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: // This should hopefully never get called
|
||||
display_error_and_abort("Invalid dkr_assets_tool option. You should not be seeing this message!");
|
||||
}
|
||||
curOptionArgs++;
|
||||
}
|
||||
}
|
||||
|
||||
if(parsingCmd) {
|
||||
display_error("Not enough args for the current command \"", get_cmd_from_parse_option(options.type), "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(!parse_options(argc, argv)) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(options.type) {
|
||||
case TT_EXTRACT:
|
||||
{
|
||||
std::string version = options.paths[0]; // us_1.0
|
||||
std::string assetsDir = options.paths[1]; // <root>/assets
|
||||
std::string configsPath = options.paths[2]; // <root>/extract-ver
|
||||
std::string baseromsPath = options.paths[3]; // <root>/baseroms
|
||||
std::string outputPath = options.paths[4]; // <root>
|
||||
|
||||
set_assets_folder_path(assetsDir + "/vanilla");
|
||||
set_version(version);
|
||||
|
||||
Extractor extractor(version, configsPath, baseromsPath, outputPath);
|
||||
}
|
||||
break;
|
||||
case TT_BUILD:
|
||||
{
|
||||
std::string version = options.paths[0]; // us_1.0
|
||||
std::string assetsDir = options.paths[1]; // <root>/assets
|
||||
std::string sourcePath = options.paths[2]; // Input .json filepath
|
||||
std::string outputPath = options.paths[3]; // Output .bin filepath
|
||||
|
||||
set_assets_folder_path(assetsDir);
|
||||
set_version(version);
|
||||
|
||||
Builder builder(sourcePath, outputPath);
|
||||
}
|
||||
break;
|
||||
case TT_ASSET_INCLUDES:
|
||||
{
|
||||
std::string version = options.paths[0]; // us_1.0
|
||||
std::string assetsDir = options.paths[1]; // <root>/assets
|
||||
std::string includeDir = options.paths[2]; // <root>/include
|
||||
std::string buildDir = options.paths[3]; // <root>/build
|
||||
std::string assetsAsmDir = options.paths[4]; // <root>/asm/assets
|
||||
|
||||
set_assets_folder_path(assetsDir);
|
||||
set_version(version);
|
||||
|
||||
AssetEnumsHeader assetEnumsHeader(includeDir);
|
||||
AssetAsmIncludes assetAsmIncludes(assetsDir + "/" + version, buildDir + "/" + version, assetsAsmDir);
|
||||
}
|
||||
break;
|
||||
case TT_ASSET_COMPILE:
|
||||
{
|
||||
std::string version = options.paths[0]; // us_1.0
|
||||
std::string assetsDir = options.paths[1]; // <root>/assets
|
||||
|
||||
set_assets_folder_path(assetsDir);
|
||||
set_version(version);
|
||||
|
||||
AssetCompiler compiler;
|
||||
}
|
||||
break;
|
||||
case TT_ASSET_COMPRESS_FILE:
|
||||
case TT_ASSET_DECOMPRESS_FILE:
|
||||
{
|
||||
DKRCompression compression;
|
||||
std::string inputFilename = options.paths[0];
|
||||
std::string outputFilename = options.paths[1];
|
||||
std::vector<uint8_t> inputBinary, outputBinary;
|
||||
|
||||
if(compression.readBinaryFile(inputBinary, inputFilename)) {
|
||||
if(inputBinary.size() == 0) {
|
||||
compression.writeBinaryFile(inputBinary, outputFilename);
|
||||
} else {
|
||||
if (options.type == TT_ASSET_COMPRESS_FILE) {
|
||||
outputBinary = compression.compressBuffer(inputBinary);
|
||||
} else if (options.type == TT_ASSET_DECOMPRESS_FILE) {
|
||||
outputBinary = compression.decompressBuffer(inputBinary);
|
||||
}
|
||||
compression.writeBinaryFile(outputBinary, outputFilename);
|
||||
}
|
||||
} else {
|
||||
display_error_and_abort("Could not read file: ", inputFilename);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
#include "build_fonts.h"
|
||||
|
||||
#define SIZEOF_FONTS_HEADER 4
|
||||
|
||||
// Note that these are just for DKR afaik. Other rare games have different sizes.
|
||||
#define SIZEOF_FONT 0x400 // Larger in later Rare games
|
||||
#define MAX_NUMBER_OF_TEXTURES 32 // Extended to 64 in later Rare games
|
||||
#define CHAR_NODE_START_OFFSET 32
|
||||
#define NUMBER_OF_CHAR_NODES 96 // Extended to 224 in later Rare games
|
||||
#define CHAR_NODE_END_OFFSET CHAR_NODE_START_OFFSET + NUMBER_OF_CHAR_NODES
|
||||
#define SIZEOF_CHAR_NODE 8
|
||||
|
||||
BuildFonts::BuildFonts(std::string srcPath, std::string dstPath) {
|
||||
|
||||
std::string fontFolderPath = get_directory_from_full_path(srcPath);
|
||||
|
||||
std::vector<std::string> fontIds = get_array_from_section("ASSET_FONTS", "fonts-order");
|
||||
int numberOfFonts = fontIds.size();
|
||||
|
||||
std::vector<uint8_t> out(align16(SIZEOF_FONT * numberOfFonts + SIZEOF_FONTS_HEADER));
|
||||
|
||||
// Write header.
|
||||
write_big_endian_word(out, 0, numberOfFonts);
|
||||
|
||||
// Write fonts.
|
||||
for(int font = 0; font < numberOfFonts; font++) {
|
||||
std::string fontPath = fontFolderPath + "/" + get_string_from_json(srcPath, "fonts", fontIds[font]);
|
||||
|
||||
int fontOffset = font * SIZEOF_FONT + SIZEOF_FONTS_HEADER;
|
||||
|
||||
insert_ascii(out, fontOffset, get_string_from_json(fontPath, "name"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x20, get_int_from_json(fontPath, "fixed-width"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x22, get_int_from_json(fontPath, "y-offset"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x24, get_int_from_json(fontPath, "special-character-width"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x26, get_int_from_json(fontPath, "tab-width"));
|
||||
insert_ascii(out, fontOffset + 0x28, get_string_from_json(fontPath, "unknown-text"));
|
||||
|
||||
int numberOfTextures = get_array_length_from_json(fontPath, "textures");
|
||||
int texOffset = fontOffset + 0x40;
|
||||
int texIndex = 0;
|
||||
// Write texture ids.
|
||||
for(; texIndex < numberOfTextures; texIndex++) {
|
||||
write_big_endian_halfword(out, texOffset, get_tex_2d_index_from_build_id(get_string_from_json(fontPath, "textures", texIndex)));
|
||||
texOffset += 2;
|
||||
}
|
||||
// Fill rest of the space with -1.
|
||||
for(; texIndex < MAX_NUMBER_OF_TEXTURES; texIndex++) {
|
||||
write_big_endian_halfword(out, texOffset, -1);
|
||||
texOffset += 2;
|
||||
}
|
||||
|
||||
std::string encoding = get_string_from_json(fontPath, "encoding", "type");
|
||||
make_uppercase(encoding);
|
||||
|
||||
bool uppercaseOnly = false;
|
||||
|
||||
if(json_has_key(fontPath, "uppercase-only")) {
|
||||
uppercaseOnly = get_bool_from_json(fontPath, "uppercase-only");
|
||||
}
|
||||
|
||||
// Write character nodes
|
||||
if(encoding == "ASCII") {
|
||||
write_ascii_char_nodes(out, fontPath, fontOffset + 0x100, uppercaseOnly);
|
||||
} else if(encoding == "CUSTOM") {
|
||||
write_custom_char_nodes(out, fontPath, fontOffset + 0x100, uppercaseOnly);
|
||||
} else {
|
||||
display_error_and_abort("Unsupported font encoding type: \"", encoding, "\"");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write_binary_file(out, dstPath);
|
||||
}
|
||||
|
||||
BuildFonts::~BuildFonts() {
|
||||
|
||||
}
|
||||
|
||||
void write_char_node(std::vector<uint8_t> &out, std::string fontPath, int nodeOffset, std::string &chr) {
|
||||
if(json_has_key(fontPath, "characters", chr)) {
|
||||
out[nodeOffset] = get_int_from_json(fontPath, "characters", chr, "tex-index");
|
||||
out[nodeOffset + 1] = get_int_from_json(fontPath, "characters", chr, "char-width");
|
||||
out[nodeOffset + 2] = get_int_from_json(fontPath, "characters", chr, "offset", 0); // X offset
|
||||
out[nodeOffset + 3] = get_int_from_json(fontPath, "characters", chr, "offset", 1); // Y offset
|
||||
out[nodeOffset + 4] = get_int_from_json(fontPath, "characters", chr, "uv", 0); // U coordinate
|
||||
out[nodeOffset + 5] = get_int_from_json(fontPath, "characters", chr, "uv", 1); // V coordinate
|
||||
out[nodeOffset + 6] = get_int_from_json(fontPath, "characters", chr, "tex-size", 0); // Width
|
||||
out[nodeOffset + 7] = get_int_from_json(fontPath, "characters", chr, "tex-size", 1); // Height
|
||||
} else { // Node doesn't exist, so just mark it as empty.
|
||||
out[nodeOffset] = -1;
|
||||
out[nodeOffset + 1] = 0;
|
||||
out[nodeOffset + 2] = 0;
|
||||
out[nodeOffset + 3] = 0;
|
||||
out[nodeOffset + 4] = 0;
|
||||
out[nodeOffset + 5] = 0;
|
||||
out[nodeOffset + 6] = 0;
|
||||
out[nodeOffset + 7] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BuildFonts::write_ascii_char_nodes(std::vector<uint8_t> &out, std::string fontPath, int offset, bool uppercaseOnly) {
|
||||
for(int node = CHAR_NODE_START_OFFSET; node < CHAR_NODE_END_OFFSET; node++) {
|
||||
std::string chr;
|
||||
if(node == 127) {
|
||||
chr = "DEL"; // Special case because the delete character itself is sometimes weird.
|
||||
} else if (node == 92) {
|
||||
chr = "\\\\";
|
||||
} else if (node == 34) {
|
||||
chr = "\\\"";
|
||||
} else {
|
||||
chr = (char)node;
|
||||
}
|
||||
int nodeOffset = offset + (node - CHAR_NODE_START_OFFSET) * SIZEOF_CHAR_NODE;
|
||||
if(uppercaseOnly && node >= (int)'a' && node <= (int)'z') {
|
||||
make_uppercase(chr);
|
||||
}
|
||||
write_char_node(out, fontPath, nodeOffset, chr);
|
||||
}
|
||||
}
|
||||
|
||||
void BuildFonts::write_custom_char_nodes(std::vector<uint8_t> &out, std::string fontPath, int offset, bool uppercaseOnly) {
|
||||
int index = 0;
|
||||
std::vector<std::string> order = get_array_from_json(fontPath, "encoding", "order");
|
||||
for(std::string &chr : order) {
|
||||
if(index >= NUMBER_OF_CHAR_NODES) {
|
||||
std::string fontName = get_string_from_json(fontPath, "name");
|
||||
display_error_and_abort("Too many character nodes in ", fontName, ". The limit is ", NUMBER_OF_CHAR_NODES);
|
||||
}
|
||||
int nodeOffset = offset + (index++ * SIZEOF_CHAR_NODE);
|
||||
write_char_node(out, fontPath, nodeOffset, chr);
|
||||
}
|
||||
// Set the rest of the nodes to show nothing.
|
||||
while(index < NUMBER_OF_CHAR_NODES) {
|
||||
int nodeOffset = offset + (index++ * SIZEOF_CHAR_NODE);
|
||||
out[nodeOffset] = -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../common/util.h"
|
||||
//#include "macros.h"
|
||||
|
||||
class BuildFonts {
|
||||
public:
|
||||
BuildFonts(std::string srcPath, std::string dstPath);
|
||||
~BuildFonts();
|
||||
private:
|
||||
void write_ascii_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset, bool uppercaseOnly);
|
||||
void write_custom_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset, bool uppercaseOnly);
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "build_gametext.h"
|
||||
|
||||
// Dialog
|
||||
#define END_OF_LINES 0x00
|
||||
#define ACTIVE_LINE 0x01
|
||||
#define CONTINUE 0x0C
|
||||
|
||||
// Textbox
|
||||
#define NEXT_PAGE 0x01
|
||||
|
||||
BuildGameText::BuildGameText(std::string srcPath, std::string dstPath) {
|
||||
std::vector<uint8_t> out;
|
||||
|
||||
|
||||
// TODO: Figure this out!
|
||||
|
||||
std::string textType = get_string_from_json(srcPath, "text-type");
|
||||
if(textType == "Dialog") {
|
||||
// This is temporary until the game text format is figured out
|
||||
int numRawBytes = get_array_length_from_json(srcPath, "raw");
|
||||
|
||||
for(int i = 0; i < numRawBytes; i++) {
|
||||
out.push_back(get_int_from_json(srcPath, "raw", i));
|
||||
}
|
||||
//build_dialog(out, srcPath);
|
||||
} else {
|
||||
build_textbox(out, srcPath);
|
||||
}
|
||||
|
||||
|
||||
while(out.size() % 8 != 0) {
|
||||
out.push_back(0); // Make sure the data is 8-byte aligned.
|
||||
}
|
||||
|
||||
|
||||
write_binary_file(out, dstPath);
|
||||
}
|
||||
|
||||
BuildGameText::~BuildGameText() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
void BuildGameText::build_dialog(std::vector<uint8_t> &out, std::string &srcPath) {
|
||||
int numberOfLines = GET_ARRAY_LENGTH("lines");
|
||||
for(int i = 0; i < numberOfLines; i++) {
|
||||
if(inputJSON["lines"][i].JSONType() == json::JSON::Class::String) {
|
||||
out.push_back(CONTINUE);
|
||||
continue;
|
||||
}
|
||||
if(HAS_KEY("unknown-data", "lines", i)) { // Check if the key "unknown-data" exists.
|
||||
for(int j = 0; j < GET_ARRAY_LENGTH("lines", i, "unknown-data"); j++) {
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "unknown-data", j));
|
||||
}
|
||||
break;
|
||||
}
|
||||
out.push_back(ACTIVE_LINE);
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "color", "red"));
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "color", "green"));
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "color", "blue"));
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "color", "alpha"));
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "font"));
|
||||
out.push_back(get_int_from_json(srcPath, "lines", i, "alignment"));
|
||||
out.push_back((uint8_t)(GET_FLOAT("lines", i, "time") * 5));
|
||||
write_ascii(out, get_string_from_json(srcPath, "lines", i, "text"));
|
||||
//if(i < numberOfLines - 1 && !HAS_KEY("unknown-data", "lines", i + 1)) {
|
||||
// out.push_back(CONTINUE);
|
||||
//}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void write_basic_command(std::vector<uint8_t> &out, uint8_t cmdId, uint8_t value) {
|
||||
out.push_back(cmdId);
|
||||
out.push_back(value);
|
||||
}
|
||||
|
||||
void write_basic_command_4_args(std::vector<uint8_t> &out, uint8_t cmdId, uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||
out.push_back(cmdId);
|
||||
out.push_back(a);
|
||||
out.push_back(b);
|
||||
out.push_back(c);
|
||||
out.push_back(d);
|
||||
}
|
||||
|
||||
void BuildGameText::build_textbox(std::vector<uint8_t> &out, std::string &srcPath) {
|
||||
int numberOfPages = get_array_length_from_json(srcPath, "pages");
|
||||
for(int page = 0; page < numberOfPages; page++) {
|
||||
int numberOfCommandsInPage = get_array_length_from_json(srcPath, "pages", page);
|
||||
for(int cmd = 0; cmd < numberOfCommandsInPage; cmd++) {
|
||||
std::string cmdType = get_string_from_json(srcPath, "pages", page, cmd, "command");
|
||||
if(cmdType == "Text") {
|
||||
write_ascii(out, get_string_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
} else if(cmdType == "SetFont") {
|
||||
std::string fontId = get_string_from_json(srcPath, "pages", page, cmd, "value");
|
||||
int fontIndex = get_index_of_string_array_value_from_section("ASSET_FONTS", fontId, "fonts-order");
|
||||
if(fontIndex == -1) {
|
||||
display_error_and_abort("Could not find the font \"", fontId, "\" in the \"fonts-order\" array in asset_fonts.json.");
|
||||
}
|
||||
write_basic_command(out, 3, fontIndex);
|
||||
} else if(cmdType == "SetBorder") {
|
||||
write_basic_command_4_args(out, 4,
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "left"),
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "top"),
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "right"),
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "bottom")
|
||||
);
|
||||
} else if(cmdType == "SetColour") {
|
||||
write_basic_command_4_args(out, 5,
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "red"),
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "green"),
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "blue"),
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "alpha")
|
||||
);
|
||||
} else if(cmdType == "SetAlignment") {
|
||||
write_basic_command(out, 6, get_string_from_json(srcPath, "pages", page, cmd, "value") == "center" ? 0 : 4);
|
||||
} else if(cmdType == "Unknown") {
|
||||
write_basic_command(out, 7, get_int_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
} else if(cmdType == "AddVerticalSpacing") {
|
||||
write_basic_command(out, 8, get_int_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
} else if(cmdType == "SetLineHeight") {
|
||||
write_basic_command(out, 9, get_int_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
} else if(cmdType == "SetTimer") {
|
||||
write_basic_command(out, 10, get_int_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
} else if(cmdType == "AllowUserInput") {
|
||||
write_basic_command(out, 11, get_bool_from_json(srcPath, "pages", page, cmd, "value") ? 1 : 0);
|
||||
}
|
||||
}
|
||||
if(page < numberOfPages - 1) {
|
||||
out.push_back(NEXT_PAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../common/util.h"
|
||||
|
||||
class BuildGameText {
|
||||
public:
|
||||
BuildGameText(std::string srcPath, std::string dstPath);
|
||||
~BuildGameText();
|
||||
private:
|
||||
/*
|
||||
void build_dialog(std::vector<uint8_t> &out, std::string &srcPath);
|
||||
*/
|
||||
void build_textbox(std::vector<uint8_t> &out, std::string &srcPath);
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "build_levelheader.h"
|
||||
|
||||
#define GET_UNKNOWN_VALUE(name, index) get_int_from_json(srcPath, "unknown-data", name, index)
|
||||
#define GET_UNKNOWN_VALUES(out, start, end, name) \
|
||||
for(int i = start; i < end; i++) { \
|
||||
out[i] = GET_UNKNOWN_VALUE(name, i - start); \
|
||||
}
|
||||
|
||||
int get_bitfield_from_enum_values(std::string &srcPath, std::string propertyName, std::string enumName) {
|
||||
int numEntries = get_array_length_from_json(srcPath, propertyName);
|
||||
int out = 0;
|
||||
for(int i = 0; i < numEntries; i++) {
|
||||
out |= 1 << get_enum_value_from_string(enumName, get_string_from_json(srcPath, propertyName, i));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
BuildLevelHeader::BuildLevelHeader(std::string srcPath, std::string dstPath) {
|
||||
std::vector<uint8_t> out(SIZEOF_LEVEL_HEADER);
|
||||
|
||||
// World ID
|
||||
out[0] = get_enum_value_from_string("World", get_string_from_json(srcPath, "world"));
|
||||
|
||||
out[1] = get_int_from_json(srcPath, "unknown-data", "unk1");
|
||||
out[2] = get_int_from_json(srcPath, "unknown-data", "unk2");
|
||||
out[3] = get_int_from_json(srcPath, "unknown-data", "unk3");
|
||||
GET_UNKNOWN_VALUES(out, 4, 8, "unk4");
|
||||
|
||||
// Ceiling height for planes
|
||||
write_big_endian_float(out, 8, get_float_from_json(srcPath, "ceiling-height"));
|
||||
|
||||
GET_UNKNOWN_VALUES(out, 0xC, 0x34, "unkC");
|
||||
|
||||
// Track ID to use
|
||||
write_big_endian_halfword(out, 0x34, get_index_from_build_id("ASSET_LEVEL_MODELS", get_string_from_json(srcPath, "model")));
|
||||
|
||||
// Collectables bitflags (bananas, balloons, etc)
|
||||
write_big_endian_halfword(out, 0x36, get_int_from_json(srcPath, "collectables"));
|
||||
|
||||
// Skydome object model ID
|
||||
write_big_endian_halfword(out, 0x38, get_int_from_json(srcPath, "skybox"));
|
||||
|
||||
// Fog
|
||||
write_big_endian_halfword(out, 0x3A, get_int_from_json(srcPath, "fog", "range", "min"));
|
||||
write_big_endian_halfword(out, 0x3C, get_int_from_json(srcPath, "fog", "range", "max"));
|
||||
write_big_endian_halfword(out, 0x3E, get_int_from_json(srcPath, "fog", "colour", "red"));
|
||||
write_big_endian_halfword(out, 0x40, get_int_from_json(srcPath, "fog", "colour", "green"));
|
||||
write_big_endian_halfword(out, 0x42, get_int_from_json(srcPath, "fog", "colour", "blue"));
|
||||
|
||||
GET_UNKNOWN_VALUES(out, 0x44, 0x4B, "unk44");
|
||||
|
||||
// Number of laps to complete the race.
|
||||
out[0x4B] = get_int_from_json(srcPath, "number-laps");
|
||||
|
||||
// Type of race (standard, boss race, hub world, etc.
|
||||
out[0x4C] = get_enum_value_from_string("RaceType", get_string_from_json(srcPath, "race-type"));
|
||||
|
||||
// Default vehicle used for this track. (Either Car, Hovercraft, or Plane)
|
||||
out[0x4D] = get_enum_value_from_string("Vehicle", get_string_from_json(srcPath, "default-vehicle"));
|
||||
|
||||
// Which vehicles can be used in this track (Either Car, Hovercraft, or Plane)
|
||||
out[0x4E] = get_bitfield_from_enum_values(srcPath, "available-vehicles", "Vehicle");
|
||||
GET_UNKNOWN_VALUES(out, 0x4F, 0x52, "unk4F");
|
||||
|
||||
// Music ID to use for this track
|
||||
out[0x52] = get_int_from_json(srcPath, "music");
|
||||
|
||||
// Unknown, but *probably* related to audio.
|
||||
out[0x53] = get_int_from_json(srcPath, "unknown-data", "unk53");
|
||||
|
||||
// Instruments bitflags. Most levels have 0xFFFF, except for the central hub which is 0xB
|
||||
write_big_endian_halfword(out, 0x54, get_int_from_json(srcPath, "instruments"));
|
||||
|
||||
GET_UNKNOWN_VALUES(out, 0x56, 0x74, "unk56");
|
||||
for(int i = 0; i < 7; i++) {
|
||||
write_big_endian_word(out, 0x74 + (i * 4), get_int_from_json(srcPath, "unknown-data", "unk74", i));
|
||||
}
|
||||
|
||||
// Weather values currently unknown.
|
||||
write_big_endian_halfword(out, 0x90, get_int_from_json(srcPath, "unknown-data", "weather", "unk90"));
|
||||
write_big_endian_halfword(out, 0x92, get_int_from_json(srcPath, "unknown-data", "weather", "unk92"));
|
||||
out[0x94] = get_int_from_json(srcPath, "unknown-data", "weather", "unk94");
|
||||
out[0x95] = get_int_from_json(srcPath, "unknown-data", "weather", "unk95");
|
||||
write_big_endian_halfword(out, 0x96, get_int_from_json(srcPath, "unknown-data", "weather", "unk96"));
|
||||
write_big_endian_halfword(out, 0x98, get_int_from_json(srcPath, "unknown-data", "weather", "unk98"));
|
||||
write_big_endian_halfword(out, 0x9A, get_int_from_json(srcPath, "unknown-data", "weather", "unk9A"));
|
||||
|
||||
// Field of view
|
||||
out[0x9C] = get_int_from_json(srcPath, "fov");
|
||||
|
||||
// Background clear color
|
||||
out[0x9D] = get_int_from_json(srcPath, "background-colour", "red");
|
||||
out[0x9E] = get_int_from_json(srcPath, "background-colour", "green");
|
||||
out[0x9F] = get_int_from_json(srcPath, "background-colour", "blue");
|
||||
|
||||
GET_UNKNOWN_VALUES(out, 0xA0, 0xA4, "unkA0");
|
||||
write_big_endian_word(out, 0xA4, get_int_from_json(srcPath, "unknown-data", "unkA4"));
|
||||
write_big_endian_halfword(out, 0xA8, get_int_from_json(srcPath, "unknown-data", "unkA8"));
|
||||
write_big_endian_halfword(out, 0xAA, get_int_from_json(srcPath, "unknown-data", "unkAA"));
|
||||
|
||||
// Pulsating lights are only used in spaceport alpha
|
||||
int pulsatingLights = -1;
|
||||
if(json_has_key(srcPath, "pulsating-lights")) {
|
||||
pulsatingLights = get_index_from_build_id("ASSET_MISC", get_string_from_json(srcPath, "pulsating-lights"));
|
||||
}
|
||||
write_big_endian_word(out, 0xAC, pulsatingLights);
|
||||
|
||||
GET_UNKNOWN_VALUES(out, 0xB0, 0xC4, "unkB0");
|
||||
write_big_endian_word(out, 0xC4, get_int_from_json(srcPath, "unknown-data", "unkC4"));
|
||||
|
||||
write_binary_file(out, dstPath);
|
||||
}
|
||||
|
||||
BuildLevelHeader::~BuildLevelHeader() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../common/util.h"
|
||||
|
||||
#define SIZEOF_LEVEL_HEADER 0xC8
|
||||
|
||||
class BuildLevelHeader {
|
||||
public:
|
||||
BuildLevelHeader(std::string srcPath, std::string dstPath);
|
||||
~BuildLevelHeader();
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "build_levelname.h"
|
||||
|
||||
BuildLevelName::BuildLevelName(std::string srcPath, std::string dstPath) {
|
||||
std::vector<uint8_t> out;
|
||||
|
||||
std::vector<std::string> languages = get_enum_keys("Language");
|
||||
|
||||
int numLangWritten = 0;
|
||||
|
||||
// Search through and add all the avaliable languages.
|
||||
// Note: If a language is not defined in the enum, then it won't be added to the output!
|
||||
for(auto &langName : languages) {
|
||||
if(json_has_key(srcPath, "languages", langName)) { // Check if the level name json has the language.
|
||||
write_ascii(out, get_string_from_json(srcPath, "languages", langName));
|
||||
numLangWritten++;
|
||||
} else {
|
||||
// Language not found. For now, this means the text will be empty.
|
||||
// TODO: Maybe have an option to default to english?
|
||||
out.push_back('\0'); // Push back a null terminator
|
||||
}
|
||||
}
|
||||
|
||||
if(numLangWritten == 0) {
|
||||
std::cout << "Warning: No languages were found." << std::endl;
|
||||
}
|
||||
|
||||
write_binary_file(out, dstPath);
|
||||
}
|
||||
|
||||
BuildLevelName::~BuildLevelName() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../common/util.h"
|
||||
|
||||
class BuildLevelName {
|
||||
public:
|
||||
BuildLevelName(std::string srcPath, std::string dstPath);
|
||||
~BuildLevelName();
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "build_menutext.h"
|
||||
|
||||
BuildMenuText::BuildMenuText(std::string srcPath, std::string dstPath) {
|
||||
//int numberOfEntries = get_array_length_from_json(srcPath, "order");
|
||||
|
||||
std::vector<std::string> ids = get_array_from_section("ASSET_MENU_TEXT", "menu-text-build-ids");
|
||||
int numberOfEntries = ids.size();
|
||||
|
||||
std::vector<uint8_t> table(numberOfEntries * 4);
|
||||
std::vector<uint8_t> text;
|
||||
|
||||
int textOffset = numberOfEntries * 4;
|
||||
|
||||
for(int i = 0; i < numberOfEntries; i++) {
|
||||
// Get the build id for this index.
|
||||
std::string buildId = ids[i];
|
||||
|
||||
// If the build ID is not in the sections, then just write -1 to the table.
|
||||
if(!json_has_key(srcPath, "sections", buildId)) {
|
||||
write_big_endian_word(table, i * 4, -1);
|
||||
continue;
|
||||
}
|
||||
// Get the text string from the inputJSON.
|
||||
std::string entryText = get_string_from_json(srcPath, "sections", buildId);
|
||||
// Write ascii text to vector
|
||||
write_ascii(text, entryText);
|
||||
// Write the offset to the text
|
||||
write_big_endian_word(table, i * 4, textOffset);
|
||||
// Increment the current offset by the length of the string (+1 for null terminator)
|
||||
textOffset += entryText.length() + 1;
|
||||
}
|
||||
|
||||
// Append the text data to the table data.
|
||||
table.insert(table.end(), text.begin(), text.end());
|
||||
|
||||
while(table.size() % 8 != 0) {
|
||||
table.push_back(0); // Make sure the data is 8-byte aligned.
|
||||
}
|
||||
|
||||
write_binary_file(table, dstPath);
|
||||
}
|
||||
|
||||
BuildMenuText::~BuildMenuText(){
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../common/util.h"
|
||||
|
||||
class BuildMenuText {
|
||||
public:
|
||||
BuildMenuText(std::string srcPath, std::string dstPath);
|
||||
~BuildMenuText();
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user