# Time System Source: `src/dusk/time/`, platform layers in `src/dusk/time/` ## Global state ```c extern dusktime_t TIME; ``` ```c typedef struct { float_t delta; // Fixed step size in seconds (DUSK_TIME_STEP) float_t time; // Accumulated game time in seconds // Only present when DUSK_TIME_DYNAMIC is defined: float_t lastNonDynamic; bool_t dynamicUpdate; // true on sub-step ticks float_t dynamicDelta; // real elapsed seconds this frame float_t dynamicTime; // accumulated real time } dusktime_t; ``` ## Fixed vs dynamic timestep ### Fixed timestep (default) `DUSK_TIME_STEP` defaults to `16ms / 1000 = 0.016f` seconds (62.5 Hz). Every call to `timeUpdate()` advances `TIME.time` by exactly `DUSK_TIME_STEP` and sets `TIME.delta = DUSK_TIME_STEP`. This is the safe, deterministic mode for physics and game logic. ### Dynamic timestep (`DUSK_TIME_DYNAMIC`) When enabled, `timeUpdate()` calls the platform tick hook to measure actual elapsed time. It fires a "non-dynamic" step (`dynamicUpdate = false`, `delta = DUSK_TIME_STEP`) once per fixed interval, and "dynamic" sub-steps (`dynamicUpdate = true`) in between. Systems that must run on the fixed interval (physics, networking) skip the dynamic sub-steps by checking: ```c if(TIME.dynamicUpdate) return; ``` ## Platform hooks Each platform provides three macros in its `time/timeplatform.h`: | Macro | Purpose | |-------|---------| | `timeTickPlatform()` | Sample the hardware timer | | `timeGetDeltaPlatform()` | Return seconds since last tick | | `timeGetRealPlatform()` | Return epoch seconds since 1970 | | `timeGetRealTimeZonePlatform()` | Return local timezone offset (seconds) | `timeTickPlatform` and `timeGetDeltaPlatform` are only required when `DUSK_TIME_DYNAMIC` is defined. ## Platform implementations | Platform | Tick source | Real time source | |----------|------------|-----------------| | Linux | `SDL_GetTicks64()` (via SDL2) | `clock_gettime(CLOCK_REALTIME)` | | Knulli | `SDL_GetTicks64()` (via SDL2) | `clock_gettime(CLOCK_REALTIME)` | | PSP | `SDL_GetTicks64()` (via SDL2) | `sceRtcGetCurrentTick()` (microseconds) | | GameCube | none (fixed step only) | `ticks_to_microsecs(__SYS_GetSystemTime())` + 2000->1970 offset | | Wii | none (fixed step only) | same as GameCube | GameCube / Wii note: the hardware timer returns ticks since 2000-01-01, so an offset of 946684800 seconds is added to convert to UNIX epoch. The timezone offset is always returned as 0.0 on Dolphin (timezone is not available without network time). ## Epoch time (`timeepoch.h`) ```c typedef struct { double_t time; // raw UTC seconds since 1970 double_t timeZone; // timezone offset in seconds double_t offsetTime; // time + timeZone } dusktimeepoch_t; dusktimeepoch_t timeGetEpoch(void); // Returns current time in local timezone. ``` ### Epoch helpers ```c int32_t timeEpochGetYear(epoch); int32_t timeEpochGetMonth(epoch); // 1-12 int32_t timeEpochGetDayOfMonth(epoch); // 1-31 int32_t timeEpochGetHours(epoch); // 0-23 int32_t timeEpochGetMinutes(epoch); // 0-59 int32_t timeEpochGetSeconds(epoch); // 0-59 bool_t timeEpochIsLeapYear(year); size_t timeEpochFormat( dusktimeepoch_t epoch, const char_t *format, // %Y %m %d %H %M %S char_t *buffer, size_t bufferSize ); ``` ## Adding a new platform time implementation 1. Create `src/dusk/time/time.h/.c`. 2. Implement `timeGetReal()` and `timeGetRealTimeZone()`. 3. If `DUSK_TIME_DYNAMIC`: also implement `timeTick()` and `timeGetDelta()`. 4. Create `src/dusk/time/timeplatform.h` with the `#define` macros pointing to your functions.