# By Pierre Sarrazin <http://sarrazip.com/>
# This file is in the public domain.
#
# THERE IS NO WARRANTY AS TO THE RELIABILITY OF THIS LIBRARY.
# Users as advised to make BACKUPS of any file that might come into
# contact with this library.

PACKAGE = decbfile
VERSION = 0.1.12

PLATFORMFLAG = --coco
PLATFORMEXT = .bin

LIBNAME = decbfile
LIBSRC = \
	closeDir.c \
	closeRecordFile.c \
	closeSectorFile.c \
	computeTrackAndSector.c \
	copyFile.c \
	createRecordFile.c \
	createSectorFile.c \
	denormalizeFilename.c \
	dskcon.c \
	drivewire.c \
	dwReadBeckerPort.c \
	dwWriteBeckerPort.c \
	FileChoiceDialog.c \
	findDirEntry.c \
	findFreeGranule.c \
	flush.c \
	freeGranuleChain.c \
	getDirEntryFromUnnormalizedFilename.c \
	getFileGranuleFromIndex.c \
	getFileSizeFromDirEntry.c \
	getFileSizeFromFilename.c \
	getFreeSpaceAddress.c \
	getFreeSpaceSize.c \
	getNumFreeGranules.c \
	getNumGranulesInFile.c \
	getNumGranulesInOpenFile.c \
	getNumRecords.c \
	getOpenFileSize.c \
	getRecordOffsets.c \
	hasFullSector.c \
	init.c \
	initSeqWriteBuffer.c \
	isValidFATEntry.c \
	kill.c \
	normalizeFilename.c \
	openDir.c \
	openRecordFile.c \
	openSectorFile.c \
	openSectorFileFromDirEntry.c \
	readDir.c \
	readFAT.c \
	readHeader.c \
	readRecord.c \
	readSector.c \
	registerWrittenBytes.c \
	rename.c \
	runDOSLoader.c \
	setDskConAddresses.c \
	setFATEntry.c \
	setNumBytesUsedInLastSector.c \
	shutdown.c \
	truncateOpenFile.c \
	truncateOpenFileInGranules.c \
	truncateOpenRecordFile.c \
	unregisterAllDrives.c \
	unregisterDrive.c \
	writeFAT.c \
	writeHeader.c \
	writeRecord.c \
	writeSector.c \
	binfile.c \
	writeMemoryToFile.c \
	readFileToMemory.c \
	readFileToDynamicMemory.c \
	decbutil.c

LIBHEADERS = \
	decbfile.h \
	decbfile_private.h \
	binfile.h \
	decbutil.h \
	decbutil_private.h \
	decbdrivewire.h \
	FileChoiceDialog.h \
	runDOSLoader.h

# w.bin to be run by w.bas, which does PCLEAR 1.
TEST_EXE = w$(PLATFORMEXT)
TEST_SRC = w.c crc16.c
TEST_HEADERS = crc16.h
TEST_ORG = 1600
TEST_LDFLAGS = $(LDFLAGS) --org=$(TEST_ORG) --stack-space=3072

# This program saves the 32x16 screen to a file in a single function call.
UTWRITE_EXE = utwrite$(PLATFORMEXT)
UTWRITE_SRC = utwrite.c
UTWRITE_HEADERS =
UTWRITE_ORG = 2800
UTWRITE_LDFLAGS = $(LDFLAGS) --org=$(UTWRITE_ORG)

# This program loads a 32x16 screen from a file in a single function call.
UTREAD_EXE = utread$(PLATFORMEXT)
UTREAD_SRC = utread.c
UTREAD_HEADERS =
UTREAD_ORG = 2800
UTREAD_LDFLAGS = $(LDFLAGS) --org=$(UTREAD_ORG)

# Demo for the FileChoiceDialog object on the 32x16 (6847) screen.
FCDEMO_EXE = fcdemo$(PLATFORMEXT)
FCDEMO_SRC = fcdemo.c
FCDEMO_HEADERS =
FCDEMO_ORG = 2800
FCDEMO_LDFLAGS = $(LDFLAGS) --org=$(FCDEMO_ORG)
FCDEMO_DSK = fcdemo.dsk

# Demo of using DriveWire via the Becker port.
DWDEMO_EXE = dwdemo$(PLATFORMEXT)
DWDEMO_SRC = dwdemo.c
DWDEMO_HEADERS =
DWDEMO_ORG = 2800
DWDEMO_LDFLAGS = $(LDFLAGS) --org=$(DWDEMO_ORG)
DWDEMO_DSK = dwdemo.dsk

# Floppy containing the demo of the driver.
FILEDRVR_DSK = filedrvr.dsk

