starfield

starfield.git
git clone git://git.lenczewski.org/starfield.git
Log | Files | Refs | Submodules | README | LICENSE

commit 11b0825dd77182992237c4e189c5a7fdec73cc95
Author: Mikołaj Lenczewski <mblenczewski@gmail.com>
Date:   Sun, 28 Apr 2024 22:42:13 +0000

Initial commit

Diffstat:
A.editorconfig | 21+++++++++++++++++++++
A.gitignore | 4++++
A.gitmodules | 3+++
ALICENSE | 18++++++++++++++++++
AREADME | 39+++++++++++++++++++++++++++++++++++++++
Abuild_linux.sh | 19+++++++++++++++++++
Abuild_win.sh | 33+++++++++++++++++++++++++++++++++
Aclean.sh | 5+++++
Acommon/starfield_api.h | 226+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aplatform/linux_starfield.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aplatform/linux_starfield.h | 34++++++++++++++++++++++++++++++++++
Aplatform/win_starfield.c | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aplatform/win_starfield.h | 28++++++++++++++++++++++++++++
Asetup_win.sh | 11+++++++++++
Astarfield/starfield.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Astarfield/starfield.h | 6++++++
Athirdparty/msvc-wine | 1+
17 files changed, 827 insertions(+), 0 deletions(-)

