power_play/src/incbin.c
2025-06-17 15:21:26 -05:00

86 lines
2.8 KiB
C

#if COMPILER_MSVC
/* ========================== *
* Msvc RC file lookup
* ========================== */
#include "incbin.h"
#include "scratch.h"
#include "string.h"
#include "atomic.h"
#include "intrinsics.h"
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#include <Windows.h>
struct rc_search_params {
/* In */
struct string name_lower;
/* Out */
b32 found;
struct string data;
};
/* Find first resource with `type` and return the data in `udata`. */
INTERNAL BOOL CALLBACK enum_func(HMODULE module, LPCWSTR type, LPCWSTR wstr_entry_name, LONG_PTR udata)
{
struct arena_temp scratch = scratch_begin_no_conflict();
struct rc_search_params *params = (struct rc_search_params *)udata;
struct string entry_name_lower = string_lower(scratch.arena, string_from_wstr_no_limit(scratch.arena, (LPWSTR)wstr_entry_name));
params->found = false;
params->data = STRING(0, 0);
if (string_eq(entry_name_lower, params->name_lower)) {
HRSRC hres = FindResourceW(module, wstr_entry_name, type);
if (hres) {
HGLOBAL hg = LoadResource(module, hres);
if (hg) {
params->found = true;
params->data.len = SizeofResource(module, hres);
params->data.text = LockResource(hg);
}
}
}
scratch_end(scratch);
return !params->found;
}
struct string _incbin_get(struct _incbin_rc_resource *inc)
{
enum _incbin_state state = atomic_i32_eval(&inc->state);
if (state != INCBIN_STATE_SEARCHED) {
struct arena_temp scratch = scratch_begin_no_conflict();
if (state == INCBIN_STATE_UNSEARCHED) {
enum _incbin_state v = atomic_i32_eval_compare_exchange(&inc->state, state, INCBIN_STATE_SEARCHING);
if (v == state) {
/* Search RC file for the resource name */
struct string name_lower = string_lower(scratch.arena, inc->rc_name);
struct rc_search_params params = { .name_lower = name_lower };
EnumResourceNamesW(NULL, RT_RCDATA, &enum_func, (LONG_PTR)&params);
if (!params.found) {
sys_panic(string_format(scratch.arena,
LIT("INCBIN include not found in RC file: \"%F\""),
FMT_STR(inc->rc_name)));
}
inc->data = params.data;
state = INCBIN_STATE_SEARCHED;
atomic_i32_eval_exchange(&inc->state, state);
} else {
state = v;
}
}
/* Spin while another thread searches */
while (state != INCBIN_STATE_SEARCHED) {
ix_pause();
state = atomic_i32_eval(&inc->state);
}
scratch_end(scratch);
}
return inc->data;
}
#endif