comparison 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
comparison
equal deleted inserted replaced
353:a60e527cd21f 354:15dd6418fe67
14 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; 14 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255};
15 15
16 uint32_t min_delay; 16 uint32_t min_delay;
17 uint32_t frame_delay = 1000/60; 17 uint32_t frame_delay = 1000/60;
18 18
19 void render_init(int width, int height, char * title) 19 int16_t * current_audio = NULL;
20 { 20 int16_t * next_audio = NULL;
21 if (SDL_Init(SDL_INIT_VIDEO) < 0) { 21
22 uint32_t buffer_samples, sample_rate;
23 uint32_t missing_count;
24
25 SDL_mutex * audio_mutex;
26 SDL_cond * audio_ready;
27 SDL_cond * audio_cond;
28
29 void audio_callback(void * userdata, uint8_t *byte_stream, int len)
30 {
31 //puts("audio_callback");
32 int16_t * stream = (int16_t *)byte_stream;
33 int samples = len/(sizeof(int16_t)*2);
34 int16_t * source_buf;
35
36 SDL_LockMutex(audio_mutex);
37 while (!current_audio) {
38 SDL_CondWait(audio_ready, audio_mutex);
39 }
40 source_buf = current_audio;
41 current_audio = NULL;
42 SDL_CondSignal(audio_cond);
43 SDL_UnlockMutex(audio_mutex);
44
45 for (int i = 0; i < samples; i++) {
46 *(stream++) = source_buf[i];
47 *(stream++) = source_buf[i];
48 }
49 }
50
51 void render_init(int width, int height, char * title, uint32_t fps)
52 {
53 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
22 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); 54 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
23 exit(1); 55 exit(1);
24 } 56 }
25 atexit(SDL_Quit); 57 atexit(SDL_Quit);
26 printf("width: %d, height: %d\n", width, height); 58 printf("width: %d, height: %d\n", width, height);
62 } 94 }
63 if (!min_delay) { 95 if (!min_delay) {
64 min_delay = 1; 96 min_delay = 1;
65 } 97 }
66 printf("minimum delay: %d\n", min_delay); 98 printf("minimum delay: %d\n", min_delay);
99
100 frame_delay = 1000/fps;
101
102 audio_mutex = SDL_CreateMutex();
103 audio_cond = SDL_CreateCond();
104 audio_ready = SDL_CreateCond();
105
106 SDL_AudioSpec desired, actual;
107 desired.freq = 48000;
108 desired.format = AUDIO_S16SYS;
109 desired.channels = 2;
110 desired.samples = 1024;
111 desired.callback = audio_callback;
112 desired.userdata = NULL;
113
114 if (SDL_OpenAudio(&desired, &actual) < 0) {
115 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError());
116 exit(1);
117 }
118 buffer_samples = actual.samples;
119 sample_rate = actual.freq;
120 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples);
121 SDL_PauseAudio(0);
67 } 122 }
68 123
69 void render_context(vdp_context * context) 124 void render_context(vdp_context * context)
70 { 125 {
71 uint8_t *buf_8; 126 uint8_t *buf_8;
228 #define BUTTON_A 0x10 283 #define BUTTON_A 0x10
229 #define BUTTON_B 0x10 284 #define BUTTON_B 0x10
230 #define BUTTON_START 0x20 285 #define BUTTON_START 0x20
231 #define BUTTON_C 0x20 286 #define BUTTON_C 0x20
232 287
288 int32_t handle_event(SDL_Event *event)
289 {
290 FILE * outfile;
291 switch (event->type) {
292 case SDL_KEYDOWN:
293 switch(event->key.keysym.sym)
294 {
295 case SDLK_LEFTBRACKET:
296 render_dbg++;
297 if (render_dbg == 4) {
298 render_dbg = 0;
299 }
300 break;
301 case SDLK_RIGHTBRACKET:
302 debug_pal++;
303 if (debug_pal == 4) {
304 debug_pal = 0;
305 }
306 break;
307 case SDLK_t:
308 /*outfile = fopen("state.gst", "wb");
309 fwrite("GST\0\0\0\xE0\x40", 1, 8, outfile);
310 vdp_save_state(context, outfile);
311 fclose(outfile);
312 puts("state saved to state.gst");*/
313 break;
314 case SDLK_u:
315 return 1;
316 case SDLK_RETURN:
317 gamepad_1.input[GAMEPAD_TH0] |= BUTTON_START;
318 break;
319 case SDLK_UP:
320 gamepad_1.input[GAMEPAD_TH0] |= DPAD_UP;
321 gamepad_1.input[GAMEPAD_TH1] |= DPAD_UP;
322 break;
323 case SDLK_DOWN:
324 gamepad_1.input[GAMEPAD_TH0] |= DPAD_DOWN;
325 gamepad_1.input[GAMEPAD_TH1] |= DPAD_DOWN;
326 break;
327 case SDLK_LEFT:
328 gamepad_1.input[GAMEPAD_TH1] |= DPAD_LEFT;
329 break;
330 case SDLK_RIGHT:
331 gamepad_1.input[GAMEPAD_TH1] |= DPAD_RIGHT;
332 break;
333 case SDLK_a:
334 gamepad_1.input[GAMEPAD_TH0] |= BUTTON_A;
335 //printf("BUTTON_A Dn | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]);
336 break;
337 case SDLK_s:
338 gamepad_1.input[GAMEPAD_TH1] |= BUTTON_B;
339 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_B;
340 break;
341 case SDLK_d:
342 gamepad_1.input[GAMEPAD_TH1] |= BUTTON_C;
343 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_C;
344 break;
345 case SDLK_q:
346 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_X;
347 break;
348 case SDLK_w:
349 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Y;
350 break;
351 case SDLK_e:
352 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Z;
353 break;
354 case SDLK_f:
355 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_MODE;
356 break;
357 }
358 break;
359 case SDL_KEYUP:
360 switch(event->key.keysym.sym)
361 {
362 case SDLK_RETURN:
363 gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_START;
364 break;
365 case SDLK_UP:
366 gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_UP;
367 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_UP;
368 break;
369 case SDLK_DOWN:
370 gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_DOWN;
371 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_DOWN;
372 break;
373 case SDLK_LEFT:
374 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_LEFT;
375 break;
376 case SDLK_RIGHT:
377 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_RIGHT;
378 break;
379 case SDLK_a:
380 gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_A;
381 //printf("BUTTON_A Up | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]);
382 break;
383 case SDLK_s:
384 gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_B;
385 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_B;
386 break;
387 case SDLK_d:
388 gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_C;
389 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_C;
390 break;
391 case SDLK_q:
392 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_X;
393 break;
394 case SDLK_w:
395 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Y;
396 break;
397 case SDLK_e:
398 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Z;
399 break;
400 case SDLK_f:
401 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_MODE;
402 break;
403 }
404 break;
405 case SDL_QUIT:
406 puts("");
407 exit(0);
408 }
409 return 0;
410 }
411
233 uint32_t frame_counter = 0; 412 uint32_t frame_counter = 0;
234 uint32_t start = 0; 413 uint32_t start = 0;
235 int wait_render_frame(vdp_context * context, int frame_limit) 414 int wait_render_frame(vdp_context * context, int frame_limit)
236 { 415 {
237 FILE * outfile;
238 SDL_Event event; 416 SDL_Event event;
239 int ret = 0; 417 int ret = 0;
240 while(SDL_PollEvent(&event)) { 418 while(SDL_PollEvent(&event)) {
241 switch (event.type) { 419 ret = handle_event(&event);
242 case SDL_KEYDOWN:
243 switch(event.key.keysym.sym)
244 {
245 case SDLK_LEFTBRACKET:
246 render_dbg++;
247 if (render_dbg == 4) {
248 render_dbg = 0;
249 }
250 break;
251 case SDLK_RIGHTBRACKET:
252 debug_pal++;
253 if (debug_pal == 4) {
254 debug_pal = 0;
255 }
256 break;
257 case SDLK_t:
258 outfile = fopen("state.gst", "wb");
259 fwrite("GST\0\0\0\xE0\x40", 1, 8, outfile);
260 vdp_save_state(context, outfile);
261 fclose(outfile);
262 puts("state saved to state.gst");
263 break;
264 case SDLK_u:
265 ret = 1;
266 break;
267 case SDLK_RETURN:
268 gamepad_1.input[GAMEPAD_TH0] |= BUTTON_START;
269 break;
270 case SDLK_UP:
271 gamepad_1.input[GAMEPAD_TH0] |= DPAD_UP;
272 gamepad_1.input[GAMEPAD_TH1] |= DPAD_UP;
273 break;
274 case SDLK_DOWN:
275 gamepad_1.input[GAMEPAD_TH0] |= DPAD_DOWN;
276 gamepad_1.input[GAMEPAD_TH1] |= DPAD_DOWN;
277 break;
278 case SDLK_LEFT:
279 gamepad_1.input[GAMEPAD_TH1] |= DPAD_LEFT;
280 break;
281 case SDLK_RIGHT:
282 gamepad_1.input[GAMEPAD_TH1] |= DPAD_RIGHT;
283 break;
284 case SDLK_a:
285 gamepad_1.input[GAMEPAD_TH0] |= BUTTON_A;
286 //printf("BUTTON_A Dn | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]);
287 break;
288 case SDLK_s:
289 gamepad_1.input[GAMEPAD_TH1] |= BUTTON_B;
290 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_B;
291 break;
292 case SDLK_d:
293 gamepad_1.input[GAMEPAD_TH1] |= BUTTON_C;
294 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_C;
295 break;
296 case SDLK_q:
297 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_X;
298 break;
299 case SDLK_w:
300 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Y;
301 break;
302 case SDLK_e:
303 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Z;
304 break;
305 case SDLK_f:
306 gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_MODE;
307 break;
308 }
309 break;
310 case SDL_KEYUP:
311 switch(event.key.keysym.sym)
312 {
313 case SDLK_RETURN:
314 gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_START;
315 break;
316 case SDLK_UP:
317 gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_UP;
318 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_UP;
319 break;
320 case SDLK_DOWN:
321 gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_DOWN;
322 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_DOWN;
323 break;
324 case SDLK_LEFT:
325 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_LEFT;
326 break;
327 case SDLK_RIGHT:
328 gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_RIGHT;
329 break;
330 case SDLK_a:
331 gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_A;
332 //printf("BUTTON_A Up | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]);
333 break;
334 case SDLK_s:
335 gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_B;
336 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_B;
337 break;
338 case SDLK_d:
339 gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_C;
340 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_C;
341 break;
342 case SDLK_q:
343 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_X;
344 break;
345 case SDLK_w:
346 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Y;
347 break;
348 case SDLK_e:
349 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Z;
350 break;
351 case SDLK_f:
352 gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_MODE;
353 break;
354 }
355 break;
356 case SDL_QUIT:
357 puts("");
358 exit(0);
359 }
360 } 420 }
361 if (frame_limit) { 421 if (frame_limit) {
422 puts("evil frame limit");
362 //TODO: Adjust frame delay so we actually get 60 FPS rather than 62.5 FPS 423 //TODO: Adjust frame delay so we actually get 60 FPS rather than 62.5 FPS
363 uint32_t current = SDL_GetTicks(); 424 uint32_t current = SDL_GetTicks();
364 uint32_t desired = last_frame + frame_delay; 425 uint32_t desired = last_frame + frame_delay;
365 if (current < desired) { 426 if (current < desired) {
366 uint32_t delay = last_frame + frame_delay - current; 427 uint32_t delay = last_frame + frame_delay - current;
385 frame_counter = 0; 446 frame_counter = 0;
386 }*/ 447 }*/
387 return ret; 448 return ret;
388 } 449 }
389 450
451 void render_wait_audio(psg_context * context)
452 {
453 SDL_LockMutex(audio_mutex);
454 while (current_audio != NULL) {
455 SDL_CondWait(audio_cond, audio_mutex);
456 }
457 current_audio = context->audio_buffer;
458 SDL_CondSignal(audio_ready);
459
460 context->audio_buffer = context->back_buffer;
461 context->back_buffer = current_audio;
462 SDL_UnlockMutex(audio_mutex);
463 context->buffer_pos = 0;
464 }
465
390 void render_fps(uint32_t fps) 466 void render_fps(uint32_t fps)
391 { 467 {
392 frame_delay = 1000/fps; 468 frame_delay = 1000/fps;
393 } 469 }
394 470
395 471 uint32_t render_audio_buffer()
472 {
473 return buffer_samples;
474 }
475
476 uint32_t render_sample_rate()
477 {
478 return sample_rate;
479 }
480
481