comparison libblastem.c @ 1931:374a5ae694e8 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 18 Apr 2020 11:42:53 -0700
parents 9fd4bedc1a31
children b387f1c5a1d0
comparison
equal deleted inserted replaced
1843:13abdc98379e 1931:374a5ae694e8
4 #include "system.h" 4 #include "system.h"
5 #include "util.h" 5 #include "util.h"
6 #include "vdp.h" 6 #include "vdp.h"
7 #include "render.h" 7 #include "render.h"
8 #include "io.h" 8 #include "io.h"
9 #include "genesis.h"
10 #include "sms.h"
9 11
10 static retro_environment_t retro_environment; 12 static retro_environment_t retro_environment;
11 RETRO_API void retro_set_environment(retro_environment_t re) 13 RETRO_API void retro_set_environment(retro_environment_t re)
12 { 14 {
13 retro_environment = re; 15 retro_environment = re;
16 # define input_descriptor_macro(pad_num) \
17 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, \
18 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, \
19 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, \
20 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, \
21 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "A" }, \
22 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "B" }, \
23 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, \
24 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "X" }, \
25 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Z" }, \
26 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "C" }, \
27 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, \
28 { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, \
29
30 static const struct retro_input_descriptor desc[] = {
31 input_descriptor_macro(0)
32 input_descriptor_macro(1)
33 input_descriptor_macro(2)
34 input_descriptor_macro(3)
35 input_descriptor_macro(4)
36 input_descriptor_macro(5)
37 input_descriptor_macro(6)
38 input_descriptor_macro(7)
39 { 0 },
40 };
41
42 re(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, (void *)desc);
14 } 43 }
15 44
16 static retro_video_refresh_t retro_video_refresh; 45 static retro_video_refresh_t retro_video_refresh;
17 RETRO_API void retro_set_video_refresh(retro_video_refresh_t rvf) 46 RETRO_API void retro_set_video_refresh(retro_video_refresh_t rvf)
18 { 47 {
19 retro_video_refresh = rvf; 48 retro_video_refresh = rvf;
20 } 49 }
21 50
22 static retro_audio_sample_t retro_audio_sample;
23 RETRO_API void retro_set_audio_sample(retro_audio_sample_t ras) 51 RETRO_API void retro_set_audio_sample(retro_audio_sample_t ras)
24 { 52 {
25 retro_audio_sample = ras; 53 }
26 } 54
27 55 static retro_audio_sample_batch_t retro_audio_sample_batch;
28 RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t rasb) 56 RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t rasb)
29 { 57 {
58 retro_audio_sample_batch = rasb;
30 } 59 }
31 60
32 static retro_input_poll_t retro_input_poll; 61 static retro_input_poll_t retro_input_poll;
33 RETRO_API void retro_set_input_poll(retro_input_poll_t rip) 62 RETRO_API void retro_set_input_poll(retro_input_poll_t rip)
34 { 63 {
50 system_header *current_system; 79 system_header *current_system;
51 system_media media; 80 system_media media;
52 81
53 RETRO_API void retro_init(void) 82 RETRO_API void retro_init(void)
54 { 83 {
84 render_audio_initialized(RENDER_AUDIO_S16, 53693175 / (7 * 6 * 4), 2, 4, sizeof(int16_t));
55 } 85 }
56 86
57 RETRO_API void retro_deinit(void) 87 RETRO_API void retro_deinit(void)
58 { 88 {
59 if (current_system) { 89 if (current_system) {
75 info->block_extract = 0; 105 info->block_extract = 0;
76 } 106 }
77 107
78 static vid_std video_standard; 108 static vid_std video_standard;
79 static uint32_t last_width, last_height; 109 static uint32_t last_width, last_height;
110 static uint32_t overscan_top, overscan_bot, overscan_left, overscan_right;
111 static void update_overscan(void)
112 {
113 uint8_t overscan;
114 retro_environment(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan);
115 if (overscan) {
116 overscan_top = overscan_bot = overscan_left = overscan_right = 0;
117 } else {
118 if (video_standard == VID_NTSC) {
119 overscan_top = 11;
120 overscan_bot = 8;
121 overscan_left = 13;
122 overscan_right = 14;
123 } else {
124 overscan_top = 30;
125 overscan_bot = 24;
126 overscan_left = 13;
127 overscan_right = 14;
128 }
129 }
130 }
131
132 static int32_t sample_rate;
80 RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info) 133 RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info)
81 { 134 {
135 update_overscan();
82 last_width = LINEBUF_SIZE; 136 last_width = LINEBUF_SIZE;
83 info->geometry.base_width = info->geometry.max_width = LINEBUF_SIZE; 137 info->geometry.base_width = info->geometry.max_width = LINEBUF_SIZE - (overscan_left + overscan_right);
84 info->geometry.base_height = video_standard == VID_NTSC ? 243 : 294; 138 info->geometry.base_height = (video_standard == VID_NTSC ? 243 : 294) - (overscan_top + overscan_bot);
85 last_height = info->geometry.base_height; 139 last_height = info->geometry.base_height;
86 info->geometry.max_height = info->geometry.base_height * 2; 140 info->geometry.max_height = info->geometry.base_height * 2;
87 info->geometry.aspect_ratio = 0; 141 info->geometry.aspect_ratio = 0;
88 info->timing.fps = video_standard == VID_NTSC ? 60 : 50; 142 double master_clock = video_standard == VID_NTSC ? 53693175 : 53203395;
89 info->timing.sample_rate = 53267; //approximate sample rate of YM2612 143 double lines = video_standard == VID_NTSC ? 262 : 313;
144 info->timing.fps = master_clock / (3420.0 * lines);
145 info->timing.sample_rate = master_clock / (7 * 6 * 24); //sample rate of YM2612
146 sample_rate = info->timing.sample_rate;
147 render_audio_initialized(RENDER_AUDIO_S16, info->timing.sample_rate, 2, 4, sizeof(int16_t));
148 //force adjustment of resampling parameters since target sample rate may have changed slightly
149 current_system->set_speed_percent(current_system, 100);
90 } 150 }
91 151
92 RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device) 152 RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device)
93 { 153 {
94 } 154 }
162 RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code) 222 RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code)
163 { 223 {
164 } 224 }
165 225
166 /* Loads a game. */ 226 /* Loads a game. */
227 static system_type stype;
167 RETRO_API bool retro_load_game(const struct retro_game_info *game) 228 RETRO_API bool retro_load_game(const struct retro_game_info *game)
168 { 229 {
169 serialize_size_cache = 0; 230 serialize_size_cache = 0;
170 if (game->path) { 231 if (game->path) {
171 media.dir = path_dirname(game->path); 232 media.dir = path_dirname(game->path);
173 media.extension = path_extension(game->path); 234 media.extension = path_extension(game->path);
174 } 235 }
175 media.buffer = malloc(nearest_pow2(game->size)); 236 media.buffer = malloc(nearest_pow2(game->size));
176 memcpy(media.buffer, game->data, game->size); 237 memcpy(media.buffer, game->data, game->size);
177 media.size = game->size; 238 media.size = game->size;
178 current_system = alloc_config_system(detect_system_type(&media), &media, 0, 0); 239 stype = detect_system_type(&media);
240 current_system = alloc_config_system(stype, &media, 0, 0);
179 241
180 unsigned format = RETRO_PIXEL_FORMAT_XRGB8888; 242 unsigned format = RETRO_PIXEL_FORMAT_XRGB8888;
181 retro_environment(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &format); 243 retro_environment(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &format);
244
182 return current_system != NULL; 245 return current_system != NULL;
183 } 246 }
184 247
185 /* Loads a "special" kind of game. Should not be used, 248 /* Loads a "special" kind of game. Should not be used,
186 * except in extreme cases. */ 249 * except in extreme cases. */
209 } 272 }
210 273
211 /* Gets region of memory. */ 274 /* Gets region of memory. */
212 RETRO_API void *retro_get_memory_data(unsigned id) 275 RETRO_API void *retro_get_memory_data(unsigned id)
213 { 276 {
277 switch (id) {
278 case RETRO_MEMORY_SYSTEM_RAM:
279 switch (stype) {
280 case SYSTEM_GENESIS: {
281 genesis_context *gen = (genesis_context *)current_system;
282 return (uint8_t *)gen->work_ram;
283 }
284 #ifndef NO_Z80
285 case SYSTEM_SMS: {
286 sms_context *sms = (sms_context *)current_system;
287 return sms->ram;
288 }
289 #endif
290 }
291 break;
292 case RETRO_MEMORY_SAVE_RAM:
293 if (stype == SYSTEM_GENESIS) {
294 genesis_context *gen = (genesis_context *)current_system;
295 if (gen->save_type != SAVE_NONE)
296 return gen->save_storage;
297 }
298 break;
299 default:
300 break;
301 }
214 return NULL; 302 return NULL;
215 } 303 }
216 304
217 RETRO_API size_t retro_get_memory_size(unsigned id) 305 RETRO_API size_t retro_get_memory_size(unsigned id)
218 { 306 {
307 switch (id) {
308 case RETRO_MEMORY_SYSTEM_RAM:
309 switch (stype) {
310 case SYSTEM_GENESIS:
311 return RAM_WORDS * sizeof(uint16_t);
312 #ifndef NO_Z80
313 case SYSTEM_SMS:
314 return SMS_RAM_SIZE;
315 #endif
316 }
317 break;
318 case RETRO_MEMORY_SAVE_RAM:
319 if (stype == SYSTEM_GENESIS) {
320 genesis_context *gen = (genesis_context *)current_system;
321 if (gen->save_type != SAVE_NONE)
322 return gen->save_size;
323 }
324 break;
325 default:
326 break;
327 }
219 return 0; 328 return 0;
220 } 329 }
221 330
222 //blastem render backend API implementation 331 //blastem render backend API implementation
223 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) 332 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
252 } 361 }
253 } 362 }
254 363
255 void render_framebuffer_updated(uint8_t which, int width) 364 void render_framebuffer_updated(uint8_t which, int width)
256 { 365 {
257 unsigned height = video_standard == VID_NTSC ? 243 : 294; 366 unsigned height = (video_standard == VID_NTSC ? 243 : 294) - (overscan_top + overscan_bot);
367 width -= (overscan_left + overscan_right);
258 unsigned base_height = height; 368 unsigned base_height = height;
259 if (which != last_fb) { 369 if (which != last_fb) {
260 height *= 2; 370 height *= 2;
261 last_fb = which; 371 last_fb = which;
262 } 372 }
268 }; 378 };
269 retro_environment(RETRO_ENVIRONMENT_SET_GEOMETRY, &geometry); 379 retro_environment(RETRO_ENVIRONMENT_SET_GEOMETRY, &geometry);
270 last_width = width; 380 last_width = width;
271 last_height = height; 381 last_height = height;
272 } 382 }
273 retro_video_refresh(fb, width, height, LINEBUF_SIZE * sizeof(uint32_t)); 383 retro_video_refresh(fb + overscan_left + LINEBUF_SIZE * overscan_top, width, height, LINEBUF_SIZE * sizeof(uint32_t));
274 current_system->request_exit(current_system); 384 current_system->request_exit(current_system);
275 } 385 }
276 386
277 uint8_t render_get_active_framebuffer(void) 387 uint8_t render_get_active_framebuffer(void)
278 { 388 {
285 } 395 }
286 396
287 int render_fullscreen(void) 397 int render_fullscreen(void)
288 { 398 {
289 return 1; 399 return 1;
400 }
401
402 uint32_t render_overscan_top()
403 {
404 return overscan_top;
405 }
406
407 uint32_t render_overscan_bot()
408 {
409 return overscan_bot;
290 } 410 }
291 411
292 void process_events() 412 void process_events()
293 { 413 {
294 static int16_t prev_state[2][RETRO_DEVICE_ID_JOYPAD_L2]; 414 static int16_t prev_state[2][RETRO_DEVICE_ID_JOYPAD_L2];
324 } 444 }
325 void render_infobox(char *title, char *message) 445 void render_infobox(char *title, char *message)
326 { 446 {
327 } 447 }
328 448
329 struct audio_source { 449 uint8_t render_is_audio_sync(void)
330 int32_t freq; 450 {
331 int32_t left_accum; 451 //whether this is true depends on the libretro frontend implementation
332 int32_t right_accum; 452 //but the sync to audio path works better here
333 int32_t num_samples; 453 return 1;
334 }; 454 }
335 455
336 static audio_source *audio_sources[8]; 456 void render_buffer_consumed(audio_source *src)
337 static uint8_t num_audio_sources; 457 {
338 audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels) 458 }
339 { 459
340 audio_sources[num_audio_sources] = calloc(1, sizeof(audio_source)); 460 void *render_new_audio_opaque(void)
341 audio_sources[num_audio_sources]->freq = master_clock / sample_divider; 461 {
342 return audio_sources[num_audio_sources++]; 462 return NULL;
343 } 463 }
344 464
345 void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider) 465 void render_free_audio_opaque(void *opaque)
346 { 466 {
347 } 467 }
348 468
349 void render_audio_source_gaindb(audio_source *src, float gain) 469 void render_lock_audio(void)
350 { 470 {
351 //TODO: Implement this once I hook up a core option for individual FM/PSG gain 471 }
352 } 472
353 473 void render_unlock_audio()
354 static void check_put_sample(void) 474 {
355 { 475 }
356 for (int i = 0; i < num_audio_sources; i++) 476
357 { 477 uint32_t render_min_buffered(void)
358 int32_t min_samples = audio_sources[i]->freq / 53267; 478 {
359 if (audio_sources[i]->num_samples < min_samples) { 479 //not actually used in the sync to audio path
360 return; 480 return 4;
361 } 481 }
362 } 482
363 int16_t left = 0, right = 0; 483 uint32_t render_audio_syncs_per_sec(void)
364 for (int i = 0; i < num_audio_sources; i++) 484 {
365 { 485 return 0;
366 left += audio_sources[i]->left_accum / audio_sources[i]->num_samples; 486 }
367 right += audio_sources[i]->right_accum / audio_sources[i]->num_samples; 487
368 audio_sources[i]->left_accum = audio_sources[i]->right_accum = audio_sources[i]->num_samples = 0; 488 void render_audio_created(audio_source *src)
369 } 489 {
370 retro_audio_sample(left, right); 490 }
371 } 491
372 492 void render_do_audio_ready(audio_source *src)
373 void render_put_mono_sample(audio_source *src, int16_t value) 493 {
374 { 494 int16_t *tmp = src->front;
375 src->left_accum += value; 495 src->front = src->back;
376 src->right_accum += value; 496 src->back = tmp;
377 src->num_samples++; 497 src->front_populated = 1;
378 check_put_sample(); 498 src->buffer_pos = 0;
379 } 499 if (all_sources_ready()) {
380 void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right) 500 int16_t buffer[8];
381 { 501 int min_remaining_out;
382 src->left_accum += left; 502 mix_and_convert((uint8_t *)buffer, sizeof(buffer), &min_remaining_out);
383 src->right_accum += right; 503 retro_audio_sample_batch(buffer, sizeof(buffer)/(2*sizeof(*buffer)));
384 src->num_samples++; 504 }
385 check_put_sample(); 505 }
386 } 506
387 507 void render_source_paused(audio_source *src, uint8_t remaining_sources)
388 void render_free_source(audio_source *src) 508 {
389 { 509 }
390 int index; 510
391 for (index = 0; index < num_audio_sources; index++) 511 void render_source_resumed(audio_source *src)
392 { 512 {
393 if (audio_sources[index] == src) {
394 break;
395 }
396 }
397 num_audio_sources--;
398 audio_sources[index] = audio_sources[num_audio_sources];
399 free(src);
400 } 513 }
401 514
402 void bindings_set_mouse_mode(uint8_t mode) 515 void bindings_set_mouse_mode(uint8_t mode)
403 { 516 {
404 } 517 }