# HG changeset patch # User Mike Pavone # Date 1379125366 25200 # Node ID 541c1ae8abf3dbbfa7f87c964ffcef1a433e0b6a # Parent 5f3344d0d42f4d266c93027dd15314ff2d1470c5 Properly delay 68K on VDP reads. Dummy VDP test port implementation. Initial stab at handling undefined bits of VSRAM and CRAM. diff -r 5f3344d0d42f -r 541c1ae8abf3 blastem.c --- a/blastem.c Wed Sep 11 19:26:35 2013 -0700 +++ b/blastem.c Fri Sep 13 19:22:46 2013 -0700 @@ -362,7 +362,7 @@ exit(1); } if (v_context->cycles != before_cycle) { - //printf("68K paused for %d (%d) cycles at cycle %d (%d)\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); + printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); context->current_cycle = v_context->cycles / MCLKS_PER_68K; } } else if (vdp_port < 0x18) { @@ -402,7 +402,7 @@ sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); psg_write(gen->psg, value); } else { - //TODO: Implement undocumented test register(s) + vdp_test_port_write(gen->vdp, value); } return context; } @@ -417,6 +417,7 @@ uint16_t value; sync_components(context, 0); vdp_context * v_context = context->video_context; + uint32_t before_cycle = v_context->cycles; if (vdp_port < 0x10) { if (vdp_port < 4) { value = vdp_data_port_read(v_context); @@ -426,9 +427,15 @@ value = vdp_hv_counter_read(v_context); //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); } + } else if (vdp_port < 0x18){ + printf("Illegal read from PSG port %X\n", vdp_port); + exit(1); } else { - printf("Illegal read from PSG or test register port %X\n", vdp_port); - exit(1); + value = vdp_test_port_read(v_context); + } + if (v_context->cycles != before_cycle) { + printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); + context->current_cycle = v_context->cycles / MCLKS_PER_68K; } return value; } diff -r 5f3344d0d42f -r 541c1ae8abf3 vdp.c --- a/vdp.c Wed Sep 11 19:26:35 2013 -0700 +++ b/vdp.c Fri Sep 13 19:22:46 2013 -0700 @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "vdp.h" @@ -391,15 +391,21 @@ void external_slot(vdp_context * context) { fifo_entry * start = (context->fifo_end - FIFO_SIZE); + if (context->flags2 & FLAG2_READ_PENDING) { + context->flags2 &= ~FLAG2_READ_PENDING; + context->flags |= FLAG_UNUSED_SLOT; + return; + } if (context->fifo_cur != start && start->cycle <= context->cycles) { switch (start->cd & 0xF) { case VRAM_WRITE: if (start->partial) { - //printf("VRAM Write: %X to %X\n", start->value, context->address ^ 1); + printf("VRAM Write: %X to %X at %d (line %d, slot %d)\n", start->value, start->address ^ 1, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16); + context->last_fifo_val = start->value; context->vdpmem[start->address ^ 1] = start->value; } else { - //printf("VRAM Write High: %X to %X\n", start->value >> 8, context->address); + printf("VRAM Write High: %X to %X at %d (line %d, slot %d)\n", start->value >> 8, start->address, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16); context->vdpmem[start->address] = start->value >> 8; start->partial = 1; //skip auto-increment and removal of entry from fifo @@ -409,12 +415,14 @@ case CRAM_WRITE: { //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); write_cram(context, start->address, start->value); + context->last_fifo_val = start->value; break; } case VSRAM_WRITE: if (((start->address/2) & 63) < VSRAM_SIZE) { //printf("VSRAM Write: %X to %X\n", start->value, context->address); context->vsram[(start->address/2) & 63] = start->value; + context->last_fifo_val = start->value; } break; @@ -1428,7 +1436,7 @@ int vdp_control_port_write(vdp_context * context, uint16_t value) { - //printf("control port write: %X at %d\n", value, context->cycles); + printf("control port write: %X at %d\n", value, context->cycles); if (context->flags & FLAG_DMA_RUN) { return -1; } @@ -1482,7 +1490,7 @@ int vdp_data_port_write(vdp_context * context, uint16_t value) { - //printf("data port write: %X at %d\n", value, context->cycles); + printf("data port write: %X at %d\n", value, context->cycles); if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { return -1; } @@ -1514,6 +1522,11 @@ return 0; } +void vdp_test_port_write(vdp_context * context, uint16_t value) +{ + //TODO: implement test register +} + uint16_t vdp_control_port_read(vdp_context * context) { context->flags &= ~FLAG_PENDING; @@ -1549,6 +1562,9 @@ return value; } +#define CRAM_BITS 0xEEE +#define VSRAM_BITS 0x3FF + uint16_t vdp_data_port_read(vdp_context * context) { context->flags &= ~FLAG_PENDING; @@ -1557,6 +1573,7 @@ } //Not sure if the FIFO should be drained before processing a read or not, but it would make sense context->flags &= ~FLAG_UNUSED_SLOT; + context->flags2 |= FLAG2_READ_PENDING; while (!(context->flags & FLAG_UNUSED_SLOT)) { vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); } @@ -1566,17 +1583,20 @@ case VRAM_READ: value = context->vdpmem[context->address] << 8; context->flags &= ~FLAG_UNUSED_SLOT; + context->flags2 |= FLAG2_READ_PENDING; while (!(context->flags & FLAG_UNUSED_SLOT)) { vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); } value |= context->vdpmem[context->address ^ 1]; break; case CRAM_READ: - value = context->cram[(context->address/2) & (CRAM_SIZE-1)]; + value = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS; + value |= context->last_fifo_val & ~CRAM_BITS; break; case VSRAM_READ: if (((context->address / 2) & 63) < VSRAM_SIZE) { - value = context->vsram[context->address & 63]; + value = context->vsram[context->address & 63] & VSRAM_BITS; + value |= context->last_fifo_val & ~VSRAM_BITS; } break; } @@ -1693,6 +1713,12 @@ return (line << 8) | linecyc; } +uint16_t vdp_test_port_read(vdp_context * context) +{ + //TODO: Find out what actually gets returned here + return 0xFFFF; +} + void vdp_adjust_cycles(vdp_context * context, uint32_t deduction) { context->cycles -= deduction; diff -r 5f3344d0d42f -r 541c1ae8abf3 vdp.h --- a/vdp.h Wed Sep 11 19:26:35 2013 -0700 +++ b/vdp.h Fri Sep 13 19:22:46 2013 -0700 @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #ifndef VDP_H_ @@ -47,6 +47,7 @@ #define FLAG2_VINT_PENDING 0x01 #define FLAG2_HINT_PENDING 0x02 +#define FLAG2_READ_PENDING 0x04 #define DISPLAY_ENABLE 0x40 @@ -149,6 +150,7 @@ uint16_t col_1; uint16_t col_2; uint16_t last_write_val; + uint16_t last_fifo_val; uint8_t v_offset; uint8_t dma_cd; uint8_t hint_counter; @@ -172,9 +174,11 @@ uint8_t vdp_save_gst(vdp_context * context, FILE * outfile); int vdp_control_port_write(vdp_context * context, uint16_t value); int vdp_data_port_write(vdp_context * context, uint16_t value); +void vdp_test_port_write(vdp_context * context, uint16_t value); uint16_t vdp_control_port_read(vdp_context * context); uint16_t vdp_data_port_read(vdp_context * context); uint16_t vdp_hv_counter_read(vdp_context * context); +uint16_t vdp_test_port_read(vdp_context * context); void vdp_adjust_cycles(vdp_context * context, uint32_t deduction); uint32_t vdp_next_hint(vdp_context * context); uint32_t vdp_next_vint(vdp_context * context);