summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2020-04-13 20:43:25 -0700
committerMichael Pavone <pavone@retrodev.com>2020-04-13 20:43:25 -0700
commit1fa2143c1aee80784f4a9aca1e9a544fc71584c0 (patch)
tree6c8824934620aa4df9f6855b74683f9c623ccc5a
parent325475eb93f8b0ec9eaa1bc75344325b6f30dcd4 (diff)
Don't apply address and cd register changes to the 'live' registers until pending flag is cleared, but do preserve the upper address bits in the latch. Fixes regression in Overdrive 2 while preserving fix to Mona in 344 bytes
-rw-r--r--vdp.c47
-rw-r--r--vdp.h2
2 files changed, 36 insertions, 13 deletions
diff --git a/vdp.c b/vdp.c
index 37ad611..d3798f1 100644
--- a/vdp.c
+++ b/vdp.c
@@ -976,7 +976,7 @@ static void external_slot(vdp_context * context)
context->flags |= FLAG_READ_FETCHED;
}
- } else if (!(context->cd & 1) && !(context->flags & (FLAG_READ_FETCHED|FLAG_PENDING))) {
+ } else if (!(context->cd & 1) && !(context->flags & FLAG_READ_FETCHED)) {
switch(context->cd & 0xF)
{
case VRAM_READ:
@@ -2752,7 +2752,7 @@ static void vdp_h40(vdp_context * context, uint32_t target_cycles)
{
case 165:
//only consider doing a line at a time if the FIFO is empty, there are no pending reads and there is no DMA running
- if (context->fifo_read == -1 && !(context->flags & FLAG_DMA_RUN) && ((context->cd & 1) || (context->flags & (FLAG_READ_FETCHED|FLAG_PENDING)))) {
+ if (context->fifo_read == -1 && !(context->flags & FLAG_DMA_RUN) && ((context->cd & 1) || (context->flags & FLAG_READ_FETCHED))) {
while (target_cycles - context->cycles >= MCLKS_LINE && context->state != PREPARING && context->vcounter != context->inactive_start) {
vdp_h40_line(context);
}
@@ -3691,6 +3691,13 @@ uint16_t vdp_hv_counter_read(vdp_context * context)
return hv;
}
+static void clear_pending(vdp_context *context)
+{
+ context->flags &= ~FLAG_PENDING;
+ context->address = context->address_latch;
+ context->cd = context->cd_latch;
+}
+
int vdp_control_port_write(vdp_context * context, uint16_t value)
{
//printf("control port write: %X at %d\n", value, context->cycles);
@@ -3698,12 +3705,12 @@ int vdp_control_port_write(vdp_context * context, uint16_t value)
return -1;
}
if (context->flags & FLAG_PENDING) {
- context->address = (context->address & 0x3FFF) | (value << 14 & 0x1C000);
+ context->address_latch = (context->address_latch & 0x3FFF) | (value << 14 & 0x1C000);
//It seems like the DMA enable bit doesn't so much enable DMA so much
//as it enables changing CD5 from control port writes
uint8_t preserve = (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) ? 0x3 : 0x23;
- context->cd = (context->cd & preserve) | ((value >> 2) & ~preserve & 0xFF);
- context->flags &= ~FLAG_PENDING;
+ context->cd_latch = (context->cd_latch & preserve) | ((value >> 2) & ~preserve & 0xFF);
+ clear_pending(context);
//Should these be taken care of here or after the first write?
context->flags &= ~FLAG_READ_FETCHED;
context->flags2 &= ~FLAG2_READ_PENDING;
@@ -3734,8 +3741,8 @@ int vdp_control_port_write(vdp_context * context, uint16_t value)
uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
//contrary to what's in Charles MacDonald's doc, it seems top 2 address bits are cleared
//needed for the Mona in 344 Bytes demo
- context->address = value & 0x3FFF;
- context->cd = (context->cd & 0x3C) | (value >> 14);
+ context->address_latch = (context->address_latch & 0x1C000) | (value & 0x3FFF);
+ context->cd_latch = (context->cd_latch & 0x3C) | (value >> 14);
if ((value & 0xC000) == 0x8000) {
//Register write
uint8_t reg = (value >> 8) & 0x1F;
@@ -3797,7 +3804,7 @@ int vdp_data_port_write(vdp_context * context, uint16_t value)
return -1;
}
if (context->flags & FLAG_PENDING) {
- context->flags &= ~FLAG_PENDING;
+ clear_pending(context);
//Should these be cleared here?
context->flags &= ~FLAG_READ_FETCHED;
context->flags2 &= ~FLAG2_READ_PENDING;
@@ -3832,7 +3839,7 @@ int vdp_data_port_write(vdp_context * context, uint16_t value)
void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
{
if (context->flags & FLAG_PENDING) {
- context->flags &= ~FLAG_PENDING;
+ clear_pending(context);
//Should these be cleared here?
context->flags &= ~FLAG_READ_FETCHED;
context->flags2 &= ~FLAG2_READ_PENDING;
@@ -3871,7 +3878,9 @@ void vdp_test_port_write(vdp_context * context, uint16_t value)
uint16_t vdp_control_port_read(vdp_context * context)
{
- context->flags &= ~FLAG_PENDING;
+ if (context->flags & FLAG_PENDING) {
+ clear_pending(context);
+ }
context->flags2 &= ~FLAG2_BYTE_PENDING;
//Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
@@ -3921,7 +3930,7 @@ uint16_t vdp_control_port_read(vdp_context * context)
uint16_t vdp_data_port_read(vdp_context * context)
{
if (context->flags & FLAG_PENDING) {
- context->flags &= ~FLAG_PENDING;
+ clear_pending(context);
//Should these be cleared here?
context->flags &= ~FLAG_READ_FETCHED;
context->flags2 &= ~FLAG2_READ_PENDING;
@@ -3938,7 +3947,10 @@ uint16_t vdp_data_port_read(vdp_context * context)
uint8_t vdp_data_port_read_pbc(vdp_context * context)
{
- context->flags &= ~(FLAG_PENDING | FLAG_READ_FETCHED);
+ if (context->flags & FLAG_PENDING) {
+ clear_pending(context);
+ }
+ context->flags &= ~FLAG_READ_FETCHED;
context->flags2 &= ~FLAG2_BYTE_PENDING;
context->cd = VRAM_READ8;
@@ -4237,7 +4249,7 @@ void vdp_int_ack(vdp_context * context)
}
}
-#define VDP_STATE_VERSION 2
+#define VDP_STATE_VERSION 3
void vdp_serialize(vdp_context *context, serialize_buffer *buf)
{
save_int8(buf, VDP_STATE_VERSION);
@@ -4317,6 +4329,8 @@ void vdp_serialize(vdp_context *context, serialize_buffer *buf)
save_int32(buf, context->cycles);
save_int32(buf, context->pending_vint_start);
save_int32(buf, context->pending_hint_start);
+ save_int32(buf, context->address_latch);
+ save_int8(buf, context->cd_latch);
}
void vdp_deserialize(deserialize_buffer *buf, void *vcontext)
@@ -4451,6 +4465,13 @@ void vdp_deserialize(deserialize_buffer *buf, void *vcontext)
context->cycles = load_int32(buf);
context->pending_vint_start = load_int32(buf);
context->pending_hint_start = load_int32(buf);
+ if (version > 2) {
+ context->address_latch = load_int32(buf);
+ context->cd_latch = load_int8(buf);
+ } else {
+ context->address_latch = context->address;
+ context->cd_latch = context->cd;
+ }
update_video_params(context);
}
diff --git a/vdp.h b/vdp.h
index cd407d3..44dc46c 100644
--- a/vdp.h
+++ b/vdp.h
@@ -174,6 +174,7 @@ typedef struct {
int32_t fifo_write;
int32_t fifo_read;
uint32_t address;
+ uint32_t address_latch;
uint32_t serial_address;
uint32_t colors[CRAM_SIZE*4];
uint32_t debugcolors[1 << (3 + 1 + 1 + 1)];//3 bits for source, 1 bit for priority, 1 bit for shadow, 1 bit for hilight
@@ -181,6 +182,7 @@ typedef struct {
uint32_t frame;
uint32_t vsram_size;
uint8_t cd;
+ uint8_t cd_latch;
uint8_t flags;
uint8_t regs[VDP_REGS];
//cycle count in MCLKs