More target platforms. Licenses updated.

This commit is contained in:
Scott Duensing 2026-10-13 14:01:46 -05:00
parent 92a7c5e49c
commit 71d1cb47a4
437 changed files with 19317 additions and 1237 deletions

21
LICENSE.md Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Scott Duensing
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,78 +1,198 @@
# Third-Party Licenses # Third-Party Licenses
This file inventories every third-party component JoeyLib depends on, JoeyLib itself is distributed under the MIT License (`LICENSE.md`). This
either at runtime (linked into the produced binaries) or at build / file inventories every component JoeyLib depends on but does not contain:
test time. Components are grouped by role; within each group entries what is linked into or shipped with the programs it builds, what builds
list the platforms that consume the component, the upstream URL, and them, and what tests them. JoeyLib's own tree holds no third-party code or
the license. assets, apart from the patches in `installer/patches/`, which are under
the licenses of the projects they patch (noted in those entries).
Components are grouped by role; each entry lists the platforms that use
it, where it comes from, its license and where the installer puts it.
When upstream license terms change, update the corresponding row here. When upstream license terms change, update the corresponding entry here.
This file summarises; the license text that comes with each component is
what counts.
--- ---
## Runtime libraries (linked into joeylib output binaries) ## Shipped in programs (linked in, or on the disk beside them)
These ship as part of, or are linked into, an executable built by These end up in what a JoeyLib program ships as, so their terms matter
JoeyLib. License compatibility for these matters most. most.
### libxmp-lite ### libxmp-lite 4.7.0
- **Used on:** DOS, Atari ST - **Used on:** DOS, Atari ST, X68000, SDL3, PSP, web, Win16, Win32, Haiku,
BeOS
- **URL:** <https://github.com/libxmp/libxmp> - **URL:** <https://github.com/libxmp/libxmp>
- **License:** MIT - **License:** MIT
- **Role:** ProTracker / Amiga MOD replayer + SMIX SFX overlay. Linked - **Role:** ProTracker / Amiga MOD replayer + SMIX SFX overlay. Each
into AUDIO binaries on the chunky-display platforms. port's makefile compiles it into AUDIO programs.
- **Installed at:** `toolchains/opt/libxmp/` (installer component `libxmp`) - **Installed at:** `toolchains/opt/libxmp/` (installer component `libxmp`)
### SDL 3.4.18
- **Used on:** SDL3, PSP, web
- **URL:** <https://www.libsdl.org/>
- **License:** zlib
- **Role:** window, input and audio for the hosted SDL3 code. Built as a
static library for the host, for the PSP with pspdev and for Emscripten
(with JoeyLib's patches, `installer/patches/sdl3Web/`, which are under
SDL's zlib license), and linked into each program.
- **Installed at:** `toolchains/opt/sdl3/`, `toolchains/opt/sdl3Psp/`,
`toolchains/opt/sdl3Web/` (installer components `sdl3`, `sdl3Psp`,
`sdl3Web`)
### NinjaTrackerPlus (NTP) ### NinjaTrackerPlus (NTP)
- **Used on:** Apple IIgs - **Used on:** Apple IIgs
- **URL:** <https://www.ninjaforce.com/html/products_software.html> - **URL:** <https://www.ninjaforce.com/html/products_software.html>
(downloads from <https://www.ninjaforce.com/downloads/>) (downloads from <https://www.ninjaforce.com/downloads/>)
- **License:** No explicit license in the source distribution; written - **License:** Unknown -- no file in the source distribution carries a
by Jesse Blue (NinjaForce). Treated here as free for use; consult license or notice. Written by Jesse Blue (Ninjaforce), who has given
upstream before commercial redistribution. JoeyLib permission to redistribute it; that permission is recorded here,
not in the archive.
- **Role:** Apple IIgs Ensoniq DOC `.NTP` module replayer + SFX - **Role:** Apple IIgs Ensoniq DOC `.NTP` module replayer + SFX
streamer. Merlin32-assembled into `ntpplayer`, which ships on the disk streamer. Merlin32-assembled into `ntpplayer`, which ships on the disk
next to each IIgs program and is loaded at run time. next to each IIgs program and is loaded at run time. Its
- **Installed at:** `toolchains/opt/ntp/` (source; installer component `ntp`). `ntpconverter.php` makes the `.NTP` files (tools/joeymod).
- **Installed at:** `toolchains/opt/ntp/` (source; installer component `ntp`)
### PTPlayer ### PTPlayer 6.4
- **Used on:** Amiga - **Used on:** Amiga
- **URL:** <http://aminet.net/mus/play/ptplayer.lha> - **URL:** <http://aminet.net/mus/play/ptplayer.lha>
(author Frank Wille, <http://aminet.net/package/mus/play/ptplayer>) (author Frank Wille, <http://aminet.net/package/mus/play/ptplayer>)
- **License:** Public Domain - **License:** Public Domain (the archive's `license` file: the Unlicense)
- **Role:** ProTracker MOD replayer + `mt_playfx` SFX channel for the - **Role:** ProTracker MOD replayer + `mt_playfx` SFX channel for the
Paula audio HAL. Paula audio HAL.
- **Installed at:** `toolchains/opt/ptplayer/` (installer component `ptplayer`) - **Installed at:** `toolchains/opt/ptplayer/` (installer component `ptplayer`)
### CWSDPMI r7
- **Used on:** DOS
- **URL:** <https://sandmann.dotster.com/cwsdpmi/>
- **License:** Custom redistribution terms (Charles W. Sandmann,
(c) 1995-2010). Binary may be redistributed without source provided
the executables are unmodified and end users are notified of
source availability -- full terms in `cwsdpmi.doc`. Source is
GPL-licensed if distributed.
- **Role:** the DPMI host. `make/support/dos/embed-dpmi.sh` puts
CWSDSTUB.EXE in front of every DOS executable, so each `.EXE` carries it
and runs without a separate CWSDPMI.EXE.
- **Installed at:** `toolchains/opt/cwsdpmi/` (installer component `cwsdpmi`)
### The toolchains' C libraries and start files
Each toolchain below also links its own C library, start files and
compiler runtime into the programs it builds. What a shipped program owes
them, in brief (the entries below have the detail):
- **DOS:** DJGPP's libc and crt0 (LGPL); a program may ship without their
source if its users are told how to get DJGPP (`copying.dj`). DVX
programs are modules DVX loads, built with DVX's SDK.
- **Atari ST:** MiNTLib, file by file under its own license (COPYMINT),
the LGPL 2 or later, BSD, Henry Spencer's and musl's MIT terms; a linked
program meets all of them (MiNTLib's `LICENSES`).
- **Amiga:** libnix (public domain).
- **X68000:** newlib (a collection of permissive licenses,
`COPYING.NEWLIB`), with elf2x68k's Human68k support (BSD).
- **PSP:** the PSPSDK (BSD) and newlib.
- **Win16:** Open Watcom's C runtime, and its Win386 supervisor, bound
into every program (Sybase Open Watcom Public License: a program that
carries them needs the notice of its section 2.2(d), in the program and
in its documentation). Every Win16 program carries the notice, never
shown, and docs/Portability.adoc ("Shipping") gives the line for its
documentation; see Open Watcom below.
- **Win32:** mingw-w64's start files and runtime (Zope Public License 2.1,
parts public domain); MSVCRT.DLL is Windows' own.
- **web:** Emscripten's system libraries (musl, MIT; libc++ and
compiler-rt, Apache 2.0 with LLVM Exceptions).
- **Apple IIgs:** llvm816's runtime (crt0, libc): Apache License 2.0 with
LLVM Exceptions, which let a program it is compiled into ship without
the license's notice conditions.
- **BeOS:** the start files from your BeOS 5 Professional CD (Be, Inc.;
terms Unknown; see the BeOS entry under the never-downloaded media
below).
- **Haiku:** the system's own shared libraries, at run time (MIT).
- **Every gcc port:** libgcc, under the GCC Runtime Library Exception,
which puts no conditions on the programs it is linked into.
---
## Sibling projects (by JoeyLib's author)
Separate repositories beside this one, which the installer takes from a
checkout there (or the path named).
### DVX
- **Used on:** DVX
- **Source:** `../dvxgui` (or `install.sh --dvx-dir PATH`)
- **License:** MIT
- **Role:** the DOS desktop the dvx port's programs run in, and the SDK
they are built with.
- **Installed at:** `toolchains/opt/dvx/` (installer component `dvx`)
### KPJOY.DRV
- **Used on:** Win16
- **Source:** `../kpjoy` (or `KPJOY_DIR`); no public home yet
- **License:** MIT. The Open Watcom code it carries (DLL start-up and C
library helpers) is under the OWPL; the driver carries its notice (see
Open Watcom below).
- **Role:** the joystick driver. Windows 3.1 has the joystick API but
ships no driver for it, so without one no program sees a stick. Every
win16 run's Windows uses it, and a Win16 program can ship it.
- **Installed at:** `toolchains/opt/kpjoy/`, with its `LICENSE.md` beside
the driver so a copy taken from there carries its notice (installer
component `kpjoy`)
### KPCOMM.DRV
- **Used on:** Win16
- **Source:** `../mscomm/drv` (or `KPCOMM_DIR`)
- **License:** MIT (the `drv` folder only). Built with Open Watcom, it
carries Open Watcom code (DLL start-up and C library helpers) under the
OWPL, and its notice (see Open Watcom below).
- **Role:** replaces Windows' COMM.DRV, for reliable 57600 and 115200 baud
on a 16550A. Every win16 run's Windows uses it, and a Win16 program can
ship it.
- **Installed at:** `toolchains/opt/kpcomm/`, with its `LICENSE.md` beside
the driver (installer component `kpcomm`)
--- ---
## Build-time toolchains (NOT linked, used to produce binaries) ## Build-time toolchains (NOT linked, used to produce binaries)
These run on the developer's machine to compile / assemble / link These run on the developer's machine to compile / assemble / link
JoeyLib for each target. They are not redistributed inside the JoeyLib for each target. The compilers themselves are not redistributed
produced game binaries. inside the produced binaries; the libraries they link in are summarised
above.
### llvm-mos (clang / llvm-mc / link816 w65816 toolchain) ### llvm816 (clang / llvm-mc / link816 w65816 toolchain)
- **Used on:** Apple IIgs - **Used on:** Apple IIgs
- **URL:** <https://github.com/llvm-mos/llvm-mos> - **URL:** <https://forge.duensing.digital/AI_Slop/65816-llvm-mos>
- **License:** Apache License 2.0 with LLVM Exceptions (the upstream (a fork of llvm-mos, <https://github.com/llvm-mos/llvm-mos>)
LLVM license). - **License:** Apache License 2.0 with LLVM Exceptions, llvm-mos's (and
LLVM's) license, for all of it: llvm-mos's code and the W65816 backend,
link816, omfEmit and the runtime (its `LICENSE.TXT`). Its README lists
the third-party code it holds under other licenses (the C++ runtime's
Embedded Template Library, MIT; test and demo sources), none of which
reaches a JoeyLib program.
- **Role:** clang C compiler targeting the 65816, plus llvm-mc for - **Role:** clang C compiler targeting the 65816, plus llvm-mc for
assembling hand-written `.s` files and link816 for producing OMF assembling hand-written `.s` files, link816 for producing OMF S16
S16 executables. Driven by `make/support/iigs/clang-build.sh`; the executables, and the runtime every IIgs program links. Driven by
toolchain root is located via the `LLVM816_ROOT` environment `make/support/iigs/clang-build.sh`; the toolchain root is located via
variable. the `LLVM816_ROOT` environment variable.
- **Installed at:** `toolchains/opt/llvm816/` (installer component `llvm816`) - **Installed at:** `toolchains/opt/llvm816/` (installer component `llvm816`)
### Merlin32 ### Merlin32 1.1
- **Used on:** Apple IIgs - **Used on:** Apple IIgs
- **URL:** <https://brutaldeluxe.fr/products/crossdevtools/merlin/> - **URL:** <https://brutaldeluxe.fr/products/crossdevtools/merlin/>
- **License:** Freely distributed by Brutal Deluxe Software - **License:** Unknown -- freely distributed by Brutal Deluxe Software
(Olivier Zardini, Antoine Vignau). Source published with no (Olivier Zardini, Antoine Vignau). Source published with no
formal open-source license header -- Brutal Deluxe's "open source formal open-source license header -- Brutal Deluxe's "open source
philosophy" but copyright is retained. Treat as "free to use, philosophy" but copyright is retained. Treat as "free to use,
@ -81,14 +201,34 @@ produced game binaries.
- **Role:** 65816 cross-assembler. Builds NinjaTrackerPlus. - **Role:** 65816 cross-assembler. Builds NinjaTrackerPlus.
- **Installed at:** `toolchains/opt/merlin32/` (installer component `merlin32`) - **Installed at:** `toolchains/opt/merlin32/` (installer component `merlin32`)
### cadius 1.4.6
- **Used on:** Apple IIgs
- **URL:** <https://github.com/mach-kernel/cadius>
- **License:** GNU GPL v3
- **Role:** ProDOS disk-image tool every IIgs disk script drives.
- **Installed at:** `toolchains/opt/cadius/` (installer component `cadius`)
### Bebbo m68k-amigaos GCC toolchain ### Bebbo m68k-amigaos GCC toolchain
- **Used on:** Amiga - **Used on:** Amiga
- **URL:** <https://github.com/AmigaPorts/m68k-amigaos-gcc> - **URL:** <https://github.com/AmigaPorts/m68k-amigaos-gcc>
- **License:** GNU GPL v2 (gcc, binutils, libnix); per-component - **License:** by part (the sub-projects of the pinned commit's
copyrights listed in upstream `README.md`. Includes assets covered `default-repos`, and the two archives its build downloads):
by individual permissive notices (Roadshow, fd2pragma public - the toolchain's build scripts: GNU GPL v2
domain, ira freeware, etc.). - gcc 6.5 and binutils: GNU GPL v3, with the GCC Runtime Library
Exception for libgcc
- libnix, the C library programs link (`-noixemul`): public domain
- clib2: BSD (3-clause, by its README)
- newlib and the ixemul SDK, installed but not linked (programs use
libnix): newlib's collection of permissive licenses; ixemul GNU GPL v2
- sfdc, fd2sfd, libdebug: GNU GPL v2
- ira: Unknown (its README calls it freeware)
- fd2pragma, amiga-netinclude (the networking headers), aros-stuff:
Unknown (none stated)
- the NDK 3.2 headers (Hyperion Entertainment's; a free download from
Hyperion and Aminet): Unknown (its readme states none)
- vasm: below
- **Role:** AmigaOS HUNK-format gcc + binutils + libnix used to - **Role:** AmigaOS HUNK-format gcc + binutils + libnix used to
compile the Amiga port and link against PTPlayer. compile the Amiga port and link against PTPlayer.
- **Installed at:** `toolchains/opt/amigaGcc/` (installer component `amigaGcc`) - **Installed at:** `toolchains/opt/amigaGcc/` (installer component `amigaGcc`)
@ -109,42 +249,34 @@ produced game binaries.
- **Installed at:** built with the Amiga GCC toolchain (AmigaPorts `vasm` - **Installed at:** built with the Amiga GCC toolchain (AmigaPorts `vasm`
sub-project), `toolchains/opt/amigaGcc/bin/vasmm68k_mot` sub-project), `toolchains/opt/amigaGcc/bin/vasmm68k_mot`
### m68k-atari-mint GCC toolchain (Thorsten Otto builds) ### m68k-atari-mint GCC toolchain
- **Used on:** Atari ST - **Used on:** Atari ST
- **URL:** <https://tho-otto.de/download/mint/> - **URL:** <https://tho-otto.de/download/mint/>
(gcc upstream: GNU; mintlib: <https://github.com/freemint/mintlib>) (Vincent Riviere's builds; mintlib: <https://github.com/freemint/mintlib>)
- **License:** GNU GPL v2 (gcc, binutils); mintlib is a mix of GPL - **License:** gcc 15.2 and binutils 2.45: GNU GPL v3, with the GCC
and permissive (per-file headers). Runtime Library Exception for libgcc. MiNTLib 0.60.1: per file, under
the MiNTLib license (COPYMINT), the LGPL 2 or later, BSD, Henry
Spencer's or musl's MIT terms; a program linked with it meets all of
them (MiNTLib's `LICENSES`).
- **Role:** GEMDOS-native gcc + binutils + mintlib used to compile - **Role:** GEMDOS-native gcc + binutils + mintlib used to compile
the Atari ST port. the Atari ST port.
- **Installed at:** `toolchains/opt/mintGcc/` (installer component `mintGcc`) - **Installed at:** `toolchains/opt/mintGcc/` (installer component `mintGcc`)
### DJGPP (build-djgpp packaging) ### DJGPP (build-djgpp packaging)
- **Used on:** DOS - **Used on:** DOS, DVX
- **URL:** <https://github.com/andrewwutw/build-djgpp> - **URL:** <https://github.com/andrewwutw/build-djgpp>
(DJGPP upstream: <http://www.delorie.com/djgpp/>) (DJGPP upstream: <http://www.delorie.com/djgpp/>)
- **License:** Build script GNU GPL v3; bundled gcc/binutils GNU - **License:** build-djgpp's scripts: GNU GPL v3. gcc 12.2.0 and
GPL v2; DJGPP runtime libraries (libc) are mostly public-domain or binutils: GNU GPL v3, with the GCC Runtime Library Exception for
permissive -- see DJGPP `readme.1st`. libgcc. DJGPP's own code (`copying.dj`): GNU GPL, except the sources of
crt0 and libc, which are LGPL; those may be linked into a program shipped
without source as long as its users are told how to get DJGPP.
- **Role:** 32-bit protected-mode gcc cross-compiler producing - **Role:** 32-bit protected-mode gcc cross-compiler producing
COFF binaries that run on 386+ DOS via DPMI. COFF binaries that run on 386+ DOS via DPMI.
- **Installed at:** `toolchains/opt/djgpp/` (installer component `djgpp`) - **Installed at:** `toolchains/opt/djgpp/` (installer component `djgpp`)
### CWSDPMI
- **Used on:** DOS
- **URL:** <https://sandmann.dotster.com/cwsdpmi/>
- **License:** Custom redistribution terms (Charles W. Sandmann,
(c) 1995-2010). Binary may be redistributed without source provided
the executables are unmodified and end users are notified of
source availability -- full terms in `cwsdpmi.doc`. Source is
GPL-licensed if distributed.
- **Role:** Stubbed-into-binary DPMI server for DJGPP-compiled DOS
executables (via `embed-dpmi.sh`).
- **Installed at:** `toolchains/opt/cwsdpmi/` (installer component `cwsdpmi`)
### NASM ### NASM
- **Used on:** DOS - **Used on:** DOS
@ -154,6 +286,100 @@ produced game binaries.
port. port.
- **Installed from:** the Linux distribution's `nasm` package - **Installed from:** the Linux distribution's `nasm` package
### elf2x68k 20260602
- **Used on:** X68000
- **URL:** <https://github.com/yunkya2/elf2x68k>
- **License:** elf2x68k's own sources: BSD; its scripts: Apache License
2.0. gcc 13.4.0 and binutils 2.44: GNU GPL v3, with the GCC Runtime
Library Exception for libgcc. newlib 4.5.0: its collection of
permissive licenses (`COPYING.NEWLIB`).
- **Role:** m68k-xelf gcc, whose link step converts the ELF output into a
Human68k `.X` executable.
- **Installed at:** `toolchains/opt/elf2x68k/` (installer component
`elf2x68k`)
### Open Watcom v2 (2026-10-01 build)
- **Used on:** Win16
- **URL:** <https://github.com/open-watcom/open-watcom-v2>
- **License:** Sybase Open Watcom Public License 1.0 (`license.txt` in
the release). A program that carries Open Watcom code in object form
-- its C runtime, and the Win386 supervisor (WIN386.EXT) bound into
every Win16 program -- must, by section 2.2(d), include a prominent
notice, in the program and its documentation, that the source is
available under the license and where to get it. Every Win16 program
carries it (`hostWin16OwplNotice`, src/hosted/win16/win16Backend.c), as
do KPJOY.DRV and KPCOMM.DRV, as a string never shown; docs/Portability.adoc
("Shipping") gives the same line for a program's documentation.
- **Role:** the Win386 target compiles the win16 port's 32-bit programs
and binds them to the supervisor; the 16-bit Windows target builds
KPJOY.DRV and KPCOMM.DRV.
- **Installed at:** `toolchains/opt/openWatcom/` (installer component
`openWatcom`)
### llvm-mingw 20260922 (msvcrt)
- **Used on:** Win32
- **URL:** <https://github.com/mstorsjo/llvm-mingw>
- **License:** clang, lld and the LLVM runtimes: Apache License 2.0 with
LLVM Exceptions. mingw-w64's headers and runtime: Zope Public License
2.1, with parts marked public domain, BSD or LGPL.
- **Role:** i686 cross compiler for the win32 port's programs, which link
Windows' MSVCRT.DLL.
- **Installed at:** `toolchains/opt/llvmMingw/` (installer component
`llvmMingw`)
### pspdev v20261001
- **Used on:** PSP
- **URL:** <https://github.com/pspdev/pspdev>
- **License:** psp-gcc and binutils: GNU GPL v3, with the GCC Runtime
Library Exception for libgcc. The PSPSDK: BSD. newlib: its collection
of permissive licenses. Every library pspdev carries has its license
under `psp/share/licenses/`.
- **Role:** psp-gcc, the PSPSDK and the tools that make an EBOOT.PBP.
- **Installed at:** `toolchains/opt/pspdev/` (installer component `pspdev`)
### Emscripten 6.0.11 (emsdk)
- **Used on:** web
- **URL:** <https://emscripten.org/>
(emsdk: <https://github.com/emscripten-core/emsdk>)
- **License:** emsdk: MIT. Emscripten: MIT or the University of
Illinois/NCSA Open Source License. Its system libraries, compiled into
each program: musl (MIT); libc++, libc++abi and compiler-rt (Apache
License 2.0 with LLVM Exceptions). Its clang and binaryen: Apache 2.0
(with LLVM Exceptions for clang). Node.js: MIT.
- **Role:** compiles the web port's programs to WebAssembly.
- **Installed at:** `toolchains/opt/emsdk/` (installer component `emsdk`)
### Haiku cross compilers (R1/beta6)
- **Used on:** Haiku (x86_64 gcc 13.3), Haiku x86 and BeOS (gcc 2.95.3)
- **URL:** <https://www.haiku-os.org/> (the toolchain layers of Haiku's
published cross-compiler images, `ghcr.io/haiku/cross-compiler`)
- **License:** gcc and binutils: GNU GPL (v3 for gcc 13.3, v2 for gcc
2.95.3), with the GCC Runtime Library Exception for gcc 13's runtime.
The sysroots (Haiku's system libraries and `haiku_devel`): MIT.
- **Role:** build the haiku and haiku32 ports; gcc 2.95.3 also builds the
beos port against BeOS R5's own sysroot.
- **Installed at:** `toolchains/opt/haikuGcc/`, `toolchains/opt/haikuGcc2/`
(installer components `haikuGcc`, `haikuGcc2`)
### Haiku host tools (R1/beta6)
- **Used on:** Haiku, Haiku x86, BeOS
- **URL:** <https://github.com/haiku/haiku>
(jam: <https://github.com/haiku/buildtools>)
- **License:** Haiku: MIT. jam: Perforce's Jam license (free use and
distribution, keeping its notice).
- **Role:** `package` unpacks the `.hpkg` packages the sysroots are made
from; `bfs_shell` reads and writes the BFS disks the VMs take their jobs
on.
- **Installed at:** `toolchains/opt/haikuTools/` (installer component
`haikuTools`)
--- ---
## Test-time emulators (not shipped, not linked) ## Test-time emulators (not shipped, not linked)
@ -162,16 +388,17 @@ Used by `joey-run` and the test gates to run the produced binaries on the
developer's machine. Not part of any redistributed artifact. Installed by developer's machine. Not part of any redistributed artifact. Installed by
`./install.sh install emulators`. `./install.sh install emulators`.
### MAME ### MAME 0.264
- **Used on:** Apple IIgs (apple2gs driver) and Sharp X68000 (x68k driver) - **Used on:** Apple IIgs (apple2gs driver) and Sharp X68000 (x68k driver)
- **URL:** <https://www.mamedev.org/> - **URL:** <https://www.mamedev.org/>
- **License:** GNU GPL v2+ (GPL-2.0-or-later) plus a 3-clause BSD - **License:** GNU GPL v2+ (GPL-2.0-or-later) plus a 3-clause BSD
alternative for some components. alternative for some components.
- **Installed at:** `toolchains/opt/mame/`, built from the 0.264 release with - **Installed at:** `toolchains/opt/mame/`, built from the 0.264 release with
the patches in `installer/patches/mame/` (installer component `mame`). the patches in `installer/patches/mame/`, which are under MAME's license
(installer component `mame`).
### Hatari ### Hatari 2.4.1
- **Used on:** Atari ST - **Used on:** Atari ST
- **URL:** <https://www.hatari-emu.org/> - **URL:** <https://www.hatari-emu.org/>
@ -180,15 +407,15 @@ developer's machine. Not part of any redistributed artifact. Installed by
`toolchains/opt/hatari/`, built from the 2.4.1 source (installer component `toolchains/opt/hatari/`, built from the 2.4.1 source (installer component
`hatari`) `hatari`)
### DOSBox Staging ### DOSBox Staging 0.83.0
- **Used on:** DOS - **Used on:** DOS, DVX, Win16 (Windows for Workgroups runs on it)
- **URL:** <https://www.dosbox-staging.org/> - **URL:** <https://www.dosbox-staging.org/>
- **License:** GNU GPL v2+ - **License:** GNU GPL v2+ (GPL-2.0-or-later)
- **Installed at:** `toolchains/opt/dosbox/` (the project's Linux release; - **Installed at:** `toolchains/opt/dosbox/` (the project's Linux release;
installer component `dosbox`) installer component `dosbox`)
### FS-UAE ### FS-UAE 3.1.66
- **Used on:** Amiga - **Used on:** Amiga
- **URL:** <https://fs-uae.net/> - **URL:** <https://fs-uae.net/>
@ -197,7 +424,7 @@ developer's machine. Not part of any redistributed artifact. Installed by
`toolchains/opt/fsuae/`, built from the 3.1.66 release (installer component `toolchains/opt/fsuae/`, built from the 3.1.66 release (installer component
`fsuae`) `fsuae`)
### EmuTOS ### EmuTOS 1.4
- **Used on:** Atari ST (TOS replacement for Hatari) - **Used on:** Atari ST (TOS replacement for Hatari)
- **URL:** <https://emutos.sourceforge.io/> - **URL:** <https://emutos.sourceforge.io/>
@ -205,13 +432,64 @@ developer's machine. Not part of any redistributed artifact. Installed by
- **Installed at:** `toolchains/firmware/atarist/emutos-512k.img` (installer - **Installed at:** `toolchains/firmware/atarist/emutos-512k.img` (installer
component `emutos`) component `emutos`)
### QEMU 11.1.2 (with pixman 0.46.4)
- **Used on:** Haiku, Haiku x86, BeOS
- **URL:** <https://www.qemu.org/> (pixman: <https://pixman.org/>)
- **License:** QEMU: GNU GPL v2. pixman, linked into it: MIT.
- **Installed at:** `toolchains/opt/qemu/`, built from the release source
(installer component `qemu`)
### PPSSPP 1.20.4
- **Used on:** PSP
- **URL:** <https://www.ppsspp.org/>
- **License:** GNU GPL v2+ (GPL-2.0-or-later)
- **Installed at:** `toolchains/opt/ppsspp/`, its headless runner built from
the release source with the patch in `installer/patches/ppsspp/`, which
is under PPSSPP's license (installer component `ppsspp`)
### Wine 11.19 (Kron4ek's portable WoW64 build)
- **Used on:** Win32
- **URL:** <https://www.winehq.org/>
(build: <https://github.com/Kron4ek/Wine-Builds>)
- **License:** GNU LGPL v2.1+
- **Installed at:** `toolchains/opt/wine/` (installer component `wine`)
--- ---
## System ROMs and disk images (used for testing only) ## Distribution packages (build and test hosts only)
Installed from the Linux distribution by the components named below
(`host`, `headless`, `ntp`); none of them ships in a program.
- **host:** GNU make, the host C compiler (gcc), tar and diffutils (GNU GPL
v3+); git and socat (GNU GPL v2); git-lfs (MIT); curl (the curl
license); xz (0BSD, parts GPL); bzip2 (bzip2's BSD-style license);
unzip (the Info-ZIP license); lhasa (ISC); procps (GNU GPL v2+ and LGPL);
Python 3 (PSF License) with Pillow (MIT-CMU).
- **headless:** Xvfb (X.Org's MIT/X11 license); xdotool (3-clause BSD);
ImageMagick (the ImageMagick License); pactl and parec, from
pulseaudio-utils (GNU LGPL v2.1+).
- **ntp:** PHP's command line (the PHP License 3.01) runs NTP's converter.
- **tools/traceLogo.py**, which made `assets/joeylibLogo.svg` and is run
only if the logo art changes, takes potracer (GNU GPL v2+), Pillow and
numpy (BSD), installed by hand with pip. The script holds none of
potracer's code, and the logo it made is not covered by potracer's
license.
- Building MAME, QEMU, PPSSPP and SDL 3 also takes the distribution's
development packages (SDL2, X11, Wayland, PulseAudio, ALSA, GLib and the
rest), each under its own license.
---
## System ROMs, operating systems and disk images (used for testing only)
These are **not** part of JoeyLib distribution. `./install.sh` These are **not** part of JoeyLib distribution. `./install.sh`
places them in `toolchains/firmware/` for emulator-side testing only; see places them in `toolchains/firmware/` or `toolchains/opt/` for
the source of each before shipping anything that depends on them. emulator-side testing only; see the source of each before shipping
anything that depends on them.
### Downloaded by the installer ### Downloaded by the installer
@ -221,11 +499,16 @@ the source of each before shipping anything that depends on them.
- **Apple IIgs System 6.0.4** (`System.Disk`): Apple Inc. proprietary OS, from - **Apple IIgs System 6.0.4** (`System.Disk`): Apple Inc. proprietary OS, from
the Apple II archive (<https://mirrors.apple2.org.za/>). Component the Apple II archive (<https://mirrors.apple2.org.za/>). Component
`iigsFirmware`. `iigsFirmware`.
- **CFFA2 card firmware** (`cffa20eec02.bin`): freely redistributed by - **CFFA2 card firmware** (`cffa20eec02.bin`): license Unknown; freely
dreher.net (<https://dreher.net/>). Component `iigsFirmware`. redistributed by dreher.net (<https://dreher.net/>). Component
`iigsFirmware`.
- **X68000 IPL-ROM and Human68k 3.02 system disk**: from Sharp's own free - **X68000 IPL-ROM and Human68k 3.02 system disk**: from Sharp's own free
release (2000), published by the X68000 LIBRARY release (2000), published by the X68000 LIBRARY
(<http://retropc.net/x68000/software/sharp/>). Component `x68kFirmware`. (<http://retropc.net/x68000/software/sharp/>). Component `x68kFirmware`.
- **Haiku R1/beta6 anyboot images** (x86_64, and x86 gcc2h): Haiku is MIT;
the third-party packages on the images carry their own licenses. Made to
boot to the desktop and run the gates' job runner. Components `haikuVm`
and `haikuVm32`.
### Never downloaded (supplied by the user or the project's own bundle) ### Never downloaded (supplied by the user or the project's own bundle)
@ -236,13 +519,33 @@ project hosts (`JOEY_BUNDLE_URL`); matched by the checksums in
- **Amiga Kickstart 3.1 ROM**: Cloanto / Amiga Corp. proprietary, sold today - **Amiga Kickstart 3.1 ROM**: Cloanto / Amiga Corp. proprietary, sold today
(Amiga Forever). Required by the Amiga test gates; `joey-run` falls back to (Amiga Forever). Required by the Amiga test gates; `joey-run` falls back to
FS-UAE's AROS without it. Component `kickstart`. FS-UAE's AROS without it. Component `kickstart`.
- **Amiga Kickstart 3.1 ROMs for the A1200 (r40.68) and A4000T (r40.70)**:
Cloanto / Amiga Corp. proprietary (Amiga Forever). Optional: they run the
Amiga gates on those machines as well as the A500. Components
`kickstartA1200` and `kickstartA4000`.
- **Amiga serial.device 37.4** (Workbench 3.1's `Devs/serial.device`): - **Amiga serial.device 37.4** (Workbench 3.1's `Devs/serial.device`):
Cloanto / Amiga Corp. proprietary, part of Workbench 3.1 (Amiga Forever). Cloanto / Amiga Corp. proprietary, part of Workbench 3.1 (Amiga Forever).
Kickstart 3.1 has no serial.device in ROM, so `joey-run` and the Amiga Kickstart 3.1 has no serial.device in ROM, so `joey-run` and the Amiga
serial gate put this copy on the boot drive; `import` also finds it inside serial gate put this copy on the boot drive; `import` also finds it inside
a Workbench `.adf`. Component `amigaSerial`. a Workbench `.adf`. Component `amigaSerial`.
- **Amiga lowlevel.library 40.35** (Workbench 3.1's `Libs/lowlevel.library`):
Cloanto / Amiga Corp. proprietary (Amiga Forever). The Amiga port reads
the joysticks through it and Kickstart 3.1 has none in ROM, so `joey-run`
and the Amiga joystick gate put this copy on the boot drive; `import`
also finds it inside a Workbench `.adf`. Component `amigaLowlevel`.
- **X68000 CG (font) ROM**: not part of Sharp's free release. MAME's x68000 - **X68000 CG (font) ROM**: not part of Sharp's free release. MAME's x68000
driver needs it. Component `x68kCgrom`. driver needs it. Component `x68kCgrom`.
- **Windows for Workgroups 3.11** (your install disc's ISO) **and the S3
Trio64V+ display driver** (its `.zip`): Microsoft and S3 proprietary.
Installed unattended into the DOSBox PC every win16 run uses. A Win16
program's users bring their own Windows. Component `win311`.
- **BeOS 5 Professional CD** (its image): Be, Inc. proprietary; the terms
for its start files are Unknown. Its boot floppy and x86 system become
the BeOS R5 VM (component `beosVm`), and its Development package's
headers, start files and system libraries the beos port's sysroot
(component `beosR5`). Every beos program links the start files
(`start_dyn.o`, `init_term_dyn.o`, `crti.o`, `crtn.o`), as every program
built with Be's own tools did; check their terms before shipping one.
--- ---
@ -250,10 +553,14 @@ project hosts (`JOEY_BUNDLE_URL`); matched by the checksums in
When adding a new third-party dependency: When adding a new third-party dependency:
1. Append a row in the appropriate section above. 1. Append an entry in the appropriate section above.
2. Record platform(s), upstream URL, license name, and a one-line 2. Record platform(s), upstream URL, license name, and a one-line
role description. role description.
3. List where the installer puts it (`toolchains/opt/<component>/` or 3. List where the installer puts it (`toolchains/opt/<component>/` or
`toolchains/firmware/`). `toolchains/firmware/`).
4. If license terms restrict redistribution, call that out 4. If license terms restrict redistribution, call that out
explicitly (as we do for Apple ROMs). explicitly (as we do for Apple ROMs).
5. If any of it ends up inside programs (a library, start files, a
runtime, a file on the program's disk), put it under "Shipped in
programs", or in that section's toolchain summary, with what a shipped
program owes it.

View file

@ -1,13 +1,26 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# JoeyLib top-level Makefile. # JoeyLib top-level Makefile.
# #
# Usage: # Usage:
# make builds every target whose toolchain is installed # make builds every target whose toolchain is installed
# make iigs builds Apple IIgs only # make iigs builds Apple IIgs only
# make amiga builds Commodore Amiga only # make amiga builds Commodore Amiga only
# make atarist builds Atari ST only # make atarist builds Atari ST only (runs on every ST)
# make ste builds the Atari STe variant (STe and Mega STe only)
# make dos builds MS-DOS only # make dos builds MS-DOS only
# make x68000 builds Sharp X68000 only # make x68000 builds Sharp X68000 only
# make dvx builds DVX (JoeyLib programs as DVX desktop programs) # make dvx builds DVX (JoeyLib programs as DVX desktop programs)
# make sdl3 builds SDL3 (JoeyLib programs as native windowed programs)
# make web builds the web port (JoeyLib programs as web pages)
# make win32 builds Win32 (Windows 95 through today, as .EXE programs)
# make win16 builds Win16 (Windows 3.1 on a 386, as .EXE programs)
# make psp builds the PSP port (JoeyLib programs as PSP homebrew EBOOT.PBPs)
# make haiku builds Haiku x86_64 (the Be API backend, gcc 13)
# make haiku32 builds Haiku 32-bit x86 (the Be API backend, gcc 2.95, BeOS ABI)
# make beos builds BeOS R5 x86 (the same backend and compiler, R5's own headers and libraries)
# make docs renders the manual to build/docs (HTML + PDF) # make docs renders the manual to build/docs (HTML + PDF)
# make verify builds every port, then runs every gate (needs emulators) # make verify builds every port, then runs every gate (needs emulators)
# make verify-audio runs every port's audio gate (needs emulators) # make verify-audio runs every port's audio gate (needs emulators)
@ -25,7 +38,7 @@ include $(dir $(firstword $(MAKEFILE_LIST)))make/common.mk
ALL_TARGETS := $(JOEY_PORTS_INSTALLED) ALL_TARGETS := $(JOEY_PORTS_INSTALLED)
.PHONY: all iigs iigs-disk iigs-verify amiga atarist dos x68000 dvx blank-check tools clean help status verify verify-audio verify-serial docs .PHONY: all iigs iigs-disk iigs-verify amiga atarist ste dos x68000 dvx sdl3 web win32 win16 psp haiku haiku32 beos blank-check tools clean help status verify verify-audio verify-serial docs
all: $(ALL_TARGETS) tools all: $(ALL_TARGETS) tools
ifeq ($(ALL_TARGETS),) ifeq ($(ALL_TARGETS),)
@ -51,6 +64,9 @@ amiga:
atarist: atarist:
@$(MAKE) -f $(REPO_DIR)/make/atarist.mk @$(MAKE) -f $(REPO_DIR)/make/atarist.mk
ste:
@$(MAKE) -f $(REPO_DIR)/make/ste.mk
dos: dos:
@$(MAKE) -f $(REPO_DIR)/make/dos.mk @$(MAKE) -f $(REPO_DIR)/make/dos.mk
@ -60,6 +76,30 @@ x68000:
dvx: dvx:
@$(MAKE) -f $(REPO_DIR)/make/dvx.mk @$(MAKE) -f $(REPO_DIR)/make/dvx.mk
sdl3:
@$(MAKE) -f $(REPO_DIR)/make/sdl3.mk
web:
@$(MAKE) -f $(REPO_DIR)/make/web.mk
win32:
@$(MAKE) -f $(REPO_DIR)/make/win32.mk
win16:
@$(MAKE) -f $(REPO_DIR)/make/win16.mk
psp:
@$(MAKE) -f $(REPO_DIR)/make/psp.mk
haiku:
@$(MAKE) -f $(REPO_DIR)/make/haiku.mk
haiku32:
@$(MAKE) -f $(REPO_DIR)/make/haiku32.mk
beos:
@$(MAKE) -f $(REPO_DIR)/make/beos.mk
# Compile + link-check the new-port template (src/blank/blank.c) with the host # Compile + link-check the new-port template (src/blank/blank.c) with the host
# cc. No toolchain needed; keeps the template from bit-rotting as the lib grows. # cc. No toolchain needed; keeps the template from bit-rotting as the lib grows.
blank-check: blank-check:
@ -101,12 +141,21 @@ status:
@echo " iigs: $(if $(HAVE_IIGS),yes,NO)" @echo " iigs: $(if $(HAVE_IIGS),yes,NO)"
@echo " amiga: $(if $(HAVE_AMIGA),yes,NO)" @echo " amiga: $(if $(HAVE_AMIGA),yes,NO)"
@echo " atarist: $(if $(HAVE_ATARIST),yes,NO)" @echo " atarist: $(if $(HAVE_ATARIST),yes,NO)"
@echo " ste: $(if $(HAVE_STE),yes,NO)"
@echo " dos: $(if $(HAVE_DOS),yes,NO)" @echo " dos: $(if $(HAVE_DOS),yes,NO)"
@echo " x68000: $(if $(HAVE_X68000),yes,NO)" @echo " x68000: $(if $(HAVE_X68000),yes,NO)"
@echo " dvx: $(if $(HAVE_DVX),yes,NO)" @echo " dvx: $(if $(HAVE_DVX),yes,NO)"
@echo " sdl3: $(if $(HAVE_SDL3),yes,NO)"
@echo " web: $(if $(HAVE_WEB),yes,NO)"
@echo " win32: $(if $(HAVE_WIN32),yes,NO)"
@echo " win16: $(if $(HAVE_WIN16),yes,NO)"
@echo " psp: $(if $(HAVE_PSP),yes,NO)"
@echo " haiku: $(if $(HAVE_HAIKU),yes,NO)"
@echo " haiku32: $(if $(HAVE_HAIKU32),yes,NO)"
@echo " beos: $(if $(HAVE_BEOS),yes,NO)"
help: help:
@echo "Targets: iigs amiga atarist dos x68000 dvx all clean status help" @echo "Targets: iigs amiga atarist ste dos x68000 dvx sdl3 web win32 win16 psp haiku haiku32 beos all clean status help"
@echo " iigs-disk iigs-verify (IIgs MAME visual check)" @echo " iigs-disk iigs-verify (IIgs MAME visual check)"
@echo " blank-check (host-cc smoke test of the new-port template + gnu89 lint)" @echo " blank-check (host-cc smoke test of the new-port template + gnu89 lint)"
@echo " verify (build every port, then run every gate; PORTS= subset)" @echo " verify (build every port, then run every gate; PORTS= subset)"

110
README.md
View file

@ -1,7 +1,8 @@
# JoeyLib # JoeyLib
A unified C game-development library targeting five early 16-bit A unified C game-development library targeting five early 16-bit
platforms, and one DOS desktop, from a single codebase: platforms, one DOS desktop, today's desktops and browsers, Haiku and BeOS,
and the PSP, from a single codebase:
- Apple IIgs (reference platform) - Apple IIgs (reference platform)
- Commodore Amiga (A500 / 68000 baseline) - Commodore Amiga (A500 / 68000 baseline)
@ -11,6 +12,24 @@ platforms, and one DOS desktop, from a single codebase:
- DVX (the DOS desktop GUI in `../dvxgui`: each program a windowed `.app` - DVX (the DOS desktop GUI in `../dvxgui`: each program a windowed `.app`
that can also take the whole screen, built with the DOS compiler against that can also take the whole screen, built with the DOS compiler against
DVX's SDK) DVX's SDK)
- SDL3 (a native windowed program for the machine you work on, Linux today:
the hosted core in `src/hosted` with an SDL3 backend, SDL 3 linked in
statically; sprites are interpreted)
- Web (the SDL3 port compiled to WebAssembly with Emscripten: each program
a page, its DATA packed in, saves kept in the browser)
- Win32 (Windows 95 through today: the hosted core with a backend written to
the Win32 API, built with llvm-mingw against MSVCRT.DLL, tested under Wine)
- Win16 (Windows 3.1 on a 386: the hosted core with a backend written to the
Windows 3.1 API, built with Open Watcom's Win386 target, tested on Windows
for Workgroups 3.11 in DOSBox Staging)
- Haiku and BeOS (the hosted core with a backend written to the Be API,
which Haiku reimplements: Haiku x86_64 and x86, and BeOS R5 x86, built
with gcc 2.95 against R5's own headers and libraries; each tested in a VM
under QEMU)
- PSP (homebrew for custom firmware: the SDL3 port built with pspdev, each
program an `EBOOT.PBP` in a folder for `PSP/GAME/`, the stage at 1:1 in
the 480x272 screen; tested under PPSSPP with every memory access checked
for alignment as a PSP checks it)
The Apple IIgs defines the capability ceiling. Stronger platforms coast. The Apple IIgs defines the capability ceiling. Stronger platforms coast.
Hot paths are hand-written assembly per port; the public API is C. Hot paths are hand-written assembly per port; the public API is C.
@ -53,7 +72,26 @@ packages them onto a disk image. DVX needs the `dvx` installer component,
which unpacks DVX and its SDK from a DVX tree's distribution, `dist/dvx.zip` which unpacks DVX and its SDK from a DVX tree's distribution, `dist/dvx.zip`
and `dist/sdk.zip` (`./install.sh --dvx-dir PATH install dvx`; the default and `dist/sdk.zip` (`./install.sh --dvx-dir PATH install dvx`; the default
is `../dvxgui`); its examples land in `build/dvx/bin/apps/joeylib/<name>/`, is `../dvxgui`); its examples land in `build/dvx/bin/apps/joeylib/<name>/`,
laid out as they install in DVX. laid out as they install in DVX. SDL3 needs the `sdl3` component
(`./install.sh install toolchain:sdl3`), which builds SDL 3 from its release
source; its examples are native programs in `build/sdl3/bin/`, and running
one takes seconds rather than an emulator's minutes. The web port needs the
`web` components (`./install.sh install toolchain:web`: Emscripten through
emsdk, and SDL 3 built with it); its examples are pages in
`build/web/bin/<NAME>/`. The Win32 port needs `toolchain:win32` (llvm-mingw)
and, to run its programs, `emulator:win32` (a portable Wine). The Win16 port
needs `toolchain:win16` (Open Watcom) and, to run its programs,
`emulator:win16` (Windows for Workgroups 3.11 in DOSBox Staging, set up from
your own install disc and S3 display driver). The PSP port
needs `toolchain:psp` (pspdev's prebuilt release, and SDL 3 built with it)
and, to run its programs, `emulator:psp` (PPSSPP's headless build, patched
for the gates); its examples are folders `build/psp/bin/<NAME>/` holding
`EBOOT.PBP` and `DATA/`, ready for a memory stick's `PSP/GAME/`. The Haiku
ports need `toolchain:haiku` or `toolchain:haiku32` (cross compilers built
from Haiku R1/beta6) and, to run their programs, `emulator:haiku` or
`emulator:haiku32` (a Haiku VM for QEMU); the BeOS port needs
`toolchain:beos` and `emulator:beos`, both made from your own BeOS 5
Professional CD.
Your own program does not go into this tree: it lives in a directory of its Your own program does not go into this tree: it lives in a directory of its
own whose Makefile describes it and includes `make/project.mk` and own whose Makefile describes it and includes `make/project.mk` and
@ -77,13 +115,24 @@ the emulators and their firmware:
./joey-run --port amiga draw ./joey-run --port amiga draw
./joey-run --headless --seconds 30 --snapshot draw.png --port atarist draw ./joey-run --headless --seconds 30 --snapshot draw.png --port atarist draw
./joey-run --port dvx draw # DVX in DOSBox, booting into the program ./joey-run --port dvx draw # DVX in DOSBox, booting into the program
./joey-run --port sdl3 draw # natively, in a window (no emulator)
./joey-run --port web draw # served here, opened in your browser
./joey-run --port win32 draw # under Wine
./joey-run --port win16 draw # on Windows 3.11 in DOSBox
./joey-run --port psp --headless --snapshot draw.png draw # under headless PPSSPP
./joey-run --port haiku draw # in a Haiku VM under QEMU
./joey-run --port beos draw # in a BeOS R5 VM under QEMU
``` ```
Three files are never downloaded -- the Amiga Kickstart, the Amiga A few files are never downloaded -- the Amiga Kickstart, the Amiga
`serial.device` from Workbench 3.1 and the X68000 font ROM -- so supply your `serial.device` and `lowlevel.library` from Workbench 3.1, the X68000 font
copies once with `./install.sh import PATH` ROM, the Windows for Workgroups 3.11 install disc and S3 Trio64V+ driver
(files, folders, `.zip` archives or Amiga `.adf` disk images). The manual's Getting Started chapter the Win16 port runs on, and the BeOS 5 Professional CD -- so supply your
covers `joey-run`'s options and the private-file bundle. copies once with `./install.sh import PATH` (files, folders, `.zip` or
`.7z` archives or Amiga `.adf` disk images; the Windows disc as its `.iso`,
the BeOS CD as its CloneCD `.img`).
The manual's Getting Started chapter covers `joey-run`'s options and the
private-file bundle.
## Building for a single target ## Building for a single target
@ -92,11 +141,16 @@ covers `joey-run`'s options and the private-file bundle.
make iigs make iigs
make amiga make amiga
make atarist make atarist
make ste
make dos make dos
make x68000 make x68000
make dvx make dvx
``` ```
`make atarist` builds programs for every ST; `make ste` builds the STe
variant, which uses the STe's BLiTTER, DMA sound and 4-bit palette and runs
only on an STe or Mega STe.
Every fragment also answers to a bare `clean`, and every fragment that builds Every fragment also answers to a bare `clean`, and every fragment that builds
through `make/common.mk` -- all of them except `make/iigs.mk`, which assembles through `make/common.mk` -- all of them except `make/iigs.mk`, which assembles
its own clang flags -- honors `EXTRA_CFLAGS`: its own clang flags -- honors `EXTRA_CFLAGS`:
@ -114,9 +168,23 @@ logs a surface hash per op. `tools/diff-uber-hashes <reference-log> <test-log>`
compares two `joeylog.txt` captures and exits non-zero on any mismatch. The compares two `joeylog.txt` captures and exits non-zero on any mismatch. The
frozen references live in `tests/goldens/uber/`. All five ports currently agree frozen references live in `tests/goldens/uber/`. All five ports currently agree
on all 51 hashes; the X68000 has no golden of its own and is diffed against on all 51 hashes; the X68000 has no golden of its own and is diffed against
`tests/goldens/uber/iigs.txt`, which it matches exactly, and DVX, which shows `tests/goldens/uber/iigs.txt`, which it matches exactly, and DVX, SDL3, the
the DOS stage, is diffed against `tests/goldens/uber/dos.txt` web and the PSP, which share the DOS stage, are diffed against
(`scripts/bench-dvx.sh`, then `tools/diff-uber-hashes`): `tests/goldens/uber/dos.txt` (`scripts/bench-dvx.sh`, `scripts/bench-sdl3.sh`,
`scripts/bench-web.sh` or `scripts/bench-psp.sh`, then
`tools/diff-uber-hashes`). SDL3's run needs no emulator and no X server
(SDL's dummy drivers) and takes about fifteen seconds; the web's runs UBER's
page in headless Chromium; the PSP's runs UBER under headless PPSSPP in a few
seconds, with every memory access checked as a PSP checks it, so an unaligned
16- or 32-bit access anywhere fails it:
```
scripts/bench-sdl3.sh && tools/diff-uber-hashes tests/goldens/uber/dos.txt build/sdl3/bin/joeylog.txt
scripts/bench-web.sh && tools/diff-uber-hashes tests/goldens/uber/dos.txt build/web/bin/UBER/joeylog.txt
scripts/bench-psp.sh && tools/diff-uber-hashes tests/goldens/uber/dos.txt build/psp/bin/UBER/joeylog.txt
```
The X68000 has gates of its own:
``` ```
make -f make/x68000.mk x68000-verify-golden # ~1 min under the patched MAME make -f make/x68000.mk x68000-verify-golden # ~1 min under the patched MAME
@ -144,6 +212,11 @@ src/generic/ portable-C default for every overridable op
src/codegen/ shared sprite-codegen staging / compile machinery src/codegen/ shared sprite-codegen staging / compile machinery
src/<machine>/ per-machine HAL + per-CPU sprite emitter src/<machine>/ per-machine HAL + per-CPU sprite emitter
(iigs, amiga, atarist, dos, x68000, dvx) (iigs, amiga, atarist, dos, x68000, dvx)
src/hosted/ the hosted core (desktop OSes and browsers: RGB
present, virtual frame clock, input events, software
mixer) and its backends (src/hosted/sdl3, which the
sdl3, web and psp ports all build; src/hosted/win32;
src/hosted/win16)
src/m68k/ 68k code shared across machines (planar and word- src/m68k/ 68k code shared across machines (planar and word-
interleaved sprite emitters; surface68k.s, which is interleaved sprite emitters; surface68k.s, which is
linked by Amiga and Atari ST only) linked by Amiga and Atari ST only)
@ -217,7 +290,7 @@ void jlRandomSeed (uint32_t seed);
All surfaces are 320x200 16-color images with a 200-entry SCB table All surfaces are 320x200 16-color images with a 200-entry SCB table
and 16 palettes of 16 `$0RGB` colors. In-memory storage is and 16 palettes of 16 `$0RGB` colors. In-memory storage is
target-native: chunky 4bpp packed on IIgs, DOS and DVX, native planar target-native: chunky 4bpp packed on IIgs, DOS, DVX, SDL3, the web and the PSP, native planar
(separate bitplanes on Amiga and Sharp X68000, word-interleaved planes (separate bitplanes on Amiga and Sharp X68000, word-interleaved planes
on Atari ST) on the 68k ports. The public API speaks in color indices on Atari ST) on the 68k ports. The public API speaks in color indices
(0..15) and hides the storage format. (0..15) and hides the storage format.
@ -678,7 +751,10 @@ from compiler-predefined macros is a fallback. Game code can
conditionally compile on these: conditionally compile on these:
``` ```
JOEYLIB_PLATFORM_IIGS / _AMIGA / _ATARIST / _DOS / _X68000 / _DVX // exactly one defined JOEYLIB_PLATFORM_IIGS / _AMIGA / _ATARIST / _DOS / _X68000 / _DVX / _HOSTED // exactly one defined
JOEYLIB_HOSTED_SDL3 / _WIN32 / _WIN16 // the hosted backend
JOEYLIB_ATARI_STE // with _ATARIST: the STe build (make ste)
JOEYLIB_SPRITE_INTERPRETED // no sprite code emitter (hosted, blank)
JOEYLIB_CPU_65816 / _68000 / _X86 JOEYLIB_CPU_65816 / _68000 / _X86
JOEYLIB_ENDIAN_LITTLE / _BIG JOEYLIB_ENDIAN_LITTLE / _BIG
JOEYLIB_NATIVE_CHUNKY / _NATIVE_PLANAR JOEYLIB_NATIVE_CHUNKY / _NATIVE_PLANAR
@ -690,4 +766,12 @@ JOEYLIB_VERSION_MAJOR / _MINOR / _PATCH / _STRING
## License ## License
TBD. JoeyLib is distributed under the MIT License ([LICENSE.md](LICENSE.md)).
A program built with it has JoeyLib compiled in, so it carries JoeyLib's
copyright and permission notice, in its documentation for instance. Each
of JoeyLib's source files opens with a short header that says so
(`SPDX-License-Identifier: MIT`); a new file gets the same.
The components JoeyLib depends on, their licenses and what a shipped
program owes them are in [LICENSES.md](LICENSES.md). The patches in
`installer/patches/` are under the licenses of the projects they patch.

View file

@ -175,8 +175,8 @@ deactivates.
[WARNING] [WARNING]
==== ====
This is called from the audio engine's refill context -- the main thread on DOS This is called from the audio engine's refill context -- the main thread on DOS,
and ST (on DVX, DVX's own sound pump, while the program is yielded), but the ST and SDL3 (on DVX, DVX's own sound pump, while the program is yielded), but the
*audio interrupt* on Amiga and IIgs. It must not block and must not allocate. *audio interrupt* on Amiga and IIgs. It must not block and must not allocate.
==== ====
@ -275,6 +275,7 @@ What each port can actually do:
all audio at once. all audio at once.
|DOS, ST |Ignored. Output is mono. |DOS, ST |Ignored. Output is mono.
|DVX |All three, through DVX's stereo mixer (on a stereo card). |DVX |All three, through DVX's stereo mixer (on a stereo card).
|SDL3 |All three: the port mixes in stereo.
|=== |===
=== jlAudioStopSfx === jlAudioStopSfx
@ -304,7 +305,8 @@ call. Designed for AGI-era music where the engine programs a divisor and lets
the chip play, so CPU cost during playback is zero. Single voice; uses voice 0 the chip play, so CPU cost during playback is zero. Single voice; uses voice 0
on platforms with several oscillators. On DOS this programs PIT counter 2 and on platforms with several oscillators. On DOS this programs PIT counter 2 and
the speaker gate; on DVX it is a square tone of DVX's sound library, on the FM the speaker gate; on DVX it is a square tone of DVX's sound library, on the FM
chip when there is one. chip when there is one; on SDL3 it is voice 0 of the port's mixer at full
volume.
[cols="1,1,4", options="header"] [cols="1,1,4", options="header"]
|=== |===
@ -339,7 +341,8 @@ Mapping to hardware: DOS uses AdLib OPL2 melodic channels 0..2; the ST uses
YM2149 channels A, B and C; the Amiga uses Paula channels 0..2 looping a YM2149 channels A, B and C; the Amiga uses Paula channels 0..2 looping a
two-byte square sample; the IIgs uses Ensoniq DOC oscillators playing a two-byte square sample; the IIgs uses Ensoniq DOC oscillators playing a
resident square; DVX plays square tones of its sound library, which puts them resident square; DVX plays square tones of its sound library, which puts them
on the FM chip when there is a free voice and mixes them otherwise. on the FM chip when there is a free voice and mixes them otherwise; SDL3 mixes
square waves in software.
Voice state is sticky -- a voice keeps its last frequency until you change it Voice state is sticky -- a voice keeps its last frequency until you change it
-- and CPU cost during sustained playback is zero, because the hardware -- and CPU cost during sustained playback is zero, because the hardware
@ -351,7 +354,8 @@ The IIgs is the exception to stickiness: each call is an approximately 80 ms
retriggered one-shot, so a note held longer must be re-asserted about once a retriggered one-shot, so a note held longer must be re-asserted about once a
frame. It also requires `jlAudioInit`, because the DOC path rides the tracker frame. It also requires `jlAudioInit`, because the DOC path rides the tracker
engine. On DOS, ST and Amiga this is direct hardware programming and works engine. On DOS, ST and Amiga this is direct hardware programming and works
without `jlAudioInit`; on DVX it opens the program's sound on first use. without `jlAudioInit`; on DVX it opens the program's sound on first use. On
SDL3 the voices are mixed in software and sound only after `jlAudioInit`.
==== ====
=== jlAudioNoise === jlAudioNoise
@ -378,7 +382,9 @@ Mapping: the ST uses the YM2149 noise generator mixed onto channel C; DOS uses
the OPL2 rhythm-mode snare, leaving the three tone channels untouched; the the OPL2 rhythm-mode snare, leaving the three tone channels untouched; the
Amiga uses Paula channel 3 with an LFSR noise sample; the IIgs uses a resident Amiga uses Paula channel 3 with an LFSR noise sample; the IIgs uses a resident
noise sample on slot 3 with the same retriggered one-shot model as its tone noise sample on slot 3 with the same retriggered one-shot model as its tone
voices; DVX uses a noise tone of its sound library. voices; DVX uses a noise tone of its sound library; SDL3 mixes the YM2149's
own noise in software (its 17-bit generator, clocked at 125 kHz divided by
the pitch), so it sounds as on the ST.
[WARNING] [WARNING]
==== ====
@ -526,6 +532,11 @@ sound library, which `jlAudioVoice` and the rest go through there, may not be
called from an interrupt. `fn` may therefore do anything, but what it does called from an interrupt. `fn` may therefore do anything, but what it does
lands on the frame, not between frames. lands on the frame, not between frames.
On SDL3 the sound is mixed in program time, a few frames ahead, and `fn` is
called by the mixer between exactly the two samples where its tick falls: in
program time, so it may do anything, yet a note it starts begins at the right
place in the sound. `hz` may be anything up to the mixer's 44100.
=== jlAudioCriticalEnter / jlAudioCriticalExit === jlAudioCriticalEnter / jlAudioCriticalExit
[source,c] [source,c]
@ -537,7 +548,7 @@ void jlAudioCriticalExit(void);
Critical section against the tick interrupt. If you mutate state that the Critical section against the tick interrupt. If you mutate state that the
registered tick callback reads, wrap the mutation in these so the interrupt registered tick callback reads, wrap the mutation in these so the interrupt
cannot observe a half-written value. On DOS this is `cli` and `sti`; on ports cannot observe a half-written value. On DOS this is `cli` and `sti`; on ports
with no audio interrupt, and on DVX, where the callback runs in program time, with no audio interrupt, and on DVX and SDL3, where the callback runs in
both are no-ops. program time, both are no-ops.
*Parameters:* none. *Returns:* nothing. *Parameters:* none. *Returns:* nothing.

View file

@ -18,7 +18,8 @@ typedef struct {
|`codegenBytes` |`codegenBytes`
|`uint32_t` |`uint32_t`
|Size of the runtime compiled-sprite cache. `0` selects a per-platform |Size of the runtime compiled-sprite cache. `0` selects a per-platform
default: 8 KB on IIgs, 32 KB on Amiga, ST, DOS and DVX. On the IIgs the cache is default: 8 KB on IIgs, 32 KB on Amiga, ST, DOS and DVX (SDL3 interprets every
sprite and leaves the cache unused). On the IIgs the cache is
one Memory Manager block that may not span a 64 KB bank boundary, so values one Memory Manager block that may not span a 64 KB bank boundary, so values
above 65536 are clamped to 65536, and even a clamped request can fail if no above 65536 are clamped to 65536, and even a clamped request can fail if no
free bank exists. Size it against `jlSpriteCompiledSize()`. free bank exists. Size it against `jlSpriteCompiledSize()`.
@ -79,7 +80,9 @@ const char *jlPlatformName(void);
*Parameters:* none. *Parameters:* none.
*Returns:* a human-readable platform identifier, for example `"Apple IIgs"`, *Returns:* a human-readable platform identifier, for example `"Apple IIgs"`,
`"MS-DOS"` or `"DVX"`. Library-owned. `"MS-DOS"`, `"DVX"`, `"SDL3"` (the web port is the SDL3 port in a browser) or
`"Windows"`.
Library-owned.
=== jlVersionString === jlVersionString
@ -196,7 +199,7 @@ uint16_t jlFrameHz(void);
*Returns:* the nominal display frame rate in Hz -- 50 on Amiga PAL, 60 on IIgs *Returns:* the nominal display frame rate in Hz -- 50 on Amiga PAL, 60 on IIgs
and ST NTSC, 55 on the X68000, 70 on VGA mode 13h and on DVX, whose window has and ST NTSC, 55 on the X68000, 70 on VGA mode 13h and on DVX, whose window has
a virtual 70 Hz (and whose full screen is mode 13h's, or a VBE mode's, with the a virtual 70 Hz (and whose full screen is mode 13h's, or a VBE mode's, with the
same frame count). The X68000 times its display at `jlInit` and rounds to the same frame count), and 60 under SDL3, whose window has a virtual 60 Hz. The X68000 times its display at `jlInit` and rounds to the
nearest whole number: 55.46 Hz on the machine, 56.07 Hz under MAME, which nearest whole number: 55.46 Hz on the machine, 56.07 Hz under MAME, which
therefore reports 56. The real cadence may drift slightly; this is the figure therefore reports 56. The real cadence may drift slightly; this is the figure
to divide by when converting frames to seconds. to divide by when converting frames to seconds.
@ -208,8 +211,8 @@ to divide by when converting frames to seconds.
uint32_t jlMillisElapsed(void); uint32_t jlMillisElapsed(void);
---- ----
Monotonic millisecond counter since `jlInit`. DOS, ST, X68000 and DVX read a Monotonic millisecond counter since `jlInit`. DOS, ST, X68000, DVX and SDL3 read a
real hardware timer; IIgs and Amiga derive it from the frame counter, so the real timer; IIgs and Amiga derive it from the frame counter, so the
value steps at frame granularity there. Two calls separated by a long render report the true value steps at frame granularity there. Two calls separated by a long render report the true
elapsed time, not the number of vertical blanks that fired. elapsed time, not the number of vertical blanks that fired.

View file

@ -74,8 +74,9 @@ int jlInputGetChar(void);
Pops the next typed character. Shift, caps lock and the keyboard layout have Pops the next typed character. Shift, caps lock and the keyboard layout have
already been applied by the backend, so punctuation and shifted symbols arrive already been applied by the backend, so punctuation and shifted symbols arrive
correctly. The layout is the machine's own on IIgs, Amiga, ST and X68000, and correctly. The layout is the machine's own on IIgs, Amiga, ST and X68000,
DVX's own on DVX; the DOS port translates with a fixed US layout. DVX's own on DVX and the operating system's on SDL3; the DOS port translates
with a fixed US layout.
Arrow keys are not characters and stay on the predicate API. Arrow keys are not characters and stay on the predicate API.
@ -138,11 +139,13 @@ bool jlMousePresent(void);
*Parameters:* none. *Parameters:* none.
*Returns:* `true` if the platform confirmed a mouse at init. On DOS that means *Returns:* `true` if the platform confirmed a mouse at init. On DOS that means
the INT 33h driver reset successfully; on Amiga, ST, IIgs, X68000 and DVX the the INT 33h driver reset successfully; on Amiga, ST, IIgs, X68000, DVX and
OS mouse is always wired. On DVX the position is the pointer's over the SDL3 the OS mouse is always wired. On DVX the position is the pointer's over
program's window, divided by the window's scale; it keeps its last value the program's window, divided by the window's scale; it keeps its last value
while the pointer is elsewhere. On DVX's full screen it is the pointer's while the pointer is elsewhere. On DVX's full screen it is the pointer's
place on the stage (DVX draws no pointer there). place on the stage (DVX draws no pointer there). On SDL3 it is the pointer's
place on the stage however the window scales it, held to the stage's edge
while the pointer is beside it; the OS pointer is hidden over the window.
=== jlMouseX / jlMouseY === jlMouseX / jlMouseY
@ -155,6 +158,8 @@ int16_t jlMouseY(void);
*Parameters:* none. *Parameters:* none.
*Returns:* pointer position in surface coordinates, 0..319 and 0..199. *Returns:* pointer position in surface coordinates, 0..319 and 0..199.
Until the platform reports the pointer, it is the middle of the stage,
(160, 100), on every port.
=== jlMouseDown / jlMousePressed / jlMouseReleased === jlMouseDown / jlMousePressed / jlMouseReleased
@ -188,7 +193,8 @@ bool jlJoystickConnected(jlJoystickE js);
*Returns:* `true` if the platform reports a stick on that port. On the ST and *Returns:* `true` if the platform reports a stick on that port. On the ST and
X68000 both ports always report one: an empty port cannot be told from a stick X68000 both ports always report one: an empty port cannot be told from a stick
at rest. at rest. The Amiga (`lowlevel.library`) has the same blind spot the other
way: it reports a stick only once it has moved, and never a mouse.
=== jlJoystickX / jlJoystickY === jlJoystickX / jlJoystickY
@ -258,7 +264,9 @@ the new centre, so the user must be holding the stick centred when you call it.
On Amiga, ST and DOS the sticks are genuinely digital and already report -1, 0 On Amiga, ST and DOS the sticks are genuinely digital and already report -1, 0
or +1, so recalibration is a no-op and `deadZone` is ignored. DVX's sticks are or +1, so recalibration is a no-op and `deadZone` is ignored. DVX's sticks are
analog but calibrated, dead zone included, in DVX's own Control Panel, so the analog but calibrated, dead zone included, in DVX's own Control Panel, so the
call is a no-op there too. The call still call is a no-op there too. SDL3's sticks are gamepads the OS calibrates; there
the call only sets the dead zone, inside which the stick reads as centred.
The call still
clears any auto-disconnect state, so it is safe and correct to make it clears any auto-disconnect state, so it is safe and correct to make it
unconditionally. unconditionally.
==== ====

View file

@ -22,11 +22,13 @@ DOS uses an interrupt-driven 8250/16550 UART; the Amiga uses `serial.device`;
the ST goes through the BIOS Aux channel; the X68000 transmits through IOCS the ST goes through the BIOS Aux channel; the X68000 transmits through IOCS
and receives on its own SCC interrupt; DVX goes through DVX's serial library, and receives on its own SCC interrupt; DVX goes through DVX's serial library,
which owns the COM ports for every program on the desktop (a port another which owns the COM ports for every program on the desktop (a port another
program has open cannot be opened). program has open cannot be opened); Win32 and Win16 go through Windows' own
communications calls, whose driver owns the ports the same way. SDL3, the web
and the PSP have no serial port: `jlSerialOpen` fails there.
The model is *non-blocking and buffered*. Received bytes accumulate in a The model is *non-blocking and buffered*. Received bytes accumulate in a
background ring -- a hardware interrupt on DOS, the X68000 and the IIgs, the background ring -- a hardware interrupt on DOS, the X68000 and the IIgs, the
OS on Amiga, ST and DVX -- and reads never block. Call `jlSerialPoll` once per OS on Amiga, ST, DVX and Windows -- and reads never block. Call `jlSerialPoll` once per
frame: it is next to a no-op where the interrupt or OS already fills the ring, frame: it is next to a no-op where the interrupt or OS already fills the ring,
and the hardware drain where nothing does, so calling it every frame is always and the hardware drain where nothing does, so calling it every frame is always
correct. On DVX it also gives the other programs their turn correct. On DVX it also gives the other programs their turn
@ -61,6 +63,7 @@ at 9600 baud, so:
|DOS, 16550A UART |16 bytes, interrupt at 14 |~2 ms from the interrupt |DOS, 16550A UART |16 bytes, interrupt at 14 |~2 ms from the interrupt
|DOS, 8250 or 16450 UART |1 byte |~1 ms |DOS, 8250 or 16450 UART |1 byte |~1 ms
|DVX |as DOS: DVX's library drives the same UARTs |as DOS |DVX |as DOS: DVX's library drives the same UARTs |as DOS
|Win32, Win16 |the UART's; Windows' driver empties it into a 4 KB queue |as DOS
|Amiga (Paula) |1 byte |~1 ms |Amiga (Paula) |1 byte |~1 ms
|Atari ST (68901 MFP) |1 byte |~1 ms |Atari ST (68901 MFP) |1 byte |~1 ms
|X68000 (Zilog 8530) |3 bytes |~3 ms |X68000 (Zilog 8530) |3 bytes |~3 ms
@ -151,8 +154,13 @@ typedef struct {
The IIgs is the machine with three device choices; elsewhere `JL_SERIAL_MODEM` The IIgs is the machine with three device choices; elsewhere `JL_SERIAL_MODEM`
and `JL_SERIAL_PRINTER` both mean the default port. `JL_SERIAL_DEFAULT` selects and `JL_SERIAL_PRINTER` both mean the default port. `JL_SERIAL_DEFAULT` selects
the IIgs modem port, DOS or DVX COM1, the ST Modem port, Amiga unit 0 or the the IIgs modem port, COM1 on DOS, DVX, Win32 and Win16, the ST Modem port,
X68000's RS-232C port. Amiga unit 0 or the X68000's RS-232C port.
On Win16 a `baud` above 57600 runs at 115200 through KPCOMM.DRV, the
communications driver JoeyLib's Windows runs with in place of Windows 3.1's
own (the `kpcomm` installer component, built from the mscomm project). On a
Windows with its own COMM.DRV, which has no 115200, it runs at 57600.
On the X68000 the serial add-on *requires* Human68k's RS-232C driver, On the X68000 the serial add-on *requires* Human68k's RS-232C driver,
RSDRV.SYS. Every Human68k system disk has it and the stock CONFIG.SYS loads RSDRV.SYS. Every Human68k system disk has it and the stock CONFIG.SYS loads
@ -165,8 +173,8 @@ fills the receive ring. 38400 is really 39062 bps, 1.7% fast, within the
usual tolerance of a UART at the far end. usual tolerance of a UART at the far end.
`unit` disambiguates `JL_SERIAL_SLOT` and is ignored otherwise: an IIgs Super `unit` disambiguates `JL_SERIAL_SLOT` and is ignored otherwise: an IIgs Super
Serial Card slot 1..7, a DOS or DVX COM number 1..4, or an Amiga Serial Card slot 1..7, a DOS or DVX COM number 1..4, a Win16 COM number
`serial.device` unit. 1..9, a Win32 COM number 1..255, or an Amiga `serial.device` unit.
=== jlSerialOpen === jlSerialOpen
@ -209,6 +217,10 @@ door returning to its BBS, or a terminal program exiting while the call stays
up. RTS is not part of that promise; on the Amiga, `serial.device` puts back up. RTS is not part of that promise; on the Amiga, `serial.device` puts back
whatever RTS was before the open. whatever RTS was before the open.
Windows cannot make the promise. On Win32 and Win16 the close gives the port
back to Windows' driver, and neither has a call that keeps DTR up past it. A
Windows program that must not hang up the line keeps the port open.
To hang up, drop DTR first: call `jlSerialSetDtr(false)`, wait longer than To hang up, drop DTR first: call `jlSerialSetDtr(false)`, wait longer than
the modem needs to notice (a Hayes modem's S25 setting, 50 ms by default), the modem needs to notice (a Hayes modem's S25 setting, 50 ms by default),
then close. The line stays down. then close. The line stays down.

View file

@ -171,8 +171,8 @@
|The character queue holds 31 entries and drops the rest. Pop it every frame. |The character queue holds 31 entries and drops the rest. Pop it every frame.
|Music plays but `jlAudioVoice` does nothing |Music plays but `jlAudioVoice` does nothing
|On ST and Amiga the module player owns those channels. Use one layer per |On ST and Amiga the module player owns those channels (in the ST build; the
scene. STe build plays modules through the DMA sound chip). Use one layer per scene.
|A note sounds for only a fraction of a second on the IIgs |A note sounds for only a fraction of a second on the IIgs
|`jlAudioVoice` is a roughly 80 ms one-shot there. Re-assert it about once a |`jlAudioVoice` is a roughly 80 ms one-shot there. Re-assert it about once a

View file

@ -293,8 +293,9 @@ $(call programDataDir,MYGAME)/font.tbk: assets/font.png
---- ----
Tile banks and `.spc` files differ per platform, while `.spr`, `.jym` and Tile banks and `.spc` files differ per platform, while `.spr`, `.jym` and
`.sfx` files are shared: `ASSET_PLATFORM` names the target a bake is for (DVX `.sfx` files are shared: `ASSET_PLATFORM` names the target a bake is for (DVX,
takes the DOS bakes) and `SPRITEBAKE` the matching host `spritebake`. SDL3 and the web take the DOS bakes; the last two use only a `.spc`'s cels, not
their code) and `SPRITEBAKE` the matching host `spritebake`.
`examples/tilebank` is a working reference: one rule in `make/examples.mk` `examples/tilebank` is a working reference: one rule in `make/examples.mk`
bakes the same PNG for each target into its `DATA/tilebank` (`TILEBANK_DATA`), bakes the same PNG for each target into its `DATA/tilebank` (`TILEBANK_DATA`),

View file

@ -45,7 +45,7 @@ directory -- the paths in the Makefile are relative to it -- or with `make -C`:
[source,console] [source,console]
---- ----
$ make # every target whose toolchain is installed $ make # every target whose toolchain is installed
$ make dos # one target: iigs amiga atarist dos x68000 dvx $ make dos # one target: iigs amiga atarist ste dos x68000 dvx
$ make clean # the project's build/ (clean-dos: one target's) $ make clean # the project's build/ (clean-dos: one target's)
$ make help $ make help
---- ----
@ -65,11 +65,21 @@ The project's outputs land in its own `build/`, laid out like JoeyLib's:
`build/iigs/data/MYGAME/`, and with `MYGAME_IIGS_GAME_DISK` the disks `build/iigs/data/MYGAME/`, and with `MYGAME_IIGS_GAME_DISK` the disks
`build/iigs/bin/MYGAME.2mg` and `MYGAME-data.2mg` `build/iigs/bin/MYGAME.2mg` and `MYGAME-data.2mg`
|Amiga |`build/amiga/bin/Mygame` |Amiga |`build/amiga/bin/Mygame`
|Atari ST |`build/atarist/bin/MYGAME.PRG` |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 |MS-DOS |`build/dos/bin/MYGAME.EXE`, with the DPMI server built in
|Sharp X68000 |`build/x68000/bin/MYGAME.X` |Sharp X68000 |`build/x68000/bin/MYGAME.X`
|DVX |`build/dvx/bin/apps/joeylib/mygame/`: `mygame.app`, `mygame.hlp` and its |DVX |`build/dvx/bin/apps/joeylib/mygame/`: `mygame.app`, `mygame.hlp` and its
`DATA/` `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)
|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 A program with `MYGAME_FOLDER` set ships in a folder of its own with its
@ -122,10 +132,12 @@ probes for gates).
|`ID_PORTS` |The targets it builds for. Every target when unset. |`ID_PORTS` |The targets it builds for. Every target when unset.
|`ID_NAME` |Its file name without the extension (see <<_naming>>). |`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, |`ID_FOLDER` |Set: it ships in a folder of its own with its `DATA/` (Amiga,
ST, DOS, X68000; on the IIgs and DVX every program is packaged apart anyway). ST, DOS, X68000, SDL3, Win32, Win16; on the IIgs, DVX, the web and the PSP
every program is packaged apart anyway).
|`ID_BINDIR` |Build it there instead of `bin/`. |`ID_BINDIR` |Build it there instead of `bin/`.
|`ID_DATA` |Its data files (<<_data_files>>). |`ID_DATA` |Its data files (<<_data_files>>).
|`ID_TITLE` |DVX: its window title. |`ID_TITLE` |DVX: its window title. PSP: its title in the PSP's menu (by
default its name).
|`ID_HELP` |DVX: the line its help file says about it. No apostrophes. |`ID_HELP` |DVX: the line its help file says about it. No apostrophes.
|`ID_IIGS_OVERFLOW_CAP` |IIgs: link large overflow segments (`0xF000`), which |`ID_IIGS_OVERFLOW_CAP` |IIgs: link large overflow segments (`0xF000`), which
a big program needs to leave the Memory Manager room (see a big program needs to leave the Memory Manager room (see
@ -162,9 +174,11 @@ set up:
|`$(call programDataDir,ID)` |Where its `DATA/` files go on this target. |`$(call programDataDir,ID)` |Where its `DATA/` files go on this target.
|`$(call programOptionalDir,ID)` |Where the files go that it can run without |`$(call programOptionalDir,ID)` |Where the files go that it can run without
(<<_disk_images_and_packaging>>). (<<_disk_images_and_packaging>>).
|`PLATFORM` |The target: `iigs`, `amiga`, `atarist`, `dos`, `x68000`, `dvx`. |`PLATFORM` |The target: `iigs`, `amiga`, `atarist`, `ste`, `dos`, `x68000`, `dvx`, `sdl3`, `web`, `win32`, `win16`, `psp`.
|`ASSET_PLATFORM` |The target its bakes are for. DVX shows the DOS stage and |`ASSET_PLATFORM` |The target its bakes are for. DVX shows the DOS stage and
runs x86 code, so it takes the DOS bakes. runs x86 code, so it takes the DOS bakes; the hosted ports' stage (SDL3, the
web, Win32, Win16, the PSP) is the same chunky one, so they take them too
(the cels of a pre-compiled sprite bank, without their code).
|`SPRITEBAKE` |The host `spritebake` for this target (its rule is |`SPRITEBAKE` |The host `spritebake` for this target (its rule is
JoeyLib's). JoeyLib's).
|`PROJECT_DIR`, `PROJECT_BUILD` |The project and its `build/`. |`PROJECT_DIR`, `PROJECT_BUILD` |The project and its `build/`.
@ -217,6 +231,11 @@ program's id:
says otherwise |`Mygame` says otherwise |`Mygame`
|Sharp X68000 |Uppercase 8.3, `.X` |`MYGAME.X` |Sharp X68000 |Uppercase 8.3, `.X` |`MYGAME.X`
|DVX |Lowercase, 8 characters, a folder of its own |`apps/joeylib/mygame/mygame.app` |DVX |Lowercase, 8 characters, a folder of its own |`apps/joeylib/mygame/mygame.app`
|SDL3 |The id, no extension |`MYGAME`
|Web |The id, a folder of its own |`MYGAME/MYGAME.html`
|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 Keep the id to 8 characters and letters and digits only, so the same name works
@ -255,6 +274,29 @@ from `MYGAME_HELP`) and its `DATA/`. Copy that folder into a DVX installation's
`APPS\JOEYLIB\` and start it from DVX, or let `joey-run` do it `APPS\JOEYLIB\` and start it from DVX, or let `joey-run` do it
(<<_dvx_programs>>). (<<_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.
*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 no icon or
pictures) and its `DATA/`. Copy the folder into `PSP/GAME/` on a memory
stick; the PSP shows it by its `ID_TITLE`. The unstripped ELF stays in
`build/psp/elf/`, for `psp-addr2line` on an address a crash reports.
=== Verifying It Actually Runs === Verifying It Actually Runs
Build success is weak evidence on retro targets. Run it with `joey-run` (see Build success is weak evidence on retro targets. Run it with `joey-run` (see
@ -310,8 +352,14 @@ Human68k floppies, environment checks) takes paths.
|`make verify-audio` |`make verify-audio`
|Every port's audio gate: the IIgs DOC and X68000 chips are read directly, |Every port's audio gate: the IIgs DOC and X68000 chips are read directly,
the ST's YM2149 register writes are traced, and the Amiga, DOS and DVX the ST's YM2149 register writes are traced (and for the STe build the
output is recorded and graded. Exits 3, not 0, if a gate had to be skipped. 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` |`make iigs-verify`
|The IIgs actually reached the program and drew something. |The IIgs actually reached the program and drew something.

View file

@ -3,7 +3,10 @@
=== Setting Up the Toolchains === Setting Up the Toolchains
JoeyLib cross-compiles for five machines and for DVX, a DOS desktop whose JoeyLib cross-compiles for five machines and for DVX, a DOS desktop whose
programs run in windows (see <<_dvx_programs>>). It builds on Linux x86-64, programs run in windows (see <<_dvx_programs>>), builds native programs for
the machine you work on through SDL3 (see <<_sdl3_programs>>), builds web
pages through Emscripten (see <<_web_programs>>), and builds PSP homebrew
through pspdev (see <<_psp_programs>>). It builds on Linux x86-64,
and on Windows inside WSL2. One script installs every cross toolchain, pinned and on Windows inside WSL2. One script installs every cross toolchain, pinned
to a known-good version and checked against a published checksum, into to a known-good version and checked against a published checksum, into
`toolchains/` in the repository. The only things it installs anywhere else `toolchains/` in the repository. The only things it installs anywhere else
@ -42,7 +45,7 @@ install:
[source,console] [source,console]
---- ----
$ make amiga $ make amiga
make/amiga.mk:5: *** toolchain:amiga is not installed; run: ./install.sh install toolchain:amiga. Stop. make/amiga.mk:13: *** toolchain:amiga is not installed; run: ./install.sh install toolchain:amiga. Stop.
---- ----
Check what the build can see: Check what the build can see:
@ -106,7 +109,14 @@ A target is a component name from `list`, or a group:
| `toolchain:PORT` | `toolchain:PORT`
| Everything needed to build for one port: `iigs`, `amiga`, `atarist`, `dos`, | Everything needed to build for one port: `iigs`, `amiga`, `atarist`, `dos`,
`x68000` or `dvx`. `x68000`, `dvx`, `sdl3` (SDL 3, built as a static library that every SDL3
program links in, so it runs without SDL installed), `web` (Emscripten,
through emsdk, and SDL 3 built with it), `win32` (llvm-mingw; its
emulator is a portable Wine), `win16` (Open Watcom; its emulator is Windows
for Workgroups 3.11 in DOSBox Staging, set up from your own install disc, see
<<Firmware that is not downloaded>>) or `psp` (pspdev's prebuilt release,
and SDL 3 built with it; its emulator is PPSSPP's headless build, patched for
the gates).
| `emulator:PORT` | `emulator:PORT`
| Everything needed to run that port's programs: the emulator and its | Everything needed to run that port's programs: the emulator and its
@ -202,6 +212,14 @@ $ make atarist # Atari ST only
$ make dos # MS-DOS only $ make dos # MS-DOS only
$ make x68000 # Sharp X68000 only $ make x68000 # Sharp X68000 only
$ make dvx # DVX only $ make dvx # DVX only
$ make sdl3 # native programs through SDL3 only
$ make web # web pages through Emscripten only
$ make win32 # Windows programs only
$ make win16 # Windows 3.x programs only
$ make psp # PSP homebrew (EBOOT.PBP) only
$ make haiku # Haiku x86_64 programs only
$ make haiku32 # Haiku x86 (gcc 2.95, the BeOS ABI) programs only
$ make beos # BeOS R5 x86 programs only
$ make clean # remove all build outputs $ make clean # remove all build outputs
---- ----
@ -312,7 +330,8 @@ back buffer called the *stage*; nothing reaches the display until you present.
=== Running What You Built === Running What You Built
`joey-run`, at the top of the repository, starts a built program in the right `joey-run`, at the top of the repository, starts a built program in the right
emulator. The emulators, and the firmware they boot, come from the installer: emulator (an SDL3 program needs none: it runs on your machine). The emulators,
and the firmware they boot, come from the installer:
[source,console] [source,console]
---- ----
@ -335,6 +354,13 @@ $ ./joey-run build/amiga/bin/Draw
$ ./joey-run --port atarist draw $ ./joey-run --port atarist draw
$ ./joey-run build/iigs/bin/DRAW.2mg $ ./joey-run build/iigs/bin/DRAW.2mg
$ ./joey-run --port dvx draw $ ./joey-run --port dvx draw
$ ./joey-run --port sdl3 draw
$ ./joey-run --port web draw
$ ./joey-run --port win32 draw
$ ./joey-run --port win16 draw
$ ./joey-run --port psp --headless --snapshot draw.png draw
$ ./joey-run --port haiku draw
$ ./joey-run --port beos draw
---- ----
It recognises the machine from the file itself. Interactive runs use the It recognises the machine from the file itself. Interactive runs use the
@ -365,6 +391,16 @@ example the game an interpreter plays.
| `--machine rom01` | `--machine rom01`
| Apple IIgs: the ROM 01 machine instead of ROM 03. | Apple IIgs: the ROM 01 machine instead of ROM 03.
| `--machine st`
| Atari: Hatari's machine, `st`, `megast`, `ste` or `megaste`. By default an
ST-build program (`make atarist`) gets a plain ST and an STe-build one
(`make ste`) an STe; the STe build runs only on `ste` and `megaste`.
| `--machine a1200`
| Amiga: FS-UAE's machine, `a500` (the default), `a1200` (68EC020, AGA) or
`a4000` (68040, AGA), each on its own Kickstart 3.1. The AGA ones need their
Kickstarts (`./install.sh install emulator:aga`).
| `--ram SIZE` | `--ram SIZE`
| Apple IIgs: MAME's memory size. The default is `4M`. | Apple IIgs: MAME's memory size. The default is `4M`.
@ -383,8 +419,9 @@ example the game an interpreter plays.
default is 9600. default is 9600.
| `-- ARGS` | `-- ARGS`
| Pass `ARGS` to the program. DOS only: the other machines' autostart cannot | Pass `ARGS` to the program. DOS, SDL3, Win32 and Win16 only: the other
pass arguments. machines' autostart cannot pass arguments, and a page and a PSP program have
none.
|=== |===
==== DVX ==== DVX
@ -398,10 +435,86 @@ the program saves, in DVX's `CONFIG` folder, is there the next time; closing
DOSBox ends the run. When the program ends, DVX stays up with an empty DOSBox ends the run. When the program ends, DVX stays up with an empty
desktop. desktop.
A headless run with a snapshot is the quickest way to check a change: ==== SDL3
An SDL3 program is a native program, so `joey-run` simply starts it, in a
window; running the file yourself does the same. `--headless` runs it on a
private virtual display at one window pixel per stage pixel, so a
`--snapshot` is exactly the 320x200 stage. The window's size, shape and full
screen are set by environment variables (<<_sdl3_programs>>). The SDL3 port
has no serial port.
==== Web
A web program is a page: `joey-run` serves its folder over HTTP on this
machine (to this machine only) and opens it in your browser; Ctrl+C stops the
server. With `--headless` it runs in headless Chromium instead, at one canvas
pixel per stage pixel, so a `--snapshot` is the stage. Its `DATA/` is packed
in when it is built, so `--data` does not apply.
==== Win32
A Windows program runs under Wine: in a window on your display, with its
Wine settings kept in the project's `build/win32/prefix` so they are set up
once (nothing goes in `~/.wine`; a run with `--serial` uses a private one, so
the kept COM1 is left alone). The window's size, shape and full screen are
set by the same environment variables as SDL3's, and Alt+Enter switches. With
`--headless` it runs on a private virtual display at one pixel per stage
pixel, so a `--snapshot` is the stage.
==== Win16
A Windows 3.x program runs on Windows for Workgroups 3.11 in DOSBox Staging,
on a fresh copy, each run, of the Windows the installer set up from your own
disc (`./install.sh install emulator:win16`): 800x600 in 256 colours through
the S3 Trio64V+ driver, with Windows' Sound Blaster driver and two drivers
of JoeyLib's own: KPJOY.DRV, the joystick driver Windows 3.1 lacks (DOSBox's
game port, two sticks), and KPCOMM.DRV in place of Windows' COMM.DRV (COM1
up to 115200 baud). Their components, `kpjoy` and `kpcomm`, build them from
the kpjoy and mscomm projects, checkouts beside JoeyLib's (`../kpjoy`,
`../mscomm/drv`; `KPJOY_DIR` and `KPCOMM_DIR` name others). The program is
Windows' shell, so Windows ends when the program does, and its folder is
drive D:, so what it saves stays there. The window's size, shape and full
screen are set by the same environment variables as SDL3's: `joey-run` puts
them in the DOS environment Windows starts from. Alt+Enter is DOSBox's own
full-screen key, so the program switches with Alt and the keypad's Enter.
With `--headless` it runs on a private virtual display at one window pixel
per stage pixel, and a `--snapshot` is DOSBox's picture of the whole 800x600
screen.
==== PSP
A PSP program runs only with `--headless` here, under PPSSPP's headless
build (`./install.sh install emulator:psp`), from a copy of its folder on a
private memory stick, `PSP/GAME/NAME`, as on a PSP. PPSSPP checks every
memory access as a PSP does: an unaligned one stops the run, and `joey-run`
names the function it was in. A `--snapshot` is the PSP's whole 480x272
screen. To play the program, copy `build/psp/bin/NAME` into `PSP/GAME/` on
a PSP's memory stick, or open its `EBOOT.PBP` in PPSSPP. The PSP has no
serial port.
==== Haiku and BeOS
A Haiku (`haiku`, `haiku32`) or BeOS R5 (`beos`) program runs in that port's
VM under QEMU (`./install.sh install emulator:haiku`, `emulator:haiku32` or
`emulator:beos`), in QEMU's window, from a copy of its folder on a second
disk. The machine boots from a disk it never writes to, runs the program,
and powers off when the program ends; what the program wrote in its folder
(saves, its log) is then copied back. The window's size, shape and full
screen are set by the same environment variables as SDL3's. Haiku's VM has
sound; BeOS's has none, and is taken through R5's boot loader menu to its
fail-safe video mode (1024x768, 16-bit colour), as R5 has no driver for any
of QEMU's video cards. With `--headless` it runs without a window at one
window pixel per stage pixel; `--seconds` counts from when the program
starts, after the boot, and a `--snapshot` is QEMU's picture of the whole
screen. Neither has a serial port here.
A headless run with a snapshot is the quickest way to check a change, and on
SDL3 it takes seconds, not the minutes an emulated machine needs:
[source,console] [source,console]
---- ----
$ ./joey-run --headless --seconds 5 --snapshot draw.png --port sdl3 draw
$ ./joey-run --headless --seconds 30 --snapshot draw.png --port dos draw $ ./joey-run --headless --seconds 30 --snapshot draw.png --port dos draw
---- ----
@ -462,6 +575,19 @@ arrives. To connect out, `socat` joins a pseudo-terminal to the network.
| DVX | DVX
| COM1 | COM1
| As on DOS; DVX's serial library drives the port. | As on DOS; DVX's serial library drives the port.
| Win16
| COM1
| As on DOS; Windows' own communications driver drives the port.
| Win32
| COM1
| As on the ST: Wine's COM1 can only be a device, so `socat` joins a
pseudo-terminal to the network both ways.
| SDL3, Web, PSP
| None
| These ports have no serial port; `jlSerialOpen` fails there.
|=== |===
`socat` comes from your distribution: `./install.sh deps host --install` `socat` comes from your distribution: `./install.sh deps host --install`
@ -478,29 +604,38 @@ rate the program sets.
and X68000, where MAME prints `Unable to load image` and runs with the port and X68000, where MAME prints `Unable to load image` and runs with the port
unplugged. unplugged.
* While a port is listening, what the program sends waits for the connection, * While a port is listening, what the program sends waits for the connection,
except on DOS, which drops it just as a cable with nothing on the other end except on DOS, DVX and Win16, where DOSBox drops it just as a cable with
would. `examples/sertest` sends its banner at once, so on DOS a client that nothing on the other end would. `examples/sertest` sends its banner at once,
connects late sees only the echo. so there a client that connects late sees only the echo.
==== Firmware that is not downloaded ==== Firmware that is not downloaded
Almost everything the emulators need is downloaded: EmuTOS for the Atari ST, Almost everything the emulators need is downloaded: EmuTOS for the Atari ST,
the Apple IIgs ROMs, GS/OS 6.0.4 and the CFFA2 card's firmware, and Sharp's own the Apple IIgs ROMs, GS/OS 6.0.4 and the CFFA2 card's firmware, and Sharp's own
free release of the X68000 IPL-ROM and Human68k 3.02. Three files are not, free release of the X68000 IPL-ROM and Human68k 3.02. A few files are not,
because they were never released for free: the Amiga Kickstart 3.1 ROM, the because they were never released for free: the Amiga Kickstart 3.1 ROM, the
Amiga `serial.device` from Workbench 3.1 (Kickstart 3.1 has none in ROM, and Amiga `serial.device` and `lowlevel.library` from Workbench 3.1 (Kickstart
a program cannot open the serial port without it) and the X68000 CG (font) 3.1 has neither in ROM, and a program cannot open the serial port without
ROM. Supply your copies once: the one or see a joystick without the other), the A1200's and A4000's
Kickstart 3.1 (optional: only for running the Amiga programs on those
machines), the X68000 CG (font) ROM,
for the Win16 port the Windows for Workgroups 3.11 install disc (as an
`.iso`) and the S3 Trio64V+ 1.70.04 Windows 3.1 display driver, from which
the installer sets Windows up unattended, and for the BeOS port the BeOS 5
Professional CD (its CloneCD `.img`, or the `.7z` holding it), from which
the installer takes R5's headers and libraries and makes the VM. Supply your
copies once:
[source,console] [source,console]
---- ----
$ ./install.sh import ~/my-roms $ ./install.sh import ~/my-roms
---- ----
`import` takes files, folders, `.zip` archives and Amiga `.adf` disk images `import` takes files, folders, `.zip` and `.7z` archives and Amiga `.adf` disk images
(point it at your Workbench 3.1 disk for `serial.device`), identifies each (point it at your Workbench 3.1 disk for `serial.device` and
file by its checksum (the list is `installer/files.sha1`) and puts it in `lowlevel.library`, and at the S3
place. driver's `.zip` for its three files), identifies each file by its checksum
(the list is `installer/files.sha1`) and puts it in place.
A project that hands its setup to testers can host these files instead: A project that hands its setup to testers can host these files instead:
`./install.sh bundle joeylib-private.tar.gz` packs the ones present on `./install.sh bundle joeylib-private.tar.gz` packs the ones present on
@ -537,4 +672,8 @@ from its own directory against a JoeyLib checkout, as any program of yours
would (<<_building_your_program>>). would (<<_building_your_program>>).
On DVX every example is a folder of its own under `build/dvx/bin/apps/joeylib/` On DVX every example is a folder of its own under `build/dvx/bin/apps/joeylib/`
with its help file (<<_dvx_programs>>). with its help file (<<_dvx_programs>>). On SDL3 every example is a native
program in `build/sdl3/bin/`, beside the shared `DATA/` (<<_sdl3_programs>>),
on the web a page in a folder of its own, `build/web/bin/NAME/`
(<<_web_programs>>), and on the PSP a folder for `PSP/GAME/`,
`build/psp/bin/NAME/` with `EBOOT.PBP` and its `DATA/` (<<_psp_programs>>).

View file

@ -1,5 +1,5 @@
= JoeyLib Manual = JoeyLib Manual
Scott Duensing <scott.duensing@gmail.com> Scott Duensing <scott@kangaroopunch.com>
:revnumber: 1.0 :revnumber: 1.0
:revdate: 2026 :revdate: 2026
:doctype: book :doctype: book

View file

@ -3,9 +3,10 @@
=== What JoeyLib Is === What JoeyLib Is
JoeyLib is a single-codebase C game library for five 16-bit and 32-bit retro JoeyLib is a single-codebase C game library for five 16-bit and 32-bit retro
machines, and for DVX, a DOS desktop whose programs run in windows. You write machines, for DVX, a DOS desktop whose programs run in windows, and for
one program against one API, and the same source compiles and runs on all of today's desktops, browsers and the PSP through SDL3, and for Windows from
them: 3.1 on. You write one program against one API, and the same source compiles
and runs on all of them:
[cols="2,2,2,4", options="header"] [cols="2,2,2,4", options="header"]
|=== |===
@ -19,12 +20,16 @@ them:
|Commodore Amiga |Commodore Amiga
|68000 (A500 class) |68000 (A500 class)
|512 KB chip, 512 KB fast recommended |512 KB chip, 512 KB fast recommended
|OCS chipset. Native planar bitplanes. |OCS chipset. Native planar bitplanes. Also tested on an A1200 (68020,
AGA) and an A4000 (68040, AGA).
|Atari ST |Atari ST, STe, Mega STe
|68000 (STF or STE) |68000 at 8 MHz (16 MHz on a Mega STe)
|512 KB |512 KB
|Word-interleaved planar. Shares 68000 assembly with the Amiga port. |Word-interleaved planar. Shares 68000 assembly with the Amiga port. Two
builds: the ST build runs on every ST and never uses STe hardware; the STe
build (`make ste`) uses the STe's 4-bit palette, DMA sound and BLiTTER, and a
Mega STe's 16 MHz, and runs only there. See <<_the_atari_st_family>>.
|MS-DOS |MS-DOS
|386 or later |386 or later
@ -42,6 +47,42 @@ them:
|A program in a window on the DVX desktop, at 1x to 3x, or on the whole |A program in a window on the DVX desktop, at 1x to 3x, or on the whole
screen at 320x200. The MS-DOS port's stage and code; a virtual 70 Hz. See screen at 320x200. The MS-DOS port's stage and code; a virtual 70 Hz. See
<<_dvx_programs>>. <<_dvx_programs>>.
|SDL3
|whatever the host has
|whatever the host has
|A native program in a window (Linux today), scaled to fit at 4:3 or with
square pixels, or on the whole screen. Sprites are interpreted; a virtual
60 Hz. The fast way to try a change without an emulator. See
<<_sdl3_programs>>.
|Web
|the browser's
|the browser's
|The SDL3 port compiled to WebAssembly: a program is a web page anyone can
open. See <<_web_programs>>.
|Win32
|386 or later
|what Windows needs
|A Windows program for Windows 95 through today: the hosted core with a
backend written to the Win32 API. See <<_windows_programs>>.
|Win16
|386 or later
|what Windows 3.1 in 386 enhanced mode needs
|A Windows 3.x program: the hosted core with a backend written to the
Windows 3.1 API, in 32-bit code through Open Watcom's Win386 extender; 8-bit
indexed, so every palette is exact on a 256-colour display. See
<<_windows_programs>>.
|PSP
|MIPS Allegrex at 222 MHz
|32 MB (PSP-1000)
|PSP homebrew, for custom firmware and PPSSPP: the SDL3 port built with
pspdev. The stage sits at 1:1 in the middle of the 480x272 screen; the
d-pad, nub and buttons are joystick 0, Start is Return and Select Escape.
See <<_psp_programs>>.
|=== |===
The Apple IIgs is deliberately the slowest target and the design reference. If The Apple IIgs is deliberately the slowest target and the design reference. If
@ -75,7 +116,7 @@ that out of your program:
|=== |===
|Platform |In-memory pixel storage |Platform |In-memory pixel storage
|Apple IIgs, MS-DOS, DVX |Apple IIgs, MS-DOS, DVX, SDL3, Web, PSP
|Chunky 4bpp packed: two pixels per byte, high nibble is the left pixel. |Chunky 4bpp packed: two pixels per byte, high nibble is the left pixel.
|Commodore Amiga |Commodore Amiga
@ -109,6 +150,19 @@ documented and flagged in this manual -- see <<_writing_portable_code>>.
* A deterministic, seedable random generator that produces *bit-identical* * A deterministic, seedable random generator that produces *bit-identical*
output on every port for a given seed output on every port for a given seed
=== License
JoeyLib is distributed under the MIT License (`LICENSE.md`). A program built
with it has JoeyLib compiled in, so it carries JoeyLib's copyright and
permission notice, in its documentation for instance. A program also carries
code from the libraries each port links (libxmp-lite for music on most
ports, the toolchains' C libraries and start files), whose terms
`LICENSES.md` lists with what a shipped program owes them. On the Atari ST
that includes MiNTLib's LGPL parts: a closed-source game lets its users
relink it against a changed MiNTLib (by shipping its object files, for
instance). For Windows 3.x, see the Win16 port's "Shipping" note in
<<_windows_programs>>.
=== How to Read This Manual === How to Read This Manual
If you are new to JoeyLib, read <<_getting_started>>, then If you are new to JoeyLib, read <<_getting_started>>, then

View file

@ -1,7 +1,7 @@
== Writing Portable Code == Writing Portable Code
A JoeyLib program that follows the rules in this chapter compiles and behaves A JoeyLib program that follows the rules in this chapter compiles and behaves
the same on all five machines and on DVX. Most of the rules exist because one the same on all five machines, on DVX, under SDL3, in a browser and on Windows. Most of the rules exist because one
particular target cannot do something the others can, and the Apple IIgs is particular target cannot do something the others can, and the Apple IIgs is
usually that target. usually that target.
@ -178,7 +178,10 @@ hardware:
On the Atari ST and Amiga, the tone voices *are* the same hardware the module On the Atari ST and Amiga, the tone voices *are* the same hardware the module
player drives. While a `.MOD` is playing, `jlAudioVoice` writes fight the player drives. While a `.MOD` is playing, `jlAudioVoice` writes fight the
player's register writes and lose. Choose the module layer or the voice and player's register writes and lose. Choose the module layer or the voice and
tracker layer *per scene*, not both at once. tracker layer *per scene*, not both at once. (The STe build plays modules and
sound effects through the STe's DMA sound chip instead, so there the voices
keep the YM2149 to themselves -- but a program that also ships the ST build
still has to follow the rule.)
==== ====
The chip tracker is the portable choice for music. It costs almost nothing on The chip tracker is the portable choice for music. It costs almost nothing on
@ -199,9 +202,9 @@ error.
The API is uniform; these are the places where what you get differs. The API is uniform; these are the places where what you get differs.
[cols="2,2,2,2,2,2,2", options="header"] [cols="2,2,2,2,2,2,2,2,2", options="header"]
|=== |===
|Feature |IIgs |Amiga |Atari ST |MS-DOS |X68000 |DVX |Feature |IIgs |Amiga |Atari ST |MS-DOS |X68000 |DVX |SDL3, Web, Win32, PSP, Haiku, BeOS |Win16
|Frame rate |Frame rate
|60 Hz |60 Hz
@ -210,6 +213,8 @@ The API is uniform; these are the places where what you get differs.
|70 Hz |70 Hz
|55 Hz (56 under MAME) |55 Hz (56 under MAME)
|70 Hz (virtual; the real retrace on the whole screen) |70 Hz (virtual; the real retrace on the whole screen)
|60 Hz (virtual)
|60 Hz (virtual)
|Pixel storage |Pixel storage
|chunky 4bpp |chunky 4bpp
@ -218,6 +223,18 @@ The API is uniform; these are the places where what you get differs.
|chunky 4bpp |chunky 4bpp
|text-plane planar |text-plane planar
|chunky 4bpp |chunky 4bpp
|chunky 4bpp
|chunky 4bpp
|Sprites
|compiled
|compiled
|compiled
|compiled
|compiled
|compiled
|interpreted
|interpreted
|Stereo pan |Stereo pan
|all three |all three
@ -226,6 +243,8 @@ The API is uniform; these are the places where what you get differs.
|ignored (mono) |ignored (mono)
|ignored |ignored
|all three |all three
|all three
|ignored (mono)
|`jlAudioTone` |`jlAudioTone`
|DOC oscillator |DOC oscillator
@ -234,6 +253,8 @@ The API is uniform; these are the places where what you get differs.
|PIT counter 2 |PIT counter 2
|- |-
|a DVX tone (FM chip or mixer) |a DVX tone (FM chip or mixer)
|voice 0 of the mixer
|voice 0 of the mixer
|Joystick |Joystick
|analog, auto-disables |analog, auto-disables
@ -242,6 +263,8 @@ The API is uniform; these are the places where what you get differs.
|digital |digital
|digital |digital
|analog (DVX calibrates) |analog (DVX calibrates)
|the OS's gamepads or joysticks (OS calibrates); the PSP's own controls
|Windows' joysticks (Control Panel calibrates)
|Keyboard layout |Keyboard layout
|machine's own |machine's own
@ -250,6 +273,8 @@ The API is uniform; these are the places where what you get differs.
|fixed US |fixed US
|machine's own |machine's own
|DVX's |DVX's
|the OS's; the PSP has no keyboard
|Windows'
|Serial ports |Serial ports
|modem, printer, slot card |modem, printer, slot card
@ -258,6 +283,8 @@ The API is uniform; these are the places where what you get differs.
|COM1..COM4 |COM1..COM4
|- |-
|COM1..COM4 (DVX's library) |COM1..COM4 (DVX's library)
|Win32: COM1 and up; the others -
|COM1..COM9
|=== |===
The joystick row deserves a note: the IIgs port *auto-disables* joystick The joystick row deserves a note: the IIgs port *auto-disables* joystick
@ -271,6 +298,27 @@ empty port cannot be told from a stick at rest. `JOY_BUTTON_0` is a stick's
trigger A and `JOY_BUTTON_1` its trigger B. Holding both directions of an axis trigger A and `JOY_BUTTON_1` its trigger B. Holding both directions of an axis
reads as the positive one (right, down), as on the Amiga and ST. reads as the positive one (right, down), as on the Amiga and ST.
On the ST, `JOYSTICK_0` is port 1, the joystick port, and `JOYSTICK_1` port 0.
JoeyLib keeps TOS's keyboard-processor mode, in which port 0 is the mouse's:
the ST reports no stick movement there, so `JOYSTICK_1` stays at rest whatever
is plugged in. Port 1's fire button is the same line as the mouse's right
button, so a press reads as both `JOY_BUTTON_0` and `MOUSE_BUTTON_RIGHT`.
On the Amiga the sticks are read through `lowlevel.library`, which Kickstart
3.1 does not have in ROM: AmigaOS loads it from `LIBS:`, so the boot drive must
carry Workbench's `Libs/lowlevel.library`, or no stick is seen. `joey-run` puts
the installer's copy there (component `amigaLowlevel`); a game shipped to boot
on its own must do the same. `lowlevel.library` reports a stick only once it
has moved, and never a mouse. It also checks each port again now and then, and
a two-button stick with both buttons held can read as nothing at that moment,
so once a port has shown a stick JoeyLib keeps it one; `jlJoystickReset` hands
the port back to `lowlevel.library`'s own detection.
On DOS the game port's counts depend on the stick and on the CPU's speed, so
the first reading after `jlInit` or `jlJoystickReset` is taken as the stick's
rest, and a push past half that value either way reads as a full push. Call
`jlJoystickReset` with the stick centred if it was not at the start.
The X68000's display refreshes at 55.46 Hz. `jlFrameHz` times it when the The X68000's display refreshes at 55.46 Hz. `jlFrameHz` times it when the
program starts and rounds to the nearest whole number, so it reports 55 -- program starts and rounds to the nearest whole number, so it reports 55 --
and 56 under MAME, whose X68000 display runs slightly fast (56.07 Hz). and 56 under MAME, whose X68000 display runs slightly fast (56.07 Hz).
@ -310,6 +358,65 @@ That last item is the one that matters. Every port has emulator run scripts
under `scripts/`, and building successfully proves considerably less than under `scripts/`, and building successfully proves considerably less than
running. running.
=== The Atari ST Family
The ST port builds two ways, and a program ships the one that suits its
audience (or both):
* *The ST build* (`make atarist`, programs in `build/atarist/bin`) is the
baseline. It is pure 68000 and *never uses STe hardware*: it runs on every
ST -- STF, STFM, Mega ST, STe and Mega STe alike -- exactly as on a plain
ST, at no cost for the STe's existence.
* *The STe build* (`make ste`, programs in `build/ste/bin`) is the same port
compiled with `JOEYLIB_ATARI_STE`. It uses the STe's hardware
unconditionally, so it *needs an STe or Mega STe*: on any other machine
`jlInit` fails and `jlLastError` says why (a Mega ST has a BLiTTER but no
DMA sound, so it is refused too). `jlPlatformName` reports `Atari STe`.
Nothing in the API differs between them:
[cols="2,3,3", options="header"]
|===
|Feature |ST build (any ST) |STe build (STe, Mega STe)
|Palette
|3 bits per channel: each channel's low bit is dropped, so `$0RGB` values one
apart can look the same
|4 bits per channel: every `$0RGB` value exactly
|Digital sound (`.MOD`, SFX, streams)
|PWM through the YM2149's channel A volume, driven by a 12288 Hz timer
interrupt; tone voice 0 is silent while it plays
|The 8-bit DMA sound chip, mono at 12517 Hz, with no interrupt; all three tone
voices keep playing
|Fills and copies
|The CPU
|The BLiTTER, for fills of 8 or more rows (24 for one 16-pixel column) and
copies of 4 or more rows; smaller work stays on the CPU, which is faster
there
|CPU clock
|As the machine is (8 MHz; TOS's setting on a Mega STe)
|8 MHz on an STe; a Mega STe is switched to 16 MHz with its cache on while
the program runs, and back to what TOS had when it ends (checked once, at
`jlInit`)
|===
The pixels are identical: UBER's 51 surface hashes match the ST's golden for
the STe build on an STe and a Mega STe, and the gates check that under Hatari.
`./joey-run` gives an ST-build program a plain ST and an STe-build program an
STe; `--machine st`, `megast`, `ste` or `megaste` picks another. A project
builds the STe variant with `make ste`, like any other port; it takes the ST's
baked assets.
What the STe build buys, measured with UBER under Hatari against the ST build
on a plain ST: a large `jlFillRect` runs up to 1.76 times as fast (80x80), a
vertical line 1.4 times and `jlSurfaceClear` 1.1 times; everything else runs
as on an ST. On a Mega STe at 16 MHz every operation runs about twice as fast.
Hatari models that 16 MHz without the RAM wait states a real Mega STe has, so
expect less on memory-bound operations there.
=== DVX Programs === DVX Programs
DVX is a DOS desktop: a VESA graphics GUI with windows, cooperative DVX is a DOS desktop: a VESA graphics GUI with windows, cooperative
@ -384,3 +491,275 @@ hashes are DOS's -- and the rest behaves like this:
`make dvx` builds every example as a DVX program (the `dvx` installer `make dvx` builds every example as a DVX program (the `dvx` installer
component supplies DVX and its SDK, <<_setting_up_the_toolchains>>), and component supplies DVX and its SDK, <<_setting_up_the_toolchains>>), and
`./joey-run --port dvx NAME` starts one in DVX under DOSBox Staging. `./joey-run --port dvx NAME` starts one in DVX under DOSBox Staging.
=== SDL3 Programs
The SDL3 port builds a JoeyLib program as a native program for the machine
you work on: Linux today, through SDL 3, which the installer builds into
JoeyLib and every program links in (the `sdl3` component). It is the hosted
core in `src/hosted` -- everything that is the same under any desktop
operating system -- with an SDL3 backend in `src/hosted/sdl3`. Its stage is
the generic chunky one, so UBER's hashes are DOS's, and the rest behaves like
this:
* *A window, or the whole screen.* The stage is scaled to fill the window at
4:3, the shape 320x200 has on the old machines' monitors (each pixel 1.2
times as tall as it is wide), with black bars as needed; SDL's pixel-art
scaling keeps the pixels sharp at any size. Each scanline goes through its
own palette, so SCB palettes are exact. Three environment variables set it
up: `JOEYLIB_SCALE=N` opens the window N times 320 pixels wide (default 3),
`JOEYLIB_ASPECT=square` keeps the pixels square (16:10) instead, and
`JOEYLIB_FULLSCREEN=1` starts on the whole screen. Alt+Enter switches
between the window and the whole screen. JoeyLib's API has no full-screen
call; it is the user's choice.
* *A virtual 60 Hz.* A window has no vertical blank. `jlFrameHz()` is 60 and
`jlWaitVBL()` sleeps to the next sixtieth of a second of the machine's
clock. The window is redrawn at most once a frame, however often the
program presents.
* *Sprites are interpreted.* There is no code emitter for the host's CPU, so
`jlSpriteCompile` returns false and every sprite is drawn by the
interpreter -- far faster than any of the old machines all the same.
`joey/platform.h` defines `JOEYLIB_SPRITE_INTERPRETED`, for a program that
checks how many of its sprites compiled. A pre-compiled bank (`.spc`)
loads its cels' pixels and leaves their code: the DOS bake is used.
* *Input.* Keys by where they are on the keyboard, so another layout does not
move the arrow keys; typed characters through the OS's keyboard layout. The
mouse is the pointer over the stage, in stage pixels (the OS pointer is
hidden over the window: JoeyLib programs draw their own). The first two
gamepads are joysticks 0 and 1: the left stick or the d-pad, the south
button (A on an Xbox pad) as `JOY_BUTTON_0` and the east button (B) as
`JOY_BUTTON_1`; they come and go as they are plugged in.
* *Closing ends the program.* Closing the window ends the program at its next
`jlWaitVBL`, `jlInputPoll` or `jlStagePresent`, as `exit()` does anywhere:
its `atexit` handlers run and the window and the sound are closed.
* *Files.* The program's own folder is the current directory from `jlInit`
on, as on the machine ports: `DATA/`, `SAVES/` and `joeylog.txt` are beside
the program.
* *Sound* is mixed in software into 16-bit stereo at 44.1 kHz: `.MOD` music
through libxmp-lite (as on DOS), the SFX slots in stereo, the three tone
voices as square waves and the noise voice as the ST's YM2149 makes it. It
is mixed in program time by `jlAudioFrameTick`, `jlWaitVBL`,
`jlInputPoll` and `jlStagePresent`, a few frames ahead, so a
`jlAudioTickRegister` callback runs in program time too -- but between
exactly the samples it falls between, so its notes start in the right
place in the sound. `jlAudioInit` is needed for every sound, the tone
voices included.
* *No serial port.*
`make sdl3` builds every example as a native program, each in
`build/sdl3/bin/` (a program that ships in a folder, in a folder of its own
with its `DATA/`), and `./joey-run --port sdl3 NAME` runs one; so does the
program itself, from anywhere.
=== Web Programs
The web port is the SDL3 port compiled to WebAssembly with Emscripten (the
`web` installer components: Emscripten through emsdk, and SDL 3 built with
it): the same hosted core, the same backend, the same stage, so UBER's hashes
are DOS's here too. Everything in <<_sdl3_programs>> holds, except:
* *A page.* A program is a folder, `build/web/bin/NAME/`: `NAME.html` (the
page), `NAME.js`, `NAME.wasm`, and `NAME.data`, the program's `DATA/`
packed in when it is built. Put the folder on any web server and open
`NAME.html`; a browser will not run it from a `file:` address. The page's
address takes the window's settings: `NAME.html?scale=2&aspect=square`.
* *Your loop still works.* A browser does not let a page's program block,
and a JoeyLib program owns its loop and blocks in `jlWaitVBL`. Programs are
built with Emscripten's ASYNCIFY, and the port's waits hand the browser its
turn and carry on where they were, so an unmodified program runs. It gets
its turn back at least once a frame even when it never waits (a loop on
`jlInputPoll` alone, as `jlWaitForAnyKey` is).
* *Sound starts with the first click or key press*, as browsers require; the
page says so.
* *Saves persist.* `SAVES/` is kept in the browser's IndexedDB for the page's
address, read back when the program starts and written back every two
seconds, so a save outlives the page.
* *No full screen by default and no closing.* Alt+Enter asks the browser for
the whole screen; the program ends when the page is closed.
`make web` builds every example as a page, and `./joey-run --port web NAME`
serves its folder on this machine and opens it in your browser.
=== PSP Programs
The PSP port is the SDL3 port built as PSP homebrew: the same hosted core
and backend, cross-compiled with pspdev's `psp-gcc` against SDL 3's PSP port
(the `psp` installer components: pspdev, and SDL 3 built with it). Its stage
is the same chunky one, so UBER's hashes are DOS's. Everything in
<<_sdl3_programs>> holds, except:
* *A folder for `PSP/GAME`.* A program is a folder, `build/psp/bin/NAME/`:
`EBOOT.PBP`, titled with the program's name (or its description's `TITLE`)
in the PSP's menu, and its `DATA/`. Copy the folder into `PSP/GAME/` on the
memory stick. Its folder is its current directory, so `DATA/`, `SAVES/`
and `joeylog.txt` are there. It runs on a PSP with custom firmware (it is
not signed) and in PPSSPP. The ELF it is packed from stays in
`build/psp/elf/`, for `psp-addr2line`.
* *The screen.* The PSP's 480x272 screen shows the stage at 1:1 in its
middle, black around it. The scale and aspect settings do not apply (a PSP
has no environment), and there is no full screen to switch to.
* *Its own controls, no keyboard.* The PSP's controls are joystick 0,
through SDL's gamepad mapping: the d-pad or the analog nub, cross as
`JOY_BUTTON_0` and circle as `JOY_BUTTON_1`; joystick 1 is never there.
Having no keyboard, the PSP also gives Start as the Return key and Select
as the Escape key, held (`KEY_RETURN`, `KEY_ESCAPE`) and typed
(`JL_CHAR_RETURN`, `JL_CHAR_ESCAPE` from `jlInputGetChar`) as those keys
are, so `jlWaitForAnyKey`, Return to go on and Escape to quit work. No
other key is ever down, nothing else is typed (the PSP's on-screen
keyboard is never opened), and there is no pointer to move.
* *HOME quits.* The HOME menu's Exit ends the program as closing a window
does.
* *Free space* (`jlDiskFree`) is that of the memory stick (or a PSP Go's
internal storage) the program is on.
* *Memory.* A PSP-1000 has 32 MB, about 24 MB of it for programs; later
models have more.
* *Alignment.* The PSP's MIPS processor stops a program that reads or writes
a 16- or 32-bit value at an address that is not a multiple of its size,
where an x86 does not notice (a 68000 stops too, but only on odd
addresses). Read a multi-byte value from a file buffer a byte at a time.
The gates run every PSP program with PPSSPP checking every access the same
way.
`make psp` builds every example, and `./joey-run --port psp --headless NAME`
runs one under PPSSPP's headless build (the `ppsspp` installer component,
patched for the gates); `--snapshot` saves the PSP's screen. There is no
window to play in here: to play, copy the folder to a PSP, or open its
`EBOOT.PBP` in PPSSPP. None of it has run on a real PSP yet.
=== Windows Programs
The Win32 port is the hosted core with a backend of its own, written to the
Win32 API (`src/hosted/win32`), for the Windows SDL3 does not reach --
Windows 95, 98, ME, NT 4 and 2000 -- and every Windows since. Its stage is
the same chunky one, so UBER's hashes are DOS's. Everything in
<<_sdl3_programs>> holds, except:
* *Old Windows on purpose.* A program is a 32-bit `NAME.EXE` built by
llvm-mingw against `MSVCRT.DLL` (the `win32` installer component), marked
for Windows 4.0 so 95 and NT 4 will load it, linked statically, and
calling only what USER, GDI, WINMM and KERNEL32 had in 1995. `MSVCRT.DLL`
came with Windows 95 OSR2 and Internet Explorer; a first-release Windows
95 needs it installed.
* *One thread.* The window is made on the program's thread, so its messages
arrive there and the port dispatches them at `jlInputPoll`, `jlWaitVBL`
and `jlStagePresent`; the sound goes out through waveOut buffers handed
over at the same calls. There are no callbacks and no locks.
* *The window.* The stage is drawn with `StretchDIBits` at the stage's shape,
4:3 or square (the same `JOEYLIB_SCALE`, `JOEYLIB_ASPECT` and
`JOEYLIB_FULLSCREEN` settings), black around it; full screen is a
borderless window over the whole monitor, which leaves the display mode
alone. On a 256-colour desktop Windows maps every colour to the nearest
one it has.
* *Keys* by the PC scan code every key message carries (the same table as
DOS), typed characters through the user's keyboard layout, and the first
two joysticks through `joyGetPosEx`, calibrated in the Control Panel. Keys
held when the window loses the keyboard are let go.
* *Serial* through the Win32 COM calls (COM1, or COM<unit> for a slot).
Closing the port lets Windows drop DTR; Win32 has no call to prevent it.
`make win32` builds every example as a Windows program in `build/win32/bin/`,
and `./joey-run --port win32 NAME` runs one under Wine (the `wine` installer
component, a portable Wine kept in `toolchains/`); the gates run there too.
None of it has run on a real Windows 9x or NT 4 here.
The Win16 port is the hosted core with a backend written to the Windows 3.1
API (`src/hosted/win16`), for Windows 3.1 and Windows for Workgroups 3.11 on
a 386 or better. Its stage is the same chunky one, so UBER's hashes are DOS's
too. Everything said of Win32 above holds -- one thread, the window, keys by
scan code, DTR dropped at close -- except:
* *32-bit code on Windows 3.1.* A program is a Windows 3.x `NAME.EXE` built
with Open Watcom's Win386 target (the `win16` installer component): flat
32-bit code bound to Watcom's supervisor, which turns each call into the
16-bit one Windows takes, so it needs Windows in 386 enhanced mode. It
calls only what Windows 3.1 has: USER, GDI, KERNEL and MMSYSTEM.
* *Exact colours.* The frame is 8-bit, a DIB whose 256-entry colour table
holds all 16 palettes and is realized as a logical palette whenever a frame
is shown, so on a 256-colour display every colour is exact, SCB palettes
included. `JOEYLIB_SCALE` defaults to 2, and the settings are read from the
DOS environment Windows started from (`joey-run` puts its own there).
Under DOSBox, Alt+Enter is DOSBox's own full-screen key; use Alt with the
keypad's Enter.
* *Sound* is 8-bit mono at 22.05 kHz through waveOut, what a Sound Blaster
and a 386 handle well; stereo pan is ignored.
* *Joysticks* are the first two MMSYSTEM sticks, through `joyGetPos`, with
their buttons 1 and 2. Windows 3.x reads sticks only through a joystick
driver, which Windows 3.1 itself does not have; without one no stick is
seen. JoeyLib's Windows runs KPJOY.DRV (the `kpjoy` installer component,
built from the kpjoy project): the PC game port's two sticks, each axis's
rest taken from its first readings, so leave the stick centred as the
program starts. A game shipped for Windows 3.x can ship KPJOY.DRV with it
(`[drivers] joystick=kpjoy.drv` in SYSTEM.INI).
* *Files.* The program's folder, drive included, is the current directory
from the moment the window opens.
* *Serial* through Windows 3.1's communications calls (`OpenComm` and the
rest): COM1, or COM<unit> for a slot. JoeyLib's Windows runs KPCOMM.DRV
in place of COMM.DRV (the `kpcomm` installer component, built from the
mscomm project): both 16550A FIFOs and 115200 baud. Windows 3.1's own
driver goes up to 57600, and a faster rate gets that there.
* *Shipping.* Every Win16 program carries Open Watcom's C library and its
Win386 supervisor, and KPJOY.DRV and KPCOMM.DRV carry Open Watcom code
too. Open Watcom's license (the Sybase Open Watcom Public License,
section 2.2(d)) asks for a notice, in the program and in its
documentation, that the source of that code is available and where. The
port builds the notice into every program and the drivers carry it, never
shown; the documentation's part is this line, in the game's readme or
manual:
+
....
This software contains code from Open Watcom. Its source code is available
under the terms of the Sybase Open Watcom Public License version 1.0 from
https://github.com/open-watcom/open-watcom-v2
....
+
KPJOY.DRV and KPCOMM.DRV are MIT licensed: ship each with its `LICENSE.md`,
which the installer puts beside the driver in `toolchains/opt/`.
`make win16` builds every example as a Windows 3.x program in
`build/win16/bin/`, and `./joey-run --port win16 NAME` runs one on Windows
for Workgroups 3.11 in DOSBox Staging (the `win311` installer component, set
up from your own install disc); the gates run there too. None of it has run
on a real 386 here.
=== Haiku and BeOS Programs
The Be API ports are the hosted core with a backend written to the Be API
(`src/hosted/be`, C++), which Haiku reimplements, kept to the calls BeOS R5
already had. One source builds three ports: `haiku` (Haiku x86_64, gcc 13),
`haiku32` (Haiku x86, gcc 2.95, the BeOS C++ ABI) and `beos` (BeOS R5 x86,
built with the same gcc 2.95 against R5's own headers and libraries, which
the `beosR5` installer component copies off your BeOS 5 Professional CD).
Their stage is the same chunky one, so UBER's hashes are DOS's. Everything in
<<_sdl3_programs>> holds, except:
* *Threads.* The program's `main` keeps its own thread; the application and
the window run on threads of their own, as every Be program's do. Key and
mouse messages reach the program as events taken at `jlInputPoll`,
`jlWaitVBL` and `jlStagePresent`, and the sound comes from a
`BSoundPlayer`.
* *The window* shows the stage from a bitmap the app_server scales without
filtering, at the stage's shape, 4:3 or square, black around it (the same
`JOEYLIB_SCALE`, `JOEYLIB_ASPECT` and `JOEYLIB_FULLSCREEN` settings;
`JOEYLIB_SCALE` defaults to 3). Alt+Enter switches between the window and
the whole screen. The pointer is hidden over the window.
* *Keys* by raw key code, the key's place on the keyboard whatever the
keymap; typed characters are the keymap's, 7-bit ASCII only. The first
two joysticks (`BJoystick`) are `JOYSTICK_0` and `JOYSTICK_1`, their first
two axes and buttons.
* *Files.* The program's folder is the current directory from the moment
the window opens.
* *No serial port.*
* *BeOS R5's loader* refuses any program with a dynamic tag it does not
know, so `make beos` links without combined relocations (`-z
nocombreloc`). Build for R5 with `make beos`, not `make haiku32`.
`make haiku`, `make haiku32` and `make beos` build every example into
`build/<port>/bin/`, and `./joey-run --port <port> NAME` runs one in that
port's VM under QEMU: Haiku R1/beta6 (the `haikuVm` and `haikuVm32` installer
components) or BeOS R5 (`beosVm`, made from your CD), booted from a disk it
never writes to, with the program's folder on a second disk. R5 drives none
of QEMU's video cards, so its VM is taken through the boot loader's menu to
the fail-safe (VESA) mode, 1024x768 in 16-bit colour; it has no sound card.
The gates run in the same VMs (`scripts/verify-be-input.sh`,
`scripts/bench-be.sh`). None of it has run on a real BeOS or Haiku machine
here.

View file

@ -25,7 +25,7 @@ native sprite blitter code into. Getting it wrong is the most common cause of
sprites drawing slowly, so it is worth understanding. sprites drawing slowly, so it is worth understanding.
* `0` selects a per-platform default: 8 KB on the IIgs, 32 KB on * `0` selects a per-platform default: 8 KB on the IIgs, 32 KB on
Amiga, ST, DOS and DVX. Amiga, ST, DOS and DVX. SDL3 interprets every sprite and never uses it.
* The 68000 and x86 emitters produce code roughly four to eight times less * The 68000 and x86 emitters produce code roughly four to eight times less
dense than the 65816 one, so the same sprite needs far more arena space on dense than the 65816 one, so the same sprite needs far more arena space on
those ports. A 32x32 sprite can need 8 to 16 KB there. those ports. A 32x32 sprite can need 8 to 16 KB there.
@ -141,8 +141,8 @@ rows. That is the one case where you have to mark the region yourself.
==== Frame-Rate Independence ==== Frame-Rate Independence
The targets do not share a refresh rate: 50 Hz (Amiga PAL), 55 Hz The targets do not share a refresh rate: 50 Hz (Amiga PAL), 55 Hz
(X68000), 60 Hz (IIgs, ST NTSC) and 70 Hz (VGA mode 13h, and DVX's virtual (X68000), 60 Hz (IIgs, ST NTSC, and SDL3's virtual rate) and 70 Hz (VGA
rate). A loop mode 13h, and DVX's virtual rate). A loop
that moves a sprite "two pixels per frame" runs 40 percent faster on DOS than that moves a sprite "two pixels per frame" runs 40 percent faster on DOS than
on a PAL Amiga. on a PAL Amiga.

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Sierra-style mini-adventure built on JoeyLib. // Sierra-style mini-adventure built on JoeyLib.
// //
// What this demonstrates: // What this demonstrates:
@ -206,7 +210,6 @@ static uint8_t gEgoTiles[DIR_COUNT][EGO_FRAMES][EGO_TILE_BYTES];
static uint8_t gEgoBackup[EGO_BACKUP_BYTES] __attribute__((aligned(2))); static uint8_t gEgoBackup[EGO_BACKUP_BYTES] __attribute__((aligned(2)));
static jlSpriteBackupT gEgoBak; static jlSpriteBackupT gEgoBak;
static bool gEgoBakValid;
/* Cursor sprite per verb (+ item-icon for "using" mode) */ /* Cursor sprite per verb (+ item-icon for "using" mode) */
static jlSpriteT *gCursor[VERB_COUNT]; static jlSpriteT *gCursor[VERB_COUNT];
@ -215,7 +218,6 @@ static jlSpriteT *gLampLitSprite; /* lit-state inventory icon */
static uint8_t gLampLitTiles[2 * 2 * TILE_BYTES]; static uint8_t gLampLitTiles[2 * 2 * TILE_BYTES];
static uint8_t gCursorBackup[CURSOR_BACKUP_BYTES] __attribute__((aligned(2))); static uint8_t gCursorBackup[CURSOR_BACKUP_BYTES] __attribute__((aligned(2)));
static jlSpriteBackupT gCursorBak; static jlSpriteBackupT gCursorBak;
static bool gCursorBakValid;
/* Ego state */ /* Ego state */
static int16_t gEgoX, gEgoY; /* top-left pixel of sprite */ static int16_t gEgoX, gEgoY; /* top-left pixel of sprite */
@ -1324,6 +1326,34 @@ static void buildPropSprites(void) {
* save-under for props. */ * save-under for props. */
// A hotspot added to a room (no compound literals: plain C89, so every
// port's compiler takes it).
static void roomHotspotAdd(RoomT *r, HotspotIdE id, int16_t x, int16_t y, int16_t w, int16_t h, const char *name) {
HotspotT *hs;
hs = &r->hotspots[r->hotspotCount++];
hs->id = id;
hs->x = x;
hs->y = y;
hs->w = w;
hs->h = h;
hs->name = name;
}
// A prop added to a room; resolvePropSprites gives it its sprite.
static void roomPropAdd(RoomT *r, int16_t x, int16_t y, int16_t w, int16_t h) {
PropT *prop;
prop = &r->props[r->propCount++];
prop->x = x;
prop->y = y;
prop->w = w;
prop->h = h;
prop->sp = NULL;
}
static void initRoomForest(void) { static void initRoomForest(void) {
RoomT *r; RoomT *r;
int i; int i;
@ -1334,15 +1364,15 @@ static void initRoomForest(void) {
} }
r->hotspotCount = 0; r->hotspotCount = 0;
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_TREE, 50, 92, TREE_W, TREE_H, "the tree" }; roomHotspotAdd(r, HS_TREE, 50, 92, TREE_W, TREE_H, "the tree");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_TREE, 140, 100, TREE_W, TREE_H, "the tree" }; roomHotspotAdd(r, HS_TREE, 140, 100, TREE_W, TREE_H, "the tree");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_TREE, 240, 95, TREE_W, TREE_H, "the tree" }; roomHotspotAdd(r, HS_TREE, 240, 95, TREE_W, TREE_H, "the tree");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_DOOR_TO_COTTAGE, 290, 110, 30, 50, "the path east" }; roomHotspotAdd(r, HS_DOOR_TO_COTTAGE, 290, 110, 30, 50, "the path east");
r->propCount = 0; r->propCount = 0;
r->props[r->propCount++] = (PropT){ 50, 92, TREE_W, TREE_H, NULL }; roomPropAdd(r, 50, 92, TREE_W, TREE_H);
r->props[r->propCount++] = (PropT){140, 100, TREE_W, TREE_H, NULL }; roomPropAdd(r, 140, 100, TREE_W, TREE_H);
r->props[r->propCount++] = (PropT){240, 95, TREE_W, TREE_H, NULL }; roomPropAdd(r, 240, 95, TREE_W, TREE_H);
r->egoEnterFromE_x = 290; r->egoEnterFromE_x = 290;
r->egoEnterFromE_y = 130; r->egoEnterFromE_y = 130;
@ -1363,18 +1393,18 @@ static void initRoomCottage(void) {
} }
r->hotspotCount = 0; r->hotspotCount = 0;
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_WINDOW, 60, 18, 50, 40, "the window" }; roomHotspotAdd(r, HS_WINDOW, 60, 18, 50, 40, "the window");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_FIRE, 220, 30, 70, 60, "the fireplace" }; roomHotspotAdd(r, HS_FIRE, 220, 30, 70, 60, "the fireplace");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_TABLE, 140, 108, TABLE_W, TABLE_H, "the table" }; roomHotspotAdd(r, HS_TABLE, 140, 108, TABLE_W, TABLE_H, "the table");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_LAMP_ON_TABLE, 156, 100, LAMP_W, LAMP_H, "a small lamp" }; roomHotspotAdd(r, HS_LAMP_ON_TABLE, 156, 100, LAMP_W, LAMP_H, "a small lamp");
r->hotspots[r->hotspotCount++] = (HotspotT){ HS_DOOR_TO_FOREST, 8, 60, 36, 80, "the door" }; roomHotspotAdd(r, HS_DOOR_TO_FOREST, 8, 60, 36, 80, "the door");
r->propCount = 0; r->propCount = 0;
r->props[r->propCount++] = (PropT){ 140, 108, TABLE_W, TABLE_H, NULL }; roomPropAdd(r, 140, 108, TABLE_W, TABLE_H);
/* The lamp prop is drawn ONLY while the player hasn't picked it /* The lamp prop is drawn ONLY while the player hasn't picked it
* up; the prop is added/removed dynamically. We pre-allocate the * up; the prop is added/removed dynamically. We pre-allocate the
* slot here so the priority pass can find it. */ * slot here so the priority pass can find it. */
r->props[r->propCount++] = (PropT){ 156, 100, LAMP_W, LAMP_H, NULL }; roomPropAdd(r, 156, 100, LAMP_W, LAMP_H);
r->egoEnterFromE_x = 280; r->egoEnterFromE_x = 280;
r->egoEnterFromE_y = 150; r->egoEnterFromE_y = 150;
@ -2200,8 +2230,6 @@ static void enterRoom(RoomE room, bool fromEast, bool fromWest) {
} }
gEgoMoving = false; gEgoMoving = false;
gEgoFrameIdx = 0; gEgoFrameIdx = 0;
gEgoBakValid = false;
gCursorBakValid = false;
gPathLen = 0; gPathLen = 0;
gPathStep = 0; gPathStep = 0;

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// adventure2 -- a Sierra-faithful sample built on JoeyLib. // adventure2 -- a Sierra-faithful sample built on JoeyLib.
// //
// The first adventure example (examples/adventure/adventure.c) used // The first adventure example (examples/adventure/adventure.c) used

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Audio demo: starts the baked chip-tracker song (demoSong.song -> // Audio demo: starts the baked chip-tracker song (demoSong.song ->
// demoSong.h via tools/songbake) on entry and exits on ESC. The keys: // demoSong.h via tools/songbake) on entry and exits on ESC. The keys:
// SPACE a short digital SFX, test.sfx from the DATA folder // SPACE a short digital SFX, test.sfx from the DATA folder

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Drawing primitive smoke test. Lays out a 2x2 grid of cells, each // Drawing primitive smoke test. Lays out a 2x2 grid of cells, each
// exercising one family of primitives. On screen each cell should show // exercising one family of primitives. On screen each cell should show
// a clear visual signal that the underlying inner loops (C or ASM) // a clear visual signal that the underlying inner loops (C or ASM)

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib hello-world example. // JoeyLib hello-world example.
// //
// Validates that the C API headers, library, and per-platform link // Validates that the C API headers, library, and per-platform link

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Joystick demo: shows position and button state for both joystick // Joystick demo: shows position and button state for both joystick
// ports as live, redraw-on-change visualizations. Each stick gets a // ports as live, redraw-on-change visualizations. Each stick gets a
// frame with a dot indicating the current axis values, plus two // frame with a dot indicating the current axis values, plus two

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Visual keyboard + mouse demo: one square per jlKeyE, lit when its // Visual keyboard + mouse demo: one square per jlKeyE, lit when its
// key is held, and a small pointer drawn at the live mouse position. // key is held, and a small pointer drawn at the live mouse position.
// Holding the left mouse button while the pointer is over a cell lights // Holding the left mouse button while the pointer is over a cell lights

View file

@ -0,0 +1,123 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Palette-change probe (PALPROBE, a gate's program, not an example): how
// fast palette and SCB changes reach the screen, and whether they reach it
// right.
//
// It times, over PROBE_FRAMES frames each, a palette change followed by a
// present, and an SCB change followed by a present, on a screen of four SCB
// bands, and logs the rates. Then it paints the bands (colour 1 of palettes
// 0..3 red, green, blue, white), makes one palette change (palette 2's
// colour 1 to yellow) and one SCB change that keeps every band where it was
// (band 3 to palette 0), logs "PALPROBE: ready" and holds the screen for
// HOLD_FRAMES frames, so a gate can look at it: top to bottom red, green,
// yellow, red. scripts/verify-amiga-palette.sh is that gate.
#include <string.h>
#include <joey/joey.h>
#define PROBE_FRAMES 200u
#define HOLD_FRAMES 400u
#define BANDS 4u
#define BAND_LINES 50u
#define PAINT_COLOR 1u
#define MS_PER_SECOND 1000ul
#define COLOR_MASK 0x0FFFu
#define PALETTE_MASK 3u
#define SCB_SWAP_FIRST 0u
#define SCB_SWAP_LAST (BAND_LINES - 1u)
#define YELLOW 0xFF0u
#define CHANGED_PALETTE 2u
#define MOVED_BAND 3u
#define MOVED_TO 0u
static void check(void);
static void timeChanges(const char *name, bool scb);
// Paint the bands, make the two changes, and hold the screen.
static void check(void) {
static const uint16_t firsts[BANDS] = { 0xF00, 0x0F0, 0x00F, 0xFFF };
uint16_t colors[SURFACE_COLORS_PER_PALETTE];
jlSurfaceT *stage;
uint16_t band;
uint16_t frame;
stage = jlStageGet();
for (band = 0; band < BANDS; band++) {
memset(colors, 0, sizeof(colors));
colors[PAINT_COLOR] = firsts[band];
jlPaletteSet(stage, (uint8_t)band, colors);
jlScbSetRange(stage, (uint16_t)(band * BAND_LINES), (uint16_t)(band * BAND_LINES + BAND_LINES - 1u), (uint8_t)band);
jlFillRect(stage, 0, (int16_t)(band * BAND_LINES), SURFACE_WIDTH, BAND_LINES, PAINT_COLOR);
}
jlStagePresent();
jlWaitVBL();
memset(colors, 0, sizeof(colors));
colors[PAINT_COLOR] = YELLOW;
jlPaletteSet(stage, CHANGED_PALETTE, colors);
jlStagePresent();
jlScbSetRange(stage, (uint16_t)(MOVED_BAND * BAND_LINES), (uint16_t)(MOVED_BAND * BAND_LINES + BAND_LINES - 1u), MOVED_TO);
jlStagePresent();
jlLogF("PALPROBE: ready");
for (frame = 0; frame < HOLD_FRAMES; frame++) {
jlWaitVBL();
}
}
// PROBE_FRAMES frames of palette changes (or SCB changes), each presented.
static void timeChanges(const char *name, bool scb) {
uint16_t colors[SURFACE_COLORS_PER_PALETTE];
jlSurfaceT *stage;
uint16_t start;
uint32_t ms0;
uint32_t elapsed;
unsigned long count;
stage = jlStageGet();
memset(colors, 0, sizeof(colors));
count = 0;
jlWaitVBL();
start = jlFrameCount();
ms0 = jlMillisElapsed();
while ((uint16_t)(jlFrameCount() - start) < PROBE_FRAMES) {
if (scb) {
jlScbSetRange(stage, SCB_SWAP_FIRST, SCB_SWAP_LAST, (uint8_t)(count & PALETTE_MASK));
} else {
colors[PAINT_COLOR] = (uint16_t)(count & COLOR_MASK);
jlPaletteSet(stage, (uint8_t)(count & PALETTE_MASK), colors);
}
jlStagePresent();
count++;
}
elapsed = jlMillisElapsed() - ms0;
jlLogF("PALPROBE: %s: %lu in %lu ms = %lu/s", name, count, (unsigned long)elapsed, (unsigned long)(count * MS_PER_SECOND / elapsed));
}
int main(void) {
jlConfigT cfg;
jlSurfaceT *stage;
uint16_t band;
cfg.codegenBytes = 0;
if (!jlInit(&cfg)) {
return 1;
}
stage = jlStageGet();
for (band = 0; band < BANDS; band++) {
jlScbSetRange(stage, (uint16_t)(band * BAND_LINES), (uint16_t)(band * BAND_LINES + BAND_LINES - 1u), (uint8_t)band);
jlFillRect(stage, 0, (int16_t)(band * BAND_LINES), SURFACE_WIDTH, BAND_LINES, (uint8_t)(band + 1u));
}
jlStagePresent();
timeChanges("palette+present", false);
timeChanges("scb+present", true);
check();
jlLogF("PALPROBE: done");
jlShutdown();
return 0;
}

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// M1 deliverable: visible test pattern exercising surfaces, palettes, // M1 deliverable: visible test pattern exercising surfaces, palettes,
// SCBs, jlFillRect, and present. // SCBs, jlFillRect, and present.
// //

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Save-file demo: a launch counter that persists across runs, plus a free-disk // Save-file demo: a launch counter that persists across runs, plus a free-disk
// bar -- no text assets. On start it reads SAVES/runs.dat, increments the // bar -- no text assets. On start it reads SAVES/runs.dat, increments the
// count, and writes it back; the 16-bit count shows as lit/unlit cells (MSB // count, and writes it back; the 16-bit count shows as lit/unlit cells (MSB

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// SCB stress screen: the per-scanline palette under the heaviest load a // SCB stress screen: the per-scanline palette under the heaviest load a
// program can reasonably put on it. Written for the ports that honour the SCB // program can reasonably put on it. Written for the ports that honour the SCB
// by reloading ONE hardware palette as the beam scans (the X68000's text-plane // by reloading ONE hardware palette as the beam scans (the X68000's text-plane

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Does opening one built-in SCC port survive the OTHER one? // Does opening one built-in SCC port survive the OTHER one?
// //
// The Zilog 8530 in a IIgs carries both built-in ports: channel A is the // The Zilog 8530 in a IIgs carries both built-in ports: channel A is the

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Serial add-on demo: an echo terminal + loopback self-test with no text // Serial add-on demo: an echo terminal + loopback self-test with no text
// assets. It opens the DEFAULT serial port at 9600 8N1 and each frame: // assets. It opens the DEFAULT serial port at 9600 8N1 and each frame:
// - drains received bytes (jlSerialPoll + jlSerialRead), echoes each one // - drains received bytes (jlSerialPoll + jlSerialRead), echoes each one

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Does a serial receiver survive the longest deaf window a JoeyLib program has? // Does a serial receiver survive the longest deaf window a JoeyLib program has?
// //
// The host peer (scripts/verify-iigs-serial-loss.sh) waits for "READY" from // The host peer (scripts/verify-iigs-serial-loss.sh) waits for "READY" from

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Serial and mouse together: traffic both ways on the serial port while the // Serial and mouse together: traffic both ways on the serial port while the
// mouse is read and drawn, for a machine whose serial port and mouse share a // mouse is read and drawn, for a machine whose serial port and mouse share a
// chip. The X68000 is one: its Z8530 SCC carries the RS-232C port on channel A // chip. The X68000 is one: its Z8530 SCC carries the RS-232C port on channel A

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Minimal headless serial self-test -- NO jlInit (no video/graphics), so it // Minimal headless serial self-test -- NO jlInit (no video/graphics), so it
// runs even where the graphics HAL can't (e.g. AROS on the Amiga). Opens the // runs even where the graphics HAL can't (e.g. AROS on the Amiga). Opens the
// DEFAULT port at 9600 8N1, sends a banner (TX heartbeat), then echoes every // DEFAULT port at 9600 8N1, sends a banner (TX heartbeat), then echoes every

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Sprite demo: bounces a 16x16 ball using the jlSpriteT API. The ball // Sprite demo: bounces a 16x16 ball using the jlSpriteT API. The ball
// art is authored as a 16x16 4bpp packed image in this file (one row // art is authored as a 16x16 4bpp packed image in this file (one row
// per source line) and converted at startup into the 2x2 tile layout // per source line) and converted at startup into the 2x2 tile layout

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Tile-bank check on a real port: loads this port's bake of the host gate's // Tile-bank check on a real port: loads this port's bake of the host gate's
// fixture both ways, checks every pixel, and makes sure every other target's // fixture both ways, checks every pixel, and makes sure every other target's
// bake is refused. It is the on-machine half of scripts/check-tilebank.sh: // bake is refused. It is the on-machine half of scripts/check-tilebank.sh:

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Uber demo: exercise every JoeyLib public API and measure throughput // Uber demo: exercise every JoeyLib public API and measure throughput
// of the per-frame-hot ones. Results are written to joeylog.txt via // of the per-frame-hot ones. Results are written to joeylog.txt via
// jlLogF. A green screen on exit means the run completed. // jlLogF. A green screen on exit means the run completed.
@ -123,7 +127,7 @@ extern uint16_t gJoeyLogRingHead;
// compiles a FILE* logger everywhere else), so there is nothing to point at. // compiles a FILE* logger everywhere else), so there is nothing to point at.
#define uberMbLayout() ((void)0) #define uberMbLayout() ((void)0)
#else #else
#define uberMbOp(_i) ((void)0) #define uberMbOp(_i) ((void)(_i))
#define uberMbPhase(_p) ((void)0) #define uberMbPhase(_p) ((void)0)
#define uberMbBeat() ((void)0) #define uberMbBeat() ((void)0)
#define uberMbTick(_t) ((void)0) #define uberMbTick(_t) ((void)0)
@ -133,7 +137,6 @@ extern uint16_t gJoeyLogRingHead;
typedef void (*OpFn)(void); typedef void (*OpFn)(void);
static const char *gCurName = "(none)";
static jlSurfaceT *gStage = NULL; static jlSurfaceT *gStage = NULL;
static jlSpriteT *gSprite = NULL; static jlSpriteT *gSprite = NULL;
static jlSpriteBackupT gBackup; static jlSpriteBackupT gBackup;
@ -261,7 +264,6 @@ static void timeOp(const char *name, OpFn op) {
uint32_t millisDelta; uint32_t millisDelta;
uint32_t hash; uint32_t hash;
gCurName = name;
gOpIndex++; gOpIndex++;
uberMbOp(gOpIndex); uberMbOp(gOpIndex);

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Audio: 4-channel Protracker .MOD music with digital one-shot SFX. // Audio: 4-channel Protracker .MOD music with digital one-shot SFX.
// //
// Authors compose music as .MOD modules. The host-side asset pipeline // Authors compose music as .MOD modules. The host-side asset pipeline

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib lifecycle: configuration, initialization, shutdown. // JoeyLib lifecycle: configuration, initialization, shutdown.
#ifndef JOEYLIB_CORE_H #ifndef JOEYLIB_CORE_H

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Crash-tracing logger. See src/core/debug.c. // Crash-tracing logger. See src/core/debug.c.
#ifndef JOEYLIB_DEBUG_H #ifndef JOEYLIB_DEBUG_H

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Drawing primitives. // Drawing primitives.
// //
// All primitives clip to the surface rectangle. Out-of-bounds draws are // All primitives clip to the surface rectangle. Out-of-bounds draws are

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib file access: read-only game data, writable save files, and a disk- // JoeyLib file access: read-only game data, writable save files, and a disk-
// space query. // space query.
// //

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Keyboard, mouse, and joystick input polling. // Keyboard, mouse, and joystick input polling.
// //
// Call jlInputPoll() once per frame (typically right before // Call jlInputPoll() once per frame (typically right before

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib umbrella header. // JoeyLib umbrella header.
// //
// Game code includes this single file: // Game code includes this single file:

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Palette and SCB (scanline control byte) accessors. // Palette and SCB (scanline control byte) accessors.
// //
// Colors are 12-bit $0RGB (bits 11..8 red, 7..4 green, 3..0 blue). // Colors are 12-bit $0RGB (bits 11..8 red, 7..4 green, 3..0 blue).

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib platform, CPU, endian, and capability defines. // JoeyLib platform, CPU, endian, and capability defines.
// //
// Exactly one JOEYLIB_PLATFORM_* must be defined per build. The build // Exactly one JOEYLIB_PLATFORM_* must be defined per build. The build
@ -15,6 +19,7 @@
!defined(JOEYLIB_PLATFORM_DOS) && \ !defined(JOEYLIB_PLATFORM_DOS) && \
!defined(JOEYLIB_PLATFORM_X68000) && \ !defined(JOEYLIB_PLATFORM_X68000) && \
!defined(JOEYLIB_PLATFORM_DVX) && \ !defined(JOEYLIB_PLATFORM_DVX) && \
!defined(JOEYLIB_PLATFORM_HOSTED) && \
!defined(JOEYLIB_PLATFORM_BLANK) !defined(JOEYLIB_PLATFORM_BLANK)
#if defined(__DJGPP__) || defined(__MSDOS__) #if defined(__DJGPP__) || defined(__MSDOS__)
@ -40,6 +45,15 @@
// JOEYLIB_PLATFORM_DVX (a program running in a window of the DVX desktop, // JOEYLIB_PLATFORM_DVX (a program running in a window of the DVX desktop,
// src/dvx/) is built with the same DJGPP compiler as DOS, so it cannot be // src/dvx/) is built with the same DJGPP compiler as DOS, so it cannot be
// told apart by compiler macros: make/dvx.mk passes -DJOEYLIB_PLATFORM_DVX. // told apart by compiler macros: make/dvx.mk passes -DJOEYLIB_PLATFORM_DVX.
//
// JOEYLIB_PLATFORM_HOSTED (a program running under a desktop operating
// system, src/hosted/) is built with the host's own compiler, so it is set
// with -D too, along with the backend that opens its window: make/sdl3.mk
// passes -DJOEYLIB_PLATFORM_HOSTED -DJOEYLIB_HOSTED_SDL3 (as do make/web.mk
// and make/psp.mk, the same backend for a browser and the PSP), make/win32.mk
// -DJOEYLIB_PLATFORM_HOSTED -DJOEYLIB_HOSTED_WIN32, make/win16.mk (Windows
// 3.x) -DJOEYLIB_PLATFORM_HOSTED -DJOEYLIB_HOSTED_WIN16, make/be.mk (Haiku)
// -DJOEYLIB_PLATFORM_HOSTED -DJOEYLIB_HOSTED_BE.
// ----- Validate exactly one platform is defined ----- // ----- Validate exactly one platform is defined -----
@ -49,6 +63,7 @@
defined(JOEYLIB_PLATFORM_DOS) + \ defined(JOEYLIB_PLATFORM_DOS) + \
defined(JOEYLIB_PLATFORM_X68000) + \ defined(JOEYLIB_PLATFORM_X68000) + \
defined(JOEYLIB_PLATFORM_DVX) + \ defined(JOEYLIB_PLATFORM_DVX) + \
defined(JOEYLIB_PLATFORM_HOSTED) + \
defined(JOEYLIB_PLATFORM_BLANK)) != 1 defined(JOEYLIB_PLATFORM_BLANK)) != 1
#error "JoeyLib: exactly one JOEYLIB_PLATFORM_* must be defined" #error "JoeyLib: exactly one JOEYLIB_PLATFORM_* must be defined"
#endif #endif
@ -71,7 +86,13 @@
#define JOEYLIB_CPU_68000 #define JOEYLIB_CPU_68000
#define JOEYLIB_ENDIAN_BIG #define JOEYLIB_ENDIAN_BIG
#define JOEYLIB_NATIVE_PLANAR #define JOEYLIB_NATIVE_PLANAR
#define JOEYLIB_PLATFORM_NAME "Atari ST" // JOEYLIB_ATARI_STE is the STe build (make ste): the same port using the
// BLiTTER, DMA sound and the 4-bit palette, for STe and Mega STe only.
#if defined(JOEYLIB_ATARI_STE)
#define JOEYLIB_PLATFORM_NAME "Atari STe"
#else
#define JOEYLIB_PLATFORM_NAME "Atari ST"
#endif
#elif defined(JOEYLIB_PLATFORM_DOS) #elif defined(JOEYLIB_PLATFORM_DOS)
#define JOEYLIB_CPU_X86 #define JOEYLIB_CPU_X86
#define JOEYLIB_ENDIAN_LITTLE #define JOEYLIB_ENDIAN_LITTLE
@ -95,15 +116,47 @@
#define JOEYLIB_ENDIAN_LITTLE #define JOEYLIB_ENDIAN_LITTLE
#define JOEYLIB_NATIVE_CHUNKY #define JOEYLIB_NATIVE_CHUNKY
#define JOEYLIB_PLATFORM_NAME "DVX" #define JOEYLIB_PLATFORM_NAME "DVX"
#elif defined(JOEYLIB_PLATFORM_HOSTED)
// The generic chunky stage, resolved through its SCB palettes into a
// window's RGB pixels by one backend (src/hosted/<backend>). Whatever CPU
// the host has: no machine code is generated, sprites are interpreted.
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define JOEYLIB_ENDIAN_BIG
#else
#define JOEYLIB_ENDIAN_LITTLE
#endif
#define JOEYLIB_NATIVE_CHUNKY
#define JOEYLIB_SPRITE_INTERPRETED
#if defined(JOEYLIB_HOSTED_SDL3) && defined(__PSP__)
#define JOEYLIB_PLATFORM_NAME "PSP"
#elif defined(JOEYLIB_HOSTED_SDL3)
#define JOEYLIB_PLATFORM_NAME "SDL3"
#elif defined(JOEYLIB_HOSTED_WIN32)
#define JOEYLIB_PLATFORM_NAME "Windows"
#elif defined(JOEYLIB_HOSTED_WIN16)
#define JOEYLIB_PLATFORM_NAME "Windows 3.x"
#elif defined(JOEYLIB_HOSTED_BE) && defined(__HAIKU__)
#define JOEYLIB_PLATFORM_NAME "Haiku"
#elif defined(JOEYLIB_HOSTED_BE)
#define JOEYLIB_PLATFORM_NAME "BeOS"
#else
#error "JoeyLib: JOEYLIB_PLATFORM_HOSTED needs a backend, e.g. -DJOEYLIB_HOSTED_SDL3"
#endif
#elif defined(JOEYLIB_PLATFORM_BLANK) #elif defined(JOEYLIB_PLATFORM_BLANK)
// Chunky little-endian is the simplest baseline for a new port: the generic // Chunky little-endian is the simplest baseline for a new port: the generic
// backend gives you fully-working software rendering out of the box. Adjust // backend gives you fully-working software rendering out of the box. Adjust
// these (or switch to JOEYLIB_NATIVE_PLANAR) once you know your hardware. // these (or switch to JOEYLIB_NATIVE_PLANAR) once you know your hardware.
#define JOEYLIB_ENDIAN_LITTLE #define JOEYLIB_ENDIAN_LITTLE
#define JOEYLIB_NATIVE_CHUNKY #define JOEYLIB_NATIVE_CHUNKY
#define JOEYLIB_SPRITE_INTERPRETED
#define JOEYLIB_PLATFORM_NAME "Blank Template" #define JOEYLIB_PLATFORM_NAME "Blank Template"
#endif #endif
// JOEYLIB_SPRITE_INTERPRETED: the port has no sprite code emitter (it links
// src/generic/spriteEmitStub.c), so every sprite is drawn by the
// interpreter. A pre-compiled bank (.spc) still gives it the cels' pixels;
// their machine code is skipped.
// ----- Per-machine op override registry (JL_HAS_<OP>) ----- // ----- Per-machine op override registry (JL_HAS_<OP>) -----
// //
// A machine #define-s JL_HAS_<OP> for each overridable platform op it replaces // A machine #define-s JL_HAS_<OP> for each overridable platform op it replaces
@ -256,6 +309,8 @@
#define JL_HAS_SAVE_DIR_ENSURE #define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE #define JL_HAS_SAVE_DELETE
#define JL_HAS_DISK_FREE #define JL_HAS_DISK_FREE
// compiled code written: clear the 68020+'s caches (exec CacheClearE)
#define JL_HAS_CODE_WRITTEN
// millisElapsed: generic frameCount*1000/frameHz (no override) // millisElapsed: generic frameCount*1000/frameHz (no override)
#elif defined(JOEYLIB_PLATFORM_ATARIST) #elif defined(JOEYLIB_PLATFORM_ATARIST)
#define JL_HAS_SURFACE_CLEAR // planar clear, function #define JL_HAS_SURFACE_CLEAR // planar clear, function
@ -314,6 +369,9 @@
#define JL_HAS_INPUT_SHUTDOWN #define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL #define JL_HAS_INPUT_POLL
#define JL_HAS_JOYSTICK_RESET #define JL_HAS_JOYSTICK_RESET
#if defined(JOEYLIB_ATARI_STE)
#define JL_HAS_LAST_ERROR // STe build: why jlInit refused a non-STe
#endif
// serial add-on (optional; BIOS Aux / XBIOS Rsconf on the Modem port) // serial add-on (optional; BIOS Aux / XBIOS Rsconf on the Modem port)
#define JL_HAS_SERIAL_OPEN #define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE #define JL_HAS_SERIAL_CLOSE
@ -512,6 +570,59 @@
#define JL_HAS_SERIAL_FLUSH #define JL_HAS_SERIAL_FLUSH
#define JL_HAS_SERIAL_SET_DTR #define JL_HAS_SERIAL_SET_DTR
#define JL_HAS_SERIAL_SET_RTS #define JL_HAS_SERIAL_SET_RTS
#elif defined(JOEYLIB_PLATFORM_HOSTED)
// A window under a desktop OS (src/hosted). The graphics are the chunky
// generics; the hosted core (src/hosted/*.c) resolves the stage into RGB,
// keeps a virtual frame clock, turns the backend's events into input state
// and mixes the audio, and the backend (src/hosted/<backend>/) is the OS.
#define JL_HAS_INIT // the backend's window
#define JL_HAS_SHUTDOWN
#define JL_HAS_LAST_ERROR // why the backend could not open it
#define JL_HAS_PRESENT // dirty rows through per-palette tables into an RGB frame
// (input shutdown and the joystick reset stay the generic no-ops: the OS
// owns the devices and calibrates the sticks)
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_POLL // the backend's key, mouse and gamepad events
#define JL_HAS_WAIT_VBL // a virtual 60 Hz frame clock
#define JL_HAS_FRAME_COUNT
#define JL_HAS_FRAME_HZ
#define JL_HAS_MILLIS_ELAPSED
// save files + disk space (the backend's file system calls)
#define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE
#define JL_HAS_DISK_FREE
// audio: a software mixer (MOD through libxmp-lite, the SFX slots, three
// square-wave voices, YM-style noise and the speaker tone) run on the
// program's thread, so the tick callback and the stream fills run there
// too and the critical sections stay the generic no-ops.
#define JL_HAS_AUDIO_INIT
#define JL_HAS_AUDIO_SHUTDOWN
#define JL_HAS_AUDIO_PLAY_MOD
#define JL_HAS_AUDIO_STOP_MOD
#define JL_HAS_AUDIO_IS_PLAYING_MOD
#define JL_HAS_AUDIO_PLAY_SFX
#define JL_HAS_AUDIO_PLAY_SFX_STREAM
#define JL_HAS_AUDIO_SET_PAN
#define JL_HAS_AUDIO_STOP_SFX
#define JL_HAS_AUDIO_TONE
#define JL_HAS_AUDIO_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_FRAME_TICK
#if defined(JOEYLIB_HOSTED_WIN32) || defined(JOEYLIB_HOSTED_WIN16)
// serial add-on (optional; a COM port through the Win32 communications
// calls, src/hosted/win32/win32Serial.c, or Windows 3.1's,
// src/hosted/win16/win16Serial.c; the driver buffers RX, so the poll
// stays the generic no-op)
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_READ
#define JL_HAS_SERIAL_WRITE
#define JL_HAS_SERIAL_AVAILABLE
#define JL_HAS_SERIAL_FLUSH
#define JL_HAS_SERIAL_SET_DTR
#define JL_HAS_SERIAL_SET_RTS
#endif
#elif defined(JOEYLIB_PLATFORM_BLANK) #elif defined(JOEYLIB_PLATFORM_BLANK)
// Copy-to-start template. It overrides ONLY the platform SERVICES (TODO // Copy-to-start template. It overrides ONLY the platform SERVICES (TODO
// stubs in src/blank/blank.c). Everything graphical -- draw / tile / sprite // stubs in src/blank/blank.c). Everything graphical -- draw / tile / sprite

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Stage present. // Stage present.
// //
// jlStagePresent flips the library-owned stage (back-buffer) to the // jlStagePresent flips the library-owned stage (back-buffer) to the

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Serial communications add-on -- portable RS-232 byte streams. // Serial communications add-on -- portable RS-232 byte streams.
// //
// OPTIONAL add-on: this header is NOT pulled in by <joey/joey.h>. Include it // OPTIONAL add-on: this header is NOT pulled in by <joey/joey.h>. Include it

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Sprites: rectangles of 8x8 tiles drawn at arbitrary pixel positions // Sprites: rectangles of 8x8 tiles drawn at arbitrary pixel positions
// with color-0 transparency. // with color-0 transparency.
// //

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Surface type and allocation. // Surface type and allocation.
// //
// All surfaces are 320x200 16-color images. In-memory storage is // All surfaces are 320x200 16-color images. In-memory storage is

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// Tiles: 8x8 pixel blocks aligned on the 8-pixel grid of any surface. // Tiles: 8x8 pixel blocks aligned on the 8-pixel grid of any surface.
// //
// A "tile" in JoeyLib isn't a separate object -- it's just the 8x8 // A "tile" in JoeyLib isn't a separate object -- it's just the 8x8

View file

@ -1,3 +1,7 @@
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib shared types and enums. // JoeyLib shared types and enums.
#ifndef JOEYLIB_TYPES_H #ifndef JOEYLIB_TYPES_H

View file

@ -23,7 +23,7 @@
# #
# Targets are component names (see `list`) or groups: # Targets are component names (see `list`) or groups:
# toolchain:PORT emulator:PORT PORT toolchains emulators all # toolchain:PORT emulator:PORT PORT toolchains emulators all
# where PORT is iigs, amiga, atarist, dos, x68000 or dvx. `all`, `toolchains` # where PORT is iigs, amiga, atarist, dos, x68000, dvx, sdl3, web, win32, win16, psp, haiku, haiku32 or beos. `all`, `toolchains`
# and `emulators` leave out optional components (dvx, which unpacks a DVX # and `emulators` leave out optional components (dvx, which unpacks a DVX
# tree's dist/ zips you have); name those explicitly. # tree's dist/ zips you have); name those explicitly.
# #
@ -48,6 +48,10 @@
# make reads toolchains/config.mk by itself. For interactive shells, # make reads toolchains/config.mk by itself. For interactive shells,
# `source toolchains/env.sh` sets the same variables. # `source toolchains/env.sh` sets the same variables.
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
set -euo pipefail set -euo pipefail
# shellcheck source=installer/lib/common.sh # shellcheck source=installer/lib/common.sh
source "$(dirname "${BASH_SOURCE[0]}")/installer/lib/common.sh" source "$(dirname "${BASH_SOURCE[0]}")/installer/lib/common.sh"
@ -58,7 +62,7 @@ source "$JOEY_INSTALLER/lib/config.sh"
# shellcheck source=installer/lib/bundle.sh # shellcheck source=installer/lib/bundle.sh
source "$JOEY_INSTALLER/lib/bundle.sh" source "$JOEY_INSTALLER/lib/bundle.sh"
JOEY_PORTS="iigs amiga atarist dos x68000 dvx" JOEY_PORTS="iigs amiga atarist dos x68000 dvx sdl3 web win32 win16 psp haiku haiku32 beos"
depsInstall=0 depsInstall=0
@ -90,7 +94,7 @@ groupMembers() {
printf '%s\n' "$id" printf '%s\n' "$id"
fi fi
;; ;;
iigs|amiga|atarist|dos|x68000|dvx) iigs|amiga|atarist|dos|x68000|dvx|sdl3|web|win32|win16|psp)
if [[ "$groups" == *" toolchain:$group "* || "$groups" == *" emulator:$group "* ]]; then if [[ "$groups" == *" toolchain:$group "* || "$groups" == *" emulator:$group "* ]]; then
printf '%s\n' "$id" printf '%s\n' "$id"
fi fi

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Amiga C toolchain: Bebbo's m68k-amigaos-gcc 6.5 (AmigaPorts), with # Amiga C toolchain: Bebbo's m68k-amigaos-gcc 6.5 (AmigaPorts), with
# binutils, libnix, clib2, the NDK 3.2 headers and vasm. Built from source # binutils, libnix, clib2, the NDK 3.2 headers and vasm. Built from source
# (~15-40 minutes). # (~15-40 minutes).

View file

@ -0,0 +1,39 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Amiga lowlevel.library (40.35, from Workbench 3.1's Libs drawer), which
# JoeyLib's Amiga port reads both joystick ports through (ReadJoyPort).
# Kickstart 3.1 has no lowlevel.library in ROM: AmigaOS loads it from LIBS:,
# so without it on the boot drive a program sees no joysticks, and joey-run
# and the Amiga joystick gate put it there. Cloanto still sells Workbench 3.1
# (Amiga Forever), so it is never downloaded from a public source: it comes
# from the private bundle or `install.sh import`, which also finds it inside
# a Workbench .adf disk image.
compDescription="Amiga firmware: lowlevel.library from Workbench 3.1 (private: bundle or import)"
compGroups="emulator:amiga"
compRequires=""
compHostDeps=""
compPrivateFile="toolchains/firmware/amiga/Libs/lowlevel.library"
compPin="$(privateSha1For "$compPrivateFile")"
compInstall() {
privateEnsure "$compPrivateFile"
}
compInstalled() {
privatePresent "$compPrivateFile"
}
compVerify() {
privatePresent "$compPrivateFile"
}
compEnv() {
envVar AMIGA_LOWLEVEL_LIBRARY "$JOEY_REPO/$compPrivateFile"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Amiga serial.device (37.4, from Workbench 3.1's Devs drawer). Kickstart 3.1 # Amiga serial.device (37.4, from Workbench 3.1's Devs drawer). Kickstart 3.1
# on the A500 has no serial.device in ROM: AmigaOS loads it from DEVS:, so a # on the A500 has no serial.device in ROM: AmigaOS loads it from DEVS:, so a
# JoeyLib program that opens the serial port needs it on the boot drive, and # JoeyLib program that opens the serial port needs it on the boot drive, and

View file

@ -0,0 +1,65 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# BeOS R5's own headers and libraries (make beos), copied from the x86
# system on your BeOS 5 Professional CD (installer/lib/beos.sh): the
# Development package's headers and start files and the system libraries,
# into toolchains/opt/beosR5/sysroot. The compiler is
# Haiku's gcc 2.95 (component haikuGcc2), the BeOS ABI;
# make/support/be/gcc2.sh points it at this sysroot.
compDescription="toolchain: BeOS R5 headers + libraries from your BeOS 5 Pro CD (beos; private media: import)"
compGroups="toolchain:beos"
compRequires="haikuGcc2 haikuTools"
compHostDeps="python3"
# shellcheck source=installer/lib/beos.sh
source "$JOEY_INSTALLER/lib/beos.sh"
# What the sysroot is made of, as "path on the CD -> folder in sysroot".
beosSysrootParts=(
"_packages_/Development/develop/headers headers"
"_packages_/Development/develop/lib develop-lib"
"beos/system/lib system-lib"
)
compInstall() {
local build
local part
local from
local to
local sysroot
build="$(freshBuildDir "$compId")"
beosSystemVolume "$build/system.bfs"
rm -rf "$compDir"
mkdir -p "$compDir/sysroot"
# bfs_shell takes host paths whole.
sysroot="$(cd "$compDir/sysroot" && pwd)"
for part in "${beosSysrootParts[@]}"; do
read -r from to <<< "$part"
printf 'cp -r /myfs/%s :%s\n' "$from" "$sysroot/$to"
done | beosBfs "$build/system.bfs" > "$build/bfs.log" 2>&1
compInstalled || die "the BeOS sysroot is incomplete; bfs_shell's log: $build/bfs.log"
dropBuildDir "$compId"
}
compInstalled() {
[ -f "$compDir/sysroot/headers/be/AppKit.h" ] &&
[ -f "$compDir/sysroot/system-lib/libbe.so" ] &&
[ -f "$compDir/sysroot/develop-lib/x86/start_dyn.o" ]
}
compVerify() {
compInstalled
}
compEnv() {
envVar BEOS_R5_SYSROOT "$compDir/sysroot"
}
# The CD and the steps that read it (after them: declare -f needs them).
compPin="$(privateSha1For "$BEOS_CD_FILE"):$(declare -f beosSystemVolume beosBfs compInstall | sha256sum | cut -d' ' -f1)"

View file

@ -0,0 +1,39 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# The BeOS R5 virtual machine the beos port's programs run in under QEMU
# (the gates): your BeOS 5 Professional CD's boot floppy and x86 system,
# made to run the job runner (installer/lib/beos.sh), which runs what a
# gate hands it on a second disk. Into toolchains/opt/beosVm; runs never
# write to it (QEMU's snapshot mode).
compDescription="emulator: BeOS R5 VM from your BeOS 5 Pro CD (beos; private media: import)"
compGroups="emulator:beos"
compRequires="qemu haikuTools"
compHostDeps="python3"
# shellcheck source=installer/lib/beos.sh
source "$JOEY_INSTALLER/lib/beos.sh"
compPin="$(beosVmPin)"
compInstall() {
beosVmPrepare "$compDir"
}
compInstalled() {
[ -s "$compDir/$BEOS_VM_SYSTEM_DISK" ] && [ -s "$compDir/$BEOS_VM_FLOPPY" ]
}
compVerify() {
beosVmVerify "$compDir"
}
compEnv() {
envVar BEOS_VM_DIR "$compDir"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# cadius: ProDOS disk-image tool used by every IIgs disk script. The # cadius: ProDOS disk-image tool used by every IIgs disk script. The
# scripts parse its CATALOG output, so it stays pinned to the mach-kernel # scripts parse its CATALOG output, so it stays pinned to the mach-kernel
# fork commit they were written against (v1.4.6). # fork commit they were written against (v1.4.6).

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# CWSDPMI r7: the DPMI host embedded into every DOS executable # CWSDPMI r7: the DPMI host embedded into every DOS executable
# (make/support/dos/embed-dpmi.sh prepends CWSDSTUB.EXE), so programs run # (make/support/dos/embed-dpmi.sh prepends CWSDSTUB.EXE), so programs run
# without a separate CWSDPMI.EXE. # without a separate CWSDPMI.EXE.

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# DOS C toolchain: DJGPP with gcc 12.2.0, prebuilt for Linux x86-64 by # DOS C toolchain: DJGPP with gcc 12.2.0, prebuilt for Linux x86-64 by
# andrewwutw/build-djgpp (release v3.4). # andrewwutw/build-djgpp (release v3.4).

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# DOSBox Staging 0.83.0: the DOS emulator (for DOS and for DVX, which runs # DOSBox Staging 0.83.0: the DOS emulator (for DOS and for DVX, which runs
# on it), as the project's own prebuilt Linux release (bundled libraries), # on it), as the project's own prebuilt Linux release (bundled libraries),
# because Debian/Ubuntu only package the old 0.74 and the gates are written # because Debian/Ubuntu only package the old 0.74 and the gates are written

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# DVX, the DOS desktop JoeyLib's dvx port runs in: the runtime the gates and # DVX, the DOS desktop JoeyLib's dvx port runs in: the runtime the gates and
# joey-run boot (dvx.exe with its libraries, widgets, programs, settings and # joey-run boot (dvx.exe with its libraries, widgets, programs, settings and
# system files) and its SDK (the headers, sdk.mk and the host tools every DVX # system files) and its SDK (the headers, sdk.mk and the host tools every DVX

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# X68000 C toolchain: yunkya2's elf2x68k (m68k-xelf gcc 13.4.0, binutils # X68000 C toolchain: yunkya2's elf2x68k (m68k-xelf gcc 13.4.0, binutils
# 2.44, newlib 4.5.0), prebuilt for Linux x86-64. m68k-xelf-gcc emits ELF; # 2.44, newlib 4.5.0), prebuilt for Linux x86-64. m68k-xelf-gcc emits ELF;
# its linker script runs elf2x68k.py (python3) to produce Human68k .X files. # its linker script runs elf2x68k.py (python3) to produce Human68k .X files.

View file

@ -0,0 +1,51 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Emscripten 6.0.11 through emsdk: the compiler the web port (make web)
# builds JoeyLib programs to WebAssembly with. emsdk is fetched at the
# release tag's commit and installs that one release of its toolchain
# (clang, binaryen, node) into toolchains/opt/emsdk; nothing reaches the
# user's home directory (EM_CACHE stays inside it too).
compDescription="web: Emscripten 6.0.11 (emsdk)"
compGroups="toolchain:web"
compRequires="host"
compHostDeps="git python3 xz"
compUrl="https://github.com/emscripten-core/emsdk.git"
compCommit="dd8e25632640cfc1fb570c7fa4cc374e8a5e5a72"
emsdkVersion="6.0.11"
compPin="$compCommit:$emsdkVersion"
compInstall() {
rm -rf "$compDir"
gitFetchCommit "$compUrl" "$compCommit" "$compDir"
(cd "$compDir" && ./emsdk install "$emsdkVersion" && ./emsdk activate --embedded "$emsdkVersion")
}
compInstalled() {
[ -x "$compDir/upstream/emscripten/emcc" ]
}
compVerify() {
local tmp
local status=1
tmp="$(mktemp -d)"
printf 'int answer(int x) { return x * 42; }\n' > "$tmp/t.c"
if EM_CONFIG="$compDir/.emscripten" EM_CACHE="$compDir/cache" "$compDir/upstream/emscripten/emcc" -c "$tmp/t.c" -o "$tmp/t.o" && [ -s "$tmp/t.o" ]; then
status=0
fi
rm -rf "$tmp"
return $status
}
compEnv() {
envVar EMSDK_DIR "$compDir"
envVar EMCC "$compDir/upstream/emscripten/emcc"
envVar EM_CONFIG "$compDir/.emscripten"
envVar EM_CACHE "$compDir/cache"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# EmuTOS 1.4 (GPL): a free TOS replacement for the Atari ST emulator, the # EmuTOS 1.4 (GPL): a free TOS replacement for the Atari ST emulator, the
# 512 KB US-English image. The gates and joey-run boot it instead of # 512 KB US-English image. The gates and joey-run boot it instead of
# Atari's copyrighted TOS. # Atari's copyrighted TOS.

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# FS-UAE 3.1.66: the Amiga emulator. Debian and Ubuntu package exactly this # FS-UAE 3.1.66: the Amiga emulator. Debian and Ubuntu package exactly this
# version; Fedora does not package FS-UAE at all, so on dnf systems it is # version; Fedora does not package FS-UAE at all, so on dnf systems it is
# built from the upstream release tarball into toolchains/opt/fsuae. # built from the upstream release tarball into toolchains/opt/fsuae.

View file

@ -0,0 +1,78 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# The Haiku x86_64 cross compiler (make haiku): gcc 13.3.0 and binutils for
# x86_64-unknown-haiku, Linux-hosted, as Haiku's own CI builds them from its
# buildtools (the toolchain layer of Haiku's published cross-compiler image,
# ghcr.io/haiku/cross-compiler:x86_64-r1beta5, pinned by its digest; the
# compiler is the same 13.3.0 2023_08_10 that R1/beta6 ships). Its sysroot
# is R1/beta6's: the system libraries out of the release image, haiku_devel
# from the release's repository and the compiler's runtime from HaikuPorts.
# Into toolchains/opt/haikuGcc: cross/ (the compiler) and sysroot/.
compDescription="haiku: gcc 13.3 cross compiler + R1/beta6 sysroot (Haiku x86_64)"
compGroups="toolchain:haiku"
compRequires="haikuTools"
compHostDeps="curl tar python3"
ociRepository="haiku/cross-compiler"
ociToolchainLayer="f6c3231b856d16aac56bf2ffe89a93c315a7bf03e6f62de3859ec2d899d5e815"
haikuArch="x86_64"
systemPackages="haiku-r1~beta6_hrev59866_79-1-x86_64.hpkg gcc_syslibs-13.3.0_2023_08_10-6-x86_64.hpkg"
develPackage="haiku_devel-r1~beta6_hrev59866_79-1-x86_64.hpkg"
develSha256="22fca2d887d394edf6f2af38b8a59d68fc693f41c759cad30576d2b48018a14f"
runtimeDevelPackage="gcc_syslibs_devel-13.3.0_2023_08_10-6-x86_64.hpkg"
runtimeDevelSha256="3db3465b7e390eb7f559690a83fa9244683582ba91322bc186d9b6f4d518ed2d"
compPin="$ociToolchainLayer:$develSha256:$runtimeDevelSha256"
# shellcheck source=installer/lib/haiku.sh
source "$JOEY_INSTALLER/lib/haiku.sh"
compInstall() {
local layer
local src
local package
local packages=()
layer="$(fetchOciBlob "$ociRepository" "$ociToolchainLayer" "haiku-cross-x86_64-r1beta5.tar.gz")"
src="$(freshBuildDir "$compId")"
tar -xzf "$layer" -C "$src" tools/cross-tools-x86_64
for package in $systemPackages; do
haikuIsoPackage "$haikuArch" "$package" "$src/$package"
packages+=("$src/$package")
done
packages+=("$(haikuRepoPackage "$HAIKU_REPO_BASE" "$haikuArch" "$HAIKU_REVISION" "$develPackage" "$develSha256")")
packages+=("$(haikuRepoPackage "$HAIKU_PORTS_BASE" "$haikuArch" current "$runtimeDevelPackage" "$runtimeDevelSha256")")
rm -rf "$compDir"
mkdir -p "$compDir"
mv "$src/tools/cross-tools-x86_64" "$compDir/cross"
# The image's own sysroot is an empty one from its build.
rm -rf "$compDir/cross/sysroot"
haikuSysroot "$compDir/sysroot" "${packages[@]}"
dropBuildDir "$compId"
}
compInstalled() {
[ -x "$compDir/cross/bin/x86_64-unknown-haiku-g++" ] && [ -e "$compDir/sysroot/boot/system/develop/lib/libbe.so" ]
}
# Link a C++ program against the Be API (libbe.so) as make/haiku.mk does.
compVerify() {
local tmp
local status=1
tmp="$(mktemp -d)"
printf '#include <Application.h>\nint main(void) { BApplication app("application/x-vnd.JoeyLib-check"); return app.InitCheck() == B_OK ? 0 : 1; }\n' > "$tmp/t.cpp"
if "$compDir/cross/bin/x86_64-unknown-haiku-g++" --sysroot="$compDir/sysroot" "$tmp/t.cpp" -o "$tmp/t" -lbe && [ -s "$tmp/t" ]; then
status=0
fi
rm -rf "$tmp"
return $status
}
compEnv() {
envVar HAIKU_CROSS "$compDir/cross/bin/x86_64-unknown-haiku-"
envVar HAIKU_SYSROOT "$compDir/sysroot"
}

View file

@ -0,0 +1,85 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# The Haiku x86_gcc2 cross compiler (make haiku32): gcc 2.95.3, the BeOS
# C++ ABI that 32-bit Haiku keeps as its primary compiler, Linux-hosted, as
# Haiku's own CI builds it from its buildtools (the toolchain layer of
# Haiku's published cross-compiler image,
# ghcr.io/haiku/cross-compiler:x86_gcc2h-r1beta5, pinned by its digest; the
# compiler is the same 2.95.3-haiku-2017_07_20 that R1/beta6 ships). Its
# sysroot is R1/beta6's: the system libraries out of the release image and
# haiku_devel from the release's repository. Into toolchains/opt/haikuGcc2:
# cross/ (the compiler) and sysroot/; make/support/be/gcc2.sh drives it.
#
# gcc 2.95 builds only as a 32-bit program, so it needs the host's 32-bit C
# library (Debian and Ubuntu: libc6-i386 or libc6:i386; Fedora: glibc.i686).
# Nothing else 32-bit: its binutils are 64-bit.
compDescription="haiku: gcc 2.95.3 cross compiler + R1/beta6 sysroot (Haiku x86, gcc2h)"
compGroups="toolchain:haiku32"
compRequires="haikuTools"
compHostDeps="curl tar python3"
ociRepository="haiku/cross-compiler"
ociToolchainLayer="ca91ed20dd950c53d8f85eb23f37f21c8634843d068896795c2a7d09bd365241"
haikuArch="x86_gcc2"
systemPackages="haiku-r1~beta6_hrev59866_79-1-x86_gcc2.hpkg"
develPackage="haiku_devel-r1~beta6_hrev59866_79-1-x86_gcc2.hpkg"
develSha256="fd091d128b0002b13ade7651a0a5d2fc259b8d9c09be45be56dbe2ec50aba0f4"
compPin="$ociToolchainLayer:$develSha256"
# The 32-bit program loader the compiler needs.
hostLoader32="/lib/ld-linux.so.2"
gcc2Driver="$JOEY_BUILD_SUPPORT/be/gcc2.sh"
# shellcheck source=installer/lib/haiku.sh
source "$JOEY_INSTALLER/lib/haiku.sh"
compInstall() {
local layer
local src
local package
local packages=()
[ -e "$hostLoader32" ] || die "gcc 2.95 is a 32-bit program and this machine cannot run one: install the 32-bit C library (Debian/Ubuntu: libc6-i386; Fedora: glibc.i686)"
layer="$(fetchOciBlob "$ociRepository" "$ociToolchainLayer" "haiku-cross-x86_gcc2h-r1beta5.tar.gz")"
src="$(freshBuildDir "$compId")"
tar -xzf "$layer" -C "$src" tools/cross-tools-x86_gcc2
for package in $systemPackages; do
haikuIsoPackage "$haikuArch" "$package" "$src/$package"
packages+=("$src/$package")
done
packages+=("$(haikuRepoPackage "$HAIKU_REPO_BASE" "$haikuArch" "$HAIKU_REVISION" "$develPackage" "$develSha256")")
rm -rf "$compDir"
mkdir -p "$compDir"
mv "$src/tools/cross-tools-x86_gcc2" "$compDir/cross"
# The image's own sysroot is an empty one from its build.
rm -rf "$compDir/cross/sysroot"
haikuSysroot "$compDir/sysroot" "${packages[@]}"
dropBuildDir "$compId"
}
compInstalled() {
[ -x "$compDir/cross/bin/i586-pc-haiku-g++" ] && [ -e "$compDir/sysroot/boot/system/develop/lib/libbe.so" ]
}
# Link a C++ program against the Be API (libbe.so) through the driver
# make/haiku32.mk uses.
compVerify() {
local tmp
local status=1
tmp="$(mktemp -d)"
printf '#include <Application.h>\nint main(void) { BApplication app("application/x-vnd.JoeyLib-check"); return app.InitCheck() == B_OK ? 0 : 1; }\n' > "$tmp/t.cpp"
if "$gcc2Driver" "$compDir" g++ "$tmp/t.cpp" -o "$tmp/t" -lbe && [ -s "$tmp/t" ]; then
status=0
fi
rm -rf "$tmp"
return $status
}
compEnv() {
envVar HAIKU32_ROOT "$compDir"
envVar HAIKU32_GCC2 "$gcc2Driver"
}

View file

@ -0,0 +1,87 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Haiku's own build-host tools, built from the R1/beta6 source: package
# (unpacks .hpkg packages: the Haiku sysroots are made from them) and
# bfs_shell (reads and writes Be File System volumes: the Haiku VM images
# get their job runner through it, and the gates hand programs to the VM
# and take results back on a BFS disk). jam, which builds them, comes from
# Haiku's buildtools at the same release. Installed into
# toolchains/opt/haikuTools; bin/ holds wrappers that find the tools'
# libraries.
compDescription="haiku: Haiku R1/beta6 host tools (package, bfs_shell; also read BeOS volumes)"
compGroups="toolchain:haiku toolchain:haiku32 toolchain:beos emulator:haiku emulator:haiku32 emulator:beos"
compRequires="host"
compHostDeps="build-tools git python3 zlib-dev zstd-dev bison flex"
compUrl="https://github.com/haiku/haiku.git"
compCommit="f6d86031a107e16f4fff6814e9aea20a39450842"
buildtoolsUrl="https://github.com/haiku/buildtools.git"
buildtoolsCommit="bfa561e3708c0e2d0155fb403b988ba515c9b16d"
compPin="$compCommit:$buildtoolsCommit"
hostTools="bfs_shell package"
compInstall() {
local src
local objects
local tool
src="$(freshBuildDir "$compId")"
gitFetchCommit "$compUrl" "$compCommit" "$src/haiku"
# Only jam is wanted from buildtools (the rest is the compilers'
# sources, gigabytes of them).
mkdir -p "$src/buildtools"
git -C "$src/buildtools" init -q
git -C "$src/buildtools" remote add origin "$buildtoolsUrl"
git -C "$src/buildtools" fetch -q --depth=1 --filter=blob:none origin "$buildtoolsCommit" || die "could not fetch $buildtoolsCommit from $buildtoolsUrl"
git -C "$src/buildtools" sparse-checkout set jam
git -C "$src/buildtools" checkout -q -f --detach FETCH_HEAD
make -C "$src/buildtools/jam" -j"$JOEY_JOBS"
mkdir -p "$src/haiku/generated"
(cd "$src/haiku/generated" && ../configure --host-only)
# The tools keep the attributes of the host's files (which have none
# here) in a folder named when they are built: theirs, not the build
# tree's, which goes.
(cd "$src/haiku/generated" && PATH="$src/buildtools/jam/bin.linuxx86:$PATH" jam -q -j"$JOEY_JOBS" -sHAIKU_BUILD_ATTRIBUTES_DIR="$compDir/attributes" '<build>bfs_shell' '<build>package')
objects="$src/haiku/generated/objects/linux"
rm -rf "$compDir"
mkdir -p "$compDir/bin" "$compDir/libexec" "$compDir/lib" "$compDir/attributes"
cp "$objects"/lib/*.so "$compDir/lib/"
for tool in $hostTools; do
cp "$(find "$objects" -type f -name "$tool" -perm -u+x -print -quit)" "$compDir/libexec/$tool"
printf '#!/bin/sh\n# Haiku build-host tool: its libraries are in ../lib.\ndir="$(cd "$(dirname "$0")/.." && pwd)"\nLD_LIBRARY_PATH="$dir/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$dir/libexec/%s" "$@"\n' "$tool" > "$compDir/bin/$tool"
chmod +x "$compDir/bin/$tool"
done
dropBuildDir "$compId"
}
compInstalled() {
[ -x "$compDir/bin/bfs_shell" ] && [ -x "$compDir/bin/package" ] && [ -x "$compDir/libexec/bfs_shell" ] && [ -x "$compDir/libexec/package" ] && [ -d "$compDir/attributes" ]
}
# Make a small BFS volume, write a file onto it and read it back; package
# starts. (Outputs are captured, not piped into grep: under pipefail a tool's
# own exit status, or SIGPIPE from an early grep, would fail the check.)
compVerify() {
local tmp
local readBack
local usage
tmp="$(mktemp -d)"
printf 'JoeyLib\n' > "$tmp/in.txt"
truncate -s 8M "$tmp/v.img"
"$compDir/bin/bfs_shell" --initialize "$tmp/v.img" Check > /dev/null 2>&1 || true
# After a copy, quit reports the volume busy; sync has written it.
printf 'cp :%s /myfs/in.txt\nsync\nquit\n' "$tmp/in.txt" | "$compDir/bin/bfs_shell" "$tmp/v.img" > /dev/null 2>&1 || true
readBack="$(printf 'cat /myfs/in.txt\nquit\n' | "$compDir/bin/bfs_shell" "$tmp/v.img" 2>&1 || true)"
usage="$("$compDir/bin/package" 2>&1 || true)"
rm -rf "$tmp"
[[ "$readBack" == *JoeyLib* && "$usage" == *"Usage: package"* ]]
}
compEnv() {
envVar HAIKU_TOOLS "$compDir/bin"
}

View file

@ -0,0 +1,42 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# The Haiku x86_64 virtual machine the haiku port's programs run in under
# QEMU (joey-run --port haiku, and the gates): the R1/beta6 anyboot image,
# made to boot straight to the desktop and run the job runner
# (installer/lib/haiku.sh), which runs what a gate or joey-run hands it on a
# second disk. Into toolchains/opt/haikuVm/haiku.img; runs never write to it
# (QEMU's snapshot mode).
compDescription="emulator: Haiku R1/beta6 x86_64 VM image (haiku)"
compGroups="emulator:haiku"
compRequires="qemu haikuTools"
compHostDeps="python3"
haikuArch="x86_64"
# shellcheck source=installer/lib/haiku.sh
source "$JOEY_INSTALLER/lib/haiku.sh"
compPin="$(haikuVmPin "$haikuArch")"
compInstall() {
mkdir -p "$compDir"
haikuVmPrepare "$haikuArch" "$compDir/haiku.img"
}
compInstalled() {
[ -s "$compDir/haiku.img" ]
}
compVerify() {
haikuVmVerify "$compDir/haiku.img"
}
compEnv() {
envVar HAIKU_VM_IMAGE "$compDir/haiku.img"
}

View file

@ -0,0 +1,42 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# The Haiku x86 (gcc2h, 32-bit) virtual machine the haiku32 port's programs
# run in under QEMU (joey-run --port haiku32, and the gates): the R1/beta6
# anyboot image, made to boot straight to the desktop and run the job runner
# (installer/lib/haiku.sh), which runs what a gate or joey-run hands it on a
# second disk. Into toolchains/opt/haikuVm32/haiku.img; runs never write to
# it (QEMU's snapshot mode).
compDescription="emulator: Haiku R1/beta6 x86 gcc2h VM image (haiku32)"
compGroups="emulator:haiku32"
compRequires="qemu haikuTools"
compHostDeps="python3"
haikuArch="x86_gcc2"
# shellcheck source=installer/lib/haiku.sh
source "$JOEY_INSTALLER/lib/haiku.sh"
compPin="$(haikuVmPin "$haikuArch")"
compInstall() {
mkdir -p "$compDir"
haikuVmPrepare "$haikuArch" "$compDir/haiku.img"
}
compInstalled() {
[ -s "$compDir/haiku.img" ]
}
compVerify() {
haikuVmVerify "$compDir/haiku.img"
}
compEnv() {
envVar HAIKU32_VM_IMAGE "$compDir/haiku.img"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Hatari 2.4.1: the Atari ST emulator. The ST gates parse its trace and # Hatari 2.4.1: the Atari ST emulator. The ST gates parse its trace and
# debugger output as Hatari 2.4 prints them. Debian and Ubuntu package # debugger output as Hatari 2.4 prints them. Debian and Ubuntu package
# 2.4.1; Fedora ships a different version, so on dnf systems 2.4.1 is built # 2.4.1; Fedora ships a different version, so on dnf systems 2.4.1 is built

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# What the test gates need to run the SDL/X11 emulators without a screen: # What the test gates need to run the SDL/X11 emulators without a screen:
# a virtual X server, key injection, screenshots, and PulseAudio's # a virtual X server, key injection, screenshots, and PulseAudio's
# capture tools for the audio gates. # capture tools for the audio gates.

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Host tools every JoeyLib setup needs: a native compiler for the in-repo # Host tools every JoeyLib setup needs: a native compiler for the in-repo
# tools, GNU make, git with LFS (the sample assets live in LFS), the # tools, GNU make, git with LFS (the sample assets live in LFS), the
# archive tools the other components unpack with, Python 3 with Pillow # archive tools the other components unpack with, Python 3 with Pillow

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Apple IIgs firmware and system software for MAME: # Apple IIgs firmware and system software for MAME:
# - the MAME apple2gs (ROM 03) and apple2gsr1 (ROM 01) ROM sets, and a2ssc # - the MAME apple2gs (ROM 03) and apple2gsr1 (ROM 01) ROM sets, and a2ssc
# (the Super Serial Card firmware the serial gates' slot card needs), from # (the Super Serial Card firmware the serial gates' slot card needs), from

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Amiga Kickstart 3.1 ROM. Cloanto still sells it (Amiga Forever), so it is # Amiga Kickstart 3.1 ROM. Cloanto still sells it (Amiga Forever), so it is
# never downloaded from a public source: it comes from the private bundle # never downloaded from a public source: it comes from the private bundle
# or `install.sh import`. The Amiga gates need it; AROS, FS-UAE's free # or `install.sh import`. The Amiga gates need it; AROS, FS-UAE's free

View file

@ -0,0 +1,36 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Amiga Kickstart 3.1 r40.68 ROM for the A1200, an AGA Amiga (68EC020), for
# running the Amiga gates on that machine as well as the A500 (JOEY_AMIGA_MODEL
# in scripts/lib/amigaGate.sh). Cloanto still sells it (Amiga Forever), so it
# is never downloaded from a public source: it comes from the private bundle
# or `install.sh import`. Optional: the A500 is the port's baseline.
compDescription="Amiga firmware: Kickstart 3.1 r40.68 for the A1200 (private: bundle or import)"
compGroups="emulator:aga optional"
compRequires=""
compHostDeps=""
compPrivateFile="toolchains/firmware/amiga/kickstartA1200.rom"
compPin="$(privateSha1For "$compPrivateFile")"
compInstall() {
privateEnsure "$compPrivateFile"
}
compInstalled() {
privatePresent "$compPrivateFile"
}
compVerify() {
privatePresent "$compPrivateFile"
}
compEnv() {
envVar KICKSTART_A1200_ROM "$JOEY_REPO/$compPrivateFile"
}

View file

@ -0,0 +1,36 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Amiga Kickstart 3.1 r40.70 ROM for the A4000T, an AGA Amiga (68040), for
# running the Amiga gates on that machine as well as the A500 (JOEY_AMIGA_MODEL
# in scripts/lib/amigaGate.sh). Cloanto still sells it (Amiga Forever), so it
# is never downloaded from a public source: it comes from the private bundle
# or `install.sh import`. Optional: the A500 is the port's baseline.
compDescription="Amiga firmware: Kickstart 3.1 r40.70 for the A4000T (private: bundle or import)"
compGroups="emulator:aga optional"
compRequires=""
compHostDeps=""
compPrivateFile="toolchains/firmware/amiga/kickstartA4000.rom"
compPin="$(privateSha1For "$compPrivateFile")"
compInstall() {
privateEnsure "$compPrivateFile"
}
compInstalled() {
privatePresent "$compPrivateFile"
}
compVerify() {
privatePresent "$compPrivateFile"
}
compEnv() {
envVar KICKSTART_A4000_ROM "$JOEY_REPO/$compPrivateFile"
}

View file

@ -0,0 +1,43 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# KPCOMM.DRV, the communications driver the win16 port's Windows runs with
# in place of Windows 3.1's COMM.DRV: both 16550A FIFOs, 115200 baud, any
# common IRQ. Built (installer/lib/winDriver.sh) from the mscomm project's
# drv folder, a checkout beside this repository (../mscomm/drv, or
# KPCOMM_DIR), with its Open Watcom makefile (watcom.mk), into
# toolchains/opt/kpcomm/kpcomm.drv; scripts/lib/win16Gate.sh installs it in
# each run's Windows as comm.drv.
compDescription="win16: KPCOMM.DRV comm driver for its Windows, built from ../mscomm/drv (KPCOMM_DIR)"
compGroups="emulator:win16"
compRequires="openWatcom"
compHostDeps="make"
# shellcheck source=installer/lib/winDriver.sh
source "$JOEY_INSTALLER/lib/winDriver.sh"
kpcommDir="${KPCOMM_DIR:-$(cd "$JOEY_REPO/.." && pwd)/mscomm/drv}"
compPin="dir:$kpcommDir:$(winDriverPin "$kpcommDir")"
compInstall() {
winDriverBuild "$kpcommDir" watcom.mk kpcomm.drv
}
compInstalled() {
[ -s "$compDir/kpcomm.drv" ]
}
compVerify() {
# A Windows module whose name is COMM (USER imports it by that name).
[ "$(head -c 2 "$compDir/kpcomm.drv")" = "MZ" ] && LC_ALL=C grep -q -a 'KPCOMM' "$compDir/kpcomm.drv"
}
compEnv() {
envVar KPCOMM_DRV "$compDir/kpcomm.drv"
}

View file

@ -0,0 +1,43 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# KPJOY.DRV, the joystick driver the win16 port's Windows runs with:
# Windows 3.1 has the joystick API (joyGetPos and the rest) but ships no
# driver for it, so without one no stick is ever seen. Built
# (installer/lib/winDriver.sh) from the kpjoy project, a checkout beside
# this repository (../kpjoy, or KPJOY_DIR), into
# toolchains/opt/kpjoy/kpjoy.drv; scripts/lib/win16Gate.sh installs it in
# each run's Windows as MMSYSTEM's joystick driver.
compDescription="win16: KPJOY.DRV joystick driver for its Windows, built from ../kpjoy (KPJOY_DIR)"
compGroups="emulator:win16"
compRequires="openWatcom"
compHostDeps="make"
# shellcheck source=installer/lib/winDriver.sh
source "$JOEY_INSTALLER/lib/winDriver.sh"
kpjoyDir="${KPJOY_DIR:-$(cd "$JOEY_REPO/.." && pwd)/kpjoy}"
compPin="dir:$kpjoyDir:$(winDriverPin "$kpjoyDir")"
compInstall() {
winDriverBuild "$kpjoyDir" Makefile kpjoy.drv
}
compInstalled() {
[ -s "$compDir/kpjoy.drv" ]
}
compVerify() {
# A Windows module whose name is KPJOY.
[ "$(head -c 2 "$compDir/kpjoy.drv")" = "MZ" ] && LC_ALL=C grep -q -a 'KPJOY' "$compDir/kpjoy.drv"
}
compEnv() {
envVar KPJOY_DRV "$compDir/kpjoy.drv"
}

View file

@ -1,8 +1,13 @@
# libxmp-lite 4.7.0: the MOD decoder the DOS, Atari ST and X68000 audio # Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# HALs compile in. Each port's makefile builds it from this source tree. # See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# libxmp-lite 4.7.0: the MOD decoder the DOS, Atari ST, X68000, SDL3, PSP,
# web, Win16, Win32, Haiku and BeOS audio HALs compile in. Each port's
# makefile builds it from this source tree.
compDescription="audio: libxmp-lite 4.7.0 source (DOS, Atari ST, X68000)" compDescription="audio: libxmp-lite 4.7.0 source (DOS, Atari ST, X68000, SDL3, PSP, web, Win16, Win32, Haiku, BeOS)"
compGroups="toolchain:dos toolchain:atarist toolchain:x68000" compGroups="toolchain:dos toolchain:atarist toolchain:x68000 toolchain:sdl3 toolchain:psp toolchain:web toolchain:win16 toolchain:win32 toolchain:haiku toolchain:haiku32 toolchain:beos"
compRequires="host" compRequires="host"
compHostDeps="tar" compHostDeps="tar"
compUrl="https://github.com/libxmp/libxmp/releases/download/libxmp-4.7.0/libxmp-lite-4.7.0.tar.gz" compUrl="https://github.com/libxmp/libxmp/releases/download/libxmp-4.7.0/libxmp-lite-4.7.0.tar.gz"

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Apple IIgs C toolchain: llvm816, a W65816 backend for llvm-mos, plus its # Apple IIgs C toolchain: llvm816, a W65816 backend for llvm-mos, plus its
# linker (link816 + omfEmit) and runtime. Cloned at a pinned commit and # linker (link816 + omfEmit) and runtime. Cloned at a pinned commit and
# built by the repo's own setup.sh; the first build is ~30-60 minutes. # built by the repo's own setup.sh; the first build is ~30-60 minutes.

View file

@ -0,0 +1,42 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# llvm-mingw 20260922, msvcrt flavour: the cross compiler the win32 port
# (make win32) builds Windows programs with -- clang, lld and the mingw-w64
# headers and libraries, prebuilt for Linux x86-64. The msvcrt flavour links
# against MSVCRT.DLL, the C library every Windows since 95 OSR2 carries (the
# ucrt one needs Windows 10's), so a program runs on the old Windows the
# port aims at. Programs are 32-bit (i686).
compDescription="win32: llvm-mingw 20260922 (msvcrt, i686 target)"
compGroups="toolchain:win32"
compRequires="host"
compHostDeps="tar xz"
compUrl="https://github.com/mstorsjo/llvm-mingw/releases/download/20260922/llvm-mingw-20260922-msvcrt-ubuntu-22.04-x86_64.tar.xz"
compSha256="17bbc667b96f7b1f02ce4a172d8cac4fa480927a1f649e788dee5914919566a1"
compPin="$compSha256"
compInstall() {
local archive
archive="$(fetchFile "$compUrl" "$compSha256")"
rm -rf "$compDir"
extractArchive "$archive" "$compDir" 1
}
compInstalled() {
[ -x "$compDir/bin/i686-w64-mingw32-clang" ]
}
compVerify() {
verifyCompiles "$compDir/bin/i686-w64-mingw32-clang"
}
compEnv() {
envVar WIN32_CC "$compDir/bin/i686-w64-mingw32-clang"
envVar WIN32_AR "$compDir/bin/i686-w64-mingw32-ar"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# MAME 0.264 with JoeyLib's patches (installer/patches/mame), built from # MAME 0.264 with JoeyLib's patches (installer/patches/mame), built from
# source as one binary holding only the two drivers the ports need: apple2gs # source as one binary holding only the two drivers the ports need: apple2gs
# (Apple IIgs) and x68k (Sharp X68000). Always built, never taken from the # (Apple IIgs) and x68k (Sharp X68000). Always built, never taken from the

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Merlin32 1.1: 65816 assembler, used only for the NinjaTrackerPlus audio # Merlin32 1.1: 65816 assembler, used only for the NinjaTrackerPlus audio
# replayer (third-party Merlin source). The release zip carries a prebuilt # replayer (third-party Merlin source). The release zip carries a prebuilt
# x86-64 Linux binary. # x86-64 Linux binary.

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Atari ST C toolchain: Vincent Riviere's m68k-atari-mint gcc 15.2 + # Atari ST C toolchain: Vincent Riviere's m68k-atari-mint gcc 15.2 +
# binutils 2.45, with MiNTLib 0.60.1, as prebuilt Linux x86-64 tarballs # binutils 2.45, with MiNTLib 0.60.1, as prebuilt Linux x86-64 tarballs
# from Thorsten Otto's mirror. Each tarball is rooted at usr/, so stripping # from Thorsten Otto's mirror. Each tarball is rooted at usr/, so stripping

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# NASM: assembler for the DOS port's x86 sources. Any 2.x release works, # NASM: assembler for the DOS port's x86 sources. Any 2.x release works,
# so it comes from the distribution. # so it comes from the distribution.

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# NinjaTrackerPlus: Ninjaforce's IIgs MOD replayer, shipped as Merlin # NinjaTrackerPlus: Ninjaforce's IIgs MOD replayer, shipped as Merlin
# source plus the PHP converter tools/joeymod uses for .MOD -> .NTP. # source plus the PHP converter tools/joeymod uses for .MOD -> .NTP.
# Redistribution is granted by the copyright holder. The URL is not # Redistribution is granted by the copyright holder. The URL is not

View file

@ -0,0 +1,59 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Open Watcom v2, the 2026-10-01 build for Linux x86-64: the compiler the
# win16 port (make win16) builds Windows 3.x programs with. Its Win386
# target compiles 32-bit flat-model C and binds it to Watcom's Windows
# supervisor (WIN386.EXT), which makes it a Windows 3.x NE executable that
# calls the 16-bit Windows API through the supervisor's covers. Its 16-bit
# Windows target builds the Windows 3.x drivers the win16 port's Windows
# runs with (components kpjoy and kpcomm). The release is the
# self-extracting installer, which is a zip archive; only the Linux tools,
# the headers, the 32- and 16-bit libraries and the supervisor are unpacked.
compDescription="win16: Open Watcom v2 2026-10-01 (Win386 and 16-bit Windows targets)"
compGroups="toolchain:win16"
compRequires="host"
compHostDeps="unzip"
compUrl="https://github.com/open-watcom/open-watcom-v2/releases/download/2026-10-01-Build/open-watcom-2_0-c-linux-x64"
compSha256="a961f3e02ce27bcd88428345dc57483457a623b6e718b6cee52c48d24ab8065f"
compPin="$compSha256"
compInstall() {
local archive
local file
# Every dated build's file has the same name; the cached copy carries
# the date, and .zip says how to unpack it.
archive="$(fetchFile "$compUrl" "$compSha256" open-watcom-2_0-c-linux-x64-2026-10-01.zip)"
rm -rf "$compDir"
mkdir -p "$compDir"
unzip -oq "$archive" 'binl64/*' 'binw/win386.ext' 'h/*' 'lib386/*' 'lib286/*' -d "$compDir"
# The zip keeps no permissions: the ELF programs among binl64's files
# are made executable.
for file in "$compDir"/binl64/*; do
if [ "$(head -c 4 "$file" | od -An -tx1 | tr -d ' \n')" = "7f454c46" ]; then
chmod 755 "$file"
fi
done
}
compInstalled() {
[ -x "$compDir/binl64/owcc" ] && [ -x "$compDir/binl64/wbind" ] && [ -f "$compDir/binw/win386.ext" ] &&
[ -f "$compDir/lib286/win/windows.lib" ]
}
compVerify() {
# owcc finds its compilers and its specs.owc on the PATH.
export WATCOM="$compDir"
export PATH="$compDir/binl64:$PATH"
verifyCompiles owcc -bwin386 "-I$compDir/h"
}
compEnv() {
envVar WIN16_WATCOM "$compDir"
}

View file

@ -0,0 +1,73 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# PPSSPP 1.20.4 with JoeyLib's patch (installer/patches/ppsspp): the PSP
# emulator the psp gates and joey-run run programs under. Only its headless
# test runner, PPSSPPHeadless, is built (no window, no sound card), from the
# release's source tarball, which carries its submodules, into
# toolchains/opt/ppsspp. ~5 minutes.
compDescription="emulator: PPSSPP 1.20.4 headless + JoeyLib patch (PSP)"
compGroups="emulator:psp"
compRequires="host"
compHostDeps="build-tools cmake python3 patch xz sdl2-dev gl-dev png-dev zlib-dev"
compUrl="https://github.com/hrydgard/ppsspp/releases/download/v1.20.4/ppsspp-1.20.4.tar.xz"
compSha256="4de21db3105d9d81a465a8a7e78c68ee3c0e0bf6597d1c1d530f7555f3ad8b31"
patchDir="$JOEY_PATCHES/ppsspp"
# Editing a patch rebuilds PPSSPP, so the patches are part of the pin.
compPin="$compSha256 $(cat "$patchDir"/*.patch | sha256sum | cut -d' ' -f1)"
compInstall() {
local src
local archive
local p
src="$(freshBuildDir "$compId")"
archive="$(fetchFile "$compUrl" "$compSha256")"
extractArchive "$archive" "$src" 1
for p in "$patchDir"/*.patch; do
info "applying $(basename "$p")"
patch -d "$src" -p1 -s -F0 --no-backup-if-mismatch < "$p"
done
# No FFmpeg (the tarball has no prebuilt one; JoeyLib programs play no
# PSP video), no GLU headers (GLEW_NO_GLU), and no ccache, which would
# write to the home directory.
cmake -S "$src" -B "$src/build" \
-DCMAKE_BUILD_TYPE=Release \
-DHEADLESS=ON \
-DUNITTEST=OFF \
-DUSING_QT_UI=OFF \
-DUSE_CCACHE=OFF \
-DUSE_DISCORD=OFF \
-DUSE_FFMPEG=OFF \
-DUSE_MINIUPNPC=OFF \
-DCMAKE_C_FLAGS=-DGLEW_NO_GLU \
-DCMAKE_CXX_FLAGS=-DGLEW_NO_GLU
cmake --build "$src/build" --target PPSSPPHeadless -j"$JOEY_JOBS"
rm -rf "$compDir"
install -D -m 755 "$src/build/PPSSPPHeadless" "$compDir/bin/PPSSPPHeadless"
dropBuildDir "$compId"
}
compInstalled() {
[ -x "$compDir/bin/PPSSPPHeadless" ]
}
# The usage text lists the patch's options; HOME is a scratch folder, as
# PPSSPP keeps its memory stick there.
compVerify() {
local tmp
local usage
tmp="$(mktemp -d)"
usage="$(HOME="$tmp" "$compDir/bin/PPSSPPHeadless" --help 2>&1 || true)"
rm -rf "$tmp"
[[ "$usage" == *"--strict-mem"* && "$usage" == *"--snapshot=FILE"* && "$usage" == *"--dump-audio"* && "$usage" == *"--input=FILE"* ]] && verifyLinked "$compDir/bin"
}
compEnv() {
envVar PPSSPP_HEADLESS "$compDir/bin/PPSSPPHeadless"
}

View file

@ -0,0 +1,54 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# pspdev v20261001: the PSP homebrew toolchain the psp port (make psp)
# builds with -- psp-gcc, the PSPSDK, newlib, and the tools that make an
# EBOOT.PBP (mksfo, pack-pbp, psp-fixup-imports) -- prebuilt by the pspdev
# project for each distribution family, unpacked into toolchains/opt/pspdev.
# Fedora gets the Fedora build, Debian the Debian one and every other apt
# system (Ubuntu, Mint) the Ubuntu one: each needs its own glibc.
compDescription="psp: pspdev v20261001 (psp-gcc, PSPSDK)"
compGroups="toolchain:psp"
compRequires="host"
compHostDeps="tar"
pspdevRelease="v20261001"
pspdevHostId="$( (. /etc/os-release 2>/dev/null && printf '%s' "${ID:-}") || true)"
if [ "$(distroFamily)" = "dnf" ]; then
pspdevFlavour="fedora-latest"
compSha256="7874d4d696f1abe58d3d17fd8ae365e9b129c4bea16b383bf708655037c0e21c"
elif [ "$pspdevHostId" = "debian" ]; then
pspdevFlavour="debian-latest"
compSha256="39b20efc7c8492cdbd9929178f45afc801dabb0967b7c882573520f22536920c"
else
pspdevFlavour="ubuntu-latest-x86_64"
compSha256="a86efe624e770005290919617859e9df24bd8fcd3e364f4587f23ec7364b0acd"
fi
compUrl="https://github.com/pspdev/pspdev/releases/download/$pspdevRelease/pspdev-$pspdevFlavour.tar.gz"
compPin="$compSha256"
compInstall() {
local archive
# Every flavour's file has the same name: cache it under the release's.
archive="$(fetchFile "$compUrl" "$compSha256" "pspdev-$pspdevRelease-$pspdevFlavour.tar.gz")"
rm -rf "$compDir"
extractArchive "$archive" "$compDir" 1
}
compInstalled() {
[ -x "$compDir/bin/psp-gcc" ] && [ -x "$compDir/bin/pack-pbp" ]
}
compVerify() {
PSPDEV="$compDir" verifyCompiles "$compDir/bin/psp-gcc" && verifyLinked "$compDir/bin"
}
compEnv() {
envVar PSPDEV "$compDir"
envVar PSP_CC "$compDir/bin/psp-gcc"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# PTPlayer 6.4: Frank Wille's ProTracker replayer for the Amiga, used by # PTPlayer 6.4: Frank Wille's ProTracker replayer for the Amiga, used by
# the Amiga audio HAL. Aminet's URL is not versioned, so the pin is the # the Amiga audio HAL. Aminet's URL is not versioned, so the pin is the
# archive's checksum. # archive's checksum.

View file

@ -0,0 +1,87 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# QEMU 11.1.2: the PC emulator the Haiku ports (src/hosted/be) are run and
# gated in, x86_64 and i386 system emulation only, with KVM when /dev/kvm is
# usable. Built from the release source into toolchains/opt/qemu, with
# pixman 0.46.4 (its display library, which distributions split into a -dev
# package that may be missing) built first as a static library and linked
# in. SDL2 gives joey-run its window; the wav audio backend the audio gate
# records through is always built in.
compDescription="emulator: QEMU 11.1.2 + pixman 0.46.4 (Haiku, BeOS)"
compGroups="emulator:haiku emulator:haiku32 emulator:beos"
compRequires="host"
compHostDeps="build-tools pkg-config python3 python3-venv ninja meson glib-dev zlib-dev sdl2-dev pulse-dev asound-dev"
compUrl="https://download.qemu.org/qemu-11.1.2.tar.xz"
compSha256="731b5681e4bb18be313231579b8efd0296c5b015fa36dc533874b639ba838016"
pixmanUrl="https://cairographics.org/releases/pixman-0.46.4.tar.xz"
pixmanSha256="a098c33924754ad43f981b740f6d576c70f9ed1006e12221b1845431ebce1239"
compPin="$compSha256:$pixmanSha256"
compInstall() {
local archive
local pixmanArchive
local src
local pixmanSrc
local pixmanPrefix
archive="$(fetchFile "$compUrl" "$compSha256")"
pixmanArchive="$(fetchFile "$pixmanUrl" "$pixmanSha256")"
src="$(freshBuildDir "$compId")"
pixmanSrc="$src/pixman"
pixmanPrefix="$src/pixman-install"
extractArchive "$pixmanArchive" "$pixmanSrc" 1
meson setup "$pixmanSrc/build" "$pixmanSrc" \
--prefix="$pixmanPrefix" \
--libdir=lib \
--buildtype=release \
-Ddefault_library=static \
-Dtests=disabled \
-Ddemos=disabled \
-Dgtk=disabled \
-Dlibpng=disabled
ninja -C "$pixmanSrc/build" -j"$JOEY_JOBS" install
extractArchive "$archive" "$src/qemu" 1
(
cd "$src/qemu"
PKG_CONFIG_PATH="$pixmanPrefix/lib/pkgconfig" ./configure \
--prefix="$compDir" \
--target-list=x86_64-softmmu,i386-softmmu \
--enable-kvm \
--enable-sdl \
--disable-gtk \
--disable-docs \
--disable-werror \
--disable-guest-agent \
--audio-drv-list=pa,alsa,sdl
make -j"$JOEY_JOBS"
rm -rf "$compDir"
make install
)
dropBuildDir "$compId"
}
compInstalled() {
[ -x "$compDir/bin/qemu-system-x86_64" ] && [ -x "$compDir/bin/qemu-system-i386" ] && [ -x "$compDir/bin/qemu-img" ]
}
# Both emulators start and know the devices the Haiku VMs use: the HD audio
# controller and codec, and the VGA card.
compVerify() {
local machine
local devices
for machine in x86_64 i386; do
devices="$("$compDir/bin/qemu-system-$machine" -device help 2>&1)" || return 1
[[ "$devices" == *'"intel-hda"'* && "$devices" == *'"hda-duplex"'* && "$devices" == *'"VGA"'* ]] || return 1
done
"$compDir/bin/qemu-system-x86_64" -audiodev help 2>&1 | grep -qx wav
}
compEnv() {
envVar QEMU_DIR "$compDir"
}

View file

@ -0,0 +1,68 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# SDL 3.4.18: the library the sdl3 port (src/hosted/sdl3) opens its window,
# reads input and plays audio through. Distributions package SDL3 too late
# or not at all (Linux Mint 22.3 has only SDL2), so it is built from the
# release source as a static library into toolchains/opt/sdl3; the programs
# link it in and run without an SDL3 on the machine. SDL loads the X11,
# Wayland, PulseAudio, PipeWire and ALSA client libraries at run time, so
# their headers must be present when it is built or those backends are left
# out (the dummy video and audio drivers the gates use are always there).
compDescription="hosted: SDL 3.4.18, static (sdl3 port)"
compGroups="toolchain:sdl3"
compRequires="host"
compHostDeps="build-tools cmake pkg-config x11-dev xext-dev xi-dev xrandr-dev xcursor-dev xfixes-dev xss-dev xkbcommon-dev wayland-dev wayland-protocols decor-dev pulse-dev asound-dev pipewire-dev udev-dev dbus-dev drm-dev gbm-dev egl-dev gl-dev gles-dev"
compUrl="https://github.com/libsdl-org/SDL/releases/download/release-3.4.18/SDL3-3.4.18.tar.gz"
compSha256="9c75cf16330322c217dedd2e0609f1124f1b54b8633e763467b4684d0f4334a3"
compPin="$compSha256"
compInstall() {
local archive
local src
archive="$(fetchFile "$compUrl" "$compSha256")"
src="$(freshBuildDir "$compId")"
extractArchive "$archive" "$src" 1
cmake -S "$src" -B "$src/build" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$compDir" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DSDL_SHARED=OFF \
-DSDL_STATIC=ON \
-DSDL_TESTS=OFF \
-DSDL_EXAMPLES=OFF
cmake --build "$src/build" -j"$JOEY_JOBS"
rm -rf "$compDir"
cmake --install "$src/build"
dropBuildDir "$compId"
}
compInstalled() {
[ -f "$compDir/lib/libSDL3.a" ] && [ -f "$compDir/lib/pkgconfig/sdl3.pc" ]
}
# Link a program against the static library the way make/sdl3.mk does and
# run it: it prints the version of the SDL it carries.
compVerify() {
local tmp
local status=1
tmp="$(mktemp -d)"
printf '#include <SDL3/SDL.h>\n#include <stdio.h>\nint main(void) { int v = SDL_GetVersion(); printf("%%d.%%d.%%d\\n", SDL_VERSIONNUM_MAJOR(v), SDL_VERSIONNUM_MINOR(v), SDL_VERSIONNUM_MICRO(v)); return 0; }\n' > "$tmp/t.c"
# shellcheck disable=SC2046
if cc "$tmp/t.c" -o "$tmp/t" $(PKG_CONFIG_PATH="$compDir/lib/pkgconfig" pkg-config --cflags --static --libs sdl3) \
&& [ "$("$tmp/t")" = "3.4.18" ]; then
status=0
fi
rm -rf "$tmp"
return $status
}
compEnv() {
envVar SDL3_DIR "$compDir"
}

View file

@ -0,0 +1,55 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# SDL 3 built with pspdev, static, for the psp port (make psp): the same
# release source the sdl3 component builds for the host (its pin is read from
# sdl3.sh, so there is one), cross-compiled with pspdev's CMake toolchain
# file into toolchains/opt/sdl3Psp. pspdev carries an SDL3 of its own; the
# port links this one, so every SDL3 port runs the same SDL.
compDescription="psp: SDL 3 for the PSP, static (psp port)"
compGroups="toolchain:psp"
compRequires="host pspdev"
compHostDeps="cmake"
sdl3Url="$(compQuery sdl3 compUrl)"
sdl3Sha256="$(compQuery sdl3 compSha256)"
compPin="$sdl3Sha256:$(compQuery pspdev compPin)"
compInstall() {
local archive
local src
archive="$(fetchFile "$sdl3Url" "$sdl3Sha256")"
src="$(freshBuildDir "$compId")"
extractArchive "$archive" "$src" 1
export PSPDEV="$JOEY_OPT/pspdev"
cmake -S "$src" -B "$src/build" \
-DCMAKE_TOOLCHAIN_FILE="$PSPDEV/psp/share/pspdev.cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$compDir" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DSDL_SHARED=OFF \
-DSDL_STATIC=ON \
-DSDL_TESTS=OFF \
-DSDL_EXAMPLES=OFF
cmake --build "$src/build" -j"$JOEY_JOBS"
rm -rf "$compDir"
cmake --install "$src/build"
dropBuildDir "$compId"
}
compInstalled() {
[ -f "$compDir/lib/libSDL3.a" ] && [ -f "$compDir/include/SDL3/SDL.h" ]
}
compVerify() {
compInstalled
}
compEnv() {
envVar SDL3_PSP_DIR "$compDir"
}

View file

@ -0,0 +1,63 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# SDL 3 built with Emscripten, static, for the web port (make web): the same
# release source the sdl3 component builds for the host (its pin is read from
# sdl3.sh, so there is one), with JoeyLib's patches for SDL's Emscripten code
# (installer/patches/sdl3Web), compiled to WebAssembly into
# toolchains/opt/sdl3Web.
compDescription="web: SDL 3 for Emscripten, static (web port)"
compGroups="toolchain:web"
compRequires="host emsdk"
compHostDeps="cmake patch"
sdl3Url="$(compQuery sdl3 compUrl)"
sdl3Sha256="$(compQuery sdl3 compSha256)"
patchDir="$JOEY_PATCHES/sdl3Web"
# Editing a patch rebuilds SDL, so the patches are part of the pin.
compPin="$sdl3Sha256:$(compQuery emsdk compPin):$(cat "$patchDir"/*.patch | sha256sum | cut -d' ' -f1)"
compInstall() {
local archive
local src
local p
local emsdk="$JOEY_OPT/emsdk"
archive="$(fetchFile "$sdl3Url" "$sdl3Sha256")"
src="$(freshBuildDir "$compId")"
extractArchive "$archive" "$src" 1
for p in "$patchDir"/*.patch; do
info "applying $(basename "$p")"
patch -d "$src" -p1 -s -F0 --no-backup-if-mismatch < "$p"
done
export EM_CONFIG="$emsdk/.emscripten"
export EM_CACHE="$emsdk/cache"
"$emsdk/upstream/emscripten/emcmake" cmake -S "$src" -B "$src/build" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$compDir" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DSDL_SHARED=OFF \
-DSDL_STATIC=ON \
-DSDL_TESTS=OFF \
-DSDL_EXAMPLES=OFF
cmake --build "$src/build" -j"$JOEY_JOBS"
rm -rf "$compDir"
cmake --install "$src/build"
dropBuildDir "$compId"
}
compInstalled() {
[ -f "$compDir/lib/libSDL3.a" ] && [ -f "$compDir/include/SDL3/SDL.h" ]
}
compVerify() {
compInstalled
}
compEnv() {
envVar SDL3_WEB_DIR "$compDir"
}

View file

@ -0,0 +1,41 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Windows for Workgroups 3.11, set up unattended on a DOSBox Staging PC with
# the S3 Trio64V+ driver at 800x600 in 256 colours and Windows' own Sound
# Blaster driver (installer/lib/win16.sh): what the win16 port's programs
# run on for joey-run and the gates (scripts/lib/win16Gate.sh). Made from
# your own install disc and S3 driver disk -- private files, never
# downloaded: ./install.sh import PATH (the ISO and the driver's .zip) or
# the private bundle. Into toolchains/opt/win311/c, drive C:; runs copy it.
compDescription="emulator: Windows for Workgroups 3.11 on DOSBox (win16; private media: import)"
compGroups="emulator:win16"
compRequires="dosbox"
compHostDeps="python3 xvfb"
# shellcheck source=installer/lib/win16.sh
source "$JOEY_INSTALLER/lib/win16.sh"
compPin="$(win16Pin)"
compInstall() {
win16Prepare "$compDir"
}
compInstalled() {
[ -f "$compDir/c/WINDOWS/WIN.COM" ]
}
compVerify() {
win16Verify "$compDir/c"
}
compEnv() {
envVar WIN16_C "$compDir/c"
}

View file

@ -0,0 +1,42 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Wine 11.19 (Kron4ek's portable build, new WoW64 mode): runs the win32
# port's programs for joey-run and the gates. Relocatable, so it is unpacked
# into toolchains/opt/wine and needs no system install; the WoW64 build runs
# 32-bit programs without any 32-bit Linux libraries. Every run uses a
# private Wine prefix (WINEPREFIX) in a temporary directory, never ~/.wine.
compDescription="emulator: Wine 11.19 portable (win32 port)"
compGroups="emulator:win32"
compRequires="host"
compHostDeps="tar xz"
compUrl="https://github.com/Kron4ek/Wine-Builds/releases/download/11.19/wine-11.19-amd64-wow64.tar.xz"
compSha256="a1fe858b45d12c9b16b91c7601d9b934f68430f7b6b95e240212ab6e2a198d8a"
compPin="$compSha256"
compInstall() {
local archive
archive="$(fetchFile "$compUrl" "$compSha256")"
rm -rf "$compDir"
extractArchive "$archive" "$compDir" 1
}
compInstalled() {
[ -x "$compDir/bin/wine" ]
}
compVerify() {
local version
version="$("$compDir/bin/wine" --version 2>/dev/null || true)"
[[ "$version" == wine-11.19* ]]
}
compEnv() {
envVar WINE "$compDir/bin/wine"
}

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# X68000 character-generator (font) ROM. Not part of Sharp's free release, # X68000 character-generator (font) ROM. Not part of Sharp's free release,
# so it comes from the private bundle or `install.sh import`. MAME's x68000 # so it comes from the private bundle or `install.sh import`. MAME's x68000
# driver will not start without it (it warns about the checksum of this # driver will not start without it (it warns about the checksum of this

View file

@ -1,3 +1,7 @@
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Sharp X68000 firmware from Sharp's own free release (2000, published by # Sharp X68000 firmware from Sharp's own free release (2000, published by
# the X68000 LIBRARY): the original IPL-ROM (all `-bios ipl10` needs) and # the X68000 LIBRARY): the original IPL-ROM (all `-bios ipl10` needs) and
# the Human68k 3.02 system disk. The CG (font) ROM is not part of that # the Human68k 3.02 system disk. The CG (font) ROM is not part of that

View file

@ -73,6 +73,24 @@ xext-dev libxext-dev libXext-devel
xinerama-dev libxinerama-dev libXinerama-devel xinerama-dev libxinerama-dev libXinerama-devel
gl-dev libgl-dev mesa-libGL-devel gl-dev libgl-dev mesa-libGL-devel
# ---- SDL3 build (the sdl3 port): the headers of every client library SDL
# loads at run time, or it leaves that video/audio backend out
xrandr-dev libxrandr-dev libXrandr-devel
xcursor-dev libxcursor-dev libXcursor-devel
xfixes-dev libxfixes-dev libXfixes-devel
xss-dev libxss-dev libXScrnSaver-devel
xkbcommon-dev libxkbcommon-dev libxkbcommon-devel
wayland-dev libwayland-dev wayland-devel
wayland-protocols wayland-protocols wayland-protocols-devel
decor-dev libdecor-0-dev libdecor-devel
pipewire-dev libpipewire-0.3-dev pipewire-devel
udev-dev libudev-dev systemd-devel
dbus-dev libdbus-1-dev dbus-devel
drm-dev libdrm-dev libdrm-devel
gbm-dev libgbm-dev mesa-libgbm-devel
egl-dev libegl-dev mesa-libEGL-devel
gles-dev libgles-dev mesa-libGLES-devel
# ---- emulators packaged by the distribution # ---- emulators packaged by the distribution
hatari hatari hatari hatari hatari hatari
fs-uae fs-uae - fs-uae fs-uae -
@ -89,3 +107,8 @@ zip zip zip
glib-dev libglib2.0-dev glib2-devel glib-dev libglib2.0-dev glib2-devel
openal-dev libopenal-dev openal-soft-devel openal-dev libopenal-dev openal-soft-devel
png-dev libpng-dev libpng-devel png-dev libpng-dev libpng-devel
# ---- QEMU and pixman builds (the Haiku ports' emulator); QEMU's configure
# makes a Python venv for its own meson
meson meson meson
python3-venv python3-venv python3

Some files were not shown because too many files have changed in this diff Show more