summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2014-02-03 09:18:10 -0800
committerMichael Pavone <pavone@retrodev.com>2014-02-03 09:18:10 -0800
commite14e901df89aa1823b1479366b58196247c16bd2 (patch)
tree14e076b4b2a409974b73dd15278c8394833ad89c
parentefcdc09b1c58be04a53fa84ea34981d4231c1a78 (diff)
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.
-rw-r--r--blastem.c10
-rw-r--r--blastem.h1
-rw-r--r--zruntime.S65
3 files changed, 74 insertions, 2 deletions
diff --git a/blastem.c b/blastem.c
index 05a1b4f..489ce62 100644
--- a/blastem.c
+++ b/blastem.c
@@ -312,10 +312,12 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_
//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 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_
//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 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_
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;
}
diff --git a/blastem.h b/blastem.h
index 6f8786f..ff05a69 100644
--- a/blastem.h
+++ b/blastem.h
@@ -34,6 +34,7 @@ typedef struct {
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;
diff --git a/zruntime.S b/zruntime.S
index 122f058..fa803fe 100644
--- a/zruntime.S
+++ b/zruntime.S
@@ -34,6 +34,21 @@ sync_io:
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 @@ z80_read_ram:
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 @@ z80_read_bank:
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 @@ z80_write_vdp:
.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 @@ z80_read_word:
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