spacetaxi/program.mk
2026-10-05 18:50:09 -05:00

145 lines
7.5 KiB
Makefile

# Space Taxi, described for JoeyLib's make/programs.mk (which lists what each
# variable means): its sources, how it ships on each port, and how its DATA
# is baked. Included by the Makefile beside it, on JoeyLib's make/project.mk.
STAXI_HOME := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
# The levels are extracted from a memory image of the original C64 game,
# which is not part of the repository (scripts/importData.sh installs it as
# stuff/raw.bin; STAXI_RAW_DUMP=FILE names another); without it the game
# still builds, and only the levels and the per-level sprite banks made from
# them are left out.
STAXI_RAW_DUMP ?= $(STAXI_HOME)/stuff/raw.bin
PROGRAMS += STAXI
STAXI_SRCS := $(addprefix $(STAXI_HOME)/,spacetaxi.c stLevel.c stLevelFile.c stRender.c stSim.c stFare.c stHooks.c stTitle.c stC64Data.c stCels.c stAudio.c stLevelCels.c)
# The IIgs links in an order of its own, the one its images were measured in.
STAXI_IIGS_SRCS := $(addprefix $(STAXI_HOME)/,stC64Data.c stCels.c stSim.c spacetaxi.c stLevel.c stLevelFile.c stRender.c stFare.c stHooks.c stTitle.c stAudio.c stLevelCels.c)
# In a folder of its own with its DATA, so its megabyte of data never rides
# onto every other program's disk.
STAXI_FOLDER := yes
STAXI_AMIGA_NAME := Taxi
STAXI_TITLE := Space Taxi
STAXI_HELP := Space Taxi: fly the taxi, pick up the fares, take them where they ask to go.
# IIgs: large overflow segments. 26 bank-aligned segments starved the Memory
# Manager, so NTP's 34K NewHandle failed and the IIgs build ran SILENT
# (gNTPReady stayed 0). Freeing that memory lets audio initialise; the
# latent crash that then surfaced is fixed in src/iigs/audio_full.c
# (sfxTrigger now requires a running replayer).
STAXI_IIGS_OVERFLOW_CAP := 0xF000
STAXI_IIGS_GAME_DISK := yes
# X68000: stripped, because the image it ships on is a 1232 KB Human68k
# floppy and the unstripped binary is most of the volume on its own.
STAXI_X68000_LDFLAGS := -s
# ---- DATA ---------------------------------------------------------------------
# Each bake is made in STAXI_GEN (per target; safe to delete, the next build
# recreates it), then what the game loads is copied into its DATA: the
# levels, the cel bank, the per-level cel banks and the speech. Tiles and the
# font come from the C64 data compiled into the binary (stC64Data.c).
STAXI_GEN := $(PROJECT_BUILD)/generated/$(ASSET_PLATFORM)
STAXI_RUN := $(call programDataDir,STAXI)
STAXI_OPT := $(call programOptionalDir,STAXI)
# 24 lettered levels (A..X) from scenes 0..23 plus the title from scene 24,
# extracted by assets/romToLevel.py, which runs the captured decompressor
# through a Python 6502 emulator over the raw RAM dump and writes STL2 .dat
# files directly. (mkstlevel + title.txt is no longer used: the C64 title
# encodes its screen with the game's custom charset, so a hand-authored tile
# layout with a different glyph mapping renders as garbage.)
STAXI_LEVEL_NUMS := 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
STAXI_LEVELS := $(foreach n,$(STAXI_LEVEL_NUMS),levels/level$(n).dat) levels/title.dat
ROMTOLEVEL := $(STAXI_HOME)/assets/romToLevel.py
# 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, and a missing bank only makes the game compile that level's
# cels at entry -- so they are optional data, which the IIgs data disk packs
# last, while there is room.
# ...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. Ship them there again if the payload ever
# moves to a hard disk image.
STAXI_CEL_LEVELS := $(if $(filter x68000,$(PLATFORM)),,07 08 09 10 12 16 17 21)
# The C64-exact cel bank, generated by staxibake (from the shared cel table
# stCels.c + C64 bitmaps) and compiled for this target by the host
# spritebake, so the game loads its cels already compiled
# (jlSpriteBankLoadPrecompiled) instead of JIT-compiling them at boot. The ST
# is the one port whose .spc carries a reloc list (the shifted-DRAW thunk's
# jmp to stSpriteDrawShiftWalker), re-stamped by the loader.
STAXIBAKE := $(PROJECT_BUILD)/tools/staxibake
STAXIBAKE_SRCS := $(STAXI_HOME)/tools/staxibake/staxibake.c $(addprefix $(STAXI_HOME)/,stCels.c stC64Data.c stLevelCels.c stLevelFile.c)
# Speech baked to sample bytes per passenger pitch (assets/genSpeechPcm.py):
# baking them here instead of 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.
# --single one polarity, 60 KB instead of 120 KB; the player negates the
# samples itself when the running polarity is odd. Measured on a
# stock 1 MB ST the two-polarity file cannot be allocated at all
# ("speech alloc FAILED (120828 bytes)": the whole game mute),
# and the X68000's 1232 KB floppy came up 18 KB short of it.
# --biased unsigned samples, as the IIgs DOC plays them.
STAXI_SPEECH_FLAGS_atarist := --single
STAXI_SPEECH_FLAGS_x68000 := --single
STAXI_SPEECH_FLAGS_iigs := --biased
STAXI_DATA := $(STAXI_RUN)/sprites/staxicels.spc $(STAXI_RUN)/speech.bin
ifneq ($(wildcard $(STAXI_RAW_DUMP)),)
STAXI_DATA += $(addprefix $(STAXI_RUN)/,$(STAXI_LEVELS)) $(foreach n,$(STAXI_CEL_LEVELS),$(STAXI_OPT)/sprites/level$(n).spc)
else
STAXI_DATA += staxi-no-levels
endif
.PHONY: staxi-no-levels
staxi-no-levels:
@echo "note: Space Taxi levels skipped: $(STAXI_RAW_DUMP) is not present"
# The bakes are kept: they are what the DATA copies come from.
.SECONDARY: $(addprefix $(STAXI_GEN)/,$(STAXI_LEVELS) sprites/staxicels.spr sprites/staxicels.spc speech.bin) \
$(foreach n,$(STAXI_CEL_LEVELS),$(STAXI_GEN)/sprites/level$(n).spr $(STAXI_GEN)/sprites/level$(n).spc)
# Every level and the title in one run of the extractor: a grouped target
# (&:, GNU Make 4.3+) runs its recipe once for the whole list.
$(addprefix $(STAXI_GEN)/,$(STAXI_LEVELS)) &: $(STAXI_RAW_DUMP) $(ROMTOLEVEL)
@mkdir -p $(STAXI_GEN)/levels
python3 $(ROMTOLEVEL) $(STAXI_RAW_DUMP) $(STAXI_GEN)/levels
$(STAXI_GEN)/sprites/staxicels.spr: $(STAXIBAKE) $(STAXI_HOME)/stCels.c $(STAXI_HOME)/stC64Data.c
@mkdir -p $(dir $@)
$(STAXIBAKE) $@
$(STAXI_GEN)/sprites/level%.spr: $(STAXI_GEN)/levels/level%.dat $(STAXIBAKE) $(STAXI_HOME)/stLevelCels.c
@mkdir -p $(dir $@)
$(STAXIBAKE) --level $< $@
$(STAXI_GEN)/sprites/%.spc: $(STAXI_GEN)/sprites/%.spr $(SPRITEBAKE)
@mkdir -p $(dir $@)
$(SPRITEBAKE) $< $@
$(STAXI_GEN)/speech.bin: $(STAXI_HOME)/stSpeechData.c $(STAXI_HOME)/assets/genSpeechPcm.py
@mkdir -p $(dir $@)
python3 $(STAXI_HOME)/assets/genSpeechPcm.py $< $@ $(STAXI_SPEECH_FLAGS_$(ASSET_PLATFORM))
$(STAXI_RUN)/%: $(STAXI_GEN)/%
@mkdir -p $(dir $@)
cp $< $@
ifneq ($(STAXI_OPT),$(STAXI_RUN))
$(STAXI_OPT)/%: $(STAXI_GEN)/%
@mkdir -p $(dir $@)
cp $< $@
endif
# A plain host tool: the .spr it writes is the same for every target.
$(STAXIBAKE): $(STAXIBAKE_SRCS)
@mkdir -p $(dir $@)
$(HOST_CC) $(HOST_CFLAGS) -I$(STAXI_HOME) $^ -o $@