# Tools and options.
CMOC = cmoc
LWASM = lwasm
WRITECOCOFILE = writecocofile
PERL = perl
LWAR = lwar
TAR = tar
WARNINGS = -Wfor-condition-sizes
WERROR = -Werror
OPTIM = -O2
CFLAGS = $(OPTIM) -DNDEBUG $(INTERMEDIATE) $(WARNINGS) $(WERROR) -I .
LDFLAGS = $(INTERMEDIATE)
INTERMEDIATE = #--intermediate

DISTFILES = Makefile $(LIBSRC) $(LIBHEADERS) $(TEST_SRC) $(TEST_HEADERS) \
		$(UTWRITE_SRC) $(UTWRITE_HEADERS) \
		$(UTREAD_SRC) $(UTREAD_HEADERS) \
		$(FCDEMO_SRC) $(FCDEMO_HEADERS) \
		$(DWDEMO_SRC) $(DWDEMO_HEADERS) \
		w.bas loadbin.c \
		filedrvr.c rdwrdemo.bas rdwrdemo.asm inputsrc.txt

TEST_OBJ = $(TEST_SRC:.c=.o)
LIBOBJ = $(LIBSRC:.c=.o)

all: dual_disks $(UTWRITE_EXE) $(UTREAD_EXE) $(FCDEMO_DSK) loadbin.dsk $(FILEDRVR_DSK) $(DWDEMO_DSK)

# Create two floppy images that w.bin uses to test the library.
# To test this on an xRoar-emulated CoCo 2:
#   xroar -machine coco2bus -type 'LOADM\"W\":EXEC\r' -load drive0.dsk -load drive1.dsk
# To test this on a MAME-emulated CoCo 3:
#   mamemess -skip_gameinfo -autoboot_command "\nLOADM\"W\":EXEC\n" coco3 -flop1 drive0.dsk -flop2 drive1.dsk
#
.PHONY: dual_disks
dual_disks: drive0.dsk drive1.dsk

drive0.dsk: $(TEST_EXE)
	$(PERL) -e 'print chr(255) x (35*18*256)' > $@
	$(WRITECOCOFILE) $@ $(TEST_EXE)

drive1.dsk:
	$(PERL) -e 'print chr(255) x (35*18*256)' > $@

$(TEST_EXE): $(TEST_OBJ) lib$(LIBNAME).a
	$(CMOC) -o $(TEST_EXE) $(TEST_LDFLAGS) $(TEST_OBJ) -L. -l$(LIBNAME)

UTWRITE_OBJ = $(UTWRITE_SRC:.c=.o)

$(UTWRITE_EXE): $(UTWRITE_OBJ) lib$(LIBNAME).a
	$(CMOC) -o $(UTWRITE_EXE) $(UTWRITE_LDFLAGS) $(UTWRITE_OBJ) -L. -l$(LIBNAME)

UTREAD_OBJ = $(UTREAD_SRC:.c=.o)

$(UTREAD_EXE): $(UTREAD_OBJ) lib$(LIBNAME).a
	$(CMOC) -o $(UTREAD_EXE) $(UTREAD_LDFLAGS) $(UTREAD_OBJ) -L. -l$(LIBNAME)

FCDEMO_OBJ = $(FCDEMO_SRC:.c=.o)

$(FCDEMO_EXE): $(FCDEMO_OBJ) lib$(LIBNAME).a
	$(CMOC) -o $(FCDEMO_EXE) $(FCDEMO_LDFLAGS) $(FCDEMO_OBJ) -L. -l$(LIBNAME)

# Put the FileChoiceDialog demo on a floppy disk image,
# then add several bogus files to help demo the directory
# listing part of the dialog.
#
$(FCDEMO_DSK): $(FCDEMO_EXE)
	$(PERL) -e 'print chr(255) x (35*18*256)' > $(FCDEMO_DSK)
	$(WRITECOCOFILE) $(FCDEMO_DSK) $(FCDEMO_EXE)
	mkdir ,temp/
	for x in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do \
		echo -ne "CONTENT $$x\r" > ,temp/file$$x.dat; \
		$(WRITECOCOFILE) $(FCDEMO_DSK) ,temp/file$$x.dat; \
	done; \
	rm -fr ,temp/

lib$(LIBNAME).a: $(LIBOBJ)
	$(LWAR) --create $@ $(LIBOBJ)

# Demo that loads a .bin file.
loadbin.dsk: loadbin.c lib$(LIBNAME).a
	$(PERL) -e 'print "S org \$$7000\n ldd #6809\n rts\n end S"' > example.asm
	$(LWASM) -f decb -o example.bin example.asm
	rm example.asm
	$(CMOC) -o loadbin.bin --org=2800 loadbin.c -L. -l$(LIBNAME)
	$(PERL) -e 'print chr(255) x (35*18*256)' > loadbin.dsk
	$(WRITECOCOFILE) loadbin.dsk loadbin.bin
	$(WRITECOCOFILE) loadbin.dsk example.bin

