316 lines
15 KiB
Makefile
316 lines
15 KiB
Makefile
# Sharp X68000 (elf2x68k / m68k-xelf-gcc) build rules.
|
|
#
|
|
# The port draws planar into the text plane (src/x68000/halPlanar.c), shares
|
|
# the Amiga's 68k planar fills, plots and sprite emitter (src/m68k), plays
|
|
# chip music on the OPM and samples through the ADPCM channel.
|
|
#
|
|
# The toolchain is elf2x68k (BSD-3, gcc 13.4.0 / binutils / newlib), installed
|
|
# by ./install.sh (X68K_ROOT). m68k-xelf-gcc emits ELF; the driver's
|
|
# -Wl,-elf2x68k pass converts it to a Human68k .X.
|
|
|
|
include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk
|
|
|
|
# The libxmp-lite rules below define a real target before `all`, which would
|
|
# otherwise silently become make's default goal (symptom: a bare `make -f
|
|
# make/x68000.mk` reports only "libxmplite.a is up to date" and builds nothing).
|
|
.DEFAULT_GOAL := all
|
|
|
|
$(call requireTool,$(X68K_ROOT)/bin/m68k-xelf-gcc,toolchain:x68000)
|
|
$(call requireTool,$(LIBXMP_DIR)/include/libxmp-lite/xmp.h,toolchain:x68000)
|
|
|
|
PLATFORM := x68000
|
|
BUILD := $(REPO_DIR)/build/$(PLATFORM)
|
|
LIBDIR := $(BUILD)/lib
|
|
BINDIR := $(BUILD)/bin
|
|
|
|
X68K_CC := $(X68K_ROOT)/bin/m68k-xelf-gcc
|
|
X68K_AR := $(X68K_ROOT)/bin/m68k-xelf-ar
|
|
|
|
# The linker is driven by a wrapper script (m68k-elf/bin/ld.x) that shells out
|
|
# to `m68k-xelf-ld.bfd` by bare name, so the toolchain's own bin/ MUST be on
|
|
# PATH or the link dies with "m68k-xelf-ld.bfd: command not found". Compiling
|
|
# and archiving work fine without it, so this only bites at link time.
|
|
export PATH := $(X68K_ROOT)/bin:$(PATH)
|
|
|
|
CFLAGS := $(COMMON_CFLAGS) -m68000 -fomit-frame-pointer \
|
|
-DJOEYLIB_PLATFORM_X68000 \
|
|
-I$(LIBXMP_DIR)/include \
|
|
-I$(SRC_DIR)/x68000 -I$(SRC_68K) -I$(REPO_DIR)/src/codegen -MMD -MP
|
|
LDFLAGS := -lm
|
|
|
|
PORT_C_SRCS := $(wildcard $(SRC_DIR)/x68000/*.c)
|
|
# Raw interrupt shims (timer tick, SCB raster, SCC receive): each saves every
|
|
# register and returns with RTE, which a C function cannot.
|
|
PORT_S_SRCS := $(wildcard $(SRC_DIR)/x68000/*.s)
|
|
|
|
# Sprite codegen is the shared 68k PLANAR emitter, unchanged. Its
|
|
# AMIGA_PLANE_STRIDE is SURFACE_WIDTH/8 = 40, which is this port's surface
|
|
# stride too -- the display's 128-byte stride never reaches the emitter, which
|
|
# only ever addresses the surface. So sprites COMPILE here rather than
|
|
# interpret; spriteEmitStub.o is gone.
|
|
CODEGEN_DIR := $(REPO_DIR)/src/codegen
|
|
|
|
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 $(SRC_DIR)/x68000/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \
|
|
$(patsubst $(SRC_DIR)/x68000/%.s,$(BUILD)/obj/port/%.o,$(PORT_S_SRCS)) \
|
|
$(BUILD)/obj/68k/planarFill.o \
|
|
$(BUILD)/obj/68k/planarPlot.o \
|
|
$(BUILD)/obj/68k/spriteEmitPlanar68k.o \
|
|
$(BUILD)/obj/codegen/spriteCompile.o \
|
|
$(BUILD)/obj/codegen/spriteStage.o
|
|
|
|
# libxmp-lite: the Protracker decoder shared with the DOS and ST ports. Same
|
|
# build recipe as make/atarist.mk -- LIBXMP_CORE_DISABLE_IT keeps it off math.h,
|
|
# which this newlib does not usefully provide for a 68000 target.
|
|
# LIBXMP_DIR comes from the installer's config.mk.
|
|
LIBXMP_SRC := $(filter-out %/win32.c, $(wildcard $(LIBXMP_DIR)/src/*.c) $(wildcard $(LIBXMP_DIR)/src/loaders/*.c))
|
|
LIBXMP_OBJDIR := $(BUILD)/obj/libxmp-lite
|
|
LIBXMP_OBJS := $(patsubst $(LIBXMP_DIR)/src/%.c,$(LIBXMP_OBJDIR)/%.o,$(LIBXMP_SRC))
|
|
LIBXMP_AR := $(LIBDIR)/libxmplite.a
|
|
LIBXMP_CFLAGS := -DLIBXMP_CORE_PLAYER -DLIBXMP_CORE_DISABLE_IT -DHAVE_FNMATCH=0 \
|
|
-I$(LIBXMP_DIR)/include -I$(LIBXMP_DIR)/include/libxmp-lite \
|
|
-I$(LIBXMP_DIR)/src -Wno-error -w
|
|
|
|
$(LIBXMP_OBJDIR)/%.o: $(LIBXMP_DIR)/src/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(COMMON_CFLAGS) -m68000 -fomit-frame-pointer $(LIBXMP_CFLAGS) -c $< -o $@
|
|
|
|
$(LIBXMP_AR): $(LIBXMP_OBJS)
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_AR) rcs $@ $(LIBXMP_OBJS)
|
|
|
|
LIB := $(LIBDIR)/libjoey.a
|
|
|
|
# Every example but Space Taxi is its sources plus the library, linked by the
|
|
# one rule below. Worth knowing which ones the gates use:
|
|
# PATTERN the SCB acceptance vehicle: 8 bands of 25 lines with 8 gradient
|
|
# palettes, so a misplaced band boundary is immediately visible.
|
|
# UBER the golden-hash vehicle: every public op, a hash per op, which
|
|
# tools/diff-uber-hashes compares against the IIgs reference.
|
|
# AUDIO both audio paths: JYM1 chip music on the OPM, MOD/SFX on ADPCM.
|
|
# KEYS the input and mouse vehicle: key predicates, the typed line
|
|
# (jlInputGetChar) and its verification row.
|
|
# SERIAL the RS-232C gate's echo program.
|
|
# SERMOUSE the serial + mouse gate's program: streams both ways on the
|
|
# RS-232C port (SCC channel A) while the mouse (channel B) moves.
|
|
# TILEBANK the tile-bank gate's program: this port's .tbk bake loaded both
|
|
# ways and pixel-checked, every other target's bake refused.
|
|
HELLO_SRC := $(EXAMPLES)/hello/hello.c
|
|
PATTERN_SRC := $(EXAMPLES)/pattern/pattern.c
|
|
DRAW_SRC := $(EXAMPLES)/draw/draw.c
|
|
KEYS_SRC := $(EXAMPLES)/keys/keys.c
|
|
SERIAL_SRC := $(EXAMPLES)/serial/serial.c
|
|
SERTEST_SRC := $(EXAMPLES)/sertest/sertest.c
|
|
SERMOUSE_SRC := $(EXAMPLES)/sermouse/sermouse.c
|
|
SAVE_SRC := $(EXAMPLES)/save/save.c
|
|
TILEBANK_SRC := $(EXAMPLES)/tilebank/tilebank.c
|
|
JOY_SRC := $(EXAMPLES)/joy/joy.c
|
|
SPRITE_SRC := $(EXAMPLES)/sprite/sprite.c
|
|
AUDIO_SRC := $(EXAMPLES)/audio/audio.c
|
|
UBER_SRC := $(EXAMPLES)/uber/uber.c
|
|
ADV_SRC := $(EXAMPLES)/adventure/adventure.c
|
|
ADV2_SRC := $(EXAMPLES)/adventure2/adventure2.c
|
|
AGI_SRC := $(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
|
|
EXAMPLES_X := HELLO PATTERN DRAW KEYS SERIAL SERTEST SERMOUSE SAVE TILEBANK JOY SPRITE AUDIO UBER ADV ADV2 AGI
|
|
EXAMPLE_BINS := $(foreach e,$(EXAMPLES_X),$(BINDIR)/$(e).X)
|
|
|
|
# AUDIO loads DATA/test.mod and DATA/test.sfx from beside the program.
|
|
DATA_DIR := $(BINDIR)/DATA
|
|
DATA_FILES := $(DATA_DIR)/test.mod $(DATA_DIR)/test.sfx
|
|
# TILEBANK's DATA/tilebank: this port's bake of the tile-bank fixture, the
|
|
# other targets' bakes it must refuse, and the expected pixels (common.mk).
|
|
TILEBANK_DATA := $(DATA_DIR)/tilebank/own.tbk
|
|
|
|
# Space Taxi ships in its own folder with its DATA, as on the other ports,
|
|
# so its megabyte of data never rides onto every other program's floppy.
|
|
STAXI_DIR := $(BINDIR)/STAXI
|
|
STAXI_BIN := $(STAXI_DIR)/STAXI.X
|
|
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
|
|
|
|
.PHONY: all x68000 x68000-lib x68000-examples x68000-verify-serial x68000-verify-mouse x68000-verify-serial-mouse x68000-verify-tilebank x68000-verify-golden clean-x68000 clean
|
|
|
|
all x68000: x68000-lib x68000-examples
|
|
|
|
x68000-lib: $(LIB) $(LIBXMP_AR)
|
|
|
|
x68000-examples: $(EXAMPLE_BINS) $(STAXI_BIN) $(DATA_FILES) $(TILEBANK_DATA)
|
|
|
|
$(BUILD)/obj/core/%.o: $(SRC_CORE)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -c $< -o $@
|
|
|
|
# Port-local asm. Same object dir as the port C objects; make picks between the
|
|
# two pattern rules by which prerequisite exists.
|
|
$(BUILD)/obj/port/%.o: $(SRC_DIR)/x68000/%.s
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/68k/%.o: $(SRC_68K)/%.s
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/68k/%.o: $(SRC_68K)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/codegen/%.o: $(CODEGEN_DIR)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@
|
|
|
|
$(BUILD)/obj/port/%.o: $(SRC_DIR)/x68000/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(LIB): $(LIB_OBJS)
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_AR) rcs $@ $(LIB_OBJS)
|
|
|
|
.SECONDEXPANSION:
|
|
$(EXAMPLE_BINS): $(BINDIR)/%.X: $$($$*_SRC) $(LIB) $(LIBXMP_AR)
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) $($*_SRC) $(LIB) $(LIBXMP_AR) $(LDFLAGS) -o $@
|
|
|
|
$(DATA_DIR)/%: $(REPO_DIR)/assets/%
|
|
@mkdir -p $(dir $@)
|
|
cp $< $@
|
|
|
|
$(TILEBANK_DATA): $(TILEBANK_BAKE_DEPS)
|
|
python3 $(TILEBANK_STAGE) $(PLATFORM) $(TILEBANK_PNG) $(dir $@)
|
|
|
|
# Space Taxi asset variables (the rules follow the binary below); make
|
|
# expands prerequisites when it reads the rule, so these come first.
|
|
STAXI_GEN_DIR := $(EXAMPLES)/spacetaxi/generated/x68000
|
|
STAXI_RUN_DIR := $(STAXI_DIR)/DATA
|
|
STAXI_LEVEL_GEN := $(foreach n,$(STAXI_LEVEL_NUMS),$(STAXI_GEN_DIR)/levels/level$(n).dat) \
|
|
$(STAXI_GEN_DIR)/levels/title.dat
|
|
STAXI_LEVEL_RUN := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXI_LEVEL_GEN))
|
|
SPRITEBAKE_BIN := $(REPO_DIR)/build/tools/spritebake-x68000
|
|
STAXIBAKE_BIN := $(REPO_DIR)/build/tools/staxibake
|
|
STAXICELS_SPR_GEN := $(STAXI_GEN_DIR)/sprites/staxicels.spr
|
|
STAXICELS_SPC_GEN := $(STAXICELS_SPR_GEN:.spr=.spc)
|
|
STAXICELS_SPC_RUN := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXICELS_SPC_GEN))
|
|
STAXI_ASSET_DSTS := $(STAXI_LEVEL_RUN) $(STAXICELS_SPC_RUN)
|
|
|
|
# Per-level hook-sprite banks: the cels stLevelCelList names for each
|
|
# level that has hook sprites, baked from its level file and pre-compiled
|
|
# for this target, so no cel is JIT-compiled mid-ride. Levels without
|
|
# hook sprites have no bank; the game JIT-compiles at level entry when a
|
|
# bank is missing.
|
|
# ...except on the X68000, where they do not fit. The Human68k floppy is
|
|
# 1232 KB and these eight banks are 787 KB of it (level09 alone is 236 KB,
|
|
# level10 175, level17 165), which with the 296 KB binary, the levels and
|
|
# the speech put the disk about 300 KB over however small speech gets.
|
|
# stRenderLevelCels already handles their absence the right way: it builds
|
|
# and compiles the level's cels at ENTRY, behind the LOADING bar, so the
|
|
# ride itself still never compiles. That is also what spacetaxi.c's
|
|
# codegen-arena comment says the 68k ports are meant to do -- their cels
|
|
# are big and their JIT is fast. Set STAXI_CEL_LEVELS to the list above to
|
|
# ship them again if the payload ever moves to a hard disk image.
|
|
STAXI_CEL_LEVELS :=
|
|
STAXILEVEL_SPR_GEN := $(foreach n,$(STAXI_CEL_LEVELS),$(STAXI_GEN_DIR)/sprites/level$(n).spr)
|
|
STAXILEVEL_SPC_GEN := $(STAXILEVEL_SPR_GEN:.spr=.spc)
|
|
STAXILEVEL_SPC_RUN := $(patsubst $(STAXI_GEN_DIR)/%,$(STAXI_RUN_DIR)/%,$(STAXILEVEL_SPC_GEN))
|
|
STAXI_ASSET_DSTS += $(STAXILEVEL_SPC_RUN)
|
|
|
|
# Speech baked to sample bytes per passenger pitch (assets/genSpeechPcm.py):
|
|
# expanding bits at play time is what keeps "HEY TAXI" from stalling the
|
|
# ride; the C64 run-length source stays in stSpeechData.c as the input.
|
|
STAXI_SPEECH_GEN := $(STAXI_GEN_DIR)/speech.bin
|
|
STAXI_SPEECH_RUN := $(STAXI_RUN_DIR)/speech.bin
|
|
STAXI_ASSET_DSTS += $(STAXI_SPEECH_RUN)
|
|
$(STAXI_SPEECH_GEN): $(EXAMPLES)/spacetaxi/stSpeechData.c $(EXAMPLES)/spacetaxi/assets/genSpeechPcm.py
|
|
@mkdir -p $(dir $@)
|
|
# --single: one polarity, 60 KB instead of 120 KB. The 1232 KB
|
|
# Human68k floppy cannot hold the two-polarity file alongside the
|
|
# binary and the levels -- it came up 18 KB short -- and the player
|
|
# negates the samples itself when the running polarity is odd.
|
|
python3 $(EXAMPLES)/spacetaxi/assets/genSpeechPcm.py $< $@ --single
|
|
$(STAXI_SPEECH_RUN): $(STAXI_SPEECH_GEN)
|
|
@mkdir -p $(dir $@)
|
|
cp $< $@
|
|
|
|
# Space Taxi. -s (strip) because the image it ships on is a 1232 KB
|
|
# Human68k floppy: the unstripped binary is most of the volume on its
|
|
# own. The DATA tree next to it (levels + the precompiled cel bank) is
|
|
# what joey-run copies onto the data floppy.
|
|
$(STAXI_BIN): $(STAXI_SRCS) $(LIB) $(LIBXMP_AR) $(call staxiData,$(STAXI_ASSET_DSTS))
|
|
@mkdir -p $(dir $@)
|
|
$(X68K_CC) $(CFLAGS) -s -I$(EXAMPLES)/spacetaxi $(STAXI_SRCS) $(LIB) $(LIBXMP_AR) $(LDFLAGS) -o $@
|
|
|
|
# Space Taxi asset staging, the amiga.mk pattern cut down to what this
|
|
# port loads at run time: the 24 levels + title extracted from the C64
|
|
# dump, and the cel bank baked by staxibake and pre-compiled for THIS
|
|
# target by spritebake-x68000 (the planar 68k emitter under target byte
|
|
# 5, so an Amiga or DOS bank is refused by the loader). Tiles and the
|
|
# font come from the C64 data in stC64Data.c, so no .tbk is staged.
|
|
.SECONDARY: $(STAXI_LEVEL_GEN) $(STAXICELS_SPR_GEN) $(STAXICELS_SPC_GEN) $(STAXILEVEL_SPR_GEN) $(STAXILEVEL_SPC_GEN)
|
|
|
|
$(STAXI_LEVEL_GEN) &: $(STAXI_RAW_DUMP) $(ROMTOLEVEL_BIN)
|
|
@mkdir -p $(STAXI_GEN_DIR)/levels
|
|
python3 $(ROMTOLEVEL_BIN) $(STAXI_RAW_DUMP) $(STAXI_GEN_DIR)/levels
|
|
|
|
$(SPRITEBAKE_BIN):
|
|
$(MAKE) -f $(REPO_DIR)/make/tools.mk spritebake-x68000
|
|
|
|
$(STAXIBAKE_BIN):
|
|
$(MAKE) -f $(REPO_DIR)/make/tools.mk staxibake
|
|
|
|
$(STAXICELS_SPR_GEN): $(STAXIBAKE_BIN) $(EXAMPLES)/spacetaxi/stCels.c $(EXAMPLES)/spacetaxi/stC64Data.c
|
|
@mkdir -p $(dir $@)
|
|
$(STAXIBAKE_BIN) $@
|
|
|
|
$(STAXI_GEN_DIR)/sprites/%.spc: $(STAXI_GEN_DIR)/sprites/%.spr $(SPRITEBAKE_BIN)
|
|
$(SPRITEBAKE_BIN) $< $@
|
|
|
|
$(STAXI_RUN_DIR)/levels/%.dat: $(STAXI_GEN_DIR)/levels/%.dat
|
|
@mkdir -p $(dir $@)
|
|
cp $< $@
|
|
|
|
$(STAXI_RUN_DIR)/sprites/%.spc: $(STAXI_GEN_DIR)/sprites/%.spc
|
|
@mkdir -p $(dir $@)
|
|
cp $< $@
|
|
|
|
# Both-directions RS-232C gate (~1 min).
|
|
x68000-verify-serial: $(BINDIR)/SERIAL.X
|
|
$(REPO_DIR)/scripts/verify-x68000-serial.sh
|
|
|
|
# Mouse gate: injected MAME mouse packets through the IOCS ROM into
|
|
# jlMouse* state, read back from KEYS.X's verification scanline.
|
|
x68000-verify-mouse: $(BINDIR)/KEYS.X
|
|
$(REPO_DIR)/scripts/verify-x68000-mouse.sh
|
|
|
|
# Serial + mouse together: both share the SCC, so stream both ways on the
|
|
# RS-232C port while the mouse moves, and check neither disturbs the other.
|
|
x68000-verify-serial-mouse: $(BINDIR)/SERMOUSE.X
|
|
$(REPO_DIR)/scripts/verify-x68000-serial-mouse.sh
|
|
|
|
# Tile-bank gate: this port's own .tbk bake loaded both ways must hash like
|
|
# the host gate's, and every other target's bake must be refused (~1 min).
|
|
x68000-verify-tilebank: $(BINDIR)/TILEBANK.X $(TILEBANK_DATA)
|
|
$(REPO_DIR)/scripts/verify-x68000-tilebank.sh
|
|
|
|
# Golden-hash gate against the Apple IIgs reference (~70 min: UBER on the
|
|
# generic renderer is slow and must reach jlLogFlush before hashes exist).
|
|
x68000-verify-golden: $(LIB) $(LIBXMP_AR)
|
|
$(REPO_DIR)/scripts/verify-x68000-golden.sh
|
|
|
|
clean-x68000:
|
|
rm -rf $(BUILD)
|
|
|
|
# `clean` as an alias for `clean-x68000`. Without it a bare
|
|
# `make -f make/x68000.mk clean` FAILS -- and with stderr discarded that
|
|
# looks like success while leaving stale objects the next build links.
|
|
clean: clean-x68000
|
|
|
|
-include $(shell find $(BUILD) -name '*.d' 2>/dev/null)
|
|
|
|
# Shorter stem than the %.spr-from-%.png pattern, so it wins for level banks.
|
|
$(STAXI_GEN_DIR)/sprites/level%.spr: $(STAXI_GEN_DIR)/levels/level%.dat $(STAXIBAKE_BIN) $(EXAMPLES)/spacetaxi/stLevelCels.c
|
|
@mkdir -p $(dir $@)
|
|
$(STAXIBAKE_BIN) --level $< $@
|