124 lines
5.7 KiB
C
124 lines
5.7 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 lifecycle: configuration, initialization, shutdown.
|
|
|
|
#ifndef JOEYLIB_CORE_H
|
|
#define JOEYLIB_CORE_H
|
|
|
|
#include "platform.h"
|
|
#include "types.h"
|
|
|
|
typedef struct {
|
|
// Runtime compiled-sprite cache size. 0 selects a per-platform
|
|
// default: 8 KB on the IIgs, 64 KB on the Amiga, ST, and X68000, and
|
|
// 32 KB on DOS, DVX, and Win16 (the 68k/x86 emitters are ~4-8x less
|
|
// code-dense than the 65816's, so a 32x32 sprite can need 8-16 KB
|
|
// there). The ports that interpret every sprite have no cache and
|
|
// allocate none. Size against jlSpriteCompiledSize() when tuning.
|
|
// Every port takes as much of the request as the machine has, and
|
|
// jlInit fails only if it can have none (jlSpriteCodegenBytesTotal
|
|
// says what it got): on the IIgs up to four Memory Manager blocks of
|
|
// at most 64 KB, each inside one bank (a compiled sprite cannot cross
|
|
// a bank), so at most 256 KB; elsewhere one block, halved until the
|
|
// heap has room, down to 4 KB.
|
|
uint32_t codegenBytes;
|
|
// True: leave audio off. Every audio call is then silent, as on a
|
|
// machine without sound, and the program pays nothing for audio:
|
|
// on the IIgs no replayer read from disk, on DOS and the Amiga no
|
|
// interrupt hooked. jlInit starts audio otherwise, and jlShutdown
|
|
// stops it.
|
|
bool noAudio;
|
|
} jlConfigT;
|
|
|
|
// Initialize the library, audio too (unless config->noAudio). Returns true
|
|
// on success; sound that does not start is not a failure (modules and
|
|
// effects are then silent, and the log says so). On failure, jlLastError()
|
|
// returns a human-readable description of why, on every port.
|
|
bool jlInit(const jlConfigT *config);
|
|
|
|
// Shut down the library, audio first, releasing the library's own
|
|
// resources. Surfaces and sprites the program created are not freed:
|
|
// destroy them first. A program that returns from main or calls exit
|
|
// without it has it run then (jlInit registers it with atexit).
|
|
void jlShutdown(void);
|
|
|
|
// Returns the most recent error message, or NULL if none.
|
|
const char *jlLastError(void);
|
|
|
|
// Returns the platform identifier string (e.g., "Apple IIgs", "MS-DOS").
|
|
const char *jlPlatformName(void);
|
|
|
|
// Returns the library version string (e.g., "1.0.0").
|
|
const char *jlVersionString(void);
|
|
|
|
// Allocate a large or persistent buffer, backed by the platform's
|
|
// native allocator rather than the small C heap. Use this (not malloc)
|
|
// for anything that exceeds the per-allocation or total ceiling of the
|
|
// stock C heap -- on the IIgs the whole C heap is one Memory Manager
|
|
// block of 32 KB to 48 KB (or, if that block cannot be had, what the
|
|
// link left in the program's bank, which can be tiny), so multi-KB
|
|
// caches and frame buffers must come from the IIgs Memory Manager
|
|
// instead. Returns NULL on failure. The returned pointer is NOT
|
|
// zero-filled.
|
|
void *jlAlloc(uint32_t bytes);
|
|
|
|
// Release a buffer returned by jlAlloc. NULL is accepted and ignored.
|
|
// Never mix jlFree and free: on the IIgs a jlAlloc block is a Memory
|
|
// Manager handle, and either one given the other's block corrupts memory.
|
|
void jlFree(void *p);
|
|
|
|
// memcpy with a 32-bit count. Same contract as memcpy (no overlap); every
|
|
// port runs its libc memcpy (on the IIgs MVN block moves at 7 cycles a
|
|
// byte, split at bank boundaries).
|
|
void jlMemCopy(void *dst, const void *src, uint32_t bytes);
|
|
|
|
// Block the calling thread until the next display vertical blank, to
|
|
// pace a game loop to the display's refresh. On the machine ports it
|
|
// waits for the display's own vertical blank. The hosted ports, and DVX
|
|
// in a window, have none to wait for: there it waits for the next tick
|
|
// of a virtual frame clock (60 Hz hosted, 70 Hz DVX), and nothing keeps
|
|
// a present from tearing.
|
|
void jlWaitVBL(void);
|
|
|
|
// Monotonic 16-bit frame counter, kept by an interrupt or derived from a
|
|
// clock, so it does not miss frames however seldom it is read (except on
|
|
// an X68000 whose system refused JoeyLib's frame interrupt: there it
|
|
// counts only while jlWaitVBL, jlFrameCount, or jlStagePresent is
|
|
// called). It wraps about every 18 minutes at 60 Hz, so compare two
|
|
// readings by subtraction. Used by benchmarks and frame-rate-independent
|
|
// animation.
|
|
uint16_t jlFrameCount(void);
|
|
|
|
// Display frame rate in Hz: 60 on the IIgs (50 on a PAL machine), 50 on
|
|
// the Amiga (60 on an NTSC machine that cannot show PAL), 50 or 60 on
|
|
// the ST as the machine is set (71 with a monochrome monitor), 70 on DOS
|
|
// and DVX, 55 on the X68000 (56 under MAME), and 60 on every hosted port. The actual VBL cadence may
|
|
// drift slightly; the value reported here is what benchmarks divide
|
|
// by to convert iters-per-N-frames to ops/sec.
|
|
uint16_t jlFrameHz(void);
|
|
|
|
// Monotonic wall-clock millisecond counter since jlInit, to the
|
|
// millisecond (a frame at a time only where the machine's timer is
|
|
// taken: docs/ApiCore.adoc). Call it at least once every 15 minutes, or
|
|
// the time between two calls can be lost. Two consecutive calls
|
|
// separated by a long render report the true elapsed time, not the
|
|
// number of VBLs that fired.
|
|
uint32_t jlMillisElapsed(void);
|
|
|
|
// Deterministic, seedable pseudo-random generator. Bit-identical
|
|
// output across every JoeyLib port for a given seed, since stdlib
|
|
// rand() varies wildly between platforms and C libraries.
|
|
// The underlying algorithm is xorshift32 (Marsaglia): period 2^32-1,
|
|
// no multiply, suitable for games but not for cryptography.
|
|
uint32_t jlRandom(void);
|
|
|
|
// Return a value in [0, bound). bound == 0 returns 0.
|
|
uint16_t jlRandomRange(uint16_t bound);
|
|
|
|
// Seed the generator. Any 32-bit value is accepted; a seed of 0 is
|
|
// remapped to 1 since xorshift cannot escape the all-zero state.
|
|
void jlRandomSeed(uint32_t seed);
|
|
|
|
#endif
|