comparison vdp.c @ 1925:039553703c20

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
author Michael Pavone <pavone@retrodev.com>
date Mon, 13 Apr 2020 20:43:25 -0700
parents b91c35bce3e9
children abc89555f2e0
comparison
equal deleted inserted replaced
1924:81b059e3ded6 1925:039553703c20
974 } else { 974 } else {
975 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1]; 975 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1];
976 976
977 context->flags |= FLAG_READ_FETCHED; 977 context->flags |= FLAG_READ_FETCHED;
978 } 978 }
979 } else if (!(context->cd & 1) && !(context->flags & (FLAG_READ_FETCHED|FLAG_PENDING))) { 979 } else if (!(context->cd & 1) && !(context->flags & FLAG_READ_FETCHED)) {
980 switch(context->cd & 0xF) 980 switch(context->cd & 0xF)
981 { 981 {
982 case VRAM_READ: 982 case VRAM_READ:
983 if (context->flags2 & FLAG2_READ_PENDING) { 983 if (context->flags2 & FLAG2_READ_PENDING) {
984 context->prefetch |= context->vdpmem[context->address | 1]; 984 context->prefetch |= context->vdpmem[context->address | 1];
2750 { 2750 {
2751 for (;;) 2751 for (;;)
2752 { 2752 {
2753 case 165: 2753 case 165:
2754 //only consider doing a line at a time if the FIFO is empty, there are no pending reads and there is no DMA running 2754 //only consider doing a line at a time if the FIFO is empty, there are no pending reads and there is no DMA running
2755 if (context->fifo_read == -1 && !(context->flags & FLAG_DMA_RUN) && ((context->cd & 1) || (context->flags & (FLAG_READ_FETCHED|FLAG_PENDING)))) { 2755 if (context->fifo_read == -1 && !(context->flags & FLAG_DMA_RUN) && ((context->cd & 1) || (context->flags & FLAG_READ_FETCHED))) {
2756 while (target_cycles - context->cycles >= MCLKS_LINE && context->state != PREPARING && context->vcounter != context->inactive_start) { 2756 while (target_cycles - context->cycles >= MCLKS_LINE && context->state != PREPARING && context->vcounter != context->inactive_start) {
2757 vdp_h40_line(context); 2757 vdp_h40_line(context);
2758 } 2758 }
2759 CHECK_ONLY 2759 CHECK_ONLY
2760 } 2760 }
3689 hv |= get_ext_vcounter(context); 3689 hv |= get_ext_vcounter(context);
3690 3690
3691 return hv; 3691 return hv;
3692 } 3692 }
3693 3693
3694 static void clear_pending(vdp_context *context)
3695 {
3696 context->flags &= ~FLAG_PENDING;
3697 context->address = context->address_latch;
3698 context->cd = context->cd_latch;
3699 }
3700
3694 int vdp_control_port_write(vdp_context * context, uint16_t value) 3701 int vdp_control_port_write(vdp_context * context, uint16_t value)
3695 { 3702 {
3696 //printf("control port write: %X at %d\n", value, context->cycles); 3703 //printf("control port write: %X at %d\n", value, context->cycles);
3697 if (context->flags & FLAG_DMA_RUN) { 3704 if (context->flags & FLAG_DMA_RUN) {
3698 return -1; 3705 return -1;
3699 } 3706 }
3700 if (context->flags & FLAG_PENDING) { 3707 if (context->flags & FLAG_PENDING) {
3701 context->address = (context->address & 0x3FFF) | (value << 14 & 0x1C000); 3708 context->address_latch = (context->address_latch & 0x3FFF) | (value << 14 & 0x1C000);
3702 //It seems like the DMA enable bit doesn't so much enable DMA so much 3709 //It seems like the DMA enable bit doesn't so much enable DMA so much
3703 //as it enables changing CD5 from control port writes 3710 //as it enables changing CD5 from control port writes
3704 uint8_t preserve = (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) ? 0x3 : 0x23; 3711 uint8_t preserve = (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) ? 0x3 : 0x23;
3705 context->cd = (context->cd & preserve) | ((value >> 2) & ~preserve & 0xFF); 3712 context->cd_latch = (context->cd_latch & preserve) | ((value >> 2) & ~preserve & 0xFF);
3706 context->flags &= ~FLAG_PENDING; 3713 clear_pending(context);
3707 //Should these be taken care of here or after the first write? 3714 //Should these be taken care of here or after the first write?
3708 context->flags &= ~FLAG_READ_FETCHED; 3715 context->flags &= ~FLAG_READ_FETCHED;
3709 context->flags2 &= ~FLAG2_READ_PENDING; 3716 context->flags2 &= ~FLAG2_READ_PENDING;
3710 //printf("New Address: %X, New CD: %X\n", context->address, context->cd); 3717 //printf("New Address: %X, New CD: %X\n", context->address, context->cd);
3711 if (context->cd & 0x20) { 3718 if (context->cd & 0x20) {
3732 } 3739 }
3733 } else { 3740 } else {
3734 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; 3741 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
3735 //contrary to what's in Charles MacDonald's doc, it seems top 2 address bits are cleared 3742 //contrary to what's in Charles MacDonald's doc, it seems top 2 address bits are cleared
3736 //needed for the Mona in 344 Bytes demo 3743 //needed for the Mona in 344 Bytes demo
3737 context->address = value & 0x3FFF; 3744 context->address_latch = (context->address_latch & 0x1C000) | (value & 0x3FFF);
3738 context->cd = (context->cd & 0x3C) | (value >> 14); 3745 context->cd_latch = (context->cd_latch & 0x3C) | (value >> 14);
3739 if ((value & 0xC000) == 0x8000) { 3746 if ((value & 0xC000) == 0x8000) {
3740 //Register write 3747 //Register write
3741 uint8_t reg = (value >> 8) & 0x1F; 3748 uint8_t reg = (value >> 8) & 0x1F;
3742 if (reg < (mode_5 ? VDP_REGS : 0xB)) { 3749 if (reg < (mode_5 ? VDP_REGS : 0xB)) {
3743 //printf("register %d set to %X\n", reg, value & 0xFF); 3750 //printf("register %d set to %X\n", reg, value & 0xFF);
3795 //printf("data port write: %X at %d\n", value, context->cycles); 3802 //printf("data port write: %X at %d\n", value, context->cycles);
3796 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) != DMA_FILL) { 3803 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) != DMA_FILL) {
3797 return -1; 3804 return -1;
3798 } 3805 }
3799 if (context->flags & FLAG_PENDING) { 3806 if (context->flags & FLAG_PENDING) {
3800 context->flags &= ~FLAG_PENDING; 3807 clear_pending(context);
3801 //Should these be cleared here? 3808 //Should these be cleared here?
3802 context->flags &= ~FLAG_READ_FETCHED; 3809 context->flags &= ~FLAG_READ_FETCHED;
3803 context->flags2 &= ~FLAG2_READ_PENDING; 3810 context->flags2 &= ~FLAG2_READ_PENDING;
3804 } 3811 }
3805 /*if (context->fifo_cur == context->fifo_end) { 3812 /*if (context->fifo_cur == context->fifo_end) {
3830 } 3837 }
3831 3838
3832 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value) 3839 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
3833 { 3840 {
3834 if (context->flags & FLAG_PENDING) { 3841 if (context->flags & FLAG_PENDING) {
3835 context->flags &= ~FLAG_PENDING; 3842 clear_pending(context);
3836 //Should these be cleared here? 3843 //Should these be cleared here?
3837 context->flags &= ~FLAG_READ_FETCHED; 3844 context->flags &= ~FLAG_READ_FETCHED;
3838 context->flags2 &= ~FLAG2_READ_PENDING; 3845 context->flags2 &= ~FLAG2_READ_PENDING;
3839 } 3846 }
3840 context->flags2 &= ~FLAG2_BYTE_PENDING; 3847 context->flags2 &= ~FLAG2_BYTE_PENDING;
3869 context->test_port = value; 3876 context->test_port = value;
3870 } 3877 }
3871 3878
3872 uint16_t vdp_control_port_read(vdp_context * context) 3879 uint16_t vdp_control_port_read(vdp_context * context)
3873 { 3880 {
3874 context->flags &= ~FLAG_PENDING; 3881 if (context->flags & FLAG_PENDING) {
3882 clear_pending(context);
3883 }
3875 context->flags2 &= ~FLAG2_BYTE_PENDING; 3884 context->flags2 &= ~FLAG2_BYTE_PENDING;
3876 //Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch 3885 //Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
3877 uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00; 3886 uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
3878 if (context->fifo_read < 0) { 3887 if (context->fifo_read < 0) {
3879 value |= 0x200; 3888 value |= 0x200;
3919 } 3928 }
3920 3929
3921 uint16_t vdp_data_port_read(vdp_context * context) 3930 uint16_t vdp_data_port_read(vdp_context * context)
3922 { 3931 {
3923 if (context->flags & FLAG_PENDING) { 3932 if (context->flags & FLAG_PENDING) {
3924 context->flags &= ~FLAG_PENDING; 3933 clear_pending(context);
3925 //Should these be cleared here? 3934 //Should these be cleared here?
3926 context->flags &= ~FLAG_READ_FETCHED; 3935 context->flags &= ~FLAG_READ_FETCHED;
3927 context->flags2 &= ~FLAG2_READ_PENDING; 3936 context->flags2 &= ~FLAG2_READ_PENDING;
3928 } 3937 }
3929 if (context->cd & 1) { 3938 if (context->cd & 1) {
3936 return context->prefetch; 3945 return context->prefetch;
3937 } 3946 }
3938 3947
3939 uint8_t vdp_data_port_read_pbc(vdp_context * context) 3948 uint8_t vdp_data_port_read_pbc(vdp_context * context)
3940 { 3949 {
3941 context->flags &= ~(FLAG_PENDING | FLAG_READ_FETCHED); 3950 if (context->flags & FLAG_PENDING) {
3951 clear_pending(context);
3952 }
3953 context->flags &= ~FLAG_READ_FETCHED;
3942 context->flags2 &= ~FLAG2_BYTE_PENDING; 3954 context->flags2 &= ~FLAG2_BYTE_PENDING;
3943 3955
3944 context->cd = VRAM_READ8; 3956 context->cd = VRAM_READ8;
3945 return context->prefetch; 3957 return context->prefetch;
3946 } 3958 }
4235 context->flags2 &= ~FLAG2_HINT_PENDING; 4247 context->flags2 &= ~FLAG2_HINT_PENDING;
4236 } 4248 }
4237 } 4249 }
4238 } 4250 }
4239 4251
4240 #define VDP_STATE_VERSION 2 4252 #define VDP_STATE_VERSION 3
4241 void vdp_serialize(vdp_context *context, serialize_buffer *buf) 4253 void vdp_serialize(vdp_context *context, serialize_buffer *buf)
4242 { 4254 {
4243 save_int8(buf, VDP_STATE_VERSION); 4255 save_int8(buf, VDP_STATE_VERSION);
4244 save_int8(buf, VRAM_SIZE / 1024);//VRAM size in KB, needed for future proofing 4256 save_int8(buf, VRAM_SIZE / 1024);//VRAM size in KB, needed for future proofing
4245 save_buffer8(buf, context->vdpmem, VRAM_SIZE); 4257 save_buffer8(buf, context->vdpmem, VRAM_SIZE);
4315 save_buffer8(buf, context->linebuf, LINEBUF_SIZE); 4327 save_buffer8(buf, context->linebuf, LINEBUF_SIZE);
4316 4328
4317 save_int32(buf, context->cycles); 4329 save_int32(buf, context->cycles);
4318 save_int32(buf, context->pending_vint_start); 4330 save_int32(buf, context->pending_vint_start);
4319 save_int32(buf, context->pending_hint_start); 4331 save_int32(buf, context->pending_hint_start);
4332 save_int32(buf, context->address_latch);
4333 save_int8(buf, context->cd_latch);
4320 } 4334 }
4321 4335
4322 void vdp_deserialize(deserialize_buffer *buf, void *vcontext) 4336 void vdp_deserialize(deserialize_buffer *buf, void *vcontext)
4323 { 4337 {
4324 vdp_context *context = vcontext; 4338 vdp_context *context = vcontext;
4449 load_buffer8(buf, context->linebuf, LINEBUF_SIZE); 4463 load_buffer8(buf, context->linebuf, LINEBUF_SIZE);
4450 4464
4451 context->cycles = load_int32(buf); 4465 context->cycles = load_int32(buf);
4452 context->pending_vint_start = load_int32(buf); 4466 context->pending_vint_start = load_int32(buf);
4453 context->pending_hint_start = load_int32(buf); 4467 context->pending_hint_start = load_int32(buf);
4468 if (version > 2) {
4469 context->address_latch = load_int32(buf);
4470 context->cd_latch = load_int8(buf);
4471 } else {
4472 context->address_latch = context->address;
4473 context->cd_latch = context->cd;
4474 }
4454 update_video_params(context); 4475 update_video_params(context);
4455 } 4476 }
4456 4477
4457 static vdp_context *current_vdp; 4478 static vdp_context *current_vdp;
4458 static void vdp_debug_window_close(uint8_t which) 4479 static void vdp_debug_window_close(uint8_t which)