== Core and Lifecycle Declared in ``, included by ``. === jlConfigT [source,c] ---- typedef struct { uint32_t codegenBytes; } jlConfigT; ---- [cols="1,1,4", options="header"] |=== |Field |Type |Description |`codegenBytes` |`uint32_t` |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 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 free bank exists. Size it against `jlSpriteCompiledSize()`. |=== === jlInit [source,c] ---- bool jlInit(const jlConfigT *config); ---- Initialises the library: takes over the display, allocates the stage and the codegen arena, and brings up input. Must be called before any other JoeyLib function. [cols="1,1,4", options="header"] |=== |Parameter |Type |Description |`config` |`const jlConfigT *` |Configuration. Must not be `NULL`. |=== *Returns:* `true` on success. On failure returns `false` and `jlLastError()` describes the reason. === jlShutdown [source,c] ---- void jlShutdown(void); ---- Shuts the library down, restoring the display mode, releasing all library resources and un-hooking any interrupt vectors the port installed. Call it on every exit path; skipping it can leave the machine unusable. *Parameters:* none. *Returns:* nothing. === jlLastError [source,c] ---- const char *jlLastError(void); ---- *Parameters:* none. *Returns:* the most recent error message, or `NULL` if there has been none. The string is library-owned; do not free it. === jlPlatformName [source,c] ---- const char *jlPlatformName(void); ---- *Parameters:* none. *Returns:* a human-readable platform identifier, for example `"Apple IIgs"`, `"MS-DOS"` or `"DVX"`. Library-owned. === jlVersionString [source,c] ---- const char *jlVersionString(void); ---- *Parameters:* none. *Returns:* the library version, for example `"1.0.0"`. Library-owned. === jlAlloc [source,c] ---- void *jlAlloc(uint32_t bytes); ---- Allocates a large or persistent buffer from the platform's native allocator rather than the small C heap. *Use this instead of `malloc` for anything substantial.* On the IIgs the C heap lives in bank 0 and is tiny, with a single `malloc` capped around 32 KB, so multi-kilobyte caches and frame buffers must come from the Memory Manager instead. [cols="1,1,4", options="header"] |=== |Parameter |Type |Description |`bytes` |`uint32_t` |Number of bytes required. |=== *Returns:* a pointer to the block, or `NULL` on failure. The memory is *not* zero-filled. === jlFree [source,c] ---- void jlFree(void *p); ---- Releases a buffer from `jlAlloc`. [cols="1,1,4", options="header"] |=== |Parameter |Type |Description |`p` |`void *` |Block to release. `NULL` is accepted and ignored. |=== *Returns:* nothing. === jlMemCopy [source,c] ---- void jlMemCopy(void *dst, const void *src, uint32_t bytes); ---- Copies a block. Same contract as `memcpy`, including that the regions must not overlap, with a 32-bit byte count on every port. It is the port's libc `memcpy`; on the IIgs that is `MVN` block moves at 7 cycles per byte, split correctly at bank boundaries. [cols="1,1,4", options="header"] |=== |Parameter |Type |Description |`dst` |`void *` |Destination. |`src` |`const void *` |Source. Must not overlap `dst`. |`bytes` |`uint32_t` |Byte count. |=== *Returns:* nothing. === jlWaitVBL [source,c] ---- void jlWaitVBL(void); ---- Blocks until the next display vertical blank, pacing a game loop to the display's native refresh rate. Cheap on every port, because the underlying mechanism is always a hardware-level wait rather than a software timer. *Parameters:* none. *Returns:* nothing. === jlFrameCount [source,c] ---- uint16_t jlFrameCount(void); ---- *Parameters:* none. *Returns:* a monotonic 16-bit frame counter. [WARNING] ==== You must poll faster than twice `jlFrameHz()` or edges are missed, and the counter wraps roughly every 18 minutes at 60 Hz. For elapsed-time work prefer `jlMillisElapsed`. ==== === jlFrameHz [source,c] ---- uint16_t jlFrameHz(void); ---- *Parameters:* none. *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 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 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 to divide by when converting frames to seconds. === jlMillisElapsed [source,c] ---- uint32_t jlMillisElapsed(void); ---- Monotonic millisecond counter since `jlInit`. DOS, ST, X68000 and DVX read a real hardware 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 elapsed time, not the number of vertical blanks that fired. *Parameters:* none. *Returns:* milliseconds since `jlInit`. [NOTE] ==== On the frame-derived ports you must poll at least once every 65535 frames -- about 18 minutes at 60 Hz -- or wrapped frames are lost. ==== === jlRandom [source,c] ---- uint32_t jlRandom(void); ---- Deterministic pseudo-random generator, xorshift32. Produces *bit-identical* output on every JoeyLib port for a given seed, which `rand()` does not. Period 2^32^-1. Suitable for games, not for cryptography. *Parameters:* none. *Returns:* the next 32-bit value. === jlRandomRange [source,c] ---- uint16_t jlRandomRange(uint16_t bound); ---- [cols="1,1,4", options="header"] |=== |Parameter |Type |Description |`bound` |`uint16_t` |Exclusive upper bound. |=== *Returns:* a value in `[0, bound)`. A `bound` of 0 returns 0. === jlRandomSeed [source,c] ---- void jlRandomSeed(uint32_t seed); ---- [cols="1,1,4", options="header"] |=== |Parameter |Type |Description |`seed` |`uint32_t` |Any 32-bit value. A seed of 0 is remapped to 1, because xorshift cannot escape the all-zero state. |=== *Returns:* nothing.