[Core/VDP] improved FIFO timings accuracy (fixes "Overdrive" Demo)

This commit is contained in:
EkeEke 2013-10-20 20:41:44 +02:00 committed by twinaphex
parent f4014c3ef1
commit adae91bd65
3 changed files with 99 additions and 64 deletions

View File

@ -357,7 +357,7 @@ void system_frame_gen(int do_skip)
/* reset VDP FIFO */
fifo_write_cnt = 0;
fifo_lastwrite = 0;
fifo_slots = 0;
/* update 6-Buttons & Lightguns */
input_refresh();
@ -703,7 +703,7 @@ void system_frame_scd(int do_skip)
/* reset VDP FIFO */
fifo_write_cnt = 0;
fifo_lastwrite = 0;
fifo_slots = 0;
/* update 6-Buttons & Lightguns */
input_refresh();
@ -1032,7 +1032,7 @@ void system_frame_sms(int do_skip)
/* reset VDP FIFO */
fifo_write_cnt = 0;
fifo_lastwrite = 0;
fifo_slots = 0;
/* update 6-Buttons & Lightguns */
input_refresh();

View File

@ -85,8 +85,8 @@ uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
uint16 v_counter; /* Vertical counter */
uint16 vc_max; /* Vertical counter overflow value */
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
int32 fifo_write_cnt; /* VDP writes fifo count */
uint32 fifo_lastwrite; /* last VDP write cycle */
int32 fifo_write_cnt; /* VDP FIFO write count */
uint32 fifo_slots; /* VDP FIFO access slot count */
uint32 hvc_latch; /* latched HV counter */
const uint8 *hctab; /* pointer to H Counter table */
@ -134,9 +134,10 @@ static uint16 sat_addr_mask; /* Index bits of SAT */
static uint16 dma_src; /* DMA source address */
static uint16 dmafill; /* DMA Fill setup */
static uint32 dma_endCycles; /* 68k cycles to DMA end */
static uint32 fifo_latency; /* CPU access latency */
static int cached_write; /* 2nd part of 32-bit CTRL port write (Genesis mode) or LSB of CRAM data (Game Gear mode) */
static uint16 fifo[4]; /* FIFO buffer */
static int fifo_byte_access; /* FIFO byte access flag */
static uint32 fifo_cycles; /* FIFO next access cycle */
/* set Z80 or 68k interrupt lines */
static void (*set_irq_line)(unsigned int level);
@ -227,8 +228,10 @@ void vdp_reset(void)
im2_flag = 0;
interlaced = 0;
fifo_write_cnt = 0;
fifo_lastwrite = 0;
fifo_cycles = 0;
fifo_slots = 0;
cached_write = -1;
fifo_byte_access = 1;
ntab = 0;
ntbb = 0;
@ -259,9 +262,6 @@ void vdp_reset(void)
/* default Window clipping */
window_clip(0,0);
/* default FIFO timings */
fifo_latency = 214;
/* reset VDP status (FIFO empty flag is set) */
if (system_hw & SYSTEM_MD)
{
@ -478,9 +478,8 @@ int vdp_context_load(uint8 *state)
load_param(&cached_write, sizeof(cached_write));
/* restore FIFO timings */
fifo_latency = (reg[12] & 1) ? 190 : 214;
fifo_latency <<= ((code & 0x0F) < 0x03);
/* restore FIFO byte access flag */
fifo_byte_access = ((code & 0x0F) < 0x03);
/* restore current NTSC/PAL mode */
if (system_hw & SYSTEM_MD)
@ -769,20 +768,12 @@ void vdp_68k_ctrl_w(unsigned int data)
/*
FIFO emulation (Chaos Engine/Soldier of Fortune, Double Clutch, Sol Deace)
--------------------------------------------------------------------------
CPU access per line is limited during active display:
H32: 16 access --> 3420/16 = ~214 Mcycles between access
H40: 18 access --> 3420/18 = ~190 Mcycles between access
This is an approximation: on real hardware, access slots are fixed.
Each VRAM access is byte wide, so one VRAM write (word) need twice cycles.
Note: Invalid code 0x02 (register write) apparently behaves the same as VRAM
access, although no data is written in this case (fixes Clue menu)
*/
fifo_latency = (reg[12] & 1) ? 190 : 214;
fifo_latency <<= ((code & 0x0F) < 0x03);
fifo_byte_access = ((code & 0x0F) <= 0x02);
}
/* Mega Drive VDP control port specific (MS compatibility mode) */
@ -1221,8 +1212,11 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
{
unsigned int temp;
/* Update FIFO flags */
/* Update FIFO status flags if not empty */
if (fifo_write_cnt)
{
vdp_fifo_update(cycles);
}
/* Update DMA Busy flag */
if ((status & 2) && !dma_length && (cycles >= dma_endCycles))
@ -1980,9 +1974,6 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
/* Update clipping */
window_clip(reg[17], 1);
/* Update fifo timings */
fifo_latency = 190;
}
else
{
@ -1997,14 +1988,8 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
/* Update clipping */
window_clip(reg[17], 0);
/* Update FIFO timings */
fifo_latency = 214;
}
/* Adjust FIFO timings for VRAM writes */
fifo_latency <<= ((code & 0x0F) < 0x03);
/* Active display width modified during HBLANK (Bugs Bunny Double Trouble) */
if ((v_counter < bitmap.viewport.h) && (cycles <= (mcycles_vdp + 860)))
{
@ -2063,38 +2048,84 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
}
}
/*--------------------------------------------------------------------------*/
/* FIFO update function (Genesis mode only) */
/* FIFO emulation (Mega Drive VDP specific) */
/* ---------------------------------------- */
/* */
/* CPU access to VRAM, CRAM & VSRAM is limited during active display: */
/* H32 mode -> 16 access per line */
/* H40 mode -> 18 access per line */
/* */
/* with fixed access slots timings detailled below. */
/* */
/* Each VRAM access is byte wide, so one VRAM write (word) need two slots. */
/* */
/*--------------------------------------------------------------------------*/
static void vdp_fifo_update(unsigned int cycles)
{
if (fifo_write_cnt > 0)
{
/* Get number of FIFO reads */
int fifo_read = ((cycles - fifo_lastwrite) / fifo_latency);
int slots, count = 0;
if (fifo_read > 0)
const int *fifo_timing;
const int fifo_cycles_h32[16+2] =
{
/* Process FIFO entries */
fifo_write_cnt -= fifo_read;
230, 510, 810, 970, 1130, 1450, 1610, 1770, 2090, 2250, 2410, 2730, 2890, 3050, 3350, 3370,
MCYCLES_PER_LINE + 230, MCYCLES_PER_LINE + 510
};
const int fifo_cycles_h40[18+2] =
{
352, 820, 948, 1076, 1332, 1460, 1588, 1844, 1972, 2100, 2356, 2484, 2612, 2868, 2996, 3124, 3364, 3380,
MCYCLES_PER_LINE + 352, MCYCLES_PER_LINE + 820
};
/* number of access slots up to current line */
if (reg[12] & 0x01)
{
fifo_timing = fifo_cycles_h40;
slots = 18 * (cycles / MCYCLES_PER_LINE);
}
else
{
fifo_timing = fifo_cycles_h32;
slots = 16 * (cycles / MCYCLES_PER_LINE);
}
/* number of access slots within current line */
cycles = cycles % MCYCLES_PER_LINE;
while (fifo_timing[count] <= cycles)
{
count++;
}
/* number of processed FIFO entries since last access */
slots = (slots + count - fifo_slots) >> fifo_byte_access;
if (slots > 0)
{
/* process FIFO entries */
fifo_write_cnt -= slots;
/* Clear FIFO full flag */
status &= 0xFEFF;
/* Check remaining FIFO entries */
if (fifo_write_cnt <= 0)
{
/* No more FIFO entries */
fifo_write_cnt = 0;
/* Set FIFO empty flag */
status |= 0x200;
fifo_write_cnt = 0;
}
/* Update FIFO cycle count */
fifo_lastwrite += (fifo_read * fifo_latency);
}
/* Update FIFO access slot counter */
fifo_slots += (slots << fifo_byte_access);
}
/* next FIFO update cycle */
fifo_cycles = mcycles_vdp + fifo_timing[count | fifo_byte_access];
}
@ -2252,9 +2283,11 @@ static void vdp_68k_data_w_m4(unsigned int data)
}
else
{
/* CPU is halted until last FIFO entry has been processed (Chaos Engine, Soldiers of Fortune, Double Clutch) */
fifo_lastwrite += fifo_latency;
m68k.cycles = fifo_lastwrite;
/* CPU is halted until next FIFO entry processing */
m68k.cycles = fifo_cycles;
/* Update FIFO access slot counter */
fifo_slots = fifo_slots + 1 + fifo_byte_access;
}
}
@ -2342,9 +2375,11 @@ static void vdp_68k_data_w_m5(unsigned int data)
}
else
{
/* CPU is halted until last FIFO entry has been processed (Chaos Engine, Soldiers of Fortune, Double Clutch) */
fifo_lastwrite += fifo_latency;
m68k.cycles = fifo_lastwrite;
/* CPU is halted until next FIFO entry processing (Chaos Engine / Soldiers of Fortune, Double Clutch, Titan Overdrive Demo) */
m68k.cycles = fifo_cycles;
/* Update FIFO access slot counter */
fifo_slots += (1 + fifo_byte_access);
}
}

View File

@ -75,7 +75,7 @@ extern uint16 vc_max;
extern uint16 vscroll;
extern uint16 lines_per_frame;
extern int32 fifo_write_cnt;
extern uint32 fifo_lastwrite;
extern uint32 fifo_slots;
extern uint32 hvc_latch;
extern const uint8 *hctab;