mirror of
https://github.com/HackerN64/F3DEX3.git
synced 2026-01-21 10:37:45 -08:00
Adds a few more toolchains while at the same time cleaning how the makefile checks for toolchains in the first place (Avoids endif spam)
233 lines
7.3 KiB
Makefile
233 lines
7.3 KiB
Makefile
# To build, run something like `make F3DEX3_BrZ` or`make F3DEX3_BrW_NOC_PA`.
|
|
# For an explanation of what all the suffixes mean, see README.md.
|
|
|
|
MAKEFLAGS += --no-builtin-rules
|
|
MAKEFLAGS += --no-builtin-variables
|
|
.SUFFIXES:
|
|
|
|
default: F3DEX3_BrZ F3DEX3_BrW
|
|
|
|
# The F3DEX3 version letter is incremented when there are major, GBI-breaking
|
|
# changes. This goes in the microcode ID string so HLE can detect the version.
|
|
VERSION = _B
|
|
|
|
# List of all compile-time options supported by the microcode source.
|
|
ALL_OPTIONS := \
|
|
CFG_G_BRANCH_W \
|
|
CFG_NO_OCCLUSION_PLANE \
|
|
CFG_PROFILING_A \
|
|
CFG_PROFILING_B \
|
|
CFG_PROFILING_C
|
|
|
|
ARMIPS ?= armips
|
|
PARENT_OUTPUT_DIR ?= ./build
|
|
ifeq ($(PARENT_OUTPUT_DIR),.)
|
|
$(error Cannot build directly in repo directory; see Makefile for details.)
|
|
# The problem is that we want to be able to have targets like F3DEX2_2.08,
|
|
# but this would also be the directory itself, whose existence and possible
|
|
# modification needs to be handled by the Makefile. It is possible to write
|
|
# the Makefile where the directory is the main target for that microcode, but
|
|
# this has worse behavior in case of modification to the directory. Worse, if
|
|
# it was done this way, then it would break if the user tried to set
|
|
# PARENT_OUTPUT_DIR anywhere else. So, better to support building everywhere
|
|
# but here than to support only building here.
|
|
endif
|
|
|
|
# Find the N64 toolchain, for creating object files.
|
|
ifneq (, $(shell which mips64-elf-ld)
|
|
CROSS := mips64-elf-
|
|
else ifneq (, $(shell which mips-n64-ld)
|
|
CROSS := mips-n64-
|
|
else ifneq (, $(shell which mips64-ld)
|
|
CROSS := mips64-
|
|
else ifneq (, $(shell which mips-linux-gnu-ld)
|
|
CROSS := mips-linux-gnu-
|
|
else ifneq (, $(shell which mips64-linux-gnu-ld)
|
|
CROSS := mips64-linux-gnu-
|
|
else ifneq (, $(shell which mips-ld)
|
|
CROSS := mips-
|
|
else ifneq (, $(shell which mips64-linux-gnuabi64-ld)
|
|
CROSS := mips64-linux-gnuabi64-
|
|
else ifneq (, $(shell which mips64-ultra-elf-ld)
|
|
CROSS := mips64-ultra-elf-
|
|
else
|
|
$(warning Could not find N64 linker, not building object files)
|
|
AS :=
|
|
endif
|
|
|
|
NO_COL := \033[0m
|
|
RED := \033[0;31m
|
|
GREEN := \033[0;32m
|
|
YELLOW := \033[0;33m
|
|
BLUE := \033[0;34m
|
|
INFO := $(BLUE)
|
|
SUCCESS := $(GREEN)
|
|
FAILURE := $(RED)
|
|
WARNING := $(YELLOW)
|
|
|
|
$(PARENT_OUTPUT_DIR):
|
|
@printf "$(INFO)Creating parent output directory$(NO_COL)\n"
|
|
ifeq ($(OS),Windows_NT)
|
|
mkdir $@
|
|
else
|
|
mkdir -p $@
|
|
endif
|
|
ALL_UCODES :=
|
|
ALL_UCODES_WITH_MD5S :=
|
|
ALL_OUTPUT_DIRS :=
|
|
|
|
ifneq (, $(AS))
|
|
%.o: %.o.s
|
|
@$(AS) -march=vr4300 -mabi=32 -I . $< -o $@
|
|
endif
|
|
|
|
define reset_vars
|
|
NAME :=
|
|
DESCRIPTION :=
|
|
ID_STR :=
|
|
MD5_CODE :=
|
|
MD5_DATA :=
|
|
OPTIONS :=
|
|
EXTRA_DEPS :=
|
|
endef
|
|
|
|
define ucode_rule
|
|
# Variables defined outside the function need one dollar sign, whereas
|
|
# variables defined within the function need two. This is because make first
|
|
# expands all this text, substituting single-dollar-sign variables, and then
|
|
# executes all of it, causing all the assignments to actually happen.
|
|
ifeq ($(NAME),)
|
|
$$(error Microcode name not set!)
|
|
endif
|
|
UCODE_OUTPUT_DIR := $(PARENT_OUTPUT_DIR)/$(NAME)
|
|
CODE_FILE := $$(UCODE_OUTPUT_DIR)/$(NAME).code
|
|
DATA_FILE := $$(UCODE_OUTPUT_DIR)/$(NAME).data
|
|
SYM_FILE := $$(UCODE_OUTPUT_DIR)/$(NAME).sym
|
|
TEMP_FILE := $$(UCODE_OUTPUT_DIR)/$(NAME).tmp.s
|
|
OS_FILE := $$(UCODE_OUTPUT_DIR)/gsp$(NAME).o.s
|
|
O_FILE := $$(UCODE_OUTPUT_DIR)/gsp$(NAME).o
|
|
ALL_UCODES += $(NAME)
|
|
ifneq ($(MD5_CODE),)
|
|
ALL_UCODES_WITH_MD5S += $(NAME)
|
|
endif
|
|
ALL_OUTPUT_DIRS += $$(UCODE_OUTPUT_DIR)
|
|
OFF_OPTIONS := $(filter-out $(OPTIONS),$(ALL_OPTIONS))
|
|
OPTIONS_EQU :=
|
|
$$(foreach option,$(OPTIONS),$$(eval OPTIONS_EQU += -equ $$(option) 1))
|
|
OFF_OPTIONS_EQU :=
|
|
$$(foreach o2,$$(OFF_OPTIONS),$$(eval OFF_OPTIONS_EQU += -equ $$(o2) 0))
|
|
ARMIPS_CMDLINE := \
|
|
-strequ CODE_FILE $$(CODE_FILE) \
|
|
-strequ DATA_FILE $$(DATA_FILE) \
|
|
$$(OPTIONS_EQU) \
|
|
$$(OFF_OPTIONS_EQU) \
|
|
f3dex3.s \
|
|
-sym2 $$(SYM_FILE) \
|
|
-temp $$(TEMP_FILE)
|
|
# Microcode target
|
|
.PHONY: $(NAME)
|
|
$(NAME): $$(CODE_FILE)
|
|
ifneq (, $(AS))
|
|
$(NAME): $$(O_FILE)
|
|
endif
|
|
# Directory target variables, see below.
|
|
$$(UCODE_OUTPUT_DIR): UCODE_OUTPUT_DIR:=$$(UCODE_OUTPUT_DIR)
|
|
# Directory target recipe
|
|
$$(UCODE_OUTPUT_DIR):
|
|
@printf "$(INFO)Creating directory $$(UCODE_OUTPUT_DIR)$(NO_COL)\n"
|
|
ifeq ($(OS),Windows_NT)
|
|
@mkdir $$(subst /,\,$$(UCODE_OUTPUT_DIR))
|
|
else
|
|
@mkdir -p $$(UCODE_OUTPUT_DIR)
|
|
endif
|
|
# Code file target variables. make does not expand variables within recipes
|
|
# until the recipe is executed, meaning that all the parts of the recipe would
|
|
# have the values from the very last microcode in the file. Here, we set
|
|
# target-specific variables--effectively local variables within the recipe--
|
|
# to the values from the global variables have right now. We are only
|
|
# targeting CODE_FILE even though we also want DATA_FILE, because target-
|
|
# specific variables may not work as expected with multiple targets from one
|
|
# recipe.
|
|
$$(CODE_FILE): ARMIPS_CMDLINE:=$$(ARMIPS_CMDLINE)
|
|
$$(CODE_FILE): CODE_FILE:=$$(CODE_FILE)
|
|
$$(CODE_FILE): DATA_FILE:=$$(DATA_FILE)
|
|
$$(OS_FILE): OS_FILE:=$$(OS_FILE)
|
|
$$(OS_FILE): NAME:=$$(NAME)
|
|
# Target recipe
|
|
$$(CODE_FILE): ./f3dex3.s ./rsp/* $(EXTRA_DEPS) | $$(UCODE_OUTPUT_DIR)
|
|
@printf "$(INFO)Building microcode: $(NAME): $(DESCRIPTION)$(NO_COL)\n"
|
|
@$(ARMIPS) -strequ ID_STR "$(ID_STR)" $$(ARMIPS_CMDLINE)
|
|
ifneq ($(MD5_CODE),)
|
|
@(printf "$(MD5_CODE) *$$(CODE_FILE)" | md5sum --status -c -) && printf " $(SUCCESS)$(NAME) code matches$(NO_COL)\n" || printf " $(FAILURE)$(NAME) code differs$(NO_COL)\n"
|
|
@(printf "$(MD5_DATA) *$$(DATA_FILE)" | md5sum --status -c -) && printf " $(SUCCESS)$(NAME) data matches$(NO_COL)\n" || printf " $(FAILURE)$(NAME) data differs$(NO_COL)\n"
|
|
endif
|
|
ifneq (, $(AS))
|
|
$$(OS_FILE): $$(CODE_FILE)
|
|
@sed "s|XXX|$(NAME)|g" ./template.o.s > $$(OS_FILE)
|
|
endif
|
|
$$(eval $$(call reset_vars))
|
|
endef
|
|
|
|
$(eval $(call reset_vars))
|
|
|
|
define rule_builder_final
|
|
NAME := F3DEX3$(NAME_FINAL)
|
|
DESCRIPTION := Will make you want to finally ditch HLE ($(OPTIONS_FINAL))
|
|
ID_STR := F3DEX3$(NAME_FINAL)$(VERSION) by Sauraen & Yoshitaka Yasumoto/Nintendo
|
|
OPTIONS := $(OPTIONS_FINAL)
|
|
$$(eval $$(call ucode_rule))
|
|
endef
|
|
|
|
define rule_builder_prof
|
|
NAME_FINAL := $(NAME_PROF)
|
|
OPTIONS_FINAL := $(OPTIONS_PROF)
|
|
$$(eval $$(call rule_builder_final))
|
|
|
|
NAME_FINAL := $(NAME_PROF)_PA
|
|
OPTIONS_FINAL := $(OPTIONS_PROF) CFG_PROFILING_A
|
|
$$(eval $$(call rule_builder_final))
|
|
|
|
NAME_FINAL := $(NAME_PROF)_PB
|
|
OPTIONS_FINAL := $(OPTIONS_PROF) CFG_PROFILING_B
|
|
$$(eval $$(call rule_builder_final))
|
|
|
|
NAME_FINAL := $(NAME_PROF)_PC
|
|
OPTIONS_FINAL := $(OPTIONS_PROF) CFG_PROFILING_C
|
|
$$(eval $$(call rule_builder_final))
|
|
endef
|
|
|
|
define rule_builder_noc
|
|
NAME_PROF := $(NAME_NOC)
|
|
OPTIONS_PROF := $(OPTIONS_NOC)
|
|
$$(eval $$(call rule_builder_prof))
|
|
|
|
NAME_PROF := $(NAME_NOC)_NOC
|
|
OPTIONS_PROF := $(OPTIONS_NOC) CFG_NO_OCCLUSION_PLANE
|
|
$$(eval $$(call rule_builder_prof))
|
|
endef
|
|
|
|
define rule_builder_br
|
|
NAME_NOC := $(NAME_BR)_BrZ
|
|
OPTIONS_NOC := $(OPTIONS_BR)
|
|
$$(eval $$(call rule_builder_noc))
|
|
|
|
NAME_NOC := $(NAME_BR)_BrW
|
|
OPTIONS_NOC := $(OPTIONS_BR) CFG_G_BRANCH_W
|
|
$$(eval $$(call rule_builder_noc))
|
|
endef
|
|
|
|
NAME_BR :=
|
|
OPTIONS_BR :=
|
|
$(eval $(call rule_builder_br))
|
|
|
|
.PHONY: default ok all clean
|
|
|
|
all: $(ALL_UCODES)
|
|
|
|
clean:
|
|
@printf "$(WARNING)Deleting all built microcode files$(NO_COL)\n"
|
|
@rm -rf $(ALL_OUTPUT_DIRS)
|
|
|
|
doc:
|
|
doxygen Doxyfile
|