diff --git a/.editorconfig b/.editorconfig @@ -0,0 +1,21 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +guidelines = 80, 120, 160 + +[*.{c,h}] +indent_style = tab +indent_size = 8 + +[*.{sh}] +indent_style = tab +indent_size = 8 + +[*.{md,txt}] +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore @@ -0,0 +1,4 @@ +bin/ +opt/ + +**/.*.swp diff --git a/.gitmodules b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "thirdparty/msvc-wine"] + path = thirdparty/msvc-wine + url = https://github.com/mstorsjo/msvc-wine.git diff --git a/LICENSE b/LICENSE @@ -0,0 +1,18 @@ +The MIT-Zero License + +Copyright (c) 2024 Mikołaj Lenczewski <mblenczewski@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README b/README @@ -0,0 +1,39 @@ +starfield +============================================================================== +A simple game, built for linux and cross-compiled for windows. + +starfield: Dependencies +------------------------------------------------------------------------------ +Our expected build environment is linux, with the following dependencies: +```text +- clang +``` + +When building for linux, our dependency list is: +```text +``` + +When building for windows, our dependency list is: +```text +- python3 (build-time dependency) +- msitools (build-time dependency) +- perl (build-time dependency) +``` + +starfield: Building +------------------------------------------------------------------------------ +To clean any built artefacts, run: +```sh +$ ./clean.sh +``` + +To build for linux, run: +```sh +$ ./build_linux.sh +``` + +To build for windows, run: +```sh +$ ./setup_win.sh # ensure this has been ran at least once +$ ./build_win.sh +``` diff --git a/build_linux.sh b/build_linux.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +CC="clang" + +WARNINGS="-Wall -Wextra -Wpedantic -Werror" + +CFLAGS="-std=c11 -O0 -g" +CPPFLAGS="-DSTARFIELD_DEBUG -Icommon" + +set -ex + +mkdir -p bin + +$CC -shared -o bin/starfield.so starfield/starfield.c \ + $WARNINGS $CFLAGS $CPPFLAGS -nostdlib + +# TODO: how to build a static binary that supports loading starfield.so? +$CC -o bin/linux_starfield platform/linux_starfield.c \ + $WARNINGS $CFLAGS $CPPFLAGS diff --git a/build_win.sh b/build_win.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# sets up windows sdk variables, make sure to run `setup_win.sh` beforehand +BIN="$(realpath ./opt/bin/x64)" . ./thirdparty/msvc-wine/msvcenv-native.sh + +CC="clang --target=x86_64-pc-windows-msvc" + +WARNINGS="-Wall -Wextra -Wpedantic -Werror" + +CFLAGS="-std=c11 -O0 -g -gcodeview" +CPPFLAGS="-DSTARFIELD_DEBUG -Icommon" +LDFLAGS="-fuse-ld=lld -Wl,/debug:full,/pdb:" + +EXPORTS=" + -Wl,/export:starfield_init + -Wl,/export:starfield_update + -Wl,/export:starfield_render + -Wl,/export:starfield_sample + -Wl,/export:starfield_free +" + +# TODO: remove -lksuser and -luuid ? +WIN_LIBS="-luser32 -lgdi32 -lwinmm -lksuser -luuid" + +set -ex + +mkdir -p bin + +$CC -shared -o bin/starfield.dll starfield/starfield.c \ + $WARNINGS $CFLAGS $CPPFLAGS $LDFLAGS $EXPORTS + +$CC -static -o bin/win_starfield.exe platform/win_starfield.c \ + $WARNINGS $CFLAGS $CPPFLAGS $LDFLAGS $WIN_LIBS -Wl,/subsystem:windows diff --git a/clean.sh b/clean.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -ex + +rm -rf bin diff --git a/common/starfield_api.h b/common/starfield_api.h @@ -0,0 +1,226 @@ +#ifndef STARFIELD_API_H +#define STARFIELD_API_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <inttypes.h> +#include <limits.h> +#include <stdalign.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +typedef int32_t b32; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef float f32; +typedef double f64; + +typedef unsigned char c8; + +struct str_t { + c8 *ptr; + u64 len; +}; + +#define KiB (1024ULL) +#define MiB (1024 * KiB) +#define GiB (1024 * MiB) +#define TiB (1024 * GiB) + +#define ARRLEN(arr) (sizeof (arr) / sizeof (arr)[0]) + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define TESTBITS(v, mask) (((v) & (mask)) == (mask)) + +#define IS_ALIGNED(v, align) (((v) & ~((align) - 1)) == 0) + +#define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) +#define ALIGN_NEXT(v, align) ALIGN_PREV((v) + (align) - 1, (align)) + +#ifdef STARFIELD_DEBUG + #define ASSERT(cond) if (!(cond)) { *((volatile u8 *) 0) = 0; } +#else + #define ASSERT(cond) +#endif + +#define global extern +#define internal static +#define func_local static + +/* platform api definitions */ + +#ifdef STARFIELD_DEBUG + +struct DEBUG_platform_read_file_result { + void *ptr; + u64 len; +}; + +#define DEBUG_PLATFORM_READ_FILE(name) \ + struct DEBUG_platform_read_file_result name(char const *filename) + +#define DEBUG_PLATFORM_WRITE_FILE(name) \ + b32 name(char const *filename, void *buf, u64 len) + +#define DEBUG_PLATFORM_FREE_FILE_MEMORY(name) \ + void name(void *ptr) + +typedef DEBUG_PLATFORM_READ_FILE(DEBUG_platform_api_read_file_t); +typedef DEBUG_PLATFORM_WRITE_FILE(DEBUG_platform_api_write_file_t); +typedef DEBUG_PLATFORM_FREE_FILE_MEMORY(DEBUG_platform_api_free_file_memory_t); + +#endif + +struct platform_api { +#ifdef STARFIELD_DEBUG + DEBUG_platform_api_read_file_t *DEBUG_read_file; + DEBUG_platform_api_write_file_t *DEBUG_write_file; + DEBUG_platform_api_free_file_memory_t *DEBUG_free_file_memory; +#endif +}; + +/* starfield api definitions */ + +#define STARFIELD_DATADIR "data" +#define STARFIELD_TEMPDIR "temp" + +struct starfield_thread; + +struct starfield_arena { + void *ptr; + u64 cap, len; +}; + +struct starfield_memory { + struct starfield_arena permanent, temporary; +}; + +struct starfield_button_input { + u32 half_transition_count; + b32 was_down; +}; + +enum starfield_mouse_button { + STARFIELD_MOUSE_L, + STARFIELD_MOUSE_R, + STARFIELD_MOUSE_M, + + STARFIELD_MOUSE_X, + STARFIELD_MOUSE_Y, + + _STARFIELD_MOUSE_BUTTON_COUNT, +}; + +struct starfield_mouse_input { + s16 x, y, z; + struct starfield_button_input buttons[_STARFIELD_MOUSE_BUTTON_COUNT]; +}; + +enum starfield_keyboard_button { + STARFIELD_KEYBOARD_ESC, + + STARFIELD_KEYBOARD_A, + STARFIELD_KEYBOARD_D, + STARFIELD_KEYBOARD_W, + STARFIELD_KEYBOARD_S, + STARFIELD_KEYBOARD_SPACE, + STARFIELD_KEYBOARD_SHIFT, + STARFIELD_KEYBOARD_CTRL, + + STARFIELD_KEYBOARD_Q, + STARFIELD_KEYBOARD_E, + + STARFIELD_KEYBOARD_J, + STARFIELD_KEYBOARD_L, + STARFIELD_KEYBOARD_I, + STARFIELD_KEYBOARD_K, + + _STARFIELD_KEYBOARD_BUTTON_COUNT, +}; + +struct starfield_keyboard_input { + struct starfield_button_input buttons[_STARFIELD_KEYBOARD_BUTTON_COUNT]; +}; + +struct starfield_input { + struct starfield_mouse_input mouse; + struct starfield_keyboard_input keyboard; +}; + +struct starfield_video_buffer { + void *buffer; + u32 width, height; + u32 pitch; +}; + +struct starfield_audio_buffer { + void *buffer; + u32 sample_rate; + u32 channels; + u32 expected_samples; +}; + +#define STARFIELD_INIT(name) \ + void name(struct starfield_thread *thread, \ + struct starfield_memory *memory, \ + struct platform_api *platform) + +#define STARFIELD_UPDATE(name) \ + void name(struct starfield_thread *thread, \ + struct starfield_memory *memory, \ + struct platform_api *platform, \ + struct starfield_input *input, \ + f32 dt) + +#define STARFIELD_RENDER(name) \ + void name(struct starfield_thread *thread, \ + struct starfield_memory *memory, \ + struct platform_api *platform, \ + struct starfield_video_buffer *video, \ + f32 dt) + +#define STARFIELD_SAMPLE(name) \ + void name(struct starfield_thread *thread, \ + struct starfield_memory *memory, \ + struct platform_api *platform, \ + struct starfield_audio_buffer *audio, \ + f32 dt) + +#define STARFIELD_FREE(name) \ + void name(struct starfield_thread *thread, \ + struct starfield_memory *memory, \ + struct platform_api *platform) + +typedef STARFIELD_INIT(starfield_api_init_t); +typedef STARFIELD_UPDATE(starfield_api_update_t); +typedef STARFIELD_RENDER(starfield_api_render_t); +typedef STARFIELD_SAMPLE(starfield_api_sample_t); +typedef STARFIELD_FREE(starfield_api_free_t); + +struct starfield_api { + starfield_api_init_t *init; + starfield_api_update_t *update; + starfield_api_render_t *render; + starfield_api_sample_t *sample; + starfield_api_free_t *free; +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* STARFIELD_API_H */ diff --git a/platform/linux_starfield.c b/platform/linux_starfield.c @@ -0,0 +1,167 @@ +#include "linux_starfield.h" + +internal struct linux_starfield_state state; + +int +main(int argc, char **argv, char **envp) +{ + /* TODO: parse out commandline arguments for debug behaviour? */ + (void) argc; + (void) envp; + + struct platform_api platform_api = load_platform_api(); + + struct starfield_thread thread = { + .id = 0, + }; + + struct starfield_memory memory; + if (!init_starfield_memory(256 * MiB, 256 * MiB, &memory)) { + fprintf(stderr, "Failed to allocate starfield memory\n"); + _exit(1); + } + + /* NOTE: we expect the library to be alongside our platform-specific + * executable. the unix loader does not search this path by default, + * so we build the absolute path to the library here as a workaround + */ + char starfield_library_path[PATH_MAX]; + strcpy(starfield_library_path, argv[0]); + strcpy(strrchr(starfield_library_path, '/'), "/starfield.so"); + + struct starfield_api starfield_api; + if (!load_starfield_api(starfield_library_path, &starfield_api)) { + fprintf(stderr, "Failed to load starfield library: %s\n", starfield_library_path); + _exit(1); + } + + starfield_api.init(&thread, &memory, &platform_api); + + state.running = 1; + while (state.running) { + f32 dt = 0; + + struct starfield_input input = { + 0, + }; + + starfield_api.update(&thread, &memory, &platform_api, &input, dt); + + struct starfield_video_buffer video = { + 0, + }; + + starfield_api.render(&thread, &memory, &platform_api, &video, dt); + + struct starfield_audio_buffer audio = { + 0, + }; + + starfield_api.sample(&thread, &memory, &platform_api, &audio, dt); + + sleep(1); + } + + starfield_api.free(&thread, &memory, &platform_api); + + _exit(0); +} + +b32 +init_starfield_memory(u64 permanent_memory_cap, u64 temporary_memory_cap, + struct starfield_memory *memory) +{ +#if STARFIELD_DEBUG + void *base_addr = (void *) (2 * TiB); +#else + void *base_addr = NULL; +#endif + + u64 len = permanent_memory_cap + temporary_memory_cap; + + /* TODO: add hugetlb support? seems to require a kernel commandline arg */ + void *ptr = mmap(base_addr, len, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0); + + if (ptr == MAP_FAILED) return false; + + /* TODO: can we make this faster? can we avoid this entirely? */ + memset(base_addr, 0, len); + + memory->permanent.ptr = ptr; + memory->permanent.cap = permanent_memory_cap; + memory->permanent.len = 0; + + memory->temporary.ptr = (u8 *) ptr + permanent_memory_cap; + memory->temporary.cap = temporary_memory_cap; + memory->temporary.len = 0; + + return true; +} + +b32 +load_starfield_api(char const *filename, struct starfield_api *api) +{ + void *library = dlopen(filename, RTLD_LAZY); + if (!library) return false; + + if (!(api->init = (starfield_api_init_t *) dlsym(library, "starfield_init"))) + return false; + + if (!(api->update = (starfield_api_update_t *) dlsym(library, "starfield_update"))) + return false; + + if (!(api->render = (starfield_api_render_t *) dlsym(library, "starfield_render"))) + return false; + + if (!(api->sample = (starfield_api_sample_t *) dlsym(library, "starfield_sample"))) + return false; + + if (!(api->free = (starfield_api_free_t *) dlsym(library, "starfield_free"))) + return false; + + return true; +} + +/* platform implementation + * =========================================================================== + */ + +#ifdef STARFIELD_DEBUG + +DEBUG_PLATFORM_READ_FILE(DEBUG_platform_read_file) +{ + (void) filename; + + return (struct DEBUG_platform_read_file_result) {0}; +} + +DEBUG_PLATFORM_WRITE_FILE(DEBUG_platform_write_file) +{ + (void) filename; + (void) buf; + (void) len; + + return true; +} + +DEBUG_PLATFORM_FREE_FILE_MEMORY(DEBUG_platform_free_file_memory) +{ + (void) ptr; +} + +#endif + +struct platform_api +load_platform_api(void) +{ + return (struct platform_api) { +#ifdef STARFIELD_DEBUG + .DEBUG_read_file = DEBUG_platform_read_file, + .DEBUG_write_file = DEBUG_platform_write_file, + .DEBUG_free_file_memory = DEBUG_platform_free_file_memory, +#endif + }; +} diff --git a/platform/linux_starfield.h b/platform/linux_starfield.h @@ -0,0 +1,34 @@ +#ifndef LINUX_STARFIELD_H +#define LINUX_STARFIELD_H + +#define _XOPEN_SOURCE 700 + +#include "starfield_api.h" + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <sys/mman.h> + +#include <dlfcn.h> + +struct starfield_thread { + u32 id; +}; + +struct linux_starfield_state { + b32 running; +}; + +struct platform_api +load_platform_api(void); + +b32 +init_starfield_memory(u64 permanent_memory_cap, u64 temporary_memory_cap, + struct starfield_memory *memory); + +b32 +load_starfield_api(char const *filename, struct starfield_api *api); + +#endif /* LINUX_STARFIELD_H */ diff --git a/platform/win_starfield.c b/platform/win_starfield.c @@ -0,0 +1,165 @@ +#include "win_starfield.h" + +internal struct win_starfield_state state; + +int WINAPI +WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow) +{ + (void) instance; + (void) prev_instance; + (void) cmdline; + (void) cmdshow; + + struct platform_api platform_api = load_platform_api(); + + struct starfield_thread thread = { + .id = 0, + }; + + struct starfield_memory memory; + if (!init_starfield_memory(256 * MiB, 256 * MiB, &memory)) { + fprintf(stderr, "Failed to allocate starfield memory\n"); + _exit(1); + } + + /* NOTE: the windows dll loader checks the parent directory of our + * instance when loading libraries, so no need to do anything fancy + */ + char starfield_library_path[] = "starfield.dll"; + + struct starfield_api starfield_api; + if (!load_starfield_api(starfield_library_path, &starfield_api)) { + fprintf(stderr, "Failed to load starfield library: %s\n", starfield_library_path); + _exit(1); + } + + starfield_api.init(&thread, &memory, &platform_api); + + state.running = 1; + while (state.running) { + f32 dt = 0; + + struct starfield_input input = { + 0, + }; + + starfield_api.update(&thread, &memory, &platform_api, &input, dt); + + struct starfield_video_buffer video = { + 0, + }; + + starfield_api.render(&thread, &memory, &platform_api, &video, dt); + + struct starfield_audio_buffer audio = { + 0, + }; + + starfield_api.sample(&thread, &memory, &platform_api, &audio, dt); + + Sleep(1000); + } + + starfield_api.free(&thread, &memory, &platform_api); + + _exit(0); +} + +b32 +init_starfield_memory(u64 permanent_memory_cap, u64 temporary_memory_cap, + struct starfield_memory *memory) +{ +#if STARFIELD_DEBUG + void *base_addr = (void *) (2 * TiB); +#else + void *base_addr = NULL; +#endif + + u64 len = permanent_memory_cap + temporary_memory_cap; + + /* TODO: add hugetlb support? + * https://learn.microsoft.com/en-us/windows/win32/memory/large-page-support + */ + void *ptr = VirtualAlloc(base_addr, len, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + + if (!ptr) return false; + + /* NOTE: windows guarantees that the memory returned by VirtualAlloc + * is zero-ed, so no need to memset it here + */ + + memory->permanent.ptr = ptr; + memory->permanent.cap = permanent_memory_cap; + memory->permanent.len = 0; + + memory->temporary.ptr = (u8 *) ptr + permanent_memory_cap; + memory->temporary.cap = temporary_memory_cap; + memory->temporary.len = 0; + + return true; +} + +b32 +load_starfield_api(char const *filename, struct starfield_api *api) +{ + HMODULE library = LoadLibraryA(filename); + if (!library) return false; + + if (!(api->init = (starfield_api_init_t *) GetProcAddress(library, "starfield_init"))) + return false; + + if (!(api->update = (starfield_api_update_t *) GetProcAddress(library, "starfield_update"))) + return false; + + if (!(api->render = (starfield_api_render_t *) GetProcAddress(library, "starfield_render"))) + return false; + + if (!(api->sample = (starfield_api_sample_t *) GetProcAddress(library, "starfield_sample"))) + return false; + + if (!(api->free = (starfield_api_free_t *) GetProcAddress(library, "starfield_free"))) + return false; + + return true; +} + +/* platform implementation + * =========================================================================== + */ + +#ifdef STARFIELD_DEBUG + +DEBUG_PLATFORM_READ_FILE(DEBUG_platform_read_file) +{ + (void) filename; + + return (struct DEBUG_platform_read_file_result) {0}; +} + +DEBUG_PLATFORM_WRITE_FILE(DEBUG_platform_write_file) +{ + (void) filename; + (void) buf; + (void) len; + + return false; +} + +DEBUG_PLATFORM_FREE_FILE_MEMORY(DEBUG_platform_free_file_memory) +{ + (void) ptr; +} + +#endif + +struct platform_api +load_platform_api(void) +{ + return (struct platform_api) { +#ifdef STARFIELD_DEBUG + .DEBUG_read_file = DEBUG_platform_read_file, + .DEBUG_write_file = DEBUG_platform_write_file, + .DEBUG_free_file_memory = DEBUG_platform_free_file_memory, +#endif + }; +} diff --git a/platform/win_starfield.h b/platform/win_starfield.h @@ -0,0 +1,28 @@ +#ifndef WIN_STARFIELD_H +#define WIN_STARFIELD_H + +#include "starfield_api.h" + +#include <stdio.h> + +#include <windows.h> + +struct starfield_thread { + u32 id; +}; + +struct win_starfield_state { + b32 running; +}; + +struct platform_api +load_platform_api(void); + +b32 +init_starfield_memory(u64 permanent_memory_cap, u64 temporary_memory_cap, + struct starfield_memory *memory); + +b32 +load_starfield_api(char const *filename, struct starfield_api *api); + +#endif /* WIN_STARFIELD_H */ diff --git a/setup_win.sh b/setup_win.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -ex + +git submodule update --init --recursive + +# TODO: switch from vsdownload.py to simplified script + +mkdir -p opt +python3 ./thirdparty/msvc-wine/vsdownload.py --dest opt +./thirdparty/msvc-wine/install.sh opt diff --git a/starfield/starfield.c b/starfield/starfield.c @@ -0,0 +1,47 @@ +#include "starfield.h" + +global +STARFIELD_INIT(starfield_init) +{ + (void) thread; + (void) memory; + (void) platform; +} + +global +STARFIELD_UPDATE(starfield_update) +{ + (void) thread; + (void) memory; + (void) platform; + (void) input; + (void) dt; +} + +global +STARFIELD_RENDER(starfield_render) +{ + (void) thread; + (void) memory; + (void) platform; + (void) video; + (void) dt; +} + +global +STARFIELD_SAMPLE(starfield_sample) +{ + (void) thread; + (void) memory; + (void) platform; + (void) audio; + (void) dt; +} + +global +STARFIELD_FREE(starfield_free) +{ + (void) thread; + (void) memory; + (void) platform; +} diff --git a/starfield/starfield.h b/starfield/starfield.h @@ -0,0 +1,6 @@ +#ifndef STARFIELD_H +#define STARFIELD_H + +#include "starfield_api.h" + +#endif /* STARFIELD_H */ diff --git a/thirdparty/msvc-wine b/thirdparty/msvc-wine @@ -0,0 +1 @@ +Subproject commit 2055e1b2a67868605479a4b0d747d1e58d2a8679