clean up and standardize types across the codebase, unify atomic operations, improve UTF-8 handling throughout the system, remove obsolete input and named queue interfaces, redesign process preparation and creation, tighten IPC and service boundaries, improve error handling and reliability, minor documentation cleanup, fix doom surfaces, fix panic in ini parsing.

This commit is contained in:
maksw committed 2026-10-12 18:17:43 +02:00
1 parent 899225f551
commit c0ad63c27f
226 files changed
+6562 -4147

No files matched your search

+62 -27
View File
@@ -10,6 +10,7 @@
#include <intrin.h>
#include <ntlite/syscall.h>
#include <ntlite/console_service.h>
#include <ntlite/desktop.h>
#include <ntlite/input_service.h>
#include <ntlite/path.h>
@@ -20,12 +21,17 @@
int _fltused;
// ---------------------------------------------------------------------------
// doom_print_fn
// ---------------------------------------------------------------------------
// PureDOOM's progress messages must not touch the physical console while DWM is presenting.
static void doom_print_wrapper(const char* msg)
{
(void)msg;
}
// Reports an unrecoverable Doom platform error before exiting.
static void doom_fatal(const char* msg)
{
if (msg) (void)NtlConsoleWrite(SYS_HANDLE_INVALID, msg, strlen(msg), NULL);
SysExitProcess(1);
}
// ---------------------------------------------------------------------------
@@ -148,7 +154,7 @@ static int doom_seek_wrapper(void* handle, int offset, doom_seek_t origin)
int64_t target = base + (int64_t)offset;
if (target < 0) target = 0;
uint32_t s = SysSeekFile(f->Handle, (uint64_t)target);
KSTATUS s = SysSeekFile(f->Handle, (uint64_t)target);
if (s != 0) return -1;
f->Pos = (uint64_t)target;
return 0;
@@ -200,10 +206,8 @@ static char* doom_getenv_wrapper(const char* name)
{
if (strcmp(name, "HOME") == 0) {
static char home[] = ".";
doom_print_wrapper("getenv: Returning HOME="); doom_print_wrapper(home); doom_print_wrapper("\n");
return home;
}
doom_print_wrapper("getenv: Unknown variable "); doom_print_wrapper(name); doom_print_wrapper("\n");
return NULL;
}
@@ -316,6 +320,8 @@ static uint32_t g_surface_handle;
static uint32_t g_display_clock_handle;
static uint32_t* g_surface_pixels;
static uint32_t g_surface_pitch_pixels;
static SYS_HANDLE g_desktop_handle = SYS_HANDLE_INVALID;
static NTL_WINDOW_ID g_window;
static void init_surface(void)
{
@@ -327,10 +333,9 @@ static void init_surface(void)
req.Format = SYS_SURFACE_FORMAT_XRGB8888;
req.Flags = SYS_SURFACE_FLAG_NONE;
req.HandleOut = &g_surface_handle;
uint32_t s = SysCreateSurface(&req);
KSTATUS s = SysCreateSurface(&req);
if (s != NTLSTATUS_SUCCESS || !g_surface_handle) {
doom_print_wrapper("doom: SysCreateSurface failed\n");
SysExitProcess(1);
doom_fatal("doom: SysCreateSurface failed\n");
}
void* base = 0;
@@ -338,14 +343,51 @@ static void init_surface(void)
s = SysMapSurface(g_surface_handle, SYS_SURFACE_MAP_READ | SYS_SURFACE_MAP_WRITE,
&base, &pitchBytes);
if (s != NTLSTATUS_SUCCESS || !base || pitchBytes < DISP_W * sizeof(uint32_t)) {
doom_print_wrapper("doom: SysMapSurface failed\n");
SysExitProcess(1);
doom_fatal("doom: SysMapSurface failed\n");
}
g_surface_pixels = (uint32_t*)base;
g_surface_pitch_pixels = pitchBytes / sizeof(uint32_t);
}
// Registers the Doom surface with DWM so committed frames are composited.
static void init_window(void)
{
const char* failedOperation = "NtlDesktopConnect";
KSTATUS status = NtlDesktopConnect(&g_desktop_handle);
if (!KSUCCESS(status) || g_desktop_handle == SYS_HANDLE_INVALID)
goto failed;
DISPLAY_RECT bounds = { 0, 0, DISP_W, DISP_H };
failedOperation = "NtlDesktopCreateWindow";
status = NtlDesktopCreateWindow(g_desktop_handle, &bounds, &g_window);
if (!KSUCCESS(status) || !g_window)
goto failed;
failedOperation = "NtlDesktopAttachSurface";
status = NtlDesktopAttachSurface(g_desktop_handle, g_window, g_surface_handle);
if (!KSUCCESS(status))
goto failed;
failedOperation = "NtlDesktopSetVisible";
status = NtlDesktopSetVisible(g_desktop_handle, g_window, 1u);
if (!KSUCCESS(status))
goto failed;
(void)NtlDesktopRaiseWindow(g_desktop_handle, g_window);
return;
failed:
(void)NtlConsoleWrite(SYS_HANDLE_INVALID, "doom: ", sizeof("doom: ") - 1u, NULL);
(void)NtlConsoleWrite(SYS_HANDLE_INVALID, failedOperation, strlen(failedOperation), NULL);
(void)NtlConsoleWrite(SYS_HANDLE_INVALID, " failed\n", sizeof(" failed\n") - 1u, NULL);
if (g_window)
(void)NtlDesktopDestroyWindow(g_desktop_handle, g_window);
if (g_desktop_handle != SYS_HANDLE_INVALID)
(void)NtlDesktopClose(g_desktop_handle);
SysExitProcess(1);
}
static void init_display_clock(void)
{
SYS_OPEN_DISPLAY_CLOCK_REQUEST req;
@@ -355,10 +397,9 @@ static void init_display_clock(void)
req.PeriodMilliseconds = 1;
req.HandleOut = &g_display_clock_handle;
uint32_t s = SysOpenDisplayClock(&req);
KSTATUS s = SysOpenDisplayClock(&req);
if (s != NTLSTATUS_SUCCESS) {
g_display_clock_handle = 0;
doom_print_wrapper("doom: display clock unavailable, using sleep pacing\n");
}
}
@@ -369,8 +410,7 @@ static void render_frame(const uint8_t* rgba)
uint32_t dstPitch = g_surface_pitch_pixels;
if (!dstBase || dstPitch < DISP_W) {
doom_print_wrapper("doom: surface not initialized\n");
SysExitProcess(1);
doom_fatal("doom: surface not initialized\n");
}
for (int y = 0; y < DOOM_H; y++) {
@@ -392,7 +432,7 @@ static void render_frame(const uint8_t* rgba)
}
DISPLAY_RECT rect = { 0, 0, DISP_W, DISP_H };
uint32_t code = SysCommitSurface(g_surface_handle, &rect, 1, 0);
KSTATUS code = SysCommitSurface(g_surface_handle, &rect, 1, 0);
if (code != NTLSTATUS_SUCCESS)
SysExitProcess(code);
}
@@ -452,7 +492,11 @@ static int wait_for_next_doom_tic(int lastTic)
return now;
if (g_display_clock_handle) {
(void)SysWaitSingle(g_display_clock_handle, SYS_WAIT_FLAG_NONE, SYS_WAIT_TIMEOUT_INFINITE);
KSTATUS status = SysWaitSingle(g_display_clock_handle, SYS_WAIT_FLAG_NONE, 100u);
if (status != NTLSTATUS_SUCCESS && status != NTLSTATUS_TIMEOUT) {
(void)SysCloseHandle(g_display_clock_handle);
g_display_clock_handle = 0;
}
} else {
SysSleep(1);
}
@@ -496,20 +540,11 @@ int main(void)
char argvStorage[512];
const char* argv[32];
int argc = build_argv_from_command_line(cmdline, argvStorage, sizeof(argvStorage), argv, 32);
if (argc == 1)
doom_print_wrapper("doom: parsed argc == 1\n");
else if (argc > 1)
doom_print_wrapper("doom: parsed argc > 1\n");
else
doom_print_wrapper("doom: parsed argc <= 0\n");
init_surface();
init_display_clock();
(void)NtlConsoleWrite(SYS_HANDLE_INVALID, "doom: starting doom\n", sizeof("doom: starting doom\n") - 1u, NULL);
doom_init(argc, argv, 0);
(void)NtlConsoleWrite(SYS_HANDLE_INVALID, "doom: starting audio\n", sizeof("doom: starting audio\n") - 1u, NULL);
DoomAudioStart();
(void)NtlConsoleWrite(SYS_HANDLE_INVALID, "doom: entering game loop\n", sizeof("doom: entering game loop\n") - 1u, NULL);
init_window();
// Core execution loop. Doom advances at TICRATE, so rendering duplicate
// frames as fast as possible only amplifies scheduler and input jitter.
+15 -14
View File
@@ -1,5 +1,7 @@
// Doom audio mixes PureDOOM SFX with optional SoundFont MIDI into one native render stream.
#include <ntlite/atomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
@@ -206,15 +208,15 @@ typedef struct DOOM_AUDIO_STATE {
uint32_t WorkerId;
uint32_t SynthLoaderHandle;
uint32_t SynthLoaderId;
volatile long StopRequested;
volatile int32_t StopRequested;
tsf* volatile Synth;
} DOOM_AUDIO_STATE;
static DOOM_AUDIO_STATE g_doomAudio;
// Writes one complete diagnostic line to the process console.
// Suppresses audio diagnostics until there is a display-independent user-mode log sink.
static void DoomAudioPrint(const char* text) {
if (text) (void)NtlConsoleWrite(SYS_HANDLE_INVALID, text, strlen(text), NULL);
(void)text;
}
// Opens the default available native render endpoint.
@@ -262,8 +264,8 @@ static KSTATUS DoomAudioFindEndpoint(uint32_t* endpointIdOut) {
// Returns the currently published synthesizer without taking the PureDOOM lock.
static tsf* DoomAudioGetSynth(void) {
return (tsf*)_InterlockedCompareExchangePointer(
(void* volatile*)&g_doomAudio.Synth, NULL, NULL);
return (tsf*)NtlAtomicCompareExchangePointer(
&g_doomAudio.Synth, NULL, NULL);
}
// Maps the optional SoundFont so TinySoundFont can parse it without a separate input copy.
@@ -353,7 +355,7 @@ static void DoomAudioSynthLoader(uintptr_t argument) {
SysExitThread(0);
}
if (_InterlockedCompareExchange(&g_doomAudio.StopRequested, 0, 0)) {
if (NtlAtomicLoad32(&g_doomAudio.StopRequested)) {
(void)SysFreeVm(soundFontBase);
SysExitThread(0);
}
@@ -367,16 +369,15 @@ static void DoomAudioSynthLoader(uintptr_t argument) {
status = DoomAudioConfigureSynth(synth);
if (status != NTLSTATUS_SUCCESS ||
_InterlockedCompareExchange(&g_doomAudio.StopRequested, 0, 0)) {
NtlAtomicLoad32(&g_doomAudio.StopRequested)) {
if (status != NTLSTATUS_SUCCESS)
DoomAudioPrint("doom: MIDI synthesizer initialization failed; continuing with sound effects only\n");
tsf_close(synth);
SysExitThread(0);
}
(void)_InterlockedExchangePointer(
(void* volatile*)&g_doomAudio.Synth, synth);
DoomAudioPrint("doom: MIDI synthesizer ready\n");
(void)NtlAtomicExchangePointer(
&g_doomAudio.Synth, synth);
SysExitThread(0);
}
@@ -620,7 +621,7 @@ static void DoomAudioWorker(uintptr_t argument) {
uint32_t requiredFrames;
KSTATUS status;
if (_InterlockedCompareExchange(&g_doomAudio.StopRequested, 0, 0))
if (NtlAtomicLoad32(&g_doomAudio.StopRequested))
break;
status = DoomAudioQueryStream(&info);
@@ -686,8 +687,8 @@ static void DoomAudioReleaseResources(void) {
(void)SysCloseHandle(g_doomAudio.StreamHandle);
g_doomAudio.StreamHandle = 0;
}
tsf* synth = (tsf*)_InterlockedExchangePointer(
(void* volatile*)&g_doomAudio.Synth, NULL);
tsf* synth = (tsf*)NtlAtomicExchangePointer(
&g_doomAudio.Synth, NULL);
if (synth)
tsf_close(synth);
if (g_doomAudio.CoreMutex) {
@@ -767,7 +768,7 @@ void DoomAudioStart(void) {
// Stops playback immediately without waiting for the producer thread.
void DoomAudioAbort(void) {
_InterlockedExchange(&g_doomAudio.StopRequested, 1);
NtlAtomicExchange32(&g_doomAudio.StopRequested, 1);
if (g_doomAudio.StreamHandle)
(void)SysAudioStop(g_doomAudio.StreamHandle);
}