diff options
author | fschildt <florian.schildt@protonmail.com> | 2025-08-22 15:23:11 +0200 |
---|---|---|
committer | fschildt <florian.schildt@protonmail.com> | 2025-08-22 15:23:11 +0200 |
commit | 2050c0e0576f05156f192aa4caf48834d2f28b14 (patch) | |
tree | ee58bd35b0df0a1bacfbc9700ed99ce80c99294e /src/graveyard/win32 |
Diffstat (limited to 'src/graveyard/win32')
-rw-r--r-- | src/graveyard/win32/Win32WindowService.cpp | 375 | ||||
-rw-r--r-- | src/graveyard/win32/Win32WindowService.h | 33 | ||||
-rw-r--r-- | src/graveyard/win32/win32_florilia.c | 111 | ||||
-rw-r--r-- | src/graveyard/win32/win32_fscord.cpp | 181 | ||||
-rw-r--r-- | src/graveyard/win32/win32_net.c | 79 | ||||
-rw-r--r-- | src/graveyard/win32/win32_network_stream.cpp | 90 | ||||
-rw-r--r-- | src/graveyard/win32/win32_window.c | 389 | ||||
-rw-r--r-- | src/graveyard/win32/win32_window.cpp | 77 |
8 files changed, 1335 insertions, 0 deletions
diff --git a/src/graveyard/win32/Win32WindowService.cpp b/src/graveyard/win32/Win32WindowService.cpp new file mode 100644 index 0000000..80d17c0 --- /dev/null +++ b/src/graveyard/win32/Win32WindowService.cpp @@ -0,0 +1,375 @@ +#include <stdio.h> + +static DWORD g_main_thread_id; +static PIXELFORMATDESCRIPTOR g_pfd; + +internal LRESULT +win32__window_proc(HWND window, UINT message, WPARAM w_param, LPARAM l_param) +{ + LRESULT result = 0; + switch (message) + { + case WM_CLOSE: + case WM_QUIT: + case WM_CHAR: + case WM_SIZE: + { + PostThreadMessage(g_main_thread_id, message, w_param, l_param); + } + break; + + case WM_KEYDOWN: + { + if (w_param >= VK_LEFT && w_param <= VK_DOWN) + { + PostThreadMessage(g_main_thread_id, message, w_param, l_param); + } + else + { + // let windows turn this into a WM_CHAR + result = DefWindowProcA(window, message, w_param, l_param); + } + } + break; + + default: + { + result = DefWindowProcA(window, message, w_param, l_param); + } + break; + } + + return result; +} + +internal HWND +win32__create_window(const char *name, int width, int height) +{ + const char *classname = "win32_window_class"; + + WNDCLASSEX window_class = {}; + window_class.style = CS_OWNDC; + window_class.cbSize = sizeof(window_class); + window_class.lpfnWndProc = &win32__window_proc; + window_class.hInstance = GetModuleHandle(NULL); + window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); + window_class.hCursor = LoadCursor(NULL, IDC_ARROW); + window_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + window_class.lpszClassName = classname; + if (RegisterClassExA(&window_class) == 0) + { + printf("RegisterClassEx() failed\n"); + return 0; + } + + HWND window = CreateWindowExA(0, + classname, + name, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + width, + height, + 0, + 0, + window_class.hInstance, + 0); + if (!window) + { + printf("CreateWindowEx() failed\n"); + } + + return window; +} + +internal void +win32__destroy_window(HWND window) +{ + DestroyWindow(window); +} + +internal LRESULT +win32__service_window_proc(HWND window, UINT message, WPARAM w_param, LPARAM l_param) +{ + LRESULT result = 0; + switch (message) + { + case Win32WindowService::CREATE_WINDOW: + { + Win32WindowSettings *settings = (Win32WindowSettings*)w_param; + + HWND handle = win32__create_window(settings->name, settings->width, settings->height); + result = (LRESULT)handle; + } + break; + + case Win32WindowService::DESTROY_WINDOW: + { + win32__destroy_window(window); + } + break; + + default: + { + result = DefWindowProc(window, message, w_param, l_param); + } + break; + } + return result; +} + +HWND +win32__create_service_window() +{ + PIXELFORMATDESCRIPTOR *pfd = &g_pfd; + memset(pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + pfd->nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd->nVersion = 1; + pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; + pfd->iPixelType = PFD_TYPE_RGBA; + pfd->cColorBits = 32; + pfd->cDepthBits = 24; + pfd->cStencilBits = 8; + pfd->iLayerType = PFD_MAIN_PLANE; + + WNDCLASSEX swc = {}; + swc.style = CS_OWNDC; + swc.cbSize = sizeof(swc); + swc.lpfnWndProc = &win32__service_window_proc; + swc.hInstance = GetModuleHandle(NULL); + swc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + swc.hCursor = LoadCursor(NULL, IDC_ARROW); + swc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + swc.lpszClassName = "win32_service_window_class"; + if (RegisterClassEx(&swc) == 0) + { + printf("RegisterClassEx() failed\n"); + return 0; + } + + const char *name = "win32_service_window"; + HWND handle = CreateWindowEx(0, + swc.lpszClassName, + name, + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + 0, + 0, + swc.hInstance, + 0); + if (!handle) + { + printf("CreateWindowEx() for service window failed\n"); + return 0; + } + + HDC dc = GetDC(handle); + if (!dc) + { + printf("GetDC() for service window failed\n"); + DestroyWindow(handle); + return 0; + } + + int pixel_format = ChoosePixelFormat(dc, &g_pfd); + if (pixel_format == 0) + { + printf("ChoosePixelFormat() for service window failed\n"); + DestroyWindow(handle); + return 0; + } + + BOOL pixel_format_set = SetPixelFormat(dc, pixel_format, &g_pfd); + if (pixel_format_set == FALSE) + { + printf("SetPixelFormat() for service window failed\n"); + DestroyWindow(handle); + return 0; + } + + return handle; +} + +DWORD WINAPI +win32__window_service_thread(LPVOID data) +{ + Win32WindowService *window_service = (Win32WindowService*)data; + + // create service window and report back to main thread + HWND service_window = win32__create_service_window(); + window_service->m_ServiceWindow = service_window; + if (!service_window) + { + PostThreadMessage(g_main_thread_id, Win32WindowService::SERVICE_WINDOW_NOT_CREATED, 0, 0); + return 0; + } + PostThreadMessage(g_main_thread_id, Win32WindowService::SERVICE_WINDOW_CREATED, 0, 0); + + // get events for all windows, redirect to service window proc, let it report back + for (;;) + { + MSG message; + BOOL recvd = GetMessageA(&message, 0, 0, 0); + if (recvd == -1) + { + printf("GetMessage failed\n"); + return 0; + } + + TranslateMessage(&message); + DispatchMessage(&message); + } +} + +bool +Win32WindowService::Init() +{ + DWORD main_thread_id = GetCurrentThreadId(); + g_main_thread_id = main_thread_id; + + DWORD tid; + HANDLE thread = CreateThread(0, 0, win32__window_service_thread, this, 0, &tid); + if (!thread) + { + printf("CreatThread() when starting window manager failed\n"); + return false; + } + + // wait until service window is ready + for (;;) + { + MSG message; + GetMessageA(&message, 0, 0, 0); + + if (message.message == Win32WindowService::SERVICE_WINDOW_CREATED) + return true; + else if (message.message == Win32WindowService::SERVICE_WINDOW_NOT_CREATED) + return false; + else assert(0); + } +} + +Win32Window * +Win32WindowService::CreateWin32Window(const char *name, int width, int height) +{ + static int counter = 0; + assert(counter++ == 0); + + // let the service (other thread) create the window + Win32WindowSettings settings = {}; + settings.name = name; + settings.width = width; + settings.height = height; + + HWND handle = (HWND)SendMessage(m_ServiceWindow, Win32WindowService::CREATE_WINDOW, (WPARAM)&settings, 0); + if (!handle) return 0; + + + // do remaining initialization + HDC dc = GetDC(handle); + if (!dc) + { + printf("GetDC failed\n"); + return 0; + } + + PIXELFORMATDESCRIPTOR *pfd = &g_pfd; + int pixel_format = ChoosePixelFormat(dc, pfd); + if (pixel_format == 0) + { + printf("ChoosePixelFormat failed\n"); + return false; + } + + BOOL pixel_format_set = SetPixelFormat(dc, pixel_format, &g_pfd); + if (pixel_format_set == FALSE) + { + printf("SetPixelFormat() failed\n"); + return false; + } + + Win32Window *window = new Win32Window(handle, dc); + if (!window->RecreateOffscreenBuffer(width, height)) + { + delete window; + window = 0; + } + return window; +} + +void +Win32WindowService::DestroyWin32Window(Win32Window *window) +{ + SendMessage(m_ServiceWindow, Win32WindowService::DESTROY_WINDOW, (WPARAM)window, 0); + delete window; +} + +i32 +Win32WindowService::GetWindowEvents(Win32Window *window, Sys_Event *events, i32 max_event_count) +{ + i32 event_count = 0; + + // This receives messages for all windows, so we can only have 1 window atm. + MSG msg; + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) && event_count < max_event_count) + { + Sys_Event *event = events + event_count; + switch (msg.message) + { +#define ADD_KEY_EVENT(keycode) \ + event->type = SYS_EVENT_KEY; \ + event->key.c = (char)keycode; \ + event_count += 1; + case WM_CHAR: + { + char keycode = (char)msg.wParam; + bool is_down = (msg.lParam & (1<<31)) == 0; + if (is_down) + { + ADD_KEY_EVENT(keycode); + } + } + break; + + case WM_KEYDOWN: + { + if (msg.wParam == VK_LEFT) {ADD_KEY_EVENT(SYS_KEY_LEFT)} + else if (msg.wParam == VK_UP) {ADD_KEY_EVENT(SYS_KEY_UP)} + else if (msg.wParam == VK_RIGHT) {ADD_KEY_EVENT(SYS_KEY_RIGHT)} + else if (msg.wParam == VK_DOWN) {ADD_KEY_EVENT(SYS_KEY_DOWN)} + else if (msg.wParam == VK_TAB) {ADD_KEY_EVENT('\t')} + else if (msg.wParam == VK_RETURN){ADD_KEY_EVENT('\r')} + else {} + } + break; +#undef ADD_KEY_EVENT + + case WM_SIZE: + { + i32 width = (i32)LOWORD(msg.lParam); + i32 height = (i32)HIWORD(msg.lParam); + window->RecreateOffscreenBuffer(width, height); + } + break; + + case WM_CLOSE: + case WM_QUIT: + { + return -1; + } + break; + + + default: + { + printf("unhandled window event %d\n", msg.message); + } + } + } + + return event_count; +} + diff --git a/src/graveyard/win32/Win32WindowService.h b/src/graveyard/win32/Win32WindowService.h new file mode 100644 index 0000000..a02ef2b --- /dev/null +++ b/src/graveyard/win32/Win32WindowService.h @@ -0,0 +1,33 @@ +struct Win32WindowSettings +{ + const char *name; + int width; + int height; +}; + +class Win32WindowService +{ +public: + bool Init(); + + Win32Window *CreateWin32Window(const char *name, int width, int height); + void DestroyWin32Window(Win32Window *window); + i32 GetWindowEvents(Win32Window *window, Sys_Event *events, i32 max_event_count); + void ShowOffscreenBuffer(Win32Window *window); + + enum + { + SERVICE_WINDOW_CREATED = (WM_USER + 0), + SERVICE_WINDOW_NOT_CREATED = (WM_USER + 1), + CREATE_WINDOW = (WM_USER + 2), + DESTROY_WINDOW = (WM_USER + 3), + WINDOW_CREATED = (WM_USER + 4), + WINDOW_DESTROYED = (WM_USER + 5) + }; + +private: + void RecreateOffscreenBuffer(Sys_Offscreen_Buffer *buff, i32 width, i32 height); + +public: + HWND m_ServiceWindow; +}; diff --git a/src/graveyard/win32/win32_florilia.c b/src/graveyard/win32/win32_florilia.c new file mode 100644 index 0000000..0c2b807 --- /dev/null +++ b/src/graveyard/win32/win32_florilia.c @@ -0,0 +1,111 @@ +// Note: This is a minimal port to win32, the main target is linux.
+
+#include "../florilia_platform.h"
+#include <windows.h>
+
+
+#include <stdio.h>
+
+typedef struct {
+ BITMAPINFO bitmap_info;
+ i32 width;
+ i32 height;
+ u32 *pixels;
+} Win32_Offscreen_Buffer;
+
+typedef struct {
+ HWND window;
+ HDC dc;
+ Win32_Offscreen_Buffer offscreen_buffer;
+} Win32_Window;
+
+typedef struct {
+ const char *name;
+ int width;
+ int height;
+} Win32_Window_Settings;
+
+#include "win32_window.c"
+#include "win32_net.c"
+
+internal
+PLATFORM_GET_TIME(win32_get_time)
+{
+ florilia_time->seconds = 0;
+ florilia_time->nanoseconds = 0;
+#if 0
+ LARGE_INTEGER frequency;
+ if (QueryPerformanceFrequency(&frequency) == FALSE)
+ {
+ printf("frequency.QuadPart = %lld\n", frequency.QuadPart);
+ }
+
+ LARGE_INTEGER perf_counter;
+ if (QueryPerformanceCounter(&perf_counter) == FALSE)
+ {
+ printf("perf_counter.QuadPart = %lld\n", perf_counter.QuadPart);
+ }
+#endif
+}
+
+
+internal bool
+win32_init_florilia_memory(Florilia_Memory *florilia_memory, u64 permanent_size)
+{
+ void *storage = VirtualAlloc(0, permanent_size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ if (!storage)
+ {
+ printf("VirtualAlloc failed\n");
+ return false;
+ }
+
+ florilia_memory->permanent_storage = storage;
+ florilia_memory->permanent_storage_size = permanent_size;
+ florilia_memory->platform.get_time = win32_get_time;
+ florilia_memory->platform.connect = win32_connect;
+ florilia_memory->platform.disconnect = win32_disconnect;
+ florilia_memory->platform.send = win32_send;
+ florilia_memory->platform.recv = win32_recv;
+ return true;
+}
+
+int WINAPI
+WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmd_line, int cmd_show)
+{
+ Win32_Window window = {};
+
+ if (!win32_init_windowing()) return 0;
+ if (!win32_create_window(&window, "Florilia", 1024, 720)) return 0;
+ if (!win32_init_networking()) return 0;
+
+ Florilia_Memory florilia_memory = {};
+ Florilia_Event events[64];
+
+ if (!win32_init_florilia_memory(&florilia_memory, Megabytes(1))) return 0;
+ florilia_init(&florilia_memory);
+
+ for (;;)
+ {
+ u32 event_count = sizeof(events) / sizeof(events[0]);
+ if (!win32_process_window_events(&window, events, &event_count))
+ {
+ break;
+ }
+
+ Florilia_Offscreen_Buffer offscreen_buffer = {};
+
+ offscreen_buffer.red_shift = 16;
+ offscreen_buffer.green_shift = 8;
+ offscreen_buffer.blue_shift = 0;
+ offscreen_buffer.width = window.offscreen_buffer.width;
+ offscreen_buffer.height = window.offscreen_buffer.height;
+ offscreen_buffer.pixels = window.offscreen_buffer.pixels;
+ Florilia_Sound_Buffer sound_buffer = {};
+
+ florilia_update(&florilia_memory, &offscreen_buffer, &sound_buffer, events, event_count);
+
+ win32_show_offscreen_buffer(&window);
+ }
+
+ return 0;
+}
diff --git a/src/graveyard/win32/win32_fscord.cpp b/src/graveyard/win32/win32_fscord.cpp new file mode 100644 index 0000000..b390e29 --- /dev/null +++ b/src/graveyard/win32/win32_fscord.cpp @@ -0,0 +1,181 @@ +#define WIN32_LEAN_AND_MEAN + +// disable annoying warnings +#pragma warning(disable: 4820) // padding in structs +#pragma warning(disable: 5045) // ??? +#define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr + +#include <common/fscord_defs.h> +#include <sys/sys.h> + +#include <windows.h> +#include <winsock2.h> +#include <malloc.h> + +#include "Win32Window.h" +#include "Win32WindowService.h" +#include "Win32Tcp.h" + +typedef struct +{ + Sys_Offscreen_Buffer sys_ob; +} Win32_Offscreen_Buffer; + +typedef struct +{ + HWND handle; + HDC dc; + Win32_Offscreen_Buffer offscreen_buffer; +} Win32_Window; + +typedef struct +{ + HWND service_window; + PIXELFORMATDESCRIPTOR pfd; +} Win32Data; + +static Win32Data g_win32_data; +static Win32WindowService g_win32_window_service; + +#include "Win32Window.cpp" +#include "Win32WindowService.cpp" +#include "Win32Tcp.cpp" + +void * +sys_allocate_memory(size_t size) +{ + LPVOID addr = VirtualAlloc(0, size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + if (!addr) + { + // GetLastError... + printf("VirtualAlloc failed\n"); + } + return addr; +} + +void +sys_free_memory(void *address, size_t size) +{ + BOOL freed = VirtualFree(address, 0, MEM_RELEASE); + if (!freed) + { + printf("VirtualFree failed\n"); + } +} + +Sys_Time +sys_get_time() +{ + // @Incomplete + Sys_Time time = {}; + return time; +} + +Sys_Window * +sys_create_window(const char *name, i32 width, i32 height) +{ + static int counter = 0; + assert(counter++ == 0); + if (!g_win32_window_service.Init()) + { + return 0; + } + + Win32Window *win32_window = g_win32_window_service.CreateWin32Window(name, width, height); + + Sys_Window *sys_window = (Sys_Window*)win32_window; + return sys_window; +} + +void +sys_destroy_window(Sys_Window *window) +{ + Win32Window *win32_window = (Win32Window*)window; + g_win32_window_service.DestroyWin32Window(win32_window); +} + +i32 +sys_get_window_events(Sys_Window *sys_window, Sys_Event *events, i32 max_event_count) +{ + Win32Window *win32_window = (Win32Window*)sys_window; + i32 event_count = g_win32_window_service.GetWindowEvents(win32_window, events, max_event_count); + return event_count; +} + +Sys_Offscreen_Buffer * +sys_get_offscreen_buffer(Sys_Window *sys_window) +{ + Win32Window *window = (Win32Window*)sys_window; + Sys_Offscreen_Buffer *screen = window->GetOffscreenBuffer(); + return screen; +} + +void +sys_show_offscreen_buffer(Sys_Window *sys_window) +{ + Win32Window *window = (Win32Window*)sys_window; + window->ShowOffscreenBuffer(); +} + +Sys_Sound_Device * +sys_open_sound_device() +{ + return 0; +} + +void +sys_close_sound_device(Sys_Sound_Device *device) +{ +} + +Sys_Sound_Buffer * +sys_get_sound_buffer(Sys_Sound_Device *device) +{ + static Sys_Sound_Buffer buff = {}; + return &buff; +} + +void +sys_play_sound_buffer(Sys_Sound_Device *device) +{ +} + +Sys_Tcp * +sys_connect(const char *address, u16 port) +{ + Win32Tcp *tcp = new Win32Tcp(); + if (tcp->Connect(address, port)) { + return (Sys_Tcp*)tcp; + } else { + return 0; + } +} + +void +sys_disconnect(Sys_Tcp *sys_tcp) +{ + Win32Tcp *win32_tcp = (Win32Tcp*)sys_tcp; + delete win32_tcp; +} + +bool +sys_send(Sys_Tcp *sys_tcp, void *buffer, i64 size) +{ + assert(size <= S32_MAX); + + Win32Tcp *win32_tcp = (Win32Tcp*)sys_tcp; + bool sent = win32_tcp->Send(buffer, (i32)size); + return sent; +} + +i64 +sys_recv(Sys_Tcp *sys_tcp, void *buffer, i64 size) +{ + assert(size <= S32_MAX); + + Win32Tcp *win32_tcp = (Win32Tcp*)sys_tcp; + int recvd = win32_tcp->Recv(buffer, (i32)size); + return recvd; +} + + diff --git a/src/graveyard/win32/win32_net.c b/src/graveyard/win32/win32_net.c new file mode 100644 index 0000000..84a9373 --- /dev/null +++ b/src/graveyard/win32/win32_net.c @@ -0,0 +1,79 @@ +DEBUG_PLATFORM_CONNECT(win32_connect)
+{
+ SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock == INVALID_SOCKET)
+ {
+ int error = WSAGetLastError();
+ printf("socket() failed, error = %d\n", error);
+ return -1;
+ }
+ printf("socket() success\n");
+
+ struct sockaddr_in server_addr;
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+ server_addr.sin_addr.s_addr = inet_addr(address);
+
+ int connected = connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
+ if (connected != 0)
+ {
+ int error = WSAGetLastError();
+ printf("connect() failed, error = %d\n", error);
+ closesocket(sock);
+ return -1;
+ }
+ printf("connect(...) success\n");
+
+ u_long mode = 1;
+ int result = ioctlsocket(sock, FIONBIO, &mode);
+ if (result != NO_ERROR)
+ {
+ int error = WSAGetLastError();
+ printf("ioctlsocket failed, error = %d\n", error);
+ closesocket(sock);
+ return -1;
+ }
+ printf("fcntl() success\n");
+
+ return sock;
+}
+
+DEBUG_PLATFORM_DISCONNECT(win32_disconnect)
+{
+ closesocket(netid);
+}
+
+internal
+DEBUG_PLATFORM_SEND(win32_send)
+{
+ printf("sending...\n");
+ int sent = send(netid, (const char*)buffer, size, 0);
+ printf("sent %d/%u bytes\n", sent, size);
+ return sent;
+}
+
+internal
+DEBUG_PLATFORM_RECV(win32_recv)
+{
+ printf("receving...\n");
+ int recvd = recv(netid, (char*)buffer, size, 0);
+ printf("recvd %d bytes\n", recvd);
+ if (recvd == SOCKET_ERROR)
+ {
+ return -1;
+ }
+ return recvd;
+}
+
+internal b32
+win32_init_networking()
+{
+ static WSADATA wsaData;
+ int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (iResult != 0) {
+ wprintf(L"WSAStartup failed: %d\n", iResult);
+ return false;
+ }
+ printf("WSAStartup done\n");
+ return true;
+}
diff --git a/src/graveyard/win32/win32_network_stream.cpp b/src/graveyard/win32/win32_network_stream.cpp new file mode 100644 index 0000000..11a180e --- /dev/null +++ b/src/graveyard/win32/win32_network_stream.cpp @@ -0,0 +1,90 @@ +#include <platform/platform.h> +#include <windows.h> +#include <stdlib.h> + +static b32 g_wsa_started; + +struct PlatformNetworkStream { + SOCKET socket; +}; + +PlatformNetworkStream *platform_network_stream_open_connection() { + PlatformNetworkStream *stream = (PlatformNetworkStream*)malloc(sizeof(*stream)); + int err; + + // start wsa + if (!g_wsa_started) { + WSADATA wsa_data; + WORD wsa_version = MAKEWORD(2, 2); + err = WSAStartup(wsa_version, &wsa_data); + if (err) { + printf("WSAStartup error %d\n", err); + return false; + } + g_wsa_started = true; + } + + // open socket + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + printf("socket() wsa error: %d\n", WSAGetLastError()); + return false; + } + + // connect + struct sockaddr_in sa = {}; + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + sa.sin_addr.s_addr = inet_addr(address); + + err = connect(sock, (SOCKADDR*)&sa, sizeof(sa)); + if (err) { + printf("connect() wsa error: %d\n", WSAGetLastError()); + closesocket(sock); + return false; + } + + // make socket non-blocking + u_long io_mode = 1; + err = ioctlsocket(sock, FIONBIO, &io_mode); + if (err) { + printf("ioctlsocket() wsa error: %d\n", WSAGetLastError()); + closesocket(sock); + return false; + } + + m_Socket = sock; + return true; +} + +void platform_network_stream_close(PlatformNetworkStream *stream) { + int err = closesocket(m_Socket); + if (err) { + printf("closesocket() wsa error: %d\n", WSAGetLastError()); + } +} + +bool platform_network_stream_send(PlatformNetworkStream *stream, void *buff, i32 size) { + int sent = send(m_Socket, (const char*)buff, size, 0); + if (sent == SOCKET_ERROR) { + int error_code = WSAGetLastError(); + printf("send() wsa error = %d\n", error_code); + return false; + } + return true; +} + +i64 platform_network_stream_recv(PlatformNetworkStream *stream, void *buff, i64 size) { + int recvd = recv(m_Socket, (char*)buff, size, 0); + if (recvd == SOCKET_ERROR) { + int error_code = WSAGetLastError(); + if (error_code == WSAEWOULDBLOCK) { + return 0; + } else { + printf("recv() wsa error: %d\n", error_code); + return -1; + } + } + return recvd; +} + diff --git a/src/graveyard/win32/win32_window.c b/src/graveyard/win32/win32_window.c new file mode 100644 index 0000000..8a25fed --- /dev/null +++ b/src/graveyard/win32/win32_window.c @@ -0,0 +1,389 @@ +#define WIN32_SERVICE_WINDOW_CREATED (WM_USER + 0)
+#define WIN32_SERVICE_WINDOW_NOT_CREATED (WM_USER + 1)
+#define WIN32_CREATE_WINDOW (WM_USER + 2)
+#define WIN32_DESTROY_WINDOW (WM_USER + 3)
+
+static HWND g_service_window;
+static DWORD g_main_thread_id;
+
+internal void
+init_pfd(PIXELFORMATDESCRIPTOR *pfd)
+{
+ memset(pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
+ pfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd->nVersion = 1;
+ pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
+ pfd->iPixelType = PFD_TYPE_RGBA;
+ pfd->cColorBits = 32;
+ pfd->cDepthBits = 24;
+ pfd->cStencilBits = 8;
+ pfd->iLayerType = PFD_MAIN_PLANE;
+}
+
+internal LRESULT
+window_proc(HWND window, UINT message, WPARAM w_param, LPARAM l_param)
+{
+ LRESULT result = 0;
+ switch (message)
+ {
+ case WM_CLOSE:
+ {
+ PostThreadMessage(g_main_thread_id, message, (WPARAM)window, l_param);
+ }
+ break;
+
+ case WM_CHAR:
+ case WM_KEYDOWN:
+ case WM_KEYUP:
+ case WM_QUIT:
+ case WM_SIZE:
+ {
+ PostThreadMessage(g_main_thread_id, message, w_param, l_param);
+ }
+ break;
+
+ default:
+ {
+ result = DefWindowProcA(window, message, w_param, l_param);
+ }
+ break;
+ }
+
+ return result;
+}
+
+internal HWND
+create_window(const char *name, int width, int height)
+{
+ const char *classname = "win32_window_class";
+
+ WNDCLASSEX window_class = {};
+ window_class.style = CS_OWNDC;
+ window_class.cbSize = sizeof(window_class);
+ window_class.lpfnWndProc = &window_proc;
+ window_class.hInstance = GetModuleHandle(NULL);
+ window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ window_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ window_class.lpszClassName = classname;
+ if (RegisterClassExA(&window_class) == 0)
+ {
+ printf("RegisterClassEx() failed\n");
+ return 0;
+ }
+
+ HWND window = CreateWindowExA(0,
+ classname,
+ name,
+ WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ width,
+ height,
+ 0,
+ 0,
+ window_class.hInstance,
+ 0);
+ if (!window)
+ {
+ printf("CreateWindowEx() failed\n");
+ return 0;
+ }
+ return window;
+}
+
+LRESULT
+win32_service_window_proc(HWND window, UINT message, WPARAM w_param, LPARAM l_param)
+{
+ LRESULT result = 0;
+ switch (message)
+ {
+ case WIN32_CREATE_WINDOW:
+ {
+ Win32_Window_Settings *settings = (Win32_Window_Settings*)w_param;
+ return (LRESULT)create_window(settings->name, settings->width, settings->height);
+ }
+ break;
+
+ case WIN32_DESTROY_WINDOW:
+ {
+ DestroyWindow(window);
+ }
+ break;
+
+ default:
+ {
+ result = DefWindowProc(window, message, w_param, l_param);
+ }
+ break;
+ }
+ return result;
+}
+
+internal bool
+create_service_window()
+{
+ WNDCLASSEX service_window_class = {};
+ service_window_class.style = CS_OWNDC;
+ service_window_class.cbSize = sizeof(service_window_class);
+ service_window_class.lpfnWndProc = &win32_service_window_proc;
+ service_window_class.hInstance = GetModuleHandle(NULL);
+ service_window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ service_window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ service_window_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ service_window_class.lpszClassName = "win32_service_window_class";
+ if (RegisterClassEx(&service_window_class) == 0)
+ {
+ printf("RegisterClassEx() failed\n");
+ return 0;
+ }
+
+ const char *service_window_name = "win32_service_window";
+ HWND service_window = CreateWindowEx(0,
+ service_window_class.lpszClassName,
+ service_window_name,
+ 0,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ 0,
+ 0,
+ service_window_class.hInstance,
+ 0);
+ if (!service_window)
+ {
+ printf("CreateWindowEx() failed\n");
+ return 0;
+ }
+
+ HDC dc = GetDC(service_window);
+ if (!dc)
+ {
+ printf("GetDC() failed\n");
+ return false;
+ }
+
+ PIXELFORMATDESCRIPTOR pfd;
+ init_pfd(&pfd);
+
+ int pixel_format = ChoosePixelFormat(dc, &pfd);
+ if (pixel_format == 0)
+ {
+ printf("ChoosePixelFormat failed\n");
+ return false;
+ }
+
+ BOOL pixel_format_set = SetPixelFormat(dc, pixel_format, &pfd);
+ if (pixel_format_set == FALSE)
+ {
+ printf("SetPixelFormat() failed\n");
+ return false;
+ }
+
+ g_service_window = service_window;
+ return true;
+}
+
+DWORD WINAPI win32_service_window_thread(LPVOID lpParameter)
+{
+ if (!create_service_window())
+ {
+ PostThreadMessage(g_main_thread_id, WIN32_SERVICE_WINDOW_NOT_CREATED, 0, 0);
+ return 0;
+ }
+
+ PostThreadMessage(g_main_thread_id, WIN32_SERVICE_WINDOW_CREATED, 0, 0);
+
+ for (;;)
+ {
+ // receive messages for all windows (created by this thread)
+ MSG message;
+ BOOL recvd = GetMessageA(&message, 0, 0, 0);
+ if (recvd == -1)
+ {
+ // handle error
+ printf("GetMessage failed\n");
+ return 0;
+ }
+
+ TranslateMessage(&message);
+ DispatchMessage(&message);
+ }
+}
+
+internal void
+win32_show_offscreen_buffer(Win32_Window *window)
+{
+ Win32_Offscreen_Buffer *buff = &window->offscreen_buffer;
+ StretchDIBits(window->dc,
+ 0, 0, buff->width, buff->height,
+ 0, 0, buff->width, buff->height,
+ buff->pixels,
+ &buff->bitmap_info,
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ SwapBuffers(window->dc);
+}
+
+internal b32
+win32_recreate_offscreen_buffer(Win32_Offscreen_Buffer *buff, i32 width, i32 height)
+{
+ i32 bytes_per_pixel = 4;
+ i32 pixels_size = width * height * bytes_per_pixel;
+
+ u32 *pixels = realloc(buff->pixels, pixels_size);
+
+ BITMAPINFO *bitmap_info = &buff->bitmap_info;
+ memset(bitmap_info->bmiColors, 0, sizeof(bitmap_info->bmiColors));
+ bitmap_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmap_info->bmiHeader.biWidth = width;
+ bitmap_info->bmiHeader.biHeight = height;
+ bitmap_info->bmiHeader.biPlanes = 1;
+ bitmap_info->bmiHeader.biBitCount = 32;
+ bitmap_info->bmiHeader.biCompression = BI_RGB;
+ bitmap_info->bmiHeader.biSizeImage = 0;
+ bitmap_info->bmiHeader.biXPelsPerMeter = 0;
+ bitmap_info->bmiHeader.biYPelsPerMeter = 0;
+ bitmap_info->bmiHeader.biClrUsed = 0;
+ bitmap_info->bmiHeader.biClrImportant = 0;
+
+ buff->width = width;
+ buff->height = height;
+ buff->pixels = pixels;
+ return true;
+}
+
+#define ADD_KEY_EVENT(_c) \
+ event->type = FLORILIA_EVENT_KEY; \
+ event->key.c = _c; \
+ *event_count += 1;
+
+internal bool
+win32_process_window_events(Win32_Window *window, Florilia_Event *events, u32 *event_count)
+{
+ u32 event_count_max = *event_count;
+ *event_count = 0;
+
+ MSG message;
+ while (*event_count < event_count_max && PeekMessage(&message, 0, 0, 0, PM_REMOVE))
+ {
+ Florilia_Event *event = events + *event_count;
+
+ switch (message.message)
+ {
+ case WM_SIZE:
+ {
+ UINT width = LOWORD(message.lParam);
+ UINT height = HIWORD(message.lParam);
+ win32_recreate_offscreen_buffer(&window->offscreen_buffer, width, height);
+ }
+ break;
+
+ case WM_CHAR:
+ {
+ if (message.wParam < 0 || message.wParam > 127)
+ break;
+
+ char c = (char)message.wParam;
+ ADD_KEY_EVENT(c);
+ }
+ break;
+
+ case WM_KEYDOWN:
+ {
+ switch (message.wParam)
+ {
+ case VK_LEFT: { ADD_KEY_EVENT(FLORILIA_KEY_LEFT); } break;
+ case VK_RIGHT: { ADD_KEY_EVENT(FLORILIA_KEY_RIGHT); } break;
+ case VK_UP: { ADD_KEY_EVENT(FLORILIA_KEY_UP); } break;
+ case VK_DOWN: { ADD_KEY_EVENT(FLORILIA_KEY_DOWN); } break;
+ case VK_DELETE: { ADD_KEY_EVENT(127 /* in ascii */); } break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ case WM_DESTROY:
+ {
+ return false;
+ }
+ break;
+
+ default:
+ {
+ return true;
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+#undef ADD_KEY_EVENT
+
+internal bool
+win32_create_window(Win32_Window *window, const char *name, int width, int height)
+{
+ // SendMessage returns after the request has been processed
+ Win32_Window_Settings settings = {name, width, height};
+ HWND handle = (HWND)SendMessage(g_service_window, WIN32_CREATE_WINDOW, (WPARAM)&settings, 0);
+ if (!handle)
+ return 0;
+
+ // We are back in our thread
+ HDC dc = GetDC(handle);
+ if (!dc)
+ {
+ printf("GetDC failed\n");
+ return 0;
+ }
+
+ PIXELFORMATDESCRIPTOR pfd;
+ init_pfd(&pfd);
+
+ int pixel_format = ChoosePixelFormat(dc, &pfd);
+ if (pixel_format == 0)
+ {
+ printf("ChoosePixelFormat failed\n");
+ return false;
+ }
+
+ BOOL pixel_format_set = SetPixelFormat(dc, pixel_format, &pfd);
+ if (pixel_format_set == FALSE)
+ {
+ printf("SetPixelFormat() failed\n");
+ return false;
+ }
+
+ window->window = handle;
+ window->dc = dc;
+ return window;
+}
+
+internal bool
+win32_init_windowing()
+{
+ g_main_thread_id = GetCurrentThreadId();
+
+ DWORD tid;
+ HANDLE thread = CreateThread(0, 0, win32_service_window_thread, 0, 0, &tid);
+ if (!thread)
+ {
+ printf("error: CreateThread(...) failed\n");
+ return false;
+ }
+
+ // wait until service window is ready
+ for (;;)
+ {
+ MSG message;
+ GetMessageA(&message, 0, 0, 0);
+
+ if (message.message == WIN32_SERVICE_WINDOW_CREATED)
+ return true;
+ else
+ return false;
+ }
+}
diff --git a/src/graveyard/win32/win32_window.cpp b/src/graveyard/win32/win32_window.cpp new file mode 100644 index 0000000..6ec0891 --- /dev/null +++ b/src/graveyard/win32/win32_window.cpp @@ -0,0 +1,77 @@ +#include <platform/platform.h> +#include <windows.h> + +struct Win32OffscreenBuffer { + PlatformOffscreenBuffer platform_offscreen_buffer; + BITMAPINFO bitmap_info; +}; + +struct PlatformWindow { + HWND wnd; + HDC dc; + Win32OffscreenBuffer offscreen_buffer; +}; + +Win32Window::Win32Window(HWND handle, HDC dc) +{ + m_Wnd = handle; + m_Dc = dc; + memset((void*)&m_OffscreenBuffer, 0, sizeof(m_OffscreenBuffer)); +} + +bool +Win32Window::RecreateOffscreenBuffer(i32 width, i32 height) +{ + Sys_Offscreen_Buffer *sys_screen = &m_OffscreenBuffer.sys_offscreen_buffer; + + sys_screen->red_shift = 16; + sys_screen->green_shift = 8; + sys_screen->blue_shift = 0; + sys_screen->alpha_shift = 24; + + u32 *new_pixels = (u32*)malloc(sizeof(sys_screen->pixels[0]) * width * height); + if (!new_pixels) + { + return false; + } + free(sys_screen->pixels); + + sys_screen->width = width; + sys_screen->height = height; + sys_screen->pixels = new_pixels; + + + BITMAPINFO *bmi = &m_OffscreenBuffer.bitmap_info; + memset(bmi, 0, sizeof(*bmi)); + bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader); + bmi->bmiHeader.biWidth = width; + bmi->bmiHeader.biHeight = height; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biBitCount = 32; + bmi->bmiHeader.biCompression = BI_RGB; + + return true; +} + +Sys_Offscreen_Buffer * +Win32Window::GetOffscreenBuffer() +{ + Sys_Offscreen_Buffer *screen = &m_OffscreenBuffer.sys_offscreen_buffer; + return screen; +} + +void +Win32Window::ShowOffscreenBuffer() +{ + i32 width = m_OffscreenBuffer.sys_offscreen_buffer.width; + i32 height = m_OffscreenBuffer.sys_offscreen_buffer.height; + u32 *pixels = m_OffscreenBuffer.sys_offscreen_buffer.pixels; + BITMAPINFO *bmi = &m_OffscreenBuffer.bitmap_info; + + StretchDIBits(m_Dc, + 0, 0, width, height, + 0, 0, width, height, + pixels, bmi, DIB_RGB_COLORS, SRCCOPY); + +} + |