|
.PHONY: all clean
|
|
|
|
MYDIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
|
|
|
ifndef PROJECT_NAME
|
|
$(error PROJECT_NAME is not set to the name of your rom.)
|
|
endif
|
|
ifndef MBC
|
|
$(error MBC is not set. Should be set to the MBC name or value you want. Example "MBC5+RAM+BATTERY")
|
|
endif
|
|
ifndef TARGETS
|
|
$(error TARGETS is not set. Should be a combination of DMG SGB CGB)
|
|
endif
|
|
ifneq ($(filter-out DMG SGB CGB,$(TARGETS)),)
|
|
$(error TARGETS should be a combination of DMG SGB CGB, unknown: $(filter-out DMG SGB CGB,$(TARGETS)))
|
|
endif
|
|
|
|
MAPS := $(shell find level/ -type f -name '*.png' -not -name '*_coll.png')
|
|
SRC := $(shell find src/ -type f -name '*.c') $(shell find $(MYDIR)/src/ -type f -name '*.c') $(MAPS:level/%.png=_build/level/%.c)
|
|
ASM := $(shell find src/ -type f -name '*.asm') $(shell find $(MYDIR)/src/ -type f -name '*.asm')
|
|
|
|
# Which files do we use from the sdcc libc
|
|
LIBC := _memset.c gbz80/memcpy.s
|
|
LIBC += _divuchar.c _divschar.c _muluchar.c _mulschar.c _modschar.c _moduchar.c
|
|
LIBC += _divuint.c _divsint.c _mulint.c _modsint.c _moduint.c
|
|
# the 32 bit functions use 10% of ROM0, so do not include them
|
|
#LIBC += _divulong.c _divslong.c _mullong.c _modslong.c _modulong.c
|
|
LIBC_PATH := $(subst \,/,$(shell sdcc -mgbz80 --print-search-dirs | grep gbz80 | tail -n 1))/../src
|
|
|
|
ifneq (1,$(words [$(LIBC_PATH)]))
|
|
$(error "your environment or sdcc is installed in a path with spaces in it, this is not allowed, as it will break sdcc")
|
|
endif
|
|
|
|
Q ?= @
|
|
|
|
BUILD := _build
|
|
TOOLS := $(MYDIR)/tools
|
|
OBJS := $(patsubst %, $(BUILD)/%.o, $(ASM) $(SRC)) $(patsubst %, $(BUILD)/libc/%.o, $(LIBC)) $(BUILD)/gsinit.end.o
|
|
|
|
CFLAGS := -mgbz80 -Isrc/ -I$(MYDIR)/inc -I$(BUILD)/level
|
|
ASFLAGS := -isrc/ -i$(MYDIR)/inc -i$(BUILD)/assets/ -Wall
|
|
LDFLAGS := --pad 0xFF
|
|
FIXFLAGS := --validate --pad-value 0xFF --title "$(PROJECT_NAME)" --mbc-type "$(MBC)" -l 0x33
|
|
ROM_EXTENSION := gb
|
|
# Replace spaces with underscores in the project name.
|
|
PROJECT_NAME := $(subst $() $(),_,$(PROJECT_NAME))
|
|
|
|
ifeq ($(filter CGB,$(TARGETS)),) # Not targeting CGB, so disable CGB features
|
|
CFLAGS += -DCGB=0
|
|
ASFLAGS += -DCGB=0
|
|
LDFLAGS += --dmg
|
|
else
|
|
CFLAGS += -DCGB=1
|
|
ASFLAGS += -DCGB=1
|
|
ifeq ($(filter DMG,$(TARGETS))$(filter SGB,$(TARGETS)),) # Check if not targeting both CGB and DMG
|
|
FIXFLAGS += --color-only
|
|
else
|
|
FIXFLAGS += --color-compatible
|
|
endif
|
|
ROM_EXTENSION := gbc
|
|
endif
|
|
ifeq ($(filter SGB,$(TARGETS)),) # Not targeting SGB, so disable SGB features
|
|
CFLAGS += -DSGB=0
|
|
ASFLAGS += -DSGB=0
|
|
else # Targeting SGB as well
|
|
CFLAGS += -DSGB=1
|
|
ASFLAGS += -DSGB=1
|
|
FIXFLAGS += --sgb-compatible
|
|
endif
|
|
ifneq ($(findstring RAM,$(MBC)),)
|
|
FIXFLAGS += --ram-size 2
|
|
endif
|
|
|
|
all: $(PROJECT_NAME).$(ROM_EXTENSION)
|
|
|
|
# Rules to make c files
|
|
$(BUILD)/%.c.as: %.c
|
|
@echo Compiling $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)sdcc $(CFLAGS) -S $< -o $@ -Wp "-MQ $@ -MD $(@:.as=.as.d)"
|
|
-include $(patsubst %.c, $(BUILD)/%.c.as.d, $(SRC))
|
|
|
|
$(BUILD)/libc/%.c.as: $(LIBC_PATH)/%.c
|
|
@echo Compiling $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)sdcc $(CFLAGS) -S $< -o $@
|
|
|
|
$(BUILD)/%.c.asm: $(BUILD)/%.c.as $(TOOLS)/asmconvert.py
|
|
$(Q)python3 $(TOOLS)/asmconvert.py $(notdir $<) < $< > $@
|
|
|
|
$(BUILD)/%.c.asm.d: $(BUILD)/%.c.asm
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbasm $(ASFLAGS) $< -M $@ -MT $(@:.asm.d=.o) -MT $@ -MG
|
|
# rgbds dependency generation is broken, as it stops after the first missing file. so list all incbins always
|
|
$(Q)cat $< | grep -i '^ *INCBIN' | sed -E 's/ *incbin *"([^"]*)"/$(subst /,\/,$(@:.asm.d=.o)): \1/gI' >> $@
|
|
-include $(patsubst %.c, $(BUILD)/%.c.asm.d, $(SRC))
|
|
|
|
$(BUILD)/%.c.o: $(BUILD)/%.c.asm $(BUILD)/%.c.asm.d
|
|
@echo "Assembling (c)" $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbasm $(ASFLAGS) $< -o $@
|
|
|
|
# Rules to build libc asm files
|
|
$(BUILD)/libc/%.s.asm: $(LIBC_PATH)/%.s $(TOOLS)/asmconvert.py
|
|
@mkdir -p $(dir $@)
|
|
$(Q)python3 $(TOOLS)/asmconvert.py $(notdir $<) < $< > $@
|
|
|
|
$(BUILD)/libc/%.s.o: $(BUILD)/libc/%.s.asm
|
|
@echo Assembling $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbasm $(ASFLAGS) $< -o $@
|
|
|
|
# Rules to build project asm files
|
|
$(BUILD)/%.asm.d: %.asm
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbasm $(ASFLAGS) $< -M $@ -MT $(@:.d=.o) -MT $@ -MG
|
|
# rgbds dependency generation is broken, as it stops after the first missing file. so list all incbins always
|
|
$(Q)cat $< | grep -i '^ *INCBIN' | sed -E 's/incbin "([^"]*)"/$(subst /,\/,$(@:.d=.o)): \1/gI' >> $@
|
|
|
|
$(BUILD)/%.asm.o: %.asm $(BUILD)/%.asm.d
|
|
@echo Assembling $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbasm $(ASFLAGS) $< -o $@
|
|
-include $(patsubst %.asm, $(BUILD)/%.asm.d, $(ASM))
|
|
|
|
# Rule to build the final rom
|
|
$(PROJECT_NAME).$(ROM_EXTENSION) $(PROJECT_NAME).map $(PROJECT_NAME).sym: $(OBJS)
|
|
@echo Linking $@
|
|
$(Q)rgblink $(LDFLAGS) $^ -o $@ -m $(basename $@).map -n $(basename $@).sym
|
|
$(Q)rgbfix $(FIXFLAGS) $@
|
|
@python3 $(TOOLS)/romspace.py $(basename $@).map
|
|
|
|
# Asset related rules
|
|
$(BUILD)/assets/%.2bpp $(BUILD)/assets/%.map: assets/%.png
|
|
@echo Converting $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbgfx \
|
|
-t "$(BUILD)/$(shell dirname $<)/$(shell basename -s .png $<).map" \
|
|
-o "$(BUILD)/$(shell dirname $<)/$(shell basename -s .png $<).2bpp" \
|
|
-u \
|
|
$<
|
|
|
|
$(BUILD)/level/%.h $(BUILD)/level/%.c: level/%.png level/%_coll.png
|
|
@echo Generating level $<
|
|
@mkdir -p $(BUILD)/level
|
|
@cp $< $(BUILD)/level/
|
|
@cp $(shell dirname $<)/$(shell basename -s .png $<)_coll.png $(BUILD)/level/
|
|
@python3 scripts/generate_map.py "$(BUILD)/$<"
|
|
|
|
$(BUILD)/assets/%.oam.2bpp: assets/%.oam.png
|
|
@echo Converting $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbgfx -h $< -o $@
|
|
|
|
$(BUILD)/assets/%.1bpp: assets/%.png
|
|
@echo Converting $<
|
|
@mkdir -p $(dir $@)
|
|
$(Q)rgbgfx -d 1 $< -o $@
|
|
|
|
# Special hack to place a ret instruction at the end of the GSINIT section.
|
|
# This has to be linked last, as that ensures that this fragment is at the end of the "GSINIT" section.
|
|
$(BUILD)/gsinit.end.o:
|
|
@printf 'SECTION FRAGMENT "GSINIT", ROMX, BANK[1]\n ret' | rgbasm - -o $@
|
|
|
|
clean:
|
|
@rm -rf $(BUILD) $(PROJECT_NAME).$(ROM_EXTENSION) $(PROJECT_NAME).map $(PROJECT_NAME).sym
|
|
|
|
# Do not remove intermediate files (like assets, c->asm files, etc)
|
|
.SECONDARY:
|