diff options
author | Michael Pavone <pavone@retrodev.com> | 2020-04-13 20:43:25 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2020-04-13 20:43:25 -0700 |
commit | 1fa2143c1aee80784f4a9aca1e9a544fc71584c0 (patch) | |
tree | 6c8824934620aa4df9f6855b74683f9c623ccc5a | |
parent | 325475eb93f8b0ec9eaa1bc75344325b6f30dcd4 (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.c | 47 | ||||
-rw-r--r-- | vdp.h | 2 |
2 files changed, 36 insertions, 13 deletions
@@ -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); } @@ -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 |