diff ym2612.c @ 1904:8312e574100a

Implement selectable YM2612/YM3834 invalid status port behavior
author Michael Pavone <pavone@retrodev.com>
date Wed, 26 Feb 2020 22:40:37 -0800
parents 32a3aa7b4a45
children 508522f08e4d
line wrap: on
line diff
--- a/ym2612.c	Tue Feb 25 20:03:04 2020 -0800
+++ b/ym2612.c	Wed Feb 26 22:40:37 2020 -0800
@@ -133,6 +133,12 @@
 	} else {
 		context->busy_start = CYCLE_NEVER;
 	}
+	if (context->last_status_cycle != CYCLE_NEVER && context->last_status_cycle >= deduction) {
+		context->last_status_cycle -= deduction;
+	} else {
+		context->last_status = 0;
+		context->last_status_cycle = CYCLE_NEVER;
+	}
 }
 
 #ifdef __ANDROID__
@@ -188,6 +194,9 @@
 	context->clock_inc = clock_div * 6;
 	context->busy_cycles = BUSY_CYCLES * context->clock_inc;
 	context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2);
+	//TODO: pick a randomish high initial value and lower it over time
+	context->invalid_status_decay = 225000 * context->clock_inc;
+	context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3;
 	
 	//some games seem to expect that the LR flags start out as 1
 	for (int i = 0; i < NUM_CHANNELS; i++) {
@@ -1117,13 +1126,25 @@
 	}
 }
 
-uint8_t ym_read_status(ym2612_context * context, uint32_t cycle)
+uint8_t ym_read_status(ym2612_context * context, uint32_t cycle, uint32_t port)
 {
-	uint8_t status = context->status;
-	if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) {
-		status |= 0x80;
+	uint8_t status;
+	port &= context->status_address_mask;
+	if (port) {
+		if (context->last_status_cycle != CYCLE_NEVER && cycle - context->last_status_cycle > context->invalid_status_decay) {
+			context->last_status = 0;
+		}
+		status = context->last_status;
+	} else {
+		status = context->status;
+		if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) {
+			status |= 0x80;
+		}
+		context->last_status = status;
+		context->last_status_cycle = cycle;
 	}
 	return status;
+		
 }
 
 void ym_print_channel_info(ym2612_context *context, int channel)
@@ -1236,6 +1257,9 @@
 	save_int32(buf, context->current_cycle);
 	save_int32(buf, context->write_cycle);
 	save_int32(buf, context->busy_start);
+	save_int32(buf, context->last_status_cycle);
+	save_int32(buf, context->invalid_status_decay);
+	save_int8(buf, context->last_status);
 }
 
 void ym_deserialize(deserialize_buffer *buf, void *vcontext)
@@ -1311,4 +1335,12 @@
 	context->current_cycle = load_int32(buf);
 	context->write_cycle = load_int32(buf);
 	context->busy_start = load_int32(buf);
+	if (buf->size > buf->cur_pos) {
+		context->last_status_cycle = load_int32(buf);
+		context->invalid_status_decay = load_int32(buf);
+		context->last_status = load_int8(buf);
+	} else {
+		context->last_status = context->status;
+		context->last_status_cycle = context->write_cycle;
+	}
 }