aboutsummaryrefslogtreecommitdiff
path: root/plat.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat.c')
-rw-r--r--plat.c342
1 files changed, 340 insertions, 2 deletions
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 <emscripten.h>
+#endif
+
+#include <SDL2/SDL.h>
+#include <stdio.h>
+#include <string.h>
+
+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