2020-05-05 12:15:53 +00:00
# Makefile to rebuild SM64 split image
### Default target ###
default : all
### Build Options ###
# These options can either be changed by modifying the makefile, or
# by building with 'make SETTING=value'. 'make clean' may be required.
# Version of the game to build
VERSION ?= us
# Graphics microcode used
GRUCODE ?= f3d_old
# If COMPARE is 1, check the output sha1sum when building 'all'
COMPARE ?= 1
# If NON_MATCHING is 1, define the NON_MATCHING and AVOID_UB macros when building (recommended)
NON_MATCHING ?= 0
# Build for the N64 (turn this off for ports)
TARGET_N64 ?= 0
# Build for Emscripten/WebGL
TARGET_WEB ?= 0
# Automatic settings only for ports
i f e q ( $( TARGET_N 64) , 0 )
NON_MATCHING := 1
GRUCODE := f3dex2e
WINDOWS_BUILD := 0
ifeq ( $( TARGET_WEB) ,0)
ifeq ( $( OS) ,Windows_NT)
WINDOWS_BUILD := 1
endif
endif
e n d i f
# Release
i f e q ( $( VERSION ) , j p )
VERSION_CFLAGS := -DVERSION_JP
VERSION_ASFLAGS := --defsym VERSION_JP = 1
GRUCODE_CFLAGS := -DF3D_OLD
GRUCODE_ASFLAGS := --defsym F3D_OLD = 1
TARGET := sm64.jp
e l s e
i f e q ( $( VERSION ) , u s )
VERSION_CFLAGS := -DVERSION_US
VERSION_ASFLAGS := --defsym VERSION_US = 1
GRUCODE_CFLAGS := -DF3D_OLD
GRUCODE_ASFLAGS := --defsym F3D_OLD = 1
TARGET := sm64.us
e l s e
i f e q ( $( VERSION ) , e u )
$( warning Building EU is experimental and is prone to breaking. Try at your own risk.)
VERSION_CFLAGS := -DVERSION_EU
VERSION_ASFLAGS := --defsym VERSION_EU = 1
GRUCODE_CFLAGS := -DF3D_NEW
GRUCODE_ASFLAGS := --defsym F3D_NEW = 1
TARGET := sm64.eu
e l s e
$( error unknown version " $( VERSION) " )
e n d i f
e n d i f
e n d i f
# Microcode
i f e q ( $( GRUCODE ) , f 3 d e x ) # Fast3DEX
GRUCODE_CFLAGS := -DF3DEX_GBI
GRUCODE_ASFLAGS := --defsym F3DEX_GBI_SHARED = 1 --defsym F3DEX_GBI = 1
TARGET := $( TARGET) .f3dex
COMPARE := 0
e l s e
i f e q ( $( GRUCODE ) , f 3 d e x 2 ) # Fast3DEX2
GRUCODE_CFLAGS := -DF3DEX_GBI_2
GRUCODE_ASFLAGS := --defsym F3DEX_GBI_SHARED = 1 --defsym F3DEX_GBI_2 = 1
TARGET := $( TARGET) .f3dex2
COMPARE := 0
e l s e
i f e q ( $( GRUCODE ) , f 3 d e x 2 e ) # Fast3DEX2 Extended (for PC)
GRUCODE_CFLAGS := -DF3DEX_GBI_2E
TARGET := $( TARGET) .f3dex2e
COMPARE := 0
e l s e
i f e q ( $( GRUCODE ) , f 3 d _ n e w ) # Fast3D 2.0H (Shindou)
GRUCODE_CFLAGS := -DF3D_NEW
GRUCODE_ASFLAGS := --defsym F3D_NEW = 1
TARGET := $( TARGET) .f3d_new
COMPARE := 0
e l s e
i f e q ( $( GRUCODE ) , f 3 d z e x ) # Fast3DZEX (2.0J / Animal Forest - Dōbutsu no Mori)
$( warning Fast3DZEX is experimental. Try at your own risk.)
GRUCODE_CFLAGS := -DF3DEX_GBI_2
GRUCODE_ASFLAGS := --defsym F3DEX_GBI_SHARED = 1 --defsym F3DZEX_GBI = 1
TARGET := $( TARGET) .f3dzex
COMPARE := 0
e n d i f
e n d i f
e n d i f
e n d i f
e n d i f
i f e q ( $( NON_MATCHING ) , 1 )
VERSION_CFLAGS := $( VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB
COMPARE := 0
e n d i f
i f e q ( $( TARGET_WEB ) , 1 )
VERSION_CFLAGS := $( VERSION_CFLAGS) -DTARGET_WEB
e n d i f
################### Universal Dependencies ###################
# (This is a bit hacky, but a lot of rules implicitly depend
# on tools and assets, and we use directory globs further down
# in the makefile that we want should cover assets.)
i f n e q ( $( MAKECMDGOALS ) , c l e a n )
i f n e q ( $( MAKECMDGOALS ) , d i s t c l e a n )
# Make sure assets exist
NOEXTRACT ?= 0
i f e q ( $( NOEXTRACT ) , 0 )
2020-05-06 21:26:13 +00:00
DUMMY != python3 ./extract_assets.py $( VERSION) >& 2 || echo FAIL
2020-05-05 12:15:53 +00:00
i f e q ( $( DUMMY ) , F A I L )
$( error Failed to extract assets)
e n d i f
e n d i f
# Make tools if out of date
DUMMY != make -s -C tools >& 2 || echo FAIL
i f e q ( $( DUMMY ) , F A I L )
$( error Failed to build tools)
e n d i f
e n d i f
e n d i f
################ Target Executable and Sources ###############
# BUILD_DIR is location where all build artifacts are placed
BUILD_DIR_BASE := build
i f e q ( $( TARGET_N 64) , 1 )
BUILD_DIR := $( BUILD_DIR_BASE) /$( VERSION)
e l s e
i f e q ( $( TARGET_WEB ) , 1 )
BUILD_DIR := $( BUILD_DIR_BASE) /$( VERSION) _web
e l s e
BUILD_DIR := $( BUILD_DIR_BASE) /$( VERSION) _pc
e n d i f
e n d i f
LIBULTRA := $( BUILD_DIR) /libultra.a
i f e q ( $( TARGET_WEB ) , 1 )
EXE := $( BUILD_DIR) /$( TARGET) .html
e l s e
i f e q ( $( WINDOWS_BUILD ) , 1 )
EXE := $( BUILD_DIR) /$( TARGET) .exe
e l s e
EXE := $( BUILD_DIR) /$( TARGET)
e n d i f
e n d i f
ROM := $( BUILD_DIR) /$( TARGET) .z64
ELF := $( BUILD_DIR) /$( TARGET) .elf
LD_SCRIPT := sm64.ld
MIO0_DIR := $( BUILD_DIR) /bin
SOUND_BIN_DIR := $( BUILD_DIR) /sound
TEXTURE_DIR := textures
ACTOR_DIR := actors
LEVEL_DIRS := $( patsubst levels/%,%,$( dir $( wildcard levels/*/header.h) ) )
# Directories containing source files
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets
ASM_DIRS := lib
i f e q ( $( TARGET_N 64) , 1 )
ASM_DIRS := asm $( ASM_DIRS)
e l s e
SRC_DIRS := $( SRC_DIRS) src/pc src/pc/gfx src/pc/audio src/pc/controller
ASM_DIRS :=
e n d i f
BIN_DIRS := bin bin/$( VERSION)
ULTRA_SRC_DIRS := lib/src lib/src/math
ULTRA_ASM_DIRS := lib/asm lib/data
ULTRA_BIN_DIRS := lib/bin
GODDARD_SRC_DIRS := src/goddard src/goddard/dynlists
MIPSISET := -mips2 -32
i f e q ( $( VERSION ) , e u )
OPT_FLAGS := -O2
e l s e
2020-05-06 21:26:13 +00:00
OPT_FLAGS := -g
2020-05-05 12:15:53 +00:00
e n d i f
i f e q ( $( TARGET_WEB ) , 1 )
OPT_FLAGS := -O2 -g4 --source-map-base http://localhost:8080/
e n d i f
# File dependencies and variables for specific files
i n c l u d e M a k e f i l e . s p l i t
# Source code files
LEVEL_C_FILES := $( wildcard levels/*/leveldata.c) $( wildcard levels/*/script.c) $( wildcard levels/*/geo.c)
C_FILES := $( foreach dir,$( SRC_DIRS) ,$( wildcard $( dir) /*.c) ) $( LEVEL_C_FILES)
CXX_FILES := $( foreach dir,$( SRC_DIRS) ,$( wildcard $( dir) /*.cpp) )
S_FILES := $( foreach dir,$( ASM_DIRS) ,$( wildcard $( dir) /*.s) )
ULTRA_C_FILES := $( foreach dir,$( ULTRA_SRC_DIRS) ,$( wildcard $( dir) /*.c) )
GODDARD_C_FILES := $( foreach dir,$( GODDARD_SRC_DIRS) ,$( wildcard $( dir) /*.c) )
i f e q ( $( TARGET_N 64) , 1 )
ULTRA_S_FILES := $( foreach dir,$( ULTRA_ASM_DIRS) ,$( wildcard $( dir) /*.s) )
e n d i f
GENERATED_C_FILES := $( BUILD_DIR) /assets/mario_anim_data.c $( BUILD_DIR) /assets/demo_data.c \
$( addprefix $( BUILD_DIR) /bin/,$( addsuffix _skybox.c,$( notdir $( basename $( wildcard textures/skyboxes/*.png) ) ) ) )
i f e q ( $( WINDOWS_BUILD ) , 0 )
CXX_FILES :=
e n d i f
i f n e q ( $( TARGET_N 64) , 1 )
ULTRA_C_FILES_SKIP := \
sqrtf.c \
string.c \
sprintf.c \
_Printf.c \
kdebugserver.c \
osInitialize.c \
osCreateThread.c \
osDestroyThread.c \
osStartThread.c \
osSetThreadPri.c \
osPiStartDma.c \
osPiRawStartDma.c \
osPiRawReadIo.c \
osPiGetCmdQueue.c \
osJamMesg.c \
osSendMesg.c \
osRecvMesg.c \
osSetEventMesg.c \
osTimer.c \
osSetTimer.c \
osSetTime.c \
osCreateViManager.c \
osViSetSpecialFeatures.c \
osVirtualToPhysical.c \
osViBlack.c \
osViSetEvent.c \
osViSetMode.c \
osViSwapBuffer.c \
osSpTaskLoadGo.c \
osCreatePiManager.c \
osGetTime.c \
osEepromProbe.c \
osEepromWrite.c \
osEepromLongWrite.c \
osEepromRead.c \
osEepromLongRead.c \
osContInit.c \
osContStartReadData.c \
osAiGetLength.c \
osAiSetFrequency.c \
osAiSetNextBuffer.c \
__osViInit.c \
__osSyncPutChars.c \
__osAtomicDec.c \
__osSiRawStartDma.c \
__osViSwapContext.c \
__osViGetCurrentContext.c
C_FILES := $( filter-out src/game/main.c,$( C_FILES) )
ULTRA_C_FILES := $( filter-out $( addprefix lib/src/,$( ULTRA_C_FILES_SKIP) ) ,$( ULTRA_C_FILES) )
e n d i f
SOUND_BANK_FILES := $( wildcard sound/sound_banks/*.json)
SOUND_SEQUENCE_FILES := $( wildcard sound/sequences/$( VERSION) /*.m64) \
$( wildcard sound/sequences/*.m64) \
$( foreach file,$( wildcard sound/sequences/$( VERSION) /*.s) ,$( BUILD_DIR) /$( file:.s= .m64) ) \
$( foreach file,$( wildcard sound/sequences/*.s) ,$( BUILD_DIR) /$( file:.s= .m64) )
SOUND_SAMPLE_DIRS := $( wildcard sound/samples/*)
SOUND_SAMPLE_AIFFS := $( foreach dir,$( SOUND_SAMPLE_DIRS) ,$( wildcard $( dir) /*.aiff) )
SOUND_SAMPLE_TABLES := $( foreach file,$( SOUND_SAMPLE_AIFFS) ,$( BUILD_DIR) /$( file:.aiff= .table) )
SOUND_SAMPLE_AIFCS := $( foreach file,$( SOUND_SAMPLE_AIFFS) ,$( BUILD_DIR) /$( file:.aiff= .aifc) )
SOUND_OBJ_FILES := $( SOUND_BIN_DIR) /sound_data.ctl.o \
$( SOUND_BIN_DIR) /sound_data.tbl.o \
$( SOUND_BIN_DIR) /sequences.bin.o \
$( SOUND_BIN_DIR) /bank_sets.o
# Object files
O_FILES := $( foreach file,$( C_FILES) ,$( BUILD_DIR) /$( file:.c= .o) ) \
$( foreach file,$( CXX_FILES) ,$( BUILD_DIR) /$( file:.cpp= .o) ) \
$( foreach file,$( S_FILES) ,$( BUILD_DIR) /$( file:.s= .o) ) \
$( foreach file,$( GENERATED_C_FILES) ,$( file:.c= .o) )
ULTRA_O_FILES := $( foreach file,$( ULTRA_S_FILES) ,$( BUILD_DIR) /$( file:.s= .o) ) \
$( foreach file,$( ULTRA_C_FILES) ,$( BUILD_DIR) /$( file:.c= .o) )
GODDARD_O_FILES := $( foreach file,$( GODDARD_C_FILES) ,$( BUILD_DIR) /$( file:.c= .o) )
# Automatic dependency files
DEP_FILES := $( O_FILES:.o= .d) $( ULTRA_O_FILES:.o= .d) $( GODDARD_O_FILES:.o= .d) $( BUILD_DIR) /$( LD_SCRIPT) .d
# Files with GLOBAL_ASM blocks
i f n e q ( $( NON_MATCHING ) , 1 )
GLOBAL_ASM_C_FILES != grep -rl 'GLOBAL_ASM(' $( wildcard src/audio/*.c) $( wildcard src/game/*.c)
GLOBAL_ASM_O_FILES = $( foreach file,$( GLOBAL_ASM_C_FILES) ,$( BUILD_DIR) /$( file:.c= .o) )
GLOBAL_ASM_DEP = $( BUILD_DIR) /src/audio/non_matching_dep
e n d i f
# Segment elf files
SEG_FILES := $( SEGMENT_ELF_FILES) $( ACTOR_ELF_FILES) $( LEVEL_ELF_FILES)
##################### Compiler Options #######################
INCLUDE_CFLAGS := -I include -I $( BUILD_DIR) -I $( BUILD_DIR) /include -I src -I .
ENDIAN_BITWIDTH := $( BUILD_DIR) /endian-and-bitwidth
i f e q ( $( TARGET_N 64) , 1 )
IRIX_ROOT := tools/ido5.3_compiler
i f e q ( $( shell type mips -linux -gnu -ld >/dev /null 2>/dev /null ; echo $ $ ?) , 0 )
CROSS := mips-linux-gnu-
e l s e
CROSS := mips64-elf-
e n d i f
# check that either QEMU_IRIX is set or qemu-irix package installed
i f n d e f Q E M U _ I R I X
QEMU_IRIX := $( shell which qemu-irix)
ifeq ( , $( QEMU_IRIX) )
$( error Please install qemu-irix package or set QEMU_IRIX env var to the full qemu-irix binary path)
endif
e n d i f
AS := $( CROSS) as
CC := $( QEMU_IRIX) -silent -L $( IRIX_ROOT) $( IRIX_ROOT) /usr/bin/cc
CPP := cpp -P -Wno-trigraphs
LD := $( CROSS) ld
AR := $( CROSS) ar
OBJDUMP := $( CROSS) objdump
OBJCOPY := $( CROSS) objcopy
PYTHON := python3
i f e q ( $( TARGET_N 64) , 1 )
TARGET_CFLAGS := -nostdinc -I include/libc -DTARGET_N64
CC_CFLAGS := -fno-builtin
e n d i f
# Check code syntax with host compiler
CC_CHECK := gcc -fsyntax-only -fsigned-char $( CC_CFLAGS) $( TARGET_CFLAGS) $( INCLUDE_CFLAGS) -std= gnu90 -Wall -Wextra -Wno-format-security -DNON_MATCHING -DAVOID_UB $( VERSION_CFLAGS) $( GRUCODE_CFLAGS)
ASFLAGS := -march= vr4300 -mabi= 32 -I include -I $( BUILD_DIR) $( VERSION_ASFLAGS) $( GRUCODE_ASFLAGS)
2020-05-08 01:06:26 +00:00
CFLAGS = -Wab,-r4300_mul -non_shared -G 0 -Xcpluscomm -Xfullwarn -signed $( OPT_FLAGS) $( TARGET_CFLAGS) $( INCLUDE_CFLAGS) $( VERSION_CFLAGS) $( MIPSISET) $( GRUCODE_CFLAGS) -O4
2020-05-05 12:15:53 +00:00
OBJCOPYFLAGS := --pad-to= 0x800000 --gap-fill= 0xFF
SYMBOL_LINKING_FLAGS := $( addprefix -R ,$( SEG_FILES) )
LDFLAGS := -T undefined_syms.txt -T $( BUILD_DIR) /$( LD_SCRIPT) -Map $( BUILD_DIR) /sm64.$( VERSION) .map --no-check-sections $( SYMBOL_LINKING_FLAGS)
ENDIAN_BITWIDTH := $( BUILD_DIR) /endian-and-bitwidth
i f e q ( $( shell getconf LONG_BIT ) , 3 2 )
# Work around memory allocation bug in QEMU
export QEMU_GUEST_BASE := 1
e l s e
# Ensure that gcc treats the code as 32-bit
2020-05-06 21:26:13 +00:00
CC_CHECK +=
2020-05-05 12:15:53 +00:00
e n d i f
e l s e # TARGET_N64
AS := as
i f n e q ( $( TARGET_WEB ) , 1 )
2020-05-08 01:06:26 +00:00
CC := clang
CXX := clang++
2020-05-05 12:15:53 +00:00
e l s e
CC := emcc
e n d i f
i f e q ( $( WINDOWS_BUILD ) , 1 )
LD := $( CXX)
e l s e
LD := $( CC)
e n d i f
CPP := cpp -P
OBJDUMP := objdump
OBJCOPY := objcopy
PYTHON := python3
i f e q ( $( WINDOWS_BUILD ) , 1 )
CC_CHECK := $( CC) -fsyntax-only -fsigned-char $( INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $( VERSION_CFLAGS) $( GRUCODE_CFLAGS) ` sdl2-config --cflags`
CFLAGS := $( OPT_FLAGS) $( INCLUDE_CFLAGS) $( VERSION_CFLAGS) $( GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv ` sdl2-config --cflags`
e l s e i f e q ( $( TARGET_WEB ) , 1 )
CC_CHECK := $( CC) -fsyntax-only -fsigned-char $( INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $( VERSION_CFLAGS) $( GRUCODE_CFLAGS) -s USE_SDL = 2
CFLAGS := $( OPT_FLAGS) $( INCLUDE_CFLAGS) $( VERSION_CFLAGS) $( GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv -s USE_SDL = 2
e l s e
CC_CHECK := $( CC) -fsyntax-only -fsigned-char $( INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $( VERSION_CFLAGS) $( GRUCODE_CFLAGS) ` pkg-config --cflags libusb-1.0 glfw3` ` sdl2-config --cflags`
CFLAGS := $( OPT_FLAGS) $( INCLUDE_CFLAGS) $( VERSION_CFLAGS) $( GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv ` pkg-config --cflags libusb-1.0 glfw3` ` sdl2-config --cflags`
e n d i f
ASFLAGS := -I include -I $( BUILD_DIR) $( VERSION_ASFLAGS)
i f e q ( $( TARGET_WEB ) , 1 )
LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY = 20MB -g4 --source-map-base http://localhost:8080/ -s "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']"
e l s e
i f e q ( $( WINDOWS_BUILD ) , 1 )
2020-05-06 21:26:13 +00:00
LDFLAGS := -Llib -lpthread -lglew32 ` sdl2-config --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static
2020-05-05 12:15:53 +00:00
e l s e
2020-05-06 21:26:13 +00:00
LDFLAGS := -lm -lGL ` sdl2-config --libs` -no-pie -lpthread ` pkg-config --libs libusb-1.0 glfw3` -lasound -lX11 -lXrandr -lpulse
2020-05-05 12:15:53 +00:00
e n d i f
e n d i f
e n d i f
####################### Other Tools #########################
# N64 tools
TOOLS_DIR = tools
MIO0TOOL = $( TOOLS_DIR) /mio0
N64CKSUM = $( TOOLS_DIR) /n64cksum
N64GRAPHICS = $( TOOLS_DIR) /n64graphics
N64GRAPHICS_CI = $( TOOLS_DIR) /n64graphics_ci
TEXTCONV = $( TOOLS_DIR) /textconv
IPLFONTUTIL = $( TOOLS_DIR) /iplfontutil
AIFF_EXTRACT_CODEBOOK = $( TOOLS_DIR) /aiff_extract_codebook
VADPCM_ENC = $( TOOLS_DIR) /vadpcm_enc
EXTRACT_DATA_FOR_MIO = $( TOOLS_DIR) /extract_data_for_mio
SKYCONV = $( TOOLS_DIR) /skyconv
EMULATOR = mupen64plus
EMU_FLAGS = --noosd
LOADER = loader64
LOADER_FLAGS = -vwf
SHA1SUM = sha1sum
###################### Dependency Check #####################
i f e q ( $( TARGET_N 64) , 1 )
BINUTILS_VER_MAJOR := $( shell $( LD) --version | grep ^GNU | sed 's/^.* //; s/\..*//g' )
BINUTILS_VER_MINOR := $( shell $( LD) --version | grep ^GNU | sed 's/^[^.]*\.//; s/\..*//g' )
BINUTILS_DEPEND := $( shell expr $( BINUTILS_VER_MAJOR) \> = 2 \& $( BINUTILS_VER_MINOR) \> = 27)
i f e q ( $( BINUTILS_DEPEND ) , 0 )
$( error binutils version 2.27 required , version $ ( BINUTILS_VER_MAJOR ) .$ ( BINUTILS_VER_MINOR ) detected )
e n d i f
e n d i f
######################## Targets #############################
i f e q ( $( TARGET_N 64) , 1 )
all : $( ROM )
i f e q ( $( COMPARE ) , 1 )
@$( SHA1SUM) -c $( TARGET) .sha1 || ( echo 'The build succeeded, but did not match the official ROM. This is expected if you are making changes to the game.\nTo silence this message, use "make COMPARE=0"' . && false )
e n d i f
e l s e
all : $( EXE )
e n d i f
clean :
$( RM) -r $( BUILD_DIR_BASE)
distclean :
$( RM) -r $( BUILD_DIR_BASE)
./extract_assets.py --clean
test : $( ROM )
$( EMULATOR) $( EMU_FLAGS) $<
load : $( ROM )
$( LOADER) $( LOADER_FLAGS) $<
libultra : $( BUILD_DIR ) /libultra .a
asm/boot.s : $( BUILD_DIR ) /lib /bin /ipl 3_font .bin
$(BUILD_DIR)/lib/bin/ipl3_font.bin : lib /ipl 3_font .png
$( IPLFONTUTIL) e $< $@
$(BUILD_DIR)/include/text_strings.h : include /text_strings .h .in
$( TEXTCONV) charmap.txt $< $@
$(BUILD_DIR)/include/text_menu_strings.h : include /text_menu_strings .h .in
$( TEXTCONV) charmap_menu.txt $< $@
i f e q ( $( VERSION ) , e u )
TEXT_DIRS := text/de text/us text/fr
# EU encoded text inserted into individual segment 0x19 files
$(BUILD_DIR)/bin/eu/translation_en.o : $( BUILD_DIR ) /text /us /define_text .inc .c
$(BUILD_DIR)/bin/eu/translation_de.o : $( BUILD_DIR ) /text /de /define_text .inc .c
$(BUILD_DIR)/bin/eu/translation_fr.o : $( BUILD_DIR ) /text /fr /define_text .inc .c
e l s e
TEXT_DIRS := text/$( VERSION)
# non-EU encoded text inserted into segment 0x02
$(BUILD_DIR)/bin/segment2.o : $( BUILD_DIR ) /text /$( VERSION ) /define_text .inc .c
e n d i f
$(BUILD_DIR)/text/%/define_text.inc.c : text /define_text .inc .c text /%/courses .h text /%/dialogs .h
$( CPP) $( VERSION_CFLAGS) $< -o $@ -I text/$* /
$( TEXTCONV) charmap.txt $@ $@
ALL_DIRS := $( BUILD_DIR) $( addprefix $( BUILD_DIR) /,$( SRC_DIRS) $( ASM_DIRS) $( GODDARD_SRC_DIRS) $( ULTRA_SRC_DIRS) $( ULTRA_ASM_DIRS) $( ULTRA_BIN_DIRS) $( BIN_DIRS) $( TEXTURE_DIRS) $( TEXT_DIRS) $( SOUND_SAMPLE_DIRS) $( addprefix levels/,$( LEVEL_DIRS) ) include) $( MIO0_DIR) $( addprefix $( MIO0_DIR) /,$( VERSION) ) $( SOUND_BIN_DIR) $( SOUND_BIN_DIR) /sequences/$( VERSION)
# Make sure build directory exists before compiling anything
DUMMY != mkdir -p $( ALL_DIRS)
$(BUILD_DIR)/include/text_strings.h : $( BUILD_DIR ) /include /text_menu_strings .h
$(BUILD_DIR)/src/menu/file_select.o : $( BUILD_DIR ) /include /text_strings .h
$(BUILD_DIR)/src/menu/star_select.o : $( BUILD_DIR ) /include /text_strings .h
$(BUILD_DIR)/src/game/ingame_menu.o : $( BUILD_DIR ) /include /text_strings .h
################################################################
# TEXTURE GENERATION #
################################################################
# RGBA32, RGBA16, IA16, IA8, IA4, IA1, I8, I4
$(BUILD_DIR)/% : %.png
$( N64GRAPHICS) -i $@ -g $< -f $( lastword $( subst ., ,$@ ) )
$(BUILD_DIR)/%.inc.c : $( BUILD_DIR ) /% %.png
hexdump -v -e '1/1 "0x%X,"' $< > $@
echo >> $@
# Color Index CI8
$(BUILD_DIR)/%.ci8 : %.ci 8.png
$( N64GRAPHICS_CI) -i $@ -g $< -f ci8
# Color Index CI4
$(BUILD_DIR)/%.ci4 : %.ci 4.png
$( N64GRAPHICS_CI) -i $@ -g $< -f ci4
################################################################
# compressed segment generation
i f e q ( $( TARGET_N 64) , 1 )
# TODO: ideally this would be `-Trodata-segment=0x07000000` but that doesn't set the address
$(BUILD_DIR)/bin/%.elf : $( BUILD_DIR ) /bin /%.o
$( LD) -e 0 -Ttext= $( SEGMENT_ADDRESS) -Map $@ .map -o $@ $<
$(BUILD_DIR)/actors/%.elf : $( BUILD_DIR ) /actors /%.o
$( LD) -e 0 -Ttext= $( SEGMENT_ADDRESS) -Map $@ .map -o $@ $<
# Override for level.elf, which otherwise matches the above pattern
.SECONDEXPANSION :
$(BUILD_DIR)/levels/%/leveldata.elf : $( BUILD_DIR ) /levels /%/leveldata .o $( BUILD_DIR ) /bin /$$( TEXTURE_BIN ) .elf
$( LD) -e 0 -Ttext= $( SEGMENT_ADDRESS) -Map $@ .map --just-symbols= $( BUILD_DIR) /bin/$( TEXTURE_BIN) .elf -o $@ $<
$(BUILD_DIR)/bin/%.bin : $( BUILD_DIR ) /bin /%.elf
$( EXTRACT_DATA_FOR_MIO) $< $@
$(BUILD_DIR)/actors/%.bin : $( BUILD_DIR ) /actors /%.elf
$( EXTRACT_DATA_FOR_MIO) $< $@
$(BUILD_DIR)/levels/%/leveldata.bin : $( BUILD_DIR ) /levels /%/leveldata .elf
$( EXTRACT_DATA_FOR_MIO) $< $@
$(BUILD_DIR)/%.mio0 : $( BUILD_DIR ) /%.bin
$( MIO0TOOL) $< $@
$(BUILD_DIR)/%.mio0.o : $( BUILD_DIR ) /%.mio 0.s
$( AS) $( ASFLAGS) -o $@ $<
$(BUILD_DIR)/%.mio0.s : $( BUILD_DIR ) /%.mio 0
printf " .section .data\n\n.incbin \" $<\"\n " > $@
e n d i f
$(BUILD_DIR)/%.table : %.aiff
$( AIFF_EXTRACT_CODEBOOK) $< >$@
$(BUILD_DIR)/%.aifc : $( BUILD_DIR ) /%.table %.aiff
$( VADPCM_ENC) -c $^ $@
$(ENDIAN_BITWIDTH) : tools /determine -endian -bitwidth .c
$( CC) -c $( CFLAGS) -o $@ .dummy2 $< 2>$@ .dummy1; true
grep -o 'msgbegin --endian .* --bitwidth .* msgend' $@ .dummy1 > $@ .dummy2
head -n1 <$@ .dummy2 | cut -d' ' -f2-5 > $@
@rm $@ .dummy1
@rm $@ .dummy2
$(SOUND_BIN_DIR)/sound_data.ctl : sound /sound_banks / $( SOUND_BANK_FILES ) $( SOUND_SAMPLE_AIFCS ) $( ENDIAN_BITWIDTH )
$( PYTHON) tools/assemble_sound.py $( BUILD_DIR) /sound/samples/ sound/sound_banks/ $( SOUND_BIN_DIR) /sound_data.ctl $( SOUND_BIN_DIR) /sound_data.tbl $( VERSION_CFLAGS) $$ ( cat $( ENDIAN_BITWIDTH) )
$(SOUND_BIN_DIR)/sound_data.tbl : $( SOUND_BIN_DIR ) /sound_data .ctl
@true
$(SOUND_BIN_DIR)/sequences.bin : $( SOUND_BANK_FILES ) sound /sequences .json sound /sequences / sound /sequences /$( VERSION ) / $( SOUND_SEQUENCE_FILES ) $( ENDIAN_BITWIDTH )
$( PYTHON) tools/assemble_sound.py --sequences $@ $( SOUND_BIN_DIR) /bank_sets sound/sound_banks/ sound/sequences.json $( SOUND_SEQUENCE_FILES) $( VERSION_CFLAGS) $$ ( cat $( ENDIAN_BITWIDTH) )
$(SOUND_BIN_DIR)/bank_sets : $( SOUND_BIN_DIR ) /sequences .bin
@true
$(SOUND_BIN_DIR)/%.m64 : $( SOUND_BIN_DIR ) /%.o
$( OBJCOPY) -j .rodata $< -O binary $@
$(SOUND_BIN_DIR)/%.o : $( SOUND_BIN_DIR ) /%.s
$( AS) $( ASFLAGS) -o $@ $<
i f e q ( $( TARGET_N 64) , 1 )
$(SOUND_BIN_DIR)/%.s : $( SOUND_BIN_DIR ) /%
printf " .section .data\n\n.incbin \" $<\"\n " > $@
e l s e
$(SOUND_BIN_DIR)/sound_data.ctl.c : $( SOUND_BIN_DIR ) /sound_data .ctl
echo "unsigned char gSoundDataADSR[] = {" > $@
hexdump -v -e '1/1 "0x%X,"' $< >> $@
echo "};" >> $@
$(SOUND_BIN_DIR)/sound_data.tbl.c : $( SOUND_BIN_DIR ) /sound_data .tbl
echo "unsigned char gSoundDataRaw[] = {" > $@
hexdump -v -e '1/1 "0x%X,"' $< >> $@
echo "};" >> $@
$(SOUND_BIN_DIR)/sequences.bin.c : $( SOUND_BIN_DIR ) /sequences .bin
echo "unsigned char gMusicData[] = {" > $@
hexdump -v -e '1/1 "0x%X,"' $< >> $@
echo "};" >> $@
$(SOUND_BIN_DIR)/bank_sets.c : $( SOUND_BIN_DIR ) /bank_sets
echo "unsigned char gBankSetsData[] = {" > $@
hexdump -v -e '1/1 "0x%X,"' $< >> $@
echo "};" >> $@
e n d i f
$(BUILD_DIR)/levels/scripts.o : $( BUILD_DIR ) /include /level_headers .h
$(BUILD_DIR)/include/level_headers.h : levels /level_headers .h .in
$( CPP) -I . levels/level_headers.h.in | $( PYTHON) tools/output_level_headers.py > $( BUILD_DIR) /include/level_headers.h
$(BUILD_DIR)/assets/mario_anim_data.c : $( wildcard assets /anims /*.inc .c )
$( PYTHON) tools/mario_anims_converter.py > $@
$(BUILD_DIR)/assets/demo_data.c : assets /demo_data .json $( wildcard assets /demos /*.bin )
$( PYTHON) tools/demo_data_converter.py assets/demo_data.json $( VERSION_CFLAGS) > $@
# Source code
$(BUILD_DIR)/src/goddard/%.o : OPT_FLAGS := -g
$(BUILD_DIR)/src/goddard/%.o : MIPSISET := -mips 1
$(BUILD_DIR)/src/audio/%.o : OPT_FLAGS := -O 2 -Wo , -loopunroll , 0
$(BUILD_DIR)/src/audio/load.o : OPT_FLAGS := -O 2 -framepointer -Wo , -loopunroll , 0
$(BUILD_DIR)/lib/src/%.o : OPT_FLAGS :=
$(BUILD_DIR)/lib/src/math/ll%.o : MIPSISET := -mips 3 -32
$(BUILD_DIR)/lib/src/math/%.o : OPT_FLAGS := -O 2
$(BUILD_DIR)/lib/src/math/ll%.o : OPT_FLAGS :=
$(BUILD_DIR)/lib/src/ldiv.o : OPT_FLAGS := -O 2
$(BUILD_DIR)/lib/src/string.o : OPT_FLAGS := -O 2
$(BUILD_DIR)/lib/src/gu%.o : OPT_FLAGS := -O 3
$(BUILD_DIR)/lib/src/al%.o : OPT_FLAGS := -O 3
i f e q ( $( VERSION ) , e u )
$(BUILD_DIR)/lib/src/_Litob.o : OPT_FLAGS := -O 3
$(BUILD_DIR)/lib/src/_Ldtob.o : OPT_FLAGS := -O 3
$(BUILD_DIR)/lib/src/_Printf.o : OPT_FLAGS := -O 3
e n d i f
i f e q ( $( NON_MATCHING ) , 0 )
$(GLOBAL_ASM_O_FILES) : CC := $( PYTHON ) tools /asm_processor /build .py $( CC ) -- $( AS ) $( ASFLAGS ) --
e n d i f
# Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes.
$(GLOBAL_ASM_O_FILES) : $( GLOBAL_ASM_DEP ) .$( NON_MATCHING )
$(GLOBAL_ASM_DEP).$(NON_MATCHING) :
@rm -f $( GLOBAL_ASM_DEP) .*
touch $@
$(BUILD_DIR)/%.o : %.cpp
@$( CXX) -fsyntax-only $( CFLAGS) -MMD -MP -MT $@ -MF $( BUILD_DIR) /$* .d $<
$( CXX) -c $( CFLAGS) -o $@ $<
$(BUILD_DIR)/%.o : %.c
@$( CC_CHECK) -MMD -MP -MT $@ -MF $( BUILD_DIR) /$* .d $<
$( CC) -c $( CFLAGS) -o $@ $<
$(BUILD_DIR)/%.o : $( BUILD_DIR ) /%.c
@$( CC_CHECK) -MMD -MP -MT $@ -MF $( BUILD_DIR) /$* .d $<
$( CC) -c $( CFLAGS) -o $@ $<
$(BUILD_DIR)/%.o : %.s
$( AS) $( ASFLAGS) -MD $( BUILD_DIR) /$* .d -o $@ $<
i f e q ( $( TARGET_N 64) , 1 )
$(BUILD_DIR)/$(LD_SCRIPT) : $( LD_SCRIPT )
$( CPP) $( VERSION_CFLAGS) -MMD -MP -MT $@ -MF $@ .d -I include/ -I . -DBUILD_DIR= $( BUILD_DIR) -o $@ $<
$(BUILD_DIR)/libultra.a : $( ULTRA_O_FILES )
$( AR) rcs -o $@ $( ULTRA_O_FILES)
tools/patch_libultra_math $@
$(BUILD_DIR)/libgoddard.a : $( GODDARD_O_FILES )
$( AR) rcs -o $@ $( GODDARD_O_FILES)
$(ELF) : $( O_FILES ) $( MIO 0_OBJ_FILES ) $( SOUND_OBJ_FILES ) $( SEG_FILES ) $( BUILD_DIR ) /$( LD_SCRIPT ) undefined_syms .txt $( BUILD_DIR ) /libultra .a $( BUILD_DIR ) /libgoddard .a
$( LD) -L $( BUILD_DIR) $( LDFLAGS) -o $@ $( O_FILES) $( LIBS) -lultra -lgoddard
$(ROM) : $( ELF )
$( OBJCOPY) $( OBJCOPYFLAGS) $< $( @:.z64= .bin) -O binary
$( N64CKSUM) $( @:.z64= .bin) $@
$(BUILD_DIR)/$(TARGET).objdump : $( ELF )
$( OBJDUMP) -D $< > $@
e l s e
$(EXE) : $( O_FILES ) $( MIO 0_FILES :.mio 0=.o ) $( SOUND_OBJ_FILES ) $( ULTRA_O_FILES ) $( GODDARD_O_FILES )
$( LD) -L $( BUILD_DIR) -o $@ $( O_FILES) $( SOUND_OBJ_FILES) $( ULTRA_O_FILES) $( GODDARD_O_FILES) $( LDFLAGS)
e n d i f
.PHONY : all clean distclean default diff test load libultra
.PRECIOUS : $( BUILD_DIR ) /bin /%.elf $( SOUND_BIN_DIR ) /%.ctl $( SOUND_BIN_DIR ) /%.tbl $( SOUND_SAMPLE_TABLES ) $( SOUND_BIN_DIR ) /%.s $( BUILD_DIR ) /%
.DELETE_ON_ERROR :
# Remove built-in rules, to improve performance
MAKEFLAGS += --no-builtin-rules
- i n c l u d e $( DEP_FILES )
print-% : ; $( info $ * is a $ ( flavor $ *) variable set to [$ ( $ *) ]) @true