316 lines
9 KiB
Text
316 lines
9 KiB
Text
== Core and Lifecycle
|
|
|
|
Declared in `<joey/core.h>`, included by `<joey/joey.h>`.
|
|
|
|
=== jlConfigT
|
|
|
|
[source,c]
|
|
----
|
|
typedef struct {
|
|
uint32_t codegenBytes;
|
|
bool noAudio;
|
|
} 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 the IIgs, 64 KB on the Amiga, ST, and X68000, and 32 KB on
|
|
DOS, DVX, and Win16. The other hosted ports interpret every sprite and have
|
|
no cache: they allocate none, whatever is asked. Every port takes as much of
|
|
the request as the machine has, and `jlInit` fails only if it can have none
|
|
of it; `jlSpriteCodegenBytesTotal()` says what it got. On the IIgs the cache
|
|
is up to four Memory Manager blocks of at most 64 KB, each inside one 64 KB
|
|
bank, so at most 256 KB (a bank that is refused is tried again at 60 KB);
|
|
elsewhere it is one block, halved until the heap has room, down to 4 KB.
|
|
Size it against `jlSpriteCompiledSize()`.
|
|
|
|
|`noAudio`
|
|
|`bool`
|
|
|`true` leaves audio off: every audio call is 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). `false` has `jlInit`
|
|
start audio and `jlShutdown` stop it.
|
|
|===
|
|
|
|
Set every field: a `jlConfigT` is read whole, so a field left unset is
|
|
whatever the memory held.
|
|
|
|
=== jlInit
|
|
|
|
[source,c]
|
|
----
|
|
bool jlInit(const jlConfigT *config);
|
|
----
|
|
|
|
Initialises the library: takes over the display, allocates the stage and the
|
|
codegen arena, brings up input, and last starts audio (unless `noAudio`). Must
|
|
be called before any other JoeyLib function. Sound that does not start is not
|
|
a failure: modules and sound effects are then silent, and the log says so
|
|
(<<_debug_logging>>). The tone and noise voices still play on the ports whose
|
|
sound chip needs no engine: the Amiga, the ST, DOS, and the X68000.
|
|
|
|
[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, on every port: for example, the plain ST refuses a
|
|
monochrome monitor, and the Amiga says when chip RAM cannot hold the two
|
|
screen pages.
|
|
|
|
=== jlShutdown
|
|
|
|
[source,c]
|
|
----
|
|
void jlShutdown(void);
|
|
----
|
|
|
|
Shuts the library down: stops audio first, then restores the display mode,
|
|
releases the library's own resources, and un-hooks any interrupt vectors the
|
|
port installed. Surfaces and sprites the program created are not released:
|
|
destroy them with `jlSurfaceDestroy` and `jlSpriteDestroy` first. A program
|
|
that ends without calling it, by returning from `main` or calling `exit`, has
|
|
it called then: the first successful `jlInit` registers it with `atexit`.
|
|
Nothing can run it after a crash or an `abort`.
|
|
|
|
*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"`, `"DVX"`, `"SDL3"` (the web port is the SDL3 port in a browser),
|
|
`"macOS"`, or `"Windows"`.
|
|
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 whole C heap is one Memory Manager block of
|
|
32 KB to 48 KB (and, if that block cannot be had, only what the program's link
|
|
left in its bank, which can be a few hundred bytes), 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`. Never mix `jlFree` and `free`: on most
|
|
ports they are the same thing, but on the IIgs a `jlAlloc` block is a Memory
|
|
Manager handle, and either call given the other's block corrupts memory.
|
|
|
|
[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. On the machine ports it waits for the
|
|
display's own vertical blank. The hosted ports, and DVX in a window, have no
|
|
vertical blank to wait for: there it waits for the next tick of a virtual
|
|
frame clock, 60 Hz on the hosted ports and 70 Hz on DVX. A hosted window shows
|
|
one frame a tick, as a display shows one a refresh (a present in a tick
|
|
already shown waits for the next); a desktop that composites its windows, as
|
|
every current one does, puts only whole frames on the screen, but on one that
|
|
does not (Windows 3.1, a bare X11 desktop) and in a DVX window nothing stops a
|
|
present from tearing.
|
|
|
|
*Parameters:* none. *Returns:* nothing.
|
|
|
|
=== jlFrameCount
|
|
|
|
[source,c]
|
|
----
|
|
uint16_t jlFrameCount(void);
|
|
----
|
|
|
|
*Parameters:* none.
|
|
|
|
*Returns:* a monotonic 16-bit frame counter. An interrupt or a clock keeps it,
|
|
so it counts every frame however seldom you read it -- except on an X68000
|
|
whose system refuses JoeyLib's frame interrupt, where it counts only while
|
|
`jlWaitVBL`, `jlFrameCount`, or `jlStagePresent` is being called.
|
|
|
|
[WARNING]
|
|
====
|
|
The counter wraps roughly every 18 minutes at 60 Hz, so compare two readings
|
|
by subtracting them. For elapsed-time work prefer `jlMillisElapsed`.
|
|
====
|
|
|
|
=== jlFrameHz
|
|
|
|
[source,c]
|
|
----
|
|
uint16_t jlFrameHz(void);
|
|
----
|
|
|
|
*Parameters:* none.
|
|
|
|
*Returns:* the nominal display frame rate in Hz -- 60 on the IIgs, or 50 on a
|
|
PAL machine; 50 on a PAL Amiga and 60 on an NTSC one, whose screen is in the
|
|
machine's own standard; 50 or 60 on the ST, as the machine is set (71 with a
|
|
monochrome monitor); 55 on the X68000; 70 on DOS's VGA 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); and 60 on every hosted port, 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 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`, read from a hardware timer to
|
|
the millisecond on every port: the IIgs from the frame count and where the
|
|
beam is, the ST and the X68000 from their system tick and the MFP timer
|
|
counting down to the next, the Amiga from the E-clock, and DOS from the PIT.
|
|
A machine whose timer is taken (an X68000 whose Timer C a resident program
|
|
has set to another rate, an Amiga with no timer.device) falls back to the
|
|
frame count and advances a frame at a time. 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]
|
|
====
|
|
Call it at least once every 15 minutes, or the time between two calls can be
|
|
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.
|