changeset 508:b976c6d6e5fb

Initial attempt at emulating extended bank area access delays when 68K bus is busy with VDP stuff. Also emulate the extra delay on the second access of a word-wide read to the bank area. Needs work as it seems to break stuff.
author Michael Pavone <pavone@retrodev.com>
date Mon, 03 Feb 2014 09:18:10 -0800
parents cc6030bd04c6
children b3738ee58195
files blastem.c blastem.h zruntime.S
diffstat 3 files changed, 74 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Tue Jan 28 08:36:06 2014 -0800
+++ b/blastem.c	Mon Feb 03 09:18:10 2014 -0800
@@ -312,10 +312,12 @@
 	//printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle);
 	sync_components(context, 0);
 	vdp_context * v_context = context->video_context;
+	genesis_context * gen = context->system;
 	if (vdp_port < 0x10) {
 		int blocked;
 		uint32_t before_cycle = v_context->cycles;
 		if (vdp_port < 4) {
+			gen->bus_busy = 1;
 			while (vdp_data_port_write(v_context, value) < 0) {
 				while(v_context->flags & FLAG_DMA_RUN) {
 					vdp_run_dma_done(v_context, mclks_per_frame);
@@ -347,6 +349,7 @@
 				//context->current_cycle = v_context->cycles / MCLKS_PER_68K;
 			}
 		} else if(vdp_port < 8) {
+			gen->bus_busy = 1;
 			blocked = vdp_control_port_write(v_context, value);
 			if (blocked) {
 				while (blocked) {
@@ -394,12 +397,17 @@
 			context->current_cycle = v_context->cycles / MCLKS_PER_68K;
 		}
 	} else if (vdp_port < 0x18) {
-		genesis_context * gen = context->system;
 		sync_sound(gen, context->current_cycle * MCLKS_PER_68K);
 		psg_write(gen->psg, value);
 	} else {
 		//TODO: Implement undocumented test register(s)
 	}
+	if (gen->bus_busy)
+	{
+		//Lock the Z80 out of the bus until the VDP access is complete
+		sync_z80(gen->z80, v_context->cycles);
+		gen->bus_busy = 0;
+	}
 	return context;
 }
 
--- a/blastem.h	Tue Jan 28 08:36:06 2014 -0800
+++ b/blastem.h	Mon Feb 03 09:18:10 2014 -0800
@@ -34,6 +34,7 @@
 	uint32_t       normal_clock; //Normal master clock (used to restore master clock after turbo mode)
 	uint8_t        bank_regs[8];
 	io_port        ports[3];
+	uint8_t        bus_busy;
 } genesis_context;
 
 extern genesis_context * genesis;
--- a/zruntime.S	Tue Jan 28 08:36:06 2014 -0800
+++ b/zruntime.S	Mon Feb 03 09:18:10 2014 -0800
@@ -34,6 +34,21 @@
 	pop %rbx
 	ret /* return to caller of z80_run */
 
+forced_sync:
+	movw $0, 164(%rsi)
+	call z80_save_context_scratch
+	pop %rax /*return address in read/write func*/
+	pop 104(%rsi) /*return address in native code*/
+	mov %rax, (%rsi)
+
+	pop %r15 /* restore callee saved regsiters */
+	pop %r14
+	pop %r13
+	pop %r12
+	pop %rbp
+	pop %rbx
+	ret /* return to caller of z80_run */
+
 	.global z80_handle_cycle_limit_int
 z80_handle_cycle_limit_int:
 	cmp 116(%rsi), %ebp
@@ -107,8 +122,14 @@
 	mov (%r11, %r13), %r13b
 	ret
 z80_read_bank:
-	/* approximation of wait states for 68K bus access */
+	push %rsi
+	mov 144(%rsi), %rsi /* get system context pointer */
+	cmp $0, 120(%rsi) /* check bus busy flag */
+	pop %rsi
+	jne bus_busy
+	/* approximation of wait states for normal 68K bus access */
 	add $3, %ebp
+z80_read_bank_cont:
 	and $0x7FFF, %r13
 	cmp $0, %r12
 	je slow_bank_read
@@ -119,6 +140,10 @@
 slow_bank_read:
 	/* TODO: Call into C to implement this */
 	ret
+bus_busy:
+	mov %edi, %ebp
+	call forced_sync
+	jp z80_read_bank_cont
 z80_read_ym2612:
 	call z80_save_context
 	mov %r13w, %di
@@ -199,6 +224,8 @@
 	.global z80_read_word
 z80_read_word:
 	call z_inccycles
+	cmp $0x8000, %r13w
+	jae z80_read_bank_word
 	push %r13
 	call z80_read_byte_noinc
 	mov %r13b, %r14b
@@ -210,6 +237,42 @@
 	mov %r14b, %r13b
 	ret
 
+z80_read_bank_word:
+	push %rsi
+	mov 144(%rsi), %rsi /* get system context pointer */
+	cmp $0, 120(%rsi) /* check bus busy flag */
+	pop %rsi
+	jne bus_busy_word
+	add $3, %ebp /* first read typically has 3 wait states */
+z80_read_bank_word_cont:
+	push %r13
+	call z80_read_bank_cont
+	mov %r13b, %r14b
+	pop %r13
+	inc %r13
+	call z_inccycles
+	push %rsi
+	mov 144(%rsi), %rsi /* get system context pointer */
+	cmp $0, 120(%rsi) /* check bus busy flag */
+	pop %rsi
+	jne bus_busy_word2
+	add $4, %ebp /* second read typically has 4 wait states */
+z80_read_bank_word_cont2:
+	call z80_read_bank_cont
+	shl $8, %r13w
+	mov %r14b, %r13b
+	ret
+
+bus_busy_word:
+	mov %edi, %ebp
+	call forced_sync
+	jp z80_read_bank_word_cont
+
+bus_busy_word2:
+	mov %edi, %ebp
+	call forced_sync
+	jp z80_read_bank_word_cont2
+
 	.global z80_write_word_highfirst
 z80_write_word_highfirst:
 	call z_inccycles