changeset 2707:a64c0e1ed6ac default tip

Implement speed control and reset for media player. Fix other bindings that could cause it to crash
author Michael Pavone <pavone@retrodev.com>
date Sun, 06 Jul 2025 20:43:37 -0700
parents 0bd48217941a
children
files bindings.c mediaplayer.c mediaplayer.h
diffstat 3 files changed, 83 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/bindings.c	Sun Jul 06 20:09:32 2025 -0700
+++ b/bindings.c	Sun Jul 06 20:43:37 2025 -0700
@@ -354,7 +354,7 @@
 			}
 			break;
 		case UI_LOAD_STATE:
-			if (allow_content_binds) {
+			if (allow_content_binds && current_system->load_state) {
 				current_system->load_state(current_system, QUICK_SAVE_SLOT);
 			}
 			break;
@@ -478,27 +478,6 @@
 		case UI_CD_GRAPHICS_DEBUG:
 			if (allow_content_binds && current_system->toggle_debug_view) {
 				current_system->toggle_debug_view(current_system, binding->subtype_a - UI_PLANE_DEBUG + DEBUG_PLANE);
-				/*
-				vdp_context *vdp = NULL;
-				if (current_system->type == SYSTEM_GENESIS || current_system->type == SYSTEM_SEGACD) {
-					genesis_context *gen = (genesis_context *)current_system;
-					vdp = gen->vdp;
-				} else if (current_system->type == SYSTEM_SMS) {
-					sms_context *sms = (sms_context *)current_system;
-					vdp = sms->vdp;
-				}
-				if (vdp) {
-					uint8_t debug_type;
-					switch(binding->subtype_a)
-					{
-					case UI_PLANE_DEBUG: debug_type = VDP_DEBUG_PLANE; break;
-					case UI_VRAM_DEBUG: debug_type = VDP_DEBUG_VRAM; break;
-					case UI_CRAM_DEBUG: debug_type = VDP_DEBUG_CRAM; break;
-					case UI_COMPOSITE_DEBUG: debug_type = VDP_DEBUG_COMPOSITE; break;
-					default: return;
-					}
-					vdp_toggle_debug_view(vdp, debug_type);
-				}*/
 				break;
 			}
 		case UI_PASTE:
--- a/mediaplayer.c	Sun Jul 06 20:09:32 2025 -0700
+++ b/mediaplayer.c	Sun Jul 06 20:43:37 2025 -0700
@@ -45,6 +45,11 @@
 	}
 }
 
+void ym_adjust_clock(chip_info *chip, uint32_t percent)
+{
+	ym_adjust_master_clock(chip->context, chip->clock * percent / 100);
+}
+
 void ym_scope(chip_info *chip, oscilloscope *scope)
 {
 	ym_enable_scope(chip->context, scope, chip->clock);
@@ -77,6 +82,11 @@
 	}
 }
 
+void psg_adjust_clock(chip_info *chip, uint32_t percent)
+{
+	psg_adjust_master_clock(chip->context, chip->clock * percent / 100);
+}
+
 void psg_scope(chip_info *chip, oscilloscope *scope)
 {
 	psg_enable_scope(chip->context, scope, chip->clock);
@@ -98,6 +108,11 @@
 	}
 }
 
+void pcm_adjust_clock(chip_info *chip, uint32_t percent)
+{
+	rf5c164_adjust_master_clock(chip->context, chip->clock * percent / 100);
+}
+
 void pcm_scope(chip_info *chip, oscilloscope *scope)
 {
 	rf5c164_enable_scope(chip->context, scope);
@@ -691,15 +706,20 @@
 	return;
 }
 
