joeylib2/include/joey/platform.h

665 lines
30 KiB
C

// 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.
//
// Exactly one JOEYLIB_PLATFORM_* must be defined per build. The build
// system normally sets this via -D; if absent, the header attempts to
// auto-detect from compiler-predefined macros.
#ifndef JOEYLIB_PLATFORM_H
#define JOEYLIB_PLATFORM_H
// ----- Auto-detect platform from compiler macros if not preset -----
#if !defined(JOEYLIB_PLATFORM_IIGS) && \
!defined(JOEYLIB_PLATFORM_AMIGA) && \
!defined(JOEYLIB_PLATFORM_ATARIST) && \
!defined(JOEYLIB_PLATFORM_DOS) && \
!defined(JOEYLIB_PLATFORM_X68000) && \
!defined(JOEYLIB_PLATFORM_DVX) && \
!defined(JOEYLIB_PLATFORM_HOSTED) && \
!defined(JOEYLIB_PLATFORM_BLANK)
#if defined(__DJGPP__) || defined(__MSDOS__)
#define JOEYLIB_PLATFORM_DOS
#elif defined(__amigaos__) || defined(AMIGA) || defined(__amigaos4__)
#define JOEYLIB_PLATFORM_AMIGA
#elif defined(__atarist__) || defined(__MINT__) || defined(__TOS__)
#define JOEYLIB_PLATFORM_ATARIST
#elif defined(__APPLE2GS__) || defined(__GNO__)
#define JOEYLIB_PLATFORM_IIGS
#elif defined(__x68k__) || defined(__X68000__) || defined(__HUMAN68K__)
#define JOEYLIB_PLATFORM_X68000
#else
#error "JoeyLib: unknown platform; define JOEYLIB_PLATFORM_<TARGET> explicitly via -D"
#endif
#endif
// JOEYLIB_PLATFORM_BLANK is the copy-to-start template for a new port (see
// src/blank/blank.c). It has no auto-detect macro -- bring it up by building
// with -DJOEYLIB_PLATFORM_BLANK.
//
// 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
// 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 -----
#if (defined(JOEYLIB_PLATFORM_IIGS) + \
defined(JOEYLIB_PLATFORM_AMIGA) + \
defined(JOEYLIB_PLATFORM_ATARIST) + \
defined(JOEYLIB_PLATFORM_DOS) + \
defined(JOEYLIB_PLATFORM_X68000) + \
defined(JOEYLIB_PLATFORM_DVX) + \
defined(JOEYLIB_PLATFORM_HOSTED) + \
defined(JOEYLIB_PLATFORM_BLANK)) != 1
#error "JoeyLib: exactly one JOEYLIB_PLATFORM_* must be defined"
#endif
// ----- Derived CPU markers -----
#if defined(JOEYLIB_PLATFORM_IIGS)
#define JL_CPU_65816
#define JL_ENDIAN_LITTLE
#define JL_NATIVE_CHUNKY
#define JL_PLATFORM_NAME "Apple IIgs"
#elif defined(JOEYLIB_PLATFORM_AMIGA)
#define JL_CPU_68000
#define JL_ENDIAN_BIG
#define JL_NATIVE_PLANAR
#define JL_HAS_BLITTER
#define JL_HAS_COPPER
#define JL_PLATFORM_NAME "Commodore Amiga"
#elif defined(JOEYLIB_PLATFORM_ATARIST)
#define JL_CPU_68000
#define JL_ENDIAN_BIG
#define JL_NATIVE_PLANAR
// JOEYLIB_ATARI_STE is the STe build (make ste): the same port using the
// BLiTTER, DMA sound, the 4-bit palette and (1040 STe) the enhanced
// joystick ports, for STe and Mega STe only.
#if defined(JOEYLIB_ATARI_STE)
#define JL_PLATFORM_NAME "Atari STe"
#else
#define JL_PLATFORM_NAME "Atari ST"
#endif
#elif defined(JOEYLIB_PLATFORM_DOS)
#define JL_CPU_X86
#define JL_ENDIAN_LITTLE
#define JL_NATIVE_CHUNKY
#define JL_PLATFORM_NAME "MS-DOS"
#elif defined(JOEYLIB_PLATFORM_X68000)
// The stage is four separate 1bpp planes in main RAM (src/x68000/halPlanar.c,
// the Amiga's layout), and a present copies its dirty rows into the text
// plane at $E00000, which is four 1bpp planes too. The text plane has one
// 16-colour palette, so per-line SCB palettes are reloaded as the beam scans
// by a CRTC raster interrupt (src/x68000/x68kRasterIsr.s).
#define JL_CPU_68000
#define JL_ENDIAN_BIG
#define JL_NATIVE_PLANAR
#define JL_PLATFORM_NAME "Sharp X68000"
#elif defined(JOEYLIB_PLATFORM_DVX)
// The DOS stage (chunky 4bpp, x86 sprite JIT and tile walker from
// src/x86/), shown in a DVX window, or on DVX's full screen, instead of
// on the VGA.
#define JL_CPU_X86
#define JL_ENDIAN_LITTLE
#define JL_NATIVE_CHUNKY
#define JL_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, sprites are interpreted -- except on Windows 3.x, whose
// 32-bit code runs on a 386 like DOS's: sprites are compiled to x86 code
// as on DOS (Win386's flat code and data selectors share one base, so the
// code arena runs as it is).
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define JL_ENDIAN_BIG
#else
#define JL_ENDIAN_LITTLE
#endif
#define JL_NATIVE_CHUNKY
#if defined(JOEYLIB_HOSTED_WIN16)
#define JL_CPU_X86
#else
#define JL_SPRITE_INTERPRETED
#endif
#if defined(JOEYLIB_HOSTED_SDL3) && defined(__PSP__)
#define JL_PLATFORM_NAME "PSP"
#elif defined(JOEYLIB_HOSTED_SDL3)
#define JL_PLATFORM_NAME "SDL3"
#elif defined(JOEYLIB_HOSTED_WIN32)
#define JL_PLATFORM_NAME "Windows"
#elif defined(JOEYLIB_HOSTED_WIN16)
#define JL_PLATFORM_NAME "Windows 3.x"
#elif defined(JOEYLIB_HOSTED_BE) && defined(__HAIKU__)
#define JL_PLATFORM_NAME "Haiku"
#elif defined(JOEYLIB_HOSTED_BE)
#define JL_PLATFORM_NAME "BeOS"
#else
#error "JoeyLib: JOEYLIB_PLATFORM_HOSTED needs a backend, e.g. -DJOEYLIB_HOSTED_SDL3"
#endif
#elif defined(JOEYLIB_PLATFORM_BLANK)
// 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
// these (or switch to JL_NATIVE_PLANAR) once you know your hardware.
#define JL_ENDIAN_LITTLE
#define JL_NATIVE_CHUNKY
#define JL_SPRITE_INTERPRETED
#define JL_PLATFORM_NAME "Blank Template"
#endif
// JL_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>) -----
//
// A machine #define-s JL_HAS_<OP> for each overridable platform op it replaces
// with its own (asm / native) implementation in src/<machine>/. Ops a machine
// does NOT claim fall back to the portable-C default in src/generic/, selected
// at compile time (no runtime dispatch). The jlp<Op> macros/prototypes in
// src/core/port.h read this table. This is the new lib's equivalent of the
// original joeylib's joey.h JL_HAS_* table.
#if defined(JOEYLIB_PLATFORM_IIGS)
#define JL_HAS_SURFACE_CLEAR // iigsSurfaceClearFastInner (stage), macro
#define JL_HAS_DRAW_PIXEL // iigsDrawPixelInner, macro
#define JL_HAS_DRAW_LINE // iigsDrawLineInner, macro
#define JL_HAS_DRAW_CIRCLE // iigsDrawCircleInner, macro
#define JL_HAS_FILL_CIRCLE // iigsFillCircleInner (stage), macro -- returns bool
#define JL_HAS_FILL_RECT // iigsFillRectMark (stage, fused mark), macro -> generic else
#define JL_HAS_TILE_FILL // iigsTileFillInner, macro
#define JL_HAS_TILE_COPY // iigsTileCopyInner, macro
#define JL_HAS_TILE_COPY_MASKED // iigsTileCopyMaskedInner, macro
#define JL_HAS_TILE_PASTE // iigsTilePasteInner, macro
#define JL_HAS_TILE_PASTE_MONO // iigsTilePasteMonoInner (stage), macro -> generic else
#define JL_HAS_TILE_PASTE_GLYPH // iigsTilePasteGlyphMark (stage, mark fused), macro -> generic else
#define JL_HAS_TILE_SNAP // iigsTileSnapInner, macro
#define JL_HAS_SURFACE_COPY_RECT // jlpSurfaceCopyRect: iigsCopyRectRows
// [dp],y row copies (short rows lose to
// memcpy's per-call setup), function
#define JL_HAS_SPRITE_DRAW // chunky -> codegen; planes mirror is noop macro
#define JL_HAS_SPRITE_SAVE // noop macro (codegen path saves)
#define JL_HAS_SPRITE_RESTORE // noop macro
#define JL_HAS_FLOOD_WALK_AND_SCANS // iigsFloodWalkAndScansInner (all-in-one), macro
#define JL_HAS_BIG_ALLOC // Memory Manager NewHandle/DisposeHandle, function
#define JL_HAS_STAGE_ALLOC_PIXELS // pinned $01:2000 display memory, function
#define JL_HAS_STAGE_FREE_PIXELS // no-op (pinned), function
#define JL_HAS_FRAME_HZ // runtime 50/60 from battery RAM, function
// (frameCount: port.h #defines jlpFrameCount straight to iigsGetTickWord,
// the VBL heartbeat tick read -- no function override to register here.)
#define JL_HAS_WAIT_VBL // the VBL heartbeat count advancing, function
// audio: every real port implements the full engine
#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_PLAY_SFX_STREAM_RAW
#define JL_HAS_AUDIO_SET_PAN
#define JL_HAS_AUDIO_STOP_SFX
#define JL_HAS_AUDIO_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_CRITICAL_ENTER
#define JL_HAS_AUDIO_CRITICAL_EXIT
#define JL_HAS_AUDIO_FRAME_TICK
// lifecycle / present / input (every real port implements)
#define JL_HAS_INIT
#define JL_HAS_SHUTDOWN
#define JL_HAS_PRESENT
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL
#define JL_HAS_JOYSTICK_RESET
// serial add-on (optional; SCC modem/printer + 6551 Super Serial Card)
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_POLL
#define JL_HAS_SERIAL_READ
#define JL_HAS_SERIAL_WRITE
#define JL_HAS_SERIAL_AVAILABLE
#define JL_HAS_SERIAL_FLUSH
// Application-driven DTR: how a program hangs up (jlSerialSetDtr).
#define JL_HAS_SERIAL_SET_DTR
// Application-driven RTS for a caller doing its own receive-side flow control (jlSerialSetRts).
#define JL_HAS_SERIAL_SET_RTS
// save files + disk space: delete (GS/OS Destroy), dir-ensure (GS/OS Create
// $2001, storageType 13), disk-free (GS/OS Volume $2008 on prefix 1's
// volume, where SAVES/ is).
#define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE
#define JL_HAS_DISK_FREE
// millisElapsed: generic frameCount*1000/frameHz (no override)
#elif defined(JOEYLIB_PLATFORM_AMIGA)
#define JL_HAS_SURFACE_CLEAR // planar clear, function
#define JL_HAS_DRAW_PIXEL // amigaPlanarSetPixel, function
#define JL_HAS_DRAW_LINE // amigaPlanarLine, function
#define JL_HAS_DRAW_CIRCLE // amiga planar circle, function
#define JL_HAS_FILL_CIRCLE // amiga planar fill circle, function -- returns bool
#define JL_HAS_FILL_RECT // amiga planar fill rect, function
#define JL_HAS_TILE_FILL // amiga planar tile fill, inline (amigaTile.h)
#define JL_HAS_TILE_COPY // amiga planar tile copy, inline (amigaTile.h)
#define JL_HAS_TILE_COPY_MASKED // amiga planar masked copy, inline (amigaTile.h)
#define JL_HAS_TILE_PASTE // amiga planar tile paste, inline (amigaTile.h)
#define JL_HAS_TILE_SNAP // amiga planar tile snap, inline (amigaTile.h)
#define JL_HAS_TILE_PASTE_MONO // amiga planar mono colorize+paste, inline (amigaTile.h)
#define JL_HAS_TILE_PASTE_GLYPH // amiga 1bpp glyph -> planes, inline (amigaTile.h)
#define JL_HAS_SPRITE_DRAW // amiga planar sprite draw, function
#define JL_HAS_SPRITE_SAVE // amiga planar sprite save, function
#define JL_HAS_SPRITE_RESTORE // amiga planar sprite restore, function
#define JL_HAS_FLOOD_WALK_PLANES // amiga planar flood walk-out, function
#define JL_HAS_FLOOD_SCAN_ROW_PLANES // amiga planar flood scan-row, function
#define JL_HAS_SURFACE_COPY_PLANES // amiga blitter plane copy, function
#define JL_HAS_SURFACE_COPY_RECT // amiga per-plane rect row copy, function
#define JL_HAS_SAMPLE_PIXEL // amiga planar nibble decode, function
#define JL_HAS_SURFACE_HASH // amiga planar hash, function
#define JL_HAS_SURFACE_LOAD_FILE // amiga planar load, function
#define JL_HAS_SURFACE_SAVE_FILE // amiga planar save, function
#define JL_HAS_STAGE_ALLOC_PIXELS // amiga: NULL (no chunky stage shadow), function
#define JL_HAS_SURFACE_ALLOC_PIXELS // amiga: NULL (planar storage), function
#define JL_HAS_SURFACE_ALLOC_PORT_DATA // amiga AmigaPlanarT + chip planes, function
#define JL_HAS_SURFACE_FREE_PORT_DATA // amiga FreeMem planes, function
#define JL_HAS_FRAME_HZ // 50 PAL / 60 NTSC, measured at init, function
#define JL_HAS_FRAME_COUNT // VBL-server counter, function
#define JL_HAS_WAIT_VBL // WaitTOF, function
// audio: every real port implements the full engine
#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_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_CRITICAL_ENTER
#define JL_HAS_AUDIO_CRITICAL_EXIT
#define JL_HAS_AUDIO_FRAME_TICK
// lifecycle / present / input (every real port implements)
#define JL_HAS_INIT
#define JL_HAS_SHUTDOWN
#define JL_HAS_PRESENT
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL
#define JL_HAS_JOYSTICK_RESET
// serial add-on (optional; serial.device)
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_POLL
#define JL_HAS_SERIAL_READ
#define JL_HAS_SERIAL_WRITE
#define JL_HAS_SERIAL_AVAILABLE
#define JL_HAS_SERIAL_FLUSH
// Application-driven DTR: how a program hangs up (jlSerialSetDtr).
#define JL_HAS_SERIAL_SET_DTR
// Application-driven RTS for a caller doing its own receive-side flow control (jlSerialSetRts).
#define JL_HAS_SERIAL_SET_RTS
// save files + disk space (CreateDir/DeleteFile/Info via dos.library)
#define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE
#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)
#elif defined(JOEYLIB_PLATFORM_ATARIST)
#define JL_HAS_SURFACE_CLEAR // planar clear, function
#define JL_HAS_DRAW_PIXEL // stPlanarSetPixel, function
#define JL_HAS_DRAW_LINE // stPlanarLine, function
#define JL_HAS_DRAW_CIRCLE // st planar circle, function
#define JL_HAS_FILL_CIRCLE // st planar fill circle, function -- returns bool
#define JL_HAS_FILL_RECT // st planar fill rect, function
#define JL_HAS_TILE_FILL // st planar tile fill, inline (stTile.h)
#define JL_HAS_TILE_COPY // st planar tile copy, inline (stTile.h)
#define JL_HAS_TILE_COPY_MASKED // st planar masked copy, inline (stTile.h)
#define JL_HAS_TILE_PASTE // st planar tile paste, inline (stTile.h)
#define JL_HAS_TILE_SNAP // st planar tile snap, inline (stTile.h)
#define JL_HAS_TILE_PASTE_MONO // st planar mono colorize+paste, inline (stTile.h)
#define JL_HAS_TILE_PASTE_GLYPH // st 1bpp glyph -> planes, inline (stTile.h)
#define JL_HAS_SPRITE_DRAW // st planar sprite draw, function
#define JL_HAS_SPRITE_SAVE // st planar sprite save, function
#define JL_HAS_SPRITE_RESTORE // st planar sprite restore, function
#define JL_HAS_FLOOD_WALK_PLANES // st planar flood walk-out, function
#define JL_HAS_FLOOD_SCAN_ROW_PLANES // st planar flood scan-row, function
#define JL_HAS_SURFACE_COPY_PLANES // st planar buffer memcpy, function
#define JL_HAS_SURFACE_COPY_RECT // st interleaved rect row memcpy, function
#define JL_HAS_SAMPLE_PIXEL // st planar nibble decode, function
#define JL_HAS_SURFACE_HASH // st planar hash, function
#define JL_HAS_SURFACE_LOAD_FILE // st planar load, function
#define JL_HAS_SURFACE_SAVE_FILE // st planar save, function
#define JL_HAS_STAGE_ALLOC_PIXELS // st: NULL (no chunky stage shadow), function
#define JL_HAS_SURFACE_ALLOC_PIXELS // st: NULL (planar storage), function
#define JL_HAS_SURFACE_ALLOC_PORT_DATA // st StPlanarT + interleaved buffer, function
#define JL_HAS_SURFACE_FREE_PORT_DATA // st free buffer, function
#define JL_HAS_FRAME_HZ // the machine's 50 / 60 (71 mono), function
#define JL_HAS_FRAME_COUNT // VBL-ISR counter, function
#define JL_HAS_WAIT_VBL // frame-counter wait, function
#define JL_HAS_MILLIS_ELAPSED // Supexec 200 Hz tick, function
// audio: every real port implements the full engine
#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_STOP_SFX
#define JL_HAS_AUDIO_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_CRITICAL_ENTER
#define JL_HAS_AUDIO_CRITICAL_EXIT
#define JL_HAS_AUDIO_FRAME_TICK
#define JL_HAS_MOD_MIX_RUN // the module player's 8-bit mix, src/m68k/modMix.s
// lifecycle / present / input (every real port implements)
#define JL_HAS_INIT
#define JL_HAS_SHUTDOWN
#define JL_HAS_PRESENT
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL
#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)
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_POLL
#define JL_HAS_SERIAL_READ
#define JL_HAS_SERIAL_WRITE
#define JL_HAS_SERIAL_AVAILABLE
#define JL_HAS_SERIAL_FLUSH
// Application-driven DTR: how a program hangs up (jlSerialSetDtr).
#define JL_HAS_SERIAL_SET_DTR
// Application-driven RTS for a caller doing its own receive-side flow control (jlSerialSetRts).
#define JL_HAS_SERIAL_SET_RTS
// save files + disk space (POSIX mkdir/remove + GEMDOS Dfree)
#define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE
#define JL_HAS_DISK_FREE
#elif defined(JOEYLIB_PLATFORM_DOS)
// chunky generics: surface clear, draw pixel/line/circle, fill circle/rect,
// tiles, surface readers, allocation -- DOS overrides the timing services
// plus the whole-map tile walker (src/x86/x86Tile.h, dispatched via the
// jlpTileMapPaste alias from tile.c's shared whole-map arm like the ST
// engine; not a jlp op, so no JL_HAS flag).
// (The planar dual-write hooks are not linked to generics: every chunky port
// elides them to ((void)0) in port.h's shared chunky block, PERF-AUDIT #42.)
#define JL_HAS_FRAME_HZ // VGA ~70, function
#define JL_HAS_FRAME_COUNT // from the millisecond clock (70 a second), function
#define JL_HAS_WAIT_VBL // $3DA retrace poll, function
#define JL_HAS_MILLIS_ELAPSED // uclock / audio-ISR tick, function
// audio: every real port implements the full engine
#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_STOP_SFX
#define JL_HAS_AUDIO_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_CRITICAL_ENTER
#define JL_HAS_AUDIO_CRITICAL_EXIT
#define JL_HAS_AUDIO_FRAME_TICK
// lifecycle / present / input (every real port implements)
#define JL_HAS_INIT
#define JL_HAS_SHUTDOWN
#define JL_HAS_PRESENT
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL
#define JL_HAS_JOYSTICK_RESET
// serial add-on (optional; 8250/16550 UART on a COM port, IRQ RX ring)
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_POLL
#define JL_HAS_SERIAL_READ
#define JL_HAS_SERIAL_WRITE
#define JL_HAS_SERIAL_AVAILABLE
#define JL_HAS_SERIAL_FLUSH
// Application-driven DTR: how a program hangs up (jlSerialSetDtr).
#define JL_HAS_SERIAL_SET_DTR
// Application-driven RTS for a caller doing its own receive-side flow control (jlSerialSetRts).
#define JL_HAS_SERIAL_SET_RTS
// save files + disk space (POSIX mkdir/remove + int21h/36h disk-free)
#define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE
#define JL_HAS_DISK_FREE
#elif defined(JOEYLIB_PLATFORM_X68000)
// Platform services in src/x68000/hal.c, the serial add-on in
// src/x68000/serial.c, and planar graphics adapted from the Amiga
// (identical surface layout, src/x68000/halPlanar.c).
#define JL_HAS_SURFACE_CLEAR
#define JL_HAS_DRAW_PIXEL
#define JL_HAS_DRAW_LINE
#define JL_HAS_DRAW_CIRCLE
#define JL_HAS_FILL_CIRCLE
#define JL_HAS_FILL_RECT
#define JL_HAS_TILE_FILL
#define JL_HAS_TILE_COPY
#define JL_HAS_TILE_COPY_MASKED
#define JL_HAS_TILE_PASTE
#define JL_HAS_TILE_SNAP
#define JL_HAS_TILE_PASTE_GLYPH // x68k 1bpp glyph -> planes, inline (x68kTile.h)
#define JL_HAS_TILE_PASTE_MONO
#define JL_HAS_SPRITE_DRAW
#define JL_HAS_SPRITE_SAVE
#define JL_HAS_SPRITE_RESTORE
#define JL_HAS_FLOOD_WALK_PLANES
#define JL_HAS_FLOOD_SCAN_ROW_PLANES
#define JL_HAS_SURFACE_COPY_PLANES
#define JL_HAS_SURFACE_COPY_RECT
#define JL_HAS_SAMPLE_PIXEL
#define JL_HAS_SURFACE_HASH
#define JL_HAS_SURFACE_LOAD_FILE
#define JL_HAS_SURFACE_SAVE_FILE
#define JL_HAS_STAGE_ALLOC_PIXELS
#define JL_HAS_SURFACE_ALLOC_PIXELS
#define JL_HAS_SURFACE_ALLOC_PORT_DATA
#define JL_HAS_SURFACE_FREE_PORT_DATA
#define JL_HAS_INIT // _iocs_crtmod display bring-up
#define JL_HAS_SHUTDOWN // restore the previous CRT mode
#define JL_HAS_PRESENT // copy the stage's dirty plane rows into the text plane
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL // IOCS work area keys/mouse, PPI joystick ports
#define JL_HAS_JOYSTICK_RESET
#define JL_HAS_WAIT_VBL // the V-DISP frame count moving
#define JL_HAS_FRAME_COUNT // V-DISP edges, counted on MFP Timer A via _VDISPST
#define JL_HAS_FRAME_HZ // measured at init: 55 on hardware, 56 under MAME
// Human68k's MFP Timer C: 100 Hz off the crystal, read to the millisecond
// through its live count (src/x68000/hal.c, "Clocks").
#define JL_HAS_MILLIS_ELAPSED
// Save add-on: Human68k _dos_dskfre / _dos_mkdir, structurally the ST HAL.
#define JL_HAS_DISK_FREE
#define JL_HAS_SAVE_DELETE
#define JL_HAS_SAVE_DIR_ENSURE
// Serial add-on: RSDRV.SYS transmit and line setup, receive on the
// port's own SCC interrupt (src/x68000/x68kSccRxIsr.s).
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_POLL
#define JL_HAS_SERIAL_AVAILABLE
#define JL_HAS_SERIAL_READ
#define JL_HAS_SERIAL_WRITE
#define JL_HAS_SERIAL_FLUSH
// Application-driven DTR: how a program hangs up (jlSerialSetDtr).
#define JL_HAS_SERIAL_SET_DTR
// Application-driven RTS for a caller doing its own receive-side flow control (jlSerialSetRts).
#define JL_HAS_SERIAL_SET_RTS
// Audio. CHIP side on the YM2151 (OPM): tone voices + noise, which is what
// the portable JYM1 tracker rides, with no CPU mixing.
#define JL_HAS_AUDIO_INIT
#define JL_HAS_AUDIO_SHUTDOWN
#define JL_HAS_AUDIO_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_CRITICAL_ENTER
#define JL_HAS_AUDIO_CRITICAL_EXIT
#define JL_HAS_AUDIO_FRAME_TICK
#define JL_HAS_MOD_MIX_RUN // the module player's 8-bit mix, src/m68k/modMix.s
#define JL_HAS_CODE_WRITTEN // the X68030's caches, after codegen
// SAMPLE side (src/x68000/audioPcm.c): the module player + the shared 5-slot SFX
// overlay, encoded to MSM6258 ADPCM and played via _iocs_adpcmlot. Separate
// device from the OPM, so chip music and digital audio do not contend.
#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_STOP_SFX
#elif defined(JOEYLIB_PLATFORM_DVX)
// A window on the DVX desktop, or DVX's full screen (src/dvx). The
// graphics are the DOS port's:
// the chunky generics, the x86 whole-map tile walker (src/x86/x86Tile.h,
// through the jlpTileMapPaste alias) and the x86 sprite JIT. DVX's
// libraries supply the services.
#define JL_HAS_INIT // the program's window
#define JL_HAS_SHUTDOWN
#define JL_HAS_PRESENT // dirty rows through per-palette tables into the window or onto the full screen
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL // held-key table, onKey characters, onMouse, joystick.lib
#define JL_HAS_JOYSTICK_RESET
#define JL_HAS_WAIT_VBL // gameFrameWait at a virtual 70 Hz (the DOS rate)
#define JL_HAS_FRAME_COUNT
#define JL_HAS_FRAME_HZ
#define JL_HAS_MILLIS_ELAPSED // platformMicros
// DVX programs share one current directory: DATA/ is found beside the
// .app, SAVES/ and joeylog.txt go in its settings folder (fileRoot.h).
#define JL_HAS_FILE_ROOTS
// save files + disk space (platformMkdirRecursive, remove, platformDiskSpace)
#define JL_HAS_SAVE_DIR_ENSURE
#define JL_HAS_SAVE_DELETE
#define JL_HAS_DISK_FREE
// audio through DVX's audio.lib and music.lib (src/dvx/audio.c). The tick
// callback runs in program time (audio.lib is not interrupt-safe), so 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_VOICE
#define JL_HAS_AUDIO_NOISE
#define JL_HAS_AUDIO_TICK_REGISTER
#define JL_HAS_AUDIO_FRAME_TICK
// serial add-on (optional; a COM port through DVX's rs232 library, which
// owns the UARTs for every program -- src/dvx/serial.c)
#define JL_HAS_SERIAL_OPEN
#define JL_HAS_SERIAL_CLOSE
#define JL_HAS_SERIAL_POLL
#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
#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 the module player, the SFX slots, three
// square-wave voices and YM-style noise) 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_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)
// Copy-to-start template. It overrides ONLY the platform SERVICES (TODO
// stubs in src/blank/blank.c). Everything graphical -- draw / tile / sprite
// primitives, surface readers, allocation, bigAlloc, millisElapsed -- comes
// from the portable-C generics for free, so a chunky port renders correctly
// before you write a line of graphics code. Add a JL_HAS_<OP> here + an
// override in blank.c only when you want to accelerate a specific op.
#define JL_HAS_INIT // bring up your display mode
#define JL_HAS_SHUTDOWN // restore it
#define JL_HAS_PRESENT // blit the chunky stage to your framebuffer
#define JL_HAS_INPUT_INIT
#define JL_HAS_INPUT_SHUTDOWN
#define JL_HAS_INPUT_POLL // read your keyboard into gKeyState[]
#define JL_HAS_JOYSTICK_RESET
#define JL_HAS_WAIT_VBL // pace to the display
#define JL_HAS_FRAME_COUNT // a monotonic frame/refresh counter
#define JL_HAS_FRAME_HZ // your refresh rate in Hz
// audio: left to the no-op generics (your port links + runs silent). Add
// JL_HAS_AUDIO_* + overrides in blank.c when you wire up sound.
#endif
// ----- Library version -----
#define JL_VERSION_MAJOR 1
#define JL_VERSION_MINOR 0
#define JL_VERSION_PATCH 0
#define JL_VERSION_STRING "1.0.0"
#endif