a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

platform_wasm.c (4991B)


      1 #include <limits.h>
      2 #include <stdalign.h>
      3 #include <stdbool.h>
      4 #include <stddef.h>
      5 #include <stdint.h>
      6 
      7 #define static_assert _Static_assert
      8 
      9 // Begin terrible libc substitutions
     10 // TODO: make this libc replacement not shitty
     11 #define assert(x) (void)0
     12 
     13 int32_t printf(const char *format, ...)
     14 {
     15     // lol
     16     return 0;
     17 }
     18 
     19 // looooooooooool
     20 #define exit(status) (void)0
     21 
     22 void *memset(void *s, int32_t c, size_t n)
     23 {
     24     uint8_t *p = s;
     25     while(n > 0)
     26     {
     27         *p = (uint8_t)c;
     28         p++;
     29         n--;
     30     }
     31     return s;
     32 }
     33 
     34 // TODO: assert no overlap
     35 void *memcpy(void *dst, const void *src, size_t n)
     36 {
     37     uint8_t *destination = (uint8_t *)dst;
     38     uint8_t *source = (uint8_t *)src;
     39 
     40     while (n--)
     41     {
     42         *destination = *source;
     43         destination++;
     44         source++;
     45     }
     46 
     47     return dst;
     48 }
     49 
     50 // TODO: actually implement
     51 void *memmove(void *dst, const void *src, size_t n)
     52 {
     53     return memcpy(dst, src, n);
     54 }
     55 
     56 static_assert(__has_builtin(__builtin_sqrtf), "No builtin sqrtf builtin");
     57 #define sqrtf(x) __builtin_sqrtf((x))
     58 
     59 float js_cosf(float);
     60 float js_fabsf(float);
     61 float js_powf(float, float);
     62 float js_sinf(float);
     63 float js_tanf(float);
     64 float js_cosf(float);
     65 
     66 float cosf(float x) {
     67     return js_cosf(x);
     68 }
     69 
     70 float fabsf(float x) {
     71     return js_fabsf(x);
     72 }
     73 
     74 float powf(float x, float y) {
     75     return js_powf(x, y);
     76 }
     77 
     78 float sinf(float x) {
     79     return js_sinf(x);
     80 }
     81 
     82 float tanf(float x) {
     83     return js_tanf(x);
     84 }
     85 // End terrible libc substitutions
     86 
     87 #include "platform_info.h"
     88 
     89 #include "game.c"
     90 #include "platform.h"
     91 #include "platform_wasm.h"
     92 
     93 // wasm-ld memory layout:
     94 //      a       b
     95 // data | stack | heap
     96 // a = __data_end
     97 // b = __heap_base
     98 extern u8 __heap_base;
     99 extern u8 __data_end;
    100 
    101 // There's no standardized, nondeprecated way to get a numeric ID of a keyboard
    102 // key, so I guess we have to do that ourselves.
    103 enum WasmKey {
    104     WASM_KEY_LEFT,
    105     WASM_KEY_RIGHT,
    106     WASM_KEY_UP,
    107     WASM_KEY_DOWN,
    108     WASM_KEY_S,
    109     WASM_KEY_F11,
    110 };
    111 
    112 // TODO: map this in a nicer way
    113 global_variable int platform_input_map[NUM_GAME_BUTTONS] = {
    114     [BTN_LEFT] = WASM_KEY_LEFT,
    115     [BTN_RIGHT] = WASM_KEY_RIGHT,
    116     [BTN_UP] = WASM_KEY_UP,
    117     [BTN_DOWN] = WASM_KEY_DOWN,
    118     [BTN_JUMP] = WASM_KEY_S,
    119     [BTN_DEBUG_FLOAT] = WASM_KEY_F11,
    120 };
    121 
    122 global_variable struct GameMemory game_memory = {0};
    123 global_variable struct GameInput game_input = {0};
    124 global_variable i32 g_width = PLATFORM_SCR_WIDTH;
    125 global_variable i32 g_height = PLATFORM_SCR_HEIGHT;
    126 global_variable u32 previous_time = 0;
    127 
    128 i32 str_length(const char *str)
    129 {
    130     i32 i = 0;
    131     while(str[i] != '\0')
    132     {
    133         i++;
    134     }
    135     return i;
    136 }
    137 
    138 int wasm_print(const char *format, ...)
    139 {
    140     i32 len = str_length(format);
    141     js_print((i32)format, len);
    142     return 0;
    143 }
    144 
    145 bool init(i32 num_wasm_memory_pages)
    146 {
    147     bool init_successful = true;
    148     game_memory = (struct GameMemory) {
    149         // NOTE(amin): each wasm memory page is 64KiB
    150         .buffer_size = num_wasm_memory_pages * KIBIBYTES(64),
    151         .platform = {
    152             &wasm_read_entire_file,
    153             &wasm_memory_free,
    154         },
    155         .buffer = &__heap_base,
    156     };
    157     if (!game_memory.buffer)
    158     {
    159         wasm_print("Game memory allocation failed\n");
    160         init_successful = false;
    161     }
    162     game_init(&game_memory, (v2u) {g_width, g_height});
    163     return init_successful;
    164 }
    165 
    166 void render(f64 current_time)
    167 {
    168     game_input.dt = current_time - previous_time;
    169     previous_time = current_time;
    170     game_update_and_render(&game_memory, &game_input, (v2u) {g_width, g_height});
    171 }
    172 
    173 void window_resize(int w, int h)
    174 {
    175     g_width = w;
    176     g_height = h;
    177 }
    178 
    179 void key_callback(enum WasmKey key, bool key_action_is_pressed)
    180 {
    181     enum GameButton game_button = NULL_GAME_BUTTON;
    182     // TODO: Determine the button in a nicer way
    183     for (enum GameButton b = 0; b < NUM_GAME_BUTTONS; b++)
    184     {
    185         if (platform_input_map[b] == key)
    186         {
    187             game_button = b;
    188         }
    189     }
    190     if (game_button != NULL_GAME_BUTTON)
    191     {
    192         if (key_action_is_pressed)
    193         {
    194             game_input.button_states |= (1 << game_button);
    195         }
    196         else
    197         {
    198             game_input.button_states &= ~(1 << game_button);
    199         }
    200     }
    201 }
    202 
    203 PLATFORM_MEMORY_FREE(wasm_memory_free)
    204 {
    205     // do nothing
    206 }
    207 
    208 PLATFORM_READ_ENTIRE_FILE(wasm_read_entire_file)
    209 {
    210     i32 num_bytes_in_file = js_get_file_size((i32)file_path, str_length(file_path));
    211 
    212     if (out_num_bytes)
    213     {
    214         *out_num_bytes = num_bytes_in_file;
    215     }
    216 
    217     size_t fail_reversion_marker = mem_st_get_marker(a);
    218     u8 *buf = mem_st_alloc_buffer(a, u8, num_bytes_in_file + 1);
    219     assert(buf);
    220 
    221     bool success = js_read_entire_file((i32)file_path, str_length(file_path), buf);
    222     if (success)
    223     {
    224         buf[num_bytes_in_file] = '\0';
    225         wasm_print("Succeeded in reading file.");
    226     }
    227     else
    228     {
    229         mem_st_free_to_marker(a, fail_reversion_marker);
    230         buf = NULL;
    231         wasm_print("Failed to read file.");
    232     }
    233     return buf;
    234 }