#include "config.h" #include "render.h" #include "input.h" #if defined(plat_emscripten) #include #endif #if defined(plat_posix) || defined(plat_emscripten) #define _POSIX_SOURCE #include #include #include #include void platform_log(const char* message, ...) { va_list args; va_start(args, message); vfprintf(stdout, message, args); va_end(args); } void platform_err(const char* message, ...) { va_list args; va_start(args, message); if (isatty(fileno(stderr))) { fprintf(stderr, "\033[31;31m"); } vfprintf(stderr, message, args); if (isatty(fileno(stderr))) { fprintf(stderr, "\033[0m"); } va_end(args); } void platform_abort(int code) { #if defined(DEBUG) && defined(plat_x86) __asm__("int3;"); #else exit(code); #endif } #endif #if defined(plat_sdl2) #define max_joysticks 16 #include #include #include extern void on_init(int argc, char** argv); extern void on_update(); extern void on_deinit(); int held_btns[btn_count]; int pressed_btns[btn_count]; int released_btns[btn_count]; int app_running = 1; int texture_w = default_window_w, texture_h = default_window_h; int button_pressed(Button btn) { return held_btns[btn]; } int button_just_pressed(Button btn) { return pressed_btns[btn]; } int button_just_released(Button btn) { return released_btns[btn]; } Button sdl_to_btn(const SDL_Event* event) { switch (event->key.keysym.sym) { case SDLK_z: case SDLK_RETURN: return btn_jump; case SDLK_x: return btn_shoot; case SDLK_LEFT: case SDLK_h: return btn_dpad_left; case SDLK_RIGHT: case SDLK_l: return btn_dpad_right; case SDLK_UP: case SDLK_k: return btn_dpad_up; case SDLK_DOWN: case SDLK_j: return btn_dpad_down; case SDLK_ESCAPE: return btn_pause; case SDLK_F12: return btn_edit; case SDLK_s: return btn_save_level; default: return btn_unknown; } } Button joy_btn_to_btn(int button) { switch (button) { case 0: return btn_jump; case 2: return btn_shoot; case 7: return btn_pause; default: return btn_unknown; } } void reset_dpad() { int i; for ( i = btn_dpad_left; i <= btn_dpad_down; i++ ) { if (held_btns[i]) { held_btns[i] = 0; released_btns[i] = 1; } } } void update_dpad(Button btn) { reset_dpad(); held_btns[btn] = 1; pressed_btns[btn] = 1; } int audio_len, audio_pos; int ticker; void fill_audio(void *udata, Uint8 *stream, int len) { /*if (audio_len == 0) { audio_len = 1024; audio_pos = 0; } len = (len > audio_len ? audio_len : len); sound_sys.mix(((unsigned short*)stream), len); audio_pos += len; audio_len -= len;*/ } void reset_input() { int i; for (i = 0; i < btn_count; i++) { pressed_btns[i] = 0; released_btns[i] = 0; } } void platform_quit() { app_running = 0; } /* lol, lmao * haha */ static SDL_Window* window; static SDL_Renderer* renderer; static SDL_Texture* backbuffer; static void* bb_pixels; static SDL_Event event; static SDL_Rect src_rect, dst_rect; #if !no_sound static SDL_AudioSpec aud_spec; #endif static Button button; static int ww, wh, bb_pitch, ntw, nth; static int to_sleep, begin_time, end_time; static SDL_Joystick* joysticks[max_joysticks]; int platform_get_time() { return SDL_GetTicks(); } static void fit_texture(int w, int h) { ntw = renderer_w; nth = renderer_h; texture_w = ntw; texture_h = nth; /* This is kinda shit lmao. */ while (1) { ntw *= 2; nth *= 2; if ( ntw > w || nth > h ) { break; } texture_w = ntw; texture_h = nth; } } static void main_loop() { #if !defined(plat_emscripten) while (app_running) { #endif begin_time = SDL_GetTicks(); reset_input(); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: app_running = 0; break; case SDL_KEYDOWN: button = sdl_to_btn(&event); held_btns[(int)button] = 1; pressed_btns[(int)button] = 1; break; case SDL_KEYUP: button = sdl_to_btn(&event); held_btns[(int)button] = 0; released_btns[(int)button] = 1; break; case SDL_JOYDEVICEADDED: joysticks[event.jdevice.which] = SDL_JoystickOpen(event.jdevice.which); break; case SDL_JOYDEVICEREMOVED: SDL_JoystickClose(joysticks[event.jdevice.which]); break; case SDL_JOYHATMOTION: switch (event.jhat.value) { case SDL_HAT_LEFT: update_dpad(btn_dpad_left); break; case SDL_HAT_UP: update_dpad(btn_dpad_up); break; case SDL_HAT_RIGHT: update_dpad(btn_dpad_right); break; case SDL_HAT_DOWN: update_dpad(btn_dpad_down); break; case SDL_HAT_CENTERED: reset_dpad(); default: break; } break; case SDL_JOYBUTTONDOWN: button = joy_btn_to_btn(event.jbutton.button); held_btns[(int)button] = 1; pressed_btns[(int)button] = 1; break; case SDL_JOYBUTTONUP: button = joy_btn_to_btn(event.jbutton.button); held_btns[(int)button] = 0; released_btns[(int)button] = 1; break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: fit_texture(event.window.data1, event.window.data2); break; } default: break; } } on_update(); SDL_GetWindowSize(window, &ww, &wh); src_rect.x = 0; src_rect.y = 0; src_rect.w = renderer_w; src_rect.h = renderer_h; src_rect.x = 0; src_rect.y = 0; src_rect.w = renderer_w; src_rect.h = renderer_h; dst_rect.x = ww / 2 - texture_w / 2; dst_rect.y = wh / 2 - texture_h / 2; dst_rect.w = texture_w; dst_rect.h = texture_h; SDL_LockTexture( backbuffer, 0, &bb_pixels, &bb_pitch ); memcpy(bb_pixels, get_render_pixels(), renderer_w * renderer_h * sizeof(Colour) ); SDL_UnlockTexture(backbuffer); SDL_UpdateTexture( backbuffer, 0, get_render_pixels(), renderer_w * sizeof(Colour) ); SDL_RenderClear(renderer); SDL_RenderCopy( renderer, backbuffer, &src_rect, &dst_rect ); SDL_RenderPresent(renderer); end_time = SDL_GetTicks(); to_sleep = 20 - ((end_time - begin_time)); if (to_sleep > 0) { SDL_Delay(to_sleep); } #if !defined(plat_emscripten) } #endif } int main(int argc, char** argv) { audio_pos = 0; audio_len = 1024; ticker = 0; SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); SDL_CreateWindowAndRenderer( default_window_w * renderer_scale, default_window_h * renderer_scale, SDL_WINDOW_RESIZABLE, &window, &renderer ); SDL_SetWindowTitle(window, game_name); #if !no_sound aud_spec.freq = 22050; aud_spec.format = AUDIO_U16; aud_spec.channels = 1; aud_spec.samples = 1024; aud_spec.callback = fill_audio; aud_spec.userdata = 0; if (SDL_OpenAudio(&aud_spec, 0) < 0) { fprintf( stderr, "Sound error: %s.\n", SDL_GetError() ); } SDL_PauseAudio(0); #endif on_init(argc, argv); backbuffer = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, renderer_w, renderer_h ); fit_texture( renderer_w * renderer_scale, renderer_h * renderer_scale ); #if defined(plat_emscripten) emscripten_set_main_loop(main_loop, 0, 1); #else main_loop(); #endif on_deinit(); SDL_DestroyTexture(backbuffer); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); #if !no_sound SDL_CloseAudio(); #endif SDL_Quit(); return 0; } #else #define No platform defined. #endif