mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-27 03:31:49 +01:00
[Core/VDP] improved FIFO timings accuracy (fixes "Overdrive" Demo)
This commit is contained in:
parent
f4014c3ef1
commit
adae91bd65
@ -357,7 +357,7 @@ void system_frame_gen(int do_skip)
|
|||||||
|
|
||||||
/* reset VDP FIFO */
|
/* reset VDP FIFO */
|
||||||
fifo_write_cnt = 0;
|
fifo_write_cnt = 0;
|
||||||
fifo_lastwrite = 0;
|
fifo_slots = 0;
|
||||||
|
|
||||||
/* update 6-Buttons & Lightguns */
|
/* update 6-Buttons & Lightguns */
|
||||||
input_refresh();
|
input_refresh();
|
||||||
@ -703,7 +703,7 @@ void system_frame_scd(int do_skip)
|
|||||||
|
|
||||||
/* reset VDP FIFO */
|
/* reset VDP FIFO */
|
||||||
fifo_write_cnt = 0;
|
fifo_write_cnt = 0;
|
||||||
fifo_lastwrite = 0;
|
fifo_slots = 0;
|
||||||
|
|
||||||
/* update 6-Buttons & Lightguns */
|
/* update 6-Buttons & Lightguns */
|
||||||
input_refresh();
|
input_refresh();
|
||||||
@ -1032,7 +1032,7 @@ void system_frame_sms(int do_skip)
|
|||||||
|
|
||||||
/* reset VDP FIFO */
|
/* reset VDP FIFO */
|
||||||
fifo_write_cnt = 0;
|
fifo_write_cnt = 0;
|
||||||
fifo_lastwrite = 0;
|
fifo_slots = 0;
|
||||||
|
|
||||||
/* update 6-Buttons & Lightguns */
|
/* update 6-Buttons & Lightguns */
|
||||||
input_refresh();
|
input_refresh();
|
||||||
|
133
core/vdp_ctrl.c
133
core/vdp_ctrl.c
@ -85,8 +85,8 @@ uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
|
|||||||
uint16 v_counter; /* Vertical counter */
|
uint16 v_counter; /* Vertical counter */
|
||||||
uint16 vc_max; /* Vertical counter overflow value */
|
uint16 vc_max; /* Vertical counter overflow value */
|
||||||
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
|
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
|
||||||
int32 fifo_write_cnt; /* VDP writes fifo count */
|
int32 fifo_write_cnt; /* VDP FIFO write count */
|
||||||
uint32 fifo_lastwrite; /* last VDP write cycle */
|
uint32 fifo_slots; /* VDP FIFO access slot count */
|
||||||
uint32 hvc_latch; /* latched HV counter */
|
uint32 hvc_latch; /* latched HV counter */
|
||||||
const uint8 *hctab; /* pointer to H Counter table */
|
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 dma_src; /* DMA source address */
|
||||||
static uint16 dmafill; /* DMA Fill setup */
|
static uint16 dmafill; /* DMA Fill setup */
|
||||||
static uint32 dma_endCycles; /* 68k cycles to DMA end */
|
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 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 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 */
|
/* set Z80 or 68k interrupt lines */
|
||||||
static void (*set_irq_line)(unsigned int level);
|
static void (*set_irq_line)(unsigned int level);
|
||||||
@ -227,8 +228,10 @@ void vdp_reset(void)
|
|||||||
im2_flag = 0;
|
im2_flag = 0;
|
||||||
interlaced = 0;
|
interlaced = 0;
|
||||||
fifo_write_cnt = 0;
|
fifo_write_cnt = 0;
|
||||||
fifo_lastwrite = 0;
|
fifo_cycles = 0;
|
||||||
|
fifo_slots = 0;
|
||||||
cached_write = -1;
|
cached_write = -1;
|
||||||
|
fifo_byte_access = 1;
|
||||||
|
|
||||||
ntab = 0;
|
ntab = 0;
|
||||||
ntbb = 0;
|
ntbb = 0;
|
||||||
@ -259,9 +262,6 @@ void vdp_reset(void)
|
|||||||
/* default Window clipping */
|
/* default Window clipping */
|
||||||
window_clip(0,0);
|
window_clip(0,0);
|
||||||
|
|
||||||
/* default FIFO timings */
|
|
||||||
fifo_latency = 214;
|
|
||||||
|
|
||||||
/* reset VDP status (FIFO empty flag is set) */
|
/* reset VDP status (FIFO empty flag is set) */
|
||||||
if (system_hw & SYSTEM_MD)
|
if (system_hw & SYSTEM_MD)
|
||||||
{
|
{
|
||||||
@ -478,9 +478,8 @@ int vdp_context_load(uint8 *state)
|
|||||||
|
|
||||||
load_param(&cached_write, sizeof(cached_write));
|
load_param(&cached_write, sizeof(cached_write));
|
||||||
|
|
||||||
/* restore FIFO timings */
|
/* restore FIFO byte access flag */
|
||||||
fifo_latency = (reg[12] & 1) ? 190 : 214;
|
fifo_byte_access = ((code & 0x0F) < 0x03);
|
||||||
fifo_latency <<= ((code & 0x0F) < 0x03);
|
|
||||||
|
|
||||||
/* restore current NTSC/PAL mode */
|
/* restore current NTSC/PAL mode */
|
||||||
if (system_hw & SYSTEM_MD)
|
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)
|
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.
|
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
|
Note: Invalid code 0x02 (register write) apparently behaves the same as VRAM
|
||||||
access, although no data is written in this case (fixes Clue menu)
|
access, although no data is written in this case (fixes Clue menu)
|
||||||
*/
|
*/
|
||||||
fifo_latency = (reg[12] & 1) ? 190 : 214;
|
fifo_byte_access = ((code & 0x0F) <= 0x02);
|
||||||
fifo_latency <<= ((code & 0x0F) < 0x03);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mega Drive VDP control port specific (MS compatibility mode) */
|
/* 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;
|
unsigned int temp;
|
||||||
|
|
||||||
/* Update FIFO flags */
|
/* Update FIFO status flags if not empty */
|
||||||
|
if (fifo_write_cnt)
|
||||||
|
{
|
||||||
vdp_fifo_update(cycles);
|
vdp_fifo_update(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
/* Update DMA Busy flag */
|
/* Update DMA Busy flag */
|
||||||
if ((status & 2) && !dma_length && (cycles >= dma_endCycles))
|
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 */
|
/* Update clipping */
|
||||||
window_clip(reg[17], 1);
|
window_clip(reg[17], 1);
|
||||||
|
|
||||||
/* Update fifo timings */
|
|
||||||
fifo_latency = 190;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1997,14 +1988,8 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
|
|||||||
|
|
||||||
/* Update clipping */
|
/* Update clipping */
|
||||||
window_clip(reg[17], 0);
|
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) */
|
/* Active display width modified during HBLANK (Bugs Bunny Double Trouble) */
|
||||||
if ((v_counter < bitmap.viewport.h) && (cycles <= (mcycles_vdp + 860)))
|
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)
|
static void vdp_fifo_update(unsigned int cycles)
|
||||||
{
|
{
|
||||||
if (fifo_write_cnt > 0)
|
int slots, count = 0;
|
||||||
{
|
|
||||||
/* Get number of FIFO reads */
|
|
||||||
int fifo_read = ((cycles - fifo_lastwrite) / fifo_latency);
|
|
||||||
|
|
||||||
if (fifo_read > 0)
|
const int *fifo_timing;
|
||||||
|
|
||||||
|
const int fifo_cycles_h32[16+2] =
|
||||||
{
|
{
|
||||||
/* Process FIFO entries */
|
230, 510, 810, 970, 1130, 1450, 1610, 1770, 2090, 2250, 2410, 2730, 2890, 3050, 3350, 3370,
|
||||||
fifo_write_cnt -= fifo_read;
|
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 */
|
/* Clear FIFO full flag */
|
||||||
status &= 0xFEFF;
|
status &= 0xFEFF;
|
||||||
|
|
||||||
/* Check remaining FIFO entries */
|
|
||||||
if (fifo_write_cnt <= 0)
|
if (fifo_write_cnt <= 0)
|
||||||
{
|
{
|
||||||
|
/* No more FIFO entries */
|
||||||
|
fifo_write_cnt = 0;
|
||||||
|
|
||||||
/* Set FIFO empty flag */
|
/* Set FIFO empty flag */
|
||||||
status |= 0x200;
|
status |= 0x200;
|
||||||
fifo_write_cnt = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update FIFO cycle count */
|
/* Update FIFO access slot counter */
|
||||||
fifo_lastwrite += (fifo_read * fifo_latency);
|
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
|
else
|
||||||
{
|
{
|
||||||
/* CPU is halted until last FIFO entry has been processed (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
/* CPU is halted until next FIFO entry processing */
|
||||||
fifo_lastwrite += fifo_latency;
|
m68k.cycles = fifo_cycles;
|
||||||
m68k.cycles = fifo_lastwrite;
|
|
||||||
|
/* 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
|
else
|
||||||
{
|
{
|
||||||
/* CPU is halted until last FIFO entry has been processed (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
/* CPU is halted until next FIFO entry processing (Chaos Engine / Soldiers of Fortune, Double Clutch, Titan Overdrive Demo) */
|
||||||
fifo_lastwrite += fifo_latency;
|
m68k.cycles = fifo_cycles;
|
||||||
m68k.cycles = fifo_lastwrite;
|
|
||||||
|
/* Update FIFO access slot counter */
|
||||||
|
fifo_slots += (1 + fifo_byte_access);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ extern uint16 vc_max;
|
|||||||
extern uint16 vscroll;
|
extern uint16 vscroll;
|
||||||
extern uint16 lines_per_frame;
|
extern uint16 lines_per_frame;
|
||||||
extern int32 fifo_write_cnt;
|
extern int32 fifo_write_cnt;
|
||||||
extern uint32 fifo_lastwrite;
|
extern uint32 fifo_slots;
|
||||||
extern uint32 hvc_latch;
|
extern uint32 hvc_latch;
|
||||||
extern const uint8 *hctab;
|
extern const uint8 *hctab;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user