# volatile information
VERSION=0.3
RELEASE=beta

DEBUG_OUTPUT_DIR=debug
DEBUG_OBJECT_DIR=debug
RELEASE_OUTPUT_DIR=release
RELEASE_OBJECT_DIR=release
QUAKE2_DIR=/usr/local/games/quake2
BIN_DIR=/usr/local/bin
ARCH=i386
SHLIBEXT=so
Q2MODULE=game$(ARCH).$(SHLIBEXT)

# directories
COMMON_DIR=common
DEMOCONV_DIR=democonv
RELAY_DIR=relay
REPLAY_DIR=replay
PROXY_DIR=proxy

# debug/release commands
CC=gcc
BASE_CFLAGS=-I$(COMMON_DIR) -Wall -fPIC
DEBUG_CFLAGS=$(BASE_CFLAGS) -g
RELEASE_CFLAGS=$(BASE_CFLAGS) -O4

BASE_LFLAGS=-lm -ldl
DEBUG_LFLAGS=$(BASE_LFLAGS)
RELEASE_LFLAGS=$(BASE_LFLAGS)

# distribution settings
DIST_BASE=relay
DIST_DIR=$(DIST_BASE)-$(VERSION)

# debug is the default build mode
ifeq ($(MODE),)
  MODE=DEBUG
endif

# convert lowercase to uppercase
ifeq ($(MODE),debug)
  MODE=DEBUG
endif
ifeq ($(MODE),release)
  MODE=RELEASE
endif

OUTPUT_DIR=$($(MODE)_OUTPUT_DIR)
OBJECT_DIR=$($(MODE)_OBJECT_DIR)
CFLAGS=$($(MODE)_CFLAGS)
LFLAGS=$($(MODE)_LFLAGS)

# commands
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
DO_LINK=$(CC) $(LFLAGS) -o $@
DO_SHLINK=$(CC) $(LFLAGS) -shared -o $@
TAR=/bin/tar

# targets
DEMOCONV_TARGET=$(OUTPUT_DIR)/$(DEMOCONV_DIR)/democonv
RELAY_TARGET=$(OUTPUT_DIR)/$(RELAY_DIR)/$(Q2MODULE)
REPLAY_TARGET=$(OUTPUT_DIR)/$(REPLAY_DIR)/$(Q2MODULE)
PROXY_TARGET=$(OUTPUT_DIR)/$(PROXY_DIR)/$(Q2MODULE)

TARGETS = \
	$(DEMOCONV_TARGET) \
	$(RELAY_TARGET) \
	$(REPLAY_TARGET) \
	$(PROXY_TARGET)

# objects
DEMOCONV_OBJS = \
	$(OBJECT_DIR)/$(COMMON_DIR)/block.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/bsp.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/dm2.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/endian.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/getopt.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/getopt1.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/pak.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/q2utils.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/utils.o \
	$(OBJECT_DIR)/$(DEMOCONV_DIR)/democonv.o \
	$(OBJECT_DIR)/$(DEMOCONV_DIR)/dc_dm2.o

RELAY_OBJS = \
	$(OBJECT_DIR)/$(COMMON_DIR)/block.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/dm2.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/endian.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/pak.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/proxy.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/q2utils.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/utils.o \
	$(OBJECT_DIR)/$(RELAY_DIR)/r_export.o \
	$(OBJECT_DIR)/$(RELAY_DIR)/r_import.o \
	$(OBJECT_DIR)/$(RELAY_DIR)/r_main.o

REPLAY_OBJS = \
	$(OBJECT_DIR)/$(COMMON_DIR)/block.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/dm2.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/endian.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/pak.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/q2utils.o \
	$(OBJECT_DIR)/$(COMMON_DIR)/utils.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/g_menu.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_client.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_cmds.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_dm2.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_main.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_menus.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_q2utils.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_save.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_spawn.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_svcmds.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_utils.o \
	$(OBJECT_DIR)/$(REPLAY_DIR)/rp_view.o

PROXY_OBJS = \
	$(OBJECT_DIR)/$(COMMON_DIR)/proxy.o \
	$(OBJECT_DIR)/$(PROXY_DIR)/p_main.o

