#define DOOM_IMPLEMENTATION #include "PureDOOM.h" #if defined(__clang__) #define IMPORT(name) __attribute__((import_module("env"), import_name(name))) #else #define IMPORT(name) #endif extern int host_open(const char *filename, const char *mode) IMPORT("host_open"); extern void host_close(int handle) IMPORT("host_close"); extern int host_read(int handle, void *buf, int count) IMPORT("host_read"); extern int host_write(int handle, const void *buf, int count) IMPORT("host_write"); extern int host_seek(int handle, int offset, int origin) IMPORT("host_seek"); extern int host_tell(int handle) IMPORT("host_tell"); extern int host_eof(int handle) IMPORT("host_eof"); extern void host_gettime(int *sec, int *usec) IMPORT("host_gettime"); extern void host_exit(int code) IMPORT("host_exit"); extern void host_print(const char *text) IMPORT("host_print"); extern unsigned char __heap_base; static char g_wad_path[1024]; static char g_home_dir[] = "."; static char g_program_name[] = "puredoom"; static char g_iwad_flag[] = "-iwad"; static char *g_argv[] = {g_program_name, g_iwad_flag, g_wad_path, 0}; static unsigned int g_heap_ptr; static unsigned int align_up(unsigned int value, unsigned int alignment) { return (value + alignment - 1u) & ~(alignment - 1u); } unsigned int strlen(const char *str) { unsigned int len = 0; while (str[len] != '\0') ++len; return len; } static int str_eq(const char *left, const char *right) { unsigned int i = 0; for (;;) { if (left[i] != right[i]) return 0; if (left[i] == '\0') return 1; ++i; } } static void *guest_malloc(int size) { unsigned int alloc_size; unsigned int end; unsigned int capacity; unsigned int extra_pages; void *result; if (size <= 0) return 0; if (g_heap_ptr == 0) g_heap_ptr = align_up((unsigned int)(unsigned long)&__heap_base, 16u); alloc_size = align_up((unsigned int)size, 16u); end = g_heap_ptr + alloc_size; capacity = __builtin_wasm_memory_size(0) * 65536u; if (end > capacity) { extra_pages = (end - capacity + 65535u) / 65536u; if (__builtin_wasm_memory_grow(0, extra_pages) == (unsigned int)-1) return 0; } result = (void *)(unsigned long)g_heap_ptr; g_heap_ptr = end; return result; } static void guest_free(void *ptr) { (void)ptr; } static void *guest_open(const char *filename, const char *mode) { int handle = host_open(filename, mode); if (handle < 0) return 0; return (void *)(unsigned long)(handle + 1); } static int guest_handle(void *handle) { return (int)(unsigned long)handle - 1; } static void guest_close(void *handle) { host_close(guest_handle(handle)); } static int guest_read(void *handle, void *buf, int count) { return host_read(guest_handle(handle), buf, count); } static int guest_write(void *handle, const void *buf, int count) { return host_write(guest_handle(handle), buf, count); } static int guest_seek(void *handle, int offset, doom_seek_t origin) { return host_seek(guest_handle(handle), offset, (int)origin); } static int guest_tell(void *handle) { return host_tell(guest_handle(handle)); } static int guest_eof(void *handle) { return host_eof(guest_handle(handle)); } static void guest_gettime(int *sec, int *usec) { host_gettime(sec, usec); } static void guest_exit(int code) { host_exit(code); } static char *guest_getenv(const char *var) { if (str_eq(var, "HOME")) return g_home_dir; return 0; } unsigned int tinywasm_doom_wad_path_buf(void) { return (unsigned int)(unsigned long)g_wad_path; } void tinywasm_doom_init(void) { doom_set_print(host_print); doom_set_malloc(guest_malloc, guest_free); doom_set_file_io(guest_open, guest_close, guest_read, guest_write, guest_seek, guest_tell, guest_eof); doom_set_gettime(guest_gettime); doom_set_exit(guest_exit); doom_set_getenv(guest_getenv); doom_set_default_int("key_up", DOOM_KEY_W); doom_set_default_int("key_down", DOOM_KEY_S); doom_set_default_int("key_strafeleft", DOOM_KEY_A); doom_set_default_int("key_straferight", DOOM_KEY_D); doom_set_default_int("key_use", DOOM_KEY_E); doom_set_resolution(320, 200); doom_init(3, g_argv, DOOM_FLAG_HIDE_MOUSE_OPTIONS | DOOM_FLAG_HIDE_SOUND_OPTIONS | DOOM_FLAG_HIDE_MUSIC_OPTIONS); } void tinywasm_doom_update(void) { doom_update(); } unsigned int tinywasm_doom_framebuffer(void) { return (unsigned int)(unsigned long)doom_get_framebuffer(4); } unsigned int tinywasm_doom_sound_buffer(void) { return (unsigned int)(unsigned long)doom_get_sound_buffer(); } unsigned long tinywasm_doom_tick_midi(void) { return doom_tick_midi(); } void tinywasm_doom_key_down(int key) { doom_key_down((doom_key_t)key); } void tinywasm_doom_key_up(int key) { doom_key_up((doom_key_t)key); }