503 lines
22 KiB
Text
503 lines
22 KiB
Text
== Building Your Program
|
|
|
|
JoeyLib does not install as a system library: each target needs its own cross
|
|
compiler, link step, packaging, and disk image; JoeyLib's makefiles own all
|
|
of that. Your program lives in a directory of its own -- its own repository,
|
|
usually -- next to a JoeyLib checkout. Its Makefile describes the program and
|
|
includes two of JoeyLib's makefiles, and that is enough to build it for every
|
|
target with exactly the flags, link order, and packaging JoeyLib's own examples
|
|
get. JoeyLib's examples are described the same way and built by the same
|
|
rules; there is one set of them.
|
|
|
|
=== A Project
|
|
|
|
----
|
|
games/
|
|
joeylib/ a JoeyLib checkout, set up with ./install.sh
|
|
mygame/
|
|
Makefile
|
|
mygame.c
|
|
world.c
|
|
assets/
|
|
tiles.png
|
|
----
|
|
|
|
The whole Makefile for a program with no data files:
|
|
|
|
[source,makefile]
|
|
----
|
|
JOEYLIB ?= ../joeylib
|
|
include $(JOEYLIB)/make/project.mk
|
|
|
|
DVX_VENDOR := acme
|
|
DVX_AUTHOR := Acme Games
|
|
MACOS_ID_PREFIX := com.example.acme
|
|
|
|
PROGRAMS := MYGAME
|
|
MYGAME_SRCS := mygame.c world.c
|
|
MYGAME_TITLE := My Game
|
|
MYGAME_HELP := One line on what it is, for its DVX help file.
|
|
|
|
include $(JOEYLIB)/make/programs.mk
|
|
----
|
|
|
|
`make/project.mk` comes first and sets up the target being built; the
|
|
description comes next and may use what it set up (see <<_data_files>>);
|
|
`make/programs.mk` comes last and makes the rules.
|
|
|
|
The first three lines say whose the programs are, which only you can say:
|
|
JoeyLib never makes it up, and building for DVX or macOS stops until they
|
|
are set. `DVX_VENDOR` is the folder your programs install in under DVX's
|
|
`APPS\` (1 to 8 letters, digits, or `_`; DVX names a package `vendor.name`)
|
|
and `DVX_AUTHOR` the author DVX shows; `MACOS_ID_PREFIX`, a reverse-DNS name
|
|
of yours, starts each Mac app's identifier, which ends in the program's name
|
|
(`com.example.acme.MYGAME`). JoeyLib's own examples carry their author's
|
|
(`kpunch`, `com.kangaroopunch.joeylib`). Run make in the project's
|
|
directory -- the paths in the Makefile are relative to it -- or with `make -C`:
|
|
|
|
[source,console]
|
|
----
|
|
$ make # every target whose toolchain is installed
|
|
$ make dos # one target: iigs amiga atarist ste dos x68000 dvx
|
|
$ make clean # the project's build/ (clean-dos: one target's)
|
|
$ make help
|
|
----
|
|
|
|
A target without its toolchain is skipped with a note. `JOEYLIB=PATH` on the
|
|
command line points at a checkout somewhere else.
|
|
|
|
==== Where things go
|
|
|
|
The project's outputs land in its own `build/`, laid out like JoeyLib's:
|
|
|
|
[cols="1,4", options="header"]
|
|
|===
|
|
|Target |Output
|
|
|
|
|Apple IIgs |`build/iigs/bin/MYGAME` (an S16 OMF), its data staged in
|
|
`build/iigs/data/MYGAME/`, its Finder icon in `build/iigs/icon/MYGAME/`, and
|
|
with `MYGAME_IIGS_GAME_DISK` the disks `build/iigs/bin/MYGAME.2mg` and
|
|
`MYGAME-data.2mg`
|
|
|Amiga |`build/amiga/bin/Mygame` and its Workbench icon, `Mygame.info`
|
|
|Atari ST |`build/atarist/bin/MYGAME.PRG`, which runs on every ST
|
|
|Atari STe |`build/ste/bin/MYGAME.PRG`, the STe build: STe and Mega STe only
|
|
(<<_the_atari_st_family>>); same toolchain and baked data as the ST
|
|
|MS-DOS |`build/dos/bin/MYGAME.EXE`, with the DPMI server built in
|
|
|Sharp X68000 |`build/x68000/bin/MYGAME.X`
|
|
|DVX |`build/dvx/bin/apps/acme/mygame/`: `mygame.app`, `mygame.hlp`, and its
|
|
`DATA/`
|
|
|SDL3 |`build/sdl3/bin/MYGAME`, a native program with SDL 3 linked in
|
|
|Web |`build/web/bin/MYGAME/`: `MYGAME.html`, `.js`, `.wasm`, and `.data`
|
|
(its `DATA/`, packed in), and `icon.png`
|
|
|macOS |`build/macos/bin/MYGAME.app`, a universal app: the program in
|
|
`Contents/MacOS/`, its `DATA/` and icon in `Contents/Resources/`; the program
|
|
it is packed from in `build/macos/link/MYGAME`
|
|
|Win32 |`build/win32/bin/MYGAME.EXE`, a 32-bit Windows program
|
|
|Win16 |`build/win16/bin/MYGAME.EXE`, a Windows 3.x program
|
|
|PSP |`build/psp/bin/MYGAME/`: `EBOOT.PBP` and its `DATA/`, a folder for the
|
|
memory stick's `PSP/GAME/`; the ELF it is packed from in
|
|
`build/psp/elf/MYGAME.elf`
|
|
|===
|
|
|
|
A program with `MYGAME_FOLDER` set ships in a folder of its own with its
|
|
`DATA/` beside it (`build/dos/bin/MYGAME/MYGAME.EXE`); otherwise programs share
|
|
`bin/DATA/`. A program's icon (<<_icons>>) is baked in
|
|
`build/<target>/icon/MYGAME/` on its way into the program.
|
|
|
|
JoeyLib's library for each target, and the host tools such as `spritebake`, are
|
|
built on demand where JoeyLib keeps them, in the checkout's `build/`, and shared
|
|
with JoeyLib's own build and every other project: the first project to need
|
|
the DOS library builds it, the rest reuse it. That is the only thing a project
|
|
writes into the JoeyLib checkout. To keep even that out, give it another place:
|
|
|
|
[source,console]
|
|
----
|
|
$ make JOEY_BUILD=$PWD/build/joeylib
|
|
----
|
|
|
|
`PROJECT_BUILD=DIR` likewise moves the project's own `build/`. Both belong on
|
|
the command line (or before the `include` of `make/project.mk`).
|
|
|
|
[NOTE]
|
|
====
|
|
How it works: every target has its own compiler and its own make variables, so
|
|
one make cannot hold two of them. `make` in a project only reads the
|
|
description, then runs the same Makefile again once per target with
|
|
`JOEY_PORT` set, and in that run `make/project.mk` includes the target's
|
|
makefile, `make/<target>.mk`. That makefile holds JoeyLib's library rules and
|
|
`programRules`, the target's rules for one program, which `make/programs.mk`
|
|
makes for every program. So any target of one port can be built directly:
|
|
`make JOEY_PORT=dos build/dos/bin/MYGAME.EXE`, and `make iigs-game-disk` is
|
|
passed to the IIgs run for you.
|
|
====
|
|
|
|
=== Describing a Program
|
|
|
|
A program is a set of variables named after its id: an upper-case name of up
|
|
to eight letters and digits, which is also its file name unless `_NAME` says
|
|
otherwise. `PROGRAMS` lists the ids. A project may describe several programs.
|
|
|
|
[cols="2,5", options="header"]
|
|
|===
|
|
|Variable |Meaning
|
|
|
|
|`PROGRAMS` |The ids that `make` builds.
|
|
|`TEST_PROGRAMS` |Ids with rules that are built only when asked for (test
|
|
probes for gates).
|
|
|`ID_SRCS` |Its C sources, in link order.
|
|
|`ID_CFLAGS` |Extra compiler flags: `-I` folders, `-D` defines.
|
|
|`ID_LDFLAGS` |Extra link flags (`-s` to strip).
|
|
|`ID_PORTS` |The targets it builds for. Every target when unset.
|
|
|`ID_NAME` |Its file name without the extension (see <<_naming>>).
|
|
|`ID_FOLDER` |Set: it ships in a folder of its own with its `DATA/` (Amiga,
|
|
ST, DOS, X68000, SDL3, Win32, Win16; on the IIgs, DVX, the web, macOS, and
|
|
the PSP every program is packaged apart anyway).
|
|
|`ID_BINDIR` |Build it there instead of `bin/`.
|
|
|`ID_DATA` |Its data files (<<_data_files>>).
|
|
|`ID_TITLE` |DVX: its window title. PSP: its title in the PSP's menu.
|
|
macOS: its app's display name (`CFBundleDisplayName`). By default its name.
|
|
|`ID_ICON` |Its icon: a picture (a PNG, best square, transparent around the
|
|
figure), baked for every target whose system shows programs by an icon
|
|
(<<_icons>>). JoeyLib's kangaroo by default.
|
|
|`ID_HELP` |DVX: the line its help file says about it.
|
|
|`ID_IIGS_OVERFLOW_CAP` |IIgs: link large overflow segments (`0xF000`), which
|
|
a big program needs to leave the Memory Manager room (see
|
|
`make/support/iigs/clang-build.sh`).
|
|
|`ID_IIGS_GAME_DISK` |IIgs: set: `make` also builds its bootable volume.
|
|
|===
|
|
|
|
Any variable can be given for one target only as `ID_<TARGET>_<VAR>`, which
|
|
wins there even when empty:
|
|
|
|
[source,makefile]
|
|
----
|
|
MYGAME_AMIGA_NAME := MyGame
|
|
MYGAME_X68000_LDFLAGS := -s
|
|
MYGAME_IIGS_DATA := # nothing staged on the IIgs
|
|
----
|
|
|
|
DVX's help and resource texts call a program "a `$(DVX_KIND)` program"
|
|
(`JoeyLib` by default) and name `$(DVX_AUTHOR)` as its author; `DVX_VENDOR`
|
|
is the folder it installs in under `APPS\` (<<_a_project>>). Set them in the
|
|
description.
|
|
|
|
=== Data Files
|
|
|
|
A program opens its files through `DATA/` (`jlDataOpen`), and its Makefile
|
|
puts them there. `ID_DATA` lists the staged files, and the project writes the
|
|
rules that make them, below its description, using what `make/project.mk`
|
|
set up:
|
|
|
|
[cols="2,5", options="header"]
|
|
|===
|
|
|Name |Meaning
|
|
|
|
|`$(call programDataDir,ID)` |Where its `DATA/` files go on this target.
|
|
|`$(call programOptionalDir,ID)` |Where the files go that it can run without
|
|
(<<_disk_images_and_packaging>>).
|
|
|`PLATFORM` |The target: `iigs`, `amiga`, `atarist`, `ste`, `dos`, `x68000`, `dvx`, `sdl3`, `web`, `macos`, `win32`, `win16`, `psp`, `haiku`, `haiku32`, `beos`.
|
|
|`ASSET_PLATFORM` |The target its bakes are for. DVX shows the DOS stage and
|
|
runs x86 code, so it takes the DOS bakes; the hosted ports' stage (SDL3, the
|
|
web, macOS, Win32, Win16, the PSP, Haiku, BeOS) is the same chunky one, so they take
|
|
them too: Win16 runs a pre-compiled sprite bank's x86 code as DVX does, and
|
|
the others take its cels without their code. The STe build takes the ST's.
|
|
|`SPRITEBAKE` |The host `spritebake` for this target (its rule is
|
|
JoeyLib's).
|
|
|`PROJECT_DIR`, `PROJECT_BUILD` |The project and its `build/`.
|
|
|`REPO_DIR` |The JoeyLib checkout, for its tools: `$(REPO_DIR)/tools/assetbake/assetbake.py`.
|
|
|`HOST_CC`, `HOST_CFLAGS` |For a host tool of the project's own.
|
|
|===
|
|
|
|
A copy, a tile-bank bake, and a pre-compiled sprite bank:
|
|
|
|
[source,makefile]
|
|
----
|
|
MYGAME_RUN := $(call programDataDir,MYGAME)
|
|
MYGAME_GEN := $(PROJECT_BUILD)/generated/$(ASSET_PLATFORM)
|
|
MYGAME_DATA := $(MYGAME_RUN)/theme.jym $(MYGAME_RUN)/tiles.tbk $(MYGAME_RUN)/player.spc
|
|
|
|
$(MYGAME_RUN)/theme.jym: assets/theme.jym
|
|
@mkdir -p $(dir $@)
|
|
cp $< $@
|
|
|
|
$(MYGAME_RUN)/tiles.tbk: assets/tiles.png
|
|
@mkdir -p $(dir $@)
|
|
python3 $(REPO_DIR)/tools/assetbake/assetbake.py --type tile --target $(ASSET_PLATFORM) $< $@
|
|
|
|
$(MYGAME_GEN)/player.spr: assets/player.png
|
|
@mkdir -p $(dir $@)
|
|
python3 $(REPO_DIR)/tools/assetbake/assetbake.py --type sprite --cell 16x16 $< $@
|
|
|
|
$(MYGAME_RUN)/player.spc: $(MYGAME_GEN)/player.spr $(SPRITEBAKE)
|
|
@mkdir -p $(dir $@)
|
|
$(SPRITEBAKE) $< $@
|
|
----
|
|
|
|
One rule serves every target: tile banks and `.spc` files differ per target,
|
|
and `ASSET_PLATFORM` and `SPRITEBAKE` say which. The Assets chapter
|
|
(<<_creating_assets>>) covers the formats and tools.
|
|
|
|
=== Naming
|
|
|
|
File naming conventions differ per platform, and the rules apply them to the
|
|
program's id:
|
|
|
|
[cols="2,2,4", options="header"]
|
|
|===
|
|
|Platform |Convention |Example
|
|
|
|
|Apple IIgs |Uppercase, 8 characters |`MYGAME`
|
|
|Atari ST |Uppercase 8.3, `.PRG` |`MYGAME.PRG`
|
|
|MS-DOS |Uppercase 8.3, `.EXE` |`MYGAME.EXE`
|
|
|Amiga |Mixed case, no extension: the id Capitalised unless `ID_AMIGA_NAME`
|
|
says otherwise |`Mygame`
|
|
|Sharp X68000 |Uppercase 8.3, `.X` |`MYGAME.X`
|
|
|DVX |Lowercase, 8 characters, a folder of its own |`apps/acme/mygame/mygame.app`
|
|
|SDL3 |The id, no extension |`MYGAME`
|
|
|Web |The id, a folder of its own |`MYGAME/MYGAME.html`
|
|
|macOS |The id, an app |`MYGAME.app`
|
|
|Win32 |Uppercase 8.3, `.EXE` |`MYGAME.EXE`
|
|
|Win16 |Uppercase 8.3, `.EXE` |`MYGAME.EXE`
|
|
|PSP |The id, a folder of its own holding `EBOOT.PBP` |`MYGAME/EBOOT.PBP`
|
|
|===
|
|
|
|
Keep the id to 8 characters and letters and digits only, so the same name works
|
|
everywhere.
|
|
|
|
=== Disk Images and Packaging
|
|
|
|
*Apple IIgs.* Programs run from ProDOS volumes. With `MYGAME_IIGS_GAME_DISK :=
|
|
yes`, `make iigs` also builds a self-booting volume, `build/iigs/bin/MYGAME.2mg`:
|
|
a stripped GS/OS that launches the program straight from its own folder, which
|
|
can be copied to a hard drive and run from there. It is an 800 KB floppy when
|
|
the program fits beside the system, otherwise a 2048 KB volume that MAME boots
|
|
off a CFFA2 card. `make iigs-game-disk GAME=NAME` builds one for any program,
|
|
`GAME_DISK_SIZE=2048KB` forces the size, and `make iigs-verify-game-disk`
|
|
boots it headlessly and checks it draws. The data the program needs goes on with
|
|
it; files listed under `programOptionalDir` (a program's optional data, which
|
|
it can run without) go on last, only while the volume has room, and the
|
|
programs' Finder icons last of all (<<_icons>>).
|
|
|
|
*Sharp X68000.* Programs ship on a Human68k floppy; `joey-run` builds one for
|
|
each run from the program and its `DATA/`. A floppy is 1232 KB, so a large
|
|
program strips its binary (`ID_X68000_LDFLAGS := -s`) and ships in a folder of
|
|
its own (`ID_FOLDER`), so its data never rides onto another program's disk. A
|
|
stale image can hide hundreds of kilobytes in subdirectories that a directory
|
|
listing does not show; rebuild from empty rather than deleting files if space
|
|
seems to vanish.
|
|
|
|
*MS-DOS.* The CWSDPMI DPMI server is built into every `.EXE`, so nothing else
|
|
needs to be on the disk.
|
|
|
|
*Amiga.* `joey-run` writes an `s/startup-sequence` that invokes your binary.
|
|
`Name.info` beside it is its Workbench icon, from which it starts too.
|
|
|
|
*DVX.* Every program is a folder laid out as it installs in DVX:
|
|
`build/dvx/bin/apps/acme/mygame/` holds `mygame.app`, its help file
|
|
`mygame.hlp` (DVX gives every program one; the rules write a one-topic help
|
|
from `MYGAME_HELP`) and its `DATA/`. Copy that folder into a DVX installation's
|
|
`APPS\ACME\` and start it from DVX, or let `joey-run` do it
|
|
(<<_dvx_programs>>).
|
|
|
|
*SDL3.* A program is one native executable with SDL 3 linked in statically,
|
|
so the folder it is in, with its `DATA/`, is all it needs on a machine like
|
|
the one that built it.
|
|
|
|
*Web.* A program is its folder, `build/web/bin/MYGAME/`, with its `DATA/`
|
|
packed into `MYGAME.data` at link time (so changing a DATA file relinks it).
|
|
Copy the folder to any web server; `MYGAME.html` is the page.
|
|
|
|
*Win32.* A program is one `.EXE` linked statically against the system's own
|
|
DLLs, so its folder, with its `DATA/`, is all it needs; it ships the way a
|
|
DOS program does.
|
|
|
|
*Win16.* A program is one `.EXE`, its 32-bit code bound to Open Watcom's
|
|
Win386 supervisor and calling only what Windows 3.1 has (USER, GDI, KERNEL,
|
|
and MMSYSTEM), so its folder, with its `DATA/`, is all it needs; it ships the
|
|
way a DOS program does.
|
|
|
|
*macOS.* A program is its app, `build/macos/bin/MYGAME.app`, which holds
|
|
everything it needs: the program (SDL 3 linked in, for Apple silicon and
|
|
Intel Macs both), its `DATA/`, its icon, and the `Info.plist` that names
|
|
them. Copy the app to a Mac, or zip it to send it; a Mac opens it from
|
|
anywhere. Its identifier is `MACOS_ID_PREFIX` and its name
|
|
(`com.example.acme.MYGAME`, <<_a_project>>).
|
|
|
|
*PSP.* A program is its folder, `build/psp/bin/MYGAME/`: `EBOOT.PBP` (the
|
|
program, SDL 3 linked in, packed as the PSPSDK packs it, with its icon and no
|
|
other pictures) and its `DATA/`. Copy the folder into `PSP/GAME/` on a memory
|
|
stick; the PSP shows it by its icon and its `ID_TITLE`. The unstripped ELF stays in
|
|
`build/psp/elf/`, for `psp-addr2line` on an address a crash reports.
|
|
|
|
=== Icons
|
|
|
|
A program has an icon on every system that shows programs by one. `ID_ICON`
|
|
names a picture, a PNG, best square and transparent around the figure, and
|
|
`make` bakes it for each target with `tools/iconBake.py`; a program without
|
|
one gets JoeyLib's kangaroo, `assets/joeyIcon.png`. A picture of 64 pixels or
|
|
less is taken for pixel art and enlarged by whole pixels; a bigger one is
|
|
resampled smoothly. Where an icon has few colours, each pixel takes the
|
|
nearest.
|
|
|
|
[cols="1,5", options="header"]
|
|
|===
|
|
|Target |The icon
|
|
|
|
|Apple IIgs |The Finder's: an icon file (type `$CA`) for each program, which
|
|
the disk scripts put in the volume's `Icons` folder as `NAME.ICONS`, where the
|
|
Finder reads icon files when it starts. 24x20 and 12x10 colour icons, which
|
|
the Finder shows as they are: in its 640 mode each icon pixel is two screen
|
|
pixels, black, red, green, or white beside black, blue, yellow, or white, seen
|
|
together as one of 16 colours (an icon drawn at an odd screen column would
|
|
pair them with the other halves of the palette; the Finder drew every one at
|
|
an even column). A data disk takes the icons
|
|
last, while there is room; a game disk keeps its program's at its root. A
|
|
program copied to another volume takes its icon file along, into that
|
|
volume's `Icons` folder.
|
|
|Amiga |Workbench's: `Name.info` beside the program, a tool's icon in
|
|
Workbench's four colours, 48x24 hires pixels, which starts it with
|
|
`AMIGA_ICON_STACK` (32768) bytes of stack. Started from it, the program runs
|
|
in its own folder, as it does from a shell.
|
|
|DVX |Program Manager's: the program's `icon32` resource, 32x32 on DVX's grey.
|
|
|Win16 |Program Manager's and the minimised window's: 32x32 in the 16 VGA
|
|
colours, bound into the `.EXE`.
|
|
|Win32 |Explorer's and the window's: 16, 32, and 48 pixels, each in 256
|
|
colours and in 32-bit, linked into the `.EXE`.
|
|
|Haiku, BeOS |Tracker's and the Deskbar's: 32x32 and 16x16 in the BeOS
|
|
palette, in the program's resources, and on Haiku the same two as one vector
|
|
icon, which draws each at its own size and the 32x32 cleanly at any larger
|
|
one (an icon with too many colour patches for the vector format goes
|
|
without). Tracker shows a file by the icons in its
|
|
attributes, which a program built on another machine does not have; the
|
|
program copies them across the first time it runs, so Tracker shows it by its
|
|
icon from then on (or at once, after `mimeset -F NAME`).
|
|
|PSP |The menu's: `ICON0` in the EBOOT, 144x80.
|
|
|SDL3 |The window's, 64x64, which the desktop shows where it shows one (title
|
|
bar, task bar, dock).
|
|
|macOS |Finder's and the Dock's: `icon.icns` in the app's `Contents/Resources/`,
|
|
16 to 128 pixels and twice that for Retina screens (up to 512, a picture that
|
|
big or pixel art).
|
|
|Web |The page's: `icon.png`, 32x32, beside it.
|
|
|===
|
|
|
|
MS-DOS, the Atari ST, and the X68000 show no program by an icon of its own,
|
|
so their programs get none.
|
|
|
|
=== Verifying It Actually Runs
|
|
|
|
Build success is weak evidence on retro targets. Run it with `joey-run` (see
|
|
<<Running What You Built>>) on every machine, by its path or by its name in
|
|
the project:
|
|
|
|
[source,console]
|
|
----
|
|
$ ../joeylib/joey-run build/dos/bin/MYGAME.EXE
|
|
$ ../joeylib/joey-run --project . --port amiga mygame
|
|
$ ../joeylib/joey-run build/iigs/bin/MYGAME.2mg
|
|
----
|
|
|
|
Without a window, which is what you want while iterating, run it headless and
|
|
look at the snapshot; the program's log lands next to it as usual:
|
|
|
|
[source,console]
|
|
----
|
|
$ ../joeylib/joey-run --headless --seconds 90 --snapshot mygame.png --project . --port atarist mygame
|
|
----
|
|
|
|
=== JoeyLib's Own Examples
|
|
|
|
JoeyLib's examples are programs like any other: `make/examples.mk` describes
|
|
them, and each target's makefile includes it and `make/programs.mk`. Built from
|
|
the JoeyLib checkout, everything lands in its `build/`:
|
|
|
|
[source,console]
|
|
----
|
|
$ make # the library and the examples, every installed target
|
|
$ make iigs-disk # the IIgs examples on build/iigs/bin/joey.2mg
|
|
$ make -f make/iigs.mk iigs-game-disk GAME=DRAW
|
|
----
|
|
|
|
`make iigs` builds only the IIgs library; `make iigs-disk` builds the examples
|
|
and packs them. Space Taxi and JoeyAGI, two complete games, are projects of
|
|
their own built exactly as this chapter describes: each repository's Makefile
|
|
includes its `program.mk` description between JoeyLib's two makefiles.
|
|
|
|
=== The Gates
|
|
|
|
The repository carries automated checks. They exist because several classes of
|
|
bug on these machines are invisible until measured, and they are worth running
|
|
against your own program too: `scripts/verify-iigs-game-disk.sh IMAGE` boots any
|
|
game disk, `scripts/verify-iigs-audio.sh` and `scripts/verify-x68000-audio.sh`
|
|
read the sound chips under any program given its path, `joey-run --headless`
|
|
runs any program, and the emulator setup in `scripts/lib/` (DVX staging,
|
|
Human68k floppies, environment checks) takes paths.
|
|
|
|
[cols="2,4", options="header"]
|
|
|===
|
|
|Command |What it proves
|
|
|
|
|`make verify-audio`
|
|
|Every port's audio gate: the IIgs DOC and X68000 chips are read directly,
|
|
the ST's YM2149 register writes are traced (and for the STe build the
|
|
samples the DMA sound chip plays), the Amiga, DOS, and DVX output
|
|
is recorded and graded, SDL3's mix is written to a file by SDL's disk
|
|
driver and graded, and the web page's sound is recorded in headless
|
|
Chromium and graded, as is the Win32 program's under Wine, the Win16
|
|
program's on Windows 3.11 in DOSBox, and what reaches the PSP's audio output
|
|
under PPSSPP. Exits 3, not 0,
|
|
if a gate had to be skipped.
|
|
|
|
|`make iigs-verify`
|
|
|The IIgs actually reached the program and drew something.
|
|
|
|
|`make iigs-verify-game-disk`
|
|
|A program's bootable IIgs volume boots, launches the program, and draws.
|
|
|
|
|`scripts/verify-<port>-tilebank.sh`
|
|
|The port's own tile-bank bake loads pixel-exact both ways, with the same
|
|
surface hash as the host check `scripts/check-tilebank.sh`, and banks baked
|
|
for the other machines are refused. `scripts/verify-all.sh tilebank` runs
|
|
every port's.
|
|
|
|
|`scripts/verify-all.sh icon`
|
|
|Every program carries its icon where its system looks
|
|
(`scripts/check-icons.sh`, no emulator), and each system shows it: the IIgs
|
|
Finder's window, the Amiga's icon.library (and a Workbench start), DVX's
|
|
Program Manager, Windows 3.11's desktop with the program minimised, the
|
|
Win32 and SDL3 windows' icons on X, and Tracker on Haiku and BeOS.
|
|
|
|
|`scripts/bench-<port>.sh`
|
|
|Per-operation throughput for that port.
|
|
|
|
|`tools/diff-uber-hashes`
|
|
|Compares a port's rendered output against the IIgs golden reference,
|
|
operation by operation, by surface hash.
|
|
|===
|
|
|
|
That last one is the strongest tool in the repository. `jlSurfaceHash` produces
|
|
the same value for the same logical pixels on every platform regardless of
|
|
internal storage format, so a hash mismatch means one port is genuinely drawing
|
|
different pixels from the others.
|
|
|
|
=== Logging from the Target
|
|
|
|
Debugging a program running on an emulated 1988 machine is awkward. JoeyLib
|
|
provides a logger that writes to a file next to the executable (on DVX, in
|
|
the program's settings folder):
|
|
|
|
[source,c]
|
|
----
|
|
jlLogReset();
|
|
jlLogF("level %d loaded, %u cels", levelNum, celCount);
|
|
jlLogFlush();
|
|
----
|
|
|
|
The headless runners retrieve that file automatically.
|
|
|
|
[NOTE]
|
|
====
|
|
The logger needs a multi-kilobyte ring buffer, which some targets cannot
|
|
afford. Space Taxi compiles it out entirely on the IIgs and X68000 for that
|
|
reason. If you are debugging a memory-tight program, expect to do the same, and
|
|
fall back to observing hardware state through an emulator instead.
|
|
====
|