diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 411 |
1 files changed, 0 insertions, 411 deletions
@@ -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; -} |