joeylib2/docs/ApiCore.adoc
2026-09-29 21:25:37 -05:00

265 lines
5.9 KiB
Text

== Core and Lifecycle
Declared in `<joey/core.h>`, included by `<joey/joey.h>`.
=== 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, but the IIgs implements it as `MVN` block moves at 7 cycles per byte
instead of a libc byte loop, 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,
ST NTSC and 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 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 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.