# Driver that can be used by an external program to access files.
FILEDRVR_ADDR = 6D00  # hex
FILEDRVR_LIMIT = 8000
filedrvr.bin: filedrvr.c lib$(LIBNAME).a
	$(CMOC) --org=$(FILEDRVR_ADDR) --limit=$(FILEDRVR_LIMIT) -o $@ $(INTERMEDIATE) -I . filedrvr.c -L . -l$(LIBNAME)

# Demo of this driver.
# The CLEAR statement in rdwrdemo.bas must be one less than RDWRDEMO_ADDR.
# The .bin must end at or before FILEDRVR_ADDR.
RDWRDEMO_ADDR = 6B00  # hex
RDWRDEMO_LIST_OPT =  #--list=$(<:.asm=.lst)  # to have assembler generate .lst assembly listing
rdwrdemo.bin: rdwrdemo.asm
	$(LWASM) -f decb -D demoStart=0x$(RDWRDEMO_ADDR) -D driver=0x$(FILEDRVR_ADDR) $(RDWRDEMO_LIST_OPT) -o $@ $<
	$(PERL) -e 'exit(-s "rdwrdemo.bin" > 0x$(FILEDRVR_ADDR)-0x$(RDWRDEMO_ADDR)+5+5)'  # fails if BIN file too large

# Floppy containing the demo of the driver.
$(FILEDRVR_DSK): rdwrdemo.bas rdwrdemo.bin input.txt filedrvr.bin
	$(PERL) -e 'print chr(255) x (35*18*256)' > $(FILEDRVR_DSK)
	$(WRITECOCOFILE) --ascii $(FILEDRVR_DSK) rdwrdemo.bas  # demo program loader
	$(WRITECOCOFILE) $(FILEDRVR_DSK) rdwrdemo.bin  # demo program
	$(WRITECOCOFILE) --ascii $(FILEDRVR_DSK) input.txt  # file loaded by demo
	$(WRITECOCOFILE) $(FILEDRVR_DSK) filedrvr.bin  # driver

# Floppy containing the DriveWire demo.
$(DWDEMO_DSK): $(DWDEMO_EXE)
	$(PERL) -e 'print chr(255) x (35*18*256)' > $(DWDEMO_DSK)
	$(WRITECOCOFILE) $(DWDEMO_DSK) $(DWDEMO_EXE)
	$(PERL) -e 'print "THIS IS A TEXT FILE.\r"' > demotext.txt
	$(WRITECOCOFILE) --ascii $(DWDEMO_DSK) demotext.txt
	rm -f demotext.txt

DWDEMO_OBJ = $(DWDEMO_SRC:.c=.o)

$(DWDEMO_EXE): $(DWDEMO_OBJ) lib$(LIBNAME).a
	$(CMOC) -o $(DWDEMO_EXE) $(DWDEMO_LDFLAGS) $(DWDEMO_OBJ) -L. -l$(LIBNAME)


# Prepare a file that contains 6847 video codes.
# Newlines are ignored.
# An underscore is replaced with a graphical character.
input.txt: inputsrc.txt
	$(PERL) -pe 's/\s+$$//; s/_/\xA9/g; s/ /\x60/g; s/\x2E/\x6E/g' < $< > $@


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

clean:
	rm -f lib$(LIBNAME).a $(LIBOBJ) $(TEST_EXE) $(TEST_OBJ) \
			$(UTWRITE_EXE) $(UTWRITE_OBJ) $(UTREAD_EXE) $(UTREAD_OBJ) \
			$(FCDEMO_EXE) $(FCDEMO_OBJ) \
			rdwrdemo.bin filedrvr.bin input.txt \
			example.asm example.bin \
			loadbin.bin loadbin.dsk $(FILEDRVR_DSK)

.PHONY: dist
dist:
	$(TAR) -chzf $(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) all
	rm -fr ,distcheck
	@echo "SUCCESS: $(PACKAGE)-$(VERSION).tar.gz ready for distribution"

bindist:
	$(TAR) -chzf $(PACKAGE)-filedrvr-$(VERSION).tar.gz --transform 's,^,$(PACKAGE)-filedrvr-$(VERSION)/,' filedrvr.bin


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

.PHONY: cleandeps
cleandeps:
	rm -f $(LIBSRC:.c=.d) $(TEST_SRC:.c=.d) $(UTWRITE_SRC:.c=.d) $(UTREAD_SRC:.c=.d) $(FCDEMO_SRC:.c=.d)

include $(TEST_SRC:.c=.d)
include $(UTWRITE_SRC:.c=.d)
include $(UTREAD_SRC:.c=.d)
include $(FCDEMO_SRC:.c=.d)
include $(LIBSRC:.c=.d)
