From 8d33b39730fd157e782f43914d136eb4c5083136 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sun, 22 Mar 2026 16:14:29 -0700 Subject: [PATCH] support both for building for Windows and via MSVC --- .gitignore | 6 +++ Makefile | 5 ++- include/collada/instance_types.h | 4 +- include/declarations.h | 9 ++++ include/directxmath/directxmath.h | 4 ++ include/font/outline_types.h | 8 ++-- include/new.h | 8 ++++ include/popcount.h | 6 +++ include/test.h | 34 ++++++++------- include/window.h | 4 +- main.lua | 18 +++++++- msvc/Makefile_windows | 71 +++++++++++++++++++++++++++++++ msvc/compile_debug.rsp | 18 ++++++++ msvc/compile_release.rsp | 19 +++++++++ msvc/link_release.rsp | 7 +++ src/boids.cpp | 2 +- src/collada/animate.cpp | 4 +- src/collada/scene.cpp | 7 ++- src/dds_validate.cpp | 2 +- src/font/bitmap.cpp | 2 +- src/font/outline.cpp | 2 +- src/lighting.cpp | 2 +- src/minecraft.cpp | 6 ++- src/test.cpp | 28 ++++++------ src/world/world.cpp | 6 ++- 25 files changed, 231 insertions(+), 51 deletions(-) create mode 100644 include/declarations.h create mode 100644 include/popcount.h create mode 100644 msvc/Makefile_windows create mode 100644 msvc/compile_debug.rsp create mode 100644 msvc/compile_release.rsp create mode 100644 msvc/link_release.rsp diff --git a/.gitignore b/.gitignore index 14e2268..ad21af0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +*.dll +*.exp +*.lib +*.pdb +*.idb +*.def .~* .\#* \#* diff --git a/Makefile b/Makefile index 35b6abf..7f018e1 100644 --- a/Makefile +++ b/Makefile @@ -14,14 +14,12 @@ CFLAGS += -fpic CFLAGS += -I./include CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -Wno-error=unused-but-set-variable CFLAGS += -Wno-error=unknown-pragmas -Wno-unknown-pragmas -CFLAGS += $(shell pkg-config --cflags glfw3) CFLAGS += -fno-strict-aliasing ifdef READ_PACK_FILE CFLAGS += -DREAD_PACK_FILE endif LDFLAGS += -lm -LDFLAGS += $(shell pkg-config --libs glfw3) MINECRAFT_OBJS = \ minecraft/love2dworld/inthash.o \ @@ -83,6 +81,9 @@ test.pack.o: test.pack test.so: $(OBJS) $(CC) $(ARCH) $(OPT) -Wl,-z noexecstack -shared -g $^ -o $@ -lSDL3 +test.dll: $(OBJS) + $(CXX) $(ARCH) $(OPT) -mthreads -static -mdll -static-libstdc++ -static-libgcc -g $^ -o $@ -L. -lSDL3 $(WINDOWS) + main: $(OBJS) src/main.o $(CC) $(ARCH) $(LDFLAGS) $(OPT) -g $^ -o $@ diff --git a/include/collada/instance_types.h b/include/collada/instance_types.h index c315fe9..2d53802 100644 --- a/include/collada/instance_types.h +++ b/include/collada/instance_types.h @@ -6,13 +6,13 @@ namespace collada::instance_types { - struct __attribute__((aligned(16))) lookat { + struct XM_ALIGNED_DATA(16) lookat { XMVECTOR eye; XMVECTOR at; XMVECTOR up; }; - struct __attribute__((aligned(16))) transform { + struct XM_ALIGNED_DATA(16) transform { union { instance_types::lookat lookat; XMMATRIX matrix; diff --git a/include/declarations.h b/include/declarations.h new file mode 100644 index 0000000..0cc69d6 --- /dev/null +++ b/include/declarations.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef _MSC_VER +#define EXPORT __declspec(dllexport) +#define DECL __cdecl +#else +#define EXPORT __attribute__((dllexport)) +#define DECL __attribute__((__cdecl__)) +#endif diff --git a/include/directxmath/directxmath.h b/include/directxmath/directxmath.h index 0318518..25f752d 100644 --- a/include/directxmath/directxmath.h +++ b/include/directxmath/directxmath.h @@ -9,8 +9,10 @@ #pragma once +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif #ifndef __cplusplus #error DirectX Math requires C++ @@ -2218,4 +2220,6 @@ namespace DirectX using namespace DirectX; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif diff --git a/include/font/outline_types.h b/include/font/outline_types.h index 2ef4930..de4a3c7 100644 --- a/include/font/outline_types.h +++ b/include/font/outline_types.h @@ -10,7 +10,7 @@ namespace font::outline::types { int32_t horiBearingX; int32_t horiBearingY; int32_t horiAdvance; - } __attribute__ ((packed)); + }; static_assert((sizeof (struct glyph_metrics)) == ((sizeof (int32_t)) * 3)); @@ -19,14 +19,14 @@ namespace font::outline::types { uint16_t y; uint16_t width; uint16_t height; - } __attribute__ ((packed)); + }; static_assert((sizeof (struct glyph_bitmap)) == ((sizeof (uint16_t)) * 4)); struct glyph { struct glyph_bitmap bitmap; struct glyph_metrics metrics; - } __attribute__ ((packed)); + }; static_assert((sizeof (struct glyph)) == ((sizeof (struct glyph_bitmap)) + (sizeof (struct glyph_metrics)))); @@ -42,7 +42,7 @@ namespace font::outline::types { uint16_t texture_width; uint16_t texture_height; uint32_t max_z_curve_ix; - } __attribute__ ((packed)); + }; static_assert((sizeof (struct font)) == ((sizeof (uint32_t)) * 7)); diff --git a/include/new.h b/include/new.h index b1a73dd..eb78e68 100644 --- a/include/new.h +++ b/include/new.h @@ -2,6 +2,14 @@ #include +#ifdef aligned_alloc +#undef aligned_alloc +#endif + +#ifdef _WIN32 +#define aligned_alloc(alignment, size) _aligned_malloc(size, alignment) +#endif + template T * New(int elements) { diff --git a/include/popcount.h b/include/popcount.h new file mode 100644 index 0000000..580e172 --- /dev/null +++ b/include/popcount.h @@ -0,0 +1,6 @@ +#pragma once + +#ifdef _MSC_VER +#include +#define __builtin_popcount __popcnt +#endif diff --git a/include/test.h b/include/test.h index 04d8cf6..5a22ffe 100644 --- a/include/test.h +++ b/include/test.h @@ -1,25 +1,27 @@ #pragma once +#include "declarations.h" + #ifdef __cplusplus extern "C" { #endif - void load(const char * source_path); - void draw(); - void love2d_state_load(); - void love2d_state_restore(); - void update_keyboard(int up, int down, int left, int right, - int w, int s, int a, int d, - int t, int g, int f, int h, - int i, int k, int j, int l); - void update_mouse(int x, int y); - void update_joystick(int joystick_index, - float lx, float ly, float rx, float ry, float tl, float tr, - int up, int down, int left, int right, - int a, int b, int x, int y, - int leftshoulder, int rightshoulder, - int start); - void update(float time); + EXPORT void DECL load(const char * source_path); + EXPORT void DECL draw(); + EXPORT void DECL love2d_state_load(); + EXPORT void DECL love2d_state_restore(); + EXPORT void DECL update_keyboard(int up, int down, int left, int right, + int w, int s, int a, int d, + int t, int g, int f, int h, + int i, int k, int j, int l); + EXPORT void DECL update_mouse(int x, int y); + EXPORT void DECL update_joystick(int joystick_index, + float lx, float ly, float rx, float ry, float tl, float tr, + int up, int down, int left, int right, + int a, int b, int x, int y, + int leftshoulder, int rightshoulder, + int start); + EXPORT void DECL update(float time); #ifdef __cplusplus } diff --git a/include/window.h b/include/window.h index a956ffa..70467ff 100644 --- a/include/window.h +++ b/include/window.h @@ -1,5 +1,7 @@ #pragma once +#include "declarations.h" + namespace window { extern float width; extern float height; @@ -8,7 +10,7 @@ namespace window { #ifdef __cplusplus extern "C" { #endif - void update_window(int width, int height); + EXPORT void DECL update_window(int width, int height); #ifdef __cplusplus } #endif diff --git a/main.lua b/main.lua index 9650c4d..f8d532a 100644 --- a/main.lua +++ b/main.lua @@ -37,6 +37,8 @@ void update(float time); local is_zip = source_path:sub(-#".zip") == ".zip" local is_love = source_path:sub(-#".love") == ".love" + local platform = love.system.getOS() + if is_zip or is_love then if love.filesystem.isFused() then local archive = love.filesystem.getSourceBaseDirectory() @@ -49,9 +51,21 @@ void update(float time); -- the love2d "filesystem" API is the worst possible design in the -- entire history of computing - test = ffi.load(app_data .. "/love/love-demo2/test.so") + if platform == "Linux" then + test = ffi.load(app_data .. "/love/love-demo2/test.so") + elseif platform == "Windows" then + test = ffi.load(app_data .. "/love/love-demo2/test.dll") + else + assert(false, "unsupported platform: " .. platform) + end else - test = ffi.load("./test.so") + if platform == "Linux" then + test = ffi.load("./test.so") + elseif platform == "Windows" then + test = ffi.load("./test.dll") + else + assert(false, "unsupported platform: " .. platform) + end end test.load(source_path) end diff --git a/msvc/Makefile_windows b/msvc/Makefile_windows new file mode 100644 index 0000000..b418439 --- /dev/null +++ b/msvc/Makefile_windows @@ -0,0 +1,71 @@ +#PREFIX = x86_64-w64-mingw32- +CC=$(PREFIX)gcc +CXX=$(PREFIX)g++ +OBJCOPY=$(PREFIX)objcopy + +OBJARCH = elf64-x86-64 + +OPT = -O0 -march=x86-64-v3 + +CSTD = -std=gnu23 +CXXSTD = -std=gnu++23 +CFLAGS += -g +CFLAGS += -fpic +CFLAGS += -I./include +CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -Wno-error=unused-but-set-variable +CFLAGS += -Wno-error=unknown-pragmas -Wno-unknown-pragmas +CFLAGS += -fno-strict-aliasing +CFLAGS += -no-pthread +ifdef READ_PACK_FILE +CFLAGS += -DREAD_PACK_FILE +endif + +LDFLAGS += -lm + +MINECRAFT_OBJS = \ + minecraft/love2dworld/inthash.o \ + minecraft/grandlecturn/inthash.o \ + minecraft/midnightmeadow/inthash.o \ + src/minecraft.o \ + src/world/world.o \ + src/world/entry_table.o + +OBJS = \ + src/gl.o \ + src/opengl.o \ + src/test.o \ + src/font/bitmap.o \ + src/font/outline.o \ + src/window.o \ + src/bresenham.o \ + src/file.o \ + src/non_block.o \ + src/view.o \ + src/hud.o \ + src/lighting.o \ + src/collision_scene.o \ + src/line_art.o \ + src/boids.o \ + src/boids_scene.o \ + src/dds_validate.o \ + src/collada/scene.o \ + src/collada/effect.o \ + src/collada/node_state.o \ + src/collada/animate.o \ + src/lua_api.o \ + src/pixel_line_art.o \ + src/flame.o \ + $(MINECRAFT_OBJS) + +%.o: %.c + cl.exe /Fo"$@" @"compile_debug.rsp" $< + +%.o: %.cpp + cl.exe /Fo"$@" @"compile_debug.rsp" $< + + +#link.exe /OUT:"$@" @"link_release.rsp" $(OBJS) /NOLOGO /ERRORREPORT:PROMPT +test.dll: $(OBJS) + cl.exe /DEBUG /D_USRDLL /D_WINDLL $(OBJS) /link /DLL /OUT:$@ /LIBPATH:../SDL/Debug SDL3.lib /PDB:"test.pdb" + +all: $(OBJS) diff --git a/msvc/compile_debug.rsp b/msvc/compile_debug.rsp new file mode 100644 index 0000000..444cca9 --- /dev/null +++ b/msvc/compile_debug.rsp @@ -0,0 +1,18 @@ +/Od +/D "WIN32" +/D "_DEBUG" +/D "_WINDOWS" +/D "_UNICODE" +/D "UNICODE" +/D "_WIN32_WINNT=0x0501" +/I ".\include" +/I "..\SDL\include" +/EHsc +/RTC1 +/MDd +/W3 +/c +/Z7 +/nologo +/errorReport:prompt +/std:c++20 diff --git a/msvc/compile_release.rsp b/msvc/compile_release.rsp new file mode 100644 index 0000000..26b0976 --- /dev/null +++ b/msvc/compile_release.rsp @@ -0,0 +1,19 @@ +/O2 +/GL +/D "WIN32" +/D "NDEBUG" +/D "_WINDOWS" +/D "_UNICODE" +/D "UNICODE" +/D "_WIN32_WINNT=0x0501" +/I ".\include" +/I "..\SDL\include" +/FD +/EHsc +/MT +/W3 +/c +/Zi +/nologo +/errorReport:prompt +/std:c++20 \ No newline at end of file diff --git a/msvc/link_release.rsp b/msvc/link_release.rsp new file mode 100644 index 0000000..c1b1819 --- /dev/null +++ b/msvc/link_release.rsp @@ -0,0 +1,7 @@ +/MANIFEST:NO +/INCREMENTAL:NO +/OPT:REF +/OPT:ICF +/LTCG +/MACHINE:X64 +SDL3.lib \ No newline at end of file diff --git a/src/boids.cpp b/src/boids.cpp index f18a427..ebd048d 100644 --- a/src/boids.cpp +++ b/src/boids.cpp @@ -26,7 +26,7 @@ namespace boids { forces.separation.force = XMVectorZero(); } - inline constexpr bool vector_equal(XMVECTOR V1, XMVECTOR V2) + static inline bool vector_equal(XMVECTOR V1, XMVECTOR V2) { uint32_t CR; XMVectorEqualR(&CR, V1, V2); diff --git a/src/collada/animate.cpp b/src/collada/animate.cpp index e23650a..b33c4bf 100644 --- a/src/collada/animate.cpp +++ b/src/collada/animate.cpp @@ -121,7 +121,7 @@ namespace collada::animate { float value) { switch (transform.type) { - case types::transform_type::TRANSLATE: __attribute__((fallthrough)); + case types::transform_type::TRANSLATE: [[fallthrough]]; case types::transform_type::SCALE: switch (channel_target_attribute) { case types::target_attribute::X: transform.vector = XMVectorSetX(transform.vector, value); return; @@ -164,7 +164,7 @@ namespace collada::animate { int target_attributes_count = 1; if (channel.target_attribute == types::target_attribute::ALL) { switch (transform.type) { - case types::transform_type::TRANSLATE: __attribute__((fallthrough)); + case types::transform_type::TRANSLATE: [[fallthrough]]; case types::transform_type::SCALE: target_attributes = translate_scale_target_attributes; target_attributes_count = 3; diff --git a/src/collada/scene.cpp b/src/collada/scene.cpp index dbab6ed..89703e8 100644 --- a/src/collada/scene.cpp +++ b/src/collada/scene.cpp @@ -446,14 +446,16 @@ namespace collada::scene { void state::draw_instance_controllers(types::instance_controller const * const instance_controllers, int const instance_controllers_count) { + static int const max_joints = 64; + static XMFLOAT4X4 joints[max_joints]; + for (int i = 0; i < instance_controllers_count; i++) { types::instance_controller const &instance_controller = instance_controllers[i]; types::skin const &skin = instance_controller.controller->skin; XMMATRIX bsm = XMLoadFloat4x4((XMFLOAT4X4*)&skin.bind_shape_matrix); - XMFLOAT4X4 joints[instance_controller.joint_count]; - int joints_size = (sizeof (joints)); + assert(instance_controller.joint_count < max_joints); for (int joint_index = 0; joint_index < instance_controller.joint_count; joint_index++) { XMMATRIX ibm = XMLoadFloat4x4((XMFLOAT4X4*)&skin.inverse_bind_matrices[joint_index]); int node_index = instance_controller.joint_node_indices[joint_index]; @@ -461,6 +463,7 @@ namespace collada::scene { XMStoreFloat4x4(&joints[joint_index], bsm * ibm * node_instance.world); } + int joints_size = (sizeof (XMFLOAT4X4)) * instance_controller.joint_count; glBindBuffer(GL_UNIFORM_BUFFER, joint_uniform_buffer); glBufferData(GL_UNIFORM_BUFFER, joints_size, (void *)&joints[0], GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); diff --git a/src/dds_validate.cpp b/src/dds_validate.cpp index 0e0a615..5d8059b 100644 --- a/src/dds_validate.cpp +++ b/src/dds_validate.cpp @@ -41,7 +41,7 @@ static inline dds_size_levels dds_mip_total_size(uintptr_t data, width /= 2; } - return (dds_size_levels){mip_total_size, mip_levels}; + return {mip_total_size, mip_levels}; } DDS_FILE const * dds_validate(void const * data, unsigned int size, void ** out_data, int * out_size) diff --git a/src/font/bitmap.cpp b/src/font/bitmap.cpp index 2e9285f..1054c72 100644 --- a/src/font/bitmap.cpp +++ b/src/font/bitmap.cpp @@ -69,7 +69,7 @@ namespace font::bitmap { glBindTexture(GL_TEXTURE_2D, 0); - return (font){ + return { .desc = &desc, .texture = texture, .stride = desc.texture_width / desc.glyph_width, diff --git a/src/font/outline.cpp b/src/font/outline.cpp index 2de90ee..4b6ce4a 100644 --- a/src/font/outline.cpp +++ b/src/font/outline.cpp @@ -74,7 +74,7 @@ namespace font::outline { // font_data intentionally not free'd - return (outline::font){ + return { .texture = texture, .font = font, .glyphs = glyphs, diff --git a/src/lighting.cpp b/src/lighting.cpp index efd21fc..8441a4f 100644 --- a/src/lighting.cpp +++ b/src/lighting.cpp @@ -11,7 +11,7 @@ extern unsigned int empty_vertex_array_object; extern unsigned int quad_index_buffer; -extern geometry_buffer<3> geometry_buffer_pnc; +extern geometry_buffer<4> geometry_buffer_pnc; namespace lighting { diff --git a/src/minecraft.cpp b/src/minecraft.cpp index 2af9b31..acbc908 100644 --- a/src/minecraft.cpp +++ b/src/minecraft.cpp @@ -11,6 +11,7 @@ #include "minecraft.h" #include "minecraft_data.inc" #include "new.h" +#include "popcount.h" #include "world/world.h" namespace minecraft { @@ -205,7 +206,10 @@ namespace minecraft { static void load_regions(world::descriptor const * const descriptor, world::region * region) { - unsigned int per_instance_vertex_buffers[descriptor->region_count]; + static int const max_region_count = 128; + static unsigned int per_instance_vertex_buffers[max_region_count]; + + assert(descriptor->region_count < max_region_count); glGenBuffers(descriptor->region_count, per_instance_vertex_buffers); for (int i = 0; i < descriptor->region_count; i++) { // vtx diff --git a/src/test.cpp b/src/test.cpp index beea871..a1e5d90 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -28,6 +28,8 @@ #include "pixel_line_art.h" #include "flame.h" #include "new.h" +#include "popcount.h" +#include "declarations.h" #include "world/entry_table.h" #include "world/world.h" @@ -74,10 +76,14 @@ font::outline::font * uncial_antiqua_fonts; geometry_buffer<4> geometry_buffer_pnc = {}; static target_type const geometry_buffer_pnc_types[4] = { - [target_name::POSITION] = { GL_RGBA16F, GL_COLOR_ATTACHMENT0 }, - [target_name::NORMAL] = { GL_RGBA16F, GL_COLOR_ATTACHMENT1 }, - [target_name::COLOR] = { GL_RGBA8, GL_COLOR_ATTACHMENT2 }, - [target_name::BLOCK] = { GL_RGBA16F, GL_COLOR_ATTACHMENT3 }, + //[target_name::POSITION] = + { GL_RGBA16F, GL_COLOR_ATTACHMENT0 }, + //[target_name::NORMAL] = + { GL_RGBA16F, GL_COLOR_ATTACHMENT1 }, + //[target_name::COLOR] = + { GL_RGBA8, GL_COLOR_ATTACHMENT2 }, + //[target_name::BLOCK] = + { GL_RGBA16F, GL_COLOR_ATTACHMENT3 }, }; collada::instance_types::node * node_eye; @@ -110,9 +116,7 @@ void load_quad_program() quad_program = program; } -extern "C" { - void * SDL_GL_GetProcAddress(const char *proc); -} +extern "C" void * DECL SDL_GL_GetProcAddress(const char *proc); void load(const char * source_path) { @@ -194,10 +198,10 @@ void load(const char * source_path) // collada ////////////////////////////////////////////////////////////////////// - collada::effect::load_effects(); - scene_state.load_scene(&book::descriptor); - node_eye = scene_state.find_node_by_name("Camera"); - assert(node_eye != nullptr); + //collada::effect::load_effects(); + //scene_state.load_scene(&book::descriptor); + //node_eye = scene_state.find_node_by_name("Camera"); + //assert(node_eye != nullptr); //view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world); //node_at = scene_state.find_node_by_name("Camera001.Target"); @@ -349,7 +353,7 @@ void update(float time) { current_time = time; - scene_state.update(time); + //scene_state.update(time); /* view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world); if (node_at == nullptr) diff --git a/src/world/world.cpp b/src/world/world.cpp index a436ef6..2cf76e6 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -17,14 +17,16 @@ namespace world { }; descriptor const descriptors[] = { - [world_id::GRANDLECTURN] = { + //[world_id::GRANDLECTURN] = + { .region_count = 4, .vertex_paths = grandlecturn_vertex_paths, .entry_table_path = "minecraft/grandlecturn/global.dump", .lights_path = "minecraft/grandlecturn/global.lights.vtx", .hash_func = grandlecturn_hash, }, - [world_id::MIDNIGHTMEADOW] = { + //[world_id::MIDNIGHTMEADOW] = + { .region_count = 4, .vertex_paths = midnightmeadow_vertex_paths, .entry_table_path = "minecraft/midnightmeadow/global.dump",