2025-01-17 20:53:47 -08:00
# To build, run something like `make F3DEX3_BrZ` or`make F3DEX3_BrW_NOC_PA`.
2024-11-18 21:44:58 -08:00
# For an explanation of what all the suffixes mean, see README.md.
2024-03-17 18:53:28 -07:00
2023-02-15 22:28:04 -08:00
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --no-builtin-variables
.SUFFIXES :
2023-10-21 15:24:26 -07:00
default : F 3DEX 3_BrZ F 3DEX 3_BrW
2023-02-14 10:44:08 -08:00
2025-07-22 21:17:31 -07:00
# 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
2023-10-21 15:24:26 -07:00
# List of all compile-time options supported by the microcode source.
2023-02-14 10:44:08 -08:00
ALL_OPTIONS := \
2023-12-23 22:47:48 -08:00
CFG_G_BRANCH_W \
2024-03-15 22:50:23 -07:00
CFG_NO_OCCLUSION_PLANE \
2024-02-27 21:30:23 -08:00
CFG_PROFILING_A \
CFG_PROFILING_B \
CFG_PROFILING_C
2023-12-23 22:47:48 -08:00
2023-02-14 10:44:08 -08:00
ARMIPS ?= armips
2024-02-27 21:30:23 -08:00
PARENT_OUTPUT_DIR ?= ./build
2023-02-15 22:28:04 -08:00
i f e q ( $( 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.
e n d i f
2023-02-14 10:44:08 -08:00
2024-11-18 21:44:58 -08:00
# Find the N64 toolchain, for creating object files.
2025-09-04 19:16:21 -04:00
i f n e q ( , $( shell which mips 64-elf -ld )
CROSS := mips64-elf-
e l s e i f n e q ( , $( shell which mips -n 64-ld )
CROSS := mips-n64-
e l s e i f n e q ( , $( shell which mips 64-ld )
CROSS := mips64-
e l s e i f n e q ( , $( shell which mips -linux -gnu -ld )
CROSS := mips-linux-gnu-
e l s e i f n e q ( , $( shell which mips 64-linux -gnu -ld )
CROSS := mips64-linux-gnu-
e l s e i f n e q ( , $( shell which mips -ld )
CROSS := mips-
e l s e i f n e q ( , $( shell which mips 64-linux -gnuabi 64-ld )
CROSS := mips64-linux-gnuabi64-
e l s e i f n e q ( , $( shell which mips 64-ultra -elf -ld )
CROSS := mips64-ultra-elf-
2024-11-18 21:44:58 -08:00
e l s e
$( warning Could not find N64 linker, not building object files)
AS :=
e n d i f
2023-02-14 10:44:08 -08:00
NO_COL := \0 33[ 0m
RED := \0 33[ 0; 31m
GREEN := \0 33[ 0; 32m
YELLOW := \0 33[ 0; 33m
BLUE := \0 33[ 0; 34m
2023-02-15 22:28:04 -08:00
INFO := $( BLUE)
2023-02-14 10:44:08 -08:00
SUCCESS := $( GREEN)
FAILURE := $( RED)
WARNING := $( YELLOW)
$(PARENT_OUTPUT_DIR) :
@printf " $( INFO) Creating parent output directory $( NO_COL) \n "
i f e q ( $( OS ) , W i n d o w s _ N T )
2023-02-15 22:28:04 -08:00
mkdir $@
2023-02-14 10:44:08 -08:00
e l s e
2023-02-15 22:28:04 -08:00
mkdir -p $@
2023-02-14 10:44:08 -08:00
e n d i f
ALL_UCODES :=
ALL_UCODES_WITH_MD5S :=
2023-02-14 16:03:21 -08:00
ALL_OUTPUT_DIRS :=
2023-02-14 10:44:08 -08:00
2024-11-18 21:44:58 -08:00
i f n e q ( , $( AS ) )
2024-11-19 20:53:39 -08:00
%.o : %.o .s
2024-11-18 21:44:58 -08:00
@$( AS) -march= vr4300 -mabi= 32 -I . $< -o $@
e n d i f
2023-02-15 22:28:04 -08:00
d e f i n e r e s e t _ v a r s
NAME :=
2024-03-20 22:13:02 -07:00
DESCRIPTION :=
ID_STR :=
2023-02-15 22:28:04 -08:00
MD5_CODE :=
MD5_DATA :=
OPTIONS :=
2024-03-20 22:13:02 -07:00
EXTRA_DEPS :=
2023-02-15 22:28:04 -08:00
e n d e f
2023-02-14 10:44:08 -08:00
d e f i n e u c o d e _ r u l e
2023-02-15 22:28:04 -08:00
# 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.
2023-02-14 10:44:08 -08:00
ifeq ( $( NAME) ,)
2023-02-15 22:28:04 -08:00
$$ ( error Microcode name not set!)
2023-02-14 10:44:08 -08:00
endif
2023-02-15 22:28:04 -08:00
UCODE_OUTPUT_DIR := $( PARENT_OUTPUT_DIR) /$( NAME)
2023-02-14 10:44:08 -08:00
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
2024-11-19 20:53:39 -08:00
OS_FILE := $$ ( UCODE_OUTPUT_DIR) /gsp$( NAME) .o.s
O_FILE := $$ ( UCODE_OUTPUT_DIR) /gsp$( NAME) .o
2023-02-14 10:44:08 -08:00
ALL_UCODES += $( NAME)
2023-02-15 22:28:04 -08:00
ifneq ( $( MD5_CODE) ,)
2023-02-14 10:44:08 -08:00
ALL_UCODES_WITH_MD5S += $( NAME)
endif
2023-02-15 22:28:04 -08:00
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) )
2023-02-14 10:44:08 -08:00
ARMIPS_CMDLINE := \
2023-02-15 22:28:04 -08:00
-strequ CODE_FILE $$ ( CODE_FILE) \
-strequ DATA_FILE $$ ( DATA_FILE) \
$$ ( OPTIONS_EQU) \
$$ ( OFF_OPTIONS_EQU) \
2023-10-21 15:24:26 -07:00
f3dex3.s \
2023-02-15 22:28:04 -08:00
-sym2 $$ ( SYM_FILE) \
-temp $$ ( TEMP_FILE)
# Microcode target
.PHONY: $( NAME)
$( NAME) : $$ ( CODE_FILE)
2024-11-18 21:44:58 -08:00
ifneq ( , $( AS) )
$( NAME) : $$ ( O_FILE)
endif
2023-02-15 22:28:04 -08:00
# Directory target variables, see below.
$$ ( UCODE_OUTPUT_DIR) : UCODE_OUTPUT_DIR:= $$ ( UCODE_OUTPUT_DIR)
# Directory target recipe
$$ ( UCODE_OUTPUT_DIR) :
2023-02-24 10:41:00 -08:00
@printf " $( INFO) Creating directory $$ (UCODE_OUTPUT_DIR) $( NO_COL) \n "
2023-02-14 10:44:08 -08:00
ifeq ( $( OS) ,Windows_NT)
2023-02-24 10:41:00 -08:00
@mkdir $$ ( subst /,\, $$ ( UCODE_OUTPUT_DIR) )
2023-02-14 10:44:08 -08:00
else
2023-02-15 22:28:04 -08:00
@mkdir -p $$ ( UCODE_OUTPUT_DIR)
2023-02-14 10:44:08 -08:00
endif
2023-02-15 22:28:04 -08:00
# 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)
2024-11-19 20:53:39 -08:00
$$ ( OS_FILE) : OS_FILE:= $$ ( OS_FILE)
$$ ( OS_FILE) : NAME:= $$ ( NAME)
2023-02-15 22:28:04 -08:00
# Target recipe
2023-10-21 15:24:26 -07:00
$$ ( CODE_FILE) : ./f3dex3.s ./rsp/* $( EXTRA_DEPS) | $$ ( UCODE_OUTPUT_DIR)
2023-02-16 21:20:48 -08:00
@printf " $( INFO) Building microcode: $( NAME) : $( DESCRIPTION) $( NO_COL) \n "
@$( ARMIPS) -strequ ID_STR " $( ID_STR) " $$ ( ARMIPS_CMDLINE)
ifneq ( $( MD5_CODE) ,)
2023-02-20 10:40:24 -08:00
@( 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 "
2023-02-14 10:44:08 -08:00
endif
2024-11-18 21:44:58 -08:00
ifneq ( , $( AS) )
2024-11-19 20:53:39 -08:00
$$ ( OS_FILE) : $$ ( CODE_FILE)
@sed " s|XXX| $( NAME) |g " ./template.o.s > $$ ( OS_FILE)
2024-11-18 21:44:58 -08:00
endif
2023-02-15 22:28:04 -08:00
$$ ( eval $$ ( call reset_vars) )
2023-02-14 10:44:08 -08:00
e n d e f
2023-02-15 22:28:04 -08:00
$( eval $ ( call reset_vars ) )
2023-02-13 23:00:03 -08:00
2024-03-17 18:53:28 -07:00
d e f i n e r u l e _ b u i l d e r _ f i n a l
NAME := F3DEX3$( NAME_FINAL)
DESCRIPTION := Will make you want to finally ditch HLE ( $( OPTIONS_FINAL) )
2025-07-22 21:17:31 -07:00
ID_STR := F3DEX3$( NAME_FINAL) $( VERSION) by Sauraen & Yoshitaka Yasumoto/Nintendo
2024-03-17 18:53:28 -07:00
OPTIONS := $( OPTIONS_FINAL)
$$ ( eval $$ ( call ucode_rule) )
e n d e f
2024-03-15 22:50:23 -07:00
2024-09-21 18:29:11 -07:00
d e f i n e r u l e _ b u i l d e r _ p r o f
NAME_FINAL := $( NAME_PROF)
OPTIONS_FINAL := $( OPTIONS_PROF)
2024-03-17 18:53:28 -07:00
$$ ( eval $$ ( call rule_builder_final) )
2024-09-21 18:29:11 -07:00
NAME_FINAL := $( NAME_PROF) _PA
OPTIONS_FINAL := $( OPTIONS_PROF) CFG_PROFILING_A
2024-03-17 18:53:28 -07:00
$$ ( eval $$ ( call rule_builder_final) )
2024-09-21 18:29:11 -07:00
NAME_FINAL := $( NAME_PROF) _PB
OPTIONS_FINAL := $( OPTIONS_PROF) CFG_PROFILING_B
$$ ( eval $$ ( call rule_builder_final) )
2024-03-17 18:53:28 -07:00
2024-09-21 18:29:11 -07:00
NAME_FINAL := $( NAME_PROF) _PC
OPTIONS_FINAL := $( OPTIONS_PROF) CFG_PROFILING_C
$$ ( eval $$ ( call rule_builder_final) )
2024-03-17 18:53:28 -07:00
e n d e f
2024-11-17 22:30:52 -08:00
d e f i n e r u l e _ b u i l d e r _ n o c
NAME_PROF := $( NAME_NOC)
OPTIONS_PROF := $( OPTIONS_NOC)
2024-03-17 18:53:28 -07:00
$$ ( eval $$ ( call rule_builder_prof) )
2024-11-17 22:30:52 -08:00
NAME_PROF := $( NAME_NOC) _NOC
OPTIONS_PROF := $( OPTIONS_NOC) CFG_NO_OCCLUSION_PLANE
2024-03-17 18:53:28 -07:00
$$ ( eval $$ ( call rule_builder_prof) )
e n d e f
2025-01-17 20:53:47 -08:00
d e f i n e r u l e _ b u i l d e r _ b r
NAME_NOC := $( NAME_BR) _BrZ
OPTIONS_NOC := $( OPTIONS_BR)
2024-03-17 18:53:28 -07:00
$$ ( eval $$ ( call rule_builder_noc) )
2025-01-17 20:53:47 -08:00
NAME_NOC := $( NAME_BR) _BrW
OPTIONS_NOC := $( OPTIONS_BR) CFG_G_BRANCH_W
2024-03-17 18:53:28 -07:00
$$ ( eval $$ ( call rule_builder_noc) )
e n d e f
2023-02-14 16:03:21 -08:00
2024-03-17 18:53:28 -07:00
NAME_BR :=
OPTIONS_BR :=
$( eval $ ( call rule_builder_br ) )
2023-02-14 16:03:21 -08:00
2024-03-17 18:53:28 -07:00
.PHONY : default ok all clean
all : $( ALL_UCODES )
2024-03-17 11:29:47 -07:00
2023-02-14 16:03:21 -08:00
clean :
@printf " $( WARNING) Deleting all built microcode files $( NO_COL) \n "
2023-02-15 22:31:03 -08:00
@rm -rf $( ALL_OUTPUT_DIRS)
2024-05-30 15:37:06 +02:00
doc :
2024-06-17 21:55:03 +02:00
doxygen Doxyfile