summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c411
1 files changed, 0 insertions, 411 deletions
diff --git a/main.c b/main.c
deleted file mode 100644
index aae22c8..0000000
--- a/main.c
+++ /dev/null
@@ -1,411 +0,0 @@
-#ifdef _WIN32
-#include <windows.h>
-#endif
-#include "gui.h"
-#if DEBUG
-typedef void (*SimFrameFn)(Frame *);
-#else
-#include "sim.c"
-#endif
-#include "time.c"
-
-#ifdef _WIN32
-#include <SDL.h>
-#else
-#include <SDL2/SDL.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-#if __unix__
-#include <dlfcn.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#elif defined _WIN32
-#else
-#error "Unsupported operating system."
-#endif
-
-#if DEBUG
-#if __unix__
-#define debug_log printf
-#else // __unix__
-static void debug_log(char const *fmt, ...) {
- char buf[256];
- va_list args;
- va_start(args, fmt);
- vsprintf_s(buf, sizeof buf, fmt, args);
- va_end(args);
- OutputDebugStringA(buf);
- OutputDebugStringA("\n");
-}
-#endif // __unix__
-#else // DEBUG
-#define debug_log(...)
-#endif
-
-static void die(char const *fmt, ...) {
- char buf[256] = {0};
-
- va_list args;
- va_start(args, fmt);
- vsnprintf(buf, sizeof buf - 1, fmt, args);
- va_end(args);
-
- // show a message box, and if that fails, print to stderr
- if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", buf, NULL) < 0) {
- fprintf(stderr, "%s\n", buf);
- }
-
- exit(EXIT_FAILURE);
-}
-
-// returns true on success
-static bool copy_file(char const *filename_from, char const *filename_to) {
- bool success = false;
- FILE *from = fopen(filename_from, "rb");
- if (from) {
- FILE *to = fopen(filename_to, "wb");
- if (to) {
- char buf[4096];
- success = true;
- while (fread(buf, 1, sizeof buf, from) == sizeof buf) {
- if (fwrite(buf, 1, sizeof buf, to) != sizeof buf) {
- success = false;
- }
- }
- fwrite(buf, 1, sizeof buf, to);
- if (ferror(from) || ferror(to)) {
- success = false;
- }
- fclose(to);
- }
- fclose(from);
- }
- return success;
-}
-
-static Key keycode_to_key(SDL_Keycode sym) {
- switch (sym) {
- case SDLK_LEFT: return KEY_LEFT;
- case SDLK_RIGHT: return KEY_RIGHT;
- case SDLK_UP: return KEY_UP;
- case SDLK_DOWN: return KEY_DOWN;
- case SDLK_SPACE: return KEY_SPACE;
- case SDLK_LCTRL: return KEY_LCTRL;
- case SDLK_RCTRL: return KEY_RCTRL;
- case SDLK_LSHIFT: return KEY_LSHIFT;
- case SDLK_RSHIFT: return KEY_RSHIFT;
- case SDLK_RETURN: return KEY_ENTER;
- case SDLK_BACKSPACE: return KEY_BACKSPACE;
- case SDLK_ESCAPE: return KEY_ESCAPE;
- case SDLK_PAGEDOWN: return KEY_PAGEDOWN;
- case SDLK_PAGEUP: return KEY_PAGEUP;
- case SDLK_EXCLAIM: return KEY_EXCLAMATION_MARK;
- case SDLK_AT: return KEY_AT;
- case SDLK_HASH: return KEY_HASH;
- case SDLK_DOLLAR: return KEY_DOLLAR;
- case SDLK_PERCENT: return KEY_PERCENT;
- case SDLK_CARET: return KEY_CARET;
- case SDLK_AMPERSAND: return KEY_AMPERSAND;
- case SDLK_ASTERISK: return KEY_ASTERISK;
- case SDLK_LEFTPAREN: return KEY_LPAREN;
- case SDLK_RIGHTPAREN: return KEY_RPAREN;
- case SDLK_KP_0: return KEY_0;
- case SDLK_PLUS: return KEY_PLUS;
- case SDLK_MINUS: return KEY_MINUS;
- case SDLK_EQUALS: return KEY_EQUALS;
- case SDLK_UNDERSCORE: return KEY_UNDERSCORE;
- default:
- if (sym >= SDLK_a && sym <= SDLK_z) {
- return (u16)(sym - SDLK_a + KEY_A);
- } else if (sym >= SDLK_0 && sym <= SDLK_9) {
- return (u16)(sym - SDLK_0 + KEY_0);
- } else if (sym >= SDLK_KP_1 && sym <= SDLK_KP_9) {
- return (u16)(sym - SDLK_KP_1 + KEY_1);
- } else if (sym >= SDLK_F1 && sym <= SDLK_F12) {
- return (u16)(sym - SDLK_F1 + KEY_F1);
- }
- }
- return KEY_UNKNOWN;
-}
-
-static SDL_Scancode key_to_scancode(Key key, bool *shift) {
- *shift = false;
- switch (key) {
- case KEY_LEFT: return SDL_SCANCODE_LEFT;
- case KEY_RIGHT: return SDL_SCANCODE_RIGHT;
- case KEY_UP: return SDL_SCANCODE_UP;
- case KEY_DOWN: return SDL_SCANCODE_DOWN;
- case KEY_SPACE: return SDL_SCANCODE_SPACE;
- case KEY_LCTRL: return SDL_SCANCODE_LCTRL;
- case KEY_RCTRL: return SDL_SCANCODE_RCTRL;
- case KEY_LSHIFT: return SDL_SCANCODE_LSHIFT;
- case KEY_RSHIFT: return SDL_SCANCODE_RSHIFT;
- case KEY_ENTER: return SDL_SCANCODE_RETURN;
- case KEY_BACKSPACE: return SDL_SCANCODE_BACKSPACE;
- case KEY_ESCAPE: return SDL_SCANCODE_ESCAPE;
- case KEY_PAGEDOWN: return SDL_SCANCODE_PAGEDOWN;
- case KEY_PAGEUP: return SDL_SCANCODE_PAGEUP;
- case KEY_MINUS: return SDL_SCANCODE_MINUS;
- case KEY_PLUS: *shift = true; return SDL_SCANCODE_MINUS;
- case KEY_EQUALS: return SDL_SCANCODE_EQUALS;
- case KEY_UNDERSCORE: *shift = true; return SDL_SCANCODE_EQUALS;
-
- case KEY_EXCLAMATION_MARK: *shift = true; return SDL_SCANCODE_1;
- case KEY_AT: *shift = true; return SDL_SCANCODE_2;
- case KEY_HASH: *shift = true; return SDL_SCANCODE_3;
- case KEY_DOLLAR: *shift = true; return SDL_SCANCODE_4;
- case KEY_PERCENT: *shift = true; return SDL_SCANCODE_5;
- case KEY_CARET: *shift = true; return SDL_SCANCODE_6;
- case KEY_AMPERSAND: *shift = true; return SDL_SCANCODE_7;
- case KEY_ASTERISK: *shift = true; return SDL_SCANCODE_8;
- case KEY_LPAREN: *shift = true; return SDL_SCANCODE_9;
- case KEY_RPAREN: *shift = true; return SDL_SCANCODE_0;
-
- case KEY_0: return SDL_SCANCODE_0; // SDL_SCANCODE_0 != SDL_SCANCODE_1 - 1
- default:
- if (key >= KEY_A && key <= KEY_Z) {
- return SDL_SCANCODE_A + (key - KEY_A);
- } else if (key >= KEY_1 && key <= KEY_9) {
- return SDL_SCANCODE_1 + (key - KEY_1);
- } else if (key >= KEY_F1 && key <= KEY_F12) {
- return SDL_SCANCODE_F1 + (key - KEY_F1);
- }
- break;
- }
- return 0;
-}
-
-#ifdef _WIN32
-int WinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nShowCmd
-) {
- (void)hInstance;
- (void)hPrevInstance;
- (void)lpCmdLine;
- (void)nShowCmd;
-#else
-int main(void) {
-#endif
- Frame frame = {0};
- Input *input = &frame.input;
-#if DEBUG
- struct timespec dynlib_last_modified = {0};
- SimFrameFn sim_frame = NULL;
- #if __unix__
- void *dynlib = NULL;
- #else
- HMODULE dynlib = NULL;
- #endif
-#endif
-
- srand((unsigned)time(NULL));
-
- SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
- die("%s", SDL_GetError());
- }
-
- SDL_Window *window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- 720, 720, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
- if (!window) {
- die("%s", SDL_GetError());
- }
-
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
- SDL_GLContext *glctx = SDL_GL_CreateContext(window);
- if (!glctx) {
- die("%s", SDL_GetError());
- }
-
- SDL_GL_SetSwapInterval(1); // vsync
-
- frame.memory_size = (size_t)16 << 20;
-
-#if DEBUG
- {
- void *address = (void *)(13ULL << 28);
- #if __unix__
- frame.memory = mmap(address, frame.memory_size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (frame.memory == MAP_FAILED) {
- frame.memory = NULL;
- }
- #else
- frame.memory = VirtualAlloc(address, frame.memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
- #endif
- }
-#else
- frame.memory = calloc(1, frame.memory_size);
-#endif
-
- if (!frame.memory) {
- die("Couldn't allocate memory (%lu bytes).", (ulong)frame.memory_size);
- }
-
- frame.get_gl_proc = (void (*(*)(char const *))(void))SDL_GL_GetProcAddress;
-
- Uint32 last_frame_ticks = SDL_GetTicks();
-
- while (1) {
- SDL_Event event;
- memset(input, 0, sizeof *input);
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- case SDL_KEYDOWN: {
- Key key = keycode_to_key(event.key.keysym.sym);
- ++input->keys_pressed[key];
- } break;
- case SDL_KEYUP: {
- Key key = keycode_to_key(event.key.keysym.sym);
- ++input->keys_released[key];
- } break;
- case SDL_QUIT:
- input->closed = true;
- break;
- }
- }
-
- frame.close = input->closed;
-
- #if DEBUG
- #if __unix__
- #define DYNLIB_EXT "so"
- #else
- #define DYNLIB_EXT "dll"
- #endif
- struct timespec new_dynlib_last_modified = time_last_modified("obj/sim." DYNLIB_EXT "_changed");
- if (timespec_cmp(dynlib_last_modified, new_dynlib_last_modified) != 0) {
- // reload dynlib
- char new_filename[256] = {0};
- snprintf(new_filename, sizeof new_filename-1, "obj/sim%08x%08x." DYNLIB_EXT, rand(), rand());
- copy_file("obj/sim." DYNLIB_EXT, new_filename);
-
- #if __unix__
- chmod(new_filename, 0755);
- void *new_dynlib = dlopen(new_filename, RTLD_NOW);
-
- if (new_dynlib) {
- SimFrameFn new_sim_frame = (SimFrameFn)dlsym(new_dynlib, "sim_frame");
- if (new_sim_frame) {
- // function loaded from dynamic library successfully
- if (dynlib) dlclose(dynlib);
- debug_log("Successfully loaded %s\n", new_filename);
- sim_frame = new_sim_frame;
- dynlib = new_dynlib;
- // delete other .so files
- {
- DIR *obj = opendir("obj");
- if (obj) {
- struct dirent *ent;
- while ((ent = readdir(obj))) {
- if (ent->d_type == DT_REG) {
- char *name = ent->d_name;
- char *ext = strrchr(name, '.');
- if (ext && strcmp(ext, ".so") == 0 && strcmp(name, "sim.so") != 0 && strcmp(name, new_filename + 4) != 0) {
- char path[256] = {0};
- snprintf(path, sizeof path - 1, "obj/%s", name);
- debug_log("Deleting old file %s.\n", path);
- unlink(path);
- }
- }
- }
- closedir(obj);
- }
- }
- } else {
- debug_log("Couldn't get sim_frame from dynamic library: %s\n", dlerror());
- }
- } else {
- debug_log("Error opening dynamic library %s: %s\n", new_filename, dlerror());
- }
-
- #else
- HMODULE new_dynlib = LoadLibraryA(new_filename);
- if (new_dynlib) {
- SimFrameFn new_sim_frame = (SimFrameFn)GetProcAddress(new_dynlib, "sim_frame");
- if (new_sim_frame) {
- // function loaded from dynamic librayr successfully
- if (dynlib) FreeLibrary(dynlib);
- debug_log("Successfully loaded %s.\n", new_filename);
- sim_frame = new_sim_frame;
- dynlib = new_dynlib;
- // delete other .dll files
- {
- WIN32_FIND_DATA find_data;
- HANDLE find = FindFirstFileA("obj\\*.dll", &find_data);
- if (find) {
- do {
- char const *filename = find_data.cFileName;
- if (strcmp(filename, "sim.dll") != 0 && strcmp(filename, "sim.dll_changed") != 0 && strcmp(filename, new_filename) != 0) {
- char path[256] = {0};
- snprintf(path, sizeof path-1, "obj/%s", filename);
- debug_log("Deleting old dll: %s\n", path);
- DeleteFileA(path);
- }
- } while (FindNextFile(find, &find_data) != 0);
- FindClose(find);
- } else {
- debug_log("Error finding dll files: %ld\n", (long)GetLastError());
- }
- }
- } else {
- FreeLibrary(new_dynlib);
- debug_log("Couldn't get sim_frame from dynamic library: %ld\n", (long)GetLastError());
- }
- } else {
- debug_log("Error opening dynamic library %s: %ld\n", new_filename, (long)GetLastError());
- }
- #endif
- dynlib_last_modified = new_dynlib_last_modified;
- }
- #endif
-
- {
- Uint8 const *kbd = SDL_GetKeyboardState(NULL);
- bool *keys_down = input->keys_down;
- bool shift = input->shift = keys_down[KEY_LSHIFT] || keys_down[KEY_RSHIFT];
- input->ctrl = keys_down[KEY_LCTRL] || keys_down[KEY_RCTRL];
- for (Key i = 0; i < NKEYS; ++i) {
- bool needs_shift;
- SDL_Scancode scan = key_to_scancode(i, &needs_shift);
- keys_down[i] = kbd[scan];
- if (needs_shift) {
- keys_down[i] &= shift;
- }
- }
- }
-
- {
- int w = 0, h = 0;
- SDL_GetWindowSize(window, &w, &h);
- frame.width = w;
- frame.height = h;
- }
-
- {
- Uint32 this_frame_ticks = SDL_GetTicks();
- Uint32 frame_ms = 0;
- if (this_frame_ticks > last_frame_ticks) // SDL_GetTicks wraps after 49 days
- frame_ms = this_frame_ticks - last_frame_ticks;
- frame.dt = 0.001 * (double)frame_ms;
- last_frame_ticks = this_frame_ticks;
- }
-
- sim_frame(&frame);
-
- SDL_SetWindowTitle(window, frame.title);
-
- if (frame.close) break;
-
- SDL_GL_SwapWindow(window);
- }
- return 0;
-}