# HG changeset patch # User Michael Pavone # Date 1586835805 25200 # Node ID 039553703c20fd1d433d01707b7af335fb36c8d4 # Parent 81b059e3ded67b0ecd48236bbb781330b9ed8e62 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 diff -r 81b059e3ded6 -r 039553703c20 vdp.c --- a/vdp.c Mon Apr 13 18:14:25 2020 -0700 +++ b/vdp.c Mon Apr 13 20:43:25 2020 -0700 @@ -976,7 +976,7 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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_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 @@ 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 @@ } } -#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 @@ 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 @@ 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 -r 81b059e3ded6 -r 039553703c20 vdp.h --- a/vdp.h Mon Apr 13 18:14:25 2020 -0700 +++ b/vdp.h Mon Apr 13 20:43:25 2020 -0700 @@ -174,6 +174,7 @@ 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 @@ 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