# Options. # HOST_PLATFORM - Which platform we're building on. # # Determined automatically if not specified on command line. # # Supported values: # * i686-windows # * i686-linux HOST_PLATFORM ?= # TARGET_PLATFORM - Which platform to build for. # # Determined from HOST_PLATFORM if not specified on command line. # # Supported values: # * i686-windows # * i686-linux TARGET_PLATFORM ?= # ROMID - The ROM version to use. # # Can be set in your environment using # $ export ROMID=... # # Supported values: # * ntsc-final ROMID ?= ntsc-final # GCC_OPT_LVL - the optimisation level if building with gcc. # # Supported values: -O0, -O1, -O2, -O3, -Os, -Og GCC_OPT_LVL = -O0 # ROM_SIZE - The desired ROM size in megabytes. # # All versions of the retail ROM are 32MB. # # If this is too low you might get this error from ld: # "final link failed: memory exhausted" ROM_SIZE := 32 # DEBUG - Enable (1) or disable (0) the debug menu and crash screen. # # When enabled, press C-up and C-down simultaneously to toggle the debug menu. # Note that some emulators have problems displaying the crash screen text. DEBUG = 0 ################################################################################ # Detect host platform if not specified. ifeq ($(HOST_PLATFORM),) ifeq ($(OS),Windows_NT) # assume msys for now UNAME_OS := $(shell uname -s) ifneq (,$(findstring MINGW64,$(UNAME_OS))) HOST_PLATFORM := x86_64-windows else HOST_PLATFORM := i686-windows endif else # TODO UNAME_ARCH := $(shell uname -m) UNAME_OS := $(shell uname -s) UNAME_OS := $(shell echo $(UNAME_OS) | tr A-Z a-z) HOST_PLATFORM := $(UNAME_ARCH)-$(UNAME_OS) endif endif # Set target platform to host platform if not specified. ifeq ($(TARGET_PLATFORM),) TARGET_PLATFORM := $(HOST_PLATFORM) endif ifeq (,$(findstring clean,$(MAKECMDGOALS))) $(info Host platform: $(HOST_PLATFORM)) $(info Target platform: $(TARGET_PLATFORM)) endif # Set whether the target arch is 64- or 32-bit. ifneq (,$(findstring 64,$(TARGET_PLATFORM))$(findstring armv8,$(TARGET_PLATFORM))) # TODO: we're not 64-bit compatible yet, error out if building the actual game ifeq (,$(findstring clean,$(MAKECMDGOALS))) $(error 64-bit target platforms are not supported yet) endif TARGET_64BIT = 1 else # TODO TARGET_64BIT = 0 endif # Set whether the target is big-endian or little-endian. TARGET_BIG_ENDIAN = 0 # TODO # The VERSION constant is used in the source to handle version-specific code. ifeq ($(ROMID),ntsc-final) VERSION = 2 else $(error ROM version $(VERSION) is not supported) endif VERSION_HASH := $(shell git rev-parse --short HEAD) VERSION_TARGET := $(TARGET_PLATFORM) VERSION_ROMID := $(ROMID) DEFINES := \ VERSION=$(VERSION) \ VERSION_HASH=\"$(VERSION_HASH)\" \ VERSION_TARGET=\"$(VERSION_TARGET)\" \ VERSION_ROMID=\"$(VERSION_ROMID)\" \ MATCHING=0 \ PAL=0 \ PIRACYCHECKS=0 \ ROM_SIZE=$(ROM_SIZE) \ _LANGUAGE_C=1 ifeq ($(DEBUG),1) DEFINES := $(DEFINES) DEBUG=1 endif C_DEFINES := $(foreach d,$(DEFINES),-D$(d)) A_DIR := src/assets/$(ROMID) B_DIR := build/$(ROMID)-port G_DIR := src/generated/$(ROMID) ifneq (,$(findstring windows,$(TARGET_PLATFORM))) TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -static-libstdc++ # on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs TOOLCHAIN := i686-w64-mingw32- else # TODO TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lGL -lz endif # On x86_64 gcc add -m32 to CFLAGS if building a 32-bit executable. ifneq (,$(findstring x86_64,$(HOST_PLATFORM))$(findstring x86_64,$(TOOLCHAIN))) ifneq (1,$(TARGET_64BIT)) TARGET_CFLAGS += -m32 endif endif # These are still used in the port, but only to generate headers. JSON_FILES := $(shell find $(A_DIR) -path '*/lang/*.json') JSON_FILES += $(shell find $(A_DIR) -path '*/pads/*.json') JSON_FILES += $(shell find $(A_DIR) -path '*/tiles/*.json') JSON_FILES += $(wildcard $(A_DIR)/*.json) JSON_HEADERS := $(patsubst $(A_DIR)/%.json, $(G_DIR)/%.h, $(JSON_FILES)) C_FILES := $(shell find src/game port -name '*.c') C_FILES := $(C_FILES) \ $(wildcard src/lib/mp3/*.c) \ $(wildcard src/lib/naudio/*.c) \ $(wildcard src/lib/ultra/audio/*.c) \ $(wildcard src/lib/ultra/gu/*.c) \ src/lib/ultra/io/vimodentsclan1.c \ src/lib/ultra/io/vimodepallan1.c \ src/lib/ultra/io/vimodempallan1.c \ src/lib/ultra/io/vitbl.c \ $(wildcard src/lib/a*.c) \ src/lib/base.c \ src/lib/collision.c \ src/lib/debughud.c \ src/lib/dma.c \ src/lib/fault.c \ src/lib/joy.c \ $(wildcard src/lib/lib_*.c) \ src/lib/mema.c \ src/lib/memp.c \ src/lib/model.c \ src/lib/modelasm_c.c \ src/lib/mp3.c \ src/lib/mtx_c.c \ src/lib/mtx.c \ src/lib/music.c \ src/lib/path.c \ src/lib/profile.c \ src/lib/rdp.c \ src/lib/rmon.c \ src/lib/rng_c.c \ src/lib/rzip_c.c \ src/lib/snd.c \ src/lib/speaker.c \ src/lib/varsinit.c \ src/lib/vi.c \ src/textureconfig.c CXX_FILES :=$(shell find port -name '*.cpp') C_O_FILES := $(patsubst %.c, $(B_DIR)/%.o, $(C_FILES)) CXX_O_FILES := $(patsubst %.cpp, $(B_DIR)/%.o, $(CXX_FILES)) O_FILES := $(C_O_FILES) $(CXX_O_FILES) INCLUDES = \ -I include \ -I include/PR \ -I src/include \ -I src/generated/$(ROMID) \ -I src/lib/ultra/audio \ -I port/include TOOLCHAIN ?= CC := $(TOOLCHAIN)gcc -std=c11 CXX := $(TOOLCHAIN)g++ -std=c++20 ifneq (,$(CXX_O_FILES)) LD := $(CXX) else LD := $(CC) endif $(C_O_FILES): OPT_LVL := $(GCC_OPT_LVL) COMMON_CFLAGS := $(C_DEFINES) -DAVOID_UB=1 $(INCLUDES) $(TARGET_CFLAGS) -g \ -fno-inline-functions \ -fno-strict-aliasing \ -funsigned-char \ -fwrapv \ -Wall \ -Wno-address \ -Wno-aggressive-loop-optimizations \ -Wno-int-in-bool-context \ -Wno-misleading-indentation \ -Wno-missing-braces \ -Wno-multichar \ -Wno-tautological-compare \ -Wno-unused-but-set-variable \ -Wno-unused-value \ -Wno-unused-variable CFLAGS := $(COMMON_CFLAGS) -Wno-pointer-sign CXXFLAGS := $(COMMON_CFLAGS) -Wno-unused-function LDFLAGS := $(TARGET_LDFLAGS) # Make ROMID available as an environment variable to all tooling. # (We use this a lot) export ROMID BIN := $(B_DIR)/pd.exe default: $(JSON_HEADERS) $(BIN) ################################################################################ # Asset Manager header generation # Anims $(G_DIR)/animations.h: $(A_DIR)/animations.json tools/assetmgr/mkanims --headers-only # Lang $(G_DIR)/lang/%.h: $(A_DIR)/lang/%.json tools/assetmgr/mklang $< en --headers-only # Pads $(G_DIR)/pads/%.h: $(A_DIR)/pads/%.json tools/assetmgr/mkpads $< --headers-only # Sequences $(G_DIR)/sequences.h: $(A_DIR)/sequences.json tools/assetmgr/mksequences --headers-only # Textures $(G_DIR)/textures.h: $(A_DIR)/textures.json tools/assetmgr/mktextures --headers-only # Tiles $(G_DIR)/tiles/%.h: $(A_DIR)/tiles/%.json tools/assetmgr/mktiles $< --headers-only ################################################################################ # Generic compilation rules $(BIN): $(O_FILES) $(LD) $(COMMON_CFLAGS) $(OPT_LVL) -o $(BIN) $^ $(LDFLAGS) $(B_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $< $(B_DIR)/%.o: %.cpp @mkdir -p $(dir $@) $(CXX) -c $(CXXFLAGS) $(OPT_LVL) -o $@ $< ################################################################################ # Clean rules clean: rm -rf build/$(ROMID)-port allclean: rm -rf build/* rm -rf src/generated codeclean: find $(B_DIR)/game $(B_DIR)/inflate $(B_DIR)/lib $(B_DIR)/port -name '*.o' -delete