Mercurial > repos > blastem
diff render_sdl.c @ 354:15dd6418fe67
Initial PSG support. Mostly works, noise channel is borked though.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 23 May 2013 23:42:42 -0700 |
parents | 13f994c88c34 |
children | 79e4b466e7d0 |
line wrap: on
line diff
--- a/render_sdl.c Wed May 22 09:37:02 2013 -0700 +++ b/render_sdl.c Thu May 23 23:42:42 2013 -0700 @@ -16,9 +16,41 @@ uint32_t min_delay; uint32_t frame_delay = 1000/60; -void render_init(int width, int height, char * title) +int16_t * current_audio = NULL; +int16_t * next_audio = NULL; + +uint32_t buffer_samples, sample_rate; +uint32_t missing_count; + +SDL_mutex * audio_mutex; +SDL_cond * audio_ready; +SDL_cond * audio_cond; + +void audio_callback(void * userdata, uint8_t *byte_stream, int len) { - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + //puts("audio_callback"); + int16_t * stream = (int16_t *)byte_stream; + int samples = len/(sizeof(int16_t)*2); + int16_t * source_buf; + + SDL_LockMutex(audio_mutex); + while (!current_audio) { + SDL_CondWait(audio_ready, audio_mutex); + } + source_buf = current_audio; + current_audio = NULL; + SDL_CondSignal(audio_cond); + SDL_UnlockMutex(audio_mutex); + + for (int i = 0; i < samples; i++) { + *(stream++) = source_buf[i]; + *(stream++) = source_buf[i]; + } +} + +void render_init(int width, int height, char * title, uint32_t fps) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(1); } @@ -64,6 +96,29 @@ min_delay = 1; } printf("minimum delay: %d\n", min_delay); + + frame_delay = 1000/fps; + + audio_mutex = SDL_CreateMutex(); + audio_cond = SDL_CreateCond(); + audio_ready = SDL_CreateCond(); + + SDL_AudioSpec desired, actual; + desired.freq = 48000; + desired.format = AUDIO_S16SYS; + desired.channels = 2; + desired.samples = 1024; + desired.callback = audio_callback; + desired.userdata = NULL; + + if (SDL_OpenAudio(&desired, &actual) < 0) { + fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError()); + exit(1); + } + buffer_samples = actual.samples; + sample_rate = actual.freq; + printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples); + SDL_PauseAudio(0); } void render_context(vdp_context * context) @@ -230,135 +285,141 @@ #define BUTTON_START 0x20 #define BUTTON_C 0x20 +int32_t handle_event(SDL_Event *event) +{ + FILE * outfile; + switch (event->type) { + case SDL_KEYDOWN: + switch(event->key.keysym.sym) + { + case SDLK_LEFTBRACKET: + render_dbg++; + if (render_dbg == 4) { + render_dbg = 0; + } + break; + case SDLK_RIGHTBRACKET: + debug_pal++; + if (debug_pal == 4) { + debug_pal = 0; + } + break; + case SDLK_t: + /*outfile = fopen("state.gst", "wb"); + fwrite("GST\0\0\0\xE0\x40", 1, 8, outfile); + vdp_save_state(context, outfile); + fclose(outfile); + puts("state saved to state.gst");*/ + break; + case SDLK_u: + return 1; + case SDLK_RETURN: + gamepad_1.input[GAMEPAD_TH0] |= BUTTON_START; + break; + case SDLK_UP: + gamepad_1.input[GAMEPAD_TH0] |= DPAD_UP; + gamepad_1.input[GAMEPAD_TH1] |= DPAD_UP; + break; + case SDLK_DOWN: + gamepad_1.input[GAMEPAD_TH0] |= DPAD_DOWN; + gamepad_1.input[GAMEPAD_TH1] |= DPAD_DOWN; + break; + case SDLK_LEFT: + gamepad_1.input[GAMEPAD_TH1] |= DPAD_LEFT; + break; + case SDLK_RIGHT: + gamepad_1.input[GAMEPAD_TH1] |= DPAD_RIGHT; + break; + case SDLK_a: + gamepad_1.input[GAMEPAD_TH0] |= BUTTON_A; + //printf("BUTTON_A Dn | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]); + break; + case SDLK_s: + gamepad_1.input[GAMEPAD_TH1] |= BUTTON_B; + gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_B; + break; + case SDLK_d: + gamepad_1.input[GAMEPAD_TH1] |= BUTTON_C; + gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_C; + break; + case SDLK_q: + gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_X; + break; + case SDLK_w: + gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Y; + break; + case SDLK_e: + gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Z; + break; + case SDLK_f: + gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_MODE; + break; + } + break; + case SDL_KEYUP: + switch(event->key.keysym.sym) + { + case SDLK_RETURN: + gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_START; + break; + case SDLK_UP: + gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_UP; + gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_UP; + break; + case SDLK_DOWN: + gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_DOWN; + gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_DOWN; + break; + case SDLK_LEFT: + gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_LEFT; + break; + case SDLK_RIGHT: + gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_RIGHT; + break; + case SDLK_a: + gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_A; + //printf("BUTTON_A Up | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]); + break; + case SDLK_s: + gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_B; + gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_B; + break; + case SDLK_d: + gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_C; + gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_C; + break; + case SDLK_q: + gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_X; + break; + case SDLK_w: + gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Y; + break; + case SDLK_e: + gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Z; + break; + case SDLK_f: + gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_MODE; + break; + } + break; + case SDL_QUIT: + puts(""); + exit(0); + } + return 0; +} + uint32_t frame_counter = 0; uint32_t start = 0; int wait_render_frame(vdp_context * context, int frame_limit) { - FILE * outfile; SDL_Event event; int ret = 0; while(SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_KEYDOWN: - switch(event.key.keysym.sym) - { - case SDLK_LEFTBRACKET: - render_dbg++; - if (render_dbg == 4) { - render_dbg = 0; - } - break; - case SDLK_RIGHTBRACKET: - debug_pal++; - if (debug_pal == 4) { - debug_pal = 0; - } - break; - case SDLK_t: - outfile = fopen("state.gst", "wb"); - fwrite("GST\0\0\0\xE0\x40", 1, 8, outfile); - vdp_save_state(context, outfile); - fclose(outfile); - puts("state saved to state.gst"); - break; - case SDLK_u: - ret = 1; - break; - case SDLK_RETURN: - gamepad_1.input[GAMEPAD_TH0] |= BUTTON_START; - break; - case SDLK_UP: - gamepad_1.input[GAMEPAD_TH0] |= DPAD_UP; - gamepad_1.input[GAMEPAD_TH1] |= DPAD_UP; - break; - case SDLK_DOWN: - gamepad_1.input[GAMEPAD_TH0] |= DPAD_DOWN; - gamepad_1.input[GAMEPAD_TH1] |= DPAD_DOWN; - break; - case SDLK_LEFT: - gamepad_1.input[GAMEPAD_TH1] |= DPAD_LEFT; - break; - case SDLK_RIGHT: - gamepad_1.input[GAMEPAD_TH1] |= DPAD_RIGHT; - break; - case SDLK_a: - gamepad_1.input[GAMEPAD_TH0] |= BUTTON_A; - //printf("BUTTON_A Dn | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]); - break; - case SDLK_s: - gamepad_1.input[GAMEPAD_TH1] |= BUTTON_B; - gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_B; - break; - case SDLK_d: - gamepad_1.input[GAMEPAD_TH1] |= BUTTON_C; - gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_C; - break; - case SDLK_q: - gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_X; - break; - case SDLK_w: - gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Y; - break; - case SDLK_e: - gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Z; - break; - case SDLK_f: - gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_MODE; - break; - } - break; - case SDL_KEYUP: - switch(event.key.keysym.sym) - { - case SDLK_RETURN: - gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_START; - break; - case SDLK_UP: - gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_UP; - gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_UP; - break; - case SDLK_DOWN: - gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_DOWN; - gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_DOWN; - break; - case SDLK_LEFT: - gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_LEFT; - break; - case SDLK_RIGHT: - gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_RIGHT; - break; - case SDLK_a: - gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_A; - //printf("BUTTON_A Up | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]); - break; - case SDLK_s: - gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_B; - gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_B; - break; - case SDLK_d: - gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_C; - gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_C; - break; - case SDLK_q: - gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_X; - break; - case SDLK_w: - gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Y; - break; - case SDLK_e: - gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Z; - break; - case SDLK_f: - gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_MODE; - break; - } - break; - case SDL_QUIT: - puts(""); - exit(0); - } + ret = handle_event(&event); } if (frame_limit) { + puts("evil frame limit"); //TODO: Adjust frame delay so we actually get 60 FPS rather than 62.5 FPS uint32_t current = SDL_GetTicks(); uint32_t desired = last_frame + frame_delay; @@ -387,9 +448,34 @@ return ret; } +void render_wait_audio(psg_context * context) +{ + SDL_LockMutex(audio_mutex); + while (current_audio != NULL) { + SDL_CondWait(audio_cond, audio_mutex); + } + current_audio = context->audio_buffer; + SDL_CondSignal(audio_ready); + + context->audio_buffer = context->back_buffer; + context->back_buffer = current_audio; + SDL_UnlockMutex(audio_mutex); + context->buffer_pos = 0; +} + void render_fps(uint32_t fps) { frame_delay = 1000/fps; } +uint32_t render_audio_buffer() +{ + return buffer_samples; +} +uint32_t render_sample_rate() +{ + return sample_rate; +} + +