Mercurial > repos > simple16
view src/system_sdl.c @ 34:4a093f15fb1b
Finish controller test for controller 1
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 03 Apr 2016 19:03:35 -0700 |
parents | c677507682e3 |
children | 3b7910575a00 |
line wrap: on
line source
#include <SDL.h> #include <stdint.h> #include <stdlib.h> #include "controller.h" static SDL_Window *window; static SDL_Renderer *renderer; static SDL_Texture *texture; static int sample_rate; static int buffer_size; static uint8_t quitting; static SDL_mutex * audio_mutex; static SDL_cond * source_ready; static SDL_cond * output_ready; static int16_t *source_buffer; static void audio_callback(void * userdata, uint8_t *stream, int len) { uint8_t local_quit; int16_t *local_source; SDL_LockMutex(audio_mutex); local_source = NULL; do { if (!local_source) { local_source = source_buffer; source_buffer = NULL; SDL_CondSignal(output_ready); } if (!quitting && !local_source) { SDL_CondWait(source_ready, audio_mutex); } } while (!quitting && !local_source); local_quit = quitting; SDL_UnlockMutex(audio_mutex); if (!local_quit) { fflush(stdout); memcpy(stream, local_source, len); } } static void close_audio() { SDL_LockMutex(audio_mutex); quitting = 1; SDL_CondSignal(source_ready); SDL_UnlockMutex(audio_mutex); SDL_CloseAudio(); } void system_present_audio(int16_t *buffer) { SDL_LockMutex(audio_mutex); while (source_buffer) { SDL_CondWait(output_ready, audio_mutex); } source_buffer = buffer; SDL_CondSignal(source_ready); SDL_UnlockMutex(audio_mutex); } int system_sample_rate() { return sample_rate; } int system_buffer_size() { return buffer_size; } static int num_controllers; static SDL_GameController **game_controllers; int system_init(int width, int height, int desired_sample_rate) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) < 0) { fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError()); return 0; } atexit(SDL_Quit); window = SDL_CreateWindow("simple16", 0, 0, width, height, 0); if (!window) { fprintf(stderr, "Failed to create window: %s\n", SDL_GetError()); return 0; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (!renderer) { fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError()); goto renderer_error; } texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB444, SDL_TEXTUREACCESS_STREAMING, 320, 240); if (!texture) { fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError()); goto error; } audio_mutex = SDL_CreateMutex(); source_ready = SDL_CreateCond(); output_ready = SDL_CreateCond(); SDL_AudioSpec desired, actual; desired.freq = desired_sample_rate; desired.format = AUDIO_S16SYS; desired.channels = 1; desired.callback = audio_callback; desired.userdata = NULL; desired.samples = 512; if (SDL_OpenAudio(&desired, &actual) < 0) { fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError()); goto error; } printf("Initialized audio at frequency %d with a %d sample buffer and %d channels\n", actual.freq, actual.samples, actual.channels); sample_rate = actual.freq; buffer_size = actual.samples; atexit(close_audio); SDL_PauseAudio(0); num_controllers = SDL_NumJoysticks(); game_controllers = calloc(num_controllers, sizeof(*game_controllers)); for (int i = 0; i < num_controllers; i++) { if (!SDL_IsGameController(i)) { printf("Joystick %d: %s is not recognized as a controller by SDL2\n", i, SDL_JoystickNameForIndex(i)); continue; } game_controllers[i] = SDL_GameControllerOpen(i); } return 1; error: SDL_DestroyRenderer(renderer); renderer_error: SDL_DestroyWindow(window); return 0; } uint16_t *system_get_framebuffer(int *pitch) { void *pixels; if (SDL_LockTexture(texture, NULL, &pixels, pitch) < 0) { fprintf(stderr, "Failed to lock texture: %s\n", SDL_GetError()); return NULL; } return pixels; } void system_framebuffer_updated() { SDL_UnlockTexture(texture); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } //SDL2 provides this, but only in 2.0.4+ SDL_GameController *controller_by_id(SDL_JoystickID which) { for (int i = 0; i < num_controllers; i++) { if (!game_controllers[i]) { continue; } if (SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(game_controllers[i])) == which) { return game_controllers[i]; } } return NULL; } const uint16_t mapping[SDL_CONTROLLER_BUTTON_MAX] = { [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = 0x001, [SDL_CONTROLLER_BUTTON_Y] = 0x002, [SDL_CONTROLLER_BUTTON_X] = 0x004, [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = 0x008, [SDL_CONTROLLER_BUTTON_B] = 0x010, [SDL_CONTROLLER_BUTTON_A] = 0x020, [SDL_CONTROLLER_BUTTON_BACK] = 0x040, [SDL_CONTROLLER_BUTTON_START] = 0x080, [SDL_CONTROLLER_BUTTON_DPAD_RIGHT] = 0x100, [SDL_CONTROLLER_BUTTON_DPAD_LEFT] = 0x200, [SDL_CONTROLLER_BUTTON_DPAD_DOWN] = 0x400, [SDL_CONTROLLER_BUTTON_DPAD_UP] = 0x800, }; void system_poll_events() { SDL_Event event; while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: exit(0); break; case SDL_CONTROLLERBUTTONDOWN: controller_pressed(event.cbutton.which, mapping[event.cbutton.button]); break; case SDL_CONTROLLERBUTTONUP: controller_released(event.cbutton.which, mapping[event.cbutton.button]); break; //TODO: Keyboard input //TODO: Controller hotplug } } }