changeset 1954:2fd0a8cb1c80

Properly initialize Genesis reset cycle on startup. Fixes crash in GDB remote debugger when stepping past the first two instructions
author Michael Pavone <pavone@retrodev.com>
date Fri, 01 May 2020 00:54:15 -0700
parents 4af54c6ca3e6
children 1c7af12efe8b
files genesis.c render_fbdev.c
diffstat 2 files changed, 10 insertions(+), 252 deletions(-) [+]
line wrap: on
line diff
--- a/genesis.c	Thu Apr 30 23:33:55 2020 -0700
+++ b/genesis.c	Fri May 01 00:54:15 2020 -0700
@@ -1657,6 +1657,7 @@
 			gen->bank_regs[i] = i;
 		}
 	}
+	gen->reset_cycle = CYCLE_NEVER;
 
 	return gen;
 }
--- a/render_fbdev.c	Thu Apr 30 23:33:55 2020 -0700
+++ b/render_fbdev.c	Fri May 01 00:54:15 2020 -0700
@@ -50,200 +50,21 @@
 
 static uint32_t last_frame = 0;
 static snd_pcm_uframes_t buffer_samples;
+static size_t buffer_bytes;
 static unsigned int output_channels, sample_rate;
-static uint32_t missing_count;
 
 
 static uint8_t quitting = 0;
 
-struct audio_source {
-	int16_t  *front;
-	int16_t  *back;
-	double   dt;
-	uint64_t buffer_fraction;
-	uint64_t buffer_inc;
-	uint32_t buffer_pos;
-	uint32_t read_start;
-	uint32_t read_end;
-	uint32_t lowpass_alpha;
-	uint32_t mask;
-	int16_t  last_left;
-	int16_t  last_right;
-	uint8_t  num_channels;
-	uint8_t  front_populated;
-};
-
-static audio_source *audio_sources[8];
-static audio_source *inactive_audio_sources[8];
-static uint8_t num_audio_sources;
-static uint8_t num_inactive_audio_sources;
-static uint32_t min_buffered;
-
-typedef int32_t (*mix_func)(audio_source *audio, void *vstream, int len);
-
-static int32_t mix_s16(audio_source *audio, void *vstream, int len)
-{
-	int samples = len/(sizeof(int16_t)*output_channels);
-	int16_t *stream = vstream;
-	int16_t *end = stream + output_channels*samples;
-	int16_t *src = audio->front;
-	uint32_t i = audio->read_start;
-	uint32_t i_end = audio->read_end;
-	int16_t *cur = stream;
-	size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
-	if (audio->num_channels == 1) {
-		while (cur < end && i != i_end)
-		{
-			*cur += src[i];
-			cur += first_add;
-			*cur += src[i++];
-			cur += second_add;
-			i &= audio->mask;
-		}
-	} else {
-		while (cur < end && i != i_end)
-		{
-			*cur += src[i++];
-			cur += first_add;
-			*cur += src[i++];
-			cur += second_add;
-			i &= audio->mask;
-		}
-	}
-	
-	if (cur != end) {
-		printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
-	}
-	if (cur != end) {
-		//printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
-		return (cur-end)/2;
-	} else {
-		return ((i_end - i) & audio->mask) / audio->num_channels;
-	}
-}
-
-static int32_t mix_f32(audio_source *audio, void *vstream, int len)
-{
-	int samples = len/(sizeof(float)*output_channels);
-	float *stream = vstream;
-	float *end = stream + output_channels*samples;
-	int16_t *src = audio->front;
-	uint32_t i = audio->read_start;
-	uint32_t i_end = audio->read_end;
-	float *cur = stream;
-	size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
-	if (audio->num_channels == 1) {
-		while (cur < end && i != i_end)
-		{
-			*cur += ((float)src[i]) / 0x7FFF;
-			cur += first_add;
-			*cur += ((float)src[i++]) / 0x7FFF;
-			cur += second_add;
-			i &= audio->mask;
-		}
-	} else {
-		while(cur < end && i != i_end)
-		{
-			*cur += ((float)src[i++]) / 0x7FFF;
-			cur += first_add;
-			*cur += ((float)src[i++]) / 0x7FFF;
-			cur += second_add;
-			i &= audio->mask;
-		}
-	}
-	if (cur != end) {
-		printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
-		return (cur-end)/2;
-	} else {
-		return ((i_end - i) & audio->mask) / audio->num_channels;
-	}
-}
-
-static int32_t mix_null(audio_source *audio, void *vstream, int len)
-{
-	return 0;
-}
-
-static mix_func mix;
 
 static void render_close_audio()
 {
 
 }
 
