From 7a7628a3feaec81d9a445acbec604baecac3a167 Mon Sep 17 00:00:00 2001 From: quou Date: Sat, 12 Oct 2024 00:23:57 +1100 Subject: sdl + emscripten backend --- plat.c | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 340 insertions(+), 2 deletions(-) (limited to 'plat.c') diff --git a/plat.c b/plat.c index 6669c12..3f2a007 100644 --- a/plat.c +++ b/plat.c @@ -179,11 +179,16 @@ void fps_update(FPS* f) { f->fps = 1000000000 / (f->ct - f->pt); } -extern int entrypoint(int, const char**, Arena*); +extern int prog_init(Arena* m); +extern int prog_update(void); +extern int prog_deinit(void); int main(int argc, const char** argv) { Arena a; void* mem = malloc(memory_size); + int r; + (void)argc; + (void)argv; if (!mem) { print_err("Out of memory.\n"); return error_out_of_memory; @@ -194,7 +199,10 @@ int main(int argc, const char** argv) { mem, memory_size ); - return entrypoint(argc, argv, &a); + if ((r = prog_init(&a))) return r; + for (r = 1; r; r = prog_update()); + prog_deinit(); + return error_none; } #endif @@ -580,3 +588,333 @@ void play_sound(int len) { } #endif + +#ifdef plat_sdl2 + +#if defined(plat_ems) +#include +#endif + +#include +#include +#include + +void print(const char* fmt, ...) { + va_list a; + va_start(a, fmt); + SDL_LogMessageV(0, SDL_LOG_PRIORITY_INFO, fmt, a); + va_end(a); +} + +void print_err(const char* fmt, ...) { + va_list a; + va_start(a, fmt); + SDL_LogMessageV(0, SDL_LOG_PRIORITY_ERROR, fmt, a); + va_end(a); +} + +void print_war(const char* fmt, ...) { + va_list a; + va_start(a, fmt); + SDL_LogMessageV(0, SDL_LOG_PRIORITY_WARN, fmt, a); + va_end(a); +} + +int imp_assert( + int val, + const char* expr, + const char* file, + int line +) { + if (!val) { + print_err( + "%d:%s: Assertion failed: %s.\n", + line, + file, + expr + ); + pbreak(error_assertion_failed); + return 0; + } + return 1; +} + +void pbreak(Error code) { + (void)code; + SDL_TriggerBreakpoint(); +} + +void init_fps(FPS* f, int mpf) { + f->now = SDL_GetTicks(); + f->next = f->now; + f->mpf = mpf; + f->pt = 0; + f->ct = -1; +} + +void fps_begin(FPS* f) { + f->now = SDL_GetTicks(); +} + +void fps_end(FPS* f) { + unsigned long ts = f->next - f->now; + if (ts > 0) { + SDL_Delay(ts); + } +} + +void fps_update(FPS* f) { + f->next += f->mpf; + f->pt = f->ct; + f->ct = SDL_GetTicks(); + f->fps = 1000 / (f->ct - f->pt); +} + +extern int prog_init(Arena* m); +extern int prog_update(void); +extern void prog_deinit(void); + +static void main_loop(void) { +#ifdef plat_ems + prog_update(); +#else + int r; + for (r = 1; r; r = prog_update()); + SDL_Quit(); +#endif +} + +int main(int argc, const char** argv) { + Arena a; + void* mem = malloc(memory_size); + int r; + (void)argc; + (void)argv; + if (!mem) { + print_err("Out of memory.\n"); + return error_out_of_memory; + } + init_arena( + &a, + mem, + memory_size + ); + if ((r = prog_init(&a))) return r; +#ifdef plat_ems + emscripten_set_main_loop(main_loop, 0, 1); +#else + main_loop(); +#endif + prog_deinit(); + return 0; +} + +Btn sdl_to_btn(const SDL_Event* e) { + switch (e->key.keysym.sym) { + case SDLK_z: + case SDLK_RETURN: + return btn_jump; + case SDLK_x: + return btn_shoot; + case SDLK_c: + return btn_special; + case SDLK_LEFT: + case SDLK_h: + return btn_left; + case SDLK_RIGHT: + case SDLK_l: + return btn_right; + case SDLK_UP: + case SDLK_k: + return btn_up; + case SDLK_DOWN: + case SDLK_j: + return btn_down; + default: return btn_unknown; + } +} + +typedef struct { + SDL_Window* wi; + SDL_Renderer* re; + SDL_Texture* bb; + unsigned* bbp; + int w, h; +} App_Internal; + +void init_window(App* a, App_Internal* i, const char* n) { + int flag = 0; +#ifndef plat_ems + flag = SDL_WINDOW_RESIZABLE; +#endif + SDL_CreateWindowAndRenderer( + viewport_w * 2, + viewport_h * 2, + flag, + &i->wi, + &i->re + ); + i->w = viewport_w * 2; + i->h = viewport_h * 2; + SDL_SetWindowTitle(i->wi, n); + i->bb = SDL_CreateTexture( + i->re, + SDL_PIXELFORMAT_ABGR8888, + SDL_TEXTUREACCESS_STREAMING, + viewport_w, + viewport_h + ); + a->fb = heap_alloc( + a->heap, + (viewport_w * viewport_h + 32) / 32 * sizeof *a->fb + ); +} + +App* new_app(struct Heap* mem, const char* n) { + App* a; + App_Internal* i; + a = heap_alloc(mem, sizeof *a + sizeof *i); + i = (App_Internal*)(&a[1]); + a->heap = mem; + a->s = 2; + a->o = 0; + a->err = error_none; + init_window(a, i, n); + a->o = 1; + return a; +} + +void deinit_app(App* a) { + +} + +void app_begin(App* a) { + App_Internal* i = (App_Internal*)(&a[1]); + SDL_Event e; + int j; + Btn btn; + for (j = 0; j < btn_count; j++) + a->btn_states[j] &= ~( + btn_state_just_pressed | btn_state_just_released + ); + while (SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_QUIT: + a->o = 0; + break; + case SDL_KEYDOWN: + btn = sdl_to_btn(&e); + a->btn_states[btn] |= + btn_state_pressed | + btn_state_just_pressed; + break; + case SDL_KEYUP: + btn = sdl_to_btn(&e); + a->btn_states[btn] &= ~btn_state_pressed; + a->btn_states[btn] |= btn_state_just_released; + break; + case SDL_WINDOWEVENT: + switch (e.window.event) { + case SDL_WINDOWEVENT_RESIZED: + i->w = e.window.data1; + i->h = e.window.data2; + break; + } + break; + default: break; + } + } +} + +void rencpy(App* a, unsigned* t, int p) { + const unsigned white = 0xffffffff; + const unsigned black = 0x00000000; + int x, y, i = 0; + p /= 4; + for (y = 0; y < viewport_h; y++) { + for (x = 0; x < viewport_w; x++, i++) { + int bit = 1 << (i & 0x1f); + bit &= a->fb[i >> 5]; + t[x + y * p] = bit? white: black; + } + } +} + +void fit_dr(App_Internal* i, SDL_Rect* r) { + int w = viewport_w, h = viewport_h, s; + for (s = 1; w * s <= i->w && h * s <= i->h; s++); + if (s > 1) s--; + r->w = viewport_w * s; + r->h = viewport_h * s; + r->x = i->w / 2 - r->w / 2; + r->y = i->h / 2 - r->h / 2; +} + +void app_end(App* a) { + App_Internal* i = (App_Internal*)(&a[1]); + unsigned* target; + SDL_Rect sr = { 0, 0, viewport_w, viewport_h }; + SDL_Rect dr = sr; + int pitch; + fit_dr((App_Internal*)&a[1], &dr); + SDL_LockTexture( + i->bb, + 0, + (void**)&target, + &pitch + ); + rencpy(a, target, pitch); + SDL_UnlockTexture(i->bb); + SDL_RenderClear(i->re); + SDL_RenderCopy( + i->re, + i->bb, + &sr, + &dr + ); + SDL_RenderPresent(i->re); +} + +static SDL_AudioSpec aud_spec; +int audio_len, audio_time; + +void fill_audio(void *udata, Uint8 *stream, int len) { + int i; + int16_t* pcm = (int16_t*)stream; + len /= 2; + for ( + i = 0; + i < len && audio_len; + i++, audio_len--, audio_time++ + ) pcm[i] = (int16_t)(sin((double)audio_time / 0.05) * 16000.0); + for (; i < len; i++) + pcm[i] = 0; +} + +void init_audio(void) { + audio_len = 0; + audio_time = 0; + aud_spec.freq = audio_sample_rate; + aud_spec.format = AUDIO_S16; + aud_spec.channels = 1; +#ifndef plat_ems + aud_spec.samples = audio_buffer_size; +#else + /* websites are retarded */ + aud_spec.samples = 1024; +#endif + aud_spec.callback = fill_audio; + aud_spec.userdata = 0; + SDL_OpenAudio(&aud_spec, 0); + SDL_PauseAudio(0); +} + +void deinit_audio(void) { + SDL_CloseAudio(); +} + +void play_sound(int len) { + audio_len += len; +} + +#endif -- cgit v1.2.3-54-g00ecf