diff options
Diffstat (limited to 'microshooter')
| -rwxr-xr-x | microshooter/build.sh | 3 | ||||
| -rw-r--r-- | microshooter/microshooter.c | 603 |
2 files changed, 0 insertions, 606 deletions
diff --git a/microshooter/build.sh b/microshooter/build.sh deleted file mode 100755 index 172c395..0000000 --- a/microshooter/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cc -o microshooter_client -O0 -g -fsanitize=address -Wall -Wextra -Wpedantic ./microshooter.c $(pkg-config --cflags --libs sdl3) -DCLIENT -cc -o microshooter_server -O0 -g -fsanitize=address -Wall -Wextra -Wpedantic ./microshooter.c $(pkg-config --cflags --libs sdl3) -DSERVER diff --git a/microshooter/microshooter.c b/microshooter/microshooter.c deleted file mode 100644 index f8ec059..0000000 --- a/microshooter/microshooter.c +++ /dev/null @@ -1,603 +0,0 @@ -#if !defined(CLIENT) && !defined(SERVER) -# error Either CLIENT or SERVER must be defined -#endif - -// ================================================================================ -// Core headers -// ================================================================================ - -#include <stdarg.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -// ================================================================================ -// Core helpers -// ================================================================================ - -#define COUNTOF(_X) (sizeof(_X) / sizeof((_X)[0])) -#define UNUSED(_X) ((void)sizeof(_X)) - -#ifdef __GNUC__ -# define NORETURN __attribute__((noreturn)) -# define PRINTF_FORMAT(_X, _Y) __attribute__((format(printf, _X, _Y))) -#endif - -// ================================================================================ -// Game -> OS API -// ================================================================================ - -NORETURN -void OS_SpewError(const char *message); - -void OS_SpewInfo(const char *message); - -// ================================================================================ -// OS -> Client API -// ================================================================================ - -typedef void(*GLProcInner)(void); -typedef GLProcInner(*GLProc)(const char *); - -typedef struct CL_InitParams CL_InitParams; -struct CL_InitParams -{ - GLProc glproc; -}; - -void CL_Init(const CL_InitParams *params); - -void CL_Render(int vp_width, int vp_height); - -// ================================================================================ -// OS -> Server API -// ================================================================================ - -typedef struct SV_InitParams SV_InitParams; -struct SV_InitParams -{ - const char *hostname; -}; - -void SV_Init(const SV_InitParams *params); - -// ================================================================================ -// Shared utility code -// ================================================================================ - -#define HEAP_FMT(_STR, _FMT) \ - do { \ - va_list va; va_start(va, _FMT); \ - int len = vsnprintf(0, 0, _FMT, va) + 1; \ - va_end(va); \ - _STR = calloc(len, 1); \ - va_start(va, _FMT); \ - vsnprintf(_STR, len, _FMT, va); \ - va_end(va); \ - } while (0); - -NORETURN PRINTF_FORMAT(1, 2) -void Error(const char *fmt, ...) -{ - char *str = 0; - HEAP_FMT(str, fmt); - OS_SpewError(str); -} - -PRINTF_FORMAT(1, 2) -void Info(const char *fmt, ...) -{ - char *str = 0; - HEAP_FMT(str, fmt); - OS_SpewInfo(str); - free(str); -} - -#undef HEAP_FMT - -// ================================================================================ -// Math -// ================================================================================ - -typedef struct Mat4 Mat4; -struct Mat4 -{ - float m[4 * 4]; -}; -#define MAT4(...) (Mat4){ .m = { __VA_ARGS__ }, } - -#if 0 -static inline Mat4 Mat4_Ident(void) -{ - return MAT4( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - ); -} -#endif - -static inline Mat4 Mat4_Ortho(float l, float r, float t, float b, float n, float f) -{ - // ref: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/orthographic-projection-matrix.html - return MAT4( - 2.0f / (r - l), 0.0f, 0.0f, 0.0f, - 0.0f, 2.0f / (t - b), 0.0f, 0.0f, - 0.0f, 0.0f, -2.0f / (f - n), 0.0f, - -((r + l) / (r - l)), -((t + b) / (t - b)), -((f + n) / (f - n)), 1.0f, - ); -} - -// ================================================================================ -// OpenGL -// ================================================================================ - -// ref: https://registry.khronos.org/OpenGL/api/GL/glcorearb.h - -#define GL_ARRAY_BUFFER 0x8892 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_COMPILE_STATUS 0x8B81 -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_FALSE 0 -#define GL_FLOAT 0x1406 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_OPERATION 0x0502 -#define GL_INVALID_VALUE 0x0501 -#define GL_LINK_STATUS 0x8B82 -#define GL_NO_ERROR 0 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_RENDERER 0x1F01 -#define GL_STATIC_DRAW 0x88E4 -#define GL_STREAM_DRAW 0x88E0 -#define GL_TRIANGLES 0x0004 -#define GL_TRUE 1 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_VENDOR 0x1F00 -#define GL_VERTEX_SHADER 0x8B31 - -typedef unsigned int GLenum; -typedef float GLfloat; -typedef int GLint; -typedef int GLsizei; -typedef unsigned int GLbitfield; -typedef unsigned int GLuint; -typedef unsigned char GLboolean; -typedef uint8_t GLubyte; -typedef size_t GLsizeiptr; -typedef intptr_t GLintptr; - -#define GLFUNCS \ - X(glAttachShader, void, GLuint, GLuint) \ - X(glBindBuffer, void, GLenum, GLuint) \ - X(glBindVertexArray, void, GLuint) \ - X(glBufferData, void, GLenum, GLsizeiptr, const void *, GLenum) \ - X(glBufferSubData, void, GLenum, GLintptr, GLsizeiptr, const void *) \ - X(glClear, void, GLbitfield) \ - X(glClearColor, void, GLfloat, GLfloat, GLfloat, GLfloat) \ - X(glCompileShader, void, GLuint) \ - X(glCreateProgram, GLuint, void) \ - X(glCreateShader, GLuint, GLenum) \ - X(glDrawElements, void, GLenum, GLsizei, GLenum, const void *) \ - X(glEnableVertexAttribArray, void, GLuint) \ - X(glGenBuffers, void, GLsizei, GLuint *) \ - X(glGenVertexArrays, void, GLsizei, GLuint *) \ - X(glGetError, GLenum, void) \ - X(glGetProgramInfoLog, void, GLuint, GLsizei, GLsizei *, char *) \ - X(glGetProgramiv, void, GLuint, GLenum, GLint *) \ - X(glGetShaderInfoLog, void, GLuint, GLsizei, GLsizei *, char *) \ - X(glGetShaderiv, void, GLuint, GLenum, GLint *) \ - X(glGetString, const GLubyte *, GLenum) \ - X(glGetUniformLocation, GLint, GLuint, const char *) \ - X(glLinkProgram, void, GLuint) \ - X(glShaderSource, void, GLuint, GLsizei, const char *const *, const GLint *) \ - X(glUniformMatrix4fv, void, GLint, GLsizei, GLboolean, const GLfloat *) \ - X(glUseProgram, void, GLuint) \ - X(glVertexAttribPointer, void, GLuint, GLint, GLenum, GLboolean, GLsizei, const void *) \ - X(glViewport, void, GLint, GLint, GLsizei, GLsizei) - -#define X(_NAME, _RET, ...) static _RET (*_NAME)(__VA_ARGS__) = 0; -GLFUNCS -#undef X - -void LoadOpenGLFunctions(GLProc glproc) -{ - #define X(_NAME, _RET, ...) \ - _NAME = (_RET(*)(__VA_ARGS__))glproc(#_NAME); \ - if (!_NAME) {Error("Failed to load OpenGL function %s", #_NAME); } - GLFUNCS - #undef X -} - -#undef GLFUNCS - -void CheckGLError(unsigned int line, const char *code) -{ - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - { - const char *error_str = "unknown error"; - switch (error) - { -#define BIND_ERROR(_ERR) case _ERR: error_str = #_ERR; break; - BIND_ERROR(GL_INVALID_ENUM); - BIND_ERROR(GL_INVALID_VALUE); - BIND_ERROR(GL_INVALID_OPERATION); - BIND_ERROR(GL_OUT_OF_MEMORY); -#undef BIND_ERROR - }; - Error("%s:%d: %s generated %s", __FILE__, line, code, error_str); - } -} - -#define GL(_CODE) _CODE; CheckGLError(__LINE__, #_CODE) - -// ================================================================================ -// Batched quad renderer -// ================================================================================ - -#define MAX_QUADS 256 - -typedef struct R_Quad R_Quad; -struct R_Quad -{ - float p[2]; - float t[2]; -}; - -typedef struct R_QuadRenderer R_QuadRenderer; -struct R_QuadRenderer -{ - GLuint vao; - GLuint vbo; - GLuint ibo; - - GLuint shader; - - R_Quad vbuf[MAX_QUADS * 4]; - size_t head; -}; - -void R_InitQuads(R_QuadRenderer *qr, GLuint shader) -{ - qr->shader = shader; - - GL(glGenVertexArrays(1, &qr->vao)); - GL(glBindVertexArray(qr->vao)); - - GL(glGenBuffers(1, &qr->vbo)); - GL(glBindBuffer(GL_ARRAY_BUFFER, qr->vbo)); - GL(glBufferData(GL_ARRAY_BUFFER, sizeof(qr->vbuf), qr->vbuf, GL_STREAM_DRAW)); - - uint16_t ibuf[MAX_QUADS * 6]; - for (int i = 0; i < MAX_QUADS; ++i) - { - ibuf[6*i+0] = 4*i+0; - ibuf[6*i+1] = 4*i+1; - ibuf[6*i+2] = 4*i+2; - ibuf[6*i+3] = 4*i+0; - ibuf[6*i+4] = 4*i+2; - ibuf[6*i+5] = 4*i+3; - } - - GL(glGenBuffers(1, &qr->ibo)); - GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, qr->ibo)); - GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ibuf), ibuf, GL_STATIC_DRAW)); - - GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(R_Quad), (const void *)offsetof(R_Quad, p))); - GL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(R_Quad), (const void *)offsetof(R_Quad, t))); - GL(glEnableVertexAttribArray(0)); - GL(glEnableVertexAttribArray(1)); -} - -void R_FlushQuads(R_QuadRenderer *qr) -{ - if (qr->head > 0) - { - GL(glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(R_Quad) * 4 * qr->head, qr->vbuf)); - GL(glDrawElements(GL_TRIANGLES, qr->head * 6, GL_UNSIGNED_SHORT, 0)); - qr->head = 0; - } -} - -void R_PushQuad(R_QuadRenderer *qr, const R_Quad *quad4) -{ - qr->vbuf[qr->head*4+0] = quad4[0]; - qr->vbuf[qr->head*4+1] = quad4[1]; - qr->vbuf[qr->head*4+2] = quad4[2]; - qr->vbuf[qr->head*4+3] = quad4[3]; - ++qr->head; - if (qr->head >= MAX_QUADS) - { - R_FlushQuads(qr); - } -} - -void R_BeginQuads(R_QuadRenderer *qr, int vp_w, int vp_h) -{ - GL(glBindVertexArray(qr->vao)); - GL(glBindBuffer(GL_ARRAY_BUFFER, qr->vbo)); - GL(glUseProgram(qr->shader)); - - Mat4 proj = Mat4_Ortho(0, vp_w, 0, vp_h, 0, 10); - GL(glUniformMatrix4fv(glGetUniformLocation(qr->shader, "u_proj"), 1, GL_FALSE, proj.m)); -} - -void R_EndQuads(R_QuadRenderer *qr) -{ - R_FlushQuads(qr); -} - -// ================================================================================ -// Client code -// ================================================================================ - -static struct -{ - R_QuadRenderer qr; - int width; - int height; -} cl = { 0 }; - -void CL_Init(const CL_InitParams *params) -{ - cl.width = -1; - cl.height = -1; - - LoadOpenGLFunctions(params->glproc); - Info("Loaded OpenGL: GL_VENDOR = %s, GL_RENDERER = %s", glGetString(GL_VENDOR), glGetString(GL_RENDERER)); - - GLuint prog_quad; - -#define GLSL(_X) "#version 330 core\n" #_X - const char* quad_vs = GLSL( - layout (location = 0) in vec2 p; - layout (location = 1) in vec2 t; - - uniform mat4 u_proj; - - void main() - { - gl_Position = u_proj * vec4(p.x, p.y, 0.0, 1.0); - } - ); - const char* quad_fs = GLSL( - out vec4 out_color; - - void main() - { - out_color = vec4(1.0, 0.0, 0.0, 1.0); - } - ); -#undef GLSL - - struct { GLuint* prog; const char *vsrc; const char *fsrc; } reg[] = - { - { .prog = &prog_quad, .vsrc = quad_vs, .fsrc = quad_fs, }, - }; - for (size_t i = 0; i < COUNTOF(reg); ++i) - { - GLuint prog = GL(glCreateProgram()); - - GLuint vs = GL(glCreateShader(GL_VERTEX_SHADER)); - GL(glShaderSource(vs, 1, ®[i].vsrc, 0)); - - GLuint fs = GL(glCreateShader(GL_FRAGMENT_SHADER)); - GL(glShaderSource(fs, 1, ®[i].fsrc, 0)); - - GLuint shaders[] = { vs, fs }; - for (size_t j = 0; j < COUNTOF(shaders); ++j) - { - GL(glCompileShader(shaders[j])); - - GLint status = GL_TRUE; - GL(glGetShaderiv(shaders[j], GL_COMPILE_STATUS, &status)); - if (status != GL_TRUE) - { - char shader_log[1024]; - GL(glGetShaderInfoLog(shaders[j], sizeof(shader_log), 0, shader_log)); - Error("Failed to compile shader: %s", shader_log); - } - - GL(glAttachShader(prog, shaders[j])); - } - - GL(glLinkProgram(prog)); - - GLint status = GL_TRUE; - GL(glGetProgramiv(prog, GL_LINK_STATUS, &status)); - if (status != GL_TRUE) - { - char shader_log[1024]; - GL(glGetProgramInfoLog(prog, sizeof(shader_log), 0, shader_log)); - Error("Failed to link shader: %s", shader_log); - } - - *reg[i].prog = prog; - } - - R_InitQuads(&cl.qr, prog_quad); -} - -void CL_Render(int vp_width, int vp_height) -{ - if (cl.width != vp_width || cl.height != vp_height) - { - cl.width = vp_width; - cl.height = vp_height; - Info("Resized to %dx%d", cl.width, cl.height); - } - - GL(glViewport(0, 0, vp_width, vp_height)); - GL(glClearColor(0.1f, 0.1f, 0.1f, 1.0f)); - GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - - R_BeginQuads(&cl.qr, cl.width, cl.height); - R_Quad rect[4] = - { - (R_Quad){ .p = { 0.0, 0.0 }, .t = { 0, 0 } }, - (R_Quad){ .p = { 100, 0.0 }, .t = { 0, 0 } }, - (R_Quad){ .p = { 100, 100 }, .t = { 0, 0 } }, - (R_Quad){ .p = { 0.0, 100 }, .t = { 0, 0 } }, - }; - R_PushQuad(&cl.qr, rect); - R_EndQuads(&cl.qr); -} - -// ================================================================================ -// Server code -// ================================================================================ - -void SV_Init(const SV_InitParams *params) -{ - Info("Starting server %s", params->hostname); -} - -// ================================================================================ -// SDL3 shared -// ================================================================================ - -#ifdef CLIENT -# define SDL_MAIN_USE_CALLBACKS -#endif -#include <SDL3/SDL.h> -#include <SDL3/SDL_main.h> - -void OS_SpewError(const char *message) -{ - printf("Error: %s\n", message); -#ifdef CLIENT - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "MicroShooter: Error!", message, 0); -#endif - exit(1); -} - -void OS_SpewInfo(const char *message) -{ - printf("%s\n", message); -} - -// ================================================================================ -// SDL3 client -// ================================================================================ - -#ifdef CLIENT - -typedef struct AppState AppState; -struct AppState -{ - SDL_Window *wnd; - SDL_GLContext glctx; -}; - -void RenderFrame(AppState *app) -{ - int vp_width = 0; - int vp_height = 0; - SDL_GetWindowSizeInPixels(app->wnd, &vp_width, &vp_height); - CL_Render(vp_width, vp_height); - SDL_GL_SwapWindow(app->wnd); -} - -SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) -{ - UNUSED(argc); - UNUSED(argv); - - *appstate = calloc(1, sizeof(AppState)); - AppState *app = *appstate; - - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) - { - Error("Failed to initialize SDL: %s", SDL_GetError()); - } - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - - app->wnd = SDL_CreateWindow("MicroShooter", 800, 600, SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); - if (!app->wnd) - { - Error("Failed to create window: %s", SDL_GetError()); - } - - app->glctx = SDL_GL_CreateContext(app->wnd); - if (!app->glctx) - { - Error("Failed to create OpenGL context: %s", SDL_GetError()); - } - - CL_InitParams init = (CL_InitParams) - { - .glproc = SDL_GL_GetProcAddress, - }; - CL_Init(&init); - - // Render one frame before showing the window - RenderFrame(app); - - SDL_ShowWindow(app->wnd); - - return SDL_APP_CONTINUE; -} - -SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) -{ - UNUSED(appstate); - - SDL_AppResult result = SDL_APP_CONTINUE; - - switch (event->type) - { - case SDL_EVENT_QUIT: - { - result = SDL_APP_SUCCESS; - break; - } - } - - return result; -} - -SDL_AppResult SDL_AppIterate(void *appstate) -{ - AppState *app = appstate; - - RenderFrame(app); - - return SDL_APP_CONTINUE; -} - -void SDL_AppQuit(void *appstate, SDL_AppResult result) -{ - UNUSED(result); - - AppState *app = appstate; - - SDL_DestroyWindow(app->wnd); - - free(app); - SDL_Quit(); -} - -#endif // CLIENT - -// ================================================================================ -// SDL3 server -// ================================================================================ - -#ifdef SERVER - -int main(int argc, char **argv) -{ - UNUSED(argc); - UNUSED(argv); - printf("<server>\n"); -} - -#endif // SERVER - |