-#define BUFFER_INC_RES 0x40000000UL
-
-void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider)
-{
-	src->buffer_inc = ((BUFFER_INC_RES * (uint64_t)sample_rate) / master_clock) * sample_divider;
-}
-
-audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels)
-{
-	audio_source *ret = NULL;
-	uint32_t alloc_size = channels * buffer_samples;
-	if (num_audio_sources < 8) {
-		ret = malloc(sizeof(audio_source));
-		ret->back = malloc(alloc_size * sizeof(int16_t));
-		ret->front = malloc(alloc_size * sizeof(int16_t));
-		ret->front_populated = 0;
-		ret->num_channels = channels;
-		audio_sources[num_audio_sources++] = ret;
-	}
-	if (!ret) {
-		fatal_error("Too many audio sources!");
-	} else {
-		render_audio_adjust_clock(ret, master_clock, sample_divider);
-		double lowpass_cutoff = get_lowpass_cutoff(config);
-		double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
-		ret->dt = 1.0 / ((double)master_clock / (double)(sample_divider));
-		double alpha = ret->dt / (ret->dt + rc);
-		ret->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
-		ret->buffer_pos = 0;
-		ret->buffer_fraction = 0;
-		ret->last_left = ret->last_right = 0;
-		ret->read_start = 0;
-		ret->read_end = buffer_samples * channels;
-		ret->mask = 0xFFFFFFFF;
-	}
-	return ret;
-}
-
-void render_pause_source(audio_source *src)
-{
-	for (uint8_t i = 0; i < num_audio_sources; i++)
-	{
-		if (audio_sources[i] == src) {
-			audio_sources[i] = audio_sources[--num_audio_sources];
-			break;
-		}
-	}
-	inactive_audio_sources[num_inactive_audio_sources++] = src;
-}
-
-void render_resume_source(audio_source *src)
-{
-	if (num_audio_sources < 8) {
-		audio_sources[num_audio_sources++] = src;
-	}
-	for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
-	{
-		if (inactive_audio_sources[i] == src) {
-			inactive_audio_sources[i] = inactive_audio_sources[--num_inactive_audio_sources];
-		}
-	}
-}
-
-void render_free_source(audio_source *src)
-{
-	render_pause_source(src);
-	
-	free(src->front);
-	free(src->back);
-	free(src);
-}
-snd_pcm_t *audio_handle;
-static void do_audio_ready(audio_source *src)
+static snd_pcm_t *audio_handle;
+static void *output_buffer;
+void render_do_audio_ready(audio_source *src)
 {
 	if (src->front_populated) {
 		fatal_error("Audio source filled up a buffer a second time before other sources finished their first\n");
@@ -254,22 +75,12 @@
 	src->front_populated = 1;
 	src->buffer_pos = 0;
 	
-	for (uint8_t i = 0; i < num_audio_sources; i++)
-	{
-		if (!audio_sources[i]->front_populated) {
-			//at least one audio source is not ready yet.
-			return;
-		}
+	if (!all_sources_ready()) {
+		return;
 	}
-	
-	size_t bytes = (mix == mix_s16 ? sizeof(int16_t) : sizeof(float)) * output_channels * buffer_samples;
-	void *buffer = malloc(bytes);
-	for (uint8_t i = 0; i < num_audio_sources; i++)
-	{
-		mix(audio_sources[i], buffer, bytes);
-		audio_sources[i]->front_populated = 0;
-	}
-	int frames = snd_pcm_writei(audio_handle, buffer, buffer_samples);
+	mix_and_convert(output_buffer, buffer_bytes, NULL);
+
+	int frames = snd_pcm_writei(audio_handle, output_buffer, buffer_samples);
 	if (frames < 0) {
 		frames = snd_pcm_recover(audio_handle, frames, 0);
 	}
@@ -278,60 +89,6 @@
 	}
 }
 
-static int16_t lowpass_sample(audio_source *src, int16_t last, int16_t current)
-{
-	int32_t tmp = current * src->lowpass_alpha + last * (0x10000 - src->lowpass_alpha);
-	current = tmp >> 16;
-	return current;
-}
-
-static void interp_sample(audio_source *src, int16_t last, int16_t current)
-{
-	int64_t tmp = last * ((src->buffer_fraction << 16) / src->buffer_inc);
-	tmp += current * (0x10000 - ((src->buffer_fraction << 16) / src->buffer_inc));
-	src->back[src->buffer_pos++] = tmp >> 16;
-}
-
-void render_put_mono_sample(audio_source *src, int16_t value)
-{
-	value = lowpass_sample(src, src->last_left, value);
-	src->buffer_fraction += src->buffer_inc;
-	uint32_t base = 0;
-	while (src->buffer_fraction > BUFFER_INC_RES)
-	{
-		src->buffer_fraction -= BUFFER_INC_RES;
-		interp_sample(src, src->last_left, value);
-		
-		if (((src->buffer_pos - base) & src->mask) >= buffer_samples) {
-			do_audio_ready(src);
-		}
-		src->buffer_pos &= src->mask;
-	}
-	src->last_left = value;
-}
-
-void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right)
-{
-	left = lowpass_sample(src, src->last_left, left);
-	right = lowpass_sample(src, src->last_right, right);
-	src->buffer_fraction += src->buffer_inc;
-	uint32_t base = 0;
-	while (src->buffer_fraction > BUFFER_INC_RES)
-	{
-		src->buffer_fraction -= BUFFER_INC_RES;
-		
-		interp_sample(src, src->last_left, left);
-		interp_sample(src, src->last_right, right);
-		
-		if (((src->buffer_pos - base) & src->mask)/2 >= buffer_samples) {
-			do_audio_ready(src);
-		}
-		src->buffer_pos &= src->mask;
-	}
-	src->last_left = left;
-	src->last_right = right;
-}
-
 int render_width()
 {
 	return main_width;