PACKAGE = coco-letters
VERSION = 0.1.0

DISPLAY_NAME = CoCo Letters

# Must be at most 8 characters.
PACKAGE_SHORT = letters

# Length of the words to be selected from file $(WORDLIST).
MIN_WORD_LEN = 2
MAX_WORD_LEN = 5

# Maximum number of MMU blocks that can contain dictionary entries.
# See the memory map in HACKING.md.
MAX_NUM_DICT_BLOCKS = 9

# Required libraries.
DECBFILE_LIB = decbfile
DECBFILE_LIB_DIR = decbfile
BCONTROL_LIB = bcontrol
BCONTROL_LIB_DIR = bcontrol
BSOUND_LIB = bsound
BSOUND_LIB_DIR = bsound

# Main program.
SRC = \
	main.c \
	graphics.c \
	file.c \
	dict.c \
	GameState.c \
	GamePlayer.c \
	WordSearch.c \
	CursorBlinker.c \
	PositionIterator.c

# N.B.: font4x8-ascii.c and font5x8-A-Z.c are not compiled.
#       They are read by $(BUILD_DATA) to generate part of the game data file.

GENERATED_SRC = $(WORD_LENGTH_FILENAME)

HEADERS = \
	defs.h \
	graphics.h \
	file.h \
	dict.h \
	GameState.h \
	GamePlayer.h \
	WordSearch.h \
	palette.h \
	board.h \
	CursorBlinker.h \
	PositionIterator.h

LIBS = -L $(DECBFILE_LIB_DIR) -l$(DECBFILE_LIB) \
		-L $(BCONTROL_LIB_DIR) -l$(BCONTROL_LIB) \
		-L $(BSOUND_LIB_DIR) -l$(BSOUND_LIB)
BIN = $(PACKAGE_SHORT).bin
DSK = $(PACKAGE)-$(VERSION).dsk
PCLEARARG = 1

# Dictionary.

#   List of words.
WORDLIST = word-list.txt

#   Files generated by the BUILD_DATA script from $(WORDLIST).
DATA_FILENAME = $(PACKAGE_SHORT).dat
WORD_LENGTH_FILENAME = word-length-index.c

# Script that builds DATA_FILENAME.
#
BUILD_DATA = build-data.pl


# Compilation and linking flags.
# The limit is $7F80 because 128 bytes are left for Basic's stack,
# which still exists at the moment when the user EXECs $(BIN).
#
ORG = --org=2000 --limit=7F80

TARGET = coco
INTERMEDIATE = #--intermediate
WERROR = -Werror
STACKSPACE = 2048
OPTIM = -fomit-frame-pointer -Oy
NDEBUG = -DNDEBUG

# Unsigned 16 bit integer other than 0.
# If defined, gets passed to srand().
# If not defined, timer is used.
#
FIXED_SEED = #-DFIXED_SEED=42

DEFINES = \
	'-DDISPLAY_NAME="$(DISPLAY_NAME)"' \
	-DVERSION=\"$(VERSION)\" \
	$(NDEBUG) \
	-DDATA_FILENAME=\"$(DATA_FILENAME)\" \
	-DMIN_WORD_LEN=$(MIN_WORD_LEN) \
	-DMAX_WORD_LEN=$(MAX_WORD_LEN) \
	-DMAX_NUM_DICT_BLOCKS=$(MAX_NUM_DICT_BLOCKS) \
	$(FIXED_SEED)
CFLAGS = --$(TARGET) $(WERROR) $(INTERMEDIATE) $(NO_RELOCATE) $(OPTIM) \
			$(DEFINES) \
			-I $(DECBFILE_LIB_DIR) -I $(BCONTROL_LIB_DIR) -I $(BSOUND_LIB_DIR) \
			--stack-space=$(STACKSPACE)
LDFLAGS = --$(TARGET) $(ORG) $(INTERMEDIATE)

OBJ = $(GENERATED_SRC:.c=.o) $(SRC:.c=.o)

DISTFILES = \
	README.md HACKING.md COPYING \
	Makefile \
	$(SRC) $(HEADERS) font4x8-ascii.c font5x8-A-Z.c autostart.c \
	$(BUILD_DATA) $(WORDLIST)

