Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- a/libblastem.c Thu Apr 18 22:06:47 2019 -0700 +++ b/libblastem.c Sat Apr 18 11:42:53 2020 -0700 @@ -6,11 +6,40 @@ #include "vdp.h" #include "render.h" #include "io.h" +#include "genesis.h" +#include "sms.h" static retro_environment_t retro_environment; RETRO_API void retro_set_environment(retro_environment_t re) { retro_environment = re; +# define input_descriptor_macro(pad_num) \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "A" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "B" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "X" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Z" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "C" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, \ + { pad_num, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, \ + + static const struct retro_input_descriptor desc[] = { + input_descriptor_macro(0) + input_descriptor_macro(1) + input_descriptor_macro(2) + input_descriptor_macro(3) + input_descriptor_macro(4) + input_descriptor_macro(5) + input_descriptor_macro(6) + input_descriptor_macro(7) + { 0 }, + }; + + re(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, (void *)desc); } static retro_video_refresh_t retro_video_refresh; @@ -19,14 +48,14 @@ retro_video_refresh = rvf; } -static retro_audio_sample_t retro_audio_sample; RETRO_API void retro_set_audio_sample(retro_audio_sample_t ras) { - retro_audio_sample = ras; } +static retro_audio_sample_batch_t retro_audio_sample_batch; RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t rasb) { + retro_audio_sample_batch = rasb; } static retro_input_poll_t retro_input_poll; @@ -52,6 +81,7 @@ RETRO_API void retro_init(void) { + render_audio_initialized(RENDER_AUDIO_S16, 53693175 / (7 * 6 * 4), 2, 4, sizeof(int16_t)); } RETRO_API void retro_deinit(void) @@ -77,16 +107,46 @@ static vid_std video_standard; static uint32_t last_width, last_height; +static uint32_t overscan_top, overscan_bot, overscan_left, overscan_right; +static void update_overscan(void) +{ + uint8_t overscan; + retro_environment(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan); + if (overscan) { + overscan_top = overscan_bot = overscan_left = overscan_right = 0; + } else { + if (video_standard == VID_NTSC) { + overscan_top = 11; + overscan_bot = 8; + overscan_left = 13; + overscan_right = 14; + } else { + overscan_top = 30; + overscan_bot = 24; + overscan_left = 13; + overscan_right = 14; + } + } +} + +static int32_t sample_rate; RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info) { + update_overscan(); last_width = LINEBUF_SIZE; - info->geometry.base_width = info->geometry.max_width = LINEBUF_SIZE; - info->geometry.base_height = video_standard == VID_NTSC ? 243 : 294; + info->geometry.base_width = info->geometry.max_width = LINEBUF_SIZE - (overscan_left + overscan_right); + info->geometry.base_height = (video_standard == VID_NTSC ? 243 : 294) - (overscan_top + overscan_bot); last_height = info->geometry.base_height; info->geometry.max_height = info->geometry.base_height * 2; info->geometry.aspect_ratio = 0; - info->timing.fps = video_standard == VID_NTSC ? 60 : 50; - info->timing.sample_rate = 53267; //approximate sample rate of YM2612 + double master_clock = video_standard == VID_NTSC ? 53693175 : 53203395; + double lines = video_standard == VID_NTSC ? 262 : 313; + info->timing.fps = master_clock / (3420.0 * lines); + info->timing.sample_rate = master_clock / (7 * 6 * 24); //sample rate of YM2612 + sample_rate = info->timing.sample_rate; + render_audio_initialized(RENDER_AUDIO_S16, info->timing.sample_rate, 2, 4, sizeof(int16_t)); + //force adjustment of resampling parameters since target sample rate may have changed slightly + current_system->set_speed_percent(current_system, 100); } RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device) @@ -164,6 +224,7 @@ } /* Loads a game. */ +static system_type stype; RETRO_API bool retro_load_game(const struct retro_game_info *game) { serialize_size_cache = 0; @@ -175,10 +236,12 @@ media.buffer = malloc(nearest_pow2(game->size)); memcpy(media.buffer, game->data, game->size); media.size = game->size; - current_system = alloc_config_system(detect_system_type(&media), &media, 0, 0); + stype = detect_system_type(&media); + current_system = alloc_config_system(stype, &media, 0, 0); unsigned format = RETRO_PIXEL_FORMAT_XRGB8888; retro_environment(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &format); + return current_system != NULL; } @@ -211,11 +274,57 @@ /* Gets region of memory. */ RETRO_API void *retro_get_memory_data(unsigned id) { + switch (id) { + case RETRO_MEMORY_SYSTEM_RAM: + switch (stype) { + case SYSTEM_GENESIS: { + genesis_context *gen = (genesis_context *)current_system; + return (uint8_t *)gen->work_ram; + } +#ifndef NO_Z80 + case SYSTEM_SMS: { + sms_context *sms = (sms_context *)current_system; + return sms->ram; + } +#endif + } + break; + case RETRO_MEMORY_SAVE_RAM: + if (stype == SYSTEM_GENESIS) { + genesis_context *gen = (genesis_context *)current_system; + if (gen->save_type != SAVE_NONE) + return gen->save_storage; + } + break; + default: + break; + } return NULL; } RETRO_API size_t retro_get_memory_size(unsigned id) { + switch (id) { + case RETRO_MEMORY_SYSTEM_RAM: + switch (stype) { + case SYSTEM_GENESIS: + return RAM_WORDS * sizeof(uint16_t); +#ifndef NO_Z80 + case SYSTEM_SMS: + return SMS_RAM_SIZE; +#endif + } + break; + case RETRO_MEMORY_SAVE_RAM: + if (stype == SYSTEM_GENESIS) { + genesis_context *gen = (genesis_context *)current_system; + if (gen->save_type != SAVE_NONE) + return gen->save_size; + } + break; + default: + break; + } return 0; } @@ -254,7 +363,8 @@ void render_framebuffer_updated(uint8_t which, int width) { - unsigned height = video_standard == VID_NTSC ? 243 : 294; + unsigned height = (video_standard == VID_NTSC ? 243 : 294) - (overscan_top + overscan_bot); + width -= (overscan_left + overscan_right); unsigned base_height = height; if (which != last_fb) { height *= 2; @@ -270,7 +380,7 @@ last_width = width; last_height = height; } - retro_video_refresh(fb, width, height, LINEBUF_SIZE * sizeof(uint32_t)); + retro_video_refresh(fb + overscan_left + LINEBUF_SIZE * overscan_top, width, height, LINEBUF_SIZE * sizeof(uint32_t)); current_system->request_exit(current_system); } @@ -289,6 +399,16 @@ return 1; } +uint32_t render_overscan_top() +{ + return overscan_top; +} + +uint32_t render_overscan_bot() +{ + return overscan_bot; +} + void process_events() { static int16_t prev_state[2][RETRO_DEVICE_ID_JOYPAD_L2]; @@ -326,77 +446,70 @@ { } -struct audio_source { - int32_t freq; - int32_t left_accum; - int32_t right_accum; - int32_t num_samples; -}; +uint8_t render_is_audio_sync(void) +{ + //whether this is true depends on the libretro frontend implementation + //but the sync to audio path works better here + return 1; +} -static audio_source *audio_sources[8]; -static uint8_t num_audio_sources; -audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels) +void render_buffer_consumed(audio_source *src) { - audio_sources[num_audio_sources] = calloc(1, sizeof(audio_source)); - audio_sources[num_audio_sources]->freq = master_clock / sample_divider; - return audio_sources[num_audio_sources++]; } -void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider) +void *render_new_audio_opaque(void) +{ + return NULL; +} + +void render_free_audio_opaque(void *opaque) +{ +} + +void render_lock_audio(void) +{ +} + +void render_unlock_audio() { } -void render_audio_source_gaindb(audio_source *src, float gain) +uint32_t render_min_buffered(void) { - //TODO: Implement this once I hook up a core option for individual FM/PSG gain + //not actually used in the sync to audio path + return 4; } -static void check_put_sample(void) +uint32_t render_audio_syncs_per_sec(void) { - for (int i = 0; i < num_audio_sources; i++) - { - int32_t min_samples = audio_sources[i]->freq / 53267; - if (audio_sources[i]->num_samples < min_samples) { - return; - } - } - int16_t left = 0, right = 0; - for (int i = 0; i < num_audio_sources; i++) - { - left += audio_sources[i]->left_accum / audio_sources[i]->num_samples; - right += audio_sources[i]->right_accum / audio_sources[i]->num_samples; - audio_sources[i]->left_accum = audio_sources[i]->right_accum = audio_sources[i]->num_samples = 0; - } - retro_audio_sample(left, right); + return 0; +} + +void render_audio_created(audio_source *src) +{ } -void render_put_mono_sample(audio_source *src, int16_t value) +void render_do_audio_ready(audio_source *src) { - src->left_accum += value; - src->right_accum += value; - src->num_samples++; - check_put_sample(); -} -void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right) -{ - src->left_accum += left; - src->right_accum += right; - src->num_samples++; - check_put_sample(); + int16_t *tmp = src->front; + src->front = src->back; + src->back = tmp; + src->front_populated = 1; + src->buffer_pos = 0; + if (all_sources_ready()) { + int16_t buffer[8]; + int min_remaining_out; + mix_and_convert((uint8_t *)buffer, sizeof(buffer), &min_remaining_out); + retro_audio_sample_batch(buffer, sizeof(buffer)/(2*sizeof(*buffer))); + } } -void render_free_source(audio_source *src) +void render_source_paused(audio_source *src, uint8_t remaining_sources) { - int index; - for (index = 0; index < num_audio_sources; index++) - { - if (audio_sources[index] == src) { - break; - } - } - num_audio_sources--; - audio_sources[index] = audio_sources[num_audio_sources]; - free(src); +} + +void render_source_resumed(audio_source *src) +{ } void bindings_set_mouse_mode(uint8_t mode)