178 lines
5.3 KiB
Markdown
178 lines
5.3 KiB
Markdown
# Engine Systems
|
||
|
||
Smaller systems that support the engine but don't warrant their own file each.
|
||
|
||
---
|
||
|
||
## Time (`src/dusk/time/`)
|
||
|
||
`dusktime_t TIME` tracks fixed and dynamic delta time.
|
||
|
||
```c
|
||
TIME.delta // fixed_t: always DUSK_TIME_STEP (16ms default) on fixed-rate platforms
|
||
TIME.time // fixed_t: total elapsed time in seconds
|
||
```
|
||
|
||
On platforms with `DUSK_TIME_DYNAMIC` (Linux/SDL2):
|
||
```c
|
||
TIME.dynamicDelta // fixed_t: actual time since last frame
|
||
TIME.dynamicTime // fixed_t: total elapsed (dynamic)
|
||
TIME.dynamicUpdate // bool_t: true when a real tick occurred
|
||
```
|
||
|
||
Call `timeUpdate()` once per frame (before input/logic). `timeGetEpoch()` returns the current wall-clock time as a `dusktimeepoch_t`.
|
||
|
||
### Epoch time (`time/timeepoch.h`)
|
||
|
||
`dusktimeepoch_t` stores a Unix timestamp (double) with timezone offset. Utilities:
|
||
|
||
```c
|
||
dusktimeepoch_t e = timeGetEpoch();
|
||
timeEpochGetHours(e) // 0–23
|
||
timeEpochGetMinutes(e) // 0–59
|
||
timeEpochGetSeconds(e) // 0–59
|
||
timeEpochGetDayOfMonth(e) // 0–30
|
||
timeEpochGetMonth(e) // 0–11
|
||
timeEpochGetYear(e)
|
||
|
||
// Format: %Y year, %m month, %d day, %H hour, %M minute, %S second
|
||
timeEpochFormat(e, "%Y-%m-%d %H:%M:%S", buf, sizeof(buf));
|
||
|
||
// Compare: returns -1, 0, 1
|
||
timeEpochCompare(a, b);
|
||
|
||
// Timezone shift:
|
||
dusktimeepoch_t local = timeEpochSwitchTimeZone(e, offsetHours);
|
||
```
|
||
|
||
---
|
||
|
||
## Thread (`src/dusk/thread/`)
|
||
|
||
Currently only the pthread backend (`DUSK_THREAD_PTHREAD`) exists. Thread objects are `thread_t` — used primarily by the asset loader.
|
||
|
||
```c
|
||
threadInit(&thread, myCallback); // myCallback: void (*)(thread_t *)
|
||
threadStart(&thread); // blocks until thread is RUNNING
|
||
threadStop(&thread); // requests stop, blocks until STOPPED
|
||
|
||
// Inside the thread callback:
|
||
while(!threadShouldStop(&thread)) { /* work */ }
|
||
```
|
||
|
||
State flow: `STOPPED → STARTING → RUNNING → (STOP_REQUESTED) → STOPPED`.
|
||
|
||
### Mutex (`thread/threadmutex.h`)
|
||
|
||
```c
|
||
threadMutexInit(&lock);
|
||
threadMutexLock(&lock);
|
||
threadMutexUnlock(&lock);
|
||
threadMutexTryLock(&lock); // non-blocking; returns false if already held
|
||
threadMutexWaitLock(&lock); // release lock and sleep until signalled
|
||
threadMutexSignal(&lock); // wake a thread waiting on this mutex
|
||
threadMutexDispose(&lock);
|
||
```
|
||
|
||
### Thread-local storage
|
||
|
||
`THREAD_LOCAL` expands to `__thread` (GCC) on pthread platforms. Used for the per-thread error state (`ERROR_STATE` in `error/error.h`).
|
||
|
||
---
|
||
|
||
## Event (`src/dusk/event/`)
|
||
|
||
A fixed-capacity multicast callback list.
|
||
|
||
```c
|
||
// Declare backing arrays (choose a size):
|
||
eventcallback_t cbs[4];
|
||
void *users[4];
|
||
event_t myEvent;
|
||
eventInit(&myEvent, cbs, users, 4);
|
||
|
||
eventSubscribe(&myEvent, myCallback, myUser);
|
||
eventUnsubscribe(&myEvent, myCallback);
|
||
eventInvoke(&myEvent, params); // calls all subscribers; params passed as-is
|
||
```
|
||
|
||
Callback signature: `void cb(void *params, void *user)`.
|
||
|
||
`event_t` does not own its callback/user arrays. Always declare them alongside the event in the same struct or as static arrays.
|
||
|
||
---
|
||
|
||
## Console (`src/dusk/console/`)
|
||
|
||
`CONSOLE` is a scrolling in-game terminal for debug output. On POSIX platforms (`DUSK_CONSOLE_POSIX`) it also polls stdin in a thread so commands can be typed during a running session.
|
||
|
||
```c
|
||
consolePrint("Value is %d", x); // printf-style; thread-safe
|
||
consoleDraw(); // renders visible history lines to screen
|
||
```
|
||
|
||
Configuration constants (`consoledefs.h`):
|
||
- `CONSOLE_LINE_MAX` — 512 chars per line
|
||
- `CONSOLE_HISTORY_MAX` — 16 lines of scrollback
|
||
- `CONSOLE_EXEC_BUFFER_MAX` — 32 pending exec commands
|
||
|
||
`CONSOLE.visible` controls whether `consoleDraw()` actually renders anything.
|
||
|
||
---
|
||
|
||
## Log (`src/dusk/log/`)
|
||
|
||
Two simple output functions, implemented per-platform:
|
||
|
||
```c
|
||
logDebug("format %s", arg); // debug output (stdout on Linux, debug channel on consoles)
|
||
logError("format %s", arg); // error output; may pause execution on some platforms
|
||
```
|
||
|
||
These go directly to the platform's native output and are not buffered by the console history.
|
||
|
||
---
|
||
|
||
## System / Platform (`src/dusk/system/`)
|
||
|
||
`systemInit()` runs platform-specific startup (e.g. Wii PAD init, PSP kernel setup). Must be the first call in `engineInit()`.
|
||
|
||
```c
|
||
systemplatform_t p = systemGetPlatform(); // SYSTEM_PLATFORM_LINUX, _PSP, etc.
|
||
systemdialogtype_t d = systemGetActiveDialogType();
|
||
// SYSTEM_DIALOG_TYPE_NONE / RENDER_BLOCKING / TICK_BLOCKING
|
||
```
|
||
|
||
The full platform list is defined via X-macro in `system/systemplatformlist.h`:
|
||
|
||
| Constant | Value |
|
||
|---|---|
|
||
| `SYSTEM_PLATFORM_LINUX` | 0 |
|
||
| `SYSTEM_PLATFORM_KNULLI` | 1 |
|
||
| `SYSTEM_PLATFORM_PSP` | 2 |
|
||
| `SYSTEM_PLATFORM_GAMECUBE` | 3 |
|
||
| `SYSTEM_PLATFORM_WII` | 4 |
|
||
|
||
---
|
||
|
||
## Network (`src/dusk/network/`)
|
||
|
||
`network_t NETWORK` manages platform connection state. The engine calls `networkInit` / `networkUpdate` / `networkDispose`; game code uses the request API:
|
||
|
||
```c
|
||
networkRequestConnection(onConnected, onFailed, onDisconnect, user);
|
||
networkRequestDisconnection(onComplete, user);
|
||
networkIsConnected(); // bool_t
|
||
```
|
||
|
||
State machine: `DISCONNECTED → CONNECTING → CONNECTED → DISCONNECTING → DISCONNECTED`.
|
||
|
||
Network address info (after connection):
|
||
```c
|
||
networkinfo_t info = networkGetInfo();
|
||
// info.type = NETWORK_TYPE_IPV4 / IPV6
|
||
// info.ipv4.ip[4] or info.ipv6.ip[16]
|
||
```
|
||
|
||
Platform backends implement `networkPlatformInit/Update/Dispose/IsConnected`. Currently only Linux (socket-based) and PSP/Vita are implemented.
|