# Tools.
CMOC = cmoc
PERL = perl
TAR = tar
WRITECOCOFILE = writecocofile
INSTALL_LOADER = install-coco-boot-loader
XROAR = xroar
PARSE_COCO_BIN = parse-coco-bin

all: $(DSK)

$(BIN): $(OBJ) $(DECBFILE_LIB_DIR)/lib$(DECBFILE_LIB).a \
				$(BCONTROL_LIB_DIR)/lib$(BCONTROL_LIB).a \
				$(BSOUND_LIB_DIR)/lib$(BSOUND_LIB).a
	$(CMOC) -o $(BIN) $(LDFLAGS) $(OBJ) $(LIBS)

.PHONY: dict
dict: $(WORD_LENGTH_FILENAME)

$(DATA_FILENAME) $(WORD_LENGTH_FILENAME): $(BUILD_DATA) $(WORDLIST) defs.h
	$(PERL) $(BUILD_DATA) $(WORDLIST) $(DATA_FILENAME) $(WORD_LENGTH_FILENAME) $(MIN_WORD_LEN) $(MAX_WORD_LEN) $(MAX_NUM_DICT_BLOCKS)
	test -f $(DATA_FILENAME)
	test -f $(WORD_LENGTH_FILENAME)

$(DSK): $(BIN) $(DATA_FILENAME) autostart.bin
	$(PERL) -e 'print chr(255) x (35*18*256)' > $(DSK)
	$(INSTALL_LOADER) $(DSK) autostart.bin
	$(WRITECOCOFILE) --allocate-after-dir $(DSK) $(BIN)
	$(WRITECOCOFILE) --allocate-before-dir $(DSK) $(DATA_FILENAME)

# Loader that goes on track 34 to be executed by the CoCo DOS command.
autostart.bin: autostart.c Makefile
	$(CMOC) --dos -o $@ -D'COMMAND="CLEAR8:PCLEAR$(PCLEARARG):LOADM\"$(PACKAGE_SHORT)\":EXEC"' autostart.c

.PHONY: sizes
sizes: $(BIN)
	$(PARSE_COCO_BIN) $(BIN)

%.o: %.c
	$(CMOC) -c $(CFLAGS) -o $@ $<

.PHONY: clean-dict
clean-dict:
	rm -f $(DATA_FILENAME) $(WORD_LENGTH_FILENAME)

clean: clean-dict
	rm -f $(BIN) autostart.bin $(OBJ) $(OBJ:.o=.s) $(OBJ:.o=.lst) $(PACKAGE).map $(PACKAGE).link

distclean: clean
	rm -f $(GENERATED_SRC) $(SRC:.c=.d)

.PHONY: dist distcheck
dist:
	$(TAR) -czf $(PACKAGE)-$(VERSION).tar.gz --transform 's,^,$(PACKAGE)-$(VERSION)/,' $(DISTFILES)

distcheck: dist
	mkdir ,distcheck
	$(TAR) -C ,distcheck -xzf $(PACKAGE)-$(VERSION).tar.gz
	$(MAKE) -C ,distcheck/$(PACKAGE)-$(VERSION) \
					DECBFILE_LIB_DIR=../../$(DECBFILE_LIB_DIR) \
					BCONTROL_LIB_DIR=../../$(BCONTROL_LIB_DIR) \
					BSOUND_LIB_DIR=../../$(BSOUND_LIB_DIR)
	rm -fr ,distcheck
	@echo "SUCCESS: $(PACKAGE)-$(VERSION).tar.gz ready for distribution"

.PHONY: binaries
binaries: $(DSK)
	$(TAR) -czf $(PACKAGE)-$(VERSION)-binaries.tar.gz $(PACKAGE)-$(VERSION).dsk

# Runs make with arguments $(RECURSION) in the library projects used by this package.
# Supports the -n (dry run) option.
# Example: make recurse RECURSION=clean
#
.PHONY: recurse
recurse:
	$(MAKE) -C $(DECBFILE_LIB_DIR) $(RECURSION)
	$(MAKE) -C $(BCONTROL_LIB_DIR) $(RECURSION)
	$(MAKE) -C $(BSOUND_LIB_DIR) $(RECURSION)

# Automatic prerequisite generation.
%.d: %.c
	$(CMOC) --deps-only $(CFLAGS) $<

.PHONY: cleandeps
cleandeps:
	rm -f $(SRC:.c=.d)

include $(SRC:.c=.d)
