From ac2a05efdba45f1c226e953232a67f3a7a75820e Mon Sep 17 00:00:00 2001 From: IonutParau Date: Thu, 2 Apr 2026 15:19:51 +0200 Subject: [PATCH] MSVC is horrendous --- build.zig | 11 ++++++++--- src/neonucleus.c | 27 ++++++++++++++++++++++++++- src/neonucleus.h | 4 ++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/build.zig b/build.zig index 493f32f..9a81bdc 100644 --- a/build.zig +++ b/build.zig @@ -51,9 +51,14 @@ const LuaVersion = enum { lua54, }; -fn compileRaylib(b: *std.Build, os: std.Target.Os.Tag, c: *std.Build.Step.Compile) void { +fn compileRaylib(b: *std.Build, os: std.Target.Os.Tag, buildOpts: LibBuildOpts, c: *std.Build.Step.Compile) void { // TODO: find out how to send our target to this build cmd - const raylib = b.addSystemCommand(&.{ "zig", "build" }); + const targetStr = buildOpts.target.result.zigTriple(b.allocator) catch unreachable; + defer b.allocator.free(targetStr); + + const targetArg = std.fmt.allocPrint(b.allocator, "-Dtarget={s}", .{targetStr}) catch unreachable; + defer b.allocator.free(targetArg); + const raylib = b.addSystemCommand(&.{ "zig", "build", targetArg }); raylib.setCwd(b.path("foreign/raylib/")); raylib.stdio = .inherit; @@ -179,7 +184,7 @@ pub fn build(b: *std.Build) !void { if (sysraylib_flag) { emulator.linkSystemLibrary("raylib"); } else { - compileRaylib(b, os, emulator); + compileRaylib(b, os, opts, emulator); } const luaVer = b.option(LuaVersion, "lua", "The version of Lua to use.") orelse LuaVersion.lua53; diff --git a/src/neonucleus.c b/src/neonucleus.c index e4ddcc0..5109404 100644 --- a/src/neonucleus.c +++ b/src/neonucleus.c @@ -15,7 +15,6 @@ // to use the numerical accuracy better #define NN_COMPONENT_CALLBUDGET 10000 -// NN_ATOMIC_NONE accepts 1 args, others 2 #ifdef NN_ATOMIC_NONE typedef size_t nn_refc_t; @@ -27,6 +26,32 @@ bool nn_decRef(nn_refc_t *refc, size_t n) { (*refc) -= n; return (*refc) == 0; } +#elif defined(NN_ATOMIC_MSVC) +// MSVC lacks C11 in C mode, but has interlocked intrinsics. +// _InterlockedExchangeAdd operates on long (32-bit), +// _InterlockedExchangeAdd64 operates on __int64 (64-bit). +// We pick the right one based on pointer size since size_t matches that. +#include + +typedef volatile size_t nn_refc_t; + +void nn_incRef(nn_refc_t *refc, size_t n) { +#if defined(_WIN64) + _InterlockedExchangeAdd64((__int64 volatile *)refc, (__int64)n); +#else + _InterlockedExchangeAdd((long volatile *)refc, (long)n); +#endif +} + +bool nn_decRef(nn_refc_t *refc, size_t n) { +#if defined(_WIN64) + __int64 old = _InterlockedExchangeAdd64((__int64 volatile *)refc, -(__int64)n); + return (size_t)old == n; +#else + long old = _InterlockedExchangeAdd((long volatile *)refc, -(long)n); + return (size_t)old == n; +#endif +} #else // we need atomics for thread-safe reference counting that will be used // for managing the lifetimes of various resources diff --git a/src/neonucleus.h b/src/neonucleus.h index a929d45..d0bdeb6 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -37,8 +37,8 @@ extern "C" { #if defined(_MSC_VER) && !defined(__cplusplus) -#ifndef NN_ATOMIC_NONE -#define NN_ATOMIC_NONE +#ifndef NN_ATOMIC_MSVC +#define NN_ATOMIC_MSVC #endif #endif