# DVX build rules: every example as a DVX program (.app). # # A JoeyLib program on DVX runs in a window of the DVX desktop, or on the # whole screen (src/dvx). The library, libjoey.a, is built here with # JoeyLib's own DJGPP (DVX is built with the same gcc 12.2.0) against the SDK # the installer unpacked from a DVX tree's dist/sdk.zip into # toolchains/opt/dvx/sdk (DVX_SDK); the stage and the graphics are the DOS # port's (src/x86, the chunky generics). Each example is then a DVX SDK # project in build/dvx/apps// -- symlinks to its sources and to the # port's entry (src/dvx/dvxApp.c), a generated one-topic help file and # resource list -- built and packaged by the SDK's own sdk.mk (KIND = app, # LIBS = libjoey.a, DATA = its data files) and copied into build/dvx/bin/ # laid out as it goes into DVX: apps/joeylib//.app, .hlp # and DATA/. The gates and joey-run copy that tree into a DVX installation. include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk # The asset rules below define real targets before `all`, which would # otherwise become make's default goal. .DEFAULT_GOAL := all $(call requireTool,$(DOS_CC),toolchain:dos) $(call requireTool,$(DVX_SDK)/sdk.mk,toolchain:dvx) PLATFORM := dvx BUILD := $(REPO_DIR)/build/$(PLATFORM) LIBDIR := $(BUILD)/lib BINDIR := $(BUILD)/bin APPSDIR := $(BUILD)/apps DATADIR := $(BUILD)/data # Where a program installs in DVX: apps///. VENDOR := joeylib PORT_DIR := $(SRC_DIR)/dvx # sdk.mk's code generation, so the library matches the programs it links # into; -fomit-frame-pointer as on DOS. DVX_ARCH := -march=i486 -mtune=i586 -fomit-frame-pointer # The SDK's header folders (sdk.mk's list: all but the BASIC and socket ones), # for the port's own files only -- the core never sees a DVX header. DVX_SDK_INCS := $(addprefix -I,$(filter-out %/basic %/net,$(patsubst %/,%,$(wildcard $(DVX_SDK)/include/*/)))) # A program's exit() and atexit() are the port's (src/dvx/program.c): the # handlers run, and JoeyLib shuts down, when the program ends rather than # when DVX does. Applied to the library and the programs, never to the port. PROGRAM_RENAMES := -Dexit=dvxPortExit -Datexit=dvxPortAtExit CFLAGS := $(COMMON_CFLAGS) $(DVX_ARCH) -DJOEYLIB_PLATFORM_DVX -I$(SRC_X86) -I$(SRC_CG) -MMD -MP LIB_CFLAGS := $(CFLAGS) $(PROGRAM_RENAMES) PORT_CFLAGS := $(CFLAGS) -I$(PORT_DIR) $(DVX_SDK_INCS) # The flags every program adds to sdk.mk's (which bring the SDK headers and # -Werror), with the include folders every port gives its examples: the # program's main becomes jlGameMain, which the port calls. APP_CFLAGS := -DJOEYLIB_PLATFORM_DVX -Dmain=jlGameMain $(PROGRAM_RENAMES) -fomit-frame-pointer -I$(INCLUDE_DIR) -I$(SRC_CORE) -I$(PORT_DIR) # dvxApp.c is compiled into each program (it names it), not the library. PORT_ENTRY := $(PORT_DIR)/dvxApp.c PORT_C_SRCS := $(filter-out $(PORT_ENTRY),$(wildcard $(PORT_DIR)/*.c)) X86_C_SRCS := $(wildcard $(SRC_X86)/*.c) LIB_OBJS := \ $(patsubst $(SRC_CORE)/%.c,$(BUILD)/obj/core/%.o,$(CORE_C_SRCS)) \ $(patsubst $(SRC_DIR)/generic/%.c,$(BUILD)/obj/generic/%.o,$(GENERIC_C_SRCS)) \ $(patsubst $(PORT_DIR)/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \ $(patsubst $(SRC_X86)/%.c,$(BUILD)/obj/x86/%.o,$(X86_C_SRCS)) \ $(BUILD)/obj/codegen/spriteCompile.o \ $(BUILD)/obj/codegen/spriteStage.o LIB := $(LIBDIR)/libjoey.a # The examples: for each, its sources, its window title and a line of help # (no apostrophes: the help lines are written through the shell in quotes). # Worth knowing which ones the gates use: # UBER the golden-hash vehicle: a hash per public op, which must equal # the DOS port's (tests/goldens/uber/dos.txt): the same stage. # TILEBANK the tile-bank gate's program: the DOS bake loaded both ways and # pixel-checked, every other target's bake refused. # KEYS the input gate's program: typed characters to jlInputGetChar. hello_SRCS := $(EXAMPLES)/hello/hello.c hello_TITLE := Hello hello_HELP := The smallest JoeyLib program: it clears the screen and waits for a key. pattern_SRCS := $(EXAMPLES)/pattern/pattern.c pattern_TITLE := Pattern pattern_HELP := Eight bands of gradient palettes, one per band of scan lines. draw_SRCS := $(EXAMPLES)/draw/draw.c draw_TITLE := Draw draw_HELP := The drawing primitives: pixels, lines, circles, rectangles and flood fills. keys_SRCS := $(EXAMPLES)/keys/keys.c keys_TITLE := Keys keys_HELP := Keyboard, typed characters and mouse: held keys light up and typed text appears. Escape ends it. serial_SRCS := $(EXAMPLES)/serial/serial.c serial_TITLE := Serial serial_HELP := A serial terminal on COM1. sertest_SRCS := $(EXAMPLES)/sertest/sertest.c sertest_TITLE := SerTest sertest_HELP := The serial port test program. save_SRCS := $(EXAMPLES)/save/save.c save_TITLE := Save save_HELP := Saved files: counts its runs in a file in its settings folder. tilebank_SRCS := $(EXAMPLES)/tilebank/tilebank.c tilebank_TITLE := TileBank tilebank_HELP := The tile bank check: loads a baked tile bank two ways and checks every pixel. joy_SRCS := $(EXAMPLES)/joy/joy.c joy_TITLE := Joy joy_HELP := Joysticks: shows the position and buttons of each joystick. sprite_SRCS := $(EXAMPLES)/sprite/sprite.c sprite_TITLE := Sprite sprite_HELP := Compiled sprites moving over a background. audio_SRCS := $(EXAMPLES)/audio/audio.c audio_TITLE := Audio audio_HELP := Sound: music, sound effects and tones. uber_SRCS := $(EXAMPLES)/uber/uber.c uber_TITLE := Uber uber_HELP := The JoeyLib conformance and speed test: every drawing call, timed and checked. Its results go to joeylog.txt in its settings folder. adv_SRCS := $(EXAMPLES)/adventure/adventure.c adv_TITLE := Adventure adv_HELP := A small adventure game. adv2_SRCS := $(EXAMPLES)/adventure2/adventure2.c adv2_TITLE := Adventure 2 adv2_HELP := A second small adventure game. agi_SRCS := $(EXAMPLES)/agi/agi.c $(EXAMPLES)/agi/agiRes.c $(EXAMPLES)/agi/agiPic.c $(EXAMPLES)/agi/agiView.c $(EXAMPLES)/agi/agiVm.c $(EXAMPLES)/agi/agiObj.c $(EXAMPLES)/agi/agiText.c agi_TITLE := AGI agi_HELP := A Sierra AGI interpreter. The files of the game it plays go in its DATA folder. staxi_SRCS := $(EXAMPLES)/spacetaxi/spacetaxi.c $(EXAMPLES)/spacetaxi/stLevel.c $(EXAMPLES)/spacetaxi/stLevelFile.c $(EXAMPLES)/spacetaxi/stRender.c $(EXAMPLES)/spacetaxi/stSim.c $(EXAMPLES)/spacetaxi/stFare.c $(EXAMPLES)/spacetaxi/stHooks.c $(EXAMPLES)/spacetaxi/stTitle.c $(EXAMPLES)/spacetaxi/stC64Data.c $(EXAMPLES)/spacetaxi/stCels.c $(EXAMPLES)/spacetaxi/stAudio.c $(EXAMPLES)/spacetaxi/stLevelCels.c staxi_TITLE := Space Taxi staxi_HELP := Space Taxi: fly the taxi, pick up the fares, take them where they ask to go. APPS := hello pattern draw keys serial sertest save tilebank joy sprite audio uber adv adv2 agi staxi # UBER's probe build (part of all; scripts/verify-dvx-display.sh): UBER # with its UBER_PROBE rows, the display parity row among them, as a program # of its own packaged apart in build/dvx/probe, so neither bin/ (joey-run's # tree) nor the goldened UBER changes. -DUBER_FRAMES=1 as the IIgs probe # build: the run is wanted for its probe rows, not its timings. # (Its name, like every program's, is a DOS 8.3 name: DVX runs on DOS.) uberprob_SRCS := $(uber_SRCS) uberprob_TITLE := Uber Probe uberprob_HELP := UBER with its probe rows: the present checked against the stage on screen. Its results go to joeylog.txt in its settings folder. uberprob_CFLAGS := -DUBER_PROBE -DUBER_FRAMES=1 uberprob_BIN := $(BUILD)/probe PROBE_APPS := uberprob # Data the examples read from DATA/ beside the program: AUDIO its music and # sound effect; TILEBANK the DOS bake of the tile-bank fixture (the DOS # target byte: DVX shows the DOS stage), every other target's bake it must # refuse, and the expected pixels (common.mk); Space Taxi the DOS bake of # its levels, compiled cel banks (x86 code, the DOS target byte) and speech, # made by make/dos.mk -- only when the C64 image it comes from is present. audio_DATA := $(DATADIR)/audio/DATA tilebank_DATA := $(DATADIR)/tilebank/DATA staxi_DATA := $(if $(HAVE_STAXI_DATA),$(DATADIR)/staxi/DATA) AUDIO_DATA_FILES := $(audio_DATA)/test.mod $(audio_DATA)/test.sfx TILEBANK_OWN := $(tilebank_DATA)/tilebank/own.tbk DOS_STAXI_DATA := $(REPO_DIR)/build/dos/bin/STAXI/DATA .PHONY: all dvx dvx-lib dvx-apps dvx-probe clean-dvx clean $(addprefix app-,$(APPS) $(PROBE_APPS)) all dvx: dvx-lib dvx-apps dvx-probe dvx-lib: $(LIB) dvx-apps: $(addprefix app-,$(APPS)) dvx-probe: $(addprefix app-,$(PROBE_APPS)) $(BUILD)/obj/core/%.o: $(SRC_CORE)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(LIB_CFLAGS) -c $< -o $@ $(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c @mkdir -p $(dir $@) $(DOS_CC) $(LIB_CFLAGS) -c $< -o $@ $(BUILD)/obj/x86/%.o: $(SRC_X86)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(LIB_CFLAGS) -c $< -o $@ $(BUILD)/obj/codegen/%.o: $(SRC_CG)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(LIB_CFLAGS) -c $< -o $@ $(BUILD)/obj/port/%.o: $(PORT_DIR)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(PORT_CFLAGS) -c $< -o $@ $(LIB): $(LIB_OBJS) @mkdir -p $(dir $@) rm -f $@ $(DOS_AR) rcs $@ $^ # One program: (re)write its SDK project -- the Makefile, symlinks to its # sources and the port's entry, the help source and the resource list -- # then let sdk.mk build and package it, and copy the package into bin/. # sdk.mk rebuilds only what changed; the project files are rewritten only # when their contents change, so an unchanged program is not relinked. # $(1) = the program's name; $(1)_CFLAGS, if any, are added to its flags, # and $(1)_BIN, if set, is where it goes instead of bin/. define appRule app-$(1): $(LIB) $$($(1)_SRCS) $(PORT_ENTRY) $$(if $$($(1)_DATA),$(1)-data) @mkdir -p $(APPSDIR)/$(1) @for src in $$($(1)_SRCS) $(PORT_ENTRY); do ln -sfn $$$$src $(APPSDIR)/$(1)/$$$$(basename $$$$src); done @printf '%s\n' \ '# Generated by make/dvx.mk: the DVX SDK project of the JoeyLib example $(1).' \ 'SDK_DIR = $(DVX_SDK)' \ 'KIND = app' \ 'NAME = $(1)' \ 'VENDOR = $(VENDOR)' \ 'LIBS = $(LIB)' \ 'DATA = $$($(1)_DATA)' \ "CFLAGS = $(APP_CFLAGS) $$($(1)_CFLAGS) -I$$(dir $$(firstword $$($(1)_SRCS))) -DDVX_PORT_APP_NAME='\"$$($(1)_TITLE)\"'" \ 'include $$$$(SDK_DIR)/sdk.mk' | $(REPO_DIR)/make/support/dvx/writeIfChanged.sh $(APPSDIR)/$(1)/Makefile @printf '%s\n' \ '.topic $(1).overview' \ '.title $$($(1)_TITLE)' \ '.toc 0 $$($(1)_TITLE)' \ '.default' \ '.index $$($(1)_TITLE)' \ '' \ '.h1 $$($(1)_TITLE)' \ '' \ '$$($(1)_HELP)' \ '' \ '$$($(1)_TITLE) is a JoeyLib example program. It runs in its own window at a virtual 70 frames a second; while the window is active every key goes to it except Alt+Tab (switch programs), Ctrl+Esc (Task Manager) and Alt+F4 (close it). Game > Exit also closes it.' \ '' \ 'Game > Full Screen, or Alt+Enter, puts it on the whole screen at 320x200 in 256 colours, and back in its window. It starts the way it was left. Alt+Tab or Ctrl+Esc brings the desktop back while it runs on; coming back to it gives it the whole screen again.' \ | $(REPO_DIR)/make/support/dvx/writeIfChanged.sh $(APPSDIR)/$(1)/$(1).dhs @printf '%s\n' \ 'name text "$$($(1)_TITLE)"' \ 'author text "JoeyLib"' \ 'description text "JoeyLib example: $$($(1)_TITLE)"' \ | $(REPO_DIR)/make/support/dvx/writeIfChanged.sh $(APPSDIR)/$(1)/$(1).res $$(MAKE) -C $(APPSDIR)/$(1) DJGPP_PREFIX=$(DOS_PREFIX) package @mkdir -p $$(or $$($(1)_BIN),$(BINDIR)) rm -rf $$(or $$($(1)_BIN),$(BINDIR))/apps/$(VENDOR)/$(1) cp -R $(APPSDIR)/$(1)/pkg/apps $$(or $$($(1)_BIN),$(BINDIR))/ endef $(foreach a,$(APPS) $(PROBE_APPS),$(eval $(call appRule,$(a)))) .PHONY: audio-data tilebank-data staxi-data audio-data: $(AUDIO_DATA_FILES) tilebank-data: $(TILEBANK_OWN) staxi-data: $(MAKE) -f $(REPO_DIR)/make/dos.mk dos-staxi-data rm -rf $(staxi_DATA) @mkdir -p $(dir $(staxi_DATA)) cp -R $(DOS_STAXI_DATA) $(staxi_DATA) $(audio_DATA)/%: $(REPO_DIR)/assets/% @mkdir -p $(dir $@) cp $< $@ $(TILEBANK_OWN): $(TILEBANK_BAKE_DEPS) python3 $(TILEBANK_STAGE) dos $(TILEBANK_PNG) $(dir $@) clean-dvx: rm -rf $(BUILD) # `clean` as an alias for `clean-dvx`. Without it a bare # `make -f make/dvx.mk clean` FAILS -- and with stderr discarded that # looks like success while leaving stale objects the next build links. clean: clean-dvx # Pull in per-object header-dependency files generated by gcc -MMD/-MP. -include $(LIB_OBJS:.o=.d)