tuxanci2-engine
Game engine for tuxanci2
Log | Files | Refs | README | LICENSE
commit 7f6f8aa0c905f6cd780acf6709a7f8e473788aa6
parent 5450a7938bd6073a2aa9ec67fe63bdff500c3998
Author: Connor Thomson <connor@gnufault.org>
Date:   Sun, 18 Oct 2026 14:22:42 -0700

Add win32 target

Diffstat:
Aplatforms/win32/.gitignore | 1+
Aplatforms/win32/Makefile | 33+++++++++++++++++++++++++++++++++
Aplatforms/win32/win32.c | 201+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 235 insertions(+), 0 deletions(-)

diff --git a/platforms/win32/.gitignore b/platforms/win32/.gitignore @@ -0,0 +1 @@ +tuxanci2.exe diff --git a/platforms/win32/Makefile b/platforms/win32/Makefile @@ -0,0 +1,33 @@ +MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +ROOT_DIR := $(abspath $(MAKEFILE_DIR)/../..) + +WIN32_CC ?= i686-w64-mingw32-gcc +WIN32_CFLAGS ?= -O2 -Wall +WIN32_LDFLAGS ?= -Wl,--subsystem,windows:3.1 +WIN32_LDLIBS ?= -lgdi32 -luser32 +WIN32_BUILD ?= build/win32 + +WIN32_SOURCE := $(MAKEFILE_DIR)win32.c +WIN32_BUILD_DIR := $(ROOT_DIR)/$(WIN32_BUILD) +WIN32_LIBRARY := $(WIN32_BUILD_DIR)/tuxanci2.a +TARGET := $(MAKEFILE_DIR)tuxanci2.exe +ROOT_INPUTS := $(shell find $(ROOT_DIR)/src -type f -name '*.c') \ + $(wildcard $(ROOT_DIR)/include/*.h) \ + $(ROOT_DIR)/include/ta_config.h.in \ + $(shell find $(ROOT_DIR)/files -type f) \ + $(ROOT_DIR)/Makefile + +.DEFAULT_GOAL := all +.PHONY: all clean + +all: $(TARGET) + +$(WIN32_LIBRARY): $(ROOT_INPUTS) + $(MAKE) -C "$(ROOT_DIR)" CC="$(WIN32_CC)" BITS=32 BUILD_DIR="$(WIN32_BUILD)" all + +$(TARGET): $(WIN32_SOURCE) $(WIN32_LIBRARY) + $(WIN32_CC) $(WIN32_CFLAGS) -I"$(ROOT_DIR)/include" -I"$(WIN32_BUILD_DIR)" "$(WIN32_SOURCE)" "$(WIN32_LIBRARY)" $(WIN32_LDFLAGS) $(WIN32_LDLIBS) -o "$@" + +clean: + $(RM) "$(TARGET)" + $(MAKE) -C "$(ROOT_DIR)" BUILD_DIR="$(WIN32_BUILD)" clean diff --git a/platforms/win32/win32.c b/platforms/win32/win32.c @@ -0,0 +1,201 @@ +#include "ta_api.h" +#include <windows.h> +#include <stdlib.h> +#include <stdbool.h> + +#define WINDOW_WIDTH 800 +#define WINDOW_HEIGHT 600 +#define WINDOW_BPP 32 +#define TARGET_FPS 60 +#define FRAME_TIME_MS (1000 / TARGET_FPS) + +static HWND window_handle = NULL; +static BITMAPINFO bmi; +static bool is_running = true; + +static ta_keyboard_keys key_from_vk(WPARAM vk) { + if (vk >= 'A' && vk <= 'Z') { + return (ta_keyboard_keys)(KEY_A + (vk - 'A')); + } + if (vk >= '0' && vk <= '9') { + return (ta_keyboard_keys)(KEY_0 + (vk - '0')); + } + + switch (vk) { + case VK_BACK: return KEY_BACKSPACE; + case VK_TAB: return KEY_TAB; + case VK_RETURN: return KEY_ENTER; + case VK_ESCAPE: return KEY_ESCAPE; + case VK_SPACE: return KEY_SPACE; + case VK_OEM_7: return KEY_APOSTROPHE; + case VK_OEM_COMMA: return KEY_COMMA; + case VK_OEM_MINUS: return KEY_MINUS; + case VK_OEM_PERIOD: return KEY_PERIOD; + case VK_OEM_2: return KEY_SLASH; + case VK_OEM_1: return KEY_SEMICOLON; + case VK_OEM_PLUS: return KEY_EQUALS; + case VK_OEM_4: return KEY_LEFT_BRACKET; + case VK_OEM_5: return KEY_BACKSLASH; + case VK_OEM_6: return KEY_RIGHT_BRACKET; + case VK_OEM_3: return KEY_GRAVE_ACCENT; + case VK_DELETE: return KEY_DELETE; + case VK_UP: return KEY_UP; + case VK_DOWN: return KEY_DOWN; + case VK_LEFT: return KEY_LEFT; + case VK_RIGHT: return KEY_RIGHT; + case VK_F1: return KEY_F1; + case VK_F2: return KEY_F2; + case VK_F3: return KEY_F3; + case VK_F4: return KEY_F4; + case VK_F5: return KEY_F5; + case VK_F6: return KEY_F6; + case VK_F7: return KEY_F7; + case VK_F8: return KEY_F8; + case VK_F9: return KEY_F9; + case VK_F10: return KEY_F10; + case VK_F11: return KEY_F11; + case VK_F12: return KEY_F12; + case VK_HOME: return KEY_HOME; + case VK_END: return KEY_END; + case VK_PRIOR: return KEY_PAGE_UP; + case VK_NEXT: return KEY_PAGE_DOWN; + case VK_INSERT: return KEY_INSERT; + case VK_CAPITAL: return KEY_CAPS_LOCK; + case VK_NUMLOCK: return KEY_NUM_LOCK; + case VK_SCROLL: return KEY_SCROLL_LOCK; + case VK_SNAPSHOT: return KEY_PRINT_SCREEN; + case VK_PAUSE: return KEY_PAUSE; + case VK_APPS: return KEY_MENU; + case VK_SHIFT: return KEY_LEFT_SHIFT; + case VK_CONTROL: return KEY_LEFT_CTRL; + case VK_MENU: return KEY_LEFT_ALT; + case VK_LWIN: return KEY_LEFT_SUPER; + case VK_RWIN: return KEY_RIGHT_SUPER; + case VK_NUMPAD0: return KEY_KP_0; + case VK_NUMPAD1: return KEY_KP_1; + case VK_NUMPAD2: return KEY_KP_2; + case VK_NUMPAD3: return KEY_KP_3; + case VK_NUMPAD4: return KEY_KP_4; + case VK_NUMPAD5: return KEY_KP_5; + case VK_NUMPAD6: return KEY_KP_6; + case VK_NUMPAD7: return KEY_KP_7; + case VK_NUMPAD8: return KEY_KP_8; + case VK_NUMPAD9: return KEY_KP_9; + case VK_DECIMAL: return KEY_KP_DECIMAL; + case VK_DIVIDE: return KEY_KP_DIVIDE; + case VK_MULTIPLY: return KEY_KP_MULTIPLY; + case VK_SUBTRACT: return KEY_KP_SUBTRACT; + case VK_ADD: return KEY_KP_ADD; + default: return KEY_NONE; + } +} + +static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch (uMsg) { + case WM_CLOSE: + case WM_DESTROY: + is_running = false; + PostQuitMessage(0); + return 0; + + case WM_KILLFOCUS: + ta_keyboard_clear(); + return 0; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: { + ta_keyboard_key_down(key_from_vk(wParam)); + return 0; + } + + case WM_KEYUP: + case WM_SYSKEYUP: { + ta_keyboard_key_up(key_from_vk(wParam)); + return 0; + } + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + (void)hPrevInstance; + (void)lpCmdLine; + + const char* CLASS_NAME = "tuxanci2"; + + WNDCLASS wc = {0}; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.lpszClassName = CLASS_NAME; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + + if (!RegisterClass(&wc)) { + return 1; + } + + DWORD window_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + + RECT wr = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; + AdjustWindowRect(&wr, window_style, FALSE); + + window_handle = CreateWindowEx(0, CLASS_NAME, "", window_style, CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, hInstance, NULL); + + if (!window_handle) { + return 1; + } + + ZeroMemory(&bmi, sizeof(bmi)); + + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = WINDOW_WIDTH; + bmi.bmiHeader.biHeight = -WINDOW_HEIGHT; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = WINDOW_BPP; + bmi.bmiHeader.biCompression = BI_RGB; + ta_fb.width = WINDOW_WIDTH; + ta_fb.height = WINDOW_HEIGHT; + ta_fb.bpp = WINDOW_BPP; + + ta_main_init(); + + ShowWindow(window_handle, nCmdShow); + UpdateWindow(window_handle); + + HDC hdc = GetDC(window_handle); + + while (is_running) { + MSG msg; + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + is_running = false; + + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (!is_running) { + break; + } + + ta_main_update(); + + StretchDIBits(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, ta_fb.buffers[0], &bmi, DIB_RGB_COLORS, SRCCOPY); + + Sleep(FRAME_TIME_MS); + } + + ReleaseDC(window_handle, hdc); + return 0; +} + +void *ta_malloc(ta_size size) { + return malloc(size); +} + +void ta_free(void *ptr) { + free(ptr); +}