+static void wave_stop(media_player *player)
+{
+	player->current_offset = player->wave->format_header.size + offsetof(wave_header, audio_format);
+	player->state = STATE_PAUSED;
+	player->playback_time = 0;
+}
+
 void wave_frame(media_player *player)
 {
 	for (uint32_t remaining_samples = player->wave->sample_rate / 60; remaining_samples > 0; remaining_samples--)
 	{
 		uint32_t sample_size = player->wave->bits_per_sample * player->wave->num_channels / 8;
 		if (sample_size > player->media->size || player->current_offset > player->media->size - sample_size) {
-			player->current_offset = player->wave->format_header.size + offsetof(wave_header, audio_format);
-			player->state = STATE_PAUSED;
-			player->playback_time = 0;
+			wave_stop(player);
 			return;
 		}
 		if (player->wave->bits_per_sample == 16) {
@@ -725,6 +745,13 @@
 	}
 }
 
+static void flac_stop(media_player *player)
+{
+	player->state = STATE_PAUSED;
+	player->playback_time = 0;
+	flac_seek(player->flac, 0);
+}
+
 void flac_frame(media_player *player)
 {
 	for (uint32_t remaining_samples = player->flac->sample_rate / 60; remaining_samples > 0; remaining_samples--)
@@ -733,8 +760,7 @@
 		if (flac_get_sample(player->flac, samples, 2)) {
 			render_put_stereo_sample(player->audio, samples[0], samples[1]);
 		} else {
-			player->state = STATE_PAUSED;
-			player->playback_time = 0;
+			flac_stop(player);
 			return;
 		}
 	}
@@ -785,6 +811,7 @@
 			.context = ym,
 			.run = (chip_run_fun)ym_run,
 			.adjust = ym_adjust,
+			.adjust_clock = ym_adjust_clock,
 			.scope = ym_scope,
 			.no_scope = ym_no_scope,
 			.free = (chip_noarg_fun)ym_free,
@@ -803,6 +830,7 @@
 			.context = psg,
 			.run = (chip_run_fun)psg_run,
 			.adjust = psg_adjust,
+			.adjust_clock = psg_adjust_clock,
 			.scope = psg_scope,
 			.no_scope = ym_no_scope,
 			.free = (chip_noarg_fun)psg_free,
@@ -820,6 +848,7 @@
 			.context = pcm,
 			.run = (chip_run_fun)rf5c164_run,
 			.adjust = pcm_adjust,
+			.adjust_clock = pcm_adjust_clock,
 			.scope = pcm_scope,
 			.no_scope = pcm_no_scope,
 			.free = pcm_free,
@@ -837,6 +866,7 @@
 			.context = pcm,
 			.run = (chip_run_fun)rf5c164_run,
 			.adjust = pcm_adjust,
+			.adjust_clock = pcm_adjust_clock,
 			.scope = pcm_scope,
 			.no_scope = pcm_no_scope,
 			.free = pcm_free,
@@ -1027,16 +1057,61 @@
 #endif
 }
 
+static void inc_debug_mode(system_header * system)
+{
+}
+
+static void soft_reset(system_header * system)
+{
+	media_player *player = (media_player *)system;
+	switch(player->media_type)
+	{
+	case AUDIO_VGM:
+		vgm_stop(player);
+		break;
+	case AUDIO_WAVE:
+		wave_stop(player);
+		break;
+	case AUDIO_FLAC:
+		flac_stop(player);
+		break;
+	}
+	player->state = STATE_PLAY;
+}
+
+static void set_speed_percent(system_header * system, uint32_t percent)
+{
+	media_player *player = (media_player *)system;
+	switch(player->media_type)
+	{
+	case AUDIO_VGM:
+		for (uint32_t i = 0; i < player->num_chips; i++)
+		{
+			player->chips[i].adjust_clock(player->chips + i, percent);
+		}
+		break;
+	case AUDIO_WAVE:
+		render_audio_adjust_clock(player->audio, player->wave->sample_rate * percent / 100, 1);
+		break;
+	case AUDIO_FLAC:
+		render_audio_adjust_clock(player->audio, player->wave->sample_rate * percent / 100, 1);
+		break;
+	}
+}
+
 media_player *alloc_media_player(system_media *media, uint32_t opts)
 {
 	media_player *player = calloc(1, sizeof(media_player));
 	player->header.start_context = start_player;
 	player->header.resume_context = resume_player;
 	player->header.request_exit = request_exit;
+	player->header.soft_reset = soft_reset;
 	player->header.free_context = free_player;
+	player->header.set_speed_percent = set_speed_percent;
 	player->header.gamepad_down = gamepad_down;
 	player->header.gamepad_up = gamepad_up;
 	player->header.toggle_debug_view = toggle_debug_view;
+	player->header.inc_debug_mode = inc_debug_mode;
 	player->header.type = SYSTEM_MEDIA_PLAYER;
 	player->header.info.name = strdup(media->name);
 
--- a/mediaplayer.h	Sun Jul 06 20:09:32 2025 -0700
+++ b/mediaplayer.h	Sun Jul 06 20:43:37 2025 -0700
@@ -15,11 +15,13 @@
 typedef void (*chip_scope_fun)(chip_info *chip, oscilloscope *scope);
 typedef void (*chip_noarg_fun)(void *context);
 typedef void (*chip_adjust_fun)(chip_info *chip);
+typedef void (*chip_clock_fun)(chip_info *chip, uint32_t percent);
 typedef void (*chip_stream_fun)(chip_info *chip, uint8_t port, uint8_t command, uint16_t sample);
 struct chip_info {
 	void            *context;
 	chip_run_fun    run;
 	chip_adjust_fun adjust;
+	chip_clock_fun  adjust_clock;
 	chip_scope_fun  scope;
 	chip_noarg_fun  no_scope;
 	chip_noarg_fun  free;