Mercurial > repos > simple16
view src/system_sdl.c @ 26:083347ccd508
Implemented vblank interrupts and fixed a bug in exception vector address calculation
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 01 Apr 2016 21:34:38 -0700 |
parents | 4c9dbfa30a66 |
children | c677507682e3 |
line wrap: on
line source
#include <SDL.h> #include <stdint.h> #include <stdlib.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; } int system_init(int width, int height, int desired_sample_rate) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 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); 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); } void system_poll_events() { SDL_Event event; while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: exit(0); break; } } }