SOURCES = \
	$(wildcard $(COMMON_DIR)/*.c) \
	$(wildcard $(DEMOCONV_DIR)/*.c) \
	$(wildcard $(RELAY_DIR)/*.c) \
	$(wildcard $(REPLAY_DIR)/*.c) \
	$(wildcard $(PROXY_DIR)/*.c)

HEADERS = \
	$(wildcard $(COMMON_DIR)/*.h) \
	$(wildcard $(DEMOCONV_DIR)/*.h) \
	$(wildcard $(RELAY_DIR)/*.h) \
	$(wildcard $(REPLAY_DIR)/*.h) \
	$(wildcard $(PROXY_DIR)/*.h) \

EXTRA_SOURCES = \
	Makefile \
	README \
	FAQ \
	ChangeLog \
	proxify \
	$(DEMOCONV_DIR)/democonv.dsp \
	$(RELAY_DIR)/relay.dsp \
	$(REPLAY_DIR)/replay.dsp \
	$(PROXY_DIR)/proxy.dsp

SOURCE_DISTFILES = $(SOURCES) $(HEADERS) $(EXTRA_SOURCES)
SOURCE_DIST = $(DIST_DIR).src.tar.gz

# phony targets
.PHONY: all common-dirs clean \
	democonv democonv-dirs clean-democonv \
	relay relay-dirs clean-relay \
	replay replay-dirs clean-replay \
	proxy proxy-dirs clean-proxy \
	dist dist-clean \
	volatile

# default build
all: $(TARGETS)

common-dirs:
	@-mkdir $(OUTPUT_DIR) > /dev/null
	@-mkdir $(OBJECT_DIR) > /dev/null
	@-mkdir $(OBJECT_DIR)/$(COMMON_DIR) > /dev/null

# democonv make
democonv: $(DEMOCONV_TARGET)

democonv-dirs:
	@-mkdir $(OUTPUT_DIR)/$(DEMOCONV_DIR)
	@-mkdir $(OBJECT_DIR)/$(DEMOCONV_DIR)

$(DEMOCONV_TARGET): common-dirs democonv-dirs $(DEMOCONV_OBJS)
	$(DO_LINK) $(DEMOCONV_OBJS)

# relay make
relay: $(RELAY_TARGET)

relay-dirs:
	@-mkdir $(OUTPUT_DIR)/$(RELAY_DIR)
	@-mkdir $(OBJECT_DIR)/$(RELAY_DIR)

$(RELAY_TARGET): common-dirs relay-dirs $(RELAY_OBJS)
	$(DO_SHLINK) $(RELAY_OBJS)

# replay make
replay: $(REPLAY_TARGET)

replay-dirs:
	@-mkdir $(OUTPUT_DIR)/$(REPLAY_DIR)
	@-mkdir $(OBJECT_DIR)/$(REPLAY_DIR)

$(REPLAY_TARGET): common-dirs replay-dirs $(REPLAY_OBJS)
	$(DO_SHLINK) $(REPLAY_OBJS)

# proxy make
proxy: $(PROXY_TARGET)

proxy-dirs:
	@-mkdir $(OUTPUT_DIR)/$(PROXY_DIR)
	@-mkdir $(OBJECT_DIR)/$(PROXY_DIR)

$(PROXY_TARGET): common-dirs proxy-dirs $(PROXY_OBJS)
	$(DO_SHLINK) $(PROXY_OBJS)

# volatile make
volatile:
	@echo \#define RELAY_VERSION \"$(VERSION)\" > $(COMMON_DIR)/volatile.h
	@echo \#define RELAY_RELEASE \"$(RELEASE)\" >> $(COMMON_DIR)/volatile.h

# distribution make
source-dir:
	@[ -e $(DIST_DIR) ] && rm -rf $(DIST_DIR) || exit 0
	@mkdir $(DIST_DIR)
	@mkdir $(DIST_DIR)/$(COMMON_DIR)
	@mkdir $(DIST_DIR)/$(RELAY_DIR)
	@mkdir $(DIST_DIR)/$(REPLAY_DIR)
	@mkdir $(DIST_DIR)/$(PROXY_DIR)
	@mkdir $(DIST_DIR)/$(DEMOCONV_DIR)
	@for file in $(SOURCE_DISTFILES); do \
	  cp -p $$file $(DIST_DIR)/$$file; \
	done
	@chmod -R a+r $(DIST_DIR)

source-dist: source-dir
	@[ -e $(SOURCE_DIST) ] && rm -f $(SOURCE_DIST) || exit 0
	$(TAR) czf $(SOURCE_DIST) $(DIST_DIR)
	@chmod 644 $(SOURCE_DIST)

# install make
install:
	@-mkdir $(QUAKE2_DIR)/release
	@-mkdir $(QUAKE2_DIR)/proxy
	@-mkdir $(QUAKE2_DIR)/proxy/relay
	@-mkdir $(QUAKE2_DIR)/proxy/replay
	cp -p $(DEMOCONV_TARGET) $(BIN_DIR)
	cp -p $(RELAY_TARGET) $(QUAKE2_DIR)/proxy/relay
	cp -p $(REPLAY_TARGET) $(QUAKE2_DIR)/proxy/replay
	cp -p $(PROXY_TARGET) $(QUAKE2_DIR)/release

# remove carriage returns
remove-carriage-returns:
	dos2unix $(SOURCE_DISTFILES)

lowercase:
	lcfile $(SOURCES) $(HEADERS)

# clean make
clean-democonv:
	-rm -f $(DEMOCONV_OBJS)
	-rm -f $(DEMOCONV_TARGET)

clean-relay:
	-rm -f $(RELAY_OBJS)
	-rm -f $(RELAY_TARGET)

clean-replay:
	-rm -f $(REPLAY_OBJS)
	-rm -f $(REPLAY_TARGET)

clean-proxy:
	-rm -f $(PROXY_OBJS)
	-rm -f $(PROXY_TARGET)

clean: clean-democonv clean-relay clean-replay clean-proxy

# common files
$(OBJECT_DIR)/$(COMMON_DIR)/block.o : $(COMMON_DIR)/block.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/bsp.o : $(COMMON_DIR)/bsp.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/dm2.o : $(COMMON_DIR)/dm2.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/endian.o : $(COMMON_DIR)/endian.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/getopt.o : $(COMMON_DIR)/getopt.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/getopt1.o : $(COMMON_DIR)/getopt1.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/pak.o : $(COMMON_DIR)/pak.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/proxy.o : $(COMMON_DIR)/proxy.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/q2utils.o : $(COMMON_DIR)/q2utils.c
	$(DO_CC)
$(OBJECT_DIR)/$(COMMON_DIR)/utils.o : $(COMMON_DIR)/utils.c
	$(DO_CC)

# democonv files
$(OBJECT_DIR)/$(DEMOCONV_DIR)/dc_dm2.o : $(DEMOCONV_DIR)/dc_dm2.c
	$(DO_CC)
$(OBJECT_DIR)/$(DEMOCONV_DIR)/democonv.o : $(DEMOCONV_DIR)/democonv.c
	$(DO_CC)

# relay files
$(OBJECT_DIR)/$(RELAY_DIR)/r_export.o : $(RELAY_DIR)/r_export.c
	$(DO_CC)
$(OBJECT_DIR)/$(RELAY_DIR)/r_import.o : $(RELAY_DIR)/r_import.c
	$(DO_CC)
$(OBJECT_DIR)/$(RELAY_DIR)/r_main.o : $(RELAY_DIR)/r_main.c
	$(DO_CC)

# replay files
$(OBJECT_DIR)/$(REPLAY_DIR)/g_menu.o : $(REPLAY_DIR)/g_menu.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_client.o : $(REPLAY_DIR)/rp_client.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_cmds.o : $(REPLAY_DIR)/rp_cmds.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_dm2.o : $(REPLAY_DIR)/rp_dm2.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_main.o : $(REPLAY_DIR)/rp_main.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_menus.o : $(REPLAY_DIR)/rp_menus.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_q2utils.o : $(REPLAY_DIR)/rp_q2utils.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_save.o : $(REPLAY_DIR)/rp_save.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_spawn.o : $(REPLAY_DIR)/rp_spawn.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_svcmds.o : $(REPLAY_DIR)/rp_svcmds.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_utils.o : $(REPLAY_DIR)/rp_utils.c
	$(DO_CC)
$(OBJECT_DIR)/$(REPLAY_DIR)/rp_view.o : $(REPLAY_DIR)/rp_view.c
	$(DO_CC)

# proxy files
$(OBJECT_DIR)/$(PROXY_DIR)/p_main.o : $(PROXY_DIR)/p_main.c
	$(